[PATCH 3/3] USB: serial: metro-usb: add missing interrupt-out endpoint check

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

Signed-off-by: Johan Hovold <johan@xxxxxxxxxx>
---
 drivers/usb/serial/metro-usb.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c
index a64940975ac6..f16915b457c9 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,
-- 
2.14.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux