diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-11-02 19:42:47 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-11-02 19:42:47 +0300 |
commit | 29ce32ecca842d73cd1c82f540a6fbde5d1ad44b (patch) | |
tree | fef1707d4ff01247d0dd969aba2a8844cfbe04db /drivers/usb/serial/metro-usb.c | |
parent | dc586a60a11d0260308db1bebe788ad8973e2729 (diff) | |
parent | 7c36e6e14da53a0a9c0893c363163afe629b2ee5 (diff) | |
download | linux-29ce32ecca842d73cd1c82f540a6fbde5d1ad44b.tar.xz |
Merge tag 'usb-serial-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next
Johan writes:
USB-serial updates for v4.15-rc1
Here are the USB-serial updates for 4.15-rc1, including:
- three fixes for longstanding issues in garmin_gps and metro-usb which
could lead to NULL-pointer dereferences and memory leaks
- a workaround for broken f81534 firmware-handling of overruns
- f81534 break support, and
- conversion to timer_setup()
Included are also various clean ups and a new qcserial device id.
All have been in linux-next with no reported issues.
Signed-off-by: Johan Hovold <johan@kernel.org>
Diffstat (limited to 'drivers/usb/serial/metro-usb.c')
-rw-r--r-- | drivers/usb/serial/metro-usb.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 14511d6a7d44..36f65df41721 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -54,21 +54,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); @@ -161,13 +173,6 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) unsigned long flags = 0; int result = 0; - /* Make sure the urb is initialized. */ - if (!port->interrupt_in_urb) { - dev_err(&port->dev, "%s - interrupt urb not initialized\n", - __func__); - return -ENODEV; - } - /* Set the private data information for the port. */ spin_lock_irqsave(&metro_priv->lock, flags); metro_priv->control_state = 0; @@ -189,7 +194,7 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) dev_err(&port->dev, "%s - failed submitting interrupt in urb, error code=%d\n", __func__, result); - goto exit; + return result; } /* Send activate cmd to device */ @@ -198,9 +203,14 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) dev_err(&port->dev, "%s - failed to configure device, error code=%d\n", __func__, result); - goto exit; + goto err_kill_urb; } -exit: + + return 0; + +err_kill_urb: + usb_kill_urb(port->interrupt_in_urb); + return result; } @@ -337,7 +347,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, |