diff options
| author | Bjørn Mork <bjorn@mork.no> | 2012-11-12 22:19:43 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-11-13 14:33:28 -0500 |
| commit | bbc8d9228ea8e37ce29fa96150d10b85a2c7be60 (patch) | |
| tree | 849a396143e9ffdd3ca787c05d8b0cef3c8279aa | |
| parent | 7702745b15128e5f0659693736a864e35be1c807 (diff) | |
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>
| -rw-r--r-- | drivers/net/usb/cdc_ncm.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 4cd582a4f625..74fab1a40156 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c | |||
| @@ -540,10 +540,12 @@ advance: | |||
| 540 | (ctx->ether_desc == NULL) || (ctx->control != intf)) | 540 | (ctx->ether_desc == NULL) || (ctx->control != intf)) |
| 541 | goto error; | 541 | goto error; |
| 542 | 542 | ||
| 543 | /* claim interfaces, if any */ | 543 | /* claim data interface, if different from control */ |
| 544 | temp = usb_driver_claim_interface(driver, ctx->data, dev); | 544 | if (ctx->data != ctx->control) { |
| 545 | if (temp) | 545 | temp = usb_driver_claim_interface(driver, ctx->data, dev); |
| 546 | goto error; | 546 | if (temp) |
| 547 | goto error; | ||
| 548 | } | ||
| 547 | 549 | ||
| 548 | iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber; | 550 | iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber; |
| 549 | 551 | ||
| @@ -623,6 +625,10 @@ static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf) | |||
| 623 | 625 | ||
| 624 | tasklet_kill(&ctx->bh); | 626 | tasklet_kill(&ctx->bh); |
| 625 | 627 | ||
| 628 | /* handle devices with combined control and data interface */ | ||
| 629 | if (ctx->control == ctx->data) | ||
| 630 | ctx->data = NULL; | ||
| 631 | |||
| 626 | /* disconnect master --> disconnect slave */ | 632 | /* disconnect master --> disconnect slave */ |
| 627 | if (intf == ctx->control && ctx->data) { | 633 | if (intf == ctx->control && ctx->data) { |
| 628 | usb_set_intfdata(ctx->data, NULL); | 634 | usb_set_intfdata(ctx->data, NULL); |
| @@ -1245,6 +1251,14 @@ static const struct usb_device_id cdc_devs[] = { | |||
| 1245 | .driver_info = (unsigned long) &wwan_info, | 1251 | .driver_info = (unsigned long) &wwan_info, |
| 1246 | }, | 1252 | }, |
| 1247 | 1253 | ||
| 1254 | /* Huawei NCM devices disguised as vendor specific */ | ||
| 1255 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16), | ||
| 1256 | .driver_info = (unsigned long)&wwan_info, | ||
| 1257 | }, | ||
| 1258 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46), | ||
| 1259 | .driver_info = (unsigned long)&wwan_info, | ||
| 1260 | }, | ||
| 1261 | |||
| 1248 | /* Generic CDC-NCM devices */ | 1262 | /* Generic CDC-NCM devices */ |
| 1249 | { USB_INTERFACE_INFO(USB_CLASS_COMM, | 1263 | { USB_INTERFACE_INFO(USB_CLASS_COMM, |
| 1250 | USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), | 1264 | USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), |
