aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/generic.c')
-rw-r--r--drivers/usb/serial/generic.c144
1 files changed, 101 insertions, 43 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 4c5c23f1cae5..297665fdd16d 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * USB Serial Converter Generic functions 2 * USB Serial Converter Generic functions
3 * 3 *
4 * Copyright (C) 2010 - 2011 Johan Hovold (jhovold@gmail.com) 4 * Copyright (C) 2010 - 2013 Johan Hovold (jhovold@gmail.com)
5 * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) 5 * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
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
@@ -45,8 +45,6 @@ struct usb_serial_driver usb_serial_generic_device = {
45 }, 45 },
46 .id_table = generic_device_ids, 46 .id_table = generic_device_ids,
47 .num_ports = 1, 47 .num_ports = 1,
48 .disconnect = usb_serial_generic_disconnect,
49 .release = usb_serial_generic_release,
50 .throttle = usb_serial_generic_throttle, 48 .throttle = usb_serial_generic_throttle,
51 .unthrottle = usb_serial_generic_unthrottle, 49 .unthrottle = usb_serial_generic_unthrottle,
52 .resume = usb_serial_generic_resume, 50 .resume = usb_serial_generic_resume,
@@ -102,32 +100,23 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port
102} 100}
103EXPORT_SYMBOL_GPL(usb_serial_generic_open); 101EXPORT_SYMBOL_GPL(usb_serial_generic_open);
104 102
105static void generic_cleanup(struct usb_serial_port *port) 103void usb_serial_generic_close(struct usb_serial_port *port)
106{ 104{
107 struct usb_serial *serial = port->serial;
108 unsigned long flags; 105 unsigned long flags;
109 int i; 106 int i;
110 107
111 if (serial->dev) { 108 if (port->bulk_out_size) {
112 /* shutdown any bulk transfers that might be going on */ 109 for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
113 if (port->bulk_out_size) { 110 usb_kill_urb(port->write_urbs[i]);
114 for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
115 usb_kill_urb(port->write_urbs[i]);
116 111
117 spin_lock_irqsave(&port->lock, flags); 112 spin_lock_irqsave(&port->lock, flags);
118 kfifo_reset_out(&port->write_fifo); 113 kfifo_reset_out(&port->write_fifo);
119 spin_unlock_irqrestore(&port->lock, flags); 114 spin_unlock_irqrestore(&port->lock, flags);
120 } 115 }
121 if (port->bulk_in_size) { 116 if (port->bulk_in_size) {
122 for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) 117 for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
123 usb_kill_urb(port->read_urbs[i]); 118 usb_kill_urb(port->read_urbs[i]);
124 }
125 } 119 }
126}
127
128void usb_serial_generic_close(struct usb_serial_port *port)
129{
130 generic_cleanup(port);
131} 120}
132EXPORT_SYMBOL_GPL(usb_serial_generic_close); 121EXPORT_SYMBOL_GPL(usb_serial_generic_close);
133 122
@@ -272,8 +261,7 @@ static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
272 if (!test_and_clear_bit(index, &port->read_urbs_free)) 261 if (!test_and_clear_bit(index, &port->read_urbs_free))
273 return 0; 262 return 0;
274 263
275 dev_dbg(&port->dev, "%s - port %d, urb %d\n", __func__, 264 dev_dbg(&port->dev, "%s - urb %d\n", __func__, index);
276 port->number, index);
277 265
278 res = usb_submit_urb(port->read_urbs[index], mem_flags); 266 res = usb_submit_urb(port->read_urbs[index], mem_flags);
279 if (res) { 267 if (res) {
@@ -347,8 +335,8 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
347 } 335 }
348 set_bit(i, &port->read_urbs_free); 336 set_bit(i, &port->read_urbs_free);
349 337
350 dev_dbg(&port->dev, "%s - port %d, urb %d, len %d\n", 338 dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i,
351 __func__, port->number, i, urb->actual_length); 339 urb->actual_length);
352 340
353 if (urb->status) { 341 if (urb->status) {
354 dev_dbg(&port->dev, "%s - non-zero urb status: %d\n", 342 dev_dbg(&port->dev, "%s - non-zero urb status: %d\n",
@@ -430,6 +418,91 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
430} 418}
431EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle); 419EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle);
432 420
421static bool usb_serial_generic_msr_changed(struct tty_struct *tty,
422 unsigned long arg, struct async_icount *cprev)
423{
424 struct usb_serial_port *port = tty->driver_data;
425 struct async_icount cnow;
426 unsigned long flags;
427 bool ret;
428
429 /*
430 * Use tty-port initialised flag to detect all hangups including the
431 * one generated at USB-device disconnect.
432 *
433 * FIXME: Remove hupping check once tty_port_hangup calls shutdown
434 * (which clears the initialised flag) before wake up.
435 */
436 if (test_bit(TTY_HUPPING, &tty->flags))
437 return true;
438 if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
439 return true;
440
441 spin_lock_irqsave(&port->lock, flags);
442 cnow = port->icount; /* atomic copy*/
443 spin_unlock_irqrestore(&port->lock, flags);
444
445 ret = ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
446 ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
447 ((arg & TIOCM_CD) && (cnow.dcd != cprev->dcd)) ||
448 ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts));
449
450 *cprev = cnow;
451
452 return ret;
453}
454
455int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg)
456{
457 struct usb_serial_port *port = tty->driver_data;
458 struct async_icount cnow;
459 unsigned long flags;
460 int ret;
461
462 spin_lock_irqsave(&port->lock, flags);
463 cnow = port->icount; /* atomic copy */
464 spin_unlock_irqrestore(&port->lock, flags);
465
466 ret = wait_event_interruptible(port->port.delta_msr_wait,
467 usb_serial_generic_msr_changed(tty, arg, &cnow));
468 if (!ret) {
469 if (test_bit(TTY_HUPPING, &tty->flags))
470 ret = -EIO;
471 if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
472 ret = -EIO;
473 }
474
475 return ret;
476}
477EXPORT_SYMBOL_GPL(usb_serial_generic_tiocmiwait);
478
479int usb_serial_generic_get_icount(struct tty_struct *tty,
480 struct serial_icounter_struct *icount)
481{
482 struct usb_serial_port *port = tty->driver_data;
483 struct async_icount cnow;
484 unsigned long flags;
485
486 spin_lock_irqsave(&port->lock, flags);
487 cnow = port->icount; /* atomic copy */
488 spin_unlock_irqrestore(&port->lock, flags);
489
490 icount->cts = cnow.cts;
491 icount->dsr = cnow.dsr;
492 icount->rng = cnow.rng;
493 icount->dcd = cnow.dcd;
494 icount->tx = cnow.tx;
495 icount->rx = cnow.rx;
496 icount->frame = cnow.frame;
497 icount->parity = cnow.parity;
498 icount->overrun = cnow.overrun;
499 icount->brk = cnow.brk;
500 icount->buf_overrun = cnow.buf_overrun;
501
502 return 0;
503}
504EXPORT_SYMBOL_GPL(usb_serial_generic_get_icount);
505
433#ifdef CONFIG_MAGIC_SYSRQ 506#ifdef CONFIG_MAGIC_SYSRQ
434int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch) 507int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
435{ 508{
@@ -473,8 +546,7 @@ void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
473{ 546{
474 struct tty_port *port = &usb_port->port; 547 struct tty_port *port = &usb_port->port;
475 548
476 dev_dbg(&usb_port->dev, "%s - port %d, status %d\n", __func__, 549 dev_dbg(&usb_port->dev, "%s - status %d\n", __func__, status);
477 usb_port->number, status);
478 550
479 if (status) 551 if (status)
480 wake_up_interruptible(&port->open_wait); 552 wake_up_interruptible(&port->open_wait);
@@ -510,17 +582,3 @@ int usb_serial_generic_resume(struct usb_serial *serial)
510 return c ? -EIO : 0; 582 return c ? -EIO : 0;
511} 583}
512EXPORT_SYMBOL_GPL(usb_serial_generic_resume); 584EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
513
514void usb_serial_generic_disconnect(struct usb_serial *serial)
515{
516 int i;
517
518 /* stop reads and writes on all ports */
519 for (i = 0; i < serial->num_ports; ++i)
520 generic_cleanup(serial->port[i]);
521}
522EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect);
523
524void usb_serial_generic_release(struct usb_serial *serial)
525{
526}