diff options
Diffstat (limited to 'drivers/usb/serial')
43 files changed, 417 insertions, 527 deletions
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 76f46224173..17b7f9ae36a 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -4,7 +4,7 @@ menuconfig USB_SERIAL tristate "USB Serial Converter support" - depends on USB + depends on USB && TTY ---help--- Say Y here if you have a USB device that provides normal serial ports, or acts like a serial device, and you want to connect it to @@ -647,6 +647,18 @@ config USB_SERIAL_VIVOPAY_SERIAL To compile this driver as a module, choose M here: the module will be called vivopay-serial. +config USB_SERIAL_XSENS_MT + tristate "Xsens motion tracker serial interface driver" + help + Say Y here if you want to use Xsens motion trackers. + + This driver supports the new generation of motion trackers + by Xsens. Older devices can be accessed using the FTDI_SIO + driver. + + To compile this driver as a module, choose M here: the + module will be called xsens_mt. + config USB_SERIAL_ZIO tristate "ZIO Motherboard USB serial interface driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 3b3e7308d47..eaf5ca14dfe 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -61,5 +61,6 @@ obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o obj-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda.o obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL) += vivopay-serial.o +obj-$(CONFIG_USB_SERIAL_XSENS_MT) += xsens_mt.o obj-$(CONFIG_USB_SERIAL_ZIO) += zio.o obj-$(CONFIG_USB_SERIAL_ZTE) += zte_ev.o diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 6d110a3bc7e..6e320cec397 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -119,9 +119,8 @@ static int aircable_probe(struct usb_serial *serial, return 0; } -static int aircable_process_packet(struct tty_struct *tty, - struct usb_serial_port *port, int has_headers, - char *packet, int len) +static int aircable_process_packet(struct usb_serial_port *port, + int has_headers, char *packet, int len) { if (has_headers) { len -= HCI_HEADER_LENGTH; @@ -132,7 +131,7 @@ static int aircable_process_packet(struct tty_struct *tty, return 0; } - tty_insert_flip_string(tty, packet, len); + tty_insert_flip_string(&port->port, packet, len); return len; } @@ -141,28 +140,22 @@ static void aircable_process_read_urb(struct urb *urb) { struct usb_serial_port *port = urb->context; char *data = (char *)urb->transfer_buffer; - struct tty_struct *tty; int has_headers; int count; int len; int i; - tty = tty_port_tty_get(&port->port); - if (!tty) - return; - has_headers = (urb->actual_length > 2 && data[0] == RX_HEADER_0); count = 0; for (i = 0; i < urb->actual_length; i += HCI_COMPLETE_FRAME) { len = min_t(int, urb->actual_length - i, HCI_COMPLETE_FRAME); - count += aircable_process_packet(tty, port, has_headers, + count += aircable_process_packet(port, has_headers, &data[i], len); } if (count) - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_flip_buffer_push(&port->port); } static struct usb_serial_driver aircable_device = { diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index a88882c0e23..cbd904b8fba 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -674,7 +674,6 @@ static void ark3116_process_read_urb(struct urb *urb) { struct usb_serial_port *port = urb->context; struct ark3116_private *priv = usb_get_serial_port_data(port); - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; char tty_flag = TTY_NORMAL; unsigned long flags; @@ -689,10 +688,6 @@ static void ark3116_process_read_urb(struct urb *urb) if (!urb->actual_length) return; - tty = tty_port_tty_get(&port->port); - if (!tty) - return; - if (lsr & UART_LSR_BRK_ERROR_BITS) { if (lsr & UART_LSR_BI) tty_flag = TTY_BREAK; @@ -703,12 +698,11 @@ static void ark3116_process_read_urb(struct urb *urb) /* overrun is special, not associated with a char */ if (lsr & UART_LSR_OE) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); } - tty_insert_flip_string_fixed_flag(tty, data, tty_flag, + tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag, urb->actual_length); - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_flip_buffer_push(&port->port); } static struct usb_serial_driver ark3116_device = { diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index b72a4c16670..84217e78ded 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -242,7 +242,6 @@ static void belkin_sa_process_read_urb(struct urb *urb) { struct usb_serial_port *port = urb->context; struct belkin_sa_private *priv = usb_get_serial_port_data(port); - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; unsigned long flags; unsigned char status; @@ -259,10 +258,6 @@ static void belkin_sa_process_read_urb(struct urb *urb) if (!urb->actual_length) return; - tty = tty_port_tty_get(&port->port); - if (!tty) - return; - if (status & BELKIN_SA_LSR_ERR) { /* Break takes precedence over parity, which takes precedence * over framing errors. */ @@ -276,13 +271,12 @@ static void belkin_sa_process_read_urb(struct urb *urb) /* Overrun is special, not associated with a char. */ if (status & BELKIN_SA_LSR_OE) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); } - tty_insert_flip_string_fixed_flag(tty, data, tty_flag, + tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag, urb->actual_length); - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_flip_buffer_push(&port->port); } static void belkin_sa_set_termios(struct tty_struct *tty, diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index f14736f647f..edc0f0dcad8 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -60,6 +60,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ + { USB_DEVICE(0x0FDE, 0xCA05) }, /* OWL Wireless Electricity Monitor CM-160 */ { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 69a4fa1cee2..629bd289450 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -324,7 +324,6 @@ static void cyberjack_read_bulk_callback(struct urb *urb) struct usb_serial_port *port = urb->context; struct cyberjack_private *priv = usb_get_serial_port_data(port); struct device *dev = &port->dev; - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; short todo; int result; @@ -337,16 +336,10 @@ static void cyberjack_read_bulk_callback(struct urb *urb) return; } - tty = tty_port_tty_get(&port->port); - if (!tty) { - dev_dbg(dev, "%s - ignoring since device not open\n", __func__); - return; - } if (urb->actual_length) { - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); + tty_insert_flip_string(&port->port, data, urb->actual_length); + tty_flip_buffer_push(&port->port); } - tty_kref_put(tty); spin_lock(&priv->lock); diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index fd8c35fd452..8efa19d0e9f 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -1214,10 +1214,10 @@ static void cypress_read_int_callback(struct urb *urb) spin_unlock_irqrestore(&priv->lock, flags); /* process read if there is data other than line status */ - if (tty && bytes > i) { - tty_insert_flip_string_fixed_flag(tty, data + i, + if (bytes > i) { + tty_insert_flip_string_fixed_flag(&port->port, data + i, tty_flag, bytes - i); - tty_flip_buffer_push(tty); + tty_flip_buffer_push(&port->port); } spin_lock_irqsave(&priv->lock, flags); diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 45d4af62967..ebe45fa0ed5 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -1399,9 +1399,7 @@ static void digi_read_bulk_callback(struct urb *urb) static int digi_read_inb_callback(struct urb *urb) { - struct usb_serial_port *port = urb->context; - struct tty_struct *tty; struct digi_port *priv = usb_get_serial_port_data(port); int opcode = ((unsigned char *)urb->transfer_buffer)[0]; int len = ((unsigned char *)urb->transfer_buffer)[1]; @@ -1425,7 +1423,6 @@ static int digi_read_inb_callback(struct urb *urb) return -1; } - tty = tty_port_tty_get(&port->port); spin_lock(&priv->dp_port_lock); /* check for throttle; if set, do not resubmit read urb */ @@ -1435,13 +1432,13 @@ static int digi_read_inb_callback(struct urb *urb) priv->dp_throttle_restart = 1; /* receive data */ - if (tty && opcode == DIGI_CMD_RECEIVE_DATA) { + if (opcode == DIGI_CMD_RECEIVE_DATA) { /* get flag from port_status */ flag = 0; /* overrun is special, not associated with a char */ if (port_status & DIGI_OVERRUN_ERROR) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); /* break takes precedence over parity, */ /* which takes precedence over framing errors */ @@ -1455,13 +1452,12 @@ static int digi_read_inb_callback(struct urb *urb) /* data length is len-1 (one byte of len is port_status) */ --len; if (len > 0) { - tty_insert_flip_string_fixed_flag(tty, data, flag, - len); - tty_flip_buffer_push(tty); + tty_insert_flip_string_fixed_flag(&port->port, data, + flag, len); + tty_flip_buffer_push(&port->port); } } spin_unlock(&priv->dp_port_lock); - tty_kref_put(tty); if (opcode == DIGI_CMD_RECEIVE_DISABLE) dev_dbg(&port->dev, "%s: got RECEIVE_DISABLE\n", __func__); diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 6e4eb57d017..b1b2dc64b50 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -100,7 +100,6 @@ static void f81232_process_read_urb(struct urb *urb) { struct usb_serial_port *port = urb->context; struct f81232_private *priv = usb_get_serial_port_data(port); - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; char tty_flag = TTY_NORMAL; unsigned long flags; @@ -117,10 +116,6 @@ static void f81232_process_read_urb(struct urb *urb) if (!urb->actual_length) return; - tty = tty_port_tty_get(&port->port); - if (!tty) - return; - /* break takes precedence over parity, */ /* which takes precedence over framing errors */ if (line_status & UART_BREAK_ERROR) @@ -133,19 +128,19 @@ static void f81232_process_read_urb(struct urb *urb) /* overrun is special, not associated with a char */ if (line_status & UART_OVERRUN_ERROR) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); if (port->port.console && port->sysrq) { for (i = 0; i < urb->actual_length; ++i) if (!usb_serial_handle_sysrq_char(port, data[i])) - tty_insert_flip_char(tty, data[i], tty_flag); + tty_insert_flip_char(&port->port, data[i], + tty_flag); } else { - tty_insert_flip_string_fixed_flag(tty, data, tty_flag, + tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag, urb->actual_length); } - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_flip_buffer_push(&port->port); } static int set_control_lines(struct usb_device *dev, u8 value) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ba68835d06a..edd162df49c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -584,6 +584,7 @@ static struct usb_device_id id_table_combined [] = { /* * ELV devices: */ + { USB_DEVICE(FTDI_ELV_VID, FTDI_ELV_WS300_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) }, @@ -670,6 +671,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) }, { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) }, @@ -1884,24 +1886,22 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on) { struct ftdi_private *priv = usb_get_serial_port_data(port); - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) { - /* Disable flow control */ - if (!on && usb_control_msg(port->serial->dev, + /* Disable flow control */ + if (!on) { + if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, priv->interface, NULL, 0, WDR_TIMEOUT) < 0) { - dev_err(&port->dev, "error from flowcontrol urb\n"); + dev_err(&port->dev, "error from flowcontrol urb\n"); } - /* drop RTS and DTR */ - if (on) - set_mctrl(port, TIOCM_DTR | TIOCM_RTS); - else - clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } - mutex_unlock(&port->serial->disc_mutex); + /* drop RTS and DTR */ + if (on) + set_mctrl(port, TIOCM_DTR | TIOCM_RTS); + else + clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } /* @@ -1960,9 +1960,8 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port, #define FTDI_RS_ERR_MASK (FTDI_RS_BI | FTDI_RS_PE | FTDI_RS_FE | FTDI_RS_OE) -static int ftdi_process_packet(struct tty_struct *tty, - struct usb_serial_port *port, struct ftdi_private *priv, - char *packet, int len) +static int ftdi_process_packet(struct usb_serial_port *port, + struct ftdi_private *priv, char *packet, int len) { int i; char status; @@ -2012,7 +2011,7 @@ static int ftdi_process_packet(struct tty_struct *tty, /* Overrun is special, not associated with a char */ if (packet[1] & FTDI_RS_OE) { priv->icount.overrun++; - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); } } @@ -2031,10 +2030,10 @@ static int ftdi_process_packet(struct tty_struct *tty, if (port->port.console && port->sysrq) { for (i = 0; i < len; i++, ch++) { if (!usb_serial_handle_sysrq_char(port, *ch)) - tty_insert_flip_char(tty, *ch, flag); + tty_insert_flip_char(&port->port, *ch, flag); } } else { - tty_insert_flip_string_fixed_flag(tty, ch, flag, len); + tty_insert_flip_string_fixed_flag(&port->port, ch, flag, len); } return len; @@ -2043,25 +2042,19 @@ static int ftdi_process_packet(struct tty_struct *tty, static void ftdi_process_read_urb(struct urb *urb) { struct usb_serial_port *port = urb->context; - struct tty_struct *tty; struct ftdi_private *priv = usb_get_serial_port_data(port); char *data = (char *)urb->transfer_buffer; int i; int len; int count = 0; - tty = tty_port_tty_get(&port->port); - if (!tty) - return; - for (i = 0; i < urb->actual_length; i += priv->max_packet_size) { len = min_t(int, urb->actual_length - i, priv->max_packet_size); - count += ftdi_process_packet(tty, port, priv, &data[i], len); + count += ftdi_process_packet(port, priv, &data[i], len); } if (count) - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_flip_buffer_push(&port->port); } static void ftdi_break_ctl(struct tty_struct *tty, int break_state) diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index fa5d5603827..9d359e189a6 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -147,6 +147,11 @@ #define XSENS_CONVERTER_6_PID 0xD38E #define XSENS_CONVERTER_7_PID 0xD38F +/** + * Zolix (www.zolix.com.cb) product ids + */ +#define FTDI_OMNI1509 0xD491 /* Omni1509 embedded USB-serial */ + /* * NDI (www.ndigital.com) product ids */ @@ -204,7 +209,7 @@ /* * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). - * All of these devices use FTDI's vendor ID (0x0403). + * Almost all of these devices use FTDI's vendor ID (0x0403). * Further IDs taken from ELV Windows .inf file. * * The previously included PID for the UO 100 module was incorrect. @@ -212,6 +217,8 @@ * * Armin Laeuger originally sent the PID for the UM 100 module. */ +#define FTDI_ELV_VID 0x1B1F /* ELV AG */ +#define FTDI_ELV_WS300_PID 0xC006 /* eQ3 WS 300 PC II */ #define FTDI_ELV_USR_PID 0xE000 /* ELV Universal-Sound-Recorder */ #define FTDI_ELV_MSM1_PID 0xE001 /* ELV Mini-Sound-Modul */ #define FTDI_ELV_KL100_PID 0xE002 /* ELV Kfz-Leistungsmesser KL 100 */ diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 203358d7e7b..1a07b12ef34 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -252,14 +252,11 @@ static inline int isAbortTrfCmnd(const unsigned char *buf) static void send_to_tty(struct usb_serial_port *port, char *data, unsigned int actual_length) { - struct tty_struct *tty = tty_port_tty_get(&port->port); - - if (tty && actual_length) { + if (actual_length) { usb_serial_debug_data(&port->dev, __func__, actual_length, data); - tty_insert_flip_string(tty, data, actual_length); - tty_flip_buffer_push(tty); + tty_insert_flip_string(&port->port, data, actual_length); + tty_flip_buffer_push(&port->port); } - tty_kref_put(tty); } diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 2ea70a63199..4c5c23f1cae 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -313,30 +313,24 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_submit_read_urbs); void usb_serial_generic_process_read_urb(struct urb *urb) { struct usb_serial_port *port = urb->context; - struct tty_struct *tty; char *ch = (char *)urb->transfer_buffer; int i; if (!urb->actual_length) return; - tty = tty_port_tty_get(&port->port); - if (!tty) - return; - /* The per character mucking around with sysrq path it too slow for stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases where the USB serial is not a console anyway */ if (!port->port.console || !port->sysrq) - tty_insert_flip_string(tty, ch, urb->actual_length); + tty_insert_flip_string(&port->port, ch, urb->actual_length); else { for (i = 0; i < urb->actual_length; i++, ch++) { if (!usb_serial_handle_sysrq_char(port, *ch)) - tty_insert_flip_char(tty, *ch, TTY_NORMAL); + tty_insert_flip_char(&port->port, *ch, TTY_NORMAL); } } - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_flip_buffer_push(&port->port); } EXPORT_SYMBOL_GPL(usb_serial_generic_process_read_urb); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 7b770c7f8b1..b00e5cbf741 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -232,8 +232,8 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength); static void process_rcvd_status(struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3); -static void edge_tty_recv(struct device *dev, struct tty_struct *tty, - unsigned char *data, int length); +static void edge_tty_recv(struct usb_serial_port *port, unsigned char *data, + int length); static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr); static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data); @@ -1752,7 +1752,6 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, struct device *dev = &edge_serial->serial->dev->dev; struct usb_serial_port *port; struct edgeport_port *edge_port; - struct tty_struct *tty; __u16 lastBufferLength; __u16 rxLen; @@ -1860,14 +1859,11 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, edge_serial->rxPort]; edge_port = usb_get_serial_port_data(port); if (edge_port->open) { - tty = tty_port_tty_get( - &edge_port->port->port); - if (tty) { - dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n", - __func__, rxLen, edge_serial->rxPort); - edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen); - tty_kref_put(tty); - } + dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n", + __func__, rxLen, + edge_serial->rxPort); + edge_tty_recv(edge_port->port, buffer, + rxLen); edge_port->icount.rx += rxLen; } buffer += rxLen; @@ -2017,20 +2013,20 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, * edge_tty_recv * this function passes data on to the tty flip buffer *****************************************************************************/ -static void edge_tty_recv(struct device *dev, struct tty_struct *tty, - unsigned char *data, int length) +static void edge_tty_recv(struct usb_serial_port *port, unsigned char *data, + int length) { int cnt; - cnt = tty_insert_flip_string(tty, data, length); + cnt = tty_insert_flip_string(&port->port, data, length); if (cnt < length) { - dev_err(dev, "%s - dropping data, %d bytes lost\n", + dev_err(&port->dev, "%s - dropping data, %d bytes lost\n", __func__, length - cnt); } data += cnt; length -= cnt; - tty_flip_buffer_push(tty); + tty_flip_buffer_push(&port->port); } @@ -2086,14 +2082,9 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, } /* Place LSR data byte into Rx buffer */ - if (lsrData) { - struct tty_struct *tty = - tty_port_tty_get(&edge_port->port->port); - if (tty) { - edge_tty_recv(&edge_port->port->dev, tty, &data, 1); - tty_kref_put(tty); - } - } + if (lsrData) + edge_tty_recv(edge_port->port, &data, 1); + /* update input line counters */ icount = &edge_port->icount; if (newLsr & LSR_BREAK) diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 82afc4d6a32..c23776679f7 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -201,8 +201,8 @@ static int closing_wait = EDGE_CLOSING_WAIT; static bool ignore_cpu_rev; static int default_uart_mode; /* RS232 */ -static void edge_tty_recv(struct device *dev, struct tty_struct *tty, - unsigned char *data, int length); +static void edge_tty_recv(struct usb_serial_port *port, unsigned char *data, + int length); static void stop_read(struct edgeport_port *edge_port); static int restart_read(struct edgeport_port *edge_port); @@ -521,65 +521,6 @@ exit_is_tx_active: return bytes_left; } -static void chase_port(struct edgeport_port *port, unsigned long timeout, - int flush) -{ - int baud_rate; - struct tty_struct *tty = tty_port_tty_get(&port->port->port); - struct usb_serial *serial = port->port->serial; - wait_queue_t wait; - unsigned long flags; - - if (!tty) - return; - - if (!timeout) - timeout = (HZ * EDGE_CLOSING_WAIT)/100; - - /* wait for data to drain from the buffer */ - spin_lock_irqsave(&port->ep_lock, flags); - init_waitqueue_entry(&wait, current); - add_wait_queue(&tty->write_wait, &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (kfifo_len(&port->write_fifo) == 0 - || timeout == 0 || signal_pending(current) - || serial->disconnected) - /* disconnect */ - break; - spin_unlock_irqrestore(&port->ep_lock, flags); - timeout = schedule_timeout(timeout); - spin_lock_irqsave(&port->ep_lock, flags); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&tty->write_wait, &wait); - if (flush) - kfifo_reset_out(&port->write_fifo); - spin_unlock_irqrestore(&port->ep_lock, flags); - tty_kref_put(tty); - - /* wait for data to drain from the device */ - timeout += jiffies; - while ((long)(jiffies - timeout) < 0 && !signal_pending(current) - && !serial->disconnected) { - /* not disconnected */ - if (!tx_active(port)) - break; - msleep(10); - } - - /* disconnected */ - if (serial->disconnected) - return; - - /* wait one more character time, based on baud rate */ - /* (tx_active doesn't seem to wait for the last byte) */ - baud_rate = port->baud_rate; - if (baud_rate == 0) - baud_rate = 50; - msleep(max(1, DIV_ROUND_UP(10000, baud_rate))); -} - static int choose_config(struct usb_device *dev) { /* @@ -1543,7 +1484,6 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data, struct async_icount *icount; __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK)); - struct tty_struct *tty; dev_dbg(&edge_port->port->dev, "%s - %02x\n", __func__, new_lsr); @@ -1557,13 +1497,8 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data, new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK); /* Place LSR data byte into Rx buffer */ - if (lsr_data) { - tty = tty_port_tty_get(&edge_port->port->port); - if (tty) { - edge_tty_recv(&edge_port->port->dev, tty, &data, 1); - tty_kref_put(tty); - } - } + if (lsr_data) + edge_tty_recv(edge_port->port, &data, 1); /* update input line counters */ icount = &edge_port->icount; @@ -1679,7 +1614,6 @@ static void edge_bulk_in_callback(struct urb *urb) struct edgeport_port *edge_port = urb->context; struct device *dev = &edge_port->port->dev; unsigned char *data = urb->transfer_buffer; - struct tty_struct *tty; int retval = 0; int port_number; int status = urb->status; @@ -1718,17 +1652,16 @@ static void edge_bulk_in_callback(struct urb *urb) ++data; } - tty = tty_port_tty_get(&edge_port->port->port); - if (tty && urb->actual_length) { + if (urb->actual_length) { usb_serial_debug_data(dev, __func__, urb->actual_length, data); if (edge_port->close_pending) dev_dbg(dev, "%s - close pending, dropping data on the floor\n", __func__); else - edge_tty_recv(dev, tty, data, urb->actual_length); + edge_tty_recv(edge_port->port, data, + urb->actual_length); edge_port->icount.rx += urb->actual_length; } - tty_kref_put(tty); exit: /* continue read unless stopped */ @@ -1743,16 +1676,16 @@ exit: dev_err(dev, "%s - usb_submit_urb failed with result %d\n", __func__, retval); } -static void edge_tty_recv(struct device *dev, struct tty_struct *tty, - unsigned char *data, int length) +static void edge_tty_recv(struct usb_serial_port *port, unsigned char *data, + int length) { int queued; - queued = tty_insert_flip_string(tty, data, length); + queued = tty_insert_flip_string(&port->port, data, length); if (queued < length) - dev_err(dev, "%s - dropping data, %d bytes lost\n", + dev_err(&port->dev, "%s - dropping data, %d bytes lost\n", __func__, length - queued); - tty_flip_buffer_push(tty); + tty_flip_buffer_push(&port->port); } static void edge_bulk_out_callback(struct urb *urb) @@ -1944,6 +1877,8 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) ++edge_serial->num_ports_open; + port->port.drain_delay = 1; + goto release_es_lock; unlink_int_urb: @@ -1959,6 +1894,7 @@ static void edge_close(struct usb_serial_port *port) struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; struct usb_serial *serial = port->serial; + unsigned long flags; int port_number; edge_serial = usb_get_serial_data(port->serial); @@ -1970,12 +1906,12 @@ static void edge_close(struct usb_serial_port *port) * this flag and dump add read data */ edge_port->close_pending = 1; - /* chase the port close and flush */ - chase_port(edge_port, (HZ * closing_wait) / 100, 1); - usb_kill_urb(port->read_urb); usb_kill_urb(port->write_urb); edge_port->ep_write_urb_in_use = 0; + spin_lock_irqsave(&edge_port->ep_lock, flags); + kfifo_reset_out(&edge_port->write_fifo); + spin_unlock_irqrestore(&edge_port->ep_lock, flags); /* assuming we can still talk to the device, * send a close port command to it */ @@ -2101,16 +2037,21 @@ static int edge_chars_in_buffer(struct tty_struct *tty) struct edgeport_port *edge_port = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; + int ret; if (edge_port == NULL) return 0; - if (edge_port->close_pending == 1) - return 0; spin_lock_irqsave(&edge_port->ep_lock, flags); chars = kfifo_len(&edge_port->write_fifo); spin_unlock_irqrestore(&edge_port->ep_lock, flags); + if (!chars) { + ret = tx_active(edge_port); + if (ret > 0) + chars = ret; + } + dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); return chars; } @@ -2448,10 +2389,15 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo) { struct serial_struct tmp; + unsigned cwait; if (!retinfo) return -EFAULT; + cwait = edge_port->port->port.closing_wait; + if (cwait != ASYNC_CLOSING_WAIT_NONE) + cwait = jiffies_to_msecs(closing_wait) / 10; + memset(&tmp, 0, sizeof(tmp)); tmp.type = PORT_16550A; @@ -2462,7 +2408,7 @@ static int get_serial_info(struct edgeport_port *edge_port, tmp.xmit_fifo_size = edge_port->port->bulk_out_size; tmp.baud_base = 9600; tmp.close_delay = 5*HZ; - tmp.closing_wait = closing_wait; + tmp.closing_wait = cwait; if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; @@ -2517,8 +2463,7 @@ static void edge_break(struct tty_struct *tty, int break_state) int status; int bv = 0; /* Off */ - /* chase the port close */ - chase_port(edge_port, 0, 0); + tty_wait_until_sent(tty, 0); if (break_state == -1) bv = 1; /* On */ @@ -2591,6 +2536,8 @@ static int edge_port_probe(struct usb_serial_port *port) return ret; } + port->port.closing_wait = msecs_to_jiffies(closing_wait * 10); + return 0; } diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index e24e2d4f4c1..716930ab1bb 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -287,7 +287,6 @@ static void ir_process_read_urb(struct urb *urb) { struct usb_serial_port *port = urb->context; unsigned char *data = urb->transfer_buffer; - struct tty_struct *tty; if (!urb->actual_length) return; @@ -302,12 +301,8 @@ static void ir_process_read_urb(struct urb *urb) if (urb->actual_length == 1) return; - tty = tty_port_tty_get(&port->port); - if (!tty) - return; - tty_insert_flip_string(tty, data + 1, urb->actual_length - 1); - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_insert_flip_string(&port->port, data + 1, urb->actual_length - 1); + tty_flip_buffer_push(&port->port); } static void ir_set_termios_callback(struct urb *urb) diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 1e1fbed65ef..ff77027160a 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -581,7 +581,6 @@ static void read_buf_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; unsigned char *data = urb->transfer_buffer; - struct tty_struct *tty; int status = urb->status; if (status) { @@ -592,14 +591,12 @@ static void read_buf_callback(struct urb *urb) } dev_dbg(&port->dev, "%s - %i chars to write\n", __func__, urb->actual_length); - tty = tty_port_tty_get(&port->port); if (data == NULL) dev_dbg(&port->dev, "%s - data is NULL !!!\n", __func__); - if (tty && urb->actual_length && data) { - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); + if (urb->actual_length && data) { + tty_insert_flip_string(&port->port, data, urb->actual_length); + tty_flip_buffer_push(&port->port); } - tty_kref_put(tty); iuu_led_activity_on(urb); } diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 97bc49f68ef..1fd1935c831 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -291,21 +291,19 @@ static void usa26_indat_callback(struct urb *urb) int i, err; int endpoint; struct usb_serial_port *port; - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int status = urb->status; endpoint = usb_pipeendpoint(urb->pipe); if (status) { - dev_dbg(&urb->dev->dev,"%s - nonzero status: %x on endpoint %d.\n", + dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n", __func__, status, endpoint); return; } port = urb->context; - tty = tty_port_tty_get(&port->port); - if (tty && urb->actual_length) { + if (urb->actual_length) { /* 0x80 bit is error flag */ if ((data[0] & 0x80) == 0) { /* no errors on individual bytes, only @@ -315,7 +313,7 @@ static void usa26_indat_callback(struct urb *urb) else err = 0; for (i = 1; i < urb->actual_length ; ++i) - tty_insert_flip_char(tty, data[i], err); + tty_insert_flip_char(&port->port, data[i], err); } else { /* some bytes had errors, every byte has status */ dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__); @@ -328,12 +326,12 @@ static void usa26_indat_callback(struct urb *urb) if (stat & RXERROR_PARITY) flag |= TTY_PARITY; /* XXX should handle break (0x10) */ - tty_insert_flip_char(tty, data[i+1], flag); + tty_insert_flip_char(&port->port, data[i+1], + flag); } } - tty_flip_buffer_push(tty); + tty_flip_buffer_push(&port->port); } - tty_kref_put(tty); /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); @@ -446,7 +444,6 @@ static void usa28_indat_callback(struct urb *urb) { int err; struct usb_serial_port *port; - struct tty_struct *tty; unsigned char *data; struct keyspan_port_private *p_priv; int status = urb->status; @@ -469,12 +466,11 @@ static void usa28_indat_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); data = urb->transfer_buffer; - tty = tty_port_tty_get(&port->port); - if (tty && urb->actual_length) { - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); + if (urb->actual_length) { + tty_insert_flip_string(&port->port, data, + urb->actual_length); + tty_flip_buffer_push(&port->port); } - tty_kref_put(tty); /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); @@ -532,7 +528,7 @@ static void usa28_instat_callback(struct urb *urb) /* dev_dbg(&urb->dev->dev, - "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__, + "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11]); */ @@ -669,7 +665,6 @@ static void usa49_indat_callback(struct urb *urb) int i, err; int endpoint; struct usb_serial_port *port; - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int status = urb->status; @@ -682,12 +677,11 @@ static void usa49_indat_callback(struct urb *urb) } port = urb->context; - tty = tty_port_tty_get(&port->port); - if (tty && urb->actual_length) { + if (urb->actual_length) { /* 0x80 bit is error flag */ if ((data[0] & 0x80) == 0) { /* no error on any byte */ - tty_insert_flip_string(tty, data + 1, + tty_insert_flip_string(&port->port, data + 1, urb->actual_length - 1); } else { /* some bytes had errors, every byte has status */ @@ -700,12 +694,12 @@ static void usa49_indat_callback(struct urb *urb) if (stat & RXERROR_PARITY) flag |= TTY_PARITY; /* XXX should handle break (0x10) */ - tty_insert_flip_char(tty, data[i+1], flag); + tty_insert_flip_char(&port->port, data[i+1], + flag); } } - tty_flip_buffer_push(tty); + tty_flip_buffer_push(&port->port); } - tty_kref_put(tty); /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); @@ -718,7 +712,6 @@ static void usa49wg_indat_callback(struct urb *urb) int i, len, x, err; struct usb_serial *serial; struct usb_serial_port *port; - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int status = urb->status; @@ -743,7 +736,6 @@ static void usa49wg_indat_callback(struct urb *urb) return; } port = serial->port[data[i++]]; - tty = tty_port_tty_get(&port->port); len = data[i++]; /* 0x80 bit is error flag */ @@ -751,7 +743,8 @@ static void usa49wg_indat_callback(struct urb *urb) /* no error on any byte */ i++; for (x = 1; x < len ; ++x) - tty_insert_flip_char(tty, data[i++], 0); + tty_insert_flip_char(&port->port, + data[i++], 0); } else { /* * some bytes had errors, every byte has status @@ -765,13 +758,12 @@ static void usa49wg_indat_callback(struct urb *urb) if (stat & RXERROR_PARITY) flag |= TTY_PARITY; /* XXX should handle break (0x10) */ - tty_insert_flip_char(tty, + tty_insert_flip_char(&port->port, data[i+1], flag); i += 2; } } - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_flip_buffer_push(&port->port); } } @@ -792,7 +784,6 @@ static void usa90_indat_callback(struct urb *urb) int endpoint; struct usb_serial_port *port; struct keyspan_port_private *p_priv; - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int status = urb->status; @@ -808,12 +799,12 @@ static void usa90_indat_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); if (urb->actual_length) { - tty = tty_port_tty_get(&port->port); /* if current mode is DMA, looks like usa28 format otherwise looks like usa26 data format */ if (p_priv->baud > 57600) - tty_insert_flip_string(tty, data, urb->actual_length); + tty_insert_flip_string(&port->port, data, + urb->actual_length); else { /* 0x80 bit is error flag */ if ((data[0] & 0x80) == 0) { @@ -824,8 +815,8 @@ static void usa90_indat_callback(struct urb *urb) else err = 0; for (i = 1; i < urb->actual_length ; ++i) - tty_insert_flip_char(tty, data[i], - err); + tty_insert_flip_char(&port->port, + data[i], err); } else { /* some bytes had errors, every byte has status */ dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__); @@ -838,13 +829,12 @@ static void usa90_indat_callback(struct urb *urb) if (stat & RXERROR_PARITY) flag |= TTY_PARITY; /* XXX should handle break (0x10) */ - tty_insert_flip_char(tty, data[i+1], - flag); + tty_insert_flip_char(&port->port, + data[i+1], flag); } } } - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_flip_buffer_push(&port->port); } /* Resubmit urb so we continue receiving */ diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 41b01092af0..3b17d5d13dc 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -138,7 +138,6 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work) static void keyspan_pda_rx_interrupt(struct urb *urb) { struct usb_serial_port *port = urb->context; - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int retval; int status = urb->status; @@ -163,14 +162,12 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) /* see if the message is data or a status interrupt */ switch (data[0]) { case 0: - tty = tty_port_tty_get(&port->port); /* rest of message is rx data */ - if (tty && urb->actual_length) { - tty_insert_flip_string(tty, data + 1, + if (urb->actual_length) { + tty_insert_flip_string(&port->port, data + 1, urb->actual_length - 1); - tty_flip_buffer_push(tty); + tty_flip_buffer_push(&port->port); } - tty_kref_put(tty); break; case 1: /* status interrupt */ diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index fc9e14a1e9b..769d910ae0a 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -389,7 +389,6 @@ static void klsi_105_process_read_urb(struct urb *urb) { struct usb_serial_port *port = urb->context; unsigned char *data = urb->transfer_buffer; - struct tty_struct *tty; unsigned len; /* empty urbs seem to happen, we ignore them */ @@ -401,19 +400,14 @@ static void klsi_105_process_read_urb(struct urb *urb) return; } - tty = tty_port_tty_get(&port->port); - if (!tty) - return; - len = get_unaligned_le16(data); if (len > urb->actual_length - KLSI_HDR_LEN) { dev_dbg(&port->dev, "%s - packet length mismatch\n", __func__); len = urb->actual_length - KLSI_HDR_LEN; } - tty_insert_flip_string(tty, data + KLSI_HDR_LEN, len); - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_insert_flip_string(&port->port, data + KLSI_HDR_LEN, len); + tty_flip_buffer_push(&port->port); } static void klsi_105_set_termios(struct tty_struct *tty, diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index b747ba615d0..903d938e174 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -324,7 +324,6 @@ static void kobil_read_int_callback(struct urb *urb) { int result; struct usb_serial_port *port = urb->context; - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int status = urb->status; @@ -333,8 +332,7 @@ static void kobil_read_int_callback(struct urb *urb) return; } - tty = tty_port_tty_get(&port->port); - if (tty && urb->actual_length) { + if (urb->actual_length) { /* BEGIN DEBUG */ /* @@ -353,10 +351,9 @@ static void kobil_read_int_callback(struct urb *urb) */ /* END DEBUG */ - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); + tty_insert_flip_string(&port->port, data, urb->actual_length); + tty_flip_buffer_push(&port->port); } - tty_kref_put(tty); result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result); diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index b6911757c85..a64d420f687 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -499,19 +499,15 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on) unsigned int control_state; struct mct_u232_private *priv = usb_get_serial_port_data(port); - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) { - /* drop DTR and RTS */ - spin_lock_irq(&priv->lock); - if (on) - priv->control_state |= TIOCM_DTR | TIOCM_RTS; - else - priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); - control_state = priv->control_state; - spin_unlock_irq(&priv->lock); - mct_u232_set_modem_ctrl(port, control_state); - } - mutex_unlock(&port->serial->disc_mutex); + spin_lock_irq(&priv->lock); + if (on) + priv->control_state |= TIOCM_DTR | TIOCM_RTS; + else + priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); + control_state = priv->control_state; + spin_unlock_irq(&priv->lock); + + mct_u232_set_modem_ctrl(port, control_state); } static void mct_u232_close(struct usb_serial_port *port) @@ -531,7 +527,6 @@ static void mct_u232_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct mct_u232_private *priv = usb_get_serial_port_data(port); - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int retval; int status = urb->status; @@ -561,13 +556,9 @@ static void mct_u232_read_int_callback(struct urb *urb) */ if (urb->transfer_buffer_length > 2) { if (urb->actual_length) { - tty = tty_port_tty_get(&port->port); - if (tty) { - tty_insert_flip_string(tty, data, - urb->actual_length); - tty_flip_buffer_push(tty); - } - tty_kref_put(tty); + tty_insert_flip_string(&port->port, data, + urb->actual_length); + tty_flip_buffer_push(&port->port); } goto exit; } diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 3d258448c29..bf3c7a23553 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -95,7 +95,6 @@ static void metrousb_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct metrousb_private *metro_priv = usb_get_serial_port_data(port); - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int throttled = 0; int result = 0; @@ -124,15 +123,13 @@ static void metrousb_read_int_callback(struct urb *urb) /* Set the data read from the usb port into the serial port buffer. */ - tty = tty_port_tty_get(&port->port); - if (tty && urb->actual_length) { + if (urb->actual_length) { /* Loop through the data copying each byte to the tty layer. */ - tty_insert_flip_string(tty, data, urb->actual_length); + tty_insert_flip_string(&port->port, data, urb->actual_length); /* Force the data to the tty layer. */ - tty_flip_buffer_push(tty); + tty_flip_buffer_push(&port->port); } - tty_kref_put(tty); /* Set any port variables. */ spin_lock_irqsave(&metro_priv->lock, flags); diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index f57a6b1fe78..e0ebec3b5d6 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -899,7 +899,6 @@ static void mos7720_bulk_in_callback(struct urb *urb) int retval; unsigned char *data ; struct usb_serial_port *port; - struct tty_struct *tty; int status = urb->status; if (status) { @@ -913,12 +912,10 @@ static void mos7720_bulk_in_callback(struct urb *urb) data = urb->transfer_buffer; - tty = tty_port_tty_get(&port->port); - if (tty && urb->actual_length) { - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); + if (urb->actual_length) { + tty_insert_flip_string(&port->port, data, urb->actual_length); + tty_flip_buffer_push(&port->port); } - tty_kref_put(tty); if (port->read_urb->status != -EINPROGRESS) { retval = usb_submit_urb(port->read_urb, GFP_ATOMIC); diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 66d9e088d9d..809fb329eca 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -744,7 +744,6 @@ static void mos7840_bulk_in_callback(struct urb *urb) struct usb_serial *serial; struct usb_serial_port *port; struct moschip_port *mos7840_port; - struct tty_struct *tty; int status = urb->status; mos7840_port = urb->context; @@ -773,12 +772,9 @@ static void mos7840_bulk_in_callback(struct urb *urb) usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); if (urb->actual_length) { - tty = tty_port_tty_get(&mos7840_port->port->port); - if (tty) { - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); - tty_kref_put(tty); - } + struct tty_port *tport = &mos7840_port->port->port; + tty_insert_flip_string(tport, data, urb->actual_length); + tty_flip_buffer_push(tport); mos7840_port->icount.rx += urb->actual_length; smp_wmb(); dev_dbg(&port->dev, "mos7840_port->icount.rx is %d:\n", mos7840_port->icount.rx); diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index 1566f8f500a..38725fc8c2c 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -32,7 +32,6 @@ static void navman_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; unsigned char *data = urb->transfer_buffer; - struct tty_struct *tty; int status = urb->status; int result; @@ -55,12 +54,10 @@ static void navman_read_int_callback(struct urb *urb) usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); - tty = tty_port_tty_get(&port->port); - if (tty && urb->actual_length) { - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); + if (urb->actual_length) { + tty_insert_flip_string(&port->port, data, urb->actual_length); + tty_flip_buffer_push(&port->port); } - tty_kref_put(tty); exit: result = usb_submit_urb(urb, GFP_ATOMIC); diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 7818af931a4..1e1cafe287e 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -174,13 +174,9 @@ static void omninet_read_bulk_callback(struct urb *urb) } if (urb->actual_length && header->oh_len) { - struct tty_struct *tty = tty_port_tty_get(&port->port); - if (tty) { - tty_insert_flip_string(tty, data + OMNINET_DATAOFFSET, - header->oh_len); - tty_flip_buffer_push(tty); - tty_kref_put(tty); - } + tty_insert_flip_string(&port->port, data + OMNINET_DATAOFFSET, + header->oh_len); + tty_flip_buffer_push(&port->port); } /* Continue trying to always read */ diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index c6bfb83efb1..e13e1a4d3e1 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -51,15 +51,8 @@ struct opticon_private { static void opticon_process_data_packet(struct usb_serial_port *port, const unsigned char *buf, size_t len) { - struct tty_struct *tty; - - tty = tty_port_tty_get(&port->port); - if (!tty) - return; - - tty_insert_flip_string(tty, buf, len); - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_insert_flip_string(&port->port, buf, len); + tty_flip_buffer_push(&port->port); } static void opticon_process_status_packet(struct usb_serial_port *port, diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 0d9dac9e7f9..f7d339d8187 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -242,6 +242,7 @@ static void option_instat_callback(struct urb *urb); #define TELIT_PRODUCT_CC864_DUAL 0x1005 #define TELIT_PRODUCT_CC864_SINGLE 0x1006 #define TELIT_PRODUCT_DE910_DUAL 0x1010 +#define TELIT_PRODUCT_LE920 0x1200 /* ZTE PRODUCTS */ #define ZTE_VENDOR_ID 0x19d2 @@ -453,6 +454,10 @@ static void option_instat_callback(struct urb *urb); #define TPLINK_VENDOR_ID 0x2357 #define TPLINK_PRODUCT_MA180 0x0201 +/* Changhong products */ +#define CHANGHONG_VENDOR_ID 0x2077 +#define CHANGHONG_PRODUCT_CH690 0x7001 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -474,6 +479,7 @@ static const struct option_blacklist_info four_g_w14_blacklist = { static const struct option_blacklist_info alcatel_x200_blacklist = { .sendsetup = BIT(0) | BIT(1), + .reserved = BIT(4), }; static const struct option_blacklist_info zte_0037_blacklist = { @@ -534,6 +540,11 @@ static const struct option_blacklist_info zte_1255_blacklist = { .reserved = BIT(3) | BIT(4), }; +static const struct option_blacklist_info telit_le920_blacklist = { + .sendsetup = BIT(0), + .reserved = BIT(1) | BIT(5), +}; + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -565,8 +576,14 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, + { USB_DEVICE(QUANTA_VENDOR_ID, 0xea42), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c05, USB_CLASS_COMM, 0x02, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1441, USB_CLASS_COMM, 0x02, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1442, USB_CLASS_COMM, 0x02, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff), @@ -784,6 +801,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), + .driver_info = (kernel_ulong_t)&telit_le920_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, @@ -1203,7 +1222,14 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist }, - { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, 0x0052), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, 0x00b6), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, 0x00b7), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, @@ -1318,6 +1344,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index d217fd6ee43..a958fd41b5b 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -820,7 +820,6 @@ static void oti6858_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct oti6858_private *priv = usb_get_serial_port_data(port); - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; unsigned long flags; int status = urb->status; @@ -835,12 +834,10 @@ static void oti6858_read_bulk_callback(struct urb *urb) return; } - tty = tty_port_tty_get(&port->port); - if (tty != NULL && urb->actual_length > 0) { - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); + if (urb->actual_length > 0) { + tty_insert_flip_string(&port->port, data, urb->actual_length); + tty_flip_buffer_push(&port->port); } - tty_kref_put(tty); /* schedule the interrupt urb */ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 60024190136..54adc9125e5 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -772,7 +772,6 @@ static void pl2303_process_read_urb(struct urb *urb) { struct usb_serial_port *port = urb->context; struct pl2303_private *priv = usb_get_serial_port_data(port); - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; char tty_flag = TTY_NORMAL; unsigned long flags; @@ -789,10 +788,6 @@ static void pl2303_process_read_urb(struct urb *urb) if (!urb->actual_length) return; - tty = tty_port_tty_get(&port->port); - if (!tty) - return; - /* break takes precedence over parity, */ /* which takes precedence over framing errors */ if (line_status & UART_BREAK_ERROR) @@ -805,19 +800,19 @@ static void pl2303_process_read_urb(struct urb *urb) /* overrun is special, not associated with a char */ if (line_status & UART_OVERRUN_ERROR) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); if (port->port.console && port->sysrq) { for (i = 0; i < urb->actual_length; ++i) if (!usb_serial_handle_sysrq_char(port, data[i])) - tty_insert_flip_char(tty, data[i], tty_flag); + tty_insert_flip_char(&port->port, data[i], + tty_flag); } else { - tty_insert_flip_string_fixed_flag(tty, data, tty_flag, + tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag, urb->actual_length); } - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_flip_buffer_push(&port->port); } /* All of the device info needed for the PL2303 SIO serial converter */ diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index aa148c21ea4..24662547dc5 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -53,6 +53,7 @@ static const struct usb_device_id id_table[] = { {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ + {DEVICE_G1K(0x1bc7, 0x900e)}, /* Telit Gobi QDL device */ /* Gobi 2000 devices */ {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */ diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index d152be97d04..00e6c9bac8a 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -609,7 +609,6 @@ void qt2_process_read_urb(struct urb *urb) struct qt2_serial_private *serial_priv; struct usb_serial_port *port; struct qt2_port_private *port_priv; - struct tty_struct *tty; bool escapeflag; unsigned char *ch; int i; @@ -620,15 +619,11 @@ void qt2_process_read_urb(struct urb *urb) return; ch = urb->transfer_buffer; - tty = NULL; serial = urb->context; serial_priv = usb_get_serial_data(serial); port = serial->port[serial_priv->current_port]; port_priv = usb_get_serial_port_data(port); - if (port_priv->is_open) - tty = tty_port_tty_get(&port->port); - for (i = 0; i < urb->actual_length; i++) { ch = (unsigned char *)urb->transfer_buffer + i; if ((i <= (len - 3)) && @@ -666,10 +661,7 @@ void qt2_process_read_urb(struct urb *urb) __func__); break; } - if (tty) { - tty_flip_buffer_push(tty); - tty_kref_put(tty); - } + tty_flip_buffer_push(&port->port); newport = *(ch + 3); @@ -683,10 +675,6 @@ void qt2_process_read_urb(struct urb *urb) serial_priv->current_port = newport; port = serial->port[serial_priv->current_port]; port_priv = usb_get_serial_port_data(port); - if (port_priv->is_open) - tty = tty_port_tty_get(&port->port); - else - tty = NULL; i += 3; escapeflag = true; break; @@ -697,8 +685,8 @@ void qt2_process_read_urb(struct urb *urb) escapeflag = true; break; case QT2_CONTROL_ESCAPE: - tty_buffer_request_room(tty, 2); - tty_insert_flip_string(tty, ch, 2); + tty_buffer_request_room(&port->port, 2); + tty_insert_flip_string(&port->port, ch, 2); i += 2; escapeflag = true; break; @@ -712,16 +700,11 @@ void qt2_process_read_urb(struct urb *urb) continue; } - if (tty) { - tty_buffer_request_room(tty, 1); - tty_insert_flip_string(tty, ch, 1); - } + tty_buffer_request_room(&port->port, 1); + tty_insert_flip_string(&port->port, ch, 1); } - if (tty) { - tty_flip_buffer_push(tty); - tty_kref_put(tty); - } + tty_flip_buffer_push(&port->port); } static void qt2_write_bulk_callback(struct urb *urb) @@ -945,19 +928,17 @@ static void qt2_dtr_rts(struct usb_serial_port *port, int on) struct usb_device *dev = port->serial->dev; struct qt2_port_private *port_priv = usb_get_serial_port_data(port); - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) { - /* Disable flow control */ - if (!on && qt2_setregister(dev, port_priv->device_port, + /* Disable flow control */ + if (!on) { + if (qt2_setregister(dev, port_priv->device_port, UART_MCR, 0) < 0) dev_warn(&port->dev, "error from flowcontrol urb\n"); - /* drop RTS and DTR */ - if (on) - update_mctrl(port_priv, TIOCM_DTR | TIOCM_RTS, 0); - else - update_mctrl(port_priv, 0, TIOCM_DTR | TIOCM_RTS); } - mutex_unlock(&port->serial->disc_mutex); + /* drop RTS and DTR */ + if (on) + update_mctrl(port_priv, TIOCM_DTR | TIOCM_RTS, 0); + else + update_mctrl(port_priv, 0, TIOCM_DTR | TIOCM_RTS); } static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch) diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index c949ce6ef0c..21cd7bf2a8c 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c @@ -207,38 +207,31 @@ static void safe_process_read_urb(struct urb *urb) unsigned char *data = urb->transfer_buffer; unsigned char length = urb->actual_length; int actual_length; - struct tty_struct *tty; __u16 fcs; if (!length) return; - tty = tty_port_tty_get(&port->port); - if (!tty) - return; - if (!safe) goto out; fcs = fcs_compute10(data, length, CRC10_INITFCS); if (fcs) { dev_err(&port->dev, "%s - bad CRC %x\n", __func__, fcs); - goto err; + return; } actual_length = data[length - 2] >> 2; if (actual_length > (length - 2)) { dev_err(&port->dev, "%s - inconsistent lengths %d:%d\n", __func__, actual_length, length); - goto err; + return; } dev_info(&urb->dev->dev, "%s - actual: %d\n", __func__, actual_length); length = actual_length; out: - tty_insert_flip_string(tty, data, length); - tty_flip_buffer_push(tty); -err: - tty_kref_put(tty); + tty_insert_flip_string(&port->port, data, length); + tty_flip_buffer_push(&port->port); } static int safe_prepare_write_buffer(struct usb_serial_port *port, diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index af06f2f5f38..c13f6e74774 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -569,7 +569,6 @@ static void sierra_indat_callback(struct urb *urb) int err; int endpoint; struct usb_serial_port *port; - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int status = urb->status; @@ -581,16 +580,12 @@ static void sierra_indat_callback(struct urb *urb) " endpoint %02x\n", __func__, status, endpoint); } else { if (urb->actual_length) { - tty = tty_port_tty_get(&port->port); - if (tty) { - tty_insert_flip_string(tty, data, - urb->actual_length); - tty_flip_buffer_push(tty); - - tty_kref_put(tty); - usb_serial_debug_data(&port->dev, __func__, - urb->actual_length, data); - } + tty_insert_flip_string(&port->port, data, + urb->actual_length); + tty_flip_buffer_push(&port->port); + + usb_serial_debug_data(&port->dev, __func__, + urb->actual_length, data); } else { dev_dbg(&port->dev, "%s: empty read urb" " received\n", __func__); @@ -861,19 +856,13 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) static void sierra_dtr_rts(struct usb_serial_port *port, int on) { - struct usb_serial *serial = port->serial; struct sierra_port_private *portdata; portdata = usb_get_serial_port_data(port); portdata->rts_state = on; portdata->dtr_state = on; - if (serial->dev) { - mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) - sierra_send_setup(port); - mutex_unlock(&serial->disc_mutex); - } + sierra_send_setup(port); } static int sierra_startup(struct usb_serial *serial) diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index a42536af125..91ff8e3bddb 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -462,7 +462,6 @@ static void spcp8x5_process_read_urb(struct urb *urb) { struct usb_serial_port *port = urb->context; struct spcp8x5_private *priv = usb_get_serial_port_data(port); - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; unsigned long flags; u8 status; @@ -481,9 +480,6 @@ static void spcp8x5_process_read_urb(struct urb *urb) if (!urb->actual_length) return; - tty = tty_port_tty_get(&port->port); - if (!tty) - return; if (status & UART_STATE_TRANSIENT_MASK) { /* break takes precedence over parity, which takes precedence @@ -498,17 +494,21 @@ static void spcp8x5_process_read_urb(struct urb *urb) /* overrun is special, not associated with a char */ if (status & UART_OVERRUN_ERROR) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - - if (status & UART_DCD) - usb_serial_handle_dcd_change(port, tty, - priv->line_status & MSR_STATUS_LINE_DCD); + tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); + + if (status & UART_DCD) { + struct tty_struct *tty = tty_port_tty_get(&port->port); + if (tty) { + usb_serial_handle_dcd_change(port, tty, + priv->line_status & MSR_STATUS_LINE_DCD); + tty_kref_put(tty); + } + } } - tty_insert_flip_string_fixed_flag(tty, data, tty_flag, + tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag, urb->actual_length); - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_flip_buffer_push(&port->port); } static int spcp8x5_wait_modem_info(struct usb_serial_port *port, diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 4543ea35022..b57cf841c5b 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -506,19 +506,16 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on) { struct usb_device *dev = port->serial->dev; - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) { - /* Disable flow control */ - if (!on && - ssu100_setregister(dev, 0, UART_MCR, 0) < 0) + /* Disable flow control */ + if (!on) { + if (ssu100_setregister(dev, 0, UART_MCR, 0) < 0) dev_err(&port->dev, "error from flowcontrol urb\n"); - /* drop RTS and DTR */ - if (on) - set_mctrl(dev, TIOCM_DTR | TIOCM_RTS); - else - clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS); } - mutex_unlock(&port->serial->disc_mutex); + /* drop RTS and DTR */ + if (on) + set_mctrl(dev, TIOCM_DTR | TIOCM_RTS); + else + clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS); } static void ssu100_update_msr(struct usb_serial_port *port, u8 msr) @@ -582,8 +579,7 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr, } -static int ssu100_process_packet(struct urb *urb, - struct tty_struct *tty) +static void ssu100_process_read_urb(struct urb *urb) { struct usb_serial_port *port = urb->context; char *packet = (char *)urb->transfer_buffer; @@ -598,7 +594,8 @@ static int ssu100_process_packet(struct urb *urb, if (packet[2] == 0x00) { ssu100_update_lsr(port, packet[3], &flag); if (flag == TTY_OVERRUN) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + tty_insert_flip_char(&port->port, 0, + TTY_OVERRUN); } if (packet[2] == 0x01) ssu100_update_msr(port, packet[3]); @@ -609,34 +606,17 @@ static int ssu100_process_packet(struct urb *urb, ch = packet; if (!len) - return 0; /* status only */ + return; /* status only */ if (port->port.console && port->sysrq) { for (i = 0; i < len; i++, ch++) { if (!usb_serial_handle_sysrq_char(port, *ch)) - tty_insert_flip_char(tty, *ch, flag); + tty_insert_flip_char(&port->port, *ch, flag); } } else - tty_insert_flip_string_fixed_flag(tty, ch, flag, len); - - return len; -} - -static void ssu100_process_read_urb(struct urb *urb) -{ - struct usb_serial_port *port = urb->context; - struct tty_struct *tty; - int count; - - tty = tty_port_tty_get(&port->port); - if (!tty) - return; - - count = ssu100_process_packet(urb, tty); + tty_insert_flip_string_fixed_flag(&port->port, ch, flag, len); - if (count) - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_flip_buffer_push(&port->port); } static struct usb_serial_driver ssu100_device = { diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index 701fffa8431..be05e6caf9a 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -48,7 +48,6 @@ static void symbol_int_callback(struct urb *urb) unsigned char *data = urb->transfer_buffer; struct usb_serial_port *port = priv->port; int status = urb->status; - struct tty_struct *tty; int result; int data_length; @@ -82,12 +81,8 @@ static void symbol_int_callback(struct urb *urb) * we pretty much just ignore the size and send everything * else to the tty layer. */ - tty = tty_port_tty_get(&port->port); - if (tty) { - tty_insert_flip_string(tty, &data[1], data_length); - tty_flip_buffer_push(tty); - tty_kref_put(tty); - } + tty_insert_flip_string(&port->port, &data[1], data_length); + tty_flip_buffer_push(&port->port); } else { dev_dbg(&priv->udev->dev, "Improper amount of data received from the device, " diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index f2530d2ef3c..39cb9b807c3 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -121,8 +121,8 @@ static void ti_interrupt_callback(struct urb *urb); static void ti_bulk_in_callback(struct urb *urb); static void ti_bulk_out_callback(struct urb *urb); -static void ti_recv(struct device *dev, struct tty_struct *tty, - unsigned char *data, int length); +static void ti_recv(struct usb_serial_port *port, unsigned char *data, + int length); static void ti_send(struct ti_port *tport); static int ti_set_mcr(struct ti_port *tport, unsigned int mcr); static int ti_get_lsr(struct ti_port *tport); @@ -1118,7 +1118,6 @@ static void ti_bulk_in_callback(struct urb *urb) struct device *dev = &urb->dev->dev; int status = urb->status; int retval = 0; - struct tty_struct *tty; switch (status) { case 0: @@ -1145,24 +1144,18 @@ static void ti_bulk_in_callback(struct urb *urb) return; } - tty = tty_port_tty_get(&port->port); - if (tty) { - if (urb->actual_length) { - usb_serial_debug_data(dev, __func__, urb->actual_length, - urb->transfer_buffer); + if (urb->actual_length) { + usb_serial_debug_data(dev, __func__, urb->actual_length, + urb->transfer_buffer); - if (!tport->tp_is_open) - dev_dbg(dev, "%s - port closed, dropping data\n", - __func__); - else - ti_recv(&urb->dev->dev, tty, - urb->transfer_buffer, - urb->actual_length); - spin_lock(&tport->tp_lock); - tport->tp_icount.rx += urb->actual_length; - spin_unlock(&tport->tp_lock); - } - tty_kref_put(tty); + if (!tport->tp_is_open) + dev_dbg(dev, "%s - port closed, dropping data\n", + __func__); + else + ti_recv(port, urb->transfer_buffer, urb->actual_length); + spin_lock(&tport->tp_lock); + tport->tp_icount.rx += urb->actual_length; + spin_unlock(&tport->tp_lock); } exit: @@ -1210,24 +1203,23 @@ static void ti_bulk_out_callback(struct urb *urb) } -static void ti_recv(struct device *dev, struct tty_struct *tty, - unsigned char *data, int length) +static void ti_recv(struct usb_serial_port *port, unsigned char *data, + int length) { int cnt; do { - cnt = tty_insert_flip_string(tty, data, length); + cnt = tty_insert_flip_string(&port->port, data, length); if (cnt < length) { - dev_err(dev, "%s - dropping data, %d bytes lost\n", + dev_err(&port->dev, "%s - dropping data, %d bytes lost\n", __func__, length - cnt); if (cnt == 0) break; } - tty_flip_buffer_push(tty); + tty_flip_buffer_push(&port->port); data += cnt; length -= cnt; } while (length > 0); - } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 64bda135ba7..a19ed74d770 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -361,15 +361,21 @@ static int serial_write_room(struct tty_struct *tty) static int serial_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; + struct usb_serial *serial = port->serial; + int count = 0; dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + mutex_lock(&serial->disc_mutex); /* if the device was unplugged then any remaining characters fell out of the connector ;) */ - if (port->serial->disconnected) - return 0; - /* pass on to the driver specific version of this function */ - return port->serial->type->chars_in_buffer(tty); + if (serial->disconnected) + count = 0; + else + count = serial->type->chars_in_buffer(tty); + mutex_unlock(&serial->disc_mutex); + + return count; } static void serial_throttle(struct tty_struct *tty) @@ -688,10 +694,20 @@ static int serial_carrier_raised(struct tty_port *port) static void serial_dtr_rts(struct tty_port *port, int on) { struct usb_serial_port *p = container_of(port, struct usb_serial_port, port); - struct usb_serial_driver *drv = p->serial->type; + struct usb_serial *serial = p->serial; + struct usb_serial_driver *drv = serial->type; - if (drv->dtr_rts) + if (!drv->dtr_rts) + return; + /* + * Work-around bug in the tty-layer which can result in dtr_rts + * being called after a disconnect (and tty_unregister_device + * has returned). Remove once bug has been squashed. + */ + mutex_lock(&serial->disc_mutex); + if (!serial->disconnected) drv->dtr_rts(p, on); + mutex_unlock(&serial->disc_mutex); } static const struct tty_port_operations serial_port_ops = { diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 01c94aada56..571965aa1cc 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -38,7 +38,6 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on) { - struct usb_serial *serial = port->serial; struct usb_wwan_port_private *portdata; struct usb_wwan_intf_private *intfdata; @@ -48,12 +47,11 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on) return; portdata = usb_get_serial_port_data(port); - mutex_lock(&serial->disc_mutex); + /* FIXME: locking */ portdata->rts_state = on; portdata->dtr_state = on; - if (serial->dev) - intfdata->send_setup(port); - mutex_unlock(&serial->disc_mutex); + + intfdata->send_setup(port); } EXPORT_SYMBOL(usb_wwan_dtr_rts); @@ -275,7 +273,6 @@ static void usb_wwan_indat_callback(struct urb *urb) int err; int endpoint; struct usb_serial_port *port; - struct tty_struct *tty; struct device *dev; unsigned char *data = urb->transfer_buffer; int status = urb->status; @@ -288,16 +285,12 @@ static void usb_wwan_indat_callback(struct urb *urb) dev_dbg(dev, "%s: nonzero status: %d on endpoint %02x.\n", __func__, status, endpoint); } else { - tty = tty_port_tty_get(&port->port); - if (tty) { - if (urb->actual_length) { - tty_insert_flip_string(tty, data, - urb->actual_length); - tty_flip_buffer_push(tty); - } else - dev_dbg(dev, "%s: empty read urb received\n", __func__); - tty_kref_put(tty); - } + if (urb->actual_length) { + tty_insert_flip_string(&port->port, data, + urb->actual_length); + tty_flip_buffer_push(&port->port); + } else + dev_dbg(dev, "%s: empty read urb received\n", __func__); /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); diff --git a/drivers/usb/serial/xsens_mt.c b/drivers/usb/serial/xsens_mt.c new file mode 100644 index 00000000000..1d5798d891b --- /dev/null +++ b/drivers/usb/serial/xsens_mt.c @@ -0,0 +1,86 @@ +/* + * Xsens MT USB driver + * + * Copyright (C) 2013 Xsens <info@xsens.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/tty.h> +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/usb/serial.h> +#include <linux/uaccess.h> + +#define XSENS_VID 0x2639 + +#define MTi_10_IMU_PID 0x0001 +#define MTi_20_VRU_PID 0x0002 +#define MTi_30_AHRS_PID 0x0003 + +#define MTi_100_IMU_PID 0x0011 +#define MTi_200_VRU_PID 0x0012 +#define MTi_300_AHRS_PID 0x0013 + +#define MTi_G_700_GPS_INS_PID 0x0017 + +static const struct usb_device_id id_table[] = { + { USB_DEVICE(XSENS_VID, MTi_10_IMU_PID) }, + { USB_DEVICE(XSENS_VID, MTi_20_VRU_PID) }, + { USB_DEVICE(XSENS_VID, MTi_30_AHRS_PID) }, + + { USB_DEVICE(XSENS_VID, MTi_100_IMU_PID) }, + { USB_DEVICE(XSENS_VID, MTi_200_VRU_PID) }, + { USB_DEVICE(XSENS_VID, MTi_300_AHRS_PID) }, + + { USB_DEVICE(XSENS_VID, MTi_G_700_GPS_INS_PID) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +static int has_required_endpoints(const struct usb_host_interface *interface) +{ + __u8 i; + int has_bulk_in = 0; + int has_bulk_out = 0; + + for (i = 0; i < interface->desc.bNumEndpoints; ++i) { + if (usb_endpoint_is_bulk_in(&interface->endpoint[i].desc)) + has_bulk_in = 1; + else if (usb_endpoint_is_bulk_out(&interface->endpoint[i].desc)) + has_bulk_out = 1; + } + + return has_bulk_in && has_bulk_out; +} + +static int xsens_mt_probe(struct usb_serial *serial, + const struct usb_device_id *id) +{ + if (!has_required_endpoints(serial->interface->cur_altsetting)) + return -ENODEV; + return 0; +} + +static struct usb_serial_driver xsens_mt_device = { + .driver = { + .owner = THIS_MODULE, + .name = "xsens_mt", + }, + .id_table = id_table, + .num_ports = 1, + + .probe = xsens_mt_probe, +}; + +static struct usb_serial_driver * const serial_drivers[] = { + &xsens_mt_device, NULL +}; + +module_usb_serial_driver(serial_drivers, id_table); + +MODULE_LICENSE("GPL"); |