drivers/net/usb/cdc_ether.c

Source file repositories/reference/linux-study-clean/drivers/net/usb/cdc_ether.c

File Facts

System
Linux kernel
Corpus path
drivers/net/usb/cdc_ether.c
Extension
.c
Size
29427 bytes
Lines
985
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (hep) {
			buf = hep->extra;
			len = hep->extralen;
		}
		if (len)
			dev_dbg(&intf->dev,
				"CDC descriptors on endpoint\n");
	}

	/* this assumes that if there's a non-RNDIS vendor variant
	 * of cdc-acm, it'll fail RNDIS requests cleanly.
	 */
	rndis = (is_rndis(&intf->cur_altsetting->desc) ||
		 is_activesync(&intf->cur_altsetting->desc) ||
		 is_wireless_rndis(&intf->cur_altsetting->desc) ||
		 is_novatel_rndis(&intf->cur_altsetting->desc));

	memset(info, 0, sizeof(*info));
	info->control = intf;

	cdc_parse_cdc_header(&header, intf, buf, len);

	info->u = header.usb_cdc_union_desc;
	info->header = header.usb_cdc_header_desc;
	info->ether = header.usb_cdc_ether_desc;
	if (!info->u) {
		if (rndis) {
			goto skip;
		} else {
			/* in that case a quirk is mandatory */
			dev_err(&dev->udev->dev, "No union descriptors\n");
			goto bad_desc;
		}
	}
	/* we need a master/control interface (what we're
	 * probed with) and a slave/data interface; union
	 * descriptors sort this all out.
	 */
	info->control = usb_ifnum_to_if(dev->udev, info->u->bMasterInterface0);
	info->data = usb_ifnum_to_if(dev->udev, info->u->bSlaveInterface0);
	if (!info->control || !info->data) {
		dev_dbg(&intf->dev,
			"master #%u/%p slave #%u/%p\n",
			info->u->bMasterInterface0,
			info->control,
			info->u->bSlaveInterface0,
			info->data);
		/* fall back to hard-wiring for RNDIS */
		if (rndis) {
			android_rndis_quirk = true;
			goto skip;
		}
		dev_err(&intf->dev, "bad CDC descriptors\n");
		goto bad_desc;
	}
	if (info->control != intf) {
		/* Ambit USB Cable Modem (and maybe others)
		 * interchanges master and slave interface.
		 */
		if (info->data == intf) {
			info->data = info->control;
			info->control = intf;
		} else {
			dev_err(&intf->dev, "bogus CDC Union\n");
			goto bad_desc;
		}
	}

	/* some devices merge these - skip class check */
	if (info->control == info->data)
		goto skip;

	/* a data interface altsetting does the real i/o */
	d = &info->data->cur_altsetting->desc;
	if (d->bInterfaceClass != USB_CLASS_CDC_DATA) {
		dev_err(&intf->dev, "slave class %u\n", d->bInterfaceClass);
		goto bad_desc;
	}
skip:
	/* Communication class functions with bmCapabilities are not
	 * RNDIS.  But some Wireless class RNDIS functions use
	 * bmCapabilities for their own purpose. The failsafe is
	 * therefore applied only to Communication class RNDIS
	 * functions.  The rndis test is redundant, but a cheap
	 * optimization.
	 */
	if (rndis && is_rndis(&intf->cur_altsetting->desc) &&
	    header.usb_cdc_acm_descriptor &&
	    header.usb_cdc_acm_descriptor->bmCapabilities) {
		dev_err(&intf->dev,

Annotation

Implementation Notes