diff options
Diffstat (limited to 'drivers/usb/serial')
53 files changed, 1024 insertions, 655 deletions
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index c480ea4..c78b255 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -472,6 +472,17 @@ config USB_SERIAL_OTI6858 To compile this driver as a module, choose M here: the module will be called oti6858. +config USB_SERIAL_QCAUX + tristate "USB Qualcomm Auxiliary Serial Port Driver" + ---help--- + Say Y here if you want to use the auxiliary serial ports provided + by many modems based on Qualcomm chipsets. These ports often use + a proprietary protocol called DM and cannot be used for AT- or + PPP-based communication. + + To compile this driver as a module, choose M here: the + module will be called moto_modem. If unsure, choose N. + config USB_SERIAL_QUALCOMM tristate "USB Qualcomm Serial modem" help @@ -600,6 +611,14 @@ config USB_SERIAL_OPTICON To compile this driver as a module, choose M here: the module will be called opticon. +config USB_SERIAL_VIVOPAY_SERIAL + tristate "USB ViVOpay serial interface driver" + help + Say Y here if you want to use a ViVOtech ViVOpay USB device. + + To compile this driver as a module, choose M here: the + module will be called vivopay-serial. + config USB_SERIAL_DEBUG tristate "USB Debugging Device" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 66619be..83c9e43 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_USB_SERIAL_OPTICON) += opticon.o obj-$(CONFIG_USB_SERIAL_OPTION) += option.o obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o +obj-$(CONFIG_USB_SERIAL_QCAUX) += qcaux.o obj-$(CONFIG_USB_SERIAL_QUALCOMM) += qcserial.o obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o @@ -55,4 +56,5 @@ obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o 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 diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index b10ac84..365db10 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -78,7 +78,7 @@ static int debug; #define DRIVER_DESC "AIRcable USB Driver" /* ID table that will be registered with USB core */ -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(AIRCABLE_VID, AIRCABLE_USB_PID) }, { }, }; @@ -468,10 +468,6 @@ static void aircable_read_bulk_callback(struct urb *urb) if (status) { dbg("%s - urb status = %d", __func__, status); - if (!port->port.count) { - dbg("%s - port is closed, exiting.", __func__); - return; - } if (status == -EPROTO) { dbg("%s - caught -EPROTO, resubmitting the urb", __func__); @@ -530,23 +526,19 @@ static void aircable_read_bulk_callback(struct urb *urb) } tty_kref_put(tty); - /* Schedule the next read _if_ we are still open */ - if (port->port.count) { - usb_fill_bulk_urb(port->read_urb, port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, - port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - aircable_read_bulk_callback, port); - - result = usb_submit_urb(urb, GFP_ATOMIC); - if (result) - dev_err(&urb->dev->dev, - "%s - failed resubmitting read urb, error %d\n", - __func__, result); - } - - return; + /* Schedule the next read */ + usb_fill_bulk_urb(port->read_urb, port->serial->dev, + usb_rcvbulkpipe(port->serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + aircable_read_bulk_callback, port); + + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result && result != -EPERM) + dev_err(&urb->dev->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); } /* Based on ftdi_sio.c throttle */ diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index a9c2dec..547c944 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -50,7 +50,7 @@ static int debug; /* usb timeout of 1 second */ #define ARK_TIMEOUT (1*HZ) -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(0x6547, 0x0232) }, { USB_DEVICE(0x18ec, 0x3118) }, /* USB to IrDA adapter */ { }, @@ -733,7 +733,6 @@ static void ark3116_read_bulk_callback(struct urb *urb) tty = tty_port_tty_get(&port->port); if (tty) { - tty_buffer_request_room(tty, urb->actual_length + 1); /* overrun is special, not associated with a char */ if (unlikely(lsr & UART_LSR_OE)) tty_insert_flip_char(tty, 0, TTY_OVERRUN); diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index a0467bc..1295e44 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -103,7 +103,7 @@ static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); -static struct usb_device_id id_table_combined [] = { +static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(BELKIN_SA_VID, BELKIN_SA_PID) }, { USB_DEVICE(BELKIN_OLD_VID, BELKIN_OLD_PID) }, { USB_DEVICE(PERACOM_VID, PERACOM_PID) }, diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 59eff72..9f4fed1 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -22,6 +22,7 @@ #include <linux/usb.h> #include <linux/usb/serial.h> #include <linux/serial.h> +#include <asm/unaligned.h> #define DEFAULT_BAUD_RATE 9600 #define DEFAULT_TIMEOUT 1000 @@ -70,7 +71,7 @@ static int debug; -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(0x4348, 0x5523) }, { USB_DEVICE(0x1a86, 0x7523) }, { }, @@ -392,16 +393,22 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state) struct usb_serial_port *port = tty->driver_data; int r; uint16_t reg_contents; - uint8_t break_reg[2]; + uint8_t *break_reg; dbg("%s()", __func__); + break_reg = kmalloc(2, GFP_KERNEL); + if (!break_reg) { + dev_err(&port->dev, "%s - kmalloc failed\n", __func__); + return; + } + r = ch341_control_in(port->serial->dev, CH341_REQ_READ_REG, - ch341_break_reg, 0, break_reg, sizeof(break_reg)); + ch341_break_reg, 0, break_reg, 2); if (r < 0) { - printk(KERN_WARNING "%s: USB control read error whilst getting" - " break register contents.\n", __FILE__); - return; + dev_err(&port->dev, "%s - USB control read error (%d)\n", + __func__, r); + goto out; } dbg("%s - initial ch341 break register contents - reg1: %x, reg2: %x", __func__, break_reg[0], break_reg[1]); @@ -416,12 +423,14 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state) } dbg("%s - New ch341 break register contents - reg1: %x, reg2: %x", __func__, break_reg[0], break_reg[1]); - reg_contents = (uint16_t)break_reg[0] | ((uint16_t)break_reg[1] << 8); + reg_contents = get_unaligned_le16(break_reg); r = ch341_control_out(port->serial->dev, CH341_REQ_WRITE_REG, ch341_break_reg, reg_contents); if (r < 0) - printk(KERN_WARNING "%s: USB control write error whilst setting" - " break register contents.\n", __FILE__); + dev_err(&port->dev, "%s - USB control write error (%d)\n", + __func__, r); +out: + kfree(break_reg); } static int ch341_tiocmset(struct tty_struct *tty, struct file *file, diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index bd254ec..507382b 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -55,7 +55,7 @@ static int cp210x_carrier_raised(struct usb_serial_port *p); static int debug; -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ { USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */ @@ -91,11 +91,12 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ + { USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */ { USB_DEVICE(0x10C4, 0x81F2) }, /* C1007 HF band RFID controller */ { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demostration module */ - { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ + { USB_DEVICE(0x10C4, 0x8293) }, /* Telegesys ETRX2USB */ { USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */ { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ { USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */ @@ -612,7 +613,7 @@ static void cp210x_set_termios(struct tty_struct *tty, baud); if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV, ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { - dbg("Baud rate requested not supported by device\n"); + dbg("Baud rate requested not supported by device"); baud = tty_termios_baud_rate(old_termios); } } diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index b0f6402..f744ab7 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -70,7 +70,7 @@ static void cyberjack_read_int_callback(struct urb *urb); static void cyberjack_read_bulk_callback(struct urb *urb); static void cyberjack_write_bulk_callback(struct urb *urb); -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(CYBERJACK_VENDOR_ID, CYBERJACK_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -391,11 +391,10 @@ static void cyberjack_read_bulk_callback(struct urb *urb) tty = tty_port_tty_get(&port->port); if (!tty) { - dbg("%s - ignoring since device not open\n", __func__); + dbg("%s - ignoring since device not open", __func__); return; } if (urb->actual_length) { - tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index a591ebe..e23c779 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -66,17 +66,15 @@ #include <linux/serial.h> #include <linux/delay.h> #include <linux/uaccess.h> +#include <asm/unaligned.h> #include "cypress_m8.h" -#ifdef CONFIG_USB_SERIAL_DEBUG - static int debug = 1; -#else - static int debug; -#endif +static int debug; static int stats; static int interval; +static int unstable_bauds; /* * Version Information @@ -89,24 +87,24 @@ static int interval; #define CYPRESS_BUF_SIZE 1024 #define CYPRESS_CLOSING_WAIT (30*HZ) -static struct usb_device_id id_table_earthmate [] = { +static const struct usb_device_id id_table_earthmate[] = { { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) }, { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) }, { } /* Terminating entry */ }; -static struct usb_device_id id_table_cyphidcomrs232 [] = { +static const struct usb_device_id id_table_cyphidcomrs232[] = { { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) }, { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) }, { } /* Terminating entry */ }; -static struct usb_device_id id_table_nokiaca42v2 [] = { +static const struct usb_device_id id_table_nokiaca42v2[] = { { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) }, { } /* Terminating entry */ }; -static struct usb_device_id id_table_combined [] = { +static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) }, { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) }, { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) }, @@ -154,7 +152,7 @@ struct cypress_private { int isthrottled; /* if throttled, discard reads */ wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */ char prev_status, diff_status; /* used for TIOCMIWAIT */ - /* we pass a pointer to this as the arguement sent to + /* we pass a pointer to this as the argument sent to cypress_set_termios old_termios */ struct ktermios tmp_termios; /* stores the old termios settings */ }; @@ -295,6 +293,9 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate) struct cypress_private *priv; priv = usb_get_serial_port_data(port); + if (unstable_bauds) + return new_rate; + /* * The general purpose firmware for the Cypress M8 allows for * a maximum speed of 57600bps (I have no idea whether DeLorme @@ -344,7 +345,8 @@ static int cypress_serial_control(struct tty_struct *tty, { int new_baudrate = 0, retval = 0, tries = 0; struct cypress_private *priv; - __u8 feature_buffer[5]; + u8 *feature_buffer; + const unsigned int feature_len = 5; unsigned long flags; dbg("%s", __func__); @@ -354,17 +356,18 @@ static int cypress_serial_control(struct tty_struct *tty, if (!priv->comm_is_ok) return -ENODEV; + feature_buffer = kcalloc(feature_len, sizeof(u8), GFP_KERNEL); + if (!feature_buffer) + return -ENOMEM; + switch (cypress_request_type) { case CYPRESS_SET_CONFIG: - new_baudrate = priv->baud_rate; /* 0 means 'Hang up' so doesn't change the true bit rate */ - if (baud_rate == 0) - new_baudrate = priv->baud_rate; - /* Change of speed ? */ - else if (baud_rate != priv->baud_rate) { + new_baudrate = priv->baud_rate; + if (baud_rate && baud_rate != priv->baud_rate) { dbg("%s - baud rate is changing", __func__); retval = analyze_baud_rate(port, baud_rate); - if (retval >= 0) { + if (retval >= 0) { new_baudrate = retval; dbg("%s - New baud rate set to %d", __func__, new_baudrate); @@ -373,9 +376,8 @@ static int cypress_serial_control(struct tty_struct *tty, dbg("%s - baud rate is being sent as %d", __func__, new_baudrate); - memset(feature_buffer, 0, sizeof(feature_buffer)); /* fill the feature_buffer with new configuration */ - *((u_int32_t *)feature_buffer) = new_baudrate; + put_unaligned_le32(new_baudrate, feature_buffer); feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */ /* 1 bit gap */ feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */ @@ -397,15 +399,15 @@ static int cypress_serial_control(struct tty_struct *tty, HID_REQ_SET_REPORT, USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS, 0x0300, 0, feature_buffer, - sizeof(feature_buffer), 500); + feature_len, 500); if (tries++ >= 3) break; - } while (retval != sizeof(feature_buffer) && + } while (retval != feature_len && retval != -ENODEV); - if (retval != sizeof(feature_buffer)) { + if (retval != feature_len) { dev_err(&port->dev, "%s - failed sending serial " "line settings - %d\n", __func__, retval); cypress_set_dead(port); @@ -425,43 +427,42 @@ static int cypress_serial_control(struct tty_struct *tty, /* Not implemented for this device, and if we try to do it we're likely to crash the hardware. */ - return -ENOTTY; + retval = -ENOTTY; + goto out; } dbg("%s - retreiving serial line settings", __func__); - /* set initial values in feature buffer */ - memset(feature_buffer, 0, sizeof(feature_buffer)); - do { retval = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), HID_REQ_GET_REPORT, USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS, 0x0300, 0, feature_buffer, - sizeof(feature_buffer), 500); + feature_len, 500); if (tries++ >= 3) break; - } while (retval != sizeof(feature_buffer) + } while (retval != feature_len && retval != -ENODEV); - if (retval != sizeof(feature_buffer)) { + if (retval != feature_len) { dev_err(&port->dev, "%s - failed to retrieve serial " "line settings - %d\n", __func__, retval); cypress_set_dead(port); - return retval; + goto out; } else { spin_lock_irqsave(&priv->lock, flags); /* store the config in one byte, and later use bit masks to check values */ priv->current_config = feature_buffer[4]; - priv->baud_rate = *((u_int32_t *)feature_buffer); + priv->baud_rate = get_unaligned_le32(feature_buffer); spin_unlock_irqrestore(&priv->lock, flags); } } spin_lock_irqsave(&priv->lock, flags); ++priv->cmd_count; spin_unlock_irqrestore(&priv->lock, flags); - +out: + kfree(feature_buffer); return retval; } /* cypress_serial_control */ @@ -690,7 +691,6 @@ static void cypress_dtr_rts(struct usb_serial_port *port, int on) { struct cypress_private *priv = usb_get_serial_port_data(port); /* drop dtr and rts */ - priv = usb_get_serial_port_data(port); spin_lock_irq(&priv->lock); if (on == 0) priv->line_control = 0; @@ -1307,13 +1307,9 @@ 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)) { - bytes = tty_buffer_request_room(tty, bytes); - for (; i < bytes ; ++i) { - dbg("pushing byte number %d - %d - %c", i, data[i], - data[i]); - tty_insert_flip_char(tty, data[i], tty_flag); - } + if (tty && bytes > i) { + tty_insert_flip_string_fixed_flag(tty, data + i, + bytes - i, tty_flag); tty_flip_buffer_push(tty); } @@ -1325,9 +1321,9 @@ static void cypress_read_int_callback(struct urb *urb) continue_read: tty_kref_put(tty); - /* Continue trying to always read... unless the port has closed. */ + /* Continue trying to always read */ - if (port->port.count > 0 && priv->comm_is_ok) { + if (priv->comm_is_ok) { usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev, usb_rcvintpipe(port->serial->dev, port->interrupt_in_endpointAddress), @@ -1336,7 +1332,7 @@ continue_read: cypress_read_int_callback, port, priv->read_urb_interval); result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); - if (result) { + if (result && result != -EPERM) { dev_err(&urb->dev->dev, "%s - failed resubmitting " "read urb, error %d\n", __func__, result); @@ -1650,3 +1646,5 @@ module_param(stats, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(stats, "Enable statistics or not"); module_param(interval, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(interval, "Overrides interrupt interval"); +module_param(unstable_bauds, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(unstable_bauds, "Allow unstable baud rates"); diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 68e80be..68b0aa5 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -470,18 +470,18 @@ static int digi_read_oob_callback(struct urb *urb); static int debug; -static struct usb_device_id id_table_combined [] = { +static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(DIGI_VENDOR_ID, DIGI_2_ID) }, { USB_DEVICE(DIGI_VENDOR_ID, DIGI_4_ID) }, { } /* Terminating entry */ }; -static struct usb_device_id id_table_2 [] = { +static const struct usb_device_id id_table_2[] = { { USB_DEVICE(DIGI_VENDOR_ID, DIGI_2_ID) }, { } /* Terminating entry */ }; -static struct usb_device_id id_table_4 [] = { +static const struct usb_device_id id_table_4[] = { { USB_DEVICE(DIGI_VENDOR_ID, DIGI_4_ID) }, { } /* Terminating entry */ }; @@ -1262,10 +1262,10 @@ static void digi_write_bulk_callback(struct urb *urb) return; } - /* try to send any buffered data on this port, if it is open */ + /* try to send any buffered data on this port */ spin_lock(&priv->dp_port_lock); priv->dp_write_urb_in_use = 0; - if (port->port.count && priv->dp_out_buf_len > 0) { + if (priv->dp_out_buf_len > 0) { *((unsigned char *)(port->write_urb->transfer_buffer)) = (unsigned char)DIGI_CMD_SEND_DATA; *((unsigned char *)(port->write_urb->transfer_buffer) + 1) @@ -1288,7 +1288,7 @@ static void digi_write_bulk_callback(struct urb *urb) schedule_work(&priv->dp_wakeup_work); spin_unlock(&priv->dp_port_lock); - if (ret) + if (ret && ret != -EPERM) dev_err(&port->dev, "%s: usb_submit_urb failed, ret=%d, port=%d\n", __func__, ret, priv->dp_port_num); @@ -1353,8 +1353,7 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port) struct digi_port *priv = usb_get_serial_port_data(port); struct ktermios not_termios; - dbg("digi_open: TOP: port=%d, open_count=%d", - priv->dp_port_num, port->port.count); + dbg("digi_open: TOP: port=%d", priv->dp_port_num); /* be sure the device is started up */ if (digi_startup_device(port->serial) != 0) @@ -1393,8 +1392,7 @@ static void digi_close(struct usb_serial_port *port) unsigned char buf[32]; struct digi_port *priv = usb_get_serial_port_data(port); - dbg("digi_close: TOP: port=%d, open_count=%d", - priv->dp_port_num, port->port.count); + dbg("digi_close: TOP: port=%d", priv->dp_port_num); mutex_lock(&port->serial->disc_mutex); /* if disconnected, just clear flags */ @@ -1629,7 +1627,7 @@ static void digi_read_bulk_callback(struct urb *urb) /* continue read */ urb->dev = port->serial->dev; ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret != 0) { + if (ret != 0 && ret != -EPERM) { dev_err(&port->dev, "%s: failed resubmitting urb, ret=%d, port=%d\n", __func__, ret, priv->dp_port_num); @@ -1658,12 +1656,11 @@ static int digi_read_inb_callback(struct urb *urb) int port_status = ((unsigned char *)urb->transfer_buffer)[2]; unsigned char *data = ((unsigned char *)urb->transfer_buffer) + 3; int flag, throttled; - int i; int status = urb->status; /* do not process callbacks on closed ports */ /* but do continue the read chain */ - if (port->port.count == 0) + if (urb->status == -ENOENT) return 0; /* short/multiple packet check */ @@ -1705,17 +1702,9 @@ static int digi_read_inb_callback(struct urb *urb) /* data length is len-1 (one byte of len is port_status) */ --len; - - len = tty_buffer_request_room(tty, len); if (len > 0) { - /* Hot path */ - if (flag == TTY_NORMAL) - tty_insert_flip_string(tty, data, len); - else { - for (i = 0; i < len; i++) - tty_insert_flip_char(tty, - data[i], flag); - } + tty_insert_flip_string_fixed_flag(tty, data, len, + flag); tty_flip_buffer_push(tty); } } @@ -1776,8 +1765,7 @@ static int digi_read_oob_callback(struct urb *urb) tty = tty_port_tty_get(&port->port); rts = 0; - if (port->port.count) - rts = tty->termios->c_cflag & CRTSCTS; + rts = tty->termios->c_cflag & CRTSCTS; if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) { spin_lock(&priv->dp_port_lock); diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 7dd0e3e..5f740a1 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -93,7 +93,7 @@ static void empeg_init_termios(struct tty_struct *tty); static void empeg_write_bulk_callback(struct urb *urb); static void empeg_read_bulk_callback(struct urb *urb); -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(EMPEG_VENDOR_ID, EMPEG_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -346,7 +346,6 @@ static void empeg_read_bulk_callback(struct urb *urb) tty = tty_port_tty_get(&port->port); if (urb->actual_length) { - tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); bytes_in += urb->actual_length; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 7638828..6af0dfa 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -33,12 +33,12 @@ #include <linux/errno.h> #include <linux/init.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <linux/tty.h> #include <linux/tty_driver.h> #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/spinlock.h> +#include <linux/mutex.h> #include <linux/uaccess.h> #include <linux/usb.h> #include <linux/serial.h> @@ -88,10 +88,10 @@ struct ftdi_private { unsigned int latency; /* latency setting in use */ spinlock_t tx_lock; /* spinlock for transmit state */ - unsigned long tx_bytes; unsigned long tx_outstanding_bytes; unsigned long tx_outstanding_urbs; unsigned short max_packet_size; + struct mutex cfg_lock; /* Avoid mess by parallel calls of config ioctl() */ }; /* struct ftdi_sio_quirk is used by devices requiring special attention. */ @@ -614,6 +614,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_OCEANIC_PID) }, { USB_DEVICE(TTI_VID, TTI_QL355P_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, + { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, @@ -737,6 +738,10 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) }, { USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) }, + { USB_DEVICE(FTDI_VID, MJSG_GENERIC_PID) }, + { USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) }, + { USB_DEVICE(FTDI_VID, MJSG_HD_RADIO_PID) }, + { USB_DEVICE(FTDI_VID, MJSG_XM_RADIO_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; @@ -812,7 +817,7 @@ static struct usb_serial_driver ftdi_sio_device = { .name = "ftdi_sio", }, .description = "FTDI USB Serial Device", - .usb_driver = &ftdi_driver , + .usb_driver = &ftdi_driver, .id_table = id_table_combined, .num_ports = 1, .probe = ftdi_sio_probe, @@ -828,8 +833,8 @@ static struct usb_serial_driver ftdi_sio_device = { .chars_in_buffer = ftdi_chars_in_buffer, .read_bulk_callback = ftdi_read_bulk_callback, .write_bulk_callback = ftdi_write_bulk_callback, - .tiocmget = ftdi_tiocmget, - .tiocmset = ftdi_tiocmset, + .tiocmget = ftdi_tiocmget, + .tiocmset = ftdi_tiocmset, .ioctl = ftdi_ioctl, .set_termios = ftdi_set_termios, .break_ctl = ftdi_break_ctl, @@ -935,7 +940,6 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned int clear) { struct ftdi_private *priv = usb_get_serial_port_data(port); - char *buf; unsigned urb_value; int rv; @@ -944,10 +948,6 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, return 0; /* no change */ } - buf = kmalloc(1, GFP_NOIO); - if (!buf) - return -ENOMEM; - clear &= ~set; /* 'set' takes precedence over 'clear' */ urb_value = 0; if (clear & TIOCM_DTR) @@ -963,9 +963,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, urb_value, priv->interface, - buf, 0, WDR_TIMEOUT); - - kfree(buf); + NULL, 0, WDR_TIMEOUT); if (rv < 0) { dbg("%s Error from MODEM_CTRL urb: DTR %s, RTS %s", __func__, @@ -1124,16 +1122,11 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); - char *buf; __u16 urb_value; __u16 urb_index; __u32 urb_index_value; int rv; - buf = kmalloc(1, GFP_NOIO); - if (!buf) - return -ENOMEM; - urb_index_value = get_ftdi_divisor(tty, port); urb_value = (__u16)urb_index_value; urb_index = (__u16)(urb_index_value >> 16); @@ -1146,9 +1139,7 @@ static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) FTDI_SIO_SET_BAUDRATE_REQUEST, FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, urb_value, urb_index, - buf, 0, WDR_SHORT_TIMEOUT); - - kfree(buf); + NULL, 0, WDR_SHORT_TIMEOUT); return rv; } @@ -1156,8 +1147,7 @@ static int write_latency_timer(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); struct usb_device *udev = port->serial->dev; - char buf[1]; - int rv = 0; + int rv; int l = priv->latency; if (priv->flags & ASYNC_LOW_LATENCY) @@ -1170,8 +1160,7 @@ static int write_latency_timer(struct usb_serial_port *port) FTDI_SIO_SET_LATENCY_TIMER_REQUEST, FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, l, priv->interface, - buf, 0, WDR_TIMEOUT); - + NULL, 0, WDR_TIMEOUT); if (rv < 0) dev_err(&port->dev, "Unable to write latency timer: %i\n", rv); return rv; @@ -1181,24 +1170,29 @@ static int read_latency_timer(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); struct usb_device *udev = port->serial->dev; - unsigned short latency = 0; - int rv = 0; - + unsigned char *buf; + int rv; dbg("%s", __func__); + buf = kmalloc(1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + rv = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), FTDI_SIO_GET_LATENCY_TIMER_REQUEST, FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, 0, priv->interface, - (char *) &latency, 1, WDR_TIMEOUT); - - if (rv < 0) { + buf, 1, WDR_TIMEOUT); + if (rv < 0) dev_err(&port->dev, "Unable to read latency timer: %i\n", rv); - return -EIO; - } - return latency; + else + priv->latency = buf[0]; + + kfree(buf); + + return rv; } static int get_serial_info(struct usb_serial_port *port, @@ -1229,7 +1223,7 @@ static int set_serial_info(struct tty_struct *tty, if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) return -EFAULT; - lock_kernel(); + mutex_lock(&priv->cfg_lock); old_priv = *priv; /* Do error checking and permission checking */ @@ -1237,7 +1231,7 @@ static int set_serial_info(struct tty_struct *tty, if (!capable(CAP_SYS_ADMIN)) { if (((new_serial.flags & ~ASYNC_USR_MASK) != (priv->flags & ~ASYNC_USR_MASK))) { - unlock_kernel(); + mutex_unlock(&priv->cfg_lock); return -EPERM; } priv->flags = ((priv->flags & ~ASYNC_USR_MASK) | @@ -1248,7 +1242,7 @@ static int set_serial_info(struct tty_struct *tty, if ((new_serial.baud_base != priv->baud_base) && (new_serial.baud_base < 9600)) { - unlock_kernel(); + mutex_unlock(&priv->cfg_lock); return -EINVAL; } @@ -1278,11 +1272,11 @@ check_and_exit: (priv->flags & ASYNC_SPD_MASK)) || (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && (old_priv.custom_divisor != priv->custom_divisor))) { - unlock_kernel(); + mutex_unlock(&priv->cfg_lock); change_speed(tty, port); } else - unlock_kernel(); + mutex_unlock(&priv->cfg_lock); return 0; } /* set_serial_info */ @@ -1338,20 +1332,20 @@ static void ftdi_determine_type(struct usb_serial_port *port) __func__); } } else if (version < 0x200) { - /* Old device. Assume its the original SIO. */ + /* Old device. Assume it's the original SIO. */ priv->chip_type = SIO; priv->baud_base = 12000000 / 16; priv->write_offset = 1; } else if (version < 0x400) { - /* Assume its an FT8U232AM (or FT8U245AM) */ + /* Assume it's an FT8U232AM (or FT8U245AM) */ /* (It might be a BM because of the iSerialNumber bug, * but it will still work as an AM device.) */ priv->chip_type = FT8U232AM; } else if (version < 0x600) { - /* Assume its an FT232BM (or FT245BM) */ + /* Assume it's an FT232BM (or FT245BM) */ priv->chip_type = FT232BM; } else { - /* Assume its an FT232R */ + /* Assume it's an FT232R */ priv->chip_type = FT232RL; } dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]); @@ -1371,7 +1365,7 @@ static void ftdi_set_max_packet_size(struct usb_serial_port *port) struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc; unsigned num_endpoints; - int i = 0; + int i; num_endpoints = interface->cur_altsetting->desc.bNumEndpoints; dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints); @@ -1423,7 +1417,7 @@ static ssize_t store_latency_timer(struct device *dev, struct usb_serial_port *port = to_usb_serial_port(dev); struct ftdi_private *priv = usb_get_serial_port_data(port); int v = simple_strtoul(valbuf, NULL, 10); - int rv = 0; + int rv; priv->latency = v; rv = write_latency_timer(port); @@ -1440,9 +1434,8 @@ static ssize_t store_event_char(struct device *dev, struct usb_serial_port *port = to_usb_serial_port(dev); struct ftdi_private *priv = usb_get_serial_port_data(port); struct usb_device *udev = port->serial->dev; - char buf[1]; int v = simple_strtoul(valbuf, NULL, 10); - int rv = 0; + int rv; dbg("%s: setting event char = %i", __func__, v); @@ -1451,8 +1444,7 @@ static ssize_t store_event_char(struct device *dev, FTDI_SIO_SET_EVENT_CHAR_REQUEST, FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE, v, priv->interface, - buf, 0, WDR_TIMEOUT); - + NULL, 0, WDR_TIMEOUT); if (rv < 0) { dbg("Unable to write event character: %i", rv); return -EIO; @@ -1551,9 +1543,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) kref_init(&priv->kref); spin_lock_init(&priv->tx_lock); + mutex_init(&priv->cfg_lock); init_waitqueue_head(&priv->delta_msr_wait); - /* This will push the characters through immediately rather - than queue a task to deliver them */ + priv->flags = ASYNC_LOW_LATENCY; if (quirk && quirk->port_probe) @@ -1585,7 +1577,8 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) ftdi_determine_type(port); ftdi_set_max_packet_size(port); - read_latency_timer(port); + if (read_latency_timer(port) < 0) + priv->latency = 16; create_sysfs_attrs(port); return 0; } @@ -1630,8 +1623,6 @@ static int ftdi_NDI_device_setup(struct usb_serial *serial) { struct usb_device *udev = serial->dev; int latency = ndi_latency_timer; - int rv = 0; - char buf[1]; if (latency == 0) latency = 1; @@ -1641,10 +1632,11 @@ static int ftdi_NDI_device_setup(struct usb_serial *serial) dbg("%s setting NDI device latency to %d", __func__, latency); dev_info(&udev->dev, "NDI device with a latency value of %d", latency); - rv = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + /* FIXME: errors are not returned */ + usb_control_msg(udev, usb_sndctrlpipe(udev, 0), FTDI_SIO_SET_LATENCY_TIMER_REQUEST, FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, - latency, 0, buf, 0, WDR_TIMEOUT); + latency, 0, NULL, 0, WDR_TIMEOUT); return 0; } @@ -1720,7 +1712,7 @@ static int ftdi_submit_read_urb(struct usb_serial_port *port, gfp_t mem_flags) urb->transfer_buffer_length, ftdi_read_bulk_callback, port); result = usb_submit_urb(urb, mem_flags); - if (result) + if (result && result != -EPERM) dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result); @@ -1732,16 +1724,10 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); unsigned long flags; - - int result = 0; - char buf[1]; /* Needed for the usb_control_msg I think */ + int result; dbg("%s", __func__); - spin_lock_irqsave(&priv->tx_lock, flags); - priv->tx_bytes = 0; - spin_unlock_irqrestore(&priv->tx_lock, flags); - write_latency_timer(port); /* No error checking for this (will get errors later anyway) */ @@ -1749,7 +1735,7 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) usb_control_msg(dev, usb_sndctrlpipe(dev, 0), FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, FTDI_SIO_RESET_SIO, - priv->interface, buf, 0, WDR_TIMEOUT); + priv->interface, NULL, 0, WDR_TIMEOUT); /* Termios defaults are set by usb_serial_init. We don't change port->tty->termios - this would lose speed settings, etc. @@ -1777,7 +1763,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) static void ftdi_dtr_rts(struct usb_serial_port *port, int on) { struct ftdi_private *priv = usb_get_serial_port_data(port); - char buf[1]; mutex_lock(&port->serial->disc_mutex); if (!port->serial->disconnected) { @@ -1786,7 +1771,7 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on) usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - 0, priv->interface, buf, 0, + 0, priv->interface, NULL, 0, WDR_TIMEOUT) < 0) { dev_err(&port->dev, "error from flowcontrol urb\n"); } @@ -1847,7 +1832,7 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, spin_lock_irqsave(&priv->tx_lock, flags); if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) { spin_unlock_irqrestore(&priv->tx_lock, flags); - dbg("%s - write limit hit\n", __func__); + dbg("%s - write limit hit", __func__); return 0; } priv->tx_outstanding_urbs++; @@ -1927,7 +1912,6 @@ static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, } else { spin_lock_irqsave(&priv->tx_lock, flags); priv->tx_outstanding_bytes += count; - priv->tx_bytes += count; spin_unlock_irqrestore(&priv->tx_lock, flags); } @@ -2154,8 +2138,7 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); - __u16 urb_value = 0; - char buf[1]; + __u16 urb_value; /* break_state = -1 to turn on break, and 0 to turn off break */ /* see drivers/char/tty_io.c to see it used */ @@ -2171,7 +2154,7 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state) FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , priv->interface, - buf, 0, WDR_TIMEOUT) < 0) { + NULL, 0, WDR_TIMEOUT) < 0) { dev_err(&port->dev, "%s FAILED to enable/disable break state " "(state was %d)\n", __func__, break_state); } @@ -2195,7 +2178,6 @@ static void ftdi_set_termios(struct tty_struct *tty, struct ktermios *termios = tty->termios; unsigned int cflag = termios->c_cflag; __u16 urb_value; /* will hold the new flags */ - char buf[1]; /* Perhaps I should dynamically alloc this? */ /* Added for xon/xoff support */ unsigned int iflag = termios->c_iflag; @@ -2246,12 +2228,10 @@ static void ftdi_set_termios(struct tty_struct *tty, } if (cflag & CSIZE) { switch (cflag & CSIZE) { - case CS5: urb_value |= 5; dbg("Setting CS5"); break; - case CS6: urb_value |= 6; dbg("Setting CS6"); break; case CS7: urb_value |= 7; dbg("Setting CS7"); break; case CS8: urb_value |= 8; dbg("Setting CS8"); break; default: - dev_err(&port->dev, "CSIZE was set but not CS5-CS8\n"); + dev_err(&port->dev, "CSIZE was set but not CS7-CS8\n"); } } @@ -2263,7 +2243,7 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , priv->interface, - buf, 0, WDR_SHORT_TIMEOUT) < 0) { + NULL, 0, WDR_SHORT_TIMEOUT) < 0) { dev_err(&port->dev, "%s FAILED to set " "databits/stopbits/parity\n", __func__); } @@ -2275,7 +2255,7 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, priv->interface, - buf, 0, WDR_TIMEOUT) < 0) { + NULL, 0, WDR_TIMEOUT) < 0) { dev_err(&port->dev, "%s error from disable flowcontrol urb\n", __func__); @@ -2301,7 +2281,7 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0 , (FTDI_SIO_RTS_CTS_HS | priv->interface), - buf, 0, WDR_TIMEOUT) < 0) { + NULL, 0, WDR_TIMEOUT) < 0) { dev_err(&port->dev, "urb failed to set to rts/cts flow control\n"); } @@ -2333,7 +2313,7 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, urb_value , (FTDI_SIO_XON_XOFF_HS | priv->interface), - buf, 0, WDR_TIMEOUT) < 0) { + NULL, 0, WDR_TIMEOUT) < 0) { dev_err(&port->dev, "urb failed to set to " "xon/xoff flow control\n"); } @@ -2347,7 +2327,7 @@ static void ftdi_set_termios(struct tty_struct *tty, FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, priv->interface, - buf, 0, WDR_TIMEOUT) < 0) { + NULL, 0, WDR_TIMEOUT) < 0) { dev_err(&port->dev, "urb failed to clear flow control\n"); } @@ -2361,21 +2341,22 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) { struct usb_serial_port *port = tty->driver_data; struct ftdi_private *priv = usb_get_serial_port_data(port); - unsigned char buf[2]; + unsigned char *buf; + int len; int ret; dbg("%s TIOCMGET", __func__); + + buf = kmalloc(2, GFP_KERNEL); + if (!buf) + return -ENOMEM; + /* + * The 8U232AM returns a two byte value (the SIO a 1 byte value) in + * the same format as the data returned from the in point. + */ switch (priv->chip_type) { case SIO: - /* Request the status from the device */ - ret = usb_control_msg(port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), - FTDI_SIO_GET_MODEM_STATUS_REQUEST, - FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, - 0, 0, - buf, 1, WDR_TIMEOUT); - if (ret < 0) - return ret; + len = 1; break; case FT8U232AM: case FT232BM: @@ -2383,27 +2364,30 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) case FT232RL: case FT2232H: case FT4232H: - /* the 8U232AM returns a two byte value (the sio is a 1 byte - value) - in the same format as the data returned from the in - point */ - ret = usb_control_msg(port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), - FTDI_SIO_GET_MODEM_STATUS_REQUEST, - FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, - 0, priv->interface, - buf, 2, WDR_TIMEOUT); - if (ret < 0) - return ret; + len = 2; break; default: - return -EFAULT; + ret = -EFAULT; + goto out; } - return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | + ret = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + FTDI_SIO_GET_MODEM_STATUS_REQUEST, + FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, + 0, priv->interface, + buf, len, WDR_TIMEOUT); + if (ret < 0) + goto out; + + ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) | priv->last_dtr_rts; +out: + kfree(buf); + return ret; } static int ftdi_tiocmset(struct tty_struct *tty, struct file *file, @@ -2508,8 +2492,7 @@ void ftdi_unthrottle(struct tty_struct *tty) port->throttled = port->throttle_req = 0; spin_unlock_irqrestore(&port->lock, flags); - /* Resubmit urb if throttled and open. */ - if (was_throttled && test_bit(ASYNCB_INITIALIZED, &port->port.flags)) + if (was_throttled) ftdi_submit_read_urb(port, GFP_KERNEL); } diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index b0e0d64..ff9bf80 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -28,13 +28,13 @@ #define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ #define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */ #define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ -#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modern status register */ +#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modem status register */ #define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ #define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ #define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */ #define FTDI_SIO_GET_LATENCY_TIMER 10 /* Get the latency timer */ -/* Interface indicies for FT2232, FT2232H and FT4232H devices*/ +/* Interface indices for FT2232, FT2232H and FT4232H devices */ #define INTERFACE_A 1 #define INTERFACE_B 2 #define INTERFACE_C 3 @@ -270,7 +270,7 @@ typedef enum { * BmRequestType: 0100 0000b * bRequest: FTDI_SIO_SET_FLOW_CTRL * wValue: Xoff/Xon - * wIndex: Protocol/Port - hIndex is protocl / lIndex is port + * wIndex: Protocol/Port - hIndex is protocol / lIndex is port * wLength: 0 * Data: None * diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index c8951ae..0727e19 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -22,7 +22,7 @@ #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ #define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */ -#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ +#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ #define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */ @@ -49,7 +49,7 @@ #define LMI_LM3S_DEVEL_BOARD_PID 0xbcd8 #define LMI_LM3S_EVAL_BOARD_PID 0xbcd9 -#define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */ +#define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmbH */ /* OpenDCC (www.opendcc.de) product id */ #define FTDI_OPENDCC_PID 0xBFD8 @@ -185,7 +185,7 @@ #define FTDI_ELV_TFD128_PID 0xE0EC /* ELV Temperatur-Feuchte-Datenlogger TFD 128 */ #define FTDI_ELV_FM3RX_PID 0xE0ED /* ELV Messwertuebertragung FM3 RX */ #define FTDI_ELV_WS777_PID 0xE0EE /* Conrad WS 777 */ -#define FTDI_ELV_EM1010PC_PID 0xE0EF /* Engery monitor EM 1010 PC */ +#define FTDI_ELV_EM1010PC_PID 0xE0EF /* Energy monitor EM 1010 PC */ #define FTDI_ELV_CSI8_PID 0xE0F0 /* Computer-Schalt-Interface (CSI 8) */ #define FTDI_ELV_EM1000DL_PID 0xE0F1 /* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */ #define FTDI_ELV_PCK100_PID 0xE0F2 /* PC-Kabeltester (PCK 100) */ @@ -212,8 +212,8 @@ * drivers, or possibly the Comedi drivers in some cases. */ #define FTDI_ELV_CLI7000_PID 0xFB59 /* Computer-Light-Interface (CLI 7000) */ #define FTDI_ELV_PPS7330_PID 0xFB5C /* Processor-Power-Supply (PPS 7330) */ -#define FTDI_ELV_TFM100_PID 0xFB5D /* Temperartur-Feuchte Messgeraet (TFM 100) */ -#define FTDI_ELV_UDF77_PID 0xFB5E /* USB DCF Funkurh (UDF 77) */ +#define FTDI_ELV_TFM100_PID 0xFB5D /* Temperatur-Feuchte-Messgeraet (TFM 100) */ +#define FTDI_ELV_UDF77_PID 0xFB5E /* USB DCF Funkuhr (UDF 77) */ #define FTDI_ELV_UIO88_PID 0xFB5F /* USB-I/O Interface (UIO 88) */ /* @@ -320,7 +320,7 @@ /* * 4N-GALAXY.DE PIDs for CAN-USB, USB-RS232, USB-RS422, USB-RS485, - * USB-TTY activ, USB-TTY passiv. Some PIDs are used by several devices + * USB-TTY aktiv, USB-TTY passiv. Some PIDs are used by several devices * and I'm not entirely sure which are used by which. */ #define FTDI_4N_GALAXY_DE_1_PID 0xF3C0 @@ -330,10 +330,10 @@ * Linx Technologies product ids */ #define LINX_SDMUSBQSS_PID 0xF448 /* Linx SDM-USB-QS-S */ -#define LINX_MASTERDEVEL2_PID 0xF449 /* Linx Master Development 2.0 */ -#define LINX_FUTURE_0_PID 0xF44A /* Linx future device */ -#define LINX_FUTURE_1_PID 0xF44B /* Linx future device */ -#define LINX_FUTURE_2_PID 0xF44C /* Linx future device */ +#define LINX_MASTERDEVEL2_PID 0xF449 /* Linx Master Development 2.0 */ +#define LINX_FUTURE_0_PID 0xF44A /* Linx future device */ +#define LINX_FUTURE_1_PID 0xF44B /* Linx future device */ +#define LINX_FUTURE_2_PID 0xF44C /* Linx future device */ /* * Oceanic product ids @@ -494,6 +494,13 @@ #define RATOC_PRODUCT_ID_USB60F 0xb020 /* + * Contec products (http://www.contec.com) + * Submitted by Daniel Sangorrin + */ +#define CONTEC_VID 0x06CE /* Vendor ID */ +#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */ + +/* * Definitions for B&B Electronics products. */ #define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */ @@ -642,7 +649,7 @@ #define FALCOM_TWIST_PID 0x0001 /* Falcom Twist USB GPRS modem */ #define FALCOM_SAMBA_PID 0x0005 /* Falcom Samba USB GPRS modem */ -/* Larsen and Brusgaard AltiTrack/USBtrack */ +/* Larsen and Brusgaard AltiTrack/USBtrack */ #define LARSENBRUSGAARD_VID 0x0FD8 #define LB_ALTITRACK_PID 0x0001 @@ -971,7 +978,7 @@ #define ALTI2_N3_PID 0x6001 /* Neptune 3 */ /* - * Dresden Elektronic Sensor Terminal Board + * Dresden Elektronik Sensor Terminal Board */ #define DE_VID 0x1cf1 /* Vendor ID */ #define STB_PID 0x0001 /* Sensor Terminal Board */ @@ -1002,3 +1009,11 @@ #define EVO_8U232AM_PID 0x02FF /* Evolution robotics RCM2 (FT232AM)*/ #define EVO_HYBRID_PID 0x0302 /* Evolution robotics RCM4 PID (FT232BM)*/ #define EVO_RCM4_PID 0x0303 /* Evolution robotics RCM4 PID */ + +/* + * MJS Gadgets HD Radio / XM Radio / Sirius Radio interfaces (using VID 0x0403) + */ +#define MJSG_GENERIC_PID 0x9378 +#define MJSG_SR_RADIO_PID 0x9379 +#define MJSG_XM_RADIO_PID 0x937A +#define MJSG_HD_RADIO_PID 0x937C diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c index d30f736..e21ce9d 100644 --- a/drivers/usb/serial/funsoft.c +++ b/drivers/usb/serial/funsoft.c @@ -18,7 +18,7 @@ static int debug; -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1404, 0xcddc) }, { }, }; diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 5ac900e..a42b29a 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -210,7 +210,7 @@ static unsigned char const PRIVATE_REQ[] -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { /* the same device id seems to be used by all usb enabled GPS devices */ { USB_DEVICE(GARMIN_VENDOR_ID, 3) }, @@ -271,7 +271,6 @@ static void send_to_tty(struct usb_serial_port *port, usb_serial_debug_data(debug, &port->dev, __func__, actual_length, data); - tty_buffer_request_room(tty, actual_length); tty_insert_flip_string(tty, data, actual_length); tty_flip_buffer_push(tty); } diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 83443d6..89fac36 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -20,6 +20,7 @@ #include <linux/usb/serial.h> #include <linux/uaccess.h> #include <linux/kfifo.h> +#include <linux/serial.h> static int debug; @@ -41,7 +42,7 @@ static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */ /* we want to look at all devices, as the vendor/product id can change * depending on the command line argument */ -static struct usb_device_id generic_serial_ids[] = { +static const struct usb_device_id generic_serial_ids[] = { {.driver_info = 42}, {} }; @@ -194,7 +195,7 @@ static int usb_serial_multi_urb_write(struct tty_struct *tty, if (port->urbs_in_flight > port->serial->type->max_in_flight_urbs) { spin_unlock_irqrestore(&port->lock, flags); - dbg("%s - write limit hit\n", __func__); + dbg("%s - write limit hit", __func__); return bwrite; } port->tx_bytes_flight += towrite; @@ -585,7 +586,7 @@ int usb_serial_generic_resume(struct usb_serial *serial) for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; - if (!port->port.count) + if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) continue; if (port->read_urb) { diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c index 4313292..8093791 100644 --- a/drivers/usb/serial/hp4x.c +++ b/drivers/usb/serial/hp4x.c @@ -29,7 +29,7 @@ #define HP_VENDOR_ID 0x03f0 #define HP49GP_PRODUCT_ID 0x0121 -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(HP_VENDOR_ID, HP49GP_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index b97960a..3ef8df0 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -364,42 +364,6 @@ static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial) release_firmware(fw); } - -/************************************************************************ - * * - * Get string descriptor from device * - * * - ************************************************************************/ -static int get_string(struct usb_device *dev, int Id, char *string, int buflen) -{ - struct usb_string_descriptor StringDesc; - struct usb_string_descriptor *pStringDesc; - - dbg("%s - USB String ID = %d", __func__, Id); - - if (!usb_get_descriptor(dev, USB_DT_STRING, Id, - &StringDesc, sizeof(StringDesc))) - return 0; - - pStringDesc = kmalloc(StringDesc.bLength, GFP_KERNEL); - if (!pStringDesc) - return 0; - - if (!usb_get_descriptor(dev, USB_DT_STRING, Id, - pStringDesc, StringDesc.bLength)) { - kfree(pStringDesc); - return 0; - } - - unicode_to_ascii(string, buflen, - pStringDesc->wData, pStringDesc->bLength/2); - - kfree(pStringDesc); - dbg("%s - USB String %s", __func__, string); - return strlen(string); -} - - #if 0 /************************************************************************ * @@ -2007,7 +1971,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, return; case IOSP_EXT_STATUS_RX_CHECK_RSP: - dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __func__, edge_serial->rxPort, byte3); + dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============", __func__, edge_serial->rxPort, byte3); /* Port->RxCheckRsp = true; */ return; } @@ -2075,7 +2039,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, break; default: - dbg("%s - Unrecognized IOSP status code %u\n", __func__, code); + dbg("%s - Unrecognized IOSP status code %u", __func__, code); break; } return; @@ -2091,18 +2055,13 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, { int cnt; - do { - cnt = tty_buffer_request_room(tty, length); - if (cnt < length) { - dev_err(dev, "%s - dropping data, %d bytes lost\n", - __func__, length - cnt); - if (cnt == 0) - break; - } - tty_insert_flip_string(tty, data, cnt); - data += cnt; - length -= cnt; - } while (length > 0); + cnt = tty_insert_flip_string(tty, data, length); + if (cnt < length) { + dev_err(dev, "%s - dropping data, %d bytes lost\n", + __func__, length - cnt); + } + data += cnt; + length -= cnt; tty_flip_buffer_push(tty); } @@ -2530,7 +2489,7 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor) *divisor = custom; - dbg("%s - Baud %d = %d\n", __func__, baudrate, custom); + dbg("%s - Baud %d = %d", __func__, baudrate, custom); return 0; } @@ -2915,7 +2874,7 @@ static void load_application_firmware(struct edgeport_serial *edge_serial) break; case EDGE_DOWNLOAD_FILE_NONE: - dbg ("No download file specified, skipping download\n"); + dbg("No download file specified, skipping download"); return; default: @@ -2997,10 +2956,12 @@ static int edge_startup(struct usb_serial *serial) usb_set_serial_data(serial, edge_serial); /* get the name for the device from the device */ - i = get_string(dev, dev->descriptor.iManufacturer, + i = usb_string(dev, dev->descriptor.iManufacturer, &edge_serial->name[0], MAX_NAME_LEN+1); + if (i < 0) + i = 0; edge_serial->name[i++] = ' '; - get_string(dev, dev->descriptor.iProduct, + usb_string(dev, dev->descriptor.iProduct, &edge_serial->name[i], MAX_NAME_LEN+2 - i); dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 9241d31..feb56a4 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -14,7 +14,7 @@ #ifndef IO_TABLES_H #define IO_TABLES_H -static struct usb_device_id edgeport_2port_id_table [] = { +static const struct usb_device_id edgeport_2port_id_table[] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_421) }, @@ -23,7 +23,7 @@ static struct usb_device_id edgeport_2port_id_table [] = { { } }; -static struct usb_device_id edgeport_4port_id_table [] = { +static const struct usb_device_id edgeport_4port_id_table[] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_RAPIDPORT_4) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4T) }, @@ -37,7 +37,7 @@ static struct usb_device_id edgeport_4port_id_table [] = { { } }; -static struct usb_device_id edgeport_8port_id_table [] = { +static const struct usb_device_id edgeport_8port_id_table[] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8I) }, @@ -47,7 +47,7 @@ static struct usb_device_id edgeport_8port_id_table [] = { { } }; -static struct usb_device_id Epic_port_id_table [] = { +static const struct usb_device_id Epic_port_id_table[] = { { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0202) }, { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0203) }, { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0310) }, @@ -60,7 +60,7 @@ static struct usb_device_id Epic_port_id_table [] = { }; /* Devices that this driver supports */ -static struct usb_device_id id_table_combined [] = { +static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_RAPIDPORT_4) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4T) }, diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index d4cc0f7..aa876f7 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -134,7 +134,7 @@ struct edgeport_serial { /* Devices that this driver supports */ -static struct usb_device_id edgeport_1port_id_table [] = { +static const struct usb_device_id edgeport_1port_id_table[] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) }, @@ -154,7 +154,7 @@ static struct usb_device_id edgeport_1port_id_table [] = { { } }; -static struct usb_device_id edgeport_2port_id_table [] = { +static const struct usb_device_id edgeport_2port_id_table[] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) }, @@ -177,7 +177,7 @@ static struct usb_device_id edgeport_2port_id_table [] = { }; /* Devices that this driver supports */ -static struct usb_device_id id_table_combined [] = { +static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) }, @@ -413,11 +413,18 @@ static int write_boot_mem(struct edgeport_serial *serial, { int status = 0; int i; - __u8 temp; + u8 *temp; /* Must do a read before write */ if (!serial->TiReadI2C) { - status = read_boot_mem(serial, 0, 1, &temp); + temp = kmalloc(1, GFP_KERNEL); + if (!temp) { + dev_err(&serial->serial->dev->dev, + "%s - out of memory\n", __func__); + return -ENOMEM; + } + status = read_boot_mem(serial, 0, 1, temp); + kfree(temp); if (status) return status; } @@ -935,37 +942,47 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev) static int i2c_type_bootmode(struct edgeport_serial *serial) { int status; - __u8 data; + u8 *data; + + data = kmalloc(1, GFP_KERNEL); + if (!data) { + dev_err(&serial->serial->dev->dev, + "%s - out of memory\n", __func__); + return -ENOMEM; + } /* Try to read type 2 */ status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ, - DTK_ADDR_SPACE_I2C_TYPE_II, 0, &data, 0x01); + DTK_ADDR_SPACE_I2C_TYPE_II, 0, data, 0x01); if (status) dbg("%s - read 2 status error = %d", __func__, status); else - dbg("%s - read 2 data = 0x%x", __func__, data); - if ((!status) && (data == UMP5152 || data == UMP3410)) { + dbg("%s - read 2 data = 0x%x", __func__, *data); + if ((!status) && (*data == UMP5152 || *data == UMP3410)) { dbg("%s - ROM_TYPE_II", __func__); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; - return 0; + goto out; } /* Try to read type 3 */ status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ, - DTK_ADDR_SPACE_I2C_TYPE_III, 0, &data, 0x01); + DTK_ADDR_SPACE_I2C_TYPE_III, 0, data, 0x01); if (status) dbg("%s - read 3 status error = %d", __func__, status); else - dbg("%s - read 2 data = 0x%x", __func__, data); - if ((!status) && (data == UMP5152 || data == UMP3410)) { + dbg("%s - read 2 data = 0x%x", __func__, *data); + if ((!status) && (*data == UMP5152 || *data == UMP3410)) { dbg("%s - ROM_TYPE_III", __func__); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III; - return 0; + goto out; } dbg("%s - Unknown", __func__); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; - return -ENODEV; + status = -ENODEV; +out: + kfree(data); + return status; } static int bulk_xfer(struct usb_serial *serial, void *buffer, @@ -1113,7 +1130,7 @@ static int download_fw(struct edgeport_serial *serial) I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc); if (start_address != 0) { struct ti_i2c_firmware_rec *firmware_version; - __u8 record; + u8 *record; dbg("%s - Found Type FIRMWARE (Type 2) record", __func__); @@ -1165,6 +1182,15 @@ static int download_fw(struct edgeport_serial *serial) OperationalMajorVersion, OperationalMinorVersion); + record = kmalloc(1, GFP_KERNEL); + if (!record) { + dev_err(dev, "%s - out of memory.\n", + __func__); + kfree(firmware_version); + kfree(rom_desc); + kfree(ti_manuf_desc); + return -ENOMEM; + } /* In order to update the I2C firmware we must * change the type 2 record to type 0xF2. This * will force the UMP to come up in Boot Mode. @@ -1177,13 +1203,14 @@ static int download_fw(struct edgeport_serial *serial) * firmware will update the record type from * 0xf2 to 0x02. */ - record = I2C_DESC_TYPE_FIRMWARE_BLANK; + *record = I2C_DESC_TYPE_FIRMWARE_BLANK; /* Change the I2C Firmware record type to 0xf2 to trigger an update */ status = write_rom(serial, start_address, - sizeof(record), &record); + sizeof(*record), record); if (status) { + kfree(record); kfree(firmware_version); kfree(rom_desc); kfree(ti_manuf_desc); @@ -1196,19 +1223,21 @@ static int download_fw(struct edgeport_serial *serial) */ status = read_rom(serial, start_address, - sizeof(record), - &record); + sizeof(*record), + record); if (status) { + kfree(record); kfree(firmware_version); kfree(rom_desc); kfree(ti_manuf_desc); return status; } - if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) { + if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) { dev_err(dev, "%s - error resetting device\n", __func__); + kfree(record); kfree(firmware_version); kfree(rom_desc); kfree(ti_manuf_desc); @@ -1226,6 +1255,7 @@ static int download_fw(struct edgeport_serial *serial) __func__, status); /* return an error on purpose. */ + kfree(record); kfree(firmware_version); kfree(rom_desc); kfree(ti_manuf_desc); @@ -1686,7 +1716,7 @@ static void edge_interrupt_callback(struct urb *urb) case TIUMP_INTERRUPT_CODE_MSR: /* MSR */ /* Copy MSR from UMP */ msr = data[1]; - dbg("%s - ===== Port %u MSR Status = %02x ======\n", + dbg("%s - ===== Port %u MSR Status = %02x ======", __func__, port_number, msr); handle_new_msr(edge_port, msr); break; @@ -1790,7 +1820,6 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, { int queued; - tty_buffer_request_room(tty, length); queued = tty_insert_flip_string(tty, data, length); if (queued < length) dev_err(dev, "%s - dropping data, %d bytes lost\n", diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index d6231c3..3fea929 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -747,7 +747,6 @@ static void ipaq_read_bulk_callback(struct urb *urb) tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { - tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); bytes_in += urb->actual_length; diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 727d323..e1d0784 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -134,7 +134,7 @@ enum { #define IPW_WANTS_TO_SEND 0x30 -static struct usb_device_id usb_ipw_ids[] = { +static const struct usb_device_id usb_ipw_ids[] = { { USB_DEVICE(IPW_VID, IPW_PID) }, { }, }; @@ -172,7 +172,6 @@ static void ipw_read_bulk_callback(struct urb *urb) tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { - tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 95d8d26..4a0f519 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -100,7 +100,7 @@ static u8 ir_baud; static u8 ir_xbof; static u8 ir_add_bof; -static struct usb_device_id ir_id_table[] = { +static const struct usb_device_id ir_id_table[] = { { USB_DEVICE(0x050f, 0x0180) }, /* KC Technology, KC-180 */ { USB_DEVICE(0x08e9, 0x0100) }, /* XTNDAccess */ { USB_DEVICE(0x09c4, 0x0011) }, /* ACTiSys ACT-IR2000U */ @@ -445,11 +445,6 @@ static void ir_read_bulk_callback(struct urb *urb) dbg("%s - port %d", __func__, port->number); - if (!port->port.count) { - dbg("%s - port closed.", __func__); - return; - } - switch (status) { case 0: /* Successful */ /* @@ -462,10 +457,8 @@ static void ir_read_bulk_callback(struct urb *urb) usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); tty = tty_port_tty_get(&port->port); - if (tty_buffer_request_room(tty, urb->actual_length - 1)) { - tty_insert_flip_string(tty, data+1, urb->actual_length - 1); - tty_flip_buffer_push(tty); - } + tty_insert_flip_string(tty, data+1, urb->actual_length - 1); + tty_flip_buffer_push(tty); tty_kref_put(tty); /* diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index e6e02b1..43f13cf 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -43,7 +43,7 @@ static int debug; #define DRIVER_VERSION "v0.11" #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" -static struct usb_device_id id_table[] = { +static const struct usb_device_id id_table[] = { {USB_DEVICE(IUU_USB_VENDOR_ID, IUU_USB_PRODUCT_ID)}, {} /* Terminating entry */ }; diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index f8c4b07..297163c 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -464,13 +464,9 @@ static void usa26_indat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; - if (port->port.count) { - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", - __func__, err); - } - return; + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) + dbg("%s - resubmit read urb failed. (%d)", __func__, err); } /* Outdat handling is common for all devices */ @@ -483,8 +479,7 @@ static void usa2x_outdat_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); dbg("%s - urb %d", __func__, urb == p_priv->out_urbs[1]); - if (port->port.count) - usb_serial_port_softint(port); + usb_serial_port_softint(port); } static void usa26_inack_callback(struct urb *urb) @@ -615,12 +610,10 @@ static void usa28_indat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; - if (port->port.count) { - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", - __func__, err); - } + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) + dbg("%s - resubmit read urb failed. (%d)", + __func__, err); p_priv->in_flip ^= 1; urb = p_priv->in_urbs[p_priv->in_flip]; @@ -856,12 +849,9 @@ static void usa49_indat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; - if (port->port.count) { - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", - __func__, err); - } + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) + dbg("%s - resubmit read urb failed. (%d)", __func__, err); } static void usa49wg_indat_callback(struct urb *urb) @@ -904,11 +894,7 @@ static void usa49wg_indat_callback(struct urb *urb) /* no error on any byte */ i++; for (x = 1; x < len ; ++x) - if (port->port.count) - tty_insert_flip_char(tty, - data[i++], 0); - else - i++; + tty_insert_flip_char(tty, data[i++], 0); } else { /* * some bytes had errors, every byte has status @@ -922,14 +908,12 @@ static void usa49wg_indat_callback(struct urb *urb) if (stat & RXERROR_PARITY) flag |= TTY_PARITY; /* XXX should handle break (0x10) */ - if (port->port.count) - tty_insert_flip_char(tty, + tty_insert_flip_char(tty, data[i+1], flag); i += 2; } } - if (port->port.count) - tty_flip_buffer_push(tty); + tty_flip_buffer_push(tty); tty_kref_put(tty); } } @@ -1013,13 +997,9 @@ static void usa90_indat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ urb->dev = port->serial->dev; - if (port->port.count) { - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", - __func__, err); - } - return; + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) + dbg("%s - resubmit read urb failed. (%d)", __func__, err); } @@ -2418,8 +2398,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, msg.portEnabled = 0; /* Sending intermediate configs */ else { - if (port->port.count) - msg.portEnabled = 1; + msg.portEnabled = 1; msg.txBreak = (p_priv->break_on); } diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 30771e5..bf3297d 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -456,7 +456,7 @@ static const struct keyspan_device_details *keyspan_devices[] = { NULL, }; -static struct usb_device_id keyspan_ids_combined[] = { +static const struct usb_device_id keyspan_ids_combined[] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_pre_product_id) }, @@ -497,7 +497,7 @@ static struct usb_driver keyspan_driver = { }; /* usb_device_id table for the pre-firmware download keyspan devices */ -static struct usb_device_id keyspan_pre_ids[] = { +static const struct usb_device_id keyspan_pre_ids[] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_pre_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_pre_product_id) }, @@ -513,7 +513,7 @@ static struct usb_device_id keyspan_pre_ids[] = { { } /* Terminating entry */ }; -static struct usb_device_id keyspan_1port_ids[] = { +static const struct usb_device_id keyspan_1port_ids[] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_product_id) }, @@ -524,7 +524,7 @@ static struct usb_device_id keyspan_1port_ids[] = { { } /* Terminating entry */ }; -static struct usb_device_id keyspan_2port_ids[] = { +static const struct usb_device_id keyspan_2port_ids[] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, @@ -532,7 +532,7 @@ static struct usb_device_id keyspan_2port_ids[] = { { } /* Terminating entry */ }; -static struct usb_device_id keyspan_4port_ids[] = { +static const struct usb_device_id keyspan_4port_ids[] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)}, diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 1296a09..185fe9a 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -125,7 +125,7 @@ struct keyspan_pda_private { #define ENTREGRA_VENDOR_ID 0x1645 #define ENTREGRA_FAKE_ID 0x8093 -static struct usb_device_id id_table_combined [] = { +static const struct usb_device_id id_table_combined[] = { #ifdef KEYSPAN { USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_FAKE_ID) }, #endif @@ -147,20 +147,20 @@ static struct usb_driver keyspan_pda_driver = { .no_dynamic_id = 1, }; -static struct usb_device_id id_table_std [] = { +static const struct usb_device_id id_table_std[] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_ID) }, { } /* Terminating entry */ }; #ifdef KEYSPAN -static struct usb_device_id id_table_fake [] = { +static const struct usb_device_id id_table_fake[] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_FAKE_ID) }, { } /* Terminating entry */ }; #endif #ifdef XIRCOM -static struct usb_device_id id_table_fake_xircom [] = { +static const struct usb_device_id id_table_fake_xircom[] = { { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) }, { USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) }, { } @@ -429,13 +429,20 @@ static int keyspan_pda_get_modem_info(struct usb_serial *serial, unsigned char *value) { int rc; - unsigned char data; + u8 *data; + + data = kmalloc(1, GFP_KERNEL); + if (!data) + return -ENOMEM; + rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 3, /* get pins */ USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN, - 0, 0, &data, 1, 2000); + 0, 0, data, 1, 2000); if (rc >= 0) - *value = data; + *value = *data; + + kfree(data); return rc; } @@ -543,7 +550,14 @@ static int keyspan_pda_write(struct tty_struct *tty, device how much room it really has. This is done only on scheduler time, since usb_control_msg() sleeps. */ if (count > priv->tx_room && !in_interrupt()) { - unsigned char room; + u8 *room; + + room = kmalloc(1, GFP_KERNEL); + if (!room) { + rc = -ENOMEM; + goto exit; + } + rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 6, /* write_room */ @@ -551,9 +565,14 @@ static int keyspan_pda_write(struct tty_struct *tty, | USB_DIR_IN, 0, /* value: 0 means "remaining room" */ 0, /* index */ - &room, + room, 1, 2000); + if (rc > 0) { + dbg(" roomquery says %d", *room); + priv->tx_room = *room; + } + kfree(room); if (rc < 0) { dbg(" roomquery failed"); goto exit; @@ -563,8 +582,6 @@ static int keyspan_pda_write(struct tty_struct *tty, rc = -EIO; /* device didn't return any data */ goto exit; } - dbg(" roomquery says %d", room); - priv->tx_room = room; } if (count > priv->tx_room) { /* we're about to completely fill the Tx buffer, so @@ -684,18 +701,22 @@ static int keyspan_pda_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_serial *serial = port->serial; - unsigned char room; + u8 *room; int rc = 0; struct keyspan_pda_private *priv; /* find out how much room is in the Tx ring */ + room = kmalloc(1, GFP_KERNEL); + if (!room) + return -ENOMEM; + rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 6, /* write_room */ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_IN, 0, /* value */ 0, /* index */ - &room, + room, 1, 2000); if (rc < 0) { @@ -708,8 +729,8 @@ static int keyspan_pda_open(struct tty_struct *tty, goto error; } priv = usb_get_serial_port_data(port); - priv->tx_room = room; - priv->tx_throttled = room ? 0 : 1; + priv->tx_room = *room; + priv->tx_throttled = *room ? 0 : 1; /*Start reading from the device*/ port->interrupt_in_urb->dev = serial->dev; @@ -718,8 +739,8 @@ static int keyspan_pda_open(struct tty_struct *tty, dbg("%s - usb_submit_urb(read int) failed", __func__); goto error; } - error: + kfree(room); return rc; } static void keyspan_pda_close(struct usb_serial_port *port) @@ -789,6 +810,13 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) return 1; } +#ifdef KEYSPAN +MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw"); +#endif +#ifdef XIRCOM +MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); +#endif + static int keyspan_pda_startup(struct usb_serial *serial) { diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 3a78738..8eef91b 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -94,7 +94,7 @@ static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file, /* * All of the device info needed for the KLSI converters. */ -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(PALMCONNECT_VID, PALMCONNECT_PID) }, { USB_DEVICE(KLSI_VID, KLSI_KL5KUSB105D_PID) }, { } /* Terminating entry */ @@ -212,10 +212,19 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, unsigned long *line_state_p) { int rc; - __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1, -1}; + u8 *status_buf; __u16 status; dev_info(&port->serial->dev->dev, "sending SIO Poll request\n"); + + status_buf = kmalloc(KLSI_STATUSBUF_LEN, GFP_KERNEL); + if (!status_buf) { + dev_err(&port->dev, "%s - out of memory for status buffer.\n", + __func__); + return -ENOMEM; + } + status_buf[0] = 0xff; + status_buf[1] = 0xff; rc = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), KL5KUSB105A_SIO_POLL, @@ -236,6 +245,8 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, *line_state_p = klsi_105_status2linestate(status); } + + kfree(status_buf); return rc; } @@ -364,7 +375,7 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) int rc; int i; unsigned long line_state; - struct klsi_105_port_settings cfg; + struct klsi_105_port_settings *cfg; unsigned long flags; dbg("%s port %d", __func__, port->number); @@ -376,12 +387,18 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) * Then read the modem line control and store values in * priv->line_state. */ - cfg.pktlen = 5; - cfg.baudrate = kl5kusb105a_sio_b9600; - cfg.databits = kl5kusb105a_dtb_8; - cfg.unknown1 = 0; - cfg.unknown2 = 1; - klsi_105_chg_port_settings(port, &cfg); + cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); + if (!cfg) { + dev_err(&port->dev, "%s - out of memory for config buffer.\n", + __func__); + return -ENOMEM; + } + cfg->pktlen = 5; + cfg->baudrate = kl5kusb105a_sio_b9600; + cfg->databits = kl5kusb105a_dtb_8; + cfg->unknown1 = 0; + cfg->unknown2 = 1; + klsi_105_chg_port_settings(port, cfg); /* set up termios structure */ spin_lock_irqsave(&priv->lock, flags); @@ -391,11 +408,11 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) priv->termios.c_lflag = tty->termios->c_lflag; for (i = 0; i < NCCS; i++) priv->termios.c_cc[i] = tty->termios->c_cc[i]; - priv->cfg.pktlen = cfg.pktlen; - priv->cfg.baudrate = cfg.baudrate; - priv->cfg.databits = cfg.databits; - priv->cfg.unknown1 = cfg.unknown1; - priv->cfg.unknown2 = cfg.unknown2; + priv->cfg.pktlen = cfg->pktlen; + priv->cfg.baudrate = cfg->baudrate; + priv->cfg.databits = cfg->databits; + priv->cfg.unknown1 = cfg->unknown1; + priv->cfg.unknown2 = cfg->unknown2; spin_unlock_irqrestore(&priv->lock, flags); /* READ_ON and urb submission */ @@ -441,6 +458,7 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) retval = rc; exit: + kfree(cfg); return retval; } /* klsi_105_open */ @@ -681,7 +699,6 @@ static void klsi_105_read_bulk_callback(struct urb *urb) bytes_sent = urb->actual_length - 2; } - tty_buffer_request_room(tty, bytes_sent); tty_insert_flip_string(tty, data + 2, bytes_sent); tty_flip_buffer_push(tty); tty_kref_put(tty); @@ -714,10 +731,17 @@ static void klsi_105_set_termios(struct tty_struct *tty, unsigned int old_iflag = old_termios->c_iflag; unsigned int cflag = tty->termios->c_cflag; unsigned int old_cflag = old_termios->c_cflag; - struct klsi_105_port_settings cfg; + struct klsi_105_port_settings *cfg; unsigned long flags; speed_t baud; + cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); + if (!cfg) { + dev_err(&port->dev, "%s - out of memory for config buffer.\n", + __func__); + return; + } + /* lock while we are modifying the settings */ spin_lock_irqsave(&priv->lock, flags); @@ -793,11 +817,11 @@ static void klsi_105_set_termios(struct tty_struct *tty, case CS5: dbg("%s - 5 bits/byte not supported", __func__); spin_unlock_irqrestore(&priv->lock, flags); - return ; + goto err; case CS6: dbg("%s - 6 bits/byte not supported", __func__); spin_unlock_irqrestore(&priv->lock, flags); - return ; + goto err; case CS7: priv->cfg.databits = kl5kusb105a_dtb_7; break; @@ -856,11 +880,13 @@ static void klsi_105_set_termios(struct tty_struct *tty, #endif ; } - memcpy(&cfg, &priv->cfg, sizeof(cfg)); + memcpy(cfg, &priv->cfg, sizeof(*cfg)); spin_unlock_irqrestore(&priv->lock, flags); /* now commit changes to device */ - klsi_105_chg_port_settings(port, &cfg); + klsi_105_chg_port_settings(port, cfg); +err: + kfree(cfg); } /* klsi_105_set_termios */ diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 45ea694..c113a2a 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -86,7 +86,7 @@ static void kobil_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); static void kobil_init_termios(struct tty_struct *tty); -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_B_PRODUCT_ID) }, { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_K_PRODUCT_ID) }, { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_USBTWIN_PRODUCT_ID) }, @@ -388,7 +388,6 @@ static void kobil_read_int_callback(struct urb *urb) */ /* END DEBUG */ - tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } @@ -624,7 +623,6 @@ static void kobil_set_termios(struct tty_struct *tty, unsigned short urb_val = 0; int c_cflag = tty->termios->c_cflag; speed_t speed; - void *settings; priv = usb_get_serial_port_data(port); if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || @@ -647,25 +645,13 @@ static void kobil_set_termios(struct tty_struct *tty, } urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit; - - settings = kzalloc(50, GFP_KERNEL); - if (!settings) - return; - - sprintf(settings, "%d ", speed); - if (c_cflag & PARENB) { - if (c_cflag & PARODD) { + if (c_cflag & PARODD) urb_val |= SUSBCR_SPASB_OddParity; - strcat(settings, "Odd Parity"); - } else { + else urb_val |= SUSBCR_SPASB_EvenParity; - strcat(settings, "Even Parity"); - } - } else { + } else urb_val |= SUSBCR_SPASB_NoParity; - strcat(settings, "No Parity"); - } tty->termios->c_cflag &= ~CMSPAR; tty_encode_baud_rate(tty, speed, speed); @@ -675,11 +661,10 @@ static void kobil_set_termios(struct tty_struct *tty, USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, urb_val, 0, - settings, + NULL, 0, KOBIL_TIMEOUT ); - kfree(settings); } static int kobil_ioctl(struct tty_struct *tty, struct file *file, diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index cd009cb..2849f8c 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -75,6 +75,7 @@ #include <linux/module.h> #include <linux/spinlock.h> #include <linux/uaccess.h> +#include <asm/unaligned.h> #include <linux/usb.h> #include <linux/usb/serial.h> #include "mct_u232.h" @@ -110,7 +111,7 @@ static void mct_u232_unthrottle(struct tty_struct *tty); /* * All of the device info needed for the MCT USB-RS232 converter. */ -static struct usb_device_id id_table_combined [] = { +static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) }, { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) }, { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) }, @@ -231,19 +232,22 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, static int mct_u232_set_baud_rate(struct tty_struct *tty, struct usb_serial *serial, struct usb_serial_port *port, speed_t value) { - __le32 divisor; + unsigned int divisor; int rc; - unsigned char zero_byte = 0; + unsigned char *buf; unsigned char cts_enable_byte = 0; speed_t speed; - divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value, - &speed)); + buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + divisor = mct_u232_calculate_baud_rate(serial, value, &speed); + put_unaligned_le32(cpu_to_le32(divisor), buf); rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCT_U232_SET_BAUD_RATE_REQUEST, MCT_U232_SET_REQUEST_TYPE, - 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE, + 0, 0, buf, MCT_U232_SET_BAUD_RATE_SIZE, WDR_TIMEOUT); if (rc < 0) /*FIXME: What value speed results */ dev_err(&port->dev, "Set BAUD RATE %d failed (error = %d)\n", @@ -269,10 +273,11 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty, a device which is not asserting 'CTS'. */ + buf[0] = 0; rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCT_U232_SET_UNKNOWN1_REQUEST, MCT_U232_SET_REQUEST_TYPE, - 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE, + 0, 0, buf, MCT_U232_SET_UNKNOWN1_SIZE, WDR_TIMEOUT); if (rc < 0) dev_err(&port->dev, "Sending USB device request code %d " @@ -284,30 +289,40 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty, dbg("set_baud_rate: send second control message, data = %02X", cts_enable_byte); + buf[0] = cts_enable_byte; rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCT_U232_SET_CTS_REQUEST, MCT_U232_SET_REQUEST_TYPE, - 0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE, + 0, 0, buf, MCT_U232_SET_CTS_SIZE, WDR_TIMEOUT); if (rc < 0) dev_err(&port->dev, "Sending USB device request code %d " "failed (error = %d)\n", MCT_U232_SET_CTS_REQUEST, rc); + kfree(buf); return rc; } /* mct_u232_set_baud_rate */ static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr) { int rc; + unsigned char *buf; + + buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + buf[0] = lcr; rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCT_U232_SET_LINE_CTRL_REQUEST, MCT_U232_SET_REQUEST_TYPE, - 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE, + 0, 0, buf, MCT_U232_SET_LINE_CTRL_SIZE, WDR_TIMEOUT); if (rc < 0) dev_err(&serial->dev->dev, "Set LINE CTRL 0x%x failed (error = %d)\n", lcr, rc); dbg("set_line_ctrl: 0x%x", lcr); + kfree(buf); return rc; } /* mct_u232_set_line_ctrl */ @@ -315,23 +330,31 @@ static int mct_u232_set_modem_ctrl(struct usb_serial *serial, unsigned int control_state) { int rc; - unsigned char mcr = MCT_U232_MCR_NONE; + unsigned char mcr; + unsigned char *buf; + + buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + mcr = MCT_U232_MCR_NONE; if (control_state & TIOCM_DTR) mcr |= MCT_U232_MCR_DTR; if (control_state & TIOCM_RTS) mcr |= MCT_U232_MCR_RTS; + buf[0] = mcr; rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCT_U232_SET_MODEM_CTRL_REQUEST, MCT_U232_SET_REQUEST_TYPE, - 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE, + 0, 0, buf, MCT_U232_SET_MODEM_CTRL_SIZE, WDR_TIMEOUT); if (rc < 0) dev_err(&serial->dev->dev, "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc); dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr); + kfree(buf); return rc; } /* mct_u232_set_modem_ctrl */ @@ -339,17 +362,27 @@ static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr) { int rc; + unsigned char *buf; + + buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL); + if (buf == NULL) { + *msr = 0; + return -ENOMEM; + } rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), MCT_U232_GET_MODEM_STAT_REQUEST, MCT_U232_GET_REQUEST_TYPE, - 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE, + 0, 0, buf, MCT_U232_GET_MODEM_STAT_SIZE, WDR_TIMEOUT); if (rc < 0) { dev_err(&serial->dev->dev, "Get MODEM STATus failed (error = %d)\n", rc); *msr = 0; + } else { + *msr = buf[0]; } dbg("get_modem_stat: 0x%x", *msr); + kfree(buf); return rc; } /* mct_u232_get_modem_stat */ diff --git a/drivers/usb/serial/mct_u232.h b/drivers/usb/serial/mct_u232.h index 07b6bec..7417d5c 100644 --- a/drivers/usb/serial/mct_u232.h +++ b/drivers/usb/serial/mct_u232.h @@ -73,6 +73,8 @@ #define MCT_U232_SET_CTS_REQUEST 12 #define MCT_U232_SET_CTS_SIZE 1 +#define MCT_U232_MAX_SIZE 4 /* of MCT_XXX_SIZE */ + /* * Baud rate (divisor) * Actually, there are two of them, MCT website calls them "Philips solution" diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 763e32a..0d47f2c 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -81,12 +81,15 @@ struct moschip_serial { static int debug; +static struct usb_serial_driver moschip7720_2port_driver; + #define USB_VENDOR_ID_MOSCHIP 0x9710 #define MOSCHIP_DEVICE_ID_7720 0x7720 #define MOSCHIP_DEVICE_ID_7715 0x7715 -static struct usb_device_id moschip_port_id_table[] = { +static const struct usb_device_id moschip_port_id_table[] = { { USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7720) }, + { USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7715) }, { } /* terminating entry */ }; MODULE_DEVICE_TABLE(usb, moschip_port_id_table); @@ -106,7 +109,7 @@ static void mos7720_interrupt_callback(struct urb *urb) __u8 sp1; __u8 sp2; - dbg("%s", " : Entering\n"); + dbg(" : Entering"); switch (status) { case 0: @@ -186,6 +189,75 @@ exit: } /* + * mos7715_interrupt_callback + * this is the 7715's callback function for when we have received data on + * the interrupt endpoint. + */ +static void mos7715_interrupt_callback(struct urb *urb) +{ + int result; + int length; + int status = urb->status; + __u8 *data; + __u8 iir; + + switch (status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __func__, + status); + return; + default: + dbg("%s - nonzero urb status received: %d", __func__, + status); + goto exit; + } + + length = urb->actual_length; + data = urb->transfer_buffer; + + /* Structure of data from 7715 device: + * Byte 1: IIR serial Port + * Byte 2: unused + * Byte 2: DSR parallel port + * Byte 4: FIFO status for both */ + + if (unlikely(length != 4)) { + dbg("Wrong data !!!"); + return; + } + + iir = data[0]; + if (!(iir & 0x01)) { /* serial port interrupt pending */ + switch (iir & 0x0f) { + case SERIAL_IIR_RLS: + dbg("Serial Port: Receiver status error or address " + "bit detected in 9-bit mode\n"); + break; + case SERIAL_IIR_CTI: + dbg("Serial Port: Receiver time out"); + break; + case SERIAL_IIR_MS: + dbg("Serial Port: Modem status change"); + break; + } + } + +exit: + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) + dev_err(&urb->dev->dev, + "%s - Error %d submitting control urb\n", + __func__, result); + return; +} + +/* * mos7720_bulk_in_callback * this is the callback function for when we have received data on the * bulk in endpoint. @@ -206,7 +278,7 @@ static void mos7720_bulk_in_callback(struct urb *urb) mos7720_port = urb->context; if (!mos7720_port) { - dbg("%s", "NULL mos7720_port pointer \n"); + dbg("NULL mos7720_port pointer"); return ; } @@ -218,7 +290,6 @@ static void mos7720_bulk_in_callback(struct urb *urb) tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { - tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } @@ -275,17 +346,15 @@ static void mos7720_bulk_out_data_callback(struct urb *urb) * this function will be used for sending command to device */ static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value, - __u16 index, void *data) + __u16 index, u8 *data) { int status; - unsigned int pipe; + u8 *buf; u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); - __u8 requesttype; - __u16 size = 0x0000; if (value < MOS_MAX_PORT) { if (product == MOSCHIP_DEVICE_ID_7715) - value = value*0x100+0x100; + value = 0x0200; /* identifies the 7715's serial port */ else value = value*0x100+0x200; } else { @@ -298,27 +367,58 @@ static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value, } if (request == MOS_WRITE) { - request = (__u8)MOS_WRITE; - requesttype = (__u8)0x40; - value = value + (__u16)*((unsigned char *)data); - data = NULL; - pipe = usb_sndctrlpipe(serial->dev, 0); + value = value + *data; + status = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), MOS_WRITE, + 0x40, value, index, NULL, 0, MOS_WDR_TIMEOUT); } else { - request = (__u8)MOS_READ; - requesttype = (__u8)0xC0; - size = 0x01; - pipe = usb_rcvctrlpipe(serial->dev, 0); + buf = kmalloc(1, GFP_KERNEL); + if (!buf) { + status = -ENOMEM; + goto out; + } + status = usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev, 0), MOS_READ, + 0xc0, value, index, buf, 1, MOS_WDR_TIMEOUT); + *data = *buf; + kfree(buf); } - - status = usb_control_msg(serial->dev, pipe, request, requesttype, - value, index, data, size, MOS_WDR_TIMEOUT); - +out: if (status < 0) - dbg("Command Write failed Value %x index %x\n", value, index); + dbg("Command Write failed Value %x index %x", value, index); return status; } + +/* + * mos77xx_probe + * this function installs the appropriate read interrupt endpoint callback + * depending on whether the device is a 7720 or 7715, thus avoiding costly + * run-time checks in the high-frequency callback routine itself. + */ +static int mos77xx_probe(struct usb_serial *serial, + const struct usb_device_id *id) +{ + if (id->idProduct == MOSCHIP_DEVICE_ID_7715) + moschip7720_2port_driver.read_int_callback = + mos7715_interrupt_callback; + else + moschip7720_2port_driver.read_int_callback = + mos7720_interrupt_callback; + + return 0; +} + +static int mos77xx_calc_num_ports(struct usb_serial *serial) +{ + u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); + if (product == MOSCHIP_DEVICE_ID_7715) + return 1; + + return 2; +} + static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_serial *serial; @@ -390,7 +490,7 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port) */ port_number = port->number - port->serial->minor; send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data); - dbg("SS::%p LSR:%x\n", mos7720_port, data); + dbg("SS::%p LSR:%x", mos7720_port, data); dbg("Check:Sending Command .........."); @@ -729,7 +829,7 @@ static void mos7720_throttle(struct tty_struct *tty) struct moschip_port *mos7720_port; int status; - dbg("%s- port %d\n", __func__, port->number); + dbg("%s- port %d", __func__, port->number); mos7720_port = usb_get_serial_port_data(port); @@ -1208,7 +1308,7 @@ static void mos7720_set_termios(struct tty_struct *tty, return; } - dbg("%s\n", "setting termios - ASPIRE"); + dbg("setting termios - ASPIRE"); cflag = tty->termios->c_cflag; @@ -1226,7 +1326,7 @@ static void mos7720_set_termios(struct tty_struct *tty, change_port_settings(tty, mos7720_port, old_termios); if (!port->read_urb) { - dbg("%s", "URB KILLED !!!!!\n"); + dbg("URB KILLED !!!!!"); return; } @@ -1495,6 +1595,7 @@ static int mos7720_startup(struct usb_serial *serial) struct usb_device *dev; int i; char data; + u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); dbg("%s: Entering ..........", __func__); @@ -1514,6 +1615,29 @@ static int mos7720_startup(struct usb_serial *serial) usb_set_serial_data(serial, mos7720_serial); + /* + * The 7715 uses the first bulk in/out endpoint pair for the parallel + * port, and the second for the serial port. Because the usbserial core + * assumes both pairs are serial ports, we must engage in a bit of + * subterfuge and swap the pointers for ports 0 and 1 in order to make + * port 0 point to the serial port. However, both moschip devices use a + * single interrupt-in endpoint for both ports (as mentioned a little + * further down), and this endpoint was assigned to port 0. So after + * the swap, we must copy the interrupt endpoint elements from port 1 + * (as newly assigned) to port 0, and null out port 1 pointers. + */ + if (product == MOSCHIP_DEVICE_ID_7715) { + struct usb_serial_port *tmp = serial->port[0]; + serial->port[0] = serial->port[1]; + serial->port[1] = tmp; + serial->port[0]->interrupt_in_urb = tmp->interrupt_in_urb; + serial->port[0]->interrupt_in_buffer = tmp->interrupt_in_buffer; + serial->port[0]->interrupt_in_endpointAddress = + tmp->interrupt_in_endpointAddress; + serial->port[1]->interrupt_in_urb = NULL; + serial->port[1]->interrupt_in_buffer = NULL; + } + /* we set up the pointers to the endpoints in the mos7720_open * * function, as the structures aren't created yet. */ @@ -1529,7 +1653,7 @@ static int mos7720_startup(struct usb_serial *serial) /* Initialize all port interrupt end point to port 0 int * endpoint. Our device has only one interrupt endpoint - * comman to all ports */ + * common to all ports */ serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress; @@ -1584,11 +1708,12 @@ static struct usb_serial_driver moschip7720_2port_driver = { .description = "Moschip 2 port adapter", .usb_driver = &usb_driver, .id_table = moschip_port_id_table, - .num_ports = 2, + .calc_num_ports = mos77xx_calc_num_ports, .open = mos7720_open, .close = mos7720_close, .throttle = mos7720_throttle, .unthrottle = mos7720_unthrottle, + .probe = mos77xx_probe, .attach = mos7720_startup, .release = mos7720_release, .ioctl = mos7720_ioctl, @@ -1600,7 +1725,7 @@ static struct usb_serial_driver moschip7720_2port_driver = { .chars_in_buffer = mos7720_chars_in_buffer, .break_ctl = mos7720_break, .read_bulk_callback = mos7720_bulk_in_callback, - .read_int_callback = mos7720_interrupt_callback, + .read_int_callback = NULL /* dynamically assigned in probe() */ }; static int __init moschip7720_init(void) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 2cfe245..2fda1c0 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -181,7 +181,7 @@ #define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ -static struct usb_device_id moschip_port_id_table[] = { +static const struct usb_device_id moschip_port_id_table[] = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, @@ -198,7 +198,7 @@ static struct usb_device_id moschip_port_id_table[] = { {} /* terminating entry */ }; -static __devinitdata struct usb_device_id moschip_id_table_combined[] = { +static const struct usb_device_id moschip_id_table_combined[] __devinitconst = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, @@ -283,12 +283,19 @@ static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg, { struct usb_device *dev = port->serial->dev; int ret = 0; + u8 *buf; + + buf = kmalloc(VENDOR_READ_LENGTH, GFP_KERNEL); + if (!buf) + return -ENOMEM; ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, - MCS_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH, + MCS_RD_RTYPE, 0, reg, buf, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); + *val = buf[0]; dbg("mos7840_get_reg_sync offset is %x, return val %x", reg, *val); - *val = (*val) & 0x00ff; + + kfree(buf); return ret; } @@ -341,6 +348,11 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, struct usb_device *dev = port->serial->dev; int ret = 0; __u16 Wval; + u8 *buf; + + buf = kmalloc(VENDOR_READ_LENGTH, GFP_KERNEL); + if (!buf) + return -ENOMEM; /* dbg("application number is %4x", (((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); */ @@ -364,9 +376,11 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, } } ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, - MCS_RD_RTYPE, Wval, reg, val, VENDOR_READ_LENGTH, + MCS_RD_RTYPE, Wval, reg, buf, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); - *val = (*val) & 0x00ff; + *val = buf[0]; + + kfree(buf); return ret; } @@ -750,7 +764,6 @@ static void mos7840_bulk_in_callback(struct urb *urb) if (urb->actual_length) { tty = tty_port_tty_get(&mos7840_port->port->port); if (tty) { - tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); dbg(" %s ", data); tty_flip_buffer_push(tty); diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c index 99bd00f5..cf17183 100644 --- a/drivers/usb/serial/moto_modem.c +++ b/drivers/usb/serial/moto_modem.c @@ -21,7 +21,7 @@ #include <linux/usb.h> #include <linux/usb/serial.h> -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(0x05c6, 0x3197) }, /* unknown Motorola phone */ { USB_DEVICE(0x0c44, 0x0022) }, /* unknown Mororola phone */ { USB_DEVICE(0x22b8, 0x2a64) }, /* Motorola KRZR K1m */ diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index 5ceaa4c6..04a6cbb 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -22,7 +22,7 @@ static int debug; -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0a99, 0x0001) }, /* Talon Technology device */ { }, }; @@ -66,7 +66,6 @@ static void navman_read_int_callback(struct urb *urb) tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { - tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 0622650..89c724c 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -75,7 +75,7 @@ static void omninet_disconnect(struct usb_serial *serial); static void omninet_release(struct usb_serial *serial); static int omninet_attach(struct usb_serial *serial); -static struct usb_device_id id_table[] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) }, { USB_DEVICE(ZYXEL_VENDOR_ID, BT_IGNITIONPRO_ID) }, { } /* Terminating entry */ @@ -218,8 +218,8 @@ static void omninet_read_bulk_callback(struct urb *urb) if (debug && header->oh_xxx != 0x30) { if (urb->actual_length) { - printk(KERN_DEBUG __FILE__ - ": omninet_read %d: ", header->oh_len); + printk(KERN_DEBUG "%s: omninet_read %d: ", + __FILE__, header->oh_len); for (i = 0; i < (header->oh_len + OMNINET_HEADERLEN); i++) printk("%.2x ", data[i]); @@ -332,7 +332,7 @@ static void omninet_write_bulk_callback(struct urb *urb) struct usb_serial_port *port = urb->context; int status = urb->status; - dbg("%s - port %0x\n", __func__, port->number); + dbg("%s - port %0x", __func__, port->number); port->write_urb_busy = 0; if (status) { diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 4cdb975..701452a 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -22,7 +22,7 @@ static int debug; -static struct usb_device_id id_table[] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(0x065a, 0x0009) }, { }, }; @@ -55,7 +55,6 @@ static void opticon_bulk_callback(struct urb *urb) int status = urb->status; struct tty_struct *tty; int result; - int available_room = 0; int data_length; dbg("%s - port %d", __func__, port->number); @@ -96,13 +95,9 @@ static void opticon_bulk_callback(struct urb *urb) /* real data, send it to the tty layer */ tty = tty_port_tty_get(&port->port); if (tty) { - available_room = tty_buffer_request_room(tty, - data_length); - if (available_room) { - tty_insert_flip_string(tty, data, - available_room); - tty_flip_buffer_push(tty); - } + tty_insert_flip_string(tty, data, + data_length); + tty_flip_buffer_push(tty); tty_kref_put(tty); } } else { @@ -120,7 +115,7 @@ static void opticon_bulk_callback(struct urb *urb) } } else { dev_dbg(&priv->udev->dev, - "Improper ammount of data received from the device, " + "Improper amount of data received from the device, " "%d bytes", urb->actual_length); } @@ -217,7 +212,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, spin_lock_irqsave(&priv->lock, flags); if (priv->outstanding_urbs > URB_UPPER_LIMIT) { spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - write limit hit\n", __func__); + dbg("%s - write limit hit", __func__); return 0; } priv->outstanding_urbs++; @@ -288,7 +283,7 @@ static int opticon_write_room(struct tty_struct *tty) spin_lock_irqsave(&priv->lock, flags); if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) { spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - write limit hit\n", __func__); + dbg("%s - write limit hit", __func__); return 0; } spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 6e94a67..847b805 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -336,15 +336,42 @@ static int option_resume(struct usb_serial *serial); #define AIRPLUS_VENDOR_ID 0x1011 #define AIRPLUS_PRODUCT_MCD650 0x3198 +/* Longcheer/Longsung vendor ID; makes whitelabel devices that + * many other vendors like 4G Systems, Alcatel, ChinaBird, + * Mobidata, etc sell under their own brand names. + */ +#define LONGCHEER_VENDOR_ID 0x1c9e + /* 4G Systems products */ -#define FOUR_G_SYSTEMS_VENDOR_ID 0x1c9e +/* This is the 4G XS Stick W14 a.k.a. Mobilcom Debitel Surf-Stick * + * It seems to contain a Qualcomm QSC6240/6290 chipset */ #define FOUR_G_SYSTEMS_PRODUCT_W14 0x9603 /* Haier products */ #define HAIER_VENDOR_ID 0x201e #define HAIER_PRODUCT_CE100 0x2009 -static struct usb_device_id option_ids[] = { +/* some devices interfaces need special handling due to a number of reasons */ +enum option_blacklist_reason { + OPTION_BLACKLIST_NONE = 0, + OPTION_BLACKLIST_SENDSETUP = 1, + OPTION_BLACKLIST_RESERVED_IF = 2 +}; + +struct option_blacklist_info { + const u32 infolen; /* number of interface numbers on blacklist */ + const u8 *ifaceinfo; /* pointer to the array holding the numbers */ + enum option_blacklist_reason reason; +}; + +static const u8 four_g_w14_no_sendsetup[] = { 0, 1 }; +static const struct option_blacklist_info four_g_w14_blacklist = { + .infolen = ARRAY_SIZE(four_g_w14_no_sendsetup), + .ifaceinfo = four_g_w14_no_sendsetup, + .reason = OPTION_BLACKLIST_SENDSETUP +}; + +static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) }, @@ -644,7 +671,9 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, - { USB_DEVICE(FOUR_G_SYSTEMS_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14) }, + { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), + .driver_info = (kernel_ulong_t)&four_g_w14_blacklist + }, { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, { } /* Terminating entry */ }; @@ -709,6 +738,7 @@ struct option_intf_private { spinlock_t susp_lock; unsigned int suspended:1; int in_flight; + struct option_blacklist_info *blacklist_info; }; struct option_port_private { @@ -778,9 +808,27 @@ static int option_probe(struct usb_serial *serial, if (!data) return -ENOMEM; spin_lock_init(&data->susp_lock); + data->blacklist_info = (struct option_blacklist_info*) id->driver_info; return 0; } +static enum option_blacklist_reason is_blacklisted(const u8 ifnum, + const struct option_blacklist_info *blacklist) +{ + const u8 *info; + int i; + + if (blacklist) { + info = blacklist->ifaceinfo; + + for (i = 0; i < blacklist->infolen; i++) { + if (info[i] == ifnum) + return blacklist->reason; + } + } + return OPTION_BLACKLIST_NONE; +} + static void option_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { @@ -921,7 +969,6 @@ static void option_indat_callback(struct urb *urb) } else { tty = tty_port_tty_get(&port->port); if (urb->actual_length) { - tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } else @@ -929,9 +976,9 @@ static void option_indat_callback(struct urb *urb) tty_kref_put(tty); /* Resubmit urb so we continue receiving */ - if (port->port.count && status != -ESHUTDOWN) { + if (status != -ESHUTDOWN) { err = usb_submit_urb(urb, GFP_ATOMIC); - if (err) + if (err && err != -EPERM) printk(KERN_ERR "%s: resubmit read urb failed. " "(%d)", __func__, err); else @@ -985,7 +1032,7 @@ static void option_instat_callback(struct urb *urb) (struct usb_ctrlrequest *)urb->transfer_buffer; if (!req_pkt) { - dbg("%s: NULL req_pkt\n", __func__); + dbg("%s: NULL req_pkt", __func__); return; } if ((req_pkt->bRequestType == 0xA1) && @@ -1211,11 +1258,19 @@ static void option_setup_urbs(struct usb_serial *serial) static int option_send_setup(struct usb_serial_port *port) { struct usb_serial *serial = port->serial; + struct option_intf_private *intfdata = + (struct option_intf_private *) serial->private; struct option_port_private *portdata; int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; int val = 0; dbg("%s", __func__); + if (is_blacklisted(ifNum, intfdata->blacklist_info) == + OPTION_BLACKLIST_SENDSETUP) { + dbg("No send_setup on blacklisted interface #%d\n", ifNum); + return -EIO; + } + portdata = usb_get_serial_port_data(port); if (portdata->dtr_state) @@ -1401,7 +1456,7 @@ static int option_resume(struct usb_serial *serial) for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; if (!port->interrupt_in_urb) { - dbg("%s: No interrupt URB for port %d\n", __func__, i); + dbg("%s: No interrupt URB for port %d", __func__, i); continue; } err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index c644e26..deeacde 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -58,7 +58,7 @@ #define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>" #define OTI6858_VERSION "0.1" -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) }, { } }; @@ -302,7 +302,7 @@ void send_data(struct work_struct *work) struct usb_serial_port *port = priv->port; int count = 0, result; unsigned long flags; - unsigned char allow; + u8 *allow; dbg("%s(port = %d)", __func__, port->number); @@ -321,13 +321,20 @@ void send_data(struct work_struct *work) count = port->bulk_out_size; if (count != 0) { + allow = kmalloc(1, GFP_KERNEL); + if (!allow) { + dev_err(&port->dev, "%s(): kmalloc failed\n", + __func__); + return; + } result = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), OTI6858_REQ_T_CHECK_TXBUFF, OTI6858_REQ_CHECK_TXBUFF, - count, 0, &allow, 1, 100); - if (result != 1 || allow != 0) + count, 0, allow, 1, 100); + if (result != 1 || *allow != 0) count = 0; + kfree(allow); } if (count == 0) { @@ -578,9 +585,6 @@ static int oti6858_open(struct tty_struct *tty, struct usb_serial_port *port) usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); - if (port->port.count != 1) - return 0; - buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL); if (buf == NULL) { dev_err(&port->dev, "%s(): out of memory!\n", __func__); @@ -927,10 +931,6 @@ static void oti6858_read_bulk_callback(struct urb *urb) spin_unlock_irqrestore(&priv->lock, flags); if (status != 0) { - if (!port->port.count) { - dbg("%s(): port is closed, exiting", __func__); - return; - } /* if (status == -EPROTO) { * PL2303 mysteriously fails with -EPROTO reschedule @@ -954,14 +954,12 @@ static void oti6858_read_bulk_callback(struct urb *urb) } tty_kref_put(tty); - /* schedule the interrupt urb if we are still open */ - if (port->port.count != 0) { - port->interrupt_in_urb->dev = port->serial->dev; - result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); - if (result != 0) { - dev_err(&port->dev, "%s(): usb_submit_urb() failed," - " error %d\n", __func__, result); - } + /* schedule the interrupt urb */ + port->interrupt_in_urb->dev = port->serial->dev; + result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); + if (result != 0 && result != -EPERM) { + dev_err(&port->dev, "%s(): usb_submit_urb() failed," + " error %d\n", __func__, result); } } diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 9ec1a49..73d5f34 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -50,7 +50,7 @@ struct pl2303_buf { char *buf_put; }; -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) }, @@ -451,7 +451,6 @@ static void pl2303_send(struct usb_serial_port *port) port->write_urb->transfer_buffer); port->write_urb->transfer_buffer_length = count; - port->write_urb->dev = port->serial->dev; result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { dev_err(&port->dev, "%s - failed submitting write urb," @@ -769,7 +768,6 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) pl2303_set_termios(tty, port, &tmp_termios); dbg("%s - submitting read urb", __func__); - port->read_urb->dev = serial->dev; result = usb_submit_urb(port->read_urb, GFP_KERNEL); if (result) { dev_err(&port->dev, "%s - failed submitting read urb," @@ -779,7 +777,6 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) } dbg("%s - submitting interrupt urb", __func__); - port->interrupt_in_urb->dev = serial->dev; result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (result) { dev_err(&port->dev, "%s - failed submitting interrupt urb," @@ -895,10 +892,23 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) static int pl2303_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { + struct serial_struct ser; struct usb_serial_port *port = tty->driver_data; dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); switch (cmd) { + case TIOCGSERIAL: + memset(&ser, 0, sizeof ser); + ser.type = PORT_16654; + ser.line = port->serial->minor; + ser.port = port->number; + ser.baud_base = 460800; + + if (copy_to_user((void __user *)arg, &ser, sizeof ser)) + return -EFAULT; + + return 0; + case TIOCMIWAIT: dbg("%s (%d) TIOCMIWAIT", __func__, port->number); return wait_modem_info(port, arg); @@ -1042,7 +1052,6 @@ static void pl2303_push_data(struct tty_struct *tty, tty_flag = TTY_FRAME; dbg("%s - tty_flag = %d", __func__, tty_flag); - tty_buffer_request_room(tty, urb->actual_length + 1); /* overrun is special, not associated with a char */ if (line_status & UART_OVERRUN_ERROR) tty_insert_flip_char(tty, 0, TTY_OVERRUN); @@ -1072,16 +1081,11 @@ static void pl2303_read_bulk_callback(struct urb *urb) if (status) { dbg("%s - urb status = %d", __func__, status); - if (!port->port.count) { - dbg("%s - port is closed, exiting.", __func__); - return; - } if (status == -EPROTO) { /* PL2303 mysteriously fails with -EPROTO reschedule * the read */ dbg("%s - caught -EPROTO, resubmitting the urb", __func__); - urb->dev = port->serial->dev; result = usb_submit_urb(urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - failed" @@ -1108,15 +1112,10 @@ static void pl2303_read_bulk_callback(struct urb *urb) } tty_kref_put(tty); /* Schedule the next read _if_ we are still open */ - if (port->port.count) { - urb->dev = port->serial->dev; - result = usb_submit_urb(urb, GFP_ATOMIC); - if (result) - dev_err(&urb->dev->dev, "%s - failed resubmitting" - " read urb, error %d\n", __func__, result); - } - - return; + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result && result != -EPERM) + dev_err(&urb->dev->dev, "%s - failed resubmitting" + " read urb, error %d\n", __func__, result); } static void pl2303_write_bulk_callback(struct urb *urb) @@ -1146,7 +1145,6 @@ static void pl2303_write_bulk_callback(struct urb *urb) dbg("%s - nonzero write bulk status received: %d", __func__, status); port->write_urb->transfer_buffer_length = 1; - port->write_urb->dev = port->serial->dev; result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - failed resubmitting write" diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c new file mode 100644 index 0000000..0b93620 --- /dev/null +++ b/drivers/usb/serial/qcaux.c @@ -0,0 +1,96 @@ +/* + * Qualcomm USB Auxiliary Serial Port driver + * + * Copyright (C) 2008 Greg Kroah-Hartman <greg@kroah.com> + * Copyright (C) 2010 Dan Williams <dcbw@redhat.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. + * + * Devices listed here usually provide a CDC ACM port on which normal modem + * AT commands and PPP can be used. But when that port is in-use by PPP it + * cannot be used simultaneously for status or signal strength. Instead, the + * ports here can be queried for that information using the Qualcomm DM + * protocol. + */ + +#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> + +/* NOTE: for now, only use this driver for devices that provide a CDC-ACM port + * for normal AT commands, but also provide secondary USB interfaces for the + * QCDM-capable ports. Devices that do not provide a CDC-ACM port should + * probably be driven by option.ko. + */ + +/* UTStarcom/Pantech/Curitel devices */ +#define UTSTARCOM_VENDOR_ID 0x106c +#define UTSTARCOM_PRODUCT_PC5740 0x3701 +#define UTSTARCOM_PRODUCT_PC5750 0x3702 /* aka Pantech PX-500 */ +#define UTSTARCOM_PRODUCT_UM150 0x3711 +#define UTSTARCOM_PRODUCT_UM175_V1 0x3712 +#define UTSTARCOM_PRODUCT_UM175_V2 0x3714 +#define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715 + +/* CMOTECH devices */ +#define CMOTECH_VENDOR_ID 0x16d8 +#define CMOTECH_PRODUCT_CDU550 0x5553 +#define CMOTECH_PRODUCT_CDX650 0x6512 + +static struct usb_device_id id_table[] = { + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_PC5740, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_PC5750, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_UM150, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_UM175_V1, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_UM175_V2, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_UM175_ALLTEL, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDU550, 0xff, 0xff, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDX650, 0xff, 0xff, 0x00) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver qcaux_driver = { + .name = "qcaux", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .no_dynamic_id = 1, +}; + +static struct usb_serial_driver qcaux_device = { + .driver = { + .owner = THIS_MODULE, + .name = "qcaux", + }, + .id_table = id_table, + .num_ports = 1, +}; + +static int __init qcaux_init(void) +{ + int retval; + + retval = usb_serial_register(&qcaux_device); + if (retval) + return retval; + retval = usb_register(&qcaux_driver); + if (retval) + usb_serial_deregister(&qcaux_device); + return retval; +} + +static void __exit qcaux_exit(void) +{ + usb_deregister(&qcaux_driver); + usb_serial_deregister(&qcaux_device); +} + +module_init(qcaux_init); +module_exit(qcaux_exit); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 7528b8d..310ff6e 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -21,7 +21,7 @@ static int debug; -static struct usb_device_id id_table[] = { +static const struct usb_device_id id_table[] = { {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c index 951ea0c..cb8195c 100644 --- a/drivers/usb/serial/siemens_mpi.c +++ b/drivers/usb/serial/siemens_mpi.c @@ -22,7 +22,7 @@ #define DRIVER_DESC "Driver for Siemens USB/MPI adapter" -static struct usb_device_id id_table[] = { +static const struct usb_device_id id_table[] = { /* Vendor and product id for 6ES7-972-0CB20-0XA0 */ { USB_DEVICE(0x908, 0x0004) }, { }, diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 3eb6143..34e6f89 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -226,7 +226,7 @@ static const struct sierra_iface_info direct_ip_interface_blacklist = { .ifaceinfo = direct_ip_non_serial_ifaces, }; -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */ { USB_DEVICE(0x03F0, 0x1B1D) }, /* HP ev2200 a.k.a MC5720 */ { USB_DEVICE(0x03F0, 0x1E1D) }, /* HP hs2300 a.k.a MC8775 */ @@ -304,16 +304,6 @@ static struct usb_device_id id_table [] = { }; MODULE_DEVICE_TABLE(usb, id_table); -static struct usb_driver sierra_driver = { - .name = "sierra", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .suspend = usb_serial_suspend, - .resume = usb_serial_resume, - .id_table = id_table, - .no_dynamic_id = 1, - .supports_autosuspend = 1, -}; struct sierra_port_private { spinlock_t lock; /* lock the structure */ @@ -477,7 +467,7 @@ static void sierra_outdat_callback(struct urb *urb) static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { - struct sierra_port_private *portdata = usb_get_serial_port_data(port); + struct sierra_port_private *portdata; struct sierra_intf_private *intfdata; struct usb_serial *serial = port->serial; unsigned long flags; @@ -604,14 +594,15 @@ static void sierra_indat_callback(struct urb *urb) } else { if (urb->actual_length) { tty = tty_port_tty_get(&port->port); - - tty_buffer_request_room(tty, urb->actual_length); - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); - - tty_kref_put(tty); - usb_serial_debug_data(debug, &port->dev, __func__, - urb->actual_length, data); + if (tty) { + tty_insert_flip_string(tty, data, + urb->actual_length); + tty_flip_buffer_push(tty); + + tty_kref_put(tty); + usb_serial_debug_data(debug, &port->dev, + __func__, urb->actual_length, data); + } } else { dev_dbg(&port->dev, "%s: empty read urb" " received\n", __func__); @@ -619,10 +610,10 @@ static void sierra_indat_callback(struct urb *urb) } /* Resubmit urb so we continue receiving */ - if (port->port.count && status != -ESHUTDOWN && status != -EPERM) { + if (status != -ESHUTDOWN && status != -EPERM) { usb_mark_last_busy(port->serial->dev); err = usb_submit_urb(urb, GFP_ATOMIC); - if (err) + if (err && err != -EPERM) dev_err(&port->dev, "resubmit read urb failed." "(%d)\n", err); } @@ -681,11 +672,11 @@ static void sierra_instat_callback(struct urb *urb) dev_dbg(&port->dev, "%s: error %d\n", __func__, status); /* Resubmit urb so we continue receiving IRQ data */ - if (port->port.count && status != -ESHUTDOWN && status != -ENOENT) { + if (status != -ESHUTDOWN && status != -ENOENT) { usb_mark_last_busy(serial->dev); urb->dev = serial->dev; err = usb_submit_urb(urb, GFP_ATOMIC); - if (err) + if (err && err != -EPERM) dev_err(&port->dev, "%s: resubmit intr urb " "failed. (%d)\n", __func__, err); } @@ -1061,11 +1052,31 @@ static int sierra_resume(struct usb_serial *serial) return ec ? -EIO : 0; } + +static int sierra_reset_resume(struct usb_interface *intf) +{ + struct usb_serial *serial = usb_get_intfdata(intf); + dev_err(&serial->dev->dev, "%s\n", __func__); + return usb_serial_resume(intf); +} #else #define sierra_suspend NULL #define sierra_resume NULL +#define sierra_reset_resume NULL #endif +static struct usb_driver sierra_driver = { + .name = "sierra", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, + .reset_resume = sierra_reset_resume, + .id_table = id_table, + .no_dynamic_id = 1, + .supports_autosuspend = 1, +}; + static struct usb_serial_driver sierra_device = { .driver = { .owner = THIS_MODULE, diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 1e58220..5d39191 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -45,7 +45,7 @@ static int debug; #define SPCP8x5_835_VID 0x04fc #define SPCP8x5_835_PID 0x0231 -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(SPCP8x5_PHILIPS_VID , SPCP8x5_PHILIPS_PID)}, { USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)}, { USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)}, @@ -609,7 +609,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty, if (i < 0) dev_err(&port->dev, "Set UART format %#x failed (error = %d)\n", uartdata, i); - dbg("0x21:0x40:0:0 %d\n", i); + dbg("0x21:0x40:0:0 %d", i); if (cflag & CRTSCTS) { /* enable hardware flow control */ @@ -677,7 +677,6 @@ static void spcp8x5_read_bulk_callback(struct urb *urb) struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; unsigned long flags; - int i; int result = urb->status; u8 status; char tty_flag; @@ -687,8 +686,6 @@ static void spcp8x5_read_bulk_callback(struct urb *urb) /* check the urb status */ if (result) { - if (!port->port.count) - return; if (result == -EPROTO) { /* spcp8x5 mysteriously fails with -EPROTO */ /* reschedule the read */ @@ -726,26 +723,20 @@ static void spcp8x5_read_bulk_callback(struct urb *urb) tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { - tty_buffer_request_room(tty, urb->actual_length + 1); /* overrun is special, not associated with a char */ if (status & UART_OVERRUN_ERROR) tty_insert_flip_char(tty, 0, TTY_OVERRUN); - for (i = 0; i < urb->actual_length; ++i) - tty_insert_flip_char(tty, data[i], tty_flag); + tty_insert_flip_string_fixed_flag(tty, data, + urb->actual_length, tty_flag); tty_flip_buffer_push(tty); } tty_kref_put(tty); - /* Schedule the next read _if_ we are still open */ - if (port->port.count) { - urb->dev = port->serial->dev; - result = usb_submit_urb(urb , GFP_ATOMIC); - if (result) - dev_dbg(&port->dev, "failed submitting read urb %d\n", - result); - } - - return; + /* Schedule the next read */ + urb->dev = port->serial->dev; + result = usb_submit_urb(urb , GFP_ATOMIC); + if (result) + dev_dbg(&port->dev, "failed submitting read urb %d\n", result); } /* get data from ring buffer and then write to usb bus */ diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index b282c0f..ee190cc 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -21,7 +21,7 @@ static int debug; -static struct usb_device_id id_table[] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(0x05e0, 0x0600) }, { }, }; @@ -51,7 +51,6 @@ static void symbol_int_callback(struct urb *urb) int status = urb->status; struct tty_struct *tty; int result; - int available_room = 0; int data_length; dbg("%s - port %d", __func__, port->number); @@ -89,18 +88,13 @@ static void symbol_int_callback(struct urb *urb) */ tty = tty_port_tty_get(&port->port); if (tty) { - available_room = tty_buffer_request_room(tty, - data_length); - if (available_room) { - tty_insert_flip_string(tty, &data[1], - available_room); - tty_flip_buffer_push(tty); - } + tty_insert_flip_string(tty, &data[1], data_length); + tty_flip_buffer_push(tty); tty_kref_put(tty); } } else { dev_dbg(&priv->udev->dev, - "Improper ammount of data received from the device, " + "Improper amount of data received from the device, " "%d bytes", urb->actual_length); } diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 1e9dc88..0afe5c7 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -1271,14 +1271,13 @@ static void ti_recv(struct device *dev, struct tty_struct *tty, int cnt; do { - cnt = tty_buffer_request_room(tty, length); + cnt = tty_insert_flip_string(tty, data, length); if (cnt < length) { dev_err(dev, "%s - dropping data, %d bytes lost\n", __func__, length - cnt); if (cnt == 0) break; } - tty_insert_flip_string(tty, data, cnt); tty_flip_buffer_push(tty); data += cnt; length -= cnt; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 33c85f7..3873660 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -358,10 +358,6 @@ static int serial_write(struct tty_struct *tty, const unsigned char *buf, dbg("%s - port %d, %d byte(s)", __func__, port->number, count); - /* count is managed under the mutex lock for the tty so cannot - drop to zero until after the last close completes */ - WARN_ON(!port->port.count); - /* pass on to the driver specific version of this function */ retval = port->serial->type->write(tty, port, buf, count); @@ -373,7 +369,6 @@ static int serial_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->port.count); /* pass on to the driver specific version of this function */ return port->serial->type->write_room(tty); } @@ -381,7 +376,7 @@ 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; - dbg("%s = port %d", __func__, port->number); + dbg("%s - port %d", __func__, port->number); /* if the device was unplugged then any remaining characters fell out of the connector ;) */ @@ -396,7 +391,6 @@ static void serial_throttle(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->port.count); /* pass on to the driver specific version of this function */ if (port->serial->type->throttle) port->serial->type->throttle(tty); @@ -407,7 +401,6 @@ static void serial_unthrottle(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->port.count); /* pass on to the driver specific version of this function */ if (port->serial->type->unthrottle) port->serial->type->unthrottle(tty); @@ -421,8 +414,6 @@ static int serial_ioctl(struct tty_struct *tty, struct file *file, dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); - WARN_ON(!port->port.count); - /* pass on to the driver specific version of this function if it is available */ if (port->serial->type->ioctl) { @@ -437,7 +428,6 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old) struct usb_serial_port *port = tty->driver_data; dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->port.count); /* pass on to the driver specific version of this function if it is available */ if (port->serial->type->set_termios) @@ -452,7 +442,6 @@ static int serial_break(struct tty_struct *tty, int break_state) dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->port.count); /* pass on to the driver specific version of this function if it is available */ if (port->serial->type->break_ctl) @@ -513,7 +502,6 @@ static int serial_tiocmget(struct tty_struct *tty, struct file *file) dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->port.count); if (port->serial->type->tiocmget) return port->serial->type->tiocmget(tty, file); return -EINVAL; @@ -526,7 +514,6 @@ static int serial_tiocmset(struct tty_struct *tty, struct file *file, dbg("%s - port %d", __func__, port->number); - WARN_ON(!port->port.count); if (port->serial->type->tiocmset) return port->serial->type->tiocmset(tty, file, set, clear); return -EINVAL; diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index 7b5bfc4..252cc2d 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -29,7 +29,7 @@ static char USB_DEBUG_BRK[USB_DEBUG_BRK_SIZE] = { 0xff, }; -static struct usb_device_id id_table [] = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0525, 0x127a) }, { }, }; diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index ad1f923..0949427 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -368,7 +368,7 @@ static int visor_write(struct tty_struct *tty, struct usb_serial_port *port, spin_lock_irqsave(&priv->lock, flags); if (priv->outstanding_urbs > URB_UPPER_LIMIT) { spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - write limit hit\n", __func__); + dbg("%s - write limit hit", __func__); return 0; } priv->outstanding_urbs++; @@ -446,7 +446,7 @@ static int visor_write_room(struct tty_struct *tty) spin_lock_irqsave(&priv->lock, flags); if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) { spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - write limit hit\n", __func__); + dbg("%s - write limit hit", __func__); return 0; } spin_unlock_irqrestore(&priv->lock, flags); @@ -503,13 +503,9 @@ static void visor_read_bulk_callback(struct urb *urb) if (urb->actual_length) { tty = tty_port_tty_get(&port->port); if (tty) { - available_room = tty_buffer_request_room(tty, - urb->actual_length); - if (available_room) { - tty_insert_flip_string(tty, data, - available_room); - tty_flip_buffer_push(tty); - } + tty_insert_flip_string(tty, data, + urb->actual_length); + tty_flip_buffer_push(tty); tty_kref_put(tty); } spin_lock(&priv->lock); @@ -807,10 +803,14 @@ static int clie_3_5_startup(struct usb_serial *serial) { struct device *dev = &serial->dev->dev; int result; - u8 data; + u8 *data; dbg("%s", __func__); + data = kmalloc(1, GFP_KERNEL); + if (!data) + return -ENOMEM; + /* * Note that PEG-300 series devices expect the following two calls. */ @@ -818,36 +818,42 @@ static int clie_3_5_startup(struct usb_serial *serial) /* get the config number */ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQ_GET_CONFIGURATION, USB_DIR_IN, - 0, 0, &data, 1, 3000); + 0, 0, data, 1, 3000); if (result < 0) { dev_err(dev, "%s: get config number failed: %d\n", __func__, result); - return result; + goto out; } if (result != 1) { dev_err(dev, "%s: get config number bad return length: %d\n", __func__, result); - return -EIO; + result = -EIO; + goto out; } /* get the interface number */ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQ_GET_INTERFACE, USB_DIR_IN | USB_RECIP_INTERFACE, - 0, 0, &data, 1, 3000); + 0, 0, data, 1, 3000); if (result < 0) { dev_err(dev, "%s: get interface number failed: %d\n", __func__, result); - return result; + goto out; } if (result != 1) { dev_err(dev, "%s: get interface number bad return length: %d\n", __func__, result); - return -EIO; + result = -EIO; + goto out; } - return generic_startup(serial); + result = generic_startup(serial); +out: + kfree(data); + + return result; } static int treo_attach(struct usb_serial *serial) diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c new file mode 100644 index 0000000..f719d00 --- /dev/null +++ b/drivers/usb/serial/vivopay-serial.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2001-2005 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2009 Outpost Embedded, LLC + */ + +#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> + + +#define DRIVER_VERSION "v1.0" +#define DRIVER_DESC "ViVOpay USB Serial Driver" + +#define VIVOPAY_VENDOR_ID 0x1d5f + + +static struct usb_device_id id_table [] = { + /* ViVOpay 8800 */ + { USB_DEVICE(VIVOPAY_VENDOR_ID, 0x1004) }, + { }, +}; + +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver vivopay_serial_driver = { + .name = "vivopay-serial", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .no_dynamic_id = 1, +}; + +static struct usb_serial_driver vivopay_serial_device = { + .driver = { + .owner = THIS_MODULE, + .name = "vivopay-serial", + }, + .id_table = id_table, + .usb_driver = &vivopay_serial_driver, + .num_ports = 1, +}; + +static int __init vivopay_serial_init(void) +{ + int retval; + retval = usb_serial_register(&vivopay_serial_device); + if (retval) + goto failed_usb_serial_register; + retval = usb_register(&vivopay_serial_driver); + if (retval) + goto failed_usb_register; + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); + return 0; +failed_usb_register: + usb_serial_deregister(&vivopay_serial_device); +failed_usb_serial_register: + return retval; +} + +static void __exit vivopay_serial_exit(void) +{ + usb_deregister(&vivopay_serial_driver); + usb_serial_deregister(&vivopay_serial_device); +} + +module_init(vivopay_serial_init); +module_exit(vivopay_serial_exit); + +MODULE_AUTHOR("Forest Bond <forest.bond@outpostembedded.com>"); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 1093d2e..12ed820 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -111,17 +111,17 @@ static int debug; separate ID tables, and then a third table that combines them just for the purpose of exporting the autoloading information. */ -static struct usb_device_id id_table_std [] = { +static const struct usb_device_id id_table_std[] = { { USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_WHITE_HEAT_ID) }, { } /* Terminating entry */ }; -static struct usb_device_id id_table_prerenumeration [] = { +static const struct usb_device_id id_table_prerenumeration[] = { { USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_FAKE_WHITE_HEAT_ID) }, { } /* Terminating entry */ }; -static struct usb_device_id id_table_combined [] = { +static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_WHITE_HEAT_ID) }, { USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_FAKE_WHITE_HEAT_ID) }, { } /* Terminating entry */ @@ -1492,21 +1492,9 @@ static void rx_data_softint(struct work_struct *work) wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); urb = wrap->urb; - if (tty && urb->actual_length) { - int len = tty_buffer_request_room(tty, - urb->actual_length); - /* This stuff can go away now I suspect */ - if (unlikely(len < urb->actual_length)) { - spin_lock_irqsave(&info->lock, flags); - list_add(tmp, &info->rx_urb_q); - spin_unlock_irqrestore(&info->lock, flags); - tty_flip_buffer_push(tty); - schedule_work(&info->rx_work); - goto out; - } - tty_insert_flip_string(tty, urb->transfer_buffer, len); - sent += len; - } + if (tty && urb->actual_length) + sent += tty_insert_flip_string(tty, + urb->transfer_buffer, urb->actual_length); urb->dev = port->serial->dev; result = usb_submit_urb(urb, GFP_ATOMIC); |