Skip to content

Commit e07896e

Browse files
anssihgregkh
authored andcommitted
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 <[email protected]> Signed-off-by: Matthew Garrett <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 3d7e59a commit e07896e

File tree

1 file changed

+25
-17
lines changed

1 file changed

+25
-17
lines changed

drivers/usb/serial/qcserial.c

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ static const struct usb_device_id id_table[] = {
7878
{USB_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
7979
{USB_DEVICE(0x16d8, 0x8001)}, /* CMDTech Gobi 2000 QDL device (VU922) */
8080
{USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */
81+
{USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */
82+
{USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */
8183
{ } /* Terminating entry */
8284
};
8385
MODULE_DEVICE_TABLE(usb, id_table);
@@ -95,6 +97,7 @@ static struct usb_driver qcdriver = {
9597
static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
9698
{
9799
struct usb_wwan_intf_private *data;
100+
struct usb_host_interface *intf = serial->interface->cur_altsetting;
98101
int retval = -ENODEV;
99102
__u8 nintf;
100103
__u8 ifnum;
@@ -103,7 +106,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
103106

104107
nintf = serial->dev->actconfig->desc.bNumInterfaces;
105108
dbg("Num Interfaces = %d", nintf);
106-
ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
109+
ifnum = intf->desc.bInterfaceNumber;
107110
dbg("This Interface = %d", ifnum);
108111

109112
data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private),
@@ -116,27 +119,32 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
116119
switch (nintf) {
117120
case 1:
118121
/* QDL mode */
119-
if (serial->interface->num_altsetting == 2) {
120-
struct usb_host_interface *intf;
121-
122+
/* Gobi 2000 has a single altsetting, older ones have two */
123+
if (serial->interface->num_altsetting == 2)
122124
intf = &serial->interface->altsetting[1];
123-
if (intf->desc.bNumEndpoints == 2) {
124-
if (usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) &&
125-
usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
126-
dbg("QDL port found");
127-
retval = usb_set_interface(serial->dev, ifnum, 1);
128-
if (retval < 0) {
129-
dev_err(&serial->dev->dev,
130-
"Could not set interface, error %d\n",
131-
retval);
132-
retval = -ENODEV;
133-
}
134-
return retval;
135-
}
125+
else if (serial->interface->num_altsetting > 2)
126+
break;
127+
128+
if (intf->desc.bNumEndpoints == 2 &&
129+
usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) &&
130+
usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
131+
dbg("QDL port found");
132+
133+
if (serial->interface->num_altsetting == 1)
134+
return 0;
135+
136+
retval = usb_set_interface(serial->dev, ifnum, 1);
137+
if (retval < 0) {
138+
dev_err(&serial->dev->dev,
139+
"Could not set interface, error %d\n",
140+
retval);
141+
retval = -ENODEV;
136142
}
143+
return retval;
137144
}
138145
break;
139146

147+
case 3:
140148
case 4:
141149
/* Composite mode */
142150
if (ifnum == 2) {

0 commit comments

Comments
 (0)