From ee13a25fc355650b3acf43857b7a496eb6b07f0b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 12 Oct 2017 10:54:23 +0200 Subject: USB: serial: metro-usb: add missing interrupt-out endpoint check One class of "unidirectional" devices managed by this driver uses an interrupt-out endpoint to send control messages at open and close. Due to a missing endpoint sanity check, this could result in an interrupt URB being submitted to endpoint 0 instead. This would be caught by USB core (without a WARN dump), but let's verify that the expected endpoints are present at probe rather than when a port is later opened. Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold --- drivers/usb/serial/metro-usb.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index a649409..f16915b 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -53,21 +53,33 @@ MODULE_DEVICE_TABLE(usb, id_table); #define UNI_CMD_OPEN 0x80 #define UNI_CMD_CLOSE 0xFF -static inline int metrousb_is_unidirectional_mode(struct usb_serial_port *port) +static int metrousb_is_unidirectional_mode(struct usb_serial *serial) { - __u16 product_id = le16_to_cpu( - port->serial->dev->descriptor.idProduct); + u16 product_id = le16_to_cpu(serial->dev->descriptor.idProduct); return product_id == FOCUS_PRODUCT_ID_UNI; } +static int metrousb_calc_num_ports(struct usb_serial *serial, + struct usb_serial_endpoints *epds) +{ + if (metrousb_is_unidirectional_mode(serial)) { + if (epds->num_interrupt_out == 0) { + dev_err(&serial->interface->dev, "interrupt-out endpoint missing\n"); + return -ENODEV; + } + } + + return 1; +} + static int metrousb_send_unidirectional_cmd(u8 cmd, struct usb_serial_port *port) { int ret; int actual_len; u8 *buffer_cmd = NULL; - if (!metrousb_is_unidirectional_mode(port)) + if (!metrousb_is_unidirectional_mode(port->serial)) return 0; buffer_cmd = kzalloc(sizeof(cmd), GFP_KERNEL); @@ -334,8 +346,8 @@ static struct usb_serial_driver metrousb_device = { }, .description = "Metrologic USB to Serial", .id_table = id_table, - .num_ports = 1, .num_interrupt_in = 1, + .calc_num_ports = metrousb_calc_num_ports, .open = metrousb_open, .close = metrousb_cleanup, .read_int_callback = metrousb_read_int_callback, -- cgit v1.1