浏览代码

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 <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Johan Hovold 7 年之前
父节点
当前提交
ee13a25fc3
共有 1 个文件被更改,包括 17 次插入5 次删除
  1. 17 5
      drivers/usb/serial/metro-usb.c

+ 17 - 5
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,