diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/visor.c | 342 |
1 files changed, 13 insertions, 329 deletions
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index fb7fc4068fb6..17fd8822d07f 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c | |||
@@ -38,17 +38,9 @@ | |||
38 | /* function prototypes for a handspring visor */ | 38 | /* function prototypes for a handspring visor */ |
39 | static int visor_open(struct tty_struct *tty, struct usb_serial_port *port); | 39 | static int visor_open(struct tty_struct *tty, struct usb_serial_port *port); |
40 | static void visor_close(struct usb_serial_port *port); | 40 | static void visor_close(struct usb_serial_port *port); |
41 | static int visor_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
42 | const unsigned char *buf, int count); | ||
43 | static int visor_write_room(struct tty_struct *tty); | ||
44 | static void visor_throttle(struct tty_struct *tty); | ||
45 | static void visor_unthrottle(struct tty_struct *tty); | ||
46 | static int visor_probe(struct usb_serial *serial, | 41 | static int visor_probe(struct usb_serial *serial, |
47 | const struct usb_device_id *id); | 42 | const struct usb_device_id *id); |
48 | static int visor_calc_num_ports(struct usb_serial *serial); | 43 | static int visor_calc_num_ports(struct usb_serial *serial); |
49 | static void visor_release(struct usb_serial *serial); | ||
50 | static void visor_write_bulk_callback(struct urb *urb); | ||
51 | static void visor_read_bulk_callback(struct urb *urb); | ||
52 | static void visor_read_int_callback(struct urb *urb); | 44 | static void visor_read_int_callback(struct urb *urb); |
53 | static int clie_3_5_startup(struct usb_serial *serial); | 45 | static int clie_3_5_startup(struct usb_serial *serial); |
54 | static int treo_attach(struct usb_serial *serial); | 46 | static int treo_attach(struct usb_serial *serial); |
@@ -196,16 +188,11 @@ static struct usb_serial_driver handspring_device = { | |||
196 | .num_ports = 2, | 188 | .num_ports = 2, |
197 | .open = visor_open, | 189 | .open = visor_open, |
198 | .close = visor_close, | 190 | .close = visor_close, |
199 | .throttle = visor_throttle, | 191 | .throttle = usb_serial_generic_throttle, |
200 | .unthrottle = visor_unthrottle, | 192 | .unthrottle = usb_serial_generic_unthrottle, |
201 | .attach = treo_attach, | 193 | .attach = treo_attach, |
202 | .probe = visor_probe, | 194 | .probe = visor_probe, |
203 | .calc_num_ports = visor_calc_num_ports, | 195 | .calc_num_ports = visor_calc_num_ports, |
204 | .release = visor_release, | ||
205 | .write = visor_write, | ||
206 | .write_room = visor_write_room, | ||
207 | .write_bulk_callback = visor_write_bulk_callback, | ||
208 | .read_bulk_callback = visor_read_bulk_callback, | ||
209 | .read_int_callback = visor_read_int_callback, | 196 | .read_int_callback = visor_read_int_callback, |
210 | }; | 197 | }; |
211 | 198 | ||
@@ -221,16 +208,11 @@ static struct usb_serial_driver clie_5_device = { | |||
221 | .num_ports = 2, | 208 | .num_ports = 2, |
222 | .open = visor_open, | 209 | .open = visor_open, |
223 | .close = visor_close, | 210 | .close = visor_close, |
224 | .throttle = visor_throttle, | 211 | .throttle = usb_serial_generic_throttle, |
225 | .unthrottle = visor_unthrottle, | 212 | .unthrottle = usb_serial_generic_unthrottle, |
226 | .attach = clie_5_attach, | 213 | .attach = clie_5_attach, |
227 | .probe = visor_probe, | 214 | .probe = visor_probe, |
228 | .calc_num_ports = visor_calc_num_ports, | 215 | .calc_num_ports = visor_calc_num_ports, |
229 | .release = visor_release, | ||
230 | .write = visor_write, | ||
231 | .write_room = visor_write_room, | ||
232 | .write_bulk_callback = visor_write_bulk_callback, | ||
233 | .read_bulk_callback = visor_read_bulk_callback, | ||
234 | .read_int_callback = visor_read_int_callback, | 216 | .read_int_callback = visor_read_int_callback, |
235 | }; | 217 | }; |
236 | 218 | ||
@@ -246,38 +228,16 @@ static struct usb_serial_driver clie_3_5_device = { | |||
246 | .num_ports = 1, | 228 | .num_ports = 1, |
247 | .open = visor_open, | 229 | .open = visor_open, |
248 | .close = visor_close, | 230 | .close = visor_close, |
249 | .throttle = visor_throttle, | 231 | .throttle = usb_serial_generic_throttle, |
250 | .unthrottle = visor_unthrottle, | 232 | .unthrottle = usb_serial_generic_unthrottle, |
251 | .attach = clie_3_5_startup, | 233 | .attach = clie_3_5_startup, |
252 | .release = visor_release, | ||
253 | .write = visor_write, | ||
254 | .write_room = visor_write_room, | ||
255 | .write_bulk_callback = visor_write_bulk_callback, | ||
256 | .read_bulk_callback = visor_read_bulk_callback, | ||
257 | }; | 234 | }; |
258 | 235 | ||
259 | struct visor_private { | ||
260 | spinlock_t lock; | ||
261 | int bytes_in; | ||
262 | int bytes_out; | ||
263 | int outstanding_urbs; | ||
264 | unsigned char throttled; | ||
265 | unsigned char actually_throttled; | ||
266 | }; | ||
267 | |||
268 | /* number of outstanding urbs to prevent userspace DoS from happening */ | ||
269 | #define URB_UPPER_LIMIT 42 | ||
270 | |||
271 | static int stats; | ||
272 | |||
273 | /****************************************************************************** | 236 | /****************************************************************************** |
274 | * Handspring Visor specific driver functions | 237 | * Handspring Visor specific driver functions |
275 | ******************************************************************************/ | 238 | ******************************************************************************/ |
276 | static int visor_open(struct tty_struct *tty, struct usb_serial_port *port) | 239 | static int visor_open(struct tty_struct *tty, struct usb_serial_port *port) |
277 | { | 240 | { |
278 | struct usb_serial *serial = port->serial; | ||
279 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
280 | unsigned long flags; | ||
281 | int result = 0; | 241 | int result = 0; |
282 | 242 | ||
283 | dbg("%s - port %d", __func__, port->number); | 243 | dbg("%s - port %d", __func__, port->number); |
@@ -288,26 +248,10 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
288 | return -ENODEV; | 248 | return -ENODEV; |
289 | } | 249 | } |
290 | 250 | ||
291 | spin_lock_irqsave(&priv->lock, flags); | ||
292 | priv->bytes_in = 0; | ||
293 | priv->bytes_out = 0; | ||
294 | priv->throttled = 0; | ||
295 | spin_unlock_irqrestore(&priv->lock, flags); | ||
296 | |||
297 | /* Start reading from the device */ | 251 | /* Start reading from the device */ |
298 | usb_fill_bulk_urb(port->read_urb, serial->dev, | 252 | result = usb_serial_generic_open(tty, port); |
299 | usb_rcvbulkpipe(serial->dev, | 253 | if (result) |
300 | port->bulk_in_endpointAddress), | ||
301 | port->read_urb->transfer_buffer, | ||
302 | port->read_urb->transfer_buffer_length, | ||
303 | visor_read_bulk_callback, port); | ||
304 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | ||
305 | if (result) { | ||
306 | dev_err(&port->dev, | ||
307 | "%s - failed submitting read urb, error %d\n", | ||
308 | __func__, result); | ||
309 | goto exit; | 254 | goto exit; |
310 | } | ||
311 | 255 | ||
312 | if (port->interrupt_in_urb) { | 256 | if (port->interrupt_in_urb) { |
313 | dbg("%s - adding interrupt input for treo", __func__); | 257 | dbg("%s - adding interrupt input for treo", __func__); |
@@ -324,13 +268,12 @@ exit: | |||
324 | 268 | ||
325 | static void visor_close(struct usb_serial_port *port) | 269 | static void visor_close(struct usb_serial_port *port) |
326 | { | 270 | { |
327 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
328 | unsigned char *transfer_buffer; | 271 | unsigned char *transfer_buffer; |
329 | 272 | ||
330 | dbg("%s - port %d", __func__, port->number); | 273 | dbg("%s - port %d", __func__, port->number); |
331 | 274 | ||
332 | /* shutdown our urbs */ | 275 | /* shutdown our urbs */ |
333 | usb_kill_urb(port->read_urb); | 276 | usb_serial_generic_close(port); |
334 | usb_kill_urb(port->interrupt_in_urb); | 277 | usb_kill_urb(port->interrupt_in_urb); |
335 | 278 | ||
336 | mutex_lock(&port->serial->disc_mutex); | 279 | mutex_lock(&port->serial->disc_mutex); |
@@ -347,192 +290,6 @@ static void visor_close(struct usb_serial_port *port) | |||
347 | } | 290 | } |
348 | } | 291 | } |
349 | mutex_unlock(&port->serial->disc_mutex); | 292 | mutex_unlock(&port->serial->disc_mutex); |
350 | |||
351 | if (stats) | ||
352 | dev_info(&port->dev, "Bytes In = %d Bytes Out = %d\n", | ||
353 | priv->bytes_in, priv->bytes_out); | ||
354 | } | ||
355 | |||
356 | |||
357 | static int visor_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
358 | const unsigned char *buf, int count) | ||
359 | { | ||
360 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
361 | struct usb_serial *serial = port->serial; | ||
362 | struct urb *urb; | ||
363 | unsigned char *buffer; | ||
364 | unsigned long flags; | ||
365 | int status; | ||
366 | |||
367 | dbg("%s - port %d", __func__, port->number); | ||
368 | |||
369 | spin_lock_irqsave(&priv->lock, flags); | ||
370 | if (priv->outstanding_urbs > URB_UPPER_LIMIT) { | ||
371 | spin_unlock_irqrestore(&priv->lock, flags); | ||
372 | dbg("%s - write limit hit", __func__); | ||
373 | return 0; | ||
374 | } | ||
375 | priv->outstanding_urbs++; | ||
376 | spin_unlock_irqrestore(&priv->lock, flags); | ||
377 | |||
378 | buffer = kmalloc(count, GFP_ATOMIC); | ||
379 | if (!buffer) { | ||
380 | dev_err(&port->dev, "out of memory\n"); | ||
381 | count = -ENOMEM; | ||
382 | goto error_no_buffer; | ||
383 | } | ||
384 | |||
385 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
386 | if (!urb) { | ||
387 | dev_err(&port->dev, "no more free urbs\n"); | ||
388 | count = -ENOMEM; | ||
389 | goto error_no_urb; | ||
390 | } | ||
391 | |||
392 | memcpy(buffer, buf, count); | ||
393 | |||
394 | usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); | ||
395 | |||
396 | usb_fill_bulk_urb(urb, serial->dev, | ||
397 | usb_sndbulkpipe(serial->dev, | ||
398 | port->bulk_out_endpointAddress), | ||
399 | buffer, count, | ||
400 | visor_write_bulk_callback, port); | ||
401 | |||
402 | /* send it down the pipe */ | ||
403 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
404 | if (status) { | ||
405 | dev_err(&port->dev, | ||
406 | "%s - usb_submit_urb(write bulk) failed with status = %d\n", | ||
407 | __func__, status); | ||
408 | count = status; | ||
409 | goto error; | ||
410 | } else { | ||
411 | spin_lock_irqsave(&priv->lock, flags); | ||
412 | priv->bytes_out += count; | ||
413 | spin_unlock_irqrestore(&priv->lock, flags); | ||
414 | } | ||
415 | |||
416 | /* we are done with this urb, so let the host driver | ||
417 | * really free it when it is finished with it */ | ||
418 | usb_free_urb(urb); | ||
419 | |||
420 | return count; | ||
421 | error: | ||
422 | usb_free_urb(urb); | ||
423 | error_no_urb: | ||
424 | kfree(buffer); | ||
425 | error_no_buffer: | ||
426 | spin_lock_irqsave(&priv->lock, flags); | ||
427 | --priv->outstanding_urbs; | ||
428 | spin_unlock_irqrestore(&priv->lock, flags); | ||
429 | return count; | ||
430 | } | ||
431 | |||
432 | |||
433 | static int visor_write_room(struct tty_struct *tty) | ||
434 | { | ||
435 | struct usb_serial_port *port = tty->driver_data; | ||
436 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
437 | unsigned long flags; | ||
438 | |||
439 | dbg("%s - port %d", __func__, port->number); | ||
440 | |||
441 | /* | ||
442 | * We really can take anything the user throws at us | ||
443 | * but let's pick a nice big number to tell the tty | ||
444 | * layer that we have lots of free space, unless we don't. | ||
445 | */ | ||
446 | |||
447 | spin_lock_irqsave(&priv->lock, flags); | ||
448 | if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) { | ||
449 | spin_unlock_irqrestore(&priv->lock, flags); | ||
450 | dbg("%s - write limit hit", __func__); | ||
451 | return 0; | ||
452 | } | ||
453 | spin_unlock_irqrestore(&priv->lock, flags); | ||
454 | |||
455 | return 2048; | ||
456 | } | ||
457 | |||
458 | |||
459 | static void visor_write_bulk_callback(struct urb *urb) | ||
460 | { | ||
461 | struct usb_serial_port *port = urb->context; | ||
462 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
463 | int status = urb->status; | ||
464 | unsigned long flags; | ||
465 | |||
466 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | ||
467 | kfree(urb->transfer_buffer); | ||
468 | |||
469 | dbg("%s - port %d", __func__, port->number); | ||
470 | |||
471 | if (status) | ||
472 | dbg("%s - nonzero write bulk status received: %d", | ||
473 | __func__, status); | ||
474 | |||
475 | spin_lock_irqsave(&priv->lock, flags); | ||
476 | --priv->outstanding_urbs; | ||
477 | spin_unlock_irqrestore(&priv->lock, flags); | ||
478 | |||
479 | usb_serial_port_softint(port); | ||
480 | } | ||
481 | |||
482 | |||
483 | static void visor_read_bulk_callback(struct urb *urb) | ||
484 | { | ||
485 | struct usb_serial_port *port = urb->context; | ||
486 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
487 | unsigned char *data = urb->transfer_buffer; | ||
488 | int status = urb->status; | ||
489 | struct tty_struct *tty; | ||
490 | int result; | ||
491 | int available_room = 0; | ||
492 | |||
493 | dbg("%s - port %d", __func__, port->number); | ||
494 | |||
495 | if (status) { | ||
496 | dbg("%s - nonzero read bulk status received: %d", | ||
497 | __func__, status); | ||
498 | return; | ||
499 | } | ||
500 | |||
501 | usb_serial_debug_data(debug, &port->dev, __func__, | ||
502 | urb->actual_length, data); | ||
503 | |||
504 | if (urb->actual_length) { | ||
505 | tty = tty_port_tty_get(&port->port); | ||
506 | if (tty) { | ||
507 | tty_insert_flip_string(tty, data, | ||
508 | urb->actual_length); | ||
509 | tty_flip_buffer_push(tty); | ||
510 | tty_kref_put(tty); | ||
511 | } | ||
512 | spin_lock(&priv->lock); | ||
513 | if (tty) | ||
514 | priv->bytes_in += available_room; | ||
515 | |||
516 | } else { | ||
517 | spin_lock(&priv->lock); | ||
518 | } | ||
519 | |||
520 | /* Continue trying to always read if we should */ | ||
521 | if (!priv->throttled) { | ||
522 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | ||
523 | usb_rcvbulkpipe(port->serial->dev, | ||
524 | port->bulk_in_endpointAddress), | ||
525 | port->read_urb->transfer_buffer, | ||
526 | port->read_urb->transfer_buffer_length, | ||
527 | visor_read_bulk_callback, port); | ||
528 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
529 | if (result) | ||
530 | dev_err(&port->dev, | ||
531 | "%s - failed resubmitting read urb, error %d\n", | ||
532 | __func__, result); | ||
533 | } else | ||
534 | priv->actually_throttled = 1; | ||
535 | spin_unlock(&priv->lock); | ||
536 | } | 293 | } |
537 | 294 | ||
538 | static void visor_read_int_callback(struct urb *urb) | 295 | static void visor_read_int_callback(struct urb *urb) |
@@ -576,41 +333,6 @@ exit: | |||
576 | __func__, result); | 333 | __func__, result); |
577 | } | 334 | } |
578 | 335 | ||
579 | static void visor_throttle(struct tty_struct *tty) | ||
580 | { | ||
581 | struct usb_serial_port *port = tty->driver_data; | ||
582 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
583 | |||
584 | dbg("%s - port %d", __func__, port->number); | ||
585 | spin_lock_irq(&priv->lock); | ||
586 | priv->throttled = 1; | ||
587 | spin_unlock_irq(&priv->lock); | ||
588 | } | ||
589 | |||
590 | |||
591 | static void visor_unthrottle(struct tty_struct *tty) | ||
592 | { | ||
593 | struct usb_serial_port *port = tty->driver_data; | ||
594 | struct visor_private *priv = usb_get_serial_port_data(port); | ||
595 | int result, was_throttled; | ||
596 | |||
597 | dbg("%s - port %d", __func__, port->number); | ||
598 | spin_lock_irq(&priv->lock); | ||
599 | priv->throttled = 0; | ||
600 | was_throttled = priv->actually_throttled; | ||
601 | priv->actually_throttled = 0; | ||
602 | spin_unlock_irq(&priv->lock); | ||
603 | |||
604 | if (was_throttled) { | ||
605 | port->read_urb->dev = port->serial->dev; | ||
606 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | ||
607 | if (result) | ||
608 | dev_err(&port->dev, | ||
609 | "%s - failed submitting read urb, error %d\n", | ||
610 | __func__, result); | ||
611 | } | ||
612 | } | ||
613 | |||
614 | static int palm_os_3_probe(struct usb_serial *serial, | 336 | static int palm_os_3_probe(struct usb_serial *serial, |
615 | const struct usb_device_id *id) | 337 | const struct usb_device_id *id) |
616 | { | 338 | { |
@@ -778,28 +500,6 @@ static int visor_calc_num_ports(struct usb_serial *serial) | |||
778 | return num_ports; | 500 | return num_ports; |
779 | } | 501 | } |
780 | 502 | ||
781 | static int generic_startup(struct usb_serial *serial) | ||
782 | { | ||
783 | struct usb_serial_port **ports = serial->port; | ||
784 | struct visor_private *priv; | ||
785 | int i; | ||
786 | |||
787 | for (i = 0; i < serial->num_ports; ++i) { | ||
788 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
789 | if (!priv) { | ||
790 | while (i-- != 0) { | ||
791 | priv = usb_get_serial_port_data(ports[i]); | ||
792 | usb_set_serial_port_data(ports[i], NULL); | ||
793 | kfree(priv); | ||
794 | } | ||
795 | return -ENOMEM; | ||
796 | } | ||
797 | spin_lock_init(&priv->lock); | ||
798 | usb_set_serial_port_data(ports[i], priv); | ||
799 | } | ||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | static int clie_3_5_startup(struct usb_serial *serial) | 503 | static int clie_3_5_startup(struct usb_serial *serial) |
804 | { | 504 | { |
805 | struct device *dev = &serial->dev->dev; | 505 | struct device *dev = &serial->dev->dev; |
@@ -850,7 +550,7 @@ static int clie_3_5_startup(struct usb_serial *serial) | |||
850 | goto out; | 550 | goto out; |
851 | } | 551 | } |
852 | 552 | ||
853 | result = generic_startup(serial); | 553 | result = 0; |
854 | out: | 554 | out: |
855 | kfree(data); | 555 | kfree(data); |
856 | 556 | ||
@@ -868,7 +568,7 @@ static int treo_attach(struct usb_serial *serial) | |||
868 | (le16_to_cpu(serial->dev->descriptor.idVendor) | 568 | (le16_to_cpu(serial->dev->descriptor.idVendor) |
869 | == KYOCERA_VENDOR_ID)) || | 569 | == KYOCERA_VENDOR_ID)) || |
870 | (serial->num_interrupt_in == 0)) | 570 | (serial->num_interrupt_in == 0)) |
871 | goto generic_startup; | 571 | return 0; |
872 | 572 | ||
873 | dbg("%s", __func__); | 573 | dbg("%s", __func__); |
874 | 574 | ||
@@ -898,8 +598,7 @@ static int treo_attach(struct usb_serial *serial) | |||
898 | COPY_PORT(serial->port[1], swap_port); | 598 | COPY_PORT(serial->port[1], swap_port); |
899 | kfree(swap_port); | 599 | kfree(swap_port); |
900 | 600 | ||
901 | generic_startup: | 601 | return 0; |
902 | return generic_startup(serial); | ||
903 | } | 602 | } |
904 | 603 | ||
905 | static int clie_5_attach(struct usb_serial *serial) | 604 | static int clie_5_attach(struct usb_serial *serial) |
@@ -922,20 +621,7 @@ static int clie_5_attach(struct usb_serial *serial) | |||
922 | serial->port[0]->bulk_out_endpointAddress = | 621 | serial->port[0]->bulk_out_endpointAddress = |
923 | serial->port[1]->bulk_out_endpointAddress; | 622 | serial->port[1]->bulk_out_endpointAddress; |
924 | 623 | ||
925 | return generic_startup(serial); | 624 | return 0; |
926 | } | ||
927 | |||
928 | static void visor_release(struct usb_serial *serial) | ||
929 | { | ||
930 | struct visor_private *priv; | ||
931 | int i; | ||
932 | |||
933 | dbg("%s", __func__); | ||
934 | |||
935 | for (i = 0; i < serial->num_ports; i++) { | ||
936 | priv = usb_get_serial_port_data(serial->port[i]); | ||
937 | kfree(priv); | ||
938 | } | ||
939 | } | 625 | } |
940 | 626 | ||
941 | static int __init visor_init(void) | 627 | static int __init visor_init(void) |
@@ -1019,8 +705,6 @@ MODULE_LICENSE("GPL"); | |||
1019 | 705 | ||
1020 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 706 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
1021 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | 707 | MODULE_PARM_DESC(debug, "Debug enabled or not"); |
1022 | module_param(stats, bool, S_IRUGO | S_IWUSR); | ||
1023 | MODULE_PARM_DESC(stats, "Enables statistics or not"); | ||
1024 | 708 | ||
1025 | module_param(vendor, ushort, 0); | 709 | module_param(vendor, ushort, 0); |
1026 | MODULE_PARM_DESC(vendor, "User specified vendor ID"); | 710 | MODULE_PARM_DESC(vendor, "User specified vendor ID"); |