Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: cdc_ncm: add Huawei devices

A number of Huawei 3G and LTE modems implement a CDC NCM function,
including the necessary functional descriptors, but using a non
standard interface layout and class/subclass/protocol codes.

These devices can be handled by this driver with only a minor
change to the probing logic, allowing a single combined control
and data interface. This works because the devices
- include a CDC Union descriptor labelling the combined
interface as both master and slave, and
- have an alternate setting #1 for the bulk endpoints on the
combined interface.

The 3G/LTE network connection is managed by vendor specific AT
commands on a serial function in the same composite device.
Handling the managment function is out of the scope of this
driver. It will be handled by an appropriate USB serial
driver.

Reported-and-Tested-by: Olof Ermis <olof.ermis@gmail.com>
Reported-and-Tested-by: Tommy Cheng <tommy7765@yahoo.com>
Signed-off-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Bjørn Mork and committed by
David S. Miller
bbc8d922 7702745b

+18 -4
+18 -4
drivers/net/usb/cdc_ncm.c
··· 540 540 (ctx->ether_desc == NULL) || (ctx->control != intf)) 541 541 goto error; 542 542 543 - /* claim interfaces, if any */ 544 - temp = usb_driver_claim_interface(driver, ctx->data, dev); 545 - if (temp) 546 - goto error; 543 + /* claim data interface, if different from control */ 544 + if (ctx->data != ctx->control) { 545 + temp = usb_driver_claim_interface(driver, ctx->data, dev); 546 + if (temp) 547 + goto error; 548 + } 547 549 548 550 iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber; 549 551 ··· 624 622 hrtimer_cancel(&ctx->tx_timer); 625 623 626 624 tasklet_kill(&ctx->bh); 625 + 626 + /* handle devices with combined control and data interface */ 627 + if (ctx->control == ctx->data) 628 + ctx->data = NULL; 627 629 628 630 /* disconnect master --> disconnect slave */ 629 631 if (intf == ctx->control && ctx->data) { ··· 1249 1243 .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, 1250 1244 .bInterfaceProtocol = USB_CDC_PROTO_NONE, 1251 1245 .driver_info = (unsigned long) &wwan_info, 1246 + }, 1247 + 1248 + /* Huawei NCM devices disguised as vendor specific */ 1249 + { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16), 1250 + .driver_info = (unsigned long)&wwan_info, 1251 + }, 1252 + { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46), 1253 + .driver_info = (unsigned long)&wwan_info, 1252 1254 }, 1253 1255 1254 1256 /* Generic CDC-NCM devices */