From 5186e02e258b00c6b302a591202fbbd4217d69b1 Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Sat, 13 Feb 2010 03:40:31 +0200 Subject: [PATCH] USB: qcserial: Add support for Qualcomm Gobi 2000 devices Add ids for Qualcomm Gobi 2000 QDL and Modem modes. Gobi 2000 has a single altsetting in QDL mode, so adapt code to handle that. Firmware upload protocol is also slightly different, with an additional firmware file. However, qcserial doesn't handle firmware uploading. Tested on Lenovo Thinkpad T510. Signed-off-by: Anssi Hannula --- BTW, what is the reason for the driver exposing the QDL device as a serial device instead of just uploading the firmware itself? drivers/usb/serial/qcserial.c | 41 ++++++++++++++++++++++++----------------- 1 files changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 7528b8d..90e2b66 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -47,6 +47,8 @@ static struct usb_device_id id_table[] = { {USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ {USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ {USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ + {USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */ + {USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, id_table); @@ -63,6 +65,7 @@ static struct usb_driver qcdriver = { static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) { + struct usb_host_interface *intf = serial->interface->cur_altsetting; int retval = -ENODEV; __u8 nintf; __u8 ifnum; @@ -71,30 +74,34 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) nintf = serial->dev->actconfig->desc.bNumInterfaces; dbg("Num Interfaces = %d", nintf); - ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber; + ifnum = intf->desc.bInterfaceNumber; dbg("This Interface = %d", ifnum); switch (nintf) { case 1: /* QDL mode */ - if (serial->interface->num_altsetting == 2) { - struct usb_host_interface *intf; - + /* Gobi 2000 has a single altsetting, older ones have two */ + if (serial->interface->num_altsetting == 2) intf = &serial->interface->altsetting[1]; - if (intf->desc.bNumEndpoints == 2) { - if (usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) && - usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { - dbg("QDL port found"); - retval = usb_set_interface(serial->dev, ifnum, 1); - if (retval < 0) { - dev_err(&serial->dev->dev, - "Could not set interface, error %d\n", - retval); - retval = -ENODEV; - } - return retval; - } + else if (serial->interface->num_altsetting > 2) + break; + + if (intf->desc.bNumEndpoints == 2 && + usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) && + usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { + dbg("QDL port found"); + + if (serial->interface->num_altsetting == 1) + return 0; + + retval = usb_set_interface(serial->dev, ifnum, 1); + if (retval < 0) { + dev_err(&serial->dev->dev, + "Could not set interface, error %d\n", + retval); + retval = -ENODEV; } + return retval; } break; -- 1.6.4.4