diff options
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/airprime.c | 35 | ||||
-rw-r--r-- | drivers/usb/serial/cp2101.c | 1 | ||||
-rw-r--r-- | drivers/usb/serial/generic.c | 102 | ||||
-rw-r--r-- | drivers/usb/serial/option.c | 4 | ||||
-rw-r--r-- | drivers/usb/serial/pl2303.c | 1 | ||||
-rw-r--r-- | drivers/usb/serial/pl2303.h | 5 |
6 files changed, 99 insertions, 49 deletions
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 0af42e32fa0a..18816bf96a4d 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c | |||
@@ -58,11 +58,6 @@ static void airprime_read_bulk_callback(struct urb *urb) | |||
58 | if (urb->status) { | 58 | if (urb->status) { |
59 | dbg("%s - nonzero read bulk status received: %d", | 59 | dbg("%s - nonzero read bulk status received: %d", |
60 | __FUNCTION__, urb->status); | 60 | __FUNCTION__, urb->status); |
61 | /* something happened, so free up the memory for this urb */ | ||
62 | if (urb->transfer_buffer) { | ||
63 | kfree (urb->transfer_buffer); | ||
64 | urb->transfer_buffer = NULL; | ||
65 | } | ||
66 | return; | 61 | return; |
67 | } | 62 | } |
68 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | 63 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); |
@@ -146,6 +141,8 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) | |||
146 | airprime_read_bulk_callback, port); | 141 | airprime_read_bulk_callback, port); |
147 | result = usb_submit_urb(urb, GFP_KERNEL); | 142 | result = usb_submit_urb(urb, GFP_KERNEL); |
148 | if (result) { | 143 | if (result) { |
144 | usb_free_urb(urb); | ||
145 | kfree(buffer); | ||
149 | dev_err(&port->dev, | 146 | dev_err(&port->dev, |
150 | "%s - failed submitting read urb %d for port %d, error %d\n", | 147 | "%s - failed submitting read urb %d for port %d, error %d\n", |
151 | __FUNCTION__, i, port->number, result); | 148 | __FUNCTION__, i, port->number, result); |
@@ -160,27 +157,12 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) | |||
160 | /* some error happened, cancel any submitted urbs and clean up anything that | 157 | /* some error happened, cancel any submitted urbs and clean up anything that |
161 | got allocated successfully */ | 158 | got allocated successfully */ |
162 | 159 | ||
163 | for ( ; i >= 0; --i) { | 160 | while (i-- != 0) { |
164 | urb = priv->read_urbp[i]; | 161 | urb = priv->read_urbp[i]; |
165 | if (urb) { | 162 | buffer = urb->transfer_buffer; |
166 | /* This urb was submitted successfully. So we have to | 163 | usb_kill_urb (urb); |
167 | cancel it. | 164 | usb_free_urb (urb); |
168 | Unlinking the urb will invoke read_bulk_callback() | 165 | kfree (buffer); |
169 | with an error status, so its transfer buffer will | ||
170 | be freed there */ | ||
171 | if (usb_unlink_urb (urb) != -EINPROGRESS) { | ||
172 | /* comments in drivers/usb/core/urb.c say this | ||
173 | can only happen if the urb was never submitted, | ||
174 | or has completed already. | ||
175 | Either way we may have to free the transfer | ||
176 | buffer here. */ | ||
177 | if (urb->transfer_buffer) { | ||
178 | kfree (urb->transfer_buffer); | ||
179 | urb->transfer_buffer = NULL; | ||
180 | } | ||
181 | } | ||
182 | usb_free_urb (urb); | ||
183 | } | ||
184 | } | 166 | } |
185 | 167 | ||
186 | out: | 168 | out: |
@@ -194,10 +176,9 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp) | |||
194 | 176 | ||
195 | dbg("%s - port %d", __FUNCTION__, port->number); | 177 | dbg("%s - port %d", __FUNCTION__, port->number); |
196 | 178 | ||
197 | /* killing the urb will invoke read_bulk_callback() with an error status, | ||
198 | so the transfer buffer will be freed there */ | ||
199 | for (i = 0; i < NUM_READ_URBS; ++i) { | 179 | for (i = 0; i < NUM_READ_URBS; ++i) { |
200 | usb_kill_urb (priv->read_urbp[i]); | 180 | usb_kill_urb (priv->read_urbp[i]); |
181 | kfree (priv->read_urbp[i]->transfer_buffer); | ||
201 | usb_free_urb (priv->read_urbp[i]); | 182 | usb_free_urb (priv->read_urbp[i]); |
202 | } | 183 | } |
203 | 184 | ||
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 3ec24870bca9..db623e754899 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c | |||
@@ -69,6 +69,7 @@ static struct usb_device_id id_table [] = { | |||
69 | { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ | 69 | { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ |
70 | { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ | 70 | { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ |
71 | { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ | 71 | { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ |
72 | { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */ | ||
72 | { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ | 73 | { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ |
73 | { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ | 74 | { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ |
74 | { } /* Terminating Entry */ | 75 | { } /* Terminating Entry */ |
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 601e0648dec6..53baeec8f265 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -66,6 +66,8 @@ struct usb_serial_driver usb_serial_generic_device = { | |||
66 | .num_bulk_out = NUM_DONT_CARE, | 66 | .num_bulk_out = NUM_DONT_CARE, |
67 | .num_ports = 1, | 67 | .num_ports = 1, |
68 | .shutdown = usb_serial_generic_shutdown, | 68 | .shutdown = usb_serial_generic_shutdown, |
69 | .throttle = usb_serial_generic_throttle, | ||
70 | .unthrottle = usb_serial_generic_unthrottle, | ||
69 | }; | 71 | }; |
70 | 72 | ||
71 | static int generic_probe(struct usb_interface *interface, | 73 | static int generic_probe(struct usb_interface *interface, |
@@ -115,6 +117,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) | |||
115 | { | 117 | { |
116 | struct usb_serial *serial = port->serial; | 118 | struct usb_serial *serial = port->serial; |
117 | int result = 0; | 119 | int result = 0; |
120 | unsigned long flags; | ||
118 | 121 | ||
119 | dbg("%s - port %d", __FUNCTION__, port->number); | 122 | dbg("%s - port %d", __FUNCTION__, port->number); |
120 | 123 | ||
@@ -124,7 +127,13 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) | |||
124 | if (port->tty) | 127 | if (port->tty) |
125 | port->tty->low_latency = 1; | 128 | port->tty->low_latency = 1; |
126 | 129 | ||
127 | /* if we have a bulk interrupt, start reading from it */ | 130 | /* clear the throttle flags */ |
131 | spin_lock_irqsave(&port->lock, flags); | ||
132 | port->throttled = 0; | ||
133 | port->throttle_req = 0; | ||
134 | spin_unlock_irqrestore(&port->lock, flags); | ||
135 | |||
136 | /* if we have a bulk endpoint, start reading from it */ | ||
128 | if (serial->num_bulk_in) { | 137 | if (serial->num_bulk_in) { |
129 | /* Start reading from the device */ | 138 | /* Start reading from the device */ |
130 | usb_fill_bulk_urb (port->read_urb, serial->dev, | 139 | usb_fill_bulk_urb (port->read_urb, serial->dev, |
@@ -253,31 +262,22 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) | |||
253 | return (chars); | 262 | return (chars); |
254 | } | 263 | } |
255 | 264 | ||
256 | void usb_serial_generic_read_bulk_callback (struct urb *urb) | 265 | /* Push data to tty layer and resubmit the bulk read URB */ |
266 | static void flush_and_resubmit_read_urb (struct usb_serial_port *port) | ||
257 | { | 267 | { |
258 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | ||
259 | struct usb_serial *serial = port->serial; | 268 | struct usb_serial *serial = port->serial; |
260 | struct tty_struct *tty; | 269 | struct urb *urb = port->read_urb; |
261 | unsigned char *data = urb->transfer_buffer; | 270 | struct tty_struct *tty = port->tty; |
262 | int result; | 271 | int result; |
263 | 272 | ||
264 | dbg("%s - port %d", __FUNCTION__, port->number); | 273 | /* Push data to tty */ |
265 | |||
266 | if (urb->status) { | ||
267 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | ||
268 | return; | ||
269 | } | ||
270 | |||
271 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | ||
272 | |||
273 | tty = port->tty; | ||
274 | if (tty && urb->actual_length) { | 274 | if (tty && urb->actual_length) { |
275 | tty_buffer_request_room(tty, urb->actual_length); | 275 | tty_buffer_request_room(tty, urb->actual_length); |
276 | tty_insert_flip_string(tty, data, urb->actual_length); | 276 | tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length); |
277 | tty_flip_buffer_push(tty); | 277 | tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */ |
278 | } | 278 | } |
279 | 279 | ||
280 | /* Continue trying to always read */ | 280 | /* Continue reading from device */ |
281 | usb_fill_bulk_urb (port->read_urb, serial->dev, | 281 | usb_fill_bulk_urb (port->read_urb, serial->dev, |
282 | usb_rcvbulkpipe (serial->dev, | 282 | usb_rcvbulkpipe (serial->dev, |
283 | port->bulk_in_endpointAddress), | 283 | port->bulk_in_endpointAddress), |
@@ -290,6 +290,40 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb) | |||
290 | if (result) | 290 | if (result) |
291 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); | 291 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); |
292 | } | 292 | } |
293 | |||
294 | void usb_serial_generic_read_bulk_callback (struct urb *urb) | ||
295 | { | ||
296 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | ||
297 | unsigned char *data = urb->transfer_buffer; | ||
298 | int is_throttled; | ||
299 | unsigned long flags; | ||
300 | |||
301 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
302 | |||
303 | if (urb->status) { | ||
304 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | ||
305 | return; | ||
306 | } | ||
307 | |||
308 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | ||
309 | |||
310 | /* Throttle the device if requested by tty */ | ||
311 | if (urb->actual_length) { | ||
312 | spin_lock_irqsave(&port->lock, flags); | ||
313 | is_throttled = port->throttled = port->throttle_req; | ||
314 | spin_unlock_irqrestore(&port->lock, flags); | ||
315 | if (is_throttled) { | ||
316 | /* Let the received data linger in the read URB; | ||
317 | * usb_serial_generic_unthrottle() will pick it | ||
318 | * up later. */ | ||
319 | dbg("%s - throttling device", __FUNCTION__); | ||
320 | return; | ||
321 | } | ||
322 | } | ||
323 | |||
324 | /* Handle data and continue reading from device */ | ||
325 | flush_and_resubmit_read_urb(port); | ||
326 | } | ||
293 | EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); | 327 | EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); |
294 | 328 | ||
295 | void usb_serial_generic_write_bulk_callback (struct urb *urb) | 329 | void usb_serial_generic_write_bulk_callback (struct urb *urb) |
@@ -308,6 +342,38 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb) | |||
308 | } | 342 | } |
309 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); | 343 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); |
310 | 344 | ||
345 | void usb_serial_generic_throttle (struct usb_serial_port *port) | ||
346 | { | ||
347 | unsigned long flags; | ||
348 | |||
349 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
350 | |||
351 | /* Set the throttle request flag. It will be picked up | ||
352 | * by usb_serial_generic_read_bulk_callback(). */ | ||
353 | spin_lock_irqsave(&port->lock, flags); | ||
354 | port->throttle_req = 1; | ||
355 | spin_unlock_irqrestore(&port->lock, flags); | ||
356 | } | ||
357 | |||
358 | void usb_serial_generic_unthrottle (struct usb_serial_port *port) | ||
359 | { | ||
360 | int was_throttled; | ||
361 | unsigned long flags; | ||
362 | |||
363 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
364 | |||
365 | /* Clear the throttle flags */ | ||
366 | spin_lock_irqsave(&port->lock, flags); | ||
367 | was_throttled = port->throttled; | ||
368 | port->throttled = port->throttle_req = 0; | ||
369 | spin_unlock_irqrestore(&port->lock, flags); | ||
370 | |||
371 | if (was_throttled) { | ||
372 | /* Handle pending data and resume reading from device */ | ||
373 | flush_and_resubmit_read_urb(port); | ||
374 | } | ||
375 | } | ||
376 | |||
311 | void usb_serial_generic_shutdown (struct usb_serial *serial) | 377 | void usb_serial_generic_shutdown (struct usb_serial *serial) |
312 | { | 378 | { |
313 | int i; | 379 | int i; |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ced9f32b29d9..9963a8b75840 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -69,7 +69,6 @@ static int option_send_setup(struct usb_serial_port *port); | |||
69 | /* Vendor and product IDs */ | 69 | /* Vendor and product IDs */ |
70 | #define OPTION_VENDOR_ID 0x0AF0 | 70 | #define OPTION_VENDOR_ID 0x0AF0 |
71 | #define HUAWEI_VENDOR_ID 0x12D1 | 71 | #define HUAWEI_VENDOR_ID 0x12D1 |
72 | #define AUDIOVOX_VENDOR_ID 0x0F3D | ||
73 | #define NOVATELWIRELESS_VENDOR_ID 0x1410 | 72 | #define NOVATELWIRELESS_VENDOR_ID 0x1410 |
74 | #define ANYDATA_VENDOR_ID 0x16d5 | 73 | #define ANYDATA_VENDOR_ID 0x16d5 |
75 | 74 | ||
@@ -81,7 +80,6 @@ static int option_send_setup(struct usb_serial_port *port); | |||
81 | #define OPTION_PRODUCT_GTMAX36 0x6701 | 80 | #define OPTION_PRODUCT_GTMAX36 0x6701 |
82 | #define HUAWEI_PRODUCT_E600 0x1001 | 81 | #define HUAWEI_PRODUCT_E600 0x1001 |
83 | #define HUAWEI_PRODUCT_E220 0x1003 | 82 | #define HUAWEI_PRODUCT_E220 0x1003 |
84 | #define AUDIOVOX_PRODUCT_AIRCARD 0x0112 | ||
85 | #define NOVATELWIRELESS_PRODUCT_U740 0x1400 | 83 | #define NOVATELWIRELESS_PRODUCT_U740 0x1400 |
86 | #define ANYDATA_PRODUCT_ID 0x6501 | 84 | #define ANYDATA_PRODUCT_ID 0x6501 |
87 | 85 | ||
@@ -94,7 +92,6 @@ static struct usb_device_id option_ids[] = { | |||
94 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) }, | 92 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) }, |
95 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, | 93 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, |
96 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, | 94 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, |
97 | { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, | ||
98 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, | 95 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, |
99 | { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, | 96 | { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, |
100 | { } /* Terminating entry */ | 97 | { } /* Terminating entry */ |
@@ -109,7 +106,6 @@ static struct usb_device_id option_ids1[] = { | |||
109 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) }, | 106 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) }, |
110 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, | 107 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, |
111 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, | 108 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, |
112 | { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, | ||
113 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, | 109 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, |
114 | { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, | 110 | { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, |
115 | { } /* Terminating entry */ | 111 | { } /* Terminating entry */ |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 6c083d4e2c9b..83dfae93a45d 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -83,6 +83,7 @@ static struct usb_device_id id_table [] = { | |||
83 | { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, | 83 | { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, |
84 | { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, | 84 | { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, |
85 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) }, | 85 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) }, |
86 | { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, | ||
86 | { } /* Terminating entry */ | 87 | { } /* Terminating entry */ |
87 | }; | 88 | }; |
88 | 89 | ||
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 65a5039665e7..f9a71d0c102e 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h | |||
@@ -97,3 +97,8 @@ | |||
97 | /* Huawei E620 UMTS/HSDPA card (ID: 12d1:1001) */ | 97 | /* Huawei E620 UMTS/HSDPA card (ID: 12d1:1001) */ |
98 | #define HUAWEI_VENDOR_ID 0x12d1 | 98 | #define HUAWEI_VENDOR_ID 0x12d1 |
99 | #define HUAWEI_PRODUCT_ID 0x1001 | 99 | #define HUAWEI_PRODUCT_ID 0x1001 |
100 | |||
101 | /* Willcom WS002IN Data Driver (by NetIndex Inc.) */ | ||
102 | #define WS002IN_VENDOR_ID 0x11f6 | ||
103 | #define WS002IN_PRODUCT_ID 0x2001 | ||
104 | |||