diff options
Diffstat (limited to 'drivers/usb/serial/generic.c')
-rw-r--r-- | drivers/usb/serial/generic.c | 109 |
1 files changed, 88 insertions, 21 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 601e0648dec6..4f8282ad7720 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -20,13 +20,14 @@ | |||
20 | #include <linux/usb/serial.h> | 20 | #include <linux/usb/serial.h> |
21 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
22 | 22 | ||
23 | static int generic_probe(struct usb_interface *interface, | ||
24 | const struct usb_device_id *id); | ||
25 | |||
26 | 23 | ||
27 | static int debug; | 24 | static int debug; |
28 | 25 | ||
29 | #ifdef CONFIG_USB_SERIAL_GENERIC | 26 | #ifdef CONFIG_USB_SERIAL_GENERIC |
27 | |||
28 | static int generic_probe(struct usb_interface *interface, | ||
29 | const struct usb_device_id *id); | ||
30 | |||
30 | static __u16 vendor = 0x05f9; | 31 | static __u16 vendor = 0x05f9; |
31 | static __u16 product = 0xffff; | 32 | static __u16 product = 0xffff; |
32 | 33 | ||
@@ -66,6 +67,8 @@ struct usb_serial_driver usb_serial_generic_device = { | |||
66 | .num_bulk_out = NUM_DONT_CARE, | 67 | .num_bulk_out = NUM_DONT_CARE, |
67 | .num_ports = 1, | 68 | .num_ports = 1, |
68 | .shutdown = usb_serial_generic_shutdown, | 69 | .shutdown = usb_serial_generic_shutdown, |
70 | .throttle = usb_serial_generic_throttle, | ||
71 | .unthrottle = usb_serial_generic_unthrottle, | ||
69 | }; | 72 | }; |
70 | 73 | ||
71 | static int generic_probe(struct usb_interface *interface, | 74 | static int generic_probe(struct usb_interface *interface, |
@@ -115,6 +118,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) | |||
115 | { | 118 | { |
116 | struct usb_serial *serial = port->serial; | 119 | struct usb_serial *serial = port->serial; |
117 | int result = 0; | 120 | int result = 0; |
121 | unsigned long flags; | ||
118 | 122 | ||
119 | dbg("%s - port %d", __FUNCTION__, port->number); | 123 | dbg("%s - port %d", __FUNCTION__, port->number); |
120 | 124 | ||
@@ -124,7 +128,13 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp) | |||
124 | if (port->tty) | 128 | if (port->tty) |
125 | port->tty->low_latency = 1; | 129 | port->tty->low_latency = 1; |
126 | 130 | ||
127 | /* if we have a bulk interrupt, start reading from it */ | 131 | /* clear the throttle flags */ |
132 | spin_lock_irqsave(&port->lock, flags); | ||
133 | port->throttled = 0; | ||
134 | port->throttle_req = 0; | ||
135 | spin_unlock_irqrestore(&port->lock, flags); | ||
136 | |||
137 | /* if we have a bulk endpoint, start reading from it */ | ||
128 | if (serial->num_bulk_in) { | 138 | if (serial->num_bulk_in) { |
129 | /* Start reading from the device */ | 139 | /* Start reading from the device */ |
130 | usb_fill_bulk_urb (port->read_urb, serial->dev, | 140 | usb_fill_bulk_urb (port->read_urb, serial->dev, |
@@ -253,31 +263,22 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) | |||
253 | return (chars); | 263 | return (chars); |
254 | } | 264 | } |
255 | 265 | ||
256 | void usb_serial_generic_read_bulk_callback (struct urb *urb) | 266 | /* Push data to tty layer and resubmit the bulk read URB */ |
267 | static void flush_and_resubmit_read_urb (struct usb_serial_port *port) | ||
257 | { | 268 | { |
258 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | ||
259 | struct usb_serial *serial = port->serial; | 269 | struct usb_serial *serial = port->serial; |
260 | struct tty_struct *tty; | 270 | struct urb *urb = port->read_urb; |
261 | unsigned char *data = urb->transfer_buffer; | 271 | struct tty_struct *tty = port->tty; |
262 | int result; | 272 | int result; |
263 | 273 | ||
264 | dbg("%s - port %d", __FUNCTION__, port->number); | 274 | /* 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) { | 275 | if (tty && urb->actual_length) { |
275 | tty_buffer_request_room(tty, urb->actual_length); | 276 | tty_buffer_request_room(tty, urb->actual_length); |
276 | tty_insert_flip_string(tty, data, urb->actual_length); | 277 | tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length); |
277 | tty_flip_buffer_push(tty); | 278 | tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */ |
278 | } | 279 | } |
279 | 280 | ||
280 | /* Continue trying to always read */ | 281 | /* Continue reading from device */ |
281 | usb_fill_bulk_urb (port->read_urb, serial->dev, | 282 | usb_fill_bulk_urb (port->read_urb, serial->dev, |
282 | usb_rcvbulkpipe (serial->dev, | 283 | usb_rcvbulkpipe (serial->dev, |
283 | port->bulk_in_endpointAddress), | 284 | port->bulk_in_endpointAddress), |
@@ -290,6 +291,40 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb) | |||
290 | if (result) | 291 | if (result) |
291 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); | 292 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); |
292 | } | 293 | } |
294 | |||
295 | void usb_serial_generic_read_bulk_callback (struct urb *urb) | ||
296 | { | ||
297 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | ||
298 | unsigned char *data = urb->transfer_buffer; | ||
299 | int is_throttled; | ||
300 | unsigned long flags; | ||
301 | |||
302 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
303 | |||
304 | if (urb->status) { | ||
305 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | ||
306 | return; | ||
307 | } | ||
308 | |||
309 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | ||
310 | |||
311 | /* Throttle the device if requested by tty */ | ||
312 | if (urb->actual_length) { | ||
313 | spin_lock_irqsave(&port->lock, flags); | ||
314 | is_throttled = port->throttled = port->throttle_req; | ||
315 | spin_unlock_irqrestore(&port->lock, flags); | ||
316 | if (is_throttled) { | ||
317 | /* Let the received data linger in the read URB; | ||
318 | * usb_serial_generic_unthrottle() will pick it | ||
319 | * up later. */ | ||
320 | dbg("%s - throttling device", __FUNCTION__); | ||
321 | return; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | /* Handle data and continue reading from device */ | ||
326 | flush_and_resubmit_read_urb(port); | ||
327 | } | ||
293 | EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); | 328 | EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); |
294 | 329 | ||
295 | void usb_serial_generic_write_bulk_callback (struct urb *urb) | 330 | void usb_serial_generic_write_bulk_callback (struct urb *urb) |
@@ -308,6 +343,38 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb) | |||
308 | } | 343 | } |
309 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); | 344 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); |
310 | 345 | ||
346 | void usb_serial_generic_throttle (struct usb_serial_port *port) | ||
347 | { | ||
348 | unsigned long flags; | ||
349 | |||
350 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
351 | |||
352 | /* Set the throttle request flag. It will be picked up | ||
353 | * by usb_serial_generic_read_bulk_callback(). */ | ||
354 | spin_lock_irqsave(&port->lock, flags); | ||
355 | port->throttle_req = 1; | ||
356 | spin_unlock_irqrestore(&port->lock, flags); | ||
357 | } | ||
358 | |||
359 | void usb_serial_generic_unthrottle (struct usb_serial_port *port) | ||
360 | { | ||
361 | int was_throttled; | ||
362 | unsigned long flags; | ||
363 | |||
364 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
365 | |||
366 | /* Clear the throttle flags */ | ||
367 | spin_lock_irqsave(&port->lock, flags); | ||
368 | was_throttled = port->throttled; | ||
369 | port->throttled = port->throttle_req = 0; | ||
370 | spin_unlock_irqrestore(&port->lock, flags); | ||
371 | |||
372 | if (was_throttled) { | ||
373 | /* Handle pending data and resume reading from device */ | ||
374 | flush_and_resubmit_read_urb(port); | ||
375 | } | ||
376 | } | ||
377 | |||
311 | void usb_serial_generic_shutdown (struct usb_serial *serial) | 378 | void usb_serial_generic_shutdown (struct usb_serial *serial) |
312 | { | 379 | { |
313 | int i; | 380 | int i; |