Skip to content

Commit 03304bc

Browse files
bmorkdavem330
authored andcommitted
net: qmi_wwan: use fixed interface number matching
This driver support many composite USB devices where the interface class/subclass/protocol provides no information about the interface function. Interfaces with different functions may all use ff/ff/ff, like this example of a device with three serial interfaces and three QMI/wwan interfaces: T: Bus=02 Lev=01 Prnt=01 Port=03 Cnt=01 Dev#=116 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1199 ProdID=68a2 Rev= 0.06 S: Manufacturer=Sierra Wireless, Incorporated S: Product=MC7710 S: SerialNumber=3581780xxxxxx C:* #Ifs= 6 Cfg#= 1 Atr=e0 MxPwr= 0mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=qcserial E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=qcserial E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qcserial E: Ad=83(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 8 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan E: Ad=85(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#=19 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan E: Ad=87(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#=20 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=89(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=8a(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms Instead of class/subclass/protocol the vendor use fixed interface numbers for each function, and the Windows drivers use these numbers to match driver and function. The driver has had its own interface number whitelisting code to simulate this functionality. Replace this with generic interface number matching now that the USB subsystem support is there. This - removes the need for a driver_info structure per interface number, - avoids running the probe function for unsupported interfaces, and - simplifies the code. Signed-off-by: Bjørn Mork <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6556bfd commit 03304bc

File tree

1 file changed

+28
-187
lines changed

1 file changed

+28
-187
lines changed

drivers/net/usb/qmi_wwan.c

Lines changed: 28 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -247,30 +247,12 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
247247
*/
248248
static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf)
249249
{
250-
int rv;
251250
struct qmi_wwan_state *info = (void *)&dev->data;
252251

253-
/* ZTE makes devices where the interface descriptors and endpoint
254-
* configurations of two or more interfaces are identical, even
255-
* though the functions are completely different. If set, then
256-
* driver_info->data is a bitmap of acceptable interface numbers
257-
* allowing us to bind to one such interface without binding to
258-
* all of them
259-
*/
260-
if (dev->driver_info->data &&
261-
!test_bit(intf->cur_altsetting->desc.bInterfaceNumber, &dev->driver_info->data)) {
262-
dev_info(&intf->dev, "not on our whitelist - ignored");
263-
rv = -ENODEV;
264-
goto err;
265-
}
266-
267252
/* control and data is shared */
268253
info->control = intf;
269254
info->data = intf;
270-
rv = qmi_wwan_register_subdriver(dev);
271-
272-
err:
273-
return rv;
255+
return qmi_wwan_register_subdriver(dev);
274256
}
275257

276258
static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf)
@@ -356,86 +338,23 @@ static const struct driver_info qmi_wwan_shared = {
356338
.manage_power = qmi_wwan_manage_power,
357339
};
358340

359-
static const struct driver_info qmi_wwan_force_int0 = {
360-
.description = "Qualcomm WWAN/QMI device",
361-
.flags = FLAG_WWAN,
362-
.bind = qmi_wwan_bind_shared,
363-
.unbind = qmi_wwan_unbind,
364-
.manage_power = qmi_wwan_manage_power,
365-
.data = BIT(0), /* interface whitelist bitmap */
366-
};
367-
368-
static const struct driver_info qmi_wwan_force_int1 = {
369-
.description = "Qualcomm WWAN/QMI device",
370-
.flags = FLAG_WWAN,
371-
.bind = qmi_wwan_bind_shared,
372-
.unbind = qmi_wwan_unbind,
373-
.manage_power = qmi_wwan_manage_power,
374-
.data = BIT(1), /* interface whitelist bitmap */
375-
};
376-
377-
static const struct driver_info qmi_wwan_force_int2 = {
378-
.description = "Qualcomm WWAN/QMI device",
379-
.flags = FLAG_WWAN,
380-
.bind = qmi_wwan_bind_shared,
381-
.unbind = qmi_wwan_unbind,
382-
.manage_power = qmi_wwan_manage_power,
383-
.data = BIT(2), /* interface whitelist bitmap */
384-
};
385-
386-
static const struct driver_info qmi_wwan_force_int3 = {
387-
.description = "Qualcomm WWAN/QMI device",
388-
.flags = FLAG_WWAN,
389-
.bind = qmi_wwan_bind_shared,
390-
.unbind = qmi_wwan_unbind,
391-
.manage_power = qmi_wwan_manage_power,
392-
.data = BIT(3), /* interface whitelist bitmap */
393-
};
394-
395-
static const struct driver_info qmi_wwan_force_int4 = {
396-
.description = "Qualcomm WWAN/QMI device",
397-
.flags = FLAG_WWAN,
398-
.bind = qmi_wwan_bind_shared,
399-
.unbind = qmi_wwan_unbind,
400-
.manage_power = qmi_wwan_manage_power,
401-
.data = BIT(4), /* interface whitelist bitmap */
402-
};
403-
404-
/* Sierra Wireless provide equally useless interface descriptors
405-
* Devices in QMI mode can be switched between two different
406-
* configurations:
407-
* a) USB interface #8 is QMI/wwan
408-
* b) USB interfaces #8, #19 and #20 are QMI/wwan
409-
*
410-
* Both configurations provide a number of other interfaces (serial++),
411-
* some of which have the same endpoint configuration as we expect, so
412-
* a whitelist or blacklist is necessary.
413-
*
414-
* FIXME: The below whitelist should include BIT(20). It does not
415-
* because I cannot get it to work...
416-
*/
417-
static const struct driver_info qmi_wwan_sierra = {
418-
.description = "Sierra Wireless wwan/QMI device",
419-
.flags = FLAG_WWAN,
420-
.bind = qmi_wwan_bind_shared,
421-
.unbind = qmi_wwan_unbind,
422-
.manage_power = qmi_wwan_manage_power,
423-
.data = BIT(8) | BIT(19), /* interface whitelist bitmap */
424-
};
425-
426341
#define HUAWEI_VENDOR_ID 0x12D1
427342

343+
/* map QMI/wwan function by a fixed interface number */
344+
#define QMI_FIXED_INTF(vend, prod, num) \
345+
USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \
346+
.driver_info = (unsigned long)&qmi_wwan_shared
347+
428348
/* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */
429349
#define QMI_GOBI1K_DEVICE(vend, prod) \
430-
USB_DEVICE(vend, prod), \
431-
.driver_info = (unsigned long)&qmi_wwan_force_int3
350+
QMI_FIXED_INTF(vend, prod, 3)
432351

433-
/* Gobi 2000 and Gobi 3000 QMI/wwan interface number is 0 according to qcserial */
352+
/* Gobi 2000/3000 QMI/wwan interface number is 0 according to qcserial */
434353
#define QMI_GOBI_DEVICE(vend, prod) \
435-
USB_DEVICE(vend, prod), \
436-
.driver_info = (unsigned long)&qmi_wwan_force_int0
354+
QMI_FIXED_INTF(vend, prod, 0)
437355

438356
static const struct usb_device_id products[] = {
357+
/* 1. CDC ECM like devices match on the control interface */
439358
{ /* Huawei E392, E398 and possibly others sharing both device id and more... */
440359
.match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO,
441360
.idVendor = HUAWEI_VENDOR_ID,
@@ -452,10 +371,9 @@ static const struct usb_device_id products[] = {
452371
.bInterfaceProtocol = 57, /* CDC Ethernet *control* interface */
453372
.driver_info = (unsigned long)&qmi_wwan_info,
454373
},
455-
{ /* Huawei E392, E398 and possibly others in "Windows mode"
456-
* using a combined control and data interface without any CDC
457-
* functional descriptors
458-
*/
374+
375+
/* 2. Combined interface devices matching on class+protocol */
376+
{ /* Huawei E392, E398 and possibly others in "Windows mode" */
459377
.match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO,
460378
.idVendor = HUAWEI_VENDOR_ID,
461379
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
@@ -472,98 +390,21 @@ static const struct usb_device_id products[] = {
472390
.bInterfaceProtocol = 0xff,
473391
.driver_info = (unsigned long)&qmi_wwan_shared,
474392
},
475-
{ /* ZTE MF820D */
476-
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
477-
.idVendor = 0x19d2,
478-
.idProduct = 0x0167,
479-
.bInterfaceClass = 0xff,
480-
.bInterfaceSubClass = 0xff,
481-
.bInterfaceProtocol = 0xff,
482-
.driver_info = (unsigned long)&qmi_wwan_force_int4,
483-
},
484-
{ /* ZTE MF821D */
485-
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
486-
.idVendor = 0x19d2,
487-
.idProduct = 0x0326,
488-
.bInterfaceClass = 0xff,
489-
.bInterfaceSubClass = 0xff,
490-
.bInterfaceProtocol = 0xff,
491-
.driver_info = (unsigned long)&qmi_wwan_force_int4,
492-
},
493-
{ /* ZTE (Vodafone) K3520-Z */
494-
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
495-
.idVendor = 0x19d2,
496-
.idProduct = 0x0055,
497-
.bInterfaceClass = 0xff,
498-
.bInterfaceSubClass = 0xff,
499-
.bInterfaceProtocol = 0xff,
500-
.driver_info = (unsigned long)&qmi_wwan_force_int1,
501-
},
502-
{ /* ZTE (Vodafone) K3565-Z */
503-
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
504-
.idVendor = 0x19d2,
505-
.idProduct = 0x0063,
506-
.bInterfaceClass = 0xff,
507-
.bInterfaceSubClass = 0xff,
508-
.bInterfaceProtocol = 0xff,
509-
.driver_info = (unsigned long)&qmi_wwan_force_int4,
510-
},
511-
{ /* ZTE (Vodafone) K3570-Z */
512-
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
513-
.idVendor = 0x19d2,
514-
.idProduct = 0x1008,
515-
.bInterfaceClass = 0xff,
516-
.bInterfaceSubClass = 0xff,
517-
.bInterfaceProtocol = 0xff,
518-
.driver_info = (unsigned long)&qmi_wwan_force_int4,
519-
},
520-
{ /* ZTE (Vodafone) K3571-Z */
521-
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
522-
.idVendor = 0x19d2,
523-
.idProduct = 0x1010,
524-
.bInterfaceClass = 0xff,
525-
.bInterfaceSubClass = 0xff,
526-
.bInterfaceProtocol = 0xff,
527-
.driver_info = (unsigned long)&qmi_wwan_force_int4,
528-
},
529-
{ /* ZTE (Vodafone) K3765-Z */
530-
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
531-
.idVendor = 0x19d2,
532-
.idProduct = 0x2002,
533-
.bInterfaceClass = 0xff,
534-
.bInterfaceSubClass = 0xff,
535-
.bInterfaceProtocol = 0xff,
536-
.driver_info = (unsigned long)&qmi_wwan_force_int4,
537-
},
538-
{ /* ZTE (Vodafone) K4505-Z */
539-
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
540-
.idVendor = 0x19d2,
541-
.idProduct = 0x0104,
542-
.bInterfaceClass = 0xff,
543-
.bInterfaceSubClass = 0xff,
544-
.bInterfaceProtocol = 0xff,
545-
.driver_info = (unsigned long)&qmi_wwan_force_int4,
546-
},
547-
{ /* ZTE MF60 */
548-
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
549-
.idVendor = 0x19d2,
550-
.idProduct = 0x1402,
551-
.bInterfaceClass = 0xff,
552-
.bInterfaceSubClass = 0xff,
553-
.bInterfaceProtocol = 0xff,
554-
.driver_info = (unsigned long)&qmi_wwan_force_int2,
555-
},
556-
{ /* Sierra Wireless MC77xx in QMI mode */
557-
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
558-
.idVendor = 0x1199,
559-
.idProduct = 0x68a2,
560-
.bInterfaceClass = 0xff,
561-
.bInterfaceSubClass = 0xff,
562-
.bInterfaceProtocol = 0xff,
563-
.driver_info = (unsigned long)&qmi_wwan_sierra,
564-
},
565393

566-
/* Gobi 1000 devices */
394+
/* 3. Combined interface devices matching on interface number */
395+
{QMI_FIXED_INTF(0x19d2, 0x0055, 1)}, /* ZTE (Vodafone) K3520-Z */
396+
{QMI_FIXED_INTF(0x19d2, 0x0063, 4)}, /* ZTE (Vodafone) K3565-Z */
397+
{QMI_FIXED_INTF(0x19d2, 0x0104, 4)}, /* ZTE (Vodafone) K4505-Z */
398+
{QMI_FIXED_INTF(0x19d2, 0x0167, 4)}, /* ZTE MF820D */
399+
{QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */
400+
{QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */
401+
{QMI_FIXED_INTF(0x19d2, 0x1010, 4)}, /* ZTE (Vodafone) K3571-Z */
402+
{QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */
403+
{QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */
404+
{QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */
405+
{QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */
406+
407+
/* 4. Gobi 1000 devices */
567408
{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
568409
{QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
569410
{QMI_GOBI1K_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */
@@ -579,7 +420,7 @@ static const struct usb_device_id products[] = {
579420
{QMI_GOBI1K_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
580421
{QMI_GOBI1K_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */
581422

582-
/* Gobi 2000 and 3000 devices */
423+
/* 5. Gobi 2000 and 3000 devices */
583424
{QMI_GOBI_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */
584425
{QMI_GOBI_DEVICE(0x05c6, 0x920b)}, /* Generic Gobi 2000 Modem device */
585426
{QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */

0 commit comments

Comments
 (0)