diff options
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/cp210x.c | 1 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 77 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio_ids.h | 2 | ||||
-rw-r--r-- | drivers/usb/serial/io_ti.c | 5 | ||||
-rw-r--r-- | drivers/usb/serial/ir-usb.c | 21 | ||||
-rw-r--r-- | drivers/usb/serial/mct_u232.c | 2 | ||||
-rw-r--r-- | drivers/usb/serial/option.c | 12 | ||||
-rw-r--r-- | drivers/usb/serial/qcserial.c | 5 | ||||
-rw-r--r-- | drivers/usb/serial/upd78f0730.c | 6 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 243 |
10 files changed, 199 insertions, 175 deletions
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 0c55e7f64269..f64e914a8985 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -141,6 +141,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */ { USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */ { USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */ + { USB_DEVICE(0x10C4, 0x8A5E) }, /* CEL EM3588 ZigBee USB Stick Long Range */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d38780fa8788..1cec03799cdf 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -809,10 +809,10 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), - .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), - .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID, 1) }, + { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID, 1) }, + { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_PID, 1) }, + { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_H_PID, 1) }, { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID), @@ -1244,42 +1244,13 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, int div_okay = 1; int baud; - /* - * The logic involved in setting the baudrate can be cleanly split into - * 3 steps. - * 1. Standard baud rates are set in tty->termios->c_cflag - * 2. If these are not enough, you can set any speed using alt_speed as - * follows: - * - set tty->termios->c_cflag speed to B38400 - * - set your real speed in tty->alt_speed; it gets ignored when - * alt_speed==0, (or) - * - call TIOCSSERIAL ioctl with (struct serial_struct) set as - * follows: - * flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], - * this just sets alt_speed to (HI: 57600, VHI: 115200, - * SHI: 230400, WARP: 460800) - * ** Steps 1, 2 are done courtesy of tty_get_baud_rate - * 3. You can also set baud rate by setting custom divisor as follows - * - set tty->termios->c_cflag speed to B38400 - * - call TIOCSSERIAL ioctl with (struct serial_struct) set as - * follows: - * o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST - * o custom_divisor set to baud_base / your_new_baudrate - * ** Step 3 is done courtesy of code borrowed from serial.c - * I should really spend some time and separate + move this common - * code to serial.c, it is replicated in nearly every serial driver - * you see. - */ - - /* 1. Get the baud rate from the tty settings, this observes - alt_speed hack */ - baud = tty_get_baud_rate(tty); dev_dbg(dev, "%s - tty_get_baud_rate reports speed %d\n", __func__, baud); - /* 2. Observe async-compatible custom_divisor hack, update baudrate - if needed */ - + /* + * Observe deprecated async-compatible custom_divisor hack, update + * baudrate if needed. + */ if (baud == 38400 && ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && (priv->custom_divisor)) { @@ -1288,8 +1259,6 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, __func__, priv->custom_divisor, baud); } - /* 3. Convert baudrate to device-specific divisor */ - if (!baud) baud = 9600; switch (priv->chip_type) { @@ -1505,8 +1474,7 @@ static int set_serial_info(struct tty_struct *tty, /* Do error checking and permission checking */ if (!capable(CAP_SYS_ADMIN)) { - if (((new_serial.flags & ~ASYNC_USR_MASK) != - (priv->flags & ~ASYNC_USR_MASK))) { + if ((new_serial.flags ^ priv->flags) & ~ASYNC_USR_MASK) { mutex_unlock(&priv->cfg_lock); return -EPERM; } @@ -1527,26 +1495,17 @@ static int set_serial_info(struct tty_struct *tty, (new_serial.flags & ASYNC_FLAGS)); priv->custom_divisor = new_serial.custom_divisor; +check_and_exit: write_latency_timer(port); -check_and_exit: - if ((old_priv.flags & ASYNC_SPD_MASK) != - (priv->flags & ASYNC_SPD_MASK)) { - if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - tty->alt_speed = 57600; - else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - tty->alt_speed = 115200; - else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - tty->alt_speed = 230400; - else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - tty->alt_speed = 460800; - else - tty->alt_speed = 0; - } - if (((old_priv.flags & ASYNC_SPD_MASK) != - (priv->flags & ASYNC_SPD_MASK)) || - (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && - (old_priv.custom_divisor != priv->custom_divisor))) { + if ((priv->flags ^ old_priv.flags) & ASYNC_SPD_MASK || + ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && + priv->custom_divisor != old_priv.custom_divisor)) { + + /* warn about deprecation unless clearing */ + if (priv->flags & ASYNC_SPD_MASK) + dev_warn_ratelimited(&port->dev, "use of SPD flags is deprecated\n"); + change_speed(tty, port); mutex_unlock(&priv->cfg_lock); } diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 71fb9e59db71..4fcf1cecb6d7 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -882,6 +882,8 @@ /* Olimex */ #define OLIMEX_VID 0x15BA #define OLIMEX_ARM_USB_OCD_PID 0x0003 +#define OLIMEX_ARM_USB_TINY_PID 0x0004 +#define OLIMEX_ARM_USB_TINY_H_PID 0x002a #define OLIMEX_ARM_USB_OCD_H_PID 0x002b /* diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 87798e625d6c..6cefb9cb133d 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2336,8 +2336,11 @@ static void change_port_settings(struct tty_struct *tty, if (!baud) { /* pick a default, any default... */ baud = 9600; - } else + } else { + /* Avoid a zero divisor. */ + baud = min(baud, 461550); tty_encode_baud_rate(tty, baud, baud); + } edge_port->baud_rate = baud; config->wBaudRate = (__u16)((461550L + baud/2) / baud); diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 73956d48a0c5..f9734a96d516 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -197,6 +197,7 @@ static u8 ir_xbof_change(u8 xbof) static int ir_startup(struct usb_serial *serial) { struct usb_irda_cs_descriptor *irda_desc; + int rates; irda_desc = irda_usb_find_class_desc(serial, 0); if (!irda_desc) { @@ -205,18 +206,20 @@ static int ir_startup(struct usb_serial *serial) return -ENODEV; } + rates = le16_to_cpu(irda_desc->wBaudRate); + dev_dbg(&serial->dev->dev, "%s - Baud rates supported:%s%s%s%s%s%s%s%s%s\n", __func__, - (irda_desc->wBaudRate & USB_IRDA_BR_2400) ? " 2400" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_9600) ? " 9600" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_19200) ? " 19200" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_38400) ? " 38400" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_57600) ? " 57600" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_115200) ? " 115200" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_576000) ? " 576000" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_1152000) ? " 1152000" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_4000000) ? " 4000000" : ""); + (rates & USB_IRDA_BR_2400) ? " 2400" : "", + (rates & USB_IRDA_BR_9600) ? " 9600" : "", + (rates & USB_IRDA_BR_19200) ? " 19200" : "", + (rates & USB_IRDA_BR_38400) ? " 38400" : "", + (rates & USB_IRDA_BR_57600) ? " 57600" : "", + (rates & USB_IRDA_BR_115200) ? " 115200" : "", + (rates & USB_IRDA_BR_576000) ? " 576000" : "", + (rates & USB_IRDA_BR_1152000) ? " 1152000" : "", + (rates & USB_IRDA_BR_4000000) ? " 4000000" : ""); switch (irda_desc->bmAdditionalBOFs) { case USB_IRDA_AB_48: diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index edbc81f205c2..70f346f1aa86 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -189,7 +189,7 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty, return -ENOMEM; divisor = mct_u232_calculate_baud_rate(serial, value, &speed); - put_unaligned_le32(cpu_to_le32(divisor), buf); + put_unaligned_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, diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index af67a0de6b5d..ebe51f11105d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -281,6 +281,7 @@ static void option_instat_callback(struct urb *urb); #define TELIT_PRODUCT_LE922_USBCFG0 0x1042 #define TELIT_PRODUCT_LE922_USBCFG3 0x1043 #define TELIT_PRODUCT_LE922_USBCFG5 0x1045 +#define TELIT_PRODUCT_ME910 0x1100 #define TELIT_PRODUCT_LE920 0x1200 #define TELIT_PRODUCT_LE910 0x1201 #define TELIT_PRODUCT_LE910_USBCFG4 0x1206 @@ -640,6 +641,11 @@ static const struct option_blacklist_info simcom_sim7100e_blacklist = { .reserved = BIT(5) | BIT(6), }; +static const struct option_blacklist_info telit_me910_blacklist = { + .sendsetup = BIT(0), + .reserved = BIT(1) | BIT(3), +}; + static const struct option_blacklist_info telit_le910_blacklist = { .sendsetup = BIT(0), .reserved = BIT(1) | BIT(2), @@ -1235,6 +1241,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG5, 0xff), .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), + .driver_info = (kernel_ulong_t)&telit_me910_blacklist }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), .driver_info = (kernel_ulong_t)&telit_le910_blacklist }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4), @@ -1869,6 +1877,10 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&four_g_w100_blacklist }, { USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, SPEEDUP_PRODUCT_SU9800, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, 0x9801, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, 0x9803, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) }, { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 38b3f0d8cd58..ebc0beea69d6 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -158,10 +158,13 @@ static const struct usb_device_id id_table[] = { {DEVICE_SWI(0x1199, 0x9056)}, /* Sierra Wireless Modem */ {DEVICE_SWI(0x1199, 0x9060)}, /* Sierra Wireless Modem */ {DEVICE_SWI(0x1199, 0x9061)}, /* Sierra Wireless Modem */ + {DEVICE_SWI(0x1199, 0x9063)}, /* Sierra Wireless EM7305 */ {DEVICE_SWI(0x1199, 0x9070)}, /* Sierra Wireless MC74xx */ {DEVICE_SWI(0x1199, 0x9071)}, /* Sierra Wireless MC74xx */ {DEVICE_SWI(0x1199, 0x9078)}, /* Sierra Wireless EM74xx */ {DEVICE_SWI(0x1199, 0x9079)}, /* Sierra Wireless EM74xx */ + {DEVICE_SWI(0x1199, 0x907a)}, /* Sierra Wireless EM74xx QDL */ + {DEVICE_SWI(0x1199, 0x907b)}, /* Sierra Wireless EM74xx */ {DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ @@ -452,6 +455,8 @@ static struct usb_serial_driver qcdevice = { .write = usb_wwan_write, .write_room = usb_wwan_write_room, .chars_in_buffer = usb_wwan_chars_in_buffer, + .tiocmget = usb_wwan_tiocmget, + .tiocmset = usb_wwan_tiocmset, .attach = qc_attach, .release = qc_release, .port_probe = usb_wwan_port_probe, diff --git a/drivers/usb/serial/upd78f0730.c b/drivers/usb/serial/upd78f0730.c index a028dd2310c9..6819a3486e5d 100644 --- a/drivers/usb/serial/upd78f0730.c +++ b/drivers/usb/serial/upd78f0730.c @@ -288,7 +288,7 @@ static void upd78f0730_dtr_rts(struct usb_serial_port *port, int on) static speed_t upd78f0730_get_baud_rate(struct tty_struct *tty) { const speed_t baud_rate = tty_get_baud_rate(tty); - const speed_t supported[] = { + static const speed_t supported[] = { 0, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 153600 }; int i; @@ -384,7 +384,7 @@ static void upd78f0730_set_termios(struct tty_struct *tty, static int upd78f0730_open(struct tty_struct *tty, struct usb_serial_port *port) { - struct upd78f0730_open_close request = { + static const struct upd78f0730_open_close request = { .opcode = UPD78F0730_CMD_OPEN_CLOSE, .state = UPD78F0730_PORT_OPEN }; @@ -402,7 +402,7 @@ static int upd78f0730_open(struct tty_struct *tty, struct usb_serial_port *port) static void upd78f0730_close(struct usb_serial_port *port) { - struct upd78f0730_open_close request = { + static const struct upd78f0730_open_close request = { .opcode = UPD78F0730_CMD_OPEN_CLOSE, .state = UPD78F0730_PORT_CLOSE }; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index c7ca95f64edc..bb34f9f7eaf4 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -742,6 +742,124 @@ static void find_endpoints(struct usb_serial *serial, } } +static int setup_port_bulk_in(struct usb_serial_port *port, + struct usb_endpoint_descriptor *epd) +{ + struct usb_serial_driver *type = port->serial->type; + struct usb_device *udev = port->serial->dev; + int buffer_size; + int i; + + buffer_size = max_t(int, type->bulk_in_size, usb_endpoint_maxp(epd)); + port->bulk_in_size = buffer_size; + port->bulk_in_endpointAddress = epd->bEndpointAddress; + + for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) { + set_bit(i, &port->read_urbs_free); + port->read_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); + if (!port->read_urbs[i]) + return -ENOMEM; + port->bulk_in_buffers[i] = kmalloc(buffer_size, GFP_KERNEL); + if (!port->bulk_in_buffers[i]) + return -ENOMEM; + usb_fill_bulk_urb(port->read_urbs[i], udev, + usb_rcvbulkpipe(udev, epd->bEndpointAddress), + port->bulk_in_buffers[i], buffer_size, + type->read_bulk_callback, port); + } + + port->read_urb = port->read_urbs[0]; + port->bulk_in_buffer = port->bulk_in_buffers[0]; + + return 0; +} + +static int setup_port_bulk_out(struct usb_serial_port *port, + struct usb_endpoint_descriptor *epd) +{ + struct usb_serial_driver *type = port->serial->type; + struct usb_device *udev = port->serial->dev; + int buffer_size; + int i; + + if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL)) + return -ENOMEM; + if (type->bulk_out_size) + buffer_size = type->bulk_out_size; + else + buffer_size = usb_endpoint_maxp(epd); + port->bulk_out_size = buffer_size; + port->bulk_out_endpointAddress = epd->bEndpointAddress; + + for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) { + set_bit(i, &port->write_urbs_free); + port->write_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); + if (!port->write_urbs[i]) + return -ENOMEM; + port->bulk_out_buffers[i] = kmalloc(buffer_size, GFP_KERNEL); + if (!port->bulk_out_buffers[i]) + return -ENOMEM; + usb_fill_bulk_urb(port->write_urbs[i], udev, + usb_sndbulkpipe(udev, epd->bEndpointAddress), + port->bulk_out_buffers[i], buffer_size, + type->write_bulk_callback, port); + } + + port->write_urb = port->write_urbs[0]; + port->bulk_out_buffer = port->bulk_out_buffers[0]; + + return 0; +} + +static int setup_port_interrupt_in(struct usb_serial_port *port, + struct usb_endpoint_descriptor *epd) +{ + struct usb_serial_driver *type = port->serial->type; + struct usb_device *udev = port->serial->dev; + int buffer_size; + + port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!port->interrupt_in_urb) + return -ENOMEM; + buffer_size = usb_endpoint_maxp(epd); + port->interrupt_in_endpointAddress = epd->bEndpointAddress; + port->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!port->interrupt_in_buffer) + return -ENOMEM; + usb_fill_int_urb(port->interrupt_in_urb, udev, + usb_rcvintpipe(udev, epd->bEndpointAddress), + port->interrupt_in_buffer, buffer_size, + type->read_int_callback, port, + epd->bInterval); + + return 0; +} + +static int setup_port_interrupt_out(struct usb_serial_port *port, + struct usb_endpoint_descriptor *epd) +{ + struct usb_serial_driver *type = port->serial->type; + struct usb_device *udev = port->serial->dev; + int buffer_size; + + port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!port->interrupt_out_urb) + return -ENOMEM; + buffer_size = usb_endpoint_maxp(epd); + port->interrupt_out_size = buffer_size; + port->interrupt_out_endpointAddress = epd->bEndpointAddress; + port->interrupt_out_buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!port->interrupt_out_buffer) + return -ENOMEM; + usb_fill_int_urb(port->interrupt_out_urb, udev, + usb_sndintpipe(udev, epd->bEndpointAddress), + port->interrupt_out_buffer, buffer_size, + type->write_int_callback, port, + epd->bInterval); + + return 0; +} + static int usb_serial_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -749,13 +867,10 @@ static int usb_serial_probe(struct usb_interface *interface, struct usb_device *dev = interface_to_usbdev(interface); struct usb_serial *serial = NULL; struct usb_serial_port *port; - struct usb_endpoint_descriptor *endpoint; struct usb_serial_endpoints *epds; struct usb_serial_driver *type = NULL; int retval; - int buffer_size; int i; - int j; int num_ports = 0; unsigned char max_endpoints; @@ -847,8 +962,10 @@ static int usb_serial_probe(struct usb_interface *interface, dev_dbg(ddev, "setting up %d port structure(s)\n", max_endpoints); for (i = 0; i < max_endpoints; ++i) { port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); - if (!port) - goto probe_error; + if (!port) { + retval = -ENOMEM; + goto err_free_epds; + } tty_port_init(&port->port); port->port.ops = &serial_port_ops; port->serial = serial; @@ -867,86 +984,24 @@ static int usb_serial_probe(struct usb_interface *interface, /* set up the endpoint information */ for (i = 0; i < epds->num_bulk_in; ++i) { - endpoint = epds->bulk_in[i]; - port = serial->port[i]; - buffer_size = max_t(int, serial->type->bulk_in_size, - usb_endpoint_maxp(endpoint)); - port->bulk_in_size = buffer_size; - port->bulk_in_endpointAddress = endpoint->bEndpointAddress; - - for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) { - set_bit(j, &port->read_urbs_free); - port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL); - if (!port->read_urbs[j]) - goto probe_error; - port->bulk_in_buffers[j] = kmalloc(buffer_size, - GFP_KERNEL); - if (!port->bulk_in_buffers[j]) - goto probe_error; - usb_fill_bulk_urb(port->read_urbs[j], dev, - usb_rcvbulkpipe(dev, - endpoint->bEndpointAddress), - port->bulk_in_buffers[j], buffer_size, - serial->type->read_bulk_callback, - port); - } - - port->read_urb = port->read_urbs[0]; - port->bulk_in_buffer = port->bulk_in_buffers[0]; + retval = setup_port_bulk_in(serial->port[i], epds->bulk_in[i]); + if (retval) + goto err_free_epds; } for (i = 0; i < epds->num_bulk_out; ++i) { - endpoint = epds->bulk_out[i]; - port = serial->port[i]; - if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL)) - goto probe_error; - buffer_size = serial->type->bulk_out_size; - if (!buffer_size) - buffer_size = usb_endpoint_maxp(endpoint); - port->bulk_out_size = buffer_size; - port->bulk_out_endpointAddress = endpoint->bEndpointAddress; - - for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) { - set_bit(j, &port->write_urbs_free); - port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL); - if (!port->write_urbs[j]) - goto probe_error; - port->bulk_out_buffers[j] = kmalloc(buffer_size, - GFP_KERNEL); - if (!port->bulk_out_buffers[j]) - goto probe_error; - usb_fill_bulk_urb(port->write_urbs[j], dev, - usb_sndbulkpipe(dev, - endpoint->bEndpointAddress), - port->bulk_out_buffers[j], buffer_size, - serial->type->write_bulk_callback, - port); - } - - port->write_urb = port->write_urbs[0]; - port->bulk_out_buffer = port->bulk_out_buffers[0]; + retval = setup_port_bulk_out(serial->port[i], + epds->bulk_out[i]); + if (retval) + goto err_free_epds; } if (serial->type->read_int_callback) { for (i = 0; i < epds->num_interrupt_in; ++i) { - endpoint = epds->interrupt_in[i]; - port = serial->port[i]; - port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!port->interrupt_in_urb) - goto probe_error; - buffer_size = usb_endpoint_maxp(endpoint); - port->interrupt_in_endpointAddress = - endpoint->bEndpointAddress; - port->interrupt_in_buffer = kmalloc(buffer_size, - GFP_KERNEL); - if (!port->interrupt_in_buffer) - goto probe_error; - usb_fill_int_urb(port->interrupt_in_urb, dev, - usb_rcvintpipe(dev, - endpoint->bEndpointAddress), - port->interrupt_in_buffer, buffer_size, - serial->type->read_int_callback, port, - endpoint->bInterval); + retval = setup_port_interrupt_in(serial->port[i], + epds->interrupt_in[i]); + if (retval) + goto err_free_epds; } } else if (epds->num_interrupt_in) { dev_dbg(ddev, "The device claims to support interrupt in transfers, but read_int_callback is not defined\n"); @@ -954,25 +1009,10 @@ static int usb_serial_probe(struct usb_interface *interface, if (serial->type->write_int_callback) { for (i = 0; i < epds->num_interrupt_out; ++i) { - endpoint = epds->interrupt_out[i]; - port = serial->port[i]; - port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!port->interrupt_out_urb) - goto probe_error; - buffer_size = usb_endpoint_maxp(endpoint); - port->interrupt_out_size = buffer_size; - port->interrupt_out_endpointAddress = - endpoint->bEndpointAddress; - port->interrupt_out_buffer = kmalloc(buffer_size, - GFP_KERNEL); - if (!port->interrupt_out_buffer) - goto probe_error; - usb_fill_int_urb(port->interrupt_out_urb, dev, - usb_sndintpipe(dev, - endpoint->bEndpointAddress), - port->interrupt_out_buffer, buffer_size, - serial->type->write_int_callback, port, - endpoint->bInterval); + retval = setup_port_interrupt_out(serial->port[i], + epds->interrupt_out[i]); + if (retval) + goto err_free_epds; } } else if (epds->num_interrupt_out) { dev_dbg(ddev, "The device claims to support interrupt out transfers, but write_int_callback is not defined\n"); @@ -984,7 +1024,7 @@ static int usb_serial_probe(struct usb_interface *interface, if (type->attach) { retval = type->attach(serial); if (retval < 0) - goto probe_error; + goto err_free_epds; serial->attached = 1; if (retval > 0) { /* quietly accept this device, but don't bind to a @@ -996,9 +1036,10 @@ static int usb_serial_probe(struct usb_interface *interface, serial->attached = 1; } - if (allocate_minors(serial, num_ports)) { + retval = allocate_minors(serial, num_ports); + if (retval) { dev_err(ddev, "No more free serial minor numbers\n"); - goto probe_error; + goto err_free_epds; } /* register all of the individual ports with the driver core */ @@ -1020,8 +1061,6 @@ exit: module_put(type->driver.owner); return 0; -probe_error: - retval = -EIO; err_free_epds: kfree(epds); err_put_serial: |