diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-10-10 16:24:06 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-10-12 14:55:34 -0700 |
commit | 063a2da8f01806906f7d7b1a1424b9afddebc443 (patch) | |
tree | 960243995fe608580e842b1a34228a3f991ea4dc /drivers/usb/serial/usb-serial.c | |
parent | cd38c1e1ae5273c28a12baacaf17c1faa062661f (diff) |
USB: serial core should respect driver requirements
This patch (as997) fixes a bug in the USB serial core. The core needs
to pay attention to drivers' requirements regarding the number and
type of endpoints a device has.
At the same time, the patch changes the NUM_DONT_CARE constant (which
is stored in a single-byte field) from -1 to a safer, unsigned value.
It also improves the kerneldoc for several fields in the
usb_serial_driver structure.
Finally, the patch replaces a list_for_each() with list_for_each_entry().
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 26e015c39a3..4b1bd7def4a 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -662,16 +662,14 @@ exit: static struct usb_serial_driver *search_serial_device(struct usb_interface *iface) { - struct list_head *p; const struct usb_device_id *id; - struct usb_serial_driver *t; + struct usb_serial_driver *drv; /* Check if the usb id matches a known device */ - list_for_each(p, &usb_serial_driver_list) { - t = list_entry(p, struct usb_serial_driver, driver_list); - id = get_iface_id(t, iface); + list_for_each_entry(drv, &usb_serial_driver_list, driver_list) { + id = get_iface_id(drv, iface); if (id) - return t; + return drv; } return NULL; @@ -811,9 +809,6 @@ int usb_serial_probe(struct usb_interface *interface, /* END HORRIBLE HACK FOR PL2303 */ #endif - /* found all that we need */ - dev_info(&interface->dev, "%s converter detected\n", type->description); - #ifdef CONFIG_USB_SERIAL_GENERIC if (type == &usb_serial_generic_device) { num_ports = num_bulk_out; @@ -847,6 +842,24 @@ int usb_serial_probe(struct usb_interface *interface, serial->num_interrupt_in = num_interrupt_in; serial->num_interrupt_out = num_interrupt_out; + /* check that the device meets the driver's requirements */ + if ((type->num_interrupt_in != NUM_DONT_CARE && + type->num_interrupt_in != num_interrupt_in) + || (type->num_interrupt_out != NUM_DONT_CARE && + type->num_interrupt_out != num_interrupt_out) + || (type->num_bulk_in != NUM_DONT_CARE && + type->num_bulk_in != num_bulk_in) + || (type->num_bulk_out != NUM_DONT_CARE && + type->num_bulk_out != num_bulk_out)) { + dbg("wrong number of endpoints"); + kfree(serial); + return -EIO; + } + + /* found all that we need */ + dev_info(&interface->dev, "%s converter detected\n", + type->description); + /* create our ports, we need as many as the max endpoints */ /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */ max_endpoints = max(num_bulk_in, num_bulk_out); |