USB Serial Sierra: Dynamic interface detection
authorKevin Lloyd <klloyd@sierrawireless.com>
Thu, 10 Jul 2008 21:14:51 +0000 (14:14 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 14 Aug 2008 00:32:51 +0000 (17:32 -0700)
This patch changes the method by which the number of ports per interface is
assigned so that it is more dynamic and calculated on the fly (as opposed to
hard coding it). This will allow for faster and easier addition of products.

Signed-off-by: Kevin Lloyd <klloyd@sierrawireless.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/serial/sierra.c

index a3aaf08e56d5334fce8e2c6a649597bba621e40d..e2a7463346fc8ad3313ae2ba477ecead06941cbe 100644 (file)
@@ -137,6 +137,8 @@ static int sierra_probe(struct usb_serial *serial,
        struct usb_device *udev;
        int *num_ports;
        u8 ifnum;
+       u8 numendpoints;
+
        dev_dbg(&serial->dev->dev, "%s", __func__);
 
        num_ports = kmalloc(sizeof(*num_ports), GFP_KERNEL);
@@ -144,23 +146,22 @@ static int sierra_probe(struct usb_serial *serial,
                return -ENOMEM;
 
        ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+       numendpoints = serial->interface->cur_altsetting->desc.bNumEndpoints;
        udev = serial->dev;
 
-               /* Figure out the interface number from the serial structure */
-               ifnum = sierra_calc_interface(serial);
-
-               /*
-                * If this interface supports more than 1 alternate
-                * select the 2nd one
-                */
-               if (serial->interface->num_altsetting == 2) {
-                       dev_dbg(&udev->dev,
-                               "Selecting alt setting for interface %d\n",
-                               ifnum);
+       /* Figure out the interface number from the serial structure */
+       ifnum = sierra_calc_interface(serial);
 
-                       /* We know the alternate setting is 1 for the MC8785 */
-                       usb_set_interface(udev, ifnum, 1);
-               }
+       /*
+        * If this interface supports more than 1 alternate
+        * select the 2nd one
+        */
+       if (serial->interface->num_altsetting == 2) {
+               dev_dbg(&udev->dev, "Selecting alt setting for interface %d\n",
+                       ifnum);
+               /* We know the alternate setting is 1 for the MC8785 */
+               usb_set_interface(udev, ifnum, 1);
+       }
 
        /* Check if in installer mode */
        if (truinstall && id->driver_info == DEVICE_INSTALLER) {
@@ -169,12 +170,14 @@ static int sierra_probe(struct usb_serial *serial,
                /* Don't bind to the device when in installer mode */
                kfree(num_ports);
                return -EIO;
-       } else if (id->driver_info == DEVICE_1_PORT)
-               *num_ports = 1;
-       else if (ifnum == 0x99)
+       /* Dummy interface present on some SKUs should be ignored */
+       } else if (ifnum == 0x99)
                *num_ports = 0;
+       else if (numendpoints <= 3)
+               *num_ports = 1;
        else
-               *num_ports = 3;
+               *num_ports = (numendpoints-1)/2;
+
        /*
         * save off our num_ports info so that we can use it in the
         * calc_num_ports callback
@@ -197,6 +200,9 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */
         /* Sierra Wireless C597 */
        { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) },
+        /* Sierra Wireless Device */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) },
+       { USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless Device */
 
        { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
        { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
@@ -209,18 +215,27 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */
        { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */
        { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */
-       { USB_DEVICE(0x1199, 0x683B), .driver_info = DEVICE_1_PORT },   /* Sierra Wireless MC8785 Composite */
+       { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */
+       { USB_DEVICE(0x1199, 0x683C) }, /* Sierra Wireless MC8790 */
+       { USB_DEVICE(0x1199, 0x683D) }, /* Sierra Wireless MC8790 */
+       { USB_DEVICE(0x1199, 0x683E) }, /* Sierra Wireless MC8790 */
        { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */
        { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */
        { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */
        { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881 E */
        { USB_DEVICE(0x1199, 0x6855) }, /* Sierra Wireless AirCard 880 U */
        { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881 U */
-       { USB_DEVICE(0x1199, 0x6859), .driver_info = DEVICE_1_PORT },   /* Sierra Wireless AirCard 885 E */
-       { USB_DEVICE(0x1199, 0x685A), .driver_info = DEVICE_1_PORT },   /* Sierra Wireless AirCard 885 E */
-
-       { USB_DEVICE(0x1199, 0x0112), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 580 */
-       { USB_DEVICE(0x0F3D, 0x0112), .driver_info = DEVICE_1_PORT }, /* Airprime/Sierra PC 5220 */
+       { USB_DEVICE(0x1199, 0x6859) }, /* Sierra Wireless AirCard 885 E */
+       { USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */
+       /* Sierra Wireless C885 */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)},
+       /* Sierra Wireless Device */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)},
+       /* Sierra Wireless Device */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
+
+       { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
+       { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
 
        { USB_DEVICE(0x1199, 0x0FFF), .driver_info = DEVICE_INSTALLER},
        { }
@@ -270,13 +285,19 @@ static int sierra_send_setup(struct tty_struct *tty,
                if (portdata->rts_state)
                        val |= 0x02;
 
-               /* Determine which port is targeted */
-               if (port->bulk_out_endpointAddress == 2)
-                       interface = 0;
-               else if (port->bulk_out_endpointAddress == 4)
-                       interface = 1;
-               else if (port->bulk_out_endpointAddress == 5)
-                       interface = 2;
+               /* If composite device then properly report interface */
+               if (serial->num_ports == 1)
+                       interface = sierra_calc_interface(serial);
+
+               /* Otherwise the need to do non-composite mapping */
+               else {
+                       if (port->bulk_out_endpointAddress == 2)
+                               interface = 0;
+                       else if (port->bulk_out_endpointAddress == 4)
+                               interface = 1;
+                       else if (port->bulk_out_endpointAddress == 5)
+                               interface = 2;
+               }
 
                return usb_control_msg(serial->dev,
                                usb_rcvctrlpipe(serial->dev, 0),