diff options
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/Kconfig | 28 | ||||
-rw-r--r-- | drivers/usb/serial/Makefile | 4 | ||||
-rw-r--r-- | drivers/usb/serial/ch341.c | 396 | ||||
-rw-r--r-- | drivers/usb/serial/cp210x.c (renamed from drivers/usb/serial/cp2101.c) | 161 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 29 | ||||
-rw-r--r-- | drivers/usb/serial/generic.c | 9 | ||||
-rw-r--r-- | drivers/usb/serial/ipaq.c | 43 | ||||
-rw-r--r-- | drivers/usb/serial/keyspan.c | 2 | ||||
-rw-r--r-- | drivers/usb/serial/opticon.c | 215 | ||||
-rw-r--r-- | drivers/usb/serial/option.c | 86 | ||||
-rw-r--r-- | drivers/usb/serial/qcserial.c | 147 | ||||
-rw-r--r-- | drivers/usb/serial/symbolserial.c | 399 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 20 |
13 files changed, 1355 insertions, 184 deletions
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index b361f05cafa..a65f9196b0a 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
@@ -116,14 +116,14 @@ config USB_SERIAL_DIGI_ACCELEPORT | |||
116 | To compile this driver as a module, choose M here: the | 116 | To compile this driver as a module, choose M here: the |
117 | module will be called digi_acceleport. | 117 | module will be called digi_acceleport. |
118 | 118 | ||
119 | config USB_SERIAL_CP2101 | 119 | config USB_SERIAL_CP210X |
120 | tristate "USB CP2101 UART Bridge Controller" | 120 | tristate "USB CP210x family of UART Bridge Controllers" |
121 | help | 121 | help |
122 | Say Y here if you want to use a CP2101/CP2102 based USB to RS232 | 122 | Say Y here if you want to use a CP2101/CP2102/CP2103 based USB |
123 | converter. | 123 | to RS232 converters. |
124 | 124 | ||
125 | To compile this driver as a module, choose M here: the | 125 | To compile this driver as a module, choose M here: the |
126 | module will be called cp2101. | 126 | module will be called cp210x. |
127 | 127 | ||
128 | config USB_SERIAL_CYPRESS_M8 | 128 | config USB_SERIAL_CYPRESS_M8 |
129 | tristate "USB Cypress M8 USB Serial Driver" | 129 | tristate "USB Cypress M8 USB Serial Driver" |
@@ -472,6 +472,15 @@ config USB_SERIAL_OTI6858 | |||
472 | To compile this driver as a module, choose M here: the | 472 | To compile this driver as a module, choose M here: the |
473 | module will be called oti6858. | 473 | module will be called oti6858. |
474 | 474 | ||
475 | config USB_SERIAL_QUALCOMM | ||
476 | tristate "USB Qualcomm Serial modem" | ||
477 | help | ||
478 | Say Y here if you have a Qualcomm USB modem device. These are | ||
479 | usually wireless cellular modems. | ||
480 | |||
481 | To compile this driver as a module, choose M here: the | ||
482 | module will be called qcserial. | ||
483 | |||
475 | config USB_SERIAL_SPCP8X5 | 484 | config USB_SERIAL_SPCP8X5 |
476 | tristate "USB SPCP8x5 USB To Serial Driver" | 485 | tristate "USB SPCP8x5 USB To Serial Driver" |
477 | help | 486 | help |
@@ -515,6 +524,15 @@ config USB_SERIAL_SIERRAWIRELESS | |||
515 | To compile this driver as a module, choose M here: the | 524 | To compile this driver as a module, choose M here: the |
516 | module will be called sierra. | 525 | module will be called sierra. |
517 | 526 | ||
527 | config USB_SERIAL_SYMBOL | ||
528 | tristate "USB Symbol Barcode driver (serial mode)" | ||
529 | help | ||
530 | Say Y here if you want to use a Symbol USB Barcode device | ||
531 | in serial emulation mode. | ||
532 | |||
533 | To compile this driver as a module, choose M here: the | ||
534 | module will be called symbolserial. | ||
535 | |||
518 | config USB_SERIAL_TI | 536 | config USB_SERIAL_TI |
519 | tristate "USB TI 3410/5052 Serial Driver" | 537 | tristate "USB TI 3410/5052 Serial Driver" |
520 | help | 538 | help |
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index b75be91eb8f..66619beb6cc 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile | |||
@@ -15,7 +15,7 @@ obj-$(CONFIG_USB_SERIAL_AIRCABLE) += aircable.o | |||
15 | obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o | 15 | obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o |
16 | obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o | 16 | obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o |
17 | obj-$(CONFIG_USB_SERIAL_CH341) += ch341.o | 17 | obj-$(CONFIG_USB_SERIAL_CH341) += ch341.o |
18 | obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o | 18 | obj-$(CONFIG_USB_SERIAL_CP210X) += cp210x.o |
19 | obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o | 19 | obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o |
20 | obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o | 20 | obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o |
21 | obj-$(CONFIG_USB_SERIAL_DEBUG) += usb_debug.o | 21 | obj-$(CONFIG_USB_SERIAL_DEBUG) += usb_debug.o |
@@ -45,10 +45,12 @@ obj-$(CONFIG_USB_SERIAL_OPTICON) += opticon.o | |||
45 | obj-$(CONFIG_USB_SERIAL_OPTION) += option.o | 45 | obj-$(CONFIG_USB_SERIAL_OPTION) += option.o |
46 | obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o | 46 | obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o |
47 | obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o | 47 | obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o |
48 | obj-$(CONFIG_USB_SERIAL_QUALCOMM) += qcserial.o | ||
48 | obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o | 49 | obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o |
49 | obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o | 50 | obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o |
50 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o | 51 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o |
51 | obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o | 52 | obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o |
53 | obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o | ||
52 | obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o | 54 | obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o |
53 | obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o | 55 | obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o |
54 | obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o | 56 | obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o |
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index f61e3ca6430..ab4cc277aa6 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c | |||
@@ -1,5 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2007, Frank A Kingswood <frank@kingswood-consulting.co.uk> | 2 | * Copyright 2007, Frank A Kingswood <frank@kingswood-consulting.co.uk> |
3 | * Copyright 2007, Werner Cornelius <werner@cornelius-consult.de> | ||
4 | * Copyright 2009, Boris Hajduk <boris@hajduk.org> | ||
3 | * | 5 | * |
4 | * ch341.c implements a serial port driver for the Winchiphead CH341. | 6 | * ch341.c implements a serial port driver for the Winchiphead CH341. |
5 | * | 7 | * |
@@ -21,9 +23,39 @@ | |||
21 | #include <linux/usb/serial.h> | 23 | #include <linux/usb/serial.h> |
22 | #include <linux/serial.h> | 24 | #include <linux/serial.h> |
23 | 25 | ||
24 | #define DEFAULT_BAUD_RATE 2400 | 26 | #define DEFAULT_BAUD_RATE 9600 |
25 | #define DEFAULT_TIMEOUT 1000 | 27 | #define DEFAULT_TIMEOUT 1000 |
26 | 28 | ||
29 | /* flags for IO-Bits */ | ||
30 | #define CH341_BIT_RTS (1 << 6) | ||
31 | #define CH341_BIT_DTR (1 << 5) | ||
32 | |||
33 | /******************************/ | ||
34 | /* interrupt pipe definitions */ | ||
35 | /******************************/ | ||
36 | /* always 4 interrupt bytes */ | ||
37 | /* first irq byte normally 0x08 */ | ||
38 | /* second irq byte base 0x7d + below */ | ||
39 | /* third irq byte base 0x94 + below */ | ||
40 | /* fourth irq byte normally 0xee */ | ||
41 | |||
42 | /* second interrupt byte */ | ||
43 | #define CH341_MULT_STAT 0x04 /* multiple status since last interrupt event */ | ||
44 | |||
45 | /* status returned in third interrupt answer byte, inverted in data | ||
46 | from irq */ | ||
47 | #define CH341_BIT_CTS 0x01 | ||
48 | #define CH341_BIT_DSR 0x02 | ||
49 | #define CH341_BIT_RI 0x04 | ||
50 | #define CH341_BIT_DCD 0x08 | ||
51 | #define CH341_BITS_MODEM_STAT 0x0f /* all bits */ | ||
52 | |||
53 | /*******************************/ | ||
54 | /* baudrate calculation factor */ | ||
55 | /*******************************/ | ||
56 | #define CH341_BAUDBASE_FACTOR 1532620800 | ||
57 | #define CH341_BAUDBASE_DIVMAX 3 | ||
58 | |||
27 | static int debug; | 59 | static int debug; |
28 | 60 | ||
29 | static struct usb_device_id id_table [] = { | 61 | static struct usb_device_id id_table [] = { |
@@ -34,9 +66,12 @@ static struct usb_device_id id_table [] = { | |||
34 | MODULE_DEVICE_TABLE(usb, id_table); | 66 | MODULE_DEVICE_TABLE(usb, id_table); |
35 | 67 | ||
36 | struct ch341_private { | 68 | struct ch341_private { |
37 | unsigned baud_rate; | 69 | spinlock_t lock; /* access lock */ |
38 | u8 dtr; | 70 | wait_queue_head_t delta_msr_wait; /* wait queue for modem status */ |
39 | u8 rts; | 71 | unsigned baud_rate; /* set baud rate */ |
72 | u8 line_control; /* set line control value RTS/DTR */ | ||
73 | u8 line_status; /* active status of modem control inputs */ | ||
74 | u8 multi_status_change; /* status changed multiple since last call */ | ||
40 | }; | 75 | }; |
41 | 76 | ||
42 | static int ch341_control_out(struct usb_device *dev, u8 request, | 77 | static int ch341_control_out(struct usb_device *dev, u8 request, |
@@ -72,37 +107,28 @@ static int ch341_set_baudrate(struct usb_device *dev, | |||
72 | { | 107 | { |
73 | short a, b; | 108 | short a, b; |
74 | int r; | 109 | int r; |
110 | unsigned long factor; | ||
111 | short divisor; | ||
75 | 112 | ||
76 | dbg("ch341_set_baudrate(%d)", priv->baud_rate); | 113 | dbg("ch341_set_baudrate(%d)", priv->baud_rate); |
77 | switch (priv->baud_rate) { | 114 | |
78 | case 2400: | 115 | if (!priv->baud_rate) |
79 | a = 0xd901; | ||
80 | b = 0x0038; | ||
81 | break; | ||
82 | case 4800: | ||
83 | a = 0x6402; | ||
84 | b = 0x001f; | ||
85 | break; | ||
86 | case 9600: | ||
87 | a = 0xb202; | ||
88 | b = 0x0013; | ||
89 | break; | ||
90 | case 19200: | ||
91 | a = 0xd902; | ||
92 | b = 0x000d; | ||
93 | break; | ||
94 | case 38400: | ||
95 | a = 0x6403; | ||
96 | b = 0x000a; | ||
97 | break; | ||
98 | case 115200: | ||
99 | a = 0xcc03; | ||
100 | b = 0x0008; | ||
101 | break; | ||
102 | default: | ||
103 | return -EINVAL; | 116 | return -EINVAL; |
117 | factor = (CH341_BAUDBASE_FACTOR / priv->baud_rate); | ||
118 | divisor = CH341_BAUDBASE_DIVMAX; | ||
119 | |||
120 | while ((factor > 0xfff0) && divisor) { | ||
121 | factor >>= 3; | ||
122 | divisor--; | ||
104 | } | 123 | } |
105 | 124 | ||
125 | if (factor > 0xfff0) | ||
126 | return -EINVAL; | ||
127 | |||
128 | factor = 0x10000 - factor; | ||
129 | a = (factor & 0xff00) | divisor; | ||
130 | b = factor & 0xff; | ||
131 | |||
106 | r = ch341_control_out(dev, 0x9a, 0x1312, a); | 132 | r = ch341_control_out(dev, 0x9a, 0x1312, a); |
107 | if (!r) | 133 | if (!r) |
108 | r = ch341_control_out(dev, 0x9a, 0x0f2c, b); | 134 | r = ch341_control_out(dev, 0x9a, 0x0f2c, b); |
@@ -110,19 +136,18 @@ static int ch341_set_baudrate(struct usb_device *dev, | |||
110 | return r; | 136 | return r; |
111 | } | 137 | } |
112 | 138 | ||
113 | static int ch341_set_handshake(struct usb_device *dev, | 139 | static int ch341_set_handshake(struct usb_device *dev, u8 control) |
114 | struct ch341_private *priv) | ||
115 | { | 140 | { |
116 | dbg("ch341_set_handshake(%d,%d)", priv->dtr, priv->rts); | 141 | dbg("ch341_set_handshake(0x%02x)", control); |
117 | return ch341_control_out(dev, 0xa4, | 142 | return ch341_control_out(dev, 0xa4, ~control, 0); |
118 | ~((priv->dtr?1<<5:0)|(priv->rts?1<<6:0)), 0); | ||
119 | } | 143 | } |
120 | 144 | ||
121 | static int ch341_get_status(struct usb_device *dev) | 145 | static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv) |
122 | { | 146 | { |
123 | char *buffer; | 147 | char *buffer; |
124 | int r; | 148 | int r; |
125 | const unsigned size = 8; | 149 | const unsigned size = 8; |
150 | unsigned long flags; | ||
126 | 151 | ||
127 | dbg("ch341_get_status()"); | 152 | dbg("ch341_get_status()"); |
128 | 153 | ||
@@ -134,10 +159,15 @@ static int ch341_get_status(struct usb_device *dev) | |||
134 | if (r < 0) | 159 | if (r < 0) |
135 | goto out; | 160 | goto out; |
136 | 161 | ||
137 | /* Not having the datasheet for the CH341, we ignore the bytes returned | 162 | /* setup the private status if available */ |
138 | * from the device. Return error if the device did not respond in time. | 163 | if (r == 2) { |
139 | */ | 164 | r = 0; |
140 | r = 0; | 165 | spin_lock_irqsave(&priv->lock, flags); |
166 | priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT; | ||
167 | priv->multi_status_change = 0; | ||
168 | spin_unlock_irqrestore(&priv->lock, flags); | ||
169 | } else | ||
170 | r = -EPROTO; | ||
141 | 171 | ||
142 | out: kfree(buffer); | 172 | out: kfree(buffer); |
143 | return r; | 173 | return r; |
@@ -180,7 +210,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) | |||
180 | goto out; | 210 | goto out; |
181 | 211 | ||
182 | /* expect 0xff 0xee */ | 212 | /* expect 0xff 0xee */ |
183 | r = ch341_get_status(dev); | 213 | r = ch341_get_status(dev, priv); |
184 | if (r < 0) | 214 | if (r < 0) |
185 | goto out; | 215 | goto out; |
186 | 216 | ||
@@ -192,12 +222,12 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) | |||
192 | if (r < 0) | 222 | if (r < 0) |
193 | goto out; | 223 | goto out; |
194 | 224 | ||
195 | r = ch341_set_handshake(dev, priv); | 225 | r = ch341_set_handshake(dev, priv->line_control); |
196 | if (r < 0) | 226 | if (r < 0) |
197 | goto out; | 227 | goto out; |
198 | 228 | ||
199 | /* expect 0x9f 0xee */ | 229 | /* expect 0x9f 0xee */ |
200 | r = ch341_get_status(dev); | 230 | r = ch341_get_status(dev, priv); |
201 | 231 | ||
202 | out: kfree(buffer); | 232 | out: kfree(buffer); |
203 | return r; | 233 | return r; |
@@ -216,9 +246,10 @@ static int ch341_attach(struct usb_serial *serial) | |||
216 | if (!priv) | 246 | if (!priv) |
217 | return -ENOMEM; | 247 | return -ENOMEM; |
218 | 248 | ||
249 | spin_lock_init(&priv->lock); | ||
250 | init_waitqueue_head(&priv->delta_msr_wait); | ||
219 | priv->baud_rate = DEFAULT_BAUD_RATE; | 251 | priv->baud_rate = DEFAULT_BAUD_RATE; |
220 | priv->dtr = 1; | 252 | priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; |
221 | priv->rts = 1; | ||
222 | 253 | ||
223 | r = ch341_configure(serial->dev, priv); | 254 | r = ch341_configure(serial->dev, priv); |
224 | if (r < 0) | 255 | if (r < 0) |
@@ -231,6 +262,35 @@ error: kfree(priv); | |||
231 | return r; | 262 | return r; |
232 | } | 263 | } |
233 | 264 | ||
265 | static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port, | ||
266 | struct file *filp) | ||
267 | { | ||
268 | struct ch341_private *priv = usb_get_serial_port_data(port); | ||
269 | unsigned long flags; | ||
270 | unsigned int c_cflag; | ||
271 | |||
272 | dbg("%s - port %d", __func__, port->number); | ||
273 | |||
274 | /* shutdown our urbs */ | ||
275 | dbg("%s - shutting down urbs", __func__); | ||
276 | usb_kill_urb(port->write_urb); | ||
277 | usb_kill_urb(port->read_urb); | ||
278 | usb_kill_urb(port->interrupt_in_urb); | ||
279 | |||
280 | if (tty) { | ||
281 | c_cflag = tty->termios->c_cflag; | ||
282 | if (c_cflag & HUPCL) { | ||
283 | /* drop DTR and RTS */ | ||
284 | spin_lock_irqsave(&priv->lock, flags); | ||
285 | priv->line_control = 0; | ||
286 | spin_unlock_irqrestore(&priv->lock, flags); | ||
287 | ch341_set_handshake(port->serial->dev, 0); | ||
288 | } | ||
289 | } | ||
290 | wake_up_interruptible(&priv->delta_msr_wait); | ||
291 | } | ||
292 | |||
293 | |||
234 | /* open this device, set default parameters */ | 294 | /* open this device, set default parameters */ |
235 | static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, | 295 | static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, |
236 | struct file *filp) | 296 | struct file *filp) |
@@ -242,14 +302,13 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
242 | dbg("ch341_open()"); | 302 | dbg("ch341_open()"); |
243 | 303 | ||
244 | priv->baud_rate = DEFAULT_BAUD_RATE; | 304 | priv->baud_rate = DEFAULT_BAUD_RATE; |
245 | priv->dtr = 1; | 305 | priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; |
246 | priv->rts = 1; | ||
247 | 306 | ||
248 | r = ch341_configure(serial->dev, priv); | 307 | r = ch341_configure(serial->dev, priv); |
249 | if (r) | 308 | if (r) |
250 | goto out; | 309 | goto out; |
251 | 310 | ||
252 | r = ch341_set_handshake(serial->dev, priv); | 311 | r = ch341_set_handshake(serial->dev, priv->line_control); |
253 | if (r) | 312 | if (r) |
254 | goto out; | 313 | goto out; |
255 | 314 | ||
@@ -257,6 +316,16 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
257 | if (r) | 316 | if (r) |
258 | goto out; | 317 | goto out; |
259 | 318 | ||
319 | dbg("%s - submitting interrupt urb", __func__); | ||
320 | port->interrupt_in_urb->dev = serial->dev; | ||
321 | r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | ||
322 | if (r) { | ||
323 | dev_err(&port->dev, "%s - failed submitting interrupt urb," | ||
324 | " error %d\n", __func__, r); | ||
325 | ch341_close(tty, port, NULL); | ||
326 | return -EPROTO; | ||
327 | } | ||
328 | |||
260 | r = usb_serial_generic_open(tty, port, filp); | 329 | r = usb_serial_generic_open(tty, port, filp); |
261 | 330 | ||
262 | out: return r; | 331 | out: return r; |
@@ -270,46 +339,224 @@ static void ch341_set_termios(struct tty_struct *tty, | |||
270 | { | 339 | { |
271 | struct ch341_private *priv = usb_get_serial_port_data(port); | 340 | struct ch341_private *priv = usb_get_serial_port_data(port); |
272 | unsigned baud_rate; | 341 | unsigned baud_rate; |
342 | unsigned long flags; | ||
273 | 343 | ||
274 | dbg("ch341_set_termios()"); | 344 | dbg("ch341_set_termios()"); |
275 | 345 | ||
346 | if (!tty || !tty->termios) | ||
347 | return; | ||
348 | |||
276 | baud_rate = tty_get_baud_rate(tty); | 349 | baud_rate = tty_get_baud_rate(tty); |
277 | 350 | ||
278 | switch (baud_rate) { | 351 | priv->baud_rate = baud_rate; |
279 | case 2400: | 352 | |
280 | case 4800: | 353 | if (baud_rate) { |
281 | case 9600: | 354 | spin_lock_irqsave(&priv->lock, flags); |
282 | case 19200: | 355 | priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS); |
283 | case 38400: | 356 | spin_unlock_irqrestore(&priv->lock, flags); |
284 | case 115200: | 357 | ch341_set_baudrate(port->serial->dev, priv); |
285 | priv->baud_rate = baud_rate; | 358 | } else { |
286 | break; | 359 | spin_lock_irqsave(&priv->lock, flags); |
287 | default: | 360 | priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS); |
288 | dbg("Rate %d not supported, using %d", | 361 | spin_unlock_irqrestore(&priv->lock, flags); |
289 | baud_rate, DEFAULT_BAUD_RATE); | ||
290 | priv->baud_rate = DEFAULT_BAUD_RATE; | ||
291 | } | 362 | } |
292 | 363 | ||
293 | ch341_set_baudrate(port->serial->dev, priv); | 364 | ch341_set_handshake(port->serial->dev, priv->line_control); |
294 | 365 | ||
295 | /* Unimplemented: | 366 | /* Unimplemented: |
296 | * (cflag & CSIZE) : data bits [5, 8] | 367 | * (cflag & CSIZE) : data bits [5, 8] |
297 | * (cflag & PARENB) : parity {NONE, EVEN, ODD} | 368 | * (cflag & PARENB) : parity {NONE, EVEN, ODD} |
298 | * (cflag & CSTOPB) : stop bits [1, 2] | 369 | * (cflag & CSTOPB) : stop bits [1, 2] |
299 | */ | 370 | */ |
371 | } | ||
372 | |||
373 | static int ch341_tiocmset(struct tty_struct *tty, struct file *file, | ||
374 | unsigned int set, unsigned int clear) | ||
375 | { | ||
376 | struct usb_serial_port *port = tty->driver_data; | ||
377 | struct ch341_private *priv = usb_get_serial_port_data(port); | ||
378 | unsigned long flags; | ||
379 | u8 control; | ||
380 | |||
381 | spin_lock_irqsave(&priv->lock, flags); | ||
382 | if (set & TIOCM_RTS) | ||
383 | priv->line_control |= CH341_BIT_RTS; | ||
384 | if (set & TIOCM_DTR) | ||
385 | priv->line_control |= CH341_BIT_DTR; | ||
386 | if (clear & TIOCM_RTS) | ||
387 | priv->line_control &= ~CH341_BIT_RTS; | ||
388 | if (clear & TIOCM_DTR) | ||
389 | priv->line_control &= ~CH341_BIT_DTR; | ||
390 | control = priv->line_control; | ||
391 | spin_unlock_irqrestore(&priv->lock, flags); | ||
392 | |||
393 | return ch341_set_handshake(port->serial->dev, control); | ||
394 | } | ||
395 | |||
396 | static void ch341_read_int_callback(struct urb *urb) | ||
397 | { | ||
398 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | ||
399 | unsigned char *data = urb->transfer_buffer; | ||
400 | unsigned int actual_length = urb->actual_length; | ||
401 | int status; | ||
402 | |||
403 | dbg("%s (%d)", __func__, port->number); | ||
404 | |||
405 | switch (urb->status) { | ||
406 | case 0: | ||
407 | /* success */ | ||
408 | break; | ||
409 | case -ECONNRESET: | ||
410 | case -ENOENT: | ||
411 | case -ESHUTDOWN: | ||
412 | /* this urb is terminated, clean up */ | ||
413 | dbg("%s - urb shutting down with status: %d", __func__, | ||
414 | urb->status); | ||
415 | return; | ||
416 | default: | ||
417 | dbg("%s - nonzero urb status received: %d", __func__, | ||
418 | urb->status); | ||
419 | goto exit; | ||
420 | } | ||
300 | 421 | ||
301 | /* Copy back the old hardware settings */ | 422 | usb_serial_debug_data(debug, &port->dev, __func__, |
302 | tty_termios_copy_hw(tty->termios, old_termios); | 423 | urb->actual_length, urb->transfer_buffer); |
303 | /* And re-encode with the new baud */ | 424 | |
304 | tty_encode_baud_rate(tty, baud_rate, baud_rate); | 425 | if (actual_length >= 4) { |
426 | struct ch341_private *priv = usb_get_serial_port_data(port); | ||
427 | unsigned long flags; | ||
428 | |||
429 | spin_lock_irqsave(&priv->lock, flags); | ||
430 | priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT; | ||
431 | if ((data[1] & CH341_MULT_STAT)) | ||
432 | priv->multi_status_change = 1; | ||
433 | spin_unlock_irqrestore(&priv->lock, flags); | ||
434 | wake_up_interruptible(&priv->delta_msr_wait); | ||
435 | } | ||
436 | |||
437 | exit: | ||
438 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
439 | if (status) | ||
440 | dev_err(&urb->dev->dev, | ||
441 | "%s - usb_submit_urb failed with result %d\n", | ||
442 | __func__, status); | ||
443 | } | ||
444 | |||
445 | static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | ||
446 | { | ||
447 | struct ch341_private *priv = usb_get_serial_port_data(port); | ||
448 | unsigned long flags; | ||
449 | u8 prevstatus; | ||
450 | u8 status; | ||
451 | u8 changed; | ||
452 | u8 multi_change = 0; | ||
453 | |||
454 | spin_lock_irqsave(&priv->lock, flags); | ||
455 | prevstatus = priv->line_status; | ||
456 | priv->multi_status_change = 0; | ||
457 | spin_unlock_irqrestore(&priv->lock, flags); | ||
458 | |||
459 | while (!multi_change) { | ||
460 | interruptible_sleep_on(&priv->delta_msr_wait); | ||
461 | /* see if a signal did it */ | ||
462 | if (signal_pending(current)) | ||
463 | return -ERESTARTSYS; | ||
464 | |||
465 | spin_lock_irqsave(&priv->lock, flags); | ||
466 | status = priv->line_status; | ||
467 | multi_change = priv->multi_status_change; | ||
468 | spin_unlock_irqrestore(&priv->lock, flags); | ||
469 | |||
470 | changed = prevstatus ^ status; | ||
471 | |||
472 | if (((arg & TIOCM_RNG) && (changed & CH341_BIT_RI)) || | ||
473 | ((arg & TIOCM_DSR) && (changed & CH341_BIT_DSR)) || | ||
474 | ((arg & TIOCM_CD) && (changed & CH341_BIT_DCD)) || | ||
475 | ((arg & TIOCM_CTS) && (changed & CH341_BIT_CTS))) { | ||
476 | return 0; | ||
477 | } | ||
478 | prevstatus = status; | ||
479 | } | ||
480 | |||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | /*static int ch341_ioctl(struct usb_serial_port *port, struct file *file,*/ | ||
485 | static int ch341_ioctl(struct tty_struct *tty, struct file *file, | ||
486 | unsigned int cmd, unsigned long arg) | ||
487 | { | ||
488 | struct usb_serial_port *port = tty->driver_data; | ||
489 | dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); | ||
490 | |||
491 | switch (cmd) { | ||
492 | case TIOCMIWAIT: | ||
493 | dbg("%s (%d) TIOCMIWAIT", __func__, port->number); | ||
494 | return wait_modem_info(port, arg); | ||
495 | |||
496 | default: | ||
497 | dbg("%s not supported = 0x%04x", __func__, cmd); | ||
498 | break; | ||
499 | } | ||
500 | |||
501 | return -ENOIOCTLCMD; | ||
502 | } | ||
503 | |||
504 | static int ch341_tiocmget(struct tty_struct *tty, struct file *file) | ||
505 | { | ||
506 | struct usb_serial_port *port = tty->driver_data; | ||
507 | struct ch341_private *priv = usb_get_serial_port_data(port); | ||
508 | unsigned long flags; | ||
509 | u8 mcr; | ||
510 | u8 status; | ||
511 | unsigned int result; | ||
512 | |||
513 | dbg("%s (%d)", __func__, port->number); | ||
514 | |||
515 | spin_lock_irqsave(&priv->lock, flags); | ||
516 | mcr = priv->line_control; | ||
517 | status = priv->line_status; | ||
518 | spin_unlock_irqrestore(&priv->lock, flags); | ||
519 | |||
520 | result = ((mcr & CH341_BIT_DTR) ? TIOCM_DTR : 0) | ||
521 | | ((mcr & CH341_BIT_RTS) ? TIOCM_RTS : 0) | ||
522 | | ((status & CH341_BIT_CTS) ? TIOCM_CTS : 0) | ||
523 | | ((status & CH341_BIT_DSR) ? TIOCM_DSR : 0) | ||
524 | | ((status & CH341_BIT_RI) ? TIOCM_RI : 0) | ||
525 | | ((status & CH341_BIT_DCD) ? TIOCM_CD : 0); | ||
526 | |||
527 | dbg("%s - result = %x", __func__, result); | ||
528 | |||
529 | return result; | ||
530 | } | ||
531 | |||
532 | |||
533 | static int ch341_reset_resume(struct usb_interface *intf) | ||
534 | { | ||
535 | struct usb_device *dev = interface_to_usbdev(intf); | ||
536 | struct usb_serial *serial = NULL; | ||
537 | struct ch341_private *priv; | ||
538 | |||
539 | serial = usb_get_intfdata(intf); | ||
540 | priv = usb_get_serial_port_data(serial->port[0]); | ||
541 | |||
542 | /*reconfigure ch341 serial port after bus-reset*/ | ||
543 | ch341_configure(dev, priv); | ||
544 | |||
545 | usb_serial_resume(intf); | ||
546 | |||
547 | return 0; | ||
305 | } | 548 | } |
306 | 549 | ||
307 | static struct usb_driver ch341_driver = { | 550 | static struct usb_driver ch341_driver = { |
308 | .name = "ch341", | 551 | .name = "ch341", |
309 | .probe = usb_serial_probe, | 552 | .probe = usb_serial_probe, |
310 | .disconnect = usb_serial_disconnect, | 553 | .disconnect = usb_serial_disconnect, |
554 | .suspend = usb_serial_suspend, | ||
555 | .resume = usb_serial_resume, | ||
556 | .reset_resume = ch341_reset_resume, | ||
311 | .id_table = id_table, | 557 | .id_table = id_table, |
312 | .no_dynamic_id = 1, | 558 | .no_dynamic_id = 1, |
559 | .supports_autosuspend = 1, | ||
313 | }; | 560 | }; |
314 | 561 | ||
315 | static struct usb_serial_driver ch341_device = { | 562 | static struct usb_serial_driver ch341_device = { |
@@ -317,12 +564,17 @@ static struct usb_serial_driver ch341_device = { | |||
317 | .owner = THIS_MODULE, | 564 | .owner = THIS_MODULE, |
318 | .name = "ch341-uart", | 565 | .name = "ch341-uart", |
319 | }, | 566 | }, |
320 | .id_table = id_table, | 567 | .id_table = id_table, |
321 | .usb_driver = &ch341_driver, | 568 | .usb_driver = &ch341_driver, |
322 | .num_ports = 1, | 569 | .num_ports = 1, |
323 | .open = ch341_open, | 570 | .open = ch341_open, |
324 | .set_termios = ch341_set_termios, | 571 | .close = ch341_close, |
325 | .attach = ch341_attach, | 572 | .ioctl = ch341_ioctl, |
573 | .set_termios = ch341_set_termios, | ||
574 | .tiocmget = ch341_tiocmget, | ||
575 | .tiocmset = ch341_tiocmset, | ||
576 | .read_int_callback = ch341_read_int_callback, | ||
577 | .attach = ch341_attach, | ||
326 | }; | 578 | }; |
327 | 579 | ||
328 | static int __init ch341_init(void) | 580 | static int __init ch341_init(void) |
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp210x.c index 9b4082b58c5..e8d5133ce9c 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp210x.c | |||
@@ -11,10 +11,6 @@ | |||
11 | * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow | 11 | * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow |
12 | * control thanks to Munir Nassar nassarmu@real-time.com | 12 | * control thanks to Munir Nassar nassarmu@real-time.com |
13 | * | 13 | * |
14 | * Outstanding Issues: | ||
15 | * Buffers are not flushed when the port is opened. | ||
16 | * Multiple calls to write() may fail with "Resource temporarily unavailable" | ||
17 | * | ||
18 | */ | 14 | */ |
19 | 15 | ||
20 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
@@ -31,7 +27,7 @@ | |||
31 | /* | 27 | /* |
32 | * Version Information | 28 | * Version Information |
33 | */ | 29 | */ |
34 | #define DRIVER_VERSION "v0.07" | 30 | #define DRIVER_VERSION "v0.08" |
35 | #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" | 31 | #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" |
36 | 32 | ||
37 | /* | 33 | /* |
@@ -42,17 +38,21 @@ static int cp2101_open(struct tty_struct *, struct usb_serial_port *, | |||
42 | static void cp2101_cleanup(struct usb_serial_port *); | 38 | static void cp2101_cleanup(struct usb_serial_port *); |
43 | static void cp2101_close(struct tty_struct *, struct usb_serial_port *, | 39 | static void cp2101_close(struct tty_struct *, struct usb_serial_port *, |
44 | struct file*); | 40 | struct file*); |
45 | static void cp2101_get_termios(struct tty_struct *); | 41 | static void cp2101_get_termios(struct tty_struct *, |
42 | struct usb_serial_port *port); | ||
43 | static void cp2101_get_termios_port(struct usb_serial_port *port, | ||
44 | unsigned int *cflagp, unsigned int *baudp); | ||
46 | static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *, | 45 | static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *, |
47 | struct ktermios*); | 46 | struct ktermios*); |
48 | static int cp2101_tiocmget(struct tty_struct *, struct file *); | 47 | static int cp2101_tiocmget(struct tty_struct *, struct file *); |
49 | static int cp2101_tiocmset(struct tty_struct *, struct file *, | 48 | static int cp2101_tiocmset(struct tty_struct *, struct file *, |
50 | unsigned int, unsigned int); | 49 | unsigned int, unsigned int); |
50 | static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *, | ||
51 | unsigned int, unsigned int); | ||
51 | static void cp2101_break_ctl(struct tty_struct *, int); | 52 | static void cp2101_break_ctl(struct tty_struct *, int); |
52 | static int cp2101_startup(struct usb_serial *); | 53 | static int cp2101_startup(struct usb_serial *); |
53 | static void cp2101_shutdown(struct usb_serial *); | 54 | static void cp2101_shutdown(struct usb_serial *); |
54 | 55 | ||
55 | |||
56 | static int debug; | 56 | static int debug; |
57 | 57 | ||
58 | static struct usb_device_id id_table [] = { | 58 | static struct usb_device_id id_table [] = { |
@@ -91,6 +91,7 @@ static struct usb_device_id id_table [] = { | |||
91 | { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ | 91 | { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ |
92 | { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ | 92 | { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ |
93 | { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ | 93 | { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ |
94 | { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ | ||
94 | { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ | 95 | { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ |
95 | { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ | 96 | { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ |
96 | { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ | 97 | { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ |
@@ -225,7 +226,7 @@ static int cp2101_get_config(struct usb_serial_port *port, u8 request, | |||
225 | kfree(buf); | 226 | kfree(buf); |
226 | 227 | ||
227 | if (result != size) { | 228 | if (result != size) { |
228 | dev_err(&port->dev, "%s - Unable to send config request, " | 229 | dbg("%s - Unable to send config request, " |
229 | "request=0x%x size=%d result=%d\n", | 230 | "request=0x%x size=%d result=%d\n", |
230 | __func__, request, size, result); | 231 | __func__, request, size, result); |
231 | return -EPROTO; | 232 | return -EPROTO; |
@@ -276,7 +277,7 @@ static int cp2101_set_config(struct usb_serial_port *port, u8 request, | |||
276 | kfree(buf); | 277 | kfree(buf); |
277 | 278 | ||
278 | if ((size > 2 && result != size) || result < 0) { | 279 | if ((size > 2 && result != size) || result < 0) { |
279 | dev_err(&port->dev, "%s - Unable to send request, " | 280 | dbg("%s - Unable to send request, " |
280 | "request=0x%x size=%d result=%d\n", | 281 | "request=0x%x size=%d result=%d\n", |
281 | __func__, request, size, result); | 282 | __func__, request, size, result); |
282 | return -EPROTO; | 283 | return -EPROTO; |
@@ -301,6 +302,47 @@ static inline int cp2101_set_config_single(struct usb_serial_port *port, | |||
301 | return cp2101_set_config(port, request, &data, 2); | 302 | return cp2101_set_config(port, request, &data, 2); |
302 | } | 303 | } |
303 | 304 | ||
305 | /* | ||
306 | * cp2101_quantise_baudrate | ||
307 | * Quantises the baud rate as per AN205 Table 1 | ||
308 | */ | ||
309 | static unsigned int cp2101_quantise_baudrate(unsigned int baud) { | ||
310 | if (baud <= 56) baud = 0; | ||
311 | else if (baud <= 300) baud = 300; | ||
312 | else if (baud <= 600) baud = 600; | ||
313 | else if (baud <= 1200) baud = 1200; | ||
314 | else if (baud <= 1800) baud = 1800; | ||
315 | else if (baud <= 2400) baud = 2400; | ||
316 | else if (baud <= 4000) baud = 4000; | ||
317 | else if (baud <= 4803) baud = 4800; | ||
318 | else if (baud <= 7207) baud = 7200; | ||
319 | else if (baud <= 9612) baud = 9600; | ||
320 | else if (baud <= 14428) baud = 14400; | ||
321 | else if (baud <= 16062) baud = 16000; | ||
322 | else if (baud <= 19250) baud = 19200; | ||
323 | else if (baud <= 28912) baud = 28800; | ||
324 | else if (baud <= 38601) baud = 38400; | ||
325 | else if (baud <= 51558) baud = 51200; | ||
326 | else if (baud <= 56280) baud = 56000; | ||
327 | else if (baud <= 58053) baud = 57600; | ||
328 | else if (baud <= 64111) baud = 64000; | ||
329 | else if (baud <= 77608) baud = 76800; | ||
330 | else if (baud <= 117028) baud = 115200; | ||
331 | else if (baud <= 129347) baud = 128000; | ||
332 | else if (baud <= 156868) baud = 153600; | ||
333 | else if (baud <= 237832) baud = 230400; | ||
334 | else if (baud <= 254234) baud = 250000; | ||
335 | else if (baud <= 273066) baud = 256000; | ||
336 | else if (baud <= 491520) baud = 460800; | ||
337 | else if (baud <= 567138) baud = 500000; | ||
338 | else if (baud <= 670254) baud = 576000; | ||
339 | else if (baud <= 1053257) baud = 921600; | ||
340 | else if (baud <= 1474560) baud = 1228800; | ||
341 | else if (baud <= 2457600) baud = 1843200; | ||
342 | else baud = 3686400; | ||
343 | return baud; | ||
344 | } | ||
345 | |||
304 | static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, | 346 | static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, |
305 | struct file *filp) | 347 | struct file *filp) |
306 | { | 348 | { |
@@ -331,10 +373,12 @@ static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
331 | } | 373 | } |
332 | 374 | ||
333 | /* Configure the termios structure */ | 375 | /* Configure the termios structure */ |
334 | cp2101_get_termios(tty); | 376 | cp2101_get_termios(tty, port); |
335 | 377 | ||
336 | /* Set the DTR and RTS pins low */ | 378 | /* Set the DTR and RTS pins low */ |
337 | cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0); | 379 | cp2101_tiocmset_port(tty ? (struct usb_serial_port *) tty->driver_data |
380 | : port, | ||
381 | NULL, TIOCM_DTR | TIOCM_RTS, 0); | ||
338 | 382 | ||
339 | return 0; | 383 | return 0; |
340 | } | 384 | } |
@@ -376,9 +420,31 @@ static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port, | |||
376 | * from the device, corrects any unsupported values, and configures the | 420 | * from the device, corrects any unsupported values, and configures the |
377 | * termios structure to reflect the state of the device | 421 | * termios structure to reflect the state of the device |
378 | */ | 422 | */ |
379 | static void cp2101_get_termios (struct tty_struct *tty) | 423 | static void cp2101_get_termios(struct tty_struct *tty, |
424 | struct usb_serial_port *port) | ||
425 | { | ||
426 | unsigned int baud; | ||
427 | |||
428 | if (tty) { | ||
429 | cp2101_get_termios_port(tty->driver_data, | ||
430 | &tty->termios->c_cflag, &baud); | ||
431 | tty_encode_baud_rate(tty, baud, baud); | ||
432 | } | ||
433 | |||
434 | else { | ||
435 | unsigned int cflag; | ||
436 | cflag = 0; | ||
437 | cp2101_get_termios_port(port, &cflag, &baud); | ||
438 | } | ||
439 | } | ||
440 | |||
441 | /* | ||
442 | * cp2101_get_termios_port | ||
443 | * This is the heart of cp2101_get_termios which always uses a &usb_serial_port. | ||
444 | */ | ||
445 | static void cp2101_get_termios_port(struct usb_serial_port *port, | ||
446 | unsigned int *cflagp, unsigned int *baudp) | ||
380 | { | 447 | { |
381 | struct usb_serial_port *port = tty->driver_data; | ||
382 | unsigned int cflag, modem_ctl[4]; | 448 | unsigned int cflag, modem_ctl[4]; |
383 | unsigned int baud; | 449 | unsigned int baud; |
384 | unsigned int bits; | 450 | unsigned int bits; |
@@ -388,12 +454,12 @@ static void cp2101_get_termios (struct tty_struct *tty) | |||
388 | cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); | 454 | cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); |
389 | /* Convert to baudrate */ | 455 | /* Convert to baudrate */ |
390 | if (baud) | 456 | if (baud) |
391 | baud = BAUD_RATE_GEN_FREQ / baud; | 457 | baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); |
392 | 458 | ||
393 | dbg("%s - baud rate = %d", __func__, baud); | 459 | dbg("%s - baud rate = %d", __func__, baud); |
460 | *baudp = baud; | ||
394 | 461 | ||
395 | tty_encode_baud_rate(tty, baud, baud); | 462 | cflag = *cflagp; |
396 | cflag = tty->termios->c_cflag; | ||
397 | 463 | ||
398 | cp2101_get_config(port, CP2101_BITS, &bits, 2); | 464 | cp2101_get_config(port, CP2101_BITS, &bits, 2); |
399 | cflag &= ~CSIZE; | 465 | cflag &= ~CSIZE; |
@@ -499,7 +565,7 @@ static void cp2101_get_termios (struct tty_struct *tty) | |||
499 | cflag &= ~CRTSCTS; | 565 | cflag &= ~CRTSCTS; |
500 | } | 566 | } |
501 | 567 | ||
502 | tty->termios->c_cflag = cflag; | 568 | *cflagp = cflag; |
503 | } | 569 | } |
504 | 570 | ||
505 | static void cp2101_set_termios(struct tty_struct *tty, | 571 | static void cp2101_set_termios(struct tty_struct *tty, |
@@ -517,46 +583,16 @@ static void cp2101_set_termios(struct tty_struct *tty, | |||
517 | tty->termios->c_cflag &= ~CMSPAR; | 583 | tty->termios->c_cflag &= ~CMSPAR; |
518 | cflag = tty->termios->c_cflag; | 584 | cflag = tty->termios->c_cflag; |
519 | old_cflag = old_termios->c_cflag; | 585 | old_cflag = old_termios->c_cflag; |
520 | baud = tty_get_baud_rate(tty); | 586 | baud = cp2101_quantise_baudrate(tty_get_baud_rate(tty)); |
521 | 587 | ||
522 | /* If the baud rate is to be updated*/ | 588 | /* If the baud rate is to be updated*/ |
523 | if (baud != tty_termios_baud_rate(old_termios)) { | 589 | if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { |
524 | switch (baud) { | 590 | dbg("%s - Setting baud rate to %d baud", __func__, |
525 | case 0: | 591 | baud); |
526 | case 600: | 592 | if (cp2101_set_config_single(port, CP2101_BAUDRATE, |
527 | case 1200: | 593 | ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { |
528 | case 1800: | 594 | dbg("Baud rate requested not supported by device\n"); |
529 | case 2400: | 595 | baud = tty_termios_baud_rate(old_termios); |
530 | case 4800: | ||
531 | case 7200: | ||
532 | case 9600: | ||
533 | case 14400: | ||
534 | case 19200: | ||
535 | case 28800: | ||
536 | case 38400: | ||
537 | case 55854: | ||
538 | case 57600: | ||
539 | case 115200: | ||
540 | case 127117: | ||
541 | case 230400: | ||
542 | case 460800: | ||
543 | case 921600: | ||
544 | case 3686400: | ||
545 | break; | ||
546 | default: | ||
547 | baud = 9600; | ||
548 | break; | ||
549 | } | ||
550 | |||
551 | if (baud) { | ||
552 | dbg("%s - Setting baud rate to %d baud", __func__, | ||
553 | baud); | ||
554 | if (cp2101_set_config_single(port, CP2101_BAUDRATE, | ||
555 | (BAUD_RATE_GEN_FREQ / baud))) { | ||
556 | dev_err(&port->dev, "Baud rate requested not " | ||
557 | "supported by device\n"); | ||
558 | baud = tty_termios_baud_rate(old_termios); | ||
559 | } | ||
560 | } | 596 | } |
561 | } | 597 | } |
562 | /* Report back the resulting baud rate */ | 598 | /* Report back the resulting baud rate */ |
@@ -588,14 +624,14 @@ static void cp2101_set_termios(struct tty_struct *tty, | |||
588 | dbg("%s - data bits = 9", __func__); | 624 | dbg("%s - data bits = 9", __func__); |
589 | break;*/ | 625 | break;*/ |
590 | default: | 626 | default: |
591 | dev_err(&port->dev, "cp2101 driver does not " | 627 | dbg("cp2101 driver does not " |
592 | "support the number of bits requested," | 628 | "support the number of bits requested," |
593 | " using 8 bit mode\n"); | 629 | " using 8 bit mode\n"); |
594 | bits |= BITS_DATA_8; | 630 | bits |= BITS_DATA_8; |
595 | break; | 631 | break; |
596 | } | 632 | } |
597 | if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) | 633 | if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) |
598 | dev_err(&port->dev, "Number of data bits requested " | 634 | dbg("Number of data bits requested " |
599 | "not supported by device\n"); | 635 | "not supported by device\n"); |
600 | } | 636 | } |
601 | 637 | ||
@@ -612,7 +648,7 @@ static void cp2101_set_termios(struct tty_struct *tty, | |||
612 | } | 648 | } |
613 | } | 649 | } |
614 | if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) | 650 | if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) |
615 | dev_err(&port->dev, "Parity mode not supported " | 651 | dbg("Parity mode not supported " |
616 | "by device\n"); | 652 | "by device\n"); |
617 | } | 653 | } |
618 | 654 | ||
@@ -627,7 +663,7 @@ static void cp2101_set_termios(struct tty_struct *tty, | |||
627 | dbg("%s - stop bits = 1", __func__); | 663 | dbg("%s - stop bits = 1", __func__); |
628 | } | 664 | } |
629 | if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) | 665 | if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) |
630 | dev_err(&port->dev, "Number of stop bits requested " | 666 | dbg("Number of stop bits requested " |
631 | "not supported by device\n"); | 667 | "not supported by device\n"); |
632 | } | 668 | } |
633 | 669 | ||
@@ -661,6 +697,12 @@ static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, | |||
661 | unsigned int set, unsigned int clear) | 697 | unsigned int set, unsigned int clear) |
662 | { | 698 | { |
663 | struct usb_serial_port *port = tty->driver_data; | 699 | struct usb_serial_port *port = tty->driver_data; |
700 | return cp2101_tiocmset_port(port, file, set, clear); | ||
701 | } | ||
702 | |||
703 | static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *file, | ||
704 | unsigned int set, unsigned int clear) | ||
705 | { | ||
664 | unsigned int control = 0; | 706 | unsigned int control = 0; |
665 | 707 | ||
666 | dbg("%s - port %d", __func__, port->number); | 708 | dbg("%s - port %d", __func__, port->number); |
@@ -685,7 +727,6 @@ static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, | |||
685 | dbg("%s - control = 0x%.4x", __func__, control); | 727 | dbg("%s - control = 0x%.4x", __func__, control); |
686 | 728 | ||
687 | return cp2101_set_config(port, CP2101_CONTROL, &control, 2); | 729 | return cp2101_set_config(port, CP2101_CONTROL, &control, 2); |
688 | |||
689 | } | 730 | } |
690 | 731 | ||
691 | static int cp2101_tiocmget (struct tty_struct *tty, struct file *file) | 732 | static int cp2101_tiocmget (struct tty_struct *tty, struct file *file) |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ae84c326a54..dcc87aaa862 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -1938,18 +1938,16 @@ static void ftdi_process_read(struct work_struct *work) | |||
1938 | /* Compare new line status to the old one, signal if different/ | 1938 | /* Compare new line status to the old one, signal if different/ |
1939 | N.B. packet may be processed more than once, but differences | 1939 | N.B. packet may be processed more than once, but differences |
1940 | are only processed once. */ | 1940 | are only processed once. */ |
1941 | if (priv != NULL) { | 1941 | char new_status = data[packet_offset + 0] & |
1942 | char new_status = data[packet_offset + 0] & | 1942 | FTDI_STATUS_B0_MASK; |
1943 | FTDI_STATUS_B0_MASK; | 1943 | if (new_status != priv->prev_status) { |
1944 | if (new_status != priv->prev_status) { | 1944 | priv->diff_status |= |
1945 | priv->diff_status |= | 1945 | new_status ^ priv->prev_status; |
1946 | new_status ^ priv->prev_status; | 1946 | wake_up_interruptible(&priv->delta_msr_wait); |
1947 | wake_up_interruptible(&priv->delta_msr_wait); | 1947 | priv->prev_status = new_status; |
1948 | priv->prev_status = new_status; | ||
1949 | } | ||
1950 | } | 1948 | } |
1951 | 1949 | ||
1952 | length = min(PKTSZ, urb->actual_length-packet_offset)-2; | 1950 | length = min_t(u32, PKTSZ, urb->actual_length-packet_offset)-2; |
1953 | if (length < 0) { | 1951 | if (length < 0) { |
1954 | dev_err(&port->dev, "%s - bad packet length: %d\n", | 1952 | dev_err(&port->dev, "%s - bad packet length: %d\n", |
1955 | __func__, length+2); | 1953 | __func__, length+2); |
@@ -2294,11 +2292,8 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) | |||
2294 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, | 2292 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, |
2295 | 0, 0, | 2293 | 0, 0, |
2296 | buf, 1, WDR_TIMEOUT); | 2294 | buf, 1, WDR_TIMEOUT); |
2297 | if (ret < 0) { | 2295 | if (ret < 0) |
2298 | dbg("%s Could not get modem status of device - err: %d", __func__, | ||
2299 | ret); | ||
2300 | return ret; | 2296 | return ret; |
2301 | } | ||
2302 | break; | 2297 | break; |
2303 | case FT8U232AM: | 2298 | case FT8U232AM: |
2304 | case FT232BM: | 2299 | case FT232BM: |
@@ -2313,15 +2308,11 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) | |||
2313 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, | 2308 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, |
2314 | 0, priv->interface, | 2309 | 0, priv->interface, |
2315 | buf, 2, WDR_TIMEOUT); | 2310 | buf, 2, WDR_TIMEOUT); |
2316 | if (ret < 0) { | 2311 | if (ret < 0) |
2317 | dbg("%s Could not get modem status of device - err: %d", __func__, | ||
2318 | ret); | ||
2319 | return ret; | 2312 | return ret; |
2320 | } | ||
2321 | break; | 2313 | break; |
2322 | default: | 2314 | default: |
2323 | return -EFAULT; | 2315 | return -EFAULT; |
2324 | break; | ||
2325 | } | 2316 | } |
2326 | 2317 | ||
2327 | return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | | 2318 | return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | |
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 814909f1ee6..9d57cace373 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -177,14 +177,6 @@ int usb_serial_generic_resume(struct usb_serial *serial) | |||
177 | struct usb_serial_port *port; | 177 | struct usb_serial_port *port; |
178 | int i, c = 0, r; | 178 | int i, c = 0, r; |
179 | 179 | ||
180 | #ifdef CONFIG_PM | ||
181 | /* | ||
182 | * If this is an autoresume, don't submit URBs. | ||
183 | * They will be submitted in the open function instead. | ||
184 | */ | ||
185 | if (serial->dev->auto_pm) | ||
186 | return 0; | ||
187 | #endif | ||
188 | for (i = 0; i < serial->num_ports; i++) { | 180 | for (i = 0; i < serial->num_ports; i++) { |
189 | port = serial->port[i]; | 181 | port = serial->port[i]; |
190 | if (port->port.count && port->read_urb) { | 182 | if (port->port.count && port->read_urb) { |
@@ -196,6 +188,7 @@ int usb_serial_generic_resume(struct usb_serial *serial) | |||
196 | 188 | ||
197 | return c ? -EIO : 0; | 189 | return c ? -EIO : 0; |
198 | } | 190 | } |
191 | EXPORT_SYMBOL_GPL(usb_serial_generic_resume); | ||
199 | 192 | ||
200 | void usb_serial_generic_close(struct tty_struct *tty, | 193 | void usb_serial_generic_close(struct tty_struct *tty, |
201 | struct usb_serial_port *port, struct file *filp) | 194 | struct usb_serial_port *port, struct file *filp) |
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 132be74d2b8..ef92095b073 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -78,6 +78,7 @@ static int ipaq_open(struct tty_struct *tty, | |||
78 | struct usb_serial_port *port, struct file *filp); | 78 | struct usb_serial_port *port, struct file *filp); |
79 | static void ipaq_close(struct tty_struct *tty, | 79 | static void ipaq_close(struct tty_struct *tty, |
80 | struct usb_serial_port *port, struct file *filp); | 80 | struct usb_serial_port *port, struct file *filp); |
81 | static int ipaq_calc_num_ports(struct usb_serial *serial); | ||
81 | static int ipaq_startup(struct usb_serial *serial); | 82 | static int ipaq_startup(struct usb_serial *serial); |
82 | static void ipaq_shutdown(struct usb_serial *serial); | 83 | static void ipaq_shutdown(struct usb_serial *serial); |
83 | static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port, | 84 | static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port, |
@@ -572,15 +573,10 @@ static struct usb_serial_driver ipaq_device = { | |||
572 | .description = "PocketPC PDA", | 573 | .description = "PocketPC PDA", |
573 | .usb_driver = &ipaq_driver, | 574 | .usb_driver = &ipaq_driver, |
574 | .id_table = ipaq_id_table, | 575 | .id_table = ipaq_id_table, |
575 | /* | ||
576 | * some devices have an extra endpoint, which | ||
577 | * must be ignored as it would make the core | ||
578 | * create a second port which oopses when used | ||
579 | */ | ||
580 | .num_ports = 1, | ||
581 | .open = ipaq_open, | 576 | .open = ipaq_open, |
582 | .close = ipaq_close, | 577 | .close = ipaq_close, |
583 | .attach = ipaq_startup, | 578 | .attach = ipaq_startup, |
579 | .calc_num_ports = ipaq_calc_num_ports, | ||
584 | .shutdown = ipaq_shutdown, | 580 | .shutdown = ipaq_shutdown, |
585 | .write = ipaq_write, | 581 | .write = ipaq_write, |
586 | .write_room = ipaq_write_room, | 582 | .write_room = ipaq_write_room, |
@@ -956,14 +952,49 @@ static void ipaq_destroy_lists(struct usb_serial_port *port) | |||
956 | } | 952 | } |
957 | 953 | ||
958 | 954 | ||
955 | static int ipaq_calc_num_ports(struct usb_serial *serial) | ||
956 | { | ||
957 | /* | ||
958 | * some devices have 3 endpoints, the 3rd of which | ||
959 | * must be ignored as it would make the core | ||
960 | * create a second port which oopses when used | ||
961 | */ | ||
962 | int ipaq_num_ports = 1; | ||
963 | |||
964 | dbg("%s - numberofendpoints: %d", __FUNCTION__, | ||
965 | (int)serial->interface->cur_altsetting->desc.bNumEndpoints); | ||
966 | |||
967 | /* | ||
968 | * a few devices have 4 endpoints, seemingly Yakuma devices, | ||
969 | * and we need the second pair, so let them have 2 ports | ||
970 | * | ||
971 | * TODO: can we drop port 1 ? | ||
972 | */ | ||
973 | if (serial->interface->cur_altsetting->desc.bNumEndpoints > 3) { | ||
974 | ipaq_num_ports = 2; | ||
975 | } | ||
976 | |||
977 | return ipaq_num_ports; | ||
978 | } | ||
979 | |||
980 | |||
959 | static int ipaq_startup(struct usb_serial *serial) | 981 | static int ipaq_startup(struct usb_serial *serial) |
960 | { | 982 | { |
961 | dbg("%s", __func__); | 983 | dbg("%s", __func__); |
962 | if (serial->dev->actconfig->desc.bConfigurationValue != 1) { | 984 | if (serial->dev->actconfig->desc.bConfigurationValue != 1) { |
985 | /* | ||
986 | * FIXME: HP iPaq rx3715, possibly others, have 1 config that | ||
987 | * is labeled as 2 | ||
988 | */ | ||
989 | |||
963 | dev_err(&serial->dev->dev, "active config #%d != 1 ??\n", | 990 | dev_err(&serial->dev->dev, "active config #%d != 1 ??\n", |
964 | serial->dev->actconfig->desc.bConfigurationValue); | 991 | serial->dev->actconfig->desc.bConfigurationValue); |
965 | return -ENODEV; | 992 | return -ENODEV; |
966 | } | 993 | } |
994 | |||
995 | dbg("%s - iPAQ module configured for %d ports", | ||
996 | __FUNCTION__, serial->num_ports); | ||
997 | |||
967 | return usb_reset_configuration(serial->dev); | 998 | return usb_reset_configuration(serial->dev); |
968 | } | 999 | } |
969 | 1000 | ||
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 9878c0fb385..00daa8f7759 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c | |||
@@ -1507,7 +1507,7 @@ static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint, | |||
1507 | } else { | 1507 | } else { |
1508 | dev_warn(&serial->interface->dev, | 1508 | dev_warn(&serial->interface->dev, |
1509 | "unsupported endpoint type %x\n", | 1509 | "unsupported endpoint type %x\n", |
1510 | ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); | 1510 | usb_endpoint_type(ep_desc)); |
1511 | usb_free_urb(urb); | 1511 | usb_free_urb(urb); |
1512 | return NULL; | 1512 | return NULL; |
1513 | } | 1513 | } |
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index cea326f1f10..839583dc8b6 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Opticon USB barcode to serial driver | 2 | * Opticon USB barcode to serial driver |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de> | 4 | * Copyright (C) 2008 - 2009 Greg Kroah-Hartman <gregkh@suse.de> |
5 | * Copyright (C) 2008 Novell Inc. | 5 | * Copyright (C) 2008 - 2009 Novell Inc. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License version | 8 | * modify it under the terms of the GNU General Public License version |
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/tty.h> | 14 | #include <linux/tty.h> |
15 | #include <linux/tty_driver.h> | 15 | #include <linux/tty_driver.h> |
16 | #include <linux/tty_flip.h> | 16 | #include <linux/tty_flip.h> |
17 | #include <linux/serial.h> | ||
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
18 | #include <linux/usb.h> | 19 | #include <linux/usb.h> |
19 | #include <linux/usb/serial.h> | 20 | #include <linux/usb/serial.h> |
@@ -40,8 +41,12 @@ struct opticon_private { | |||
40 | bool throttled; | 41 | bool throttled; |
41 | bool actually_throttled; | 42 | bool actually_throttled; |
42 | bool rts; | 43 | bool rts; |
44 | int outstanding_urbs; | ||
43 | }; | 45 | }; |
44 | 46 | ||
47 | /* max number of write urbs in flight */ | ||
48 | #define URB_UPPER_LIMIT 4 | ||
49 | |||
45 | static void opticon_bulk_callback(struct urb *urb) | 50 | static void opticon_bulk_callback(struct urb *urb) |
46 | { | 51 | { |
47 | struct opticon_private *priv = urb->context; | 52 | struct opticon_private *priv = urb->context; |
@@ -106,7 +111,6 @@ static void opticon_bulk_callback(struct urb *urb) | |||
106 | priv->rts = false; | 111 | priv->rts = false; |
107 | else | 112 | else |
108 | priv->rts = true; | 113 | priv->rts = true; |
109 | /* FIXME change the RTS level */ | ||
110 | } else { | 114 | } else { |
111 | dev_dbg(&priv->udev->dev, | 115 | dev_dbg(&priv->udev->dev, |
112 | "Unknown data packet received from the device:" | 116 | "Unknown data packet received from the device:" |
@@ -188,6 +192,120 @@ static void opticon_close(struct tty_struct *tty, struct usb_serial_port *port, | |||
188 | usb_kill_urb(priv->bulk_read_urb); | 192 | usb_kill_urb(priv->bulk_read_urb); |
189 | } | 193 | } |
190 | 194 | ||
195 | static void opticon_write_bulk_callback(struct urb *urb) | ||
196 | { | ||
197 | struct opticon_private *priv = urb->context; | ||
198 | int status = urb->status; | ||
199 | unsigned long flags; | ||
200 | |||
201 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | ||
202 | kfree(urb->transfer_buffer); | ||
203 | |||
204 | if (status) | ||
205 | dbg("%s - nonzero write bulk status received: %d", | ||
206 | __func__, status); | ||
207 | |||
208 | spin_lock_irqsave(&priv->lock, flags); | ||
209 | --priv->outstanding_urbs; | ||
210 | spin_unlock_irqrestore(&priv->lock, flags); | ||
211 | |||
212 | usb_serial_port_softint(priv->port); | ||
213 | } | ||
214 | |||
215 | static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
216 | const unsigned char *buf, int count) | ||
217 | { | ||
218 | struct opticon_private *priv = usb_get_serial_data(port->serial); | ||
219 | struct usb_serial *serial = port->serial; | ||
220 | struct urb *urb; | ||
221 | unsigned char *buffer; | ||
222 | unsigned long flags; | ||
223 | int status; | ||
224 | |||
225 | dbg("%s - port %d", __func__, port->number); | ||
226 | |||
227 | spin_lock_irqsave(&priv->lock, flags); | ||
228 | if (priv->outstanding_urbs > URB_UPPER_LIMIT) { | ||
229 | spin_unlock_irqrestore(&priv->lock, flags); | ||
230 | dbg("%s - write limit hit\n", __func__); | ||
231 | return 0; | ||
232 | } | ||
233 | priv->outstanding_urbs++; | ||
234 | spin_unlock_irqrestore(&priv->lock, flags); | ||
235 | |||
236 | buffer = kmalloc(count, GFP_ATOMIC); | ||
237 | if (!buffer) { | ||
238 | dev_err(&port->dev, "out of memory\n"); | ||
239 | count = -ENOMEM; | ||
240 | goto error_no_buffer; | ||
241 | } | ||
242 | |||
243 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
244 | if (!urb) { | ||
245 | dev_err(&port->dev, "no more free urbs\n"); | ||
246 | count = -ENOMEM; | ||
247 | goto error_no_urb; | ||
248 | } | ||
249 | |||
250 | memcpy(buffer, buf, count); | ||
251 | |||
252 | usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); | ||
253 | |||
254 | usb_fill_bulk_urb(urb, serial->dev, | ||
255 | usb_sndbulkpipe(serial->dev, | ||
256 | port->bulk_out_endpointAddress), | ||
257 | buffer, count, opticon_write_bulk_callback, priv); | ||
258 | |||
259 | /* send it down the pipe */ | ||
260 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
261 | if (status) { | ||
262 | dev_err(&port->dev, | ||
263 | "%s - usb_submit_urb(write bulk) failed with status = %d\n", | ||
264 | __func__, status); | ||
265 | count = status; | ||
266 | goto error; | ||
267 | } | ||
268 | |||
269 | /* we are done with this urb, so let the host driver | ||
270 | * really free it when it is finished with it */ | ||
271 | usb_free_urb(urb); | ||
272 | |||
273 | return count; | ||
274 | error: | ||
275 | usb_free_urb(urb); | ||
276 | error_no_urb: | ||
277 | kfree(buffer); | ||
278 | error_no_buffer: | ||
279 | spin_lock_irqsave(&priv->lock, flags); | ||
280 | --priv->outstanding_urbs; | ||
281 | spin_unlock_irqrestore(&priv->lock, flags); | ||
282 | return count; | ||
283 | } | ||
284 | |||
285 | static int opticon_write_room(struct tty_struct *tty) | ||
286 | { | ||
287 | struct usb_serial_port *port = tty->driver_data; | ||
288 | struct opticon_private *priv = usb_get_serial_data(port->serial); | ||
289 | unsigned long flags; | ||
290 | |||
291 | dbg("%s - port %d", __func__, port->number); | ||
292 | |||
293 | /* | ||
294 | * We really can take almost anything the user throws at us | ||
295 | * but let's pick a nice big number to tell the tty | ||
296 | * layer that we have lots of free space, unless we don't. | ||
297 | */ | ||
298 | spin_lock_irqsave(&priv->lock, flags); | ||
299 | if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) { | ||
300 | spin_unlock_irqrestore(&priv->lock, flags); | ||
301 | dbg("%s - write limit hit\n", __func__); | ||
302 | return 0; | ||
303 | } | ||
304 | spin_unlock_irqrestore(&priv->lock, flags); | ||
305 | |||
306 | return 2048; | ||
307 | } | ||
308 | |||
191 | static void opticon_throttle(struct tty_struct *tty) | 309 | static void opticon_throttle(struct tty_struct *tty) |
192 | { | 310 | { |
193 | struct usb_serial_port *port = tty->driver_data; | 311 | struct usb_serial_port *port = tty->driver_data; |
@@ -223,6 +341,67 @@ static void opticon_unthrottle(struct tty_struct *tty) | |||
223 | __func__, result); | 341 | __func__, result); |
224 | } | 342 | } |
225 | 343 | ||
344 | static int opticon_tiocmget(struct tty_struct *tty, struct file *file) | ||
345 | { | ||
346 | struct usb_serial_port *port = tty->driver_data; | ||
347 | struct opticon_private *priv = usb_get_serial_data(port->serial); | ||
348 | unsigned long flags; | ||
349 | int result = 0; | ||
350 | |||
351 | dbg("%s - port %d", __func__, port->number); | ||
352 | |||
353 | spin_lock_irqsave(&priv->lock, flags); | ||
354 | if (priv->rts) | ||
355 | result = TIOCM_RTS; | ||
356 | spin_unlock_irqrestore(&priv->lock, flags); | ||
357 | |||
358 | dbg("%s - %x", __func__, result); | ||
359 | return result; | ||
360 | } | ||
361 | |||
362 | static int get_serial_info(struct opticon_private *priv, | ||
363 | struct serial_struct __user *serial) | ||
364 | { | ||
365 | struct serial_struct tmp; | ||
366 | |||
367 | if (!serial) | ||
368 | return -EFAULT; | ||
369 | |||
370 | memset(&tmp, 0x00, sizeof(tmp)); | ||
371 | |||
372 | /* fake emulate a 16550 uart to make userspace code happy */ | ||
373 | tmp.type = PORT_16550A; | ||
374 | tmp.line = priv->serial->minor; | ||
375 | tmp.port = 0; | ||
376 | tmp.irq = 0; | ||
377 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | ||
378 | tmp.xmit_fifo_size = 1024; | ||
379 | tmp.baud_base = 9600; | ||
380 | tmp.close_delay = 5*HZ; | ||
381 | tmp.closing_wait = 30*HZ; | ||
382 | |||
383 | if (copy_to_user(serial, &tmp, sizeof(*serial))) | ||
384 | return -EFAULT; | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static int opticon_ioctl(struct tty_struct *tty, struct file *file, | ||
389 | unsigned int cmd, unsigned long arg) | ||
390 | { | ||
391 | struct usb_serial_port *port = tty->driver_data; | ||
392 | struct opticon_private *priv = usb_get_serial_data(port->serial); | ||
393 | |||
394 | dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); | ||
395 | |||
396 | switch (cmd) { | ||
397 | case TIOCGSERIAL: | ||
398 | return get_serial_info(priv, | ||
399 | (struct serial_struct __user *)arg); | ||
400 | } | ||
401 | |||
402 | return -ENOIOCTLCMD; | ||
403 | } | ||
404 | |||
226 | static int opticon_startup(struct usb_serial *serial) | 405 | static int opticon_startup(struct usb_serial *serial) |
227 | { | 406 | { |
228 | struct opticon_private *priv; | 407 | struct opticon_private *priv; |
@@ -306,11 +485,37 @@ static void opticon_shutdown(struct usb_serial *serial) | |||
306 | usb_set_serial_data(serial, NULL); | 485 | usb_set_serial_data(serial, NULL); |
307 | } | 486 | } |
308 | 487 | ||
488 | static int opticon_suspend(struct usb_interface *intf, pm_message_t message) | ||
489 | { | ||
490 | struct usb_serial *serial = usb_get_intfdata(intf); | ||
491 | struct opticon_private *priv = usb_get_serial_data(serial); | ||
492 | |||
493 | usb_kill_urb(priv->bulk_read_urb); | ||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | static int opticon_resume(struct usb_interface *intf) | ||
498 | { | ||
499 | struct usb_serial *serial = usb_get_intfdata(intf); | ||
500 | struct opticon_private *priv = usb_get_serial_data(serial); | ||
501 | struct usb_serial_port *port = serial->port[0]; | ||
502 | int result; | ||
503 | |||
504 | mutex_lock(&port->mutex); | ||
505 | if (port->port.count) | ||
506 | result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); | ||
507 | else | ||
508 | result = 0; | ||
509 | mutex_unlock(&port->mutex); | ||
510 | return result; | ||
511 | } | ||
309 | 512 | ||
310 | static struct usb_driver opticon_driver = { | 513 | static struct usb_driver opticon_driver = { |
311 | .name = "opticon", | 514 | .name = "opticon", |
312 | .probe = usb_serial_probe, | 515 | .probe = usb_serial_probe, |
313 | .disconnect = usb_serial_disconnect, | 516 | .disconnect = usb_serial_disconnect, |
517 | .suspend = opticon_suspend, | ||
518 | .resume = opticon_resume, | ||
314 | .id_table = id_table, | 519 | .id_table = id_table, |
315 | .no_dynamic_id = 1, | 520 | .no_dynamic_id = 1, |
316 | }; | 521 | }; |
@@ -326,9 +531,13 @@ static struct usb_serial_driver opticon_device = { | |||
326 | .attach = opticon_startup, | 531 | .attach = opticon_startup, |
327 | .open = opticon_open, | 532 | .open = opticon_open, |
328 | .close = opticon_close, | 533 | .close = opticon_close, |
534 | .write = opticon_write, | ||
535 | .write_room = opticon_write_room, | ||
329 | .shutdown = opticon_shutdown, | 536 | .shutdown = opticon_shutdown, |
330 | .throttle = opticon_throttle, | 537 | .throttle = opticon_throttle, |
331 | .unthrottle = opticon_unthrottle, | 538 | .unthrottle = opticon_unthrottle, |
539 | .ioctl = opticon_ioctl, | ||
540 | .tiocmget = opticon_tiocmget, | ||
332 | }; | 541 | }; |
333 | 542 | ||
334 | static int __init opticon_init(void) | 543 | static int __init opticon_init(void) |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 61ebddc4849..d560c0b54e6 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -62,6 +62,8 @@ static int option_tiocmget(struct tty_struct *tty, struct file *file); | |||
62 | static int option_tiocmset(struct tty_struct *tty, struct file *file, | 62 | static int option_tiocmset(struct tty_struct *tty, struct file *file, |
63 | unsigned int set, unsigned int clear); | 63 | unsigned int set, unsigned int clear); |
64 | static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *port); | 64 | static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *port); |
65 | static int option_suspend(struct usb_serial *serial, pm_message_t message); | ||
66 | static int option_resume(struct usb_serial *serial); | ||
65 | 67 | ||
66 | /* Vendor and product IDs */ | 68 | /* Vendor and product IDs */ |
67 | #define OPTION_VENDOR_ID 0x0AF0 | 69 | #define OPTION_VENDOR_ID 0x0AF0 |
@@ -523,6 +525,8 @@ static struct usb_driver option_driver = { | |||
523 | .name = "option", | 525 | .name = "option", |
524 | .probe = usb_serial_probe, | 526 | .probe = usb_serial_probe, |
525 | .disconnect = usb_serial_disconnect, | 527 | .disconnect = usb_serial_disconnect, |
528 | .suspend = usb_serial_suspend, | ||
529 | .resume = usb_serial_resume, | ||
526 | .id_table = option_ids, | 530 | .id_table = option_ids, |
527 | .no_dynamic_id = 1, | 531 | .no_dynamic_id = 1, |
528 | }; | 532 | }; |
@@ -551,6 +555,8 @@ static struct usb_serial_driver option_1port_device = { | |||
551 | .attach = option_startup, | 555 | .attach = option_startup, |
552 | .shutdown = option_shutdown, | 556 | .shutdown = option_shutdown, |
553 | .read_int_callback = option_instat_callback, | 557 | .read_int_callback = option_instat_callback, |
558 | .suspend = option_suspend, | ||
559 | .resume = option_resume, | ||
554 | }; | 560 | }; |
555 | 561 | ||
556 | static int debug; | 562 | static int debug; |
@@ -821,10 +827,10 @@ static void option_instat_callback(struct urb *urb) | |||
821 | req_pkt->bRequestType, req_pkt->bRequest); | 827 | req_pkt->bRequestType, req_pkt->bRequest); |
822 | } | 828 | } |
823 | } else | 829 | } else |
824 | dbg("%s: error %d", __func__, status); | 830 | err("%s: error %d", __func__, status); |
825 | 831 | ||
826 | /* Resubmit urb so we continue receiving IRQ data */ | 832 | /* Resubmit urb so we continue receiving IRQ data */ |
827 | if (status != -ESHUTDOWN) { | 833 | if (status != -ESHUTDOWN && status != -ENOENT) { |
828 | urb->dev = serial->dev; | 834 | urb->dev = serial->dev; |
829 | err = usb_submit_urb(urb, GFP_ATOMIC); | 835 | err = usb_submit_urb(urb, GFP_ATOMIC); |
830 | if (err) | 836 | if (err) |
@@ -843,7 +849,6 @@ static int option_write_room(struct tty_struct *tty) | |||
843 | 849 | ||
844 | portdata = usb_get_serial_port_data(port); | 850 | portdata = usb_get_serial_port_data(port); |
845 | 851 | ||
846 | |||
847 | for (i = 0; i < N_OUT_URB; i++) { | 852 | for (i = 0; i < N_OUT_URB; i++) { |
848 | this_urb = portdata->out_urbs[i]; | 853 | this_urb = portdata->out_urbs[i]; |
849 | if (this_urb && !test_bit(i, &portdata->out_busy)) | 854 | if (this_urb && !test_bit(i, &portdata->out_busy)) |
@@ -1105,14 +1110,12 @@ bail_out_error: | |||
1105 | return 1; | 1110 | return 1; |
1106 | } | 1111 | } |
1107 | 1112 | ||
1108 | static void option_shutdown(struct usb_serial *serial) | 1113 | static void stop_read_write_urbs(struct usb_serial *serial) |
1109 | { | 1114 | { |
1110 | int i, j; | 1115 | int i, j; |
1111 | struct usb_serial_port *port; | 1116 | struct usb_serial_port *port; |
1112 | struct option_port_private *portdata; | 1117 | struct option_port_private *portdata; |
1113 | 1118 | ||
1114 | dbg("%s", __func__); | ||
1115 | |||
1116 | /* Stop reading/writing urbs */ | 1119 | /* Stop reading/writing urbs */ |
1117 | for (i = 0; i < serial->num_ports; ++i) { | 1120 | for (i = 0; i < serial->num_ports; ++i) { |
1118 | port = serial->port[i]; | 1121 | port = serial->port[i]; |
@@ -1122,6 +1125,17 @@ static void option_shutdown(struct usb_serial *serial) | |||
1122 | for (j = 0; j < N_OUT_URB; j++) | 1125 | for (j = 0; j < N_OUT_URB; j++) |
1123 | usb_kill_urb(portdata->out_urbs[j]); | 1126 | usb_kill_urb(portdata->out_urbs[j]); |
1124 | } | 1127 | } |
1128 | } | ||
1129 | |||
1130 | static void option_shutdown(struct usb_serial *serial) | ||
1131 | { | ||
1132 | int i, j; | ||
1133 | struct usb_serial_port *port; | ||
1134 | struct option_port_private *portdata; | ||
1135 | |||
1136 | dbg("%s", __func__); | ||
1137 | |||
1138 | stop_read_write_urbs(serial); | ||
1125 | 1139 | ||
1126 | /* Now free them */ | 1140 | /* Now free them */ |
1127 | for (i = 0; i < serial->num_ports; ++i) { | 1141 | for (i = 0; i < serial->num_ports; ++i) { |
@@ -1152,6 +1166,66 @@ static void option_shutdown(struct usb_serial *serial) | |||
1152 | } | 1166 | } |
1153 | } | 1167 | } |
1154 | 1168 | ||
1169 | static int option_suspend(struct usb_serial *serial, pm_message_t message) | ||
1170 | { | ||
1171 | dbg("%s entered", __func__); | ||
1172 | stop_read_write_urbs(serial); | ||
1173 | |||
1174 | return 0; | ||
1175 | } | ||
1176 | |||
1177 | static int option_resume(struct usb_serial *serial) | ||
1178 | { | ||
1179 | int err, i, j; | ||
1180 | struct usb_serial_port *port; | ||
1181 | struct urb *urb; | ||
1182 | struct option_port_private *portdata; | ||
1183 | |||
1184 | dbg("%s entered", __func__); | ||
1185 | /* get the interrupt URBs resubmitted unconditionally */ | ||
1186 | for (i = 0; i < serial->num_ports; i++) { | ||
1187 | port = serial->port[i]; | ||
1188 | if (!port->interrupt_in_urb) { | ||
1189 | dbg("%s: No interrupt URB for port %d\n", __func__, i); | ||
1190 | continue; | ||
1191 | } | ||
1192 | port->interrupt_in_urb->dev = serial->dev; | ||
1193 | err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); | ||
1194 | dbg("Submitted interrupt URB for port %d (result %d)", i, err); | ||
1195 | if (err < 0) { | ||
1196 | err("%s: Error %d for interrupt URB of port%d", | ||
1197 | __func__, err, i); | ||
1198 | return err; | ||
1199 | } | ||
1200 | } | ||
1201 | |||
1202 | for (i = 0; i < serial->num_ports; i++) { | ||
1203 | /* walk all ports */ | ||
1204 | port = serial->port[i]; | ||
1205 | portdata = usb_get_serial_port_data(port); | ||
1206 | mutex_lock(&port->mutex); | ||
1207 | |||
1208 | /* skip closed ports */ | ||
1209 | if (!port->port.count) { | ||
1210 | mutex_unlock(&port->mutex); | ||
1211 | continue; | ||
1212 | } | ||
1213 | |||
1214 | for (j = 0; j < N_IN_URB; j++) { | ||
1215 | urb = portdata->in_urbs[j]; | ||
1216 | err = usb_submit_urb(urb, GFP_NOIO); | ||
1217 | if (err < 0) { | ||
1218 | mutex_unlock(&port->mutex); | ||
1219 | err("%s: Error %d for bulk URB %d", | ||
1220 | __func__, err, i); | ||
1221 | return err; | ||
1222 | } | ||
1223 | } | ||
1224 | mutex_unlock(&port->mutex); | ||
1225 | } | ||
1226 | return 0; | ||
1227 | } | ||
1228 | |||
1155 | MODULE_AUTHOR(DRIVER_AUTHOR); | 1229 | MODULE_AUTHOR(DRIVER_AUTHOR); |
1156 | MODULE_DESCRIPTION(DRIVER_DESC); | 1230 | MODULE_DESCRIPTION(DRIVER_DESC); |
1157 | MODULE_VERSION(DRIVER_VERSION); | 1231 | MODULE_VERSION(DRIVER_VERSION); |
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c new file mode 100644 index 00000000000..e6d6b0c17fd --- /dev/null +++ b/drivers/usb/serial/qcserial.c | |||
@@ -0,0 +1,147 @@ | |||
1 | /* | ||
2 | * Qualcomm Serial USB driver | ||
3 | * | ||
4 | * Copyright (c) 2008 QUALCOMM Incorporated. | ||
5 | * Copyright (c) 2009 Greg Kroah-Hartman <gregkh@suse.de> | ||
6 | * Copyright (c) 2009 Novell Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License version | ||
10 | * 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/tty.h> | ||
15 | #include <linux/tty_flip.h> | ||
16 | #include <linux/usb.h> | ||
17 | #include <linux/usb/serial.h> | ||
18 | |||
19 | #define DRIVER_AUTHOR "Qualcomm Inc" | ||
20 | #define DRIVER_DESC "Qualcomm USB Serial driver" | ||
21 | |||
22 | static int debug; | ||
23 | |||
24 | static struct usb_device_id id_table[] = { | ||
25 | {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ | ||
26 | {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ | ||
27 | {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ | ||
28 | {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */ | ||
29 | { } /* Terminating entry */ | ||
30 | }; | ||
31 | MODULE_DEVICE_TABLE(usb, id_table); | ||
32 | |||
33 | static struct usb_driver qcdriver = { | ||
34 | .name = "qcserial", | ||
35 | .probe = usb_serial_probe, | ||
36 | .disconnect = usb_serial_disconnect, | ||
37 | .id_table = id_table, | ||
38 | .suspend = usb_serial_suspend, | ||
39 | .resume = usb_serial_resume, | ||
40 | .supports_autosuspend = true, | ||
41 | }; | ||
42 | |||
43 | static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | ||
44 | { | ||
45 | int retval = -ENODEV; | ||
46 | __u8 nintf; | ||
47 | __u8 ifnum; | ||
48 | |||
49 | dbg("%s", __func__); | ||
50 | |||
51 | nintf = serial->dev->actconfig->desc.bNumInterfaces; | ||
52 | dbg("Num Interfaces = %d", nintf); | ||
53 | ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber; | ||
54 | dbg("This Interface = %d", ifnum); | ||
55 | |||
56 | switch (nintf) { | ||
57 | case 1: | ||
58 | /* QDL mode */ | ||
59 | if (serial->interface->num_altsetting == 2) { | ||
60 | struct usb_host_interface *intf; | ||
61 | |||
62 | intf = &serial->interface->altsetting[1]; | ||
63 | if (intf->desc.bNumEndpoints == 2) { | ||
64 | if (usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) && | ||
65 | usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { | ||
66 | dbg("QDL port found"); | ||
67 | retval = usb_set_interface(serial->dev, ifnum, 1); | ||
68 | if (retval < 0) { | ||
69 | dev_err(&serial->dev->dev, | ||
70 | "Could not set interface, error %d\n", | ||
71 | retval); | ||
72 | retval = -ENODEV; | ||
73 | } | ||
74 | return retval; | ||
75 | } | ||
76 | } | ||
77 | } | ||
78 | break; | ||
79 | |||
80 | case 4: | ||
81 | /* Composite mode */ | ||
82 | if (ifnum == 2) { | ||
83 | dbg("Modem port found"); | ||
84 | retval = usb_set_interface(serial->dev, ifnum, 0); | ||
85 | if (retval < 0) { | ||
86 | dev_err(&serial->dev->dev, | ||
87 | "Could not set interface, error %d\n", | ||
88 | retval); | ||
89 | retval = -ENODEV; | ||
90 | } | ||
91 | return retval; | ||
92 | } | ||
93 | break; | ||
94 | |||
95 | default: | ||
96 | dev_err(&serial->dev->dev, | ||
97 | "unknown number of interfaces: %d\n", nintf); | ||
98 | return -ENODEV; | ||
99 | } | ||
100 | |||
101 | return retval; | ||
102 | } | ||
103 | |||
104 | static struct usb_serial_driver qcdevice = { | ||
105 | .driver = { | ||
106 | .owner = THIS_MODULE, | ||
107 | .name = "qcserial", | ||
108 | }, | ||
109 | .description = "Qualcomm USB modem", | ||
110 | .id_table = id_table, | ||
111 | .usb_driver = &qcdriver, | ||
112 | .num_ports = 1, | ||
113 | .probe = qcprobe, | ||
114 | }; | ||
115 | |||
116 | static int __init qcinit(void) | ||
117 | { | ||
118 | int retval; | ||
119 | |||
120 | retval = usb_serial_register(&qcdevice); | ||
121 | if (retval) | ||
122 | return retval; | ||
123 | |||
124 | retval = usb_register(&qcdriver); | ||
125 | if (retval) { | ||
126 | usb_serial_deregister(&qcdevice); | ||
127 | return retval; | ||
128 | } | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static void __exit qcexit(void) | ||
134 | { | ||
135 | usb_deregister(&qcdriver); | ||
136 | usb_serial_deregister(&qcdevice); | ||
137 | } | ||
138 | |||
139 | module_init(qcinit); | ||
140 | module_exit(qcexit); | ||
141 | |||
142 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
143 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
144 | MODULE_LICENSE("GPL v2"); | ||
145 | |||
146 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
147 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c new file mode 100644 index 00000000000..8b3cbc87adc --- /dev/null +++ b/drivers/usb/serial/symbolserial.c | |||
@@ -0,0 +1,399 @@ | |||
1 | /* | ||
2 | * Symbol USB barcode to serial driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Greg Kroah-Hartman <gregkh@suse.de> | ||
5 | * Copyright (C) 2009 Novell Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License version | ||
9 | * 2 as published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/tty.h> | ||
15 | #include <linux/tty_driver.h> | ||
16 | #include <linux/tty_flip.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/usb.h> | ||
19 | #include <linux/usb/serial.h> | ||
20 | #include <linux/uaccess.h> | ||
21 | |||
22 | static int debug; | ||
23 | |||
24 | static struct usb_device_id id_table[] = { | ||
25 | { USB_DEVICE(0x05e0, 0x0600) }, | ||
26 | { }, | ||
27 | }; | ||
28 | MODULE_DEVICE_TABLE(usb, id_table); | ||
29 | |||
30 | /* This structure holds all of the individual device information */ | ||
31 | struct symbol_private { | ||
32 | struct usb_device *udev; | ||
33 | struct usb_serial *serial; | ||
34 | struct usb_serial_port *port; | ||
35 | unsigned char *int_buffer; | ||
36 | struct urb *int_urb; | ||
37 | int buffer_size; | ||
38 | u8 bInterval; | ||
39 | u8 int_address; | ||
40 | spinlock_t lock; /* protects the following flags */ | ||
41 | bool throttled; | ||
42 | bool actually_throttled; | ||
43 | bool rts; | ||
44 | }; | ||
45 | |||
46 | static void symbol_int_callback(struct urb *urb) | ||
47 | { | ||
48 | struct symbol_private *priv = urb->context; | ||
49 | unsigned char *data = urb->transfer_buffer; | ||
50 | struct usb_serial_port *port = priv->port; | ||
51 | int status = urb->status; | ||
52 | struct tty_struct *tty; | ||
53 | int result; | ||
54 | int available_room = 0; | ||
55 | int data_length; | ||
56 | |||
57 | dbg("%s - port %d", __func__, port->number); | ||
58 | |||
59 | switch (status) { | ||
60 | case 0: | ||
61 | /* success */ | ||
62 | break; | ||
63 | case -ECONNRESET: | ||
64 | case -ENOENT: | ||
65 | case -ESHUTDOWN: | ||
66 | /* this urb is terminated, clean up */ | ||
67 | dbg("%s - urb shutting down with status: %d", | ||
68 | __func__, status); | ||
69 | return; | ||
70 | default: | ||
71 | dbg("%s - nonzero urb status received: %d", | ||
72 | __func__, status); | ||
73 | goto exit; | ||
74 | } | ||
75 | |||
76 | usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, | ||
77 | data); | ||
78 | |||
79 | if (urb->actual_length > 1) { | ||
80 | data_length = urb->actual_length - 1; | ||
81 | |||
82 | /* | ||
83 | * Data from the device comes with a 1 byte header: | ||
84 | * | ||
85 | * <size of data>data... | ||
86 | * This is real data to be sent to the tty layer | ||
87 | * we pretty much just ignore the size and send everything | ||
88 | * else to the tty layer. | ||
89 | */ | ||
90 | tty = tty_port_tty_get(&port->port); | ||
91 | if (tty) { | ||
92 | available_room = tty_buffer_request_room(tty, | ||
93 | data_length); | ||
94 | if (available_room) { | ||
95 | tty_insert_flip_string(tty, &data[1], | ||
96 | available_room); | ||
97 | tty_flip_buffer_push(tty); | ||
98 | } | ||
99 | tty_kref_put(tty); | ||
100 | } | ||
101 | } else { | ||
102 | dev_dbg(&priv->udev->dev, | ||
103 | "Improper ammount of data received from the device, " | ||
104 | "%d bytes", urb->actual_length); | ||
105 | } | ||
106 | |||
107 | exit: | ||
108 | spin_lock(&priv->lock); | ||
109 | |||
110 | /* Continue trying to always read if we should */ | ||
111 | if (!priv->throttled) { | ||
112 | usb_fill_int_urb(priv->int_urb, priv->udev, | ||
113 | usb_rcvintpipe(priv->udev, | ||
114 | priv->int_address), | ||
115 | priv->int_buffer, priv->buffer_size, | ||
116 | symbol_int_callback, priv, priv->bInterval); | ||
117 | result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); | ||
118 | if (result) | ||
119 | dev_err(&port->dev, | ||
120 | "%s - failed resubmitting read urb, error %d\n", | ||
121 | __func__, result); | ||
122 | } else | ||
123 | priv->actually_throttled = true; | ||
124 | spin_unlock(&priv->lock); | ||
125 | } | ||
126 | |||
127 | static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port, | ||
128 | struct file *filp) | ||
129 | { | ||
130 | struct symbol_private *priv = usb_get_serial_data(port->serial); | ||
131 | unsigned long flags; | ||
132 | int result = 0; | ||
133 | |||
134 | dbg("%s - port %d", __func__, port->number); | ||
135 | |||
136 | spin_lock_irqsave(&priv->lock, flags); | ||
137 | priv->throttled = false; | ||
138 | priv->actually_throttled = false; | ||
139 | priv->port = port; | ||
140 | spin_unlock_irqrestore(&priv->lock, flags); | ||
141 | |||
142 | /* | ||
143 | * Force low_latency on so that our tty_push actually forces the data | ||
144 | * through, otherwise it is scheduled, and with high data rates (like | ||
145 | * with OHCI) data can get lost. | ||
146 | */ | ||
147 | if (tty) | ||
148 | tty->low_latency = 1; | ||
149 | |||
150 | /* Start reading from the device */ | ||
151 | usb_fill_int_urb(priv->int_urb, priv->udev, | ||
152 | usb_rcvintpipe(priv->udev, priv->int_address), | ||
153 | priv->int_buffer, priv->buffer_size, | ||
154 | symbol_int_callback, priv, priv->bInterval); | ||
155 | result = usb_submit_urb(priv->int_urb, GFP_KERNEL); | ||
156 | if (result) | ||
157 | dev_err(&port->dev, | ||
158 | "%s - failed resubmitting read urb, error %d\n", | ||
159 | __func__, result); | ||
160 | return result; | ||
161 | } | ||
162 | |||
163 | static void symbol_close(struct tty_struct *tty, struct usb_serial_port *port, | ||
164 | struct file *filp) | ||
165 | { | ||
166 | struct symbol_private *priv = usb_get_serial_data(port->serial); | ||
167 | |||
168 | dbg("%s - port %d", __func__, port->number); | ||
169 | |||
170 | /* shutdown our urbs */ | ||
171 | usb_kill_urb(priv->int_urb); | ||
172 | } | ||
173 | |||
174 | static void symbol_throttle(struct tty_struct *tty) | ||
175 | { | ||
176 | struct usb_serial_port *port = tty->driver_data; | ||
177 | struct symbol_private *priv = usb_get_serial_data(port->serial); | ||
178 | unsigned long flags; | ||
179 | |||
180 | dbg("%s - port %d", __func__, port->number); | ||
181 | spin_lock_irqsave(&priv->lock, flags); | ||
182 | priv->throttled = true; | ||
183 | spin_unlock_irqrestore(&priv->lock, flags); | ||
184 | } | ||
185 | |||
186 | static void symbol_unthrottle(struct tty_struct *tty) | ||
187 | { | ||
188 | struct usb_serial_port *port = tty->driver_data; | ||
189 | struct symbol_private *priv = usb_get_serial_data(port->serial); | ||
190 | unsigned long flags; | ||
191 | int result; | ||
192 | |||
193 | dbg("%s - port %d", __func__, port->number); | ||
194 | |||
195 | spin_lock_irqsave(&priv->lock, flags); | ||
196 | priv->throttled = false; | ||
197 | priv->actually_throttled = false; | ||
198 | spin_unlock_irqrestore(&priv->lock, flags); | ||
199 | |||
200 | priv->int_urb->dev = port->serial->dev; | ||
201 | result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); | ||
202 | if (result) | ||
203 | dev_err(&port->dev, | ||
204 | "%s - failed submitting read urb, error %d\n", | ||
205 | __func__, result); | ||
206 | } | ||
207 | |||
208 | static int symbol_ioctl(struct tty_struct *tty, struct file *file, | ||
209 | unsigned int cmd, unsigned long arg) | ||
210 | { | ||
211 | struct usb_serial_port *port = tty->driver_data; | ||
212 | struct device *dev = &port->dev; | ||
213 | |||
214 | /* | ||
215 | * Right now we need to figure out what commands | ||
216 | * most userspace tools want to see for this driver, | ||
217 | * so just log the things. | ||
218 | */ | ||
219 | switch (cmd) { | ||
220 | case TIOCSERGETLSR: | ||
221 | dev_info(dev, "%s: TIOCSERGETLSR\n", __func__); | ||
222 | break; | ||
223 | |||
224 | case TIOCGSERIAL: | ||
225 | dev_info(dev, "%s: TIOCGSERIAL\n", __func__); | ||
226 | break; | ||
227 | |||
228 | case TIOCMIWAIT: | ||
229 | dev_info(dev, "%s: TIOCMIWAIT\n", __func__); | ||
230 | break; | ||
231 | |||
232 | case TIOCGICOUNT: | ||
233 | dev_info(dev, "%s: TIOCGICOUNT\n", __func__); | ||
234 | break; | ||
235 | default: | ||
236 | dev_info(dev, "%s: unknown (%d)\n", __func__, cmd); | ||
237 | } | ||
238 | return -ENOIOCTLCMD; | ||
239 | } | ||
240 | |||
241 | static int symbol_tiocmget(struct tty_struct *tty, struct file *file) | ||
242 | { | ||
243 | struct usb_serial_port *port = tty->driver_data; | ||
244 | struct device *dev = &port->dev; | ||
245 | |||
246 | /* TODO */ | ||
247 | /* probably just need to shadow whatever was sent to us here */ | ||
248 | dev_info(dev, "%s\n", __func__); | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static int symbol_tiocmset(struct tty_struct *tty, struct file *file, | ||
253 | unsigned int set, unsigned int clear) | ||
254 | { | ||
255 | struct usb_serial_port *port = tty->driver_data; | ||
256 | struct device *dev = &port->dev; | ||
257 | |||
258 | /* TODO */ | ||
259 | /* probably just need to shadow whatever was sent to us here */ | ||
260 | dev_info(dev, "%s\n", __func__); | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static int symbol_startup(struct usb_serial *serial) | ||
265 | { | ||
266 | struct symbol_private *priv; | ||
267 | struct usb_host_interface *intf; | ||
268 | int i; | ||
269 | int retval = -ENOMEM; | ||
270 | bool int_in_found = false; | ||
271 | |||
272 | /* create our private serial structure */ | ||
273 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
274 | if (priv == NULL) { | ||
275 | dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__); | ||
276 | return -ENOMEM; | ||
277 | } | ||
278 | spin_lock_init(&priv->lock); | ||
279 | priv->serial = serial; | ||
280 | priv->port = serial->port[0]; | ||
281 | priv->udev = serial->dev; | ||
282 | |||
283 | /* find our interrupt endpoint */ | ||
284 | intf = serial->interface->altsetting; | ||
285 | for (i = 0; i < intf->desc.bNumEndpoints; ++i) { | ||
286 | struct usb_endpoint_descriptor *endpoint; | ||
287 | |||
288 | endpoint = &intf->endpoint[i].desc; | ||
289 | if (!usb_endpoint_is_int_in(endpoint)) | ||
290 | continue; | ||
291 | |||
292 | priv->int_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
293 | if (!priv->int_urb) { | ||
294 | dev_err(&priv->udev->dev, "out of memory\n"); | ||
295 | goto error; | ||
296 | } | ||
297 | |||
298 | priv->buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2; | ||
299 | priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL); | ||
300 | if (!priv->int_buffer) { | ||
301 | dev_err(&priv->udev->dev, "out of memory\n"); | ||
302 | goto error; | ||
303 | } | ||
304 | |||
305 | priv->int_address = endpoint->bEndpointAddress; | ||
306 | priv->bInterval = endpoint->bInterval; | ||
307 | |||
308 | /* set up our int urb */ | ||
309 | usb_fill_int_urb(priv->int_urb, priv->udev, | ||
310 | usb_rcvintpipe(priv->udev, | ||
311 | endpoint->bEndpointAddress), | ||
312 | priv->int_buffer, priv->buffer_size, | ||
313 | symbol_int_callback, priv, priv->bInterval); | ||
314 | |||
315 | int_in_found = true; | ||
316 | break; | ||
317 | } | ||
318 | |||
319 | if (!int_in_found) { | ||
320 | dev_err(&priv->udev->dev, | ||
321 | "Error - the proper endpoints were not found!\n"); | ||
322 | goto error; | ||
323 | } | ||
324 | |||
325 | usb_set_serial_data(serial, priv); | ||
326 | return 0; | ||
327 | |||
328 | error: | ||
329 | usb_free_urb(priv->int_urb); | ||
330 | kfree(priv->int_buffer); | ||
331 | kfree(priv); | ||
332 | return retval; | ||
333 | } | ||
334 | |||
335 | static void symbol_shutdown(struct usb_serial *serial) | ||
336 | { | ||
337 | struct symbol_private *priv = usb_get_serial_data(serial); | ||
338 | |||
339 | dbg("%s", __func__); | ||
340 | |||
341 | usb_kill_urb(priv->int_urb); | ||
342 | usb_free_urb(priv->int_urb); | ||
343 | kfree(priv->int_buffer); | ||
344 | kfree(priv); | ||
345 | usb_set_serial_data(serial, NULL); | ||
346 | } | ||
347 | |||
348 | static struct usb_driver symbol_driver = { | ||
349 | .name = "symbol", | ||
350 | .probe = usb_serial_probe, | ||
351 | .disconnect = usb_serial_disconnect, | ||
352 | .id_table = id_table, | ||
353 | .no_dynamic_id = 1, | ||
354 | }; | ||
355 | |||
356 | static struct usb_serial_driver symbol_device = { | ||
357 | .driver = { | ||
358 | .owner = THIS_MODULE, | ||
359 | .name = "symbol", | ||
360 | }, | ||
361 | .id_table = id_table, | ||
362 | .usb_driver = &symbol_driver, | ||
363 | .num_ports = 1, | ||
364 | .attach = symbol_startup, | ||
365 | .open = symbol_open, | ||
366 | .close = symbol_close, | ||
367 | .shutdown = symbol_shutdown, | ||
368 | .throttle = symbol_throttle, | ||
369 | .unthrottle = symbol_unthrottle, | ||
370 | .ioctl = symbol_ioctl, | ||
371 | .tiocmget = symbol_tiocmget, | ||
372 | .tiocmset = symbol_tiocmset, | ||
373 | }; | ||
374 | |||
375 | static int __init symbol_init(void) | ||
376 | { | ||
377 | int retval; | ||
378 | |||
379 | retval = usb_serial_register(&symbol_device); | ||
380 | if (retval) | ||
381 | return retval; | ||
382 | retval = usb_register(&symbol_driver); | ||
383 | if (retval) | ||
384 | usb_serial_deregister(&symbol_device); | ||
385 | return retval; | ||
386 | } | ||
387 | |||
388 | static void __exit symbol_exit(void) | ||
389 | { | ||
390 | usb_deregister(&symbol_driver); | ||
391 | usb_serial_deregister(&symbol_device); | ||
392 | } | ||
393 | |||
394 | module_init(symbol_init); | ||
395 | module_exit(symbol_exit); | ||
396 | MODULE_LICENSE("GPL"); | ||
397 | |||
398 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
399 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index cfcfd5ab06c..742a5bc44be 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -204,6 +204,11 @@ static int serial_open (struct tty_struct *tty, struct file *filp) | |||
204 | goto bailout_kref_put; | 204 | goto bailout_kref_put; |
205 | } | 205 | } |
206 | 206 | ||
207 | if (port->serial->disconnected) { | ||
208 | retval = -ENODEV; | ||
209 | goto bailout_kref_put; | ||
210 | } | ||
211 | |||
207 | if (mutex_lock_interruptible(&port->mutex)) { | 212 | if (mutex_lock_interruptible(&port->mutex)) { |
208 | retval = -ERESTARTSYS; | 213 | retval = -ERESTARTSYS; |
209 | goto bailout_kref_put; | 214 | goto bailout_kref_put; |
@@ -1067,6 +1072,8 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) | |||
1067 | struct usb_serial_port *port; | 1072 | struct usb_serial_port *port; |
1068 | int i, r = 0; | 1073 | int i, r = 0; |
1069 | 1074 | ||
1075 | serial->suspending = 1; | ||
1076 | |||
1070 | for (i = 0; i < serial->num_ports; ++i) { | 1077 | for (i = 0; i < serial->num_ports; ++i) { |
1071 | port = serial->port[i]; | 1078 | port = serial->port[i]; |
1072 | if (port) | 1079 | if (port) |
@@ -1083,10 +1090,15 @@ EXPORT_SYMBOL(usb_serial_suspend); | |||
1083 | int usb_serial_resume(struct usb_interface *intf) | 1090 | int usb_serial_resume(struct usb_interface *intf) |
1084 | { | 1091 | { |
1085 | struct usb_serial *serial = usb_get_intfdata(intf); | 1092 | struct usb_serial *serial = usb_get_intfdata(intf); |
1093 | int rv; | ||
1086 | 1094 | ||
1095 | serial->suspending = 0; | ||
1087 | if (serial->type->resume) | 1096 | if (serial->type->resume) |
1088 | return serial->type->resume(serial); | 1097 | rv = serial->type->resume(serial); |
1089 | return 0; | 1098 | else |
1099 | rv = usb_serial_generic_resume(serial); | ||
1100 | |||
1101 | return rv; | ||
1090 | } | 1102 | } |
1091 | EXPORT_SYMBOL(usb_serial_resume); | 1103 | EXPORT_SYMBOL(usb_serial_resume); |
1092 | 1104 | ||
@@ -1222,7 +1234,6 @@ static void fixup_generic(struct usb_serial_driver *device) | |||
1222 | set_to_generic_if_null(device, read_bulk_callback); | 1234 | set_to_generic_if_null(device, read_bulk_callback); |
1223 | set_to_generic_if_null(device, write_bulk_callback); | 1235 | set_to_generic_if_null(device, write_bulk_callback); |
1224 | set_to_generic_if_null(device, shutdown); | 1236 | set_to_generic_if_null(device, shutdown); |
1225 | set_to_generic_if_null(device, resume); | ||
1226 | } | 1237 | } |
1227 | 1238 | ||
1228 | int usb_serial_register(struct usb_serial_driver *driver) | 1239 | int usb_serial_register(struct usb_serial_driver *driver) |
@@ -1230,6 +1241,9 @@ int usb_serial_register(struct usb_serial_driver *driver) | |||
1230 | /* must be called with BKL held */ | 1241 | /* must be called with BKL held */ |
1231 | int retval; | 1242 | int retval; |
1232 | 1243 | ||
1244 | if (usb_disabled()) | ||
1245 | return -ENODEV; | ||
1246 | |||
1233 | fixup_generic(driver); | 1247 | fixup_generic(driver); |
1234 | 1248 | ||
1235 | if (!driver->description) | 1249 | if (!driver->description) |