USB: spcp8x5: reimplement device type detection
authorJohan Hovold <jhovold@gmail.com>
Thu, 21 Mar 2013 11:37:29 +0000 (12:37 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 25 Mar 2013 20:52:28 +0000 (13:52 -0700)
Reimplement device type detection using the device id table and quirks.

Device type was used to detect one device type which did not support to
control functions. Add quirks to the device table and store them in the
private port data at probe instead.

Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/serial/spcp8x5.c

index e0093dd..a454a3f 100644 (file)
@@ -28,6 +28,9 @@
 
 #define DRIVER_DESC    "SPCP8x5 USB to serial adaptor driver"
 
+#define SPCP825_QUIRK_NO_UART_STATUS   0x01
+#define SPCP825_QUIRK_NO_WORK_MODE     0x02
+
 #define SPCP8x5_007_VID                0x04FC
 #define SPCP8x5_007_PID                0x0201
 #define SPCP8x5_008_VID                0x04fc
@@ -44,7 +47,9 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)},
        { USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)},
        { USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)},
-       { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID)},
+       { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID),
+         .driver_info = SPCP825_QUIRK_NO_UART_STATUS |
+                               SPCP825_QUIRK_NO_WORK_MODE },
        { }                                     /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, id_table);
@@ -136,47 +141,32 @@ struct spcp8x5_usb_ctrl_arg {
 #define UART_OVERRUN_ERROR             0x40
 #define UART_CTS                       0x80
 
-enum spcp8x5_type {
-       SPCP825_007_TYPE,
-       SPCP825_008_TYPE,
-       SPCP825_PHILIP_TYPE,
-       SPCP825_INTERMATIC_TYPE,
-       SPCP835_TYPE,
-};
-
 struct spcp8x5_private {
+       unsigned                quirks;
        spinlock_t              lock;
-       enum spcp8x5_type       type;
        u8                      line_control;
        u8                      line_status;
 };
 
+static int spcp8x5_probe(struct usb_serial *serial,
+                                               const struct usb_device_id *id)
+{
+       usb_set_serial_data(serial, (void *)id);
+
+       return 0;
+}
+
 static int spcp8x5_port_probe(struct usb_serial_port *port)
 {
-       struct usb_serial *serial = port->serial;
+       const struct usb_device_id *id = usb_get_serial_data(port->serial);
        struct spcp8x5_private *priv;
-       enum spcp8x5_type type = SPCP825_007_TYPE;
-       u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
-
-       if (product == 0x0201)
-               type = SPCP825_007_TYPE;
-       else if (product == 0x0231)
-               type = SPCP835_TYPE;
-       else if (product == 0x0235)
-               type = SPCP825_008_TYPE;
-       else if (product == 0x0204)
-               type = SPCP825_INTERMATIC_TYPE;
-       else if (product == 0x0471 &&
-                serial->dev->descriptor.idVendor == cpu_to_le16(0x081e))
-               type = SPCP825_PHILIP_TYPE;
-       dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
        spin_lock_init(&priv->lock);
-       priv->type = type;
+       priv->quirks = id->driver_info;
 
        usb_set_serial_port_data(port, priv);
 
@@ -193,18 +183,13 @@ static int spcp8x5_port_remove(struct usb_serial_port *port)
        return 0;
 }
 
-/*
- * Set the modem control line of the device.
- *
- * NOTE: not supported by spcp825-007
- */
 static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr)
 {
        struct spcp8x5_private *priv = usb_get_serial_port_data(port);
        struct usb_device *dev = port->serial->dev;
        int retval;
 
-       if (priv->type == SPCP825_007_TYPE)
+       if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)
                return -EPERM;
 
        retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -217,11 +202,6 @@ static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr)
        return retval;
 }
 
-/*
- * Get the modem status register of the device.
- *
- * NOTE: not supported by spcp825-007
- */
 static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status)
 {
        struct spcp8x5_private *priv = usb_get_serial_port_data(port);
@@ -229,9 +209,7 @@ static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status)
        u8 *buf;
        int ret;
 
-       /* I return Permited not support here but seem inval device
-        * is more fix */
-       if (priv->type == SPCP825_007_TYPE)
+       if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)
                return -EPERM;
 
        buf = kzalloc(1, GFP_KERNEL);
@@ -251,11 +229,6 @@ static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status)
        return ret;
 }
 
-/*
- * Select the work mode.
- *
- * NOTE: not supported by spcp825-007
- */
 static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value,
                                                                 u16 index)
 {
@@ -263,9 +236,7 @@ static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value,
        struct usb_device *dev = port->serial->dev;
        int ret;
 
-       /* I return Permited not support here but seem inval device
-        * is more fix */
-       if (priv->type == SPCP825_007_TYPE)
+       if (priv->quirks & SPCP825_QUIRK_NO_WORK_MODE)
                return;
 
        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -518,6 +489,7 @@ static struct usb_serial_driver spcp8x5_device = {
        .init_termios           = spcp8x5_init_termios,
        .tiocmget               = spcp8x5_tiocmget,
        .tiocmset               = spcp8x5_tiocmset,
+       .probe                  = spcp8x5_probe,
        .port_probe             = spcp8x5_port_probe,
        .port_remove            = spcp8x5_port_remove,
 };