Commit c8d204b3 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'usb-serial-4.10-rc3' of...

Merge tag 'usb-serial-4.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-linus

Johan writes:

USB-serial fixes for v4.10-rc3

These fixes address a number of long-standing issues in various
USB-serial drivers which would lead to crashes should a malicious device
lack the expected endpoints.

Included are also a few related fixes, and a couple of unrelated ones
that were found during my survey (e.g. a memleak and a
sleep-while-atomic).

A compiler warning revealed an error-handling issue in the new f81534
driver which is also fixed.
Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
parents 29fc1aa4 ef079936
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#define CYBERJACK_PRODUCT_ID 0x0100 #define CYBERJACK_PRODUCT_ID 0x0100
/* Function prototypes */ /* Function prototypes */
static int cyberjack_attach(struct usb_serial *serial);
static int cyberjack_port_probe(struct usb_serial_port *port); static int cyberjack_port_probe(struct usb_serial_port *port);
static int cyberjack_port_remove(struct usb_serial_port *port); static int cyberjack_port_remove(struct usb_serial_port *port);
static int cyberjack_open(struct tty_struct *tty, static int cyberjack_open(struct tty_struct *tty,
...@@ -77,6 +78,7 @@ static struct usb_serial_driver cyberjack_device = { ...@@ -77,6 +78,7 @@ static struct usb_serial_driver cyberjack_device = {
.description = "Reiner SCT Cyberjack USB card reader", .description = "Reiner SCT Cyberjack USB card reader",
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_ports = 1,
.attach = cyberjack_attach,
.port_probe = cyberjack_port_probe, .port_probe = cyberjack_port_probe,
.port_remove = cyberjack_port_remove, .port_remove = cyberjack_port_remove,
.open = cyberjack_open, .open = cyberjack_open,
...@@ -100,6 +102,14 @@ struct cyberjack_private { ...@@ -100,6 +102,14 @@ struct cyberjack_private {
short wrsent; /* Data already sent */ short wrsent; /* Data already sent */
}; };
static int cyberjack_attach(struct usb_serial *serial)
{
if (serial->num_bulk_out < serial->num_ports)
return -ENODEV;
return 0;
}
static int cyberjack_port_probe(struct usb_serial_port *port) static int cyberjack_port_probe(struct usb_serial_port *port)
{ {
struct cyberjack_private *priv; struct cyberjack_private *priv;
......
...@@ -1237,6 +1237,7 @@ static int f81534_attach(struct usb_serial *serial) ...@@ -1237,6 +1237,7 @@ static int f81534_attach(struct usb_serial *serial)
static int f81534_port_probe(struct usb_serial_port *port) static int f81534_port_probe(struct usb_serial_port *port)
{ {
struct f81534_port_private *port_priv; struct f81534_port_private *port_priv;
int ret;
port_priv = devm_kzalloc(&port->dev, sizeof(*port_priv), GFP_KERNEL); port_priv = devm_kzalloc(&port->dev, sizeof(*port_priv), GFP_KERNEL);
if (!port_priv) if (!port_priv)
...@@ -1246,10 +1247,11 @@ static int f81534_port_probe(struct usb_serial_port *port) ...@@ -1246,10 +1247,11 @@ static int f81534_port_probe(struct usb_serial_port *port)
mutex_init(&port_priv->mcr_mutex); mutex_init(&port_priv->mcr_mutex);
/* Assign logic-to-phy mapping */ /* Assign logic-to-phy mapping */
port_priv->phy_num = f81534_logic_to_phy_port(port->serial, port); ret = f81534_logic_to_phy_port(port->serial, port);
if (port_priv->phy_num < 0 || port_priv->phy_num >= F81534_NUM_PORT) if (ret < 0)
return -ENODEV; return ret;
port_priv->phy_num = ret;
usb_set_serial_port_data(port, port_priv); usb_set_serial_port_data(port, port_priv);
dev_dbg(&port->dev, "%s: port_number: %d, phy_num: %d\n", __func__, dev_dbg(&port->dev, "%s: port_number: %d, phy_num: %d\n", __func__,
port->port_number, port_priv->phy_num); port->port_number, port_priv->phy_num);
......
...@@ -1043,6 +1043,7 @@ static int garmin_write_bulk(struct usb_serial_port *port, ...@@ -1043,6 +1043,7 @@ static int garmin_write_bulk(struct usb_serial_port *port,
"%s - usb_submit_urb(write bulk) failed with status = %d\n", "%s - usb_submit_urb(write bulk) failed with status = %d\n",
__func__, status); __func__, status);
count = status; count = status;
kfree(buffer);
} }
/* we are done with this urb, so let the host driver /* we are done with this urb, so let the host driver
......
...@@ -2751,6 +2751,11 @@ static int edge_startup(struct usb_serial *serial) ...@@ -2751,6 +2751,11 @@ static int edge_startup(struct usb_serial *serial)
EDGE_COMPATIBILITY_MASK1, EDGE_COMPATIBILITY_MASK1,
EDGE_COMPATIBILITY_MASK2 }; EDGE_COMPATIBILITY_MASK2 };
if (serial->num_bulk_in < 1 || serial->num_interrupt_in < 1) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
dev = serial->dev; dev = serial->dev;
/* create our private serial structure */ /* create our private serial structure */
......
...@@ -1499,8 +1499,7 @@ static int do_boot_mode(struct edgeport_serial *serial, ...@@ -1499,8 +1499,7 @@ static int do_boot_mode(struct edgeport_serial *serial,
dev_dbg(dev, "%s - Download successful -- Device rebooting...\n", __func__); dev_dbg(dev, "%s - Download successful -- Device rebooting...\n", __func__);
/* return an error on purpose */ return 1;
return -ENODEV;
} }
stayinbootmode: stayinbootmode:
...@@ -1508,7 +1507,7 @@ static int do_boot_mode(struct edgeport_serial *serial, ...@@ -1508,7 +1507,7 @@ static int do_boot_mode(struct edgeport_serial *serial,
dev_dbg(dev, "%s - STAYING IN BOOT MODE\n", __func__); dev_dbg(dev, "%s - STAYING IN BOOT MODE\n", __func__);
serial->product_info.TiMode = TI_MODE_BOOT; serial->product_info.TiMode = TI_MODE_BOOT;
return 0; return 1;
} }
static int ti_do_config(struct edgeport_port *port, int feature, int on) static int ti_do_config(struct edgeport_port *port, int feature, int on)
...@@ -2546,6 +2545,13 @@ static int edge_startup(struct usb_serial *serial) ...@@ -2546,6 +2545,13 @@ static int edge_startup(struct usb_serial *serial)
int status; int status;
u16 product_id; u16 product_id;
/* Make sure we have the required endpoints when in download mode. */
if (serial->interface->cur_altsetting->desc.bNumEndpoints > 1) {
if (serial->num_bulk_in < serial->num_ports ||
serial->num_bulk_out < serial->num_ports)
return -ENODEV;
}
/* create our private serial structure */ /* create our private serial structure */
edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
if (!edge_serial) if (!edge_serial)
...@@ -2553,14 +2559,18 @@ static int edge_startup(struct usb_serial *serial) ...@@ -2553,14 +2559,18 @@ static int edge_startup(struct usb_serial *serial)
mutex_init(&edge_serial->es_lock); mutex_init(&edge_serial->es_lock);
edge_serial->serial = serial; edge_serial->serial = serial;
INIT_DELAYED_WORK(&edge_serial->heartbeat_work, edge_heartbeat_work);
usb_set_serial_data(serial, edge_serial); usb_set_serial_data(serial, edge_serial);
status = download_fw(edge_serial); status = download_fw(edge_serial);
if (status) { if (status < 0) {
kfree(edge_serial); kfree(edge_serial);
return status; return status;
} }
if (status > 0)
return 1; /* bind but do not register any ports */
product_id = le16_to_cpu( product_id = le16_to_cpu(
edge_serial->serial->dev->descriptor.idProduct); edge_serial->serial->dev->descriptor.idProduct);
...@@ -2572,7 +2582,6 @@ static int edge_startup(struct usb_serial *serial) ...@@ -2572,7 +2582,6 @@ static int edge_startup(struct usb_serial *serial)
} }
} }
INIT_DELAYED_WORK(&edge_serial->heartbeat_work, edge_heartbeat_work);
edge_heartbeat_schedule(edge_serial); edge_heartbeat_schedule(edge_serial);
return 0; return 0;
...@@ -2580,6 +2589,9 @@ static int edge_startup(struct usb_serial *serial) ...@@ -2580,6 +2589,9 @@ static int edge_startup(struct usb_serial *serial)
static void edge_disconnect(struct usb_serial *serial) static void edge_disconnect(struct usb_serial *serial)
{ {
struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
cancel_delayed_work_sync(&edge_serial->heartbeat_work);
} }
static void edge_release(struct usb_serial *serial) static void edge_release(struct usb_serial *serial)
......
...@@ -68,6 +68,16 @@ struct iuu_private { ...@@ -68,6 +68,16 @@ struct iuu_private {
u32 clk; u32 clk;
}; };
static int iuu_attach(struct usb_serial *serial)
{
unsigned char num_ports = serial->num_ports;
if (serial->num_bulk_in < num_ports || serial->num_bulk_out < num_ports)
return -ENODEV;
return 0;
}
static int iuu_port_probe(struct usb_serial_port *port) static int iuu_port_probe(struct usb_serial_port *port)
{ {
struct iuu_private *priv; struct iuu_private *priv;
...@@ -1196,6 +1206,7 @@ static struct usb_serial_driver iuu_device = { ...@@ -1196,6 +1206,7 @@ static struct usb_serial_driver iuu_device = {
.tiocmset = iuu_tiocmset, .tiocmset = iuu_tiocmset,
.set_termios = iuu_set_termios, .set_termios = iuu_set_termios,
.init_termios = iuu_init_termios, .init_termios = iuu_init_termios,
.attach = iuu_attach,
.port_probe = iuu_port_probe, .port_probe = iuu_port_probe,
.port_remove = iuu_port_remove, .port_remove = iuu_port_remove,
}; };
......
...@@ -699,6 +699,19 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw"); ...@@ -699,6 +699,19 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw");
MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw");
#endif #endif
static int keyspan_pda_attach(struct usb_serial *serial)
{
unsigned char num_ports = serial->num_ports;
if (serial->num_bulk_out < num_ports ||
serial->num_interrupt_in < num_ports) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
return 0;
}
static int keyspan_pda_port_probe(struct usb_serial_port *port) static int keyspan_pda_port_probe(struct usb_serial_port *port)
{ {
...@@ -776,6 +789,7 @@ static struct usb_serial_driver keyspan_pda_device = { ...@@ -776,6 +789,7 @@ static struct usb_serial_driver keyspan_pda_device = {
.break_ctl = keyspan_pda_break_ctl, .break_ctl = keyspan_pda_break_ctl,
.tiocmget = keyspan_pda_tiocmget, .tiocmget = keyspan_pda_tiocmget,
.tiocmset = keyspan_pda_tiocmset, .tiocmset = keyspan_pda_tiocmset,
.attach = keyspan_pda_attach,
.port_probe = keyspan_pda_port_probe, .port_probe = keyspan_pda_port_probe,
.port_remove = keyspan_pda_port_remove, .port_remove = keyspan_pda_port_remove,
}; };
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
/* Function prototypes */ /* Function prototypes */
static int kobil_attach(struct usb_serial *serial);
static int kobil_port_probe(struct usb_serial_port *probe); static int kobil_port_probe(struct usb_serial_port *probe);
static int kobil_port_remove(struct usb_serial_port *probe); static int kobil_port_remove(struct usb_serial_port *probe);
static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port);
...@@ -86,6 +87,7 @@ static struct usb_serial_driver kobil_device = { ...@@ -86,6 +87,7 @@ static struct usb_serial_driver kobil_device = {
.description = "KOBIL USB smart card terminal", .description = "KOBIL USB smart card terminal",
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_ports = 1,
.attach = kobil_attach,
.port_probe = kobil_port_probe, .port_probe = kobil_port_probe,
.port_remove = kobil_port_remove, .port_remove = kobil_port_remove,
.ioctl = kobil_ioctl, .ioctl = kobil_ioctl,
...@@ -113,6 +115,16 @@ struct kobil_private { ...@@ -113,6 +115,16 @@ struct kobil_private {
}; };
static int kobil_attach(struct usb_serial *serial)
{
if (serial->num_interrupt_out < serial->num_ports) {
dev_err(&serial->interface->dev, "missing interrupt-out endpoint\n");
return -ENODEV;
}
return 0;
}
static int kobil_port_probe(struct usb_serial_port *port) static int kobil_port_probe(struct usb_serial_port *port)
{ {
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
......
...@@ -65,8 +65,6 @@ struct moschip_port { ...@@ -65,8 +65,6 @@ struct moschip_port {
struct urb *write_urb_pool[NUM_URBS]; struct urb *write_urb_pool[NUM_URBS];
}; };
static struct usb_serial_driver moschip7720_2port_driver;
#define USB_VENDOR_ID_MOSCHIP 0x9710 #define USB_VENDOR_ID_MOSCHIP 0x9710
#define MOSCHIP_DEVICE_ID_7720 0x7720 #define MOSCHIP_DEVICE_ID_7720 0x7720
#define MOSCHIP_DEVICE_ID_7715 0x7715 #define MOSCHIP_DEVICE_ID_7715 0x7715
...@@ -970,25 +968,6 @@ static void mos7720_bulk_out_data_callback(struct urb *urb) ...@@ -970,25 +968,6 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
tty_port_tty_wakeup(&mos7720_port->port->port); tty_port_tty_wakeup(&mos7720_port->port->port);
} }
/*
* 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) static int mos77xx_calc_num_ports(struct usb_serial *serial)
{ {
u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
...@@ -1917,6 +1896,11 @@ static int mos7720_startup(struct usb_serial *serial) ...@@ -1917,6 +1896,11 @@ static int mos7720_startup(struct usb_serial *serial)
u16 product; u16 product;
int ret_val; int ret_val;
if (serial->num_bulk_in < 2 || serial->num_bulk_out < 2) {
dev_err(&serial->interface->dev, "missing bulk endpoints\n");
return -ENODEV;
}
product = le16_to_cpu(serial->dev->descriptor.idProduct); product = le16_to_cpu(serial->dev->descriptor.idProduct);
dev = serial->dev; dev = serial->dev;
...@@ -1941,19 +1925,18 @@ static int mos7720_startup(struct usb_serial *serial) ...@@ -1941,19 +1925,18 @@ static int mos7720_startup(struct usb_serial *serial)
tmp->interrupt_in_endpointAddress; tmp->interrupt_in_endpointAddress;
serial->port[1]->interrupt_in_urb = NULL; serial->port[1]->interrupt_in_urb = NULL;
serial->port[1]->interrupt_in_buffer = NULL; serial->port[1]->interrupt_in_buffer = NULL;
if (serial->port[0]->interrupt_in_urb) {
struct urb *urb = serial->port[0]->interrupt_in_urb;
urb->complete = mos7715_interrupt_callback;
}
} }
/* setting configuration feature to one */ /* setting configuration feature to one */
usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
(__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000); (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000);
/* start the interrupt urb */
ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL);
if (ret_val)
dev_err(&dev->dev,
"%s - Error %d submitting control urb\n",
__func__, ret_val);
#ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
if (product == MOSCHIP_DEVICE_ID_7715) { if (product == MOSCHIP_DEVICE_ID_7715) {
ret_val = mos7715_parport_init(serial); ret_val = mos7715_parport_init(serial);
...@@ -1961,6 +1944,13 @@ static int mos7720_startup(struct usb_serial *serial) ...@@ -1961,6 +1944,13 @@ static int mos7720_startup(struct usb_serial *serial)
return ret_val; return ret_val;
} }
#endif #endif
/* start the interrupt urb */
ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL);
if (ret_val) {
dev_err(&dev->dev, "failed to submit interrupt urb: %d\n",
ret_val);
}
/* LSR For Port 1 */ /* LSR For Port 1 */
read_mos_reg(serial, 0, MOS7720_LSR, &data); read_mos_reg(serial, 0, MOS7720_LSR, &data);
dev_dbg(&dev->dev, "LSR:%x\n", data); dev_dbg(&dev->dev, "LSR:%x\n", data);
...@@ -1970,6 +1960,8 @@ static int mos7720_startup(struct usb_serial *serial) ...@@ -1970,6 +1960,8 @@ static int mos7720_startup(struct usb_serial *serial)
static void mos7720_release(struct usb_serial *serial) static void mos7720_release(struct usb_serial *serial)
{ {
usb_kill_urb(serial->port[0]->interrupt_in_urb);
#ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
/* close the parallel port */ /* close the parallel port */
...@@ -2019,11 +2011,6 @@ static int mos7720_port_probe(struct usb_serial_port *port) ...@@ -2019,11 +2011,6 @@ static int mos7720_port_probe(struct usb_serial_port *port)
if (!mos7720_port) if (!mos7720_port)
return -ENOMEM; return -ENOMEM;
/* Initialize all port interrupt end point to port 0 int endpoint.
* Our device has only one interrupt endpoint common to all ports.
*/
port->interrupt_in_endpointAddress =
port->serial->port[0]->interrupt_in_endpointAddress;
mos7720_port->port = port; mos7720_port->port = port;
usb_set_serial_port_data(port, mos7720_port); usb_set_serial_port_data(port, mos7720_port);
...@@ -2053,7 +2040,6 @@ static struct usb_serial_driver moschip7720_2port_driver = { ...@@ -2053,7 +2040,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {
.close = mos7720_close, .close = mos7720_close,
.throttle = mos7720_throttle, .throttle = mos7720_throttle,
.unthrottle = mos7720_unthrottle, .unthrottle = mos7720_unthrottle,
.probe = mos77xx_probe,
.attach = mos7720_startup, .attach = mos7720_startup,
.release = mos7720_release, .release = mos7720_release,
.port_probe = mos7720_port_probe, .port_probe = mos7720_port_probe,
...@@ -2067,7 +2053,7 @@ static struct usb_serial_driver moschip7720_2port_driver = { ...@@ -2067,7 +2053,7 @@ static struct usb_serial_driver moschip7720_2port_driver = {
.chars_in_buffer = mos7720_chars_in_buffer, .chars_in_buffer = mos7720_chars_in_buffer,
.break_ctl = mos7720_break, .break_ctl = mos7720_break,
.read_bulk_callback = mos7720_bulk_in_callback, .read_bulk_callback = mos7720_bulk_in_callback,
.read_int_callback = NULL /* dynamically assigned in probe() */ .read_int_callback = mos7720_interrupt_callback,
}; };
static struct usb_serial_driver * const serial_drivers[] = { static struct usb_serial_driver * const serial_drivers[] = {
......
...@@ -214,7 +214,6 @@ MODULE_DEVICE_TABLE(usb, id_table); ...@@ -214,7 +214,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
struct moschip_port { struct moschip_port {
int port_num; /*Actual port number in the device(1,2,etc) */ int port_num; /*Actual port number in the device(1,2,etc) */
struct urb *write_urb; /* write URB for this port */
struct urb *read_urb; /* read URB for this port */ struct urb *read_urb; /* read URB for this port */
__u8 shadowLCR; /* last LCR value received */ __u8 shadowLCR; /* last LCR value received */
__u8 shadowMCR; /* last MCR value received */ __u8 shadowMCR; /* last MCR value received */
...@@ -1037,9 +1036,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) ...@@ -1037,9 +1036,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
serial, serial,
serial->port[0]->interrupt_in_urb->interval); serial->port[0]->interrupt_in_urb->interval);
/* start interrupt read for mos7840 * /* start interrupt read for mos7840 */
* will continue as long as mos7840 is connected */
response = response =
usb_submit_urb(serial->port[0]->interrupt_in_urb, usb_submit_urb(serial->port[0]->interrupt_in_urb,
GFP_KERNEL); GFP_KERNEL);
...@@ -1186,7 +1183,6 @@ static void mos7840_close(struct usb_serial_port *port) ...@@ -1186,7 +1183,6 @@ static void mos7840_close(struct usb_serial_port *port)
} }
} }
usb_kill_urb(mos7840_port->write_urb);
usb_kill_urb(mos7840_port->read_urb); usb_kill_urb(mos7840_port->read_urb);
mos7840_port->read_urb_busy = false; mos7840_port->read_urb_busy = false;
...@@ -1199,12 +1195,6 @@ static void mos7840_close(struct usb_serial_port *port) ...@@ -1199,12 +1195,6 @@ static void mos7840_close(struct usb_serial_port *port)
} }
} }
if (mos7840_port->write_urb) {
/* if this urb had a transfer buffer already (old tx) free it */
kfree(mos7840_port->write_urb->transfer_buffer);
usb_free_urb(mos7840_port->write_urb);
}
Data = 0x0; Data = 0x0;
mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
...@@ -2113,6 +2103,17 @@ static int mos7840_calc_num_ports(struct usb_serial *serial) ...@@ -2113,6 +2103,17 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)
return mos7840_num_ports; return mos7840_num_ports;
} }
static int mos7840_attach(struct usb_serial *serial)
{
if (serial->num_bulk_in < serial->num_ports ||
serial->num_bulk_out < serial->num_ports) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
return 0;
}
static int mos7840_port_probe(struct usb_serial_port *port) static int mos7840_port_probe(struct usb_serial_port *port)
{ {
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
...@@ -2388,6 +2389,7 @@ static struct usb_serial_driver moschip7840_4port_device = { ...@@ -2388,6 +2389,7 @@ static struct usb_serial_driver moschip7840_4port_device = {
.tiocmset = mos7840_tiocmset, .tiocmset = mos7840_tiocmset,
.tiocmiwait = usb_serial_generic_tiocmiwait, .tiocmiwait = usb_serial_generic_tiocmiwait,
.get_icount = usb_serial_generic_get_icount, .get_icount = usb_serial_generic_get_icount,
.attach = mos7840_attach,
.port_probe = mos7840_port_probe, .port_probe = mos7840_port_probe,
.port_remove = mos7840_port_remove, .port_remove = mos7840_port_remove,
.read_bulk_callback = mos7840_bulk_in_callback, .read_bulk_callback = mos7840_bulk_in_callback,
......
...@@ -38,6 +38,7 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -38,6 +38,7 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count); const unsigned char *buf, int count);
static int omninet_write_room(struct tty_struct *tty); static int omninet_write_room(struct tty_struct *tty);
static void omninet_disconnect(struct usb_serial *serial); static void omninet_disconnect(struct usb_serial *serial);
static int omninet_attach(struct usb_serial *serial);
static int omninet_port_probe(struct usb_serial_port *port); static int omninet_port_probe(struct usb_serial_port *port);
static int omninet_port_remove(struct usb_serial_port *port); static int omninet_port_remove(struct usb_serial_port *port);
...@@ -56,6 +57,7 @@ static struct usb_serial_driver zyxel_omninet_device = { ...@@ -56,6 +57,7 @@ static struct usb_serial_driver zyxel_omninet_device = {
.description = "ZyXEL - omni.net lcd plus usb", .description = "ZyXEL - omni.net lcd plus usb",
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_ports = 1,
.attach = omninet_attach,
.port_probe = omninet_port_probe, .port_probe = omninet_port_probe,
.port_remove = omninet_port_remove, .port_remove = omninet_port_remove,
.open = omninet_open, .open = omninet_open,
...@@ -104,6 +106,17 @@ struct omninet_data { ...@@ -104,6 +106,17 @@ struct omninet_data {
__u8 od_outseq; /* Sequence number for bulk_out URBs */ __u8 od_outseq; /* Sequence number for bulk_out URBs */
}; };
static int omninet_attach(struct usb_serial *serial)
{
/* The second bulk-out endpoint is used for writing. */
if (serial->num_bulk_out < 2) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
return 0;
}
static int omninet_port_probe(struct usb_serial_port *port) static int omninet_port_probe(struct usb_serial_port *port)
{ {
struct omninet_data *od; struct omninet_data *od;
......
...@@ -134,6 +134,7 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty); ...@@ -134,6 +134,7 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty);
static int oti6858_tiocmget(struct tty_struct *tty); static int oti6858_tiocmget(struct tty_struct *tty);
static int oti6858_tiocmset(struct tty_struct *tty, static int oti6858_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear); unsigned int set, unsigned int clear);
static int oti6858_attach(struct usb_serial *serial);
static int oti6858_port_probe(struct usb_serial_port *port); static int oti6858_port_probe(struct usb_serial_port *port);
static int oti6858_port_remove(struct usb_serial_port *port); static int oti6858_port_remove(struct usb_serial_port *port);
...@@ -158,6 +159,7 @@ static struct usb_serial_driver oti6858_device = { ...@@ -158,6 +159,7 @@ static struct usb_serial_driver oti6858_device = {
.write_bulk_callback = oti6858_write_bulk_callback, .write_bulk_callback = oti6858_write_bulk_callback,
.write_room = oti6858_write_room, .write_room = oti6858_write_room,
.chars_in_buffer = oti6858_chars_in_buffer, .chars_in_buffer = oti6858_chars_in_buffer,
.attach = oti6858_attach,
.port_probe = oti6858_port_probe, .port_probe = oti6858_port_probe,
.port_remove = oti6858_port_remove, .port_remove = oti6858_port_remove,
}; };
...@@ -324,6 +326,20 @@ static void send_data(struct work_struct *work) ...@@ -324,6 +326,20 @@ static void send_data(struct work_struct *work)
usb_serial_port_softint(port); usb_serial_port_softint(port);
} }
static int oti6858_attach(struct usb_serial *serial)
{
unsigned char num_ports = serial->num_ports;
if (serial->num_bulk_in < num_ports ||
serial->num_bulk_out < num_ports ||
serial->num_interrupt_in < num_ports) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
return 0;
}
static int oti6858_port_probe(struct usb_serial_port *port) static int oti6858_port_probe(struct usb_serial_port *port)
{ {
struct oti6858_private *priv; struct oti6858_private *priv;
......
...@@ -220,9 +220,17 @@ static int pl2303_probe(struct usb_serial *serial, ...@@ -220,9 +220,17 @@ static int pl2303_probe(struct usb_serial *serial,
static int pl2303_startup(struct usb_serial *serial) static int pl2303_startup(struct usb_serial *serial)
{ {
struct pl2303_serial_private *spriv; struct pl2303_serial_private *spriv;
unsigned char num_ports = serial->num_ports;
enum pl2303_type type = TYPE_01; enum pl2303_type type = TYPE_01;
unsigned char *buf; unsigned char *buf;
if (serial->num_bulk_in < num_ports ||
serial->num_bulk_out < num_ports ||
serial->num_interrupt_in < num_ports) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
if (!spriv) if (!spriv)
return -ENOMEM; return -ENOMEM;
......
...@@ -408,16 +408,12 @@ static void qt2_close(struct usb_serial_port *port) ...@@ -408,16 +408,12 @@ static void qt2_close(struct usb_serial_port *port)
{ {
struct usb_serial *serial; struct usb_serial *serial;
struct qt2_port_private *port_priv; struct qt2_port_private *port_priv;
unsigned long flags;
int i; int i;
serial = port->serial; serial = port->serial;
port_priv = usb_get_serial_port_data(port); port_priv = usb_get_serial_port_data(port);
spin_lock_irqsave(&port_priv->urb_lock, flags);
usb_kill_urb(port_priv->write_urb); usb_kill_urb(port_priv->write_urb);
port_priv->urb_in_use = false;
spin_unlock_irqrestore(&port_priv->urb_lock, flags);
/* flush the port transmit buffer */ /* flush the port transmit buffer */
i = usb_control_msg(serial->dev, i = usb_control_msg(serial->dev,
......
...@@ -154,6 +154,19 @@ static int spcp8x5_probe(struct usb_serial *serial, ...@@ -154,6 +154,19 @@ static int spcp8x5_probe(struct usb_serial *serial,
return 0; return 0;
} }
static int spcp8x5_attach(struct usb_serial *serial)
{
unsigned char num_ports = serial->num_ports;
if (serial->num_bulk_in < num_ports ||
serial->num_bulk_out < num_ports) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
return 0;
}
static int spcp8x5_port_probe(struct usb_serial_port *port) static int spcp8x5_port_probe(struct usb_serial_port *port)
{ {
const struct usb_device_id *id = usb_get_serial_data(port->serial); const struct usb_device_id *id = usb_get_serial_data(port->serial);
...@@ -477,6 +490,7 @@ static struct usb_serial_driver spcp8x5_device = { ...@@ -477,6 +490,7 @@ static struct usb_serial_driver spcp8x5_device = {
.tiocmget = spcp8x5_tiocmget, .tiocmget = spcp8x5_tiocmget,
.tiocmset = spcp8x5_tiocmset, .tiocmset = spcp8x5_tiocmset,
.probe = spcp8x5_probe, .probe = spcp8x5_probe,
.attach = spcp8x5_attach,
.port_probe = spcp8x5_port_probe, .port_probe = spcp8x5_port_probe,
.port_remove = spcp8x5_port_remove, .port_remove = spcp8x5_port_remove,
}; };
......
...@@ -579,6 +579,13 @@ static int ti_startup(struct usb_serial *serial) ...@@ -579,6 +579,13 @@ static int ti_startup(struct usb_serial *serial)
goto free_tdev; goto free_tdev;
} }
if (serial->num_bulk_in < serial->num_ports ||
serial->num_bulk_out < serial->num_ports) {
dev_err(&serial->interface->dev, "missing endpoints\n");
status = -ENODEV;
goto free_tdev;
}
return 0; return 0;
free_tdev: free_tdev:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment