|
@@ -49,6 +49,7 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port,
|
|
|
unsigned int, unsigned int);
|
|
|
static void cp210x_break_ctl(struct tty_struct *, int);
|
|
|
static int cp210x_startup(struct usb_serial *);
|
|
|
+static void cp210x_release(struct usb_serial *);
|
|
|
static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
|
|
|
|
|
|
static bool debug;
|
|
@@ -121,6 +122,8 @@ static const struct usb_device_id id_table[] = {
|
|
|
{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
|
|
|
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
|
|
|
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
|
|
|
+ { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
|
|
|
+ { USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */
|
|
|
{ USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
|
|
|
{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
|
|
|
{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
|
|
@@ -149,6 +152,10 @@ static const struct usb_device_id id_table[] = {
|
|
|
|
|
|
MODULE_DEVICE_TABLE(usb, id_table);
|
|
|
|
|
|
+struct cp210x_port_private {
|
|
|
+ __u8 bInterfaceNumber;
|
|
|
+};
|
|
|
+
|
|
|
static struct usb_driver cp210x_driver = {
|
|
|
.name = "cp210x",
|
|
|
.probe = usb_serial_probe,
|
|
@@ -172,6 +179,7 @@ static struct usb_serial_driver cp210x_device = {
|
|
|
.tiocmget = cp210x_tiocmget,
|
|
|
.tiocmset = cp210x_tiocmset,
|
|
|
.attach = cp210x_startup,
|
|
|
+ .release = cp210x_release,
|
|
|
.dtr_rts = cp210x_dtr_rts
|
|
|
};
|
|
|
|
|
@@ -263,6 +271,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
|
|
|
unsigned int *data, int size)
|
|
|
{
|
|
|
struct usb_serial *serial = port->serial;
|
|
|
+ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
|
|
|
__le32 *buf;
|
|
|
int result, i, length;
|
|
|
|
|
@@ -278,7 +287,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
|
|
|
/* Issue the request, attempting to read 'size' bytes */
|
|
|
result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
|
|
|
request, REQTYPE_DEVICE_TO_HOST, 0x0000,
|
|
|
- 0, buf, size, 300);
|
|
|
+ port_priv->bInterfaceNumber, buf, size, 300);
|
|
|
|
|
|
/* Convert data into an array of integers */
|
|
|
for (i = 0; i < length; i++)
|
|
@@ -309,6 +318,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
|
|
|
unsigned int *data, int size)
|
|
|
{
|
|
|
struct usb_serial *serial = port->serial;
|
|
|
+ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
|
|
|
__le32 *buf;
|
|
|
int result, i, length;
|
|
|
|
|
@@ -330,12 +340,12 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
|
|
|
result = usb_control_msg(serial->dev,
|
|
|
usb_sndctrlpipe(serial->dev, 0),
|
|
|
request, REQTYPE_HOST_TO_DEVICE, 0x0000,
|
|
|
- 0, buf, size, 300);
|
|
|
+ port_priv->bInterfaceNumber, buf, size, 300);
|
|
|
} else {
|
|
|
result = usb_control_msg(serial->dev,
|
|
|
usb_sndctrlpipe(serial->dev, 0),
|
|
|
request, REQTYPE_HOST_TO_DEVICE, data[0],
|
|
|
- 0, NULL, 0, 300);
|
|
|
+ port_priv->bInterfaceNumber, NULL, 0, 300);
|
|
|
}
|
|
|
|
|
|
kfree(buf);
|
|
@@ -845,11 +855,39 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
|
|
|
|
|
|
static int cp210x_startup(struct usb_serial *serial)
|
|
|
{
|
|
|
+ struct cp210x_port_private *port_priv;
|
|
|
+ int i;
|
|
|
+
|
|
|
/* cp210x buffers behave strangely unless device is reset */
|
|
|
usb_reset_device(serial->dev);
|
|
|
+
|
|
|
+ for (i = 0; i < serial->num_ports; i++) {
|
|
|
+ port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
|
|
|
+ if (!port_priv)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ memset(port_priv, 0x00, sizeof(*port_priv));
|
|
|
+ port_priv->bInterfaceNumber =
|
|
|
+ serial->interface->cur_altsetting->desc.bInterfaceNumber;
|
|
|
+
|
|
|
+ usb_set_serial_port_data(serial->port[i], port_priv);
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void cp210x_release(struct usb_serial *serial)
|
|
|
+{
|
|
|
+ struct cp210x_port_private *port_priv;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < serial->num_ports; i++) {
|
|
|
+ port_priv = usb_get_serial_port_data(serial->port[i]);
|
|
|
+ kfree(port_priv);
|
|
|
+ usb_set_serial_port_data(serial->port[i], NULL);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
module_usb_serial_driver(cp210x_driver, serial_drivers);
|
|
|
|
|
|
MODULE_DESCRIPTION(DRIVER_DESC);
|