Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bbc8d922 authored by Bjørn Mork's avatar Bjørn Mork Committed by David S. Miller
Browse files

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: default avatarOlof Ermis <olof.ermis@gmail.com>
Reported-and-Tested-by: default avatarTommy Cheng <tommy7765@yahoo.com>
Signed-off-by: default avatarBjørn Mork <bjorn@mork.no>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7702745b
Loading
Loading
Loading
Loading
+18 −4
Original line number Diff line number Diff line
@@ -540,10 +540,12 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
	    (ctx->ether_desc == NULL) || (ctx->control != intf))
		goto error;

	/* claim interfaces, if any */
	/* claim data interface, if different from control */
	if (ctx->data != ctx->control) {
		temp = usb_driver_claim_interface(driver, ctx->data, dev);
		if (temp)
			goto error;
	}

	iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber;

@@ -623,6 +625,10 @@ static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)

	tasklet_kill(&ctx->bh);

	/* handle devices with combined control and data interface */
	if (ctx->control == ctx->data)
		ctx->data = NULL;

	/* disconnect master --> disconnect slave */
	if (intf == ctx->control && ctx->data) {
		usb_set_intfdata(ctx->data, NULL);
@@ -1245,6 +1251,14 @@ static const struct usb_device_id cdc_devs[] = {
	  .driver_info = (unsigned long) &wwan_info,
	},

	/* Huawei NCM devices disguised as vendor specific */
	{ USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16),
	  .driver_info = (unsigned long)&wwan_info,
	},
	{ USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46),
	  .driver_info = (unsigned long)&wwan_info,
	},

	/* Generic CDC-NCM devices */
	{ USB_INTERFACE_INFO(USB_CLASS_COMM,
		USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),