summaryrefslogtreecommitdiff
path: root/drivers/usb/serial/spcp8x5.c
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2013-03-21 12:37:29 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-25 13:52:28 -0700
commit4d63143db1426342f186cfe258db73571bf57897 (patch)
tree88b144ffda0d920f500cee80983352a319507828 /drivers/usb/serial/spcp8x5.c
parent0a967f62e6623a2a7bb3a5707352b6667c0c649e (diff)
USB: spcp8x5: reimplement device type detection
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>
Diffstat (limited to 'drivers/usb/serial/spcp8x5.c')
-rw-r--r--drivers/usb/serial/spcp8x5.c70
1 files changed, 21 insertions, 49 deletions
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index e0093dd22238..a454a3f1acb3 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -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,
};