]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/meta-ti-glsdk.git/blob - recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.14/0033-usb-cp210x-Update-to-support-CP2105-and-multiple-int.patch
linux-ti335x-psp 3.2: update to 3.2.14
[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-ti33x-psp-3.2 / 3.2.14 / 0033-usb-cp210x-Update-to-support-CP2105-and-multiple-int.patch
1 From 4d2e98ccb5f7c69868760e889389c5ba01a89bf5 Mon Sep 17 00:00:00 2001
2 From: Preston Fick <preston.fick@silabs.com>
3 Date: Fri, 24 Feb 2012 13:42:39 -0600
4 Subject: [PATCH 033/147] usb: cp210x: Update to support CP2105 and multiple
5  interface devices
7 commit a5360a53a7ccad5ed9ccef210b94fef13c6e5529 upstream.
9 This patch updates the cp210x driver to support CP210x multiple
10 interface devices devices from Silicon Labs. The existing driver
11 always sends control requests to interface 0, which is hardcoded in
12 the usb_control_msg function calls. This only allows for single
13 interface devices to be used, and causes a bug when using ports on an
14 interface other than 0 in the multiple interface devices.
16 Here are the changes included in this patch:
17 - Updated the device list to contain the Silicon Labs factory default
18   VID/PID for multiple interface CP210x devices
19 - Created a cp210x_port_private struct created for each port on
20   startup, this struct holds the interface number
21 - Added a cp210x_release function to clean up the cp210x_port_private
22   memory created on startup
23 - Modified usb_get_config and usb_set_config to get a pointer to the
24   cp210x_port_private struct, and use the interface number there in the
25   usb_control_message wIndex param
27 Signed-off-by: Preston Fick <preston.fick@silabs.com>
28 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
29 ---
30  drivers/usb/serial/cp210x.c |   44 ++++++++++++++++++++++++++++++++++++++++---
31  1 file changed, 41 insertions(+), 3 deletions(-)
33 diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
34 index 33d25d4..4c12404 100644
35 --- a/drivers/usb/serial/cp210x.c
36 +++ b/drivers/usb/serial/cp210x.c
37 @@ -49,6 +49,7 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port,
38                 unsigned int, unsigned int);
39  static void cp210x_break_ctl(struct tty_struct *, int);
40  static int cp210x_startup(struct usb_serial *);
41 +static void cp210x_release(struct usb_serial *);
42  static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
43  
44  static int debug;
45 @@ -121,6 +122,8 @@ static const struct usb_device_id id_table[] = {
46         { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
47         { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
48         { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
49 +       { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
50 +       { USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */
51         { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
52         { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
53         { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
54 @@ -149,6 +152,10 @@ static const struct usb_device_id id_table[] = {
55  
56  MODULE_DEVICE_TABLE(usb, id_table);
57  
58 +struct cp210x_port_private {
59 +       __u8                    bInterfaceNumber;
60 +};
61 +
62  static struct usb_driver cp210x_driver = {
63         .name           = "cp210x",
64         .probe          = usb_serial_probe,
65 @@ -174,6 +181,7 @@ static struct usb_serial_driver cp210x_device = {
66         .tiocmget               = cp210x_tiocmget,
67         .tiocmset               = cp210x_tiocmset,
68         .attach                 = cp210x_startup,
69 +       .release                = cp210x_release,
70         .dtr_rts                = cp210x_dtr_rts
71  };
72  
73 @@ -261,6 +269,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
74                 unsigned int *data, int size)
75  {
76         struct usb_serial *serial = port->serial;
77 +       struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
78         __le32 *buf;
79         int result, i, length;
80  
81 @@ -276,7 +285,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
82         /* Issue the request, attempting to read 'size' bytes */
83         result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
84                                 request, REQTYPE_DEVICE_TO_HOST, 0x0000,
85 -                               0, buf, size, 300);
86 +                               port_priv->bInterfaceNumber, buf, size, 300);
87  
88         /* Convert data into an array of integers */
89         for (i = 0; i < length; i++)
90 @@ -304,6 +313,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
91                 unsigned int *data, int size)
92  {
93         struct usb_serial *serial = port->serial;
94 +       struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
95         __le32 *buf;
96         int result, i, length;
97  
98 @@ -325,12 +335,12 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
99                 result = usb_control_msg(serial->dev,
100                                 usb_sndctrlpipe(serial->dev, 0),
101                                 request, REQTYPE_HOST_TO_DEVICE, 0x0000,
102 -                               0, buf, size, 300);
103 +                               port_priv->bInterfaceNumber, buf, size, 300);
104         } else {
105                 result = usb_control_msg(serial->dev,
106                                 usb_sndctrlpipe(serial->dev, 0),
107                                 request, REQTYPE_HOST_TO_DEVICE, data[0],
108 -                               0, NULL, 0, 300);
109 +                               port_priv->bInterfaceNumber, NULL, 0, 300);
110         }
111  
112         kfree(buf);
113 @@ -830,11 +840,39 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
114  
115  static int cp210x_startup(struct usb_serial *serial)
116  {
117 +       struct cp210x_port_private *port_priv;
118 +       int i;
120         /* cp210x buffers behave strangely unless device is reset */
121         usb_reset_device(serial->dev);
123 +       for (i = 0; i < serial->num_ports; i++) {
124 +               port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
125 +               if (!port_priv)
126 +                       return -ENOMEM;
128 +               memset(port_priv, 0x00, sizeof(*port_priv));
129 +               port_priv->bInterfaceNumber =
130 +                   serial->interface->cur_altsetting->desc.bInterfaceNumber;
132 +               usb_set_serial_port_data(serial->port[i], port_priv);
133 +       }
135         return 0;
136  }
137  
138 +static void cp210x_release(struct usb_serial *serial)
139 +{
140 +       struct cp210x_port_private *port_priv;
141 +       int i;
143 +       for (i = 0; i < serial->num_ports; i++) {
144 +               port_priv = usb_get_serial_port_data(serial->port[i]);
145 +               kfree(port_priv);
146 +               usb_set_serial_port_data(serial->port[i], NULL);
147 +       }
148 +}
150  static int __init cp210x_init(void)
151  {
152         int retval;
153 -- 
154 1.7.9.4