drivers/net/usb/cdc-phonet.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/usb/cdc-phonet.c
Extension
.c
Size
10306 bytes
Lines
439
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct net_device_ops usbpn_ops = {
	.ndo_open	= usbpn_open,
	.ndo_stop	= usbpn_close,
	.ndo_start_xmit = usbpn_xmit,
	.ndo_siocdevprivate = usbpn_siocdevprivate,
};

static void usbpn_setup(struct net_device *dev)
{
	const u8 addr = PN_MEDIA_USB;

	dev->features		= 0;
	dev->netdev_ops		= &usbpn_ops;
	dev->header_ops		= &phonet_header_ops;
	dev->type		= ARPHRD_PHONET;
	dev->flags		= IFF_POINTOPOINT | IFF_NOARP;
	dev->mtu		= PHONET_MAX_MTU;
	dev->min_mtu		= PHONET_MIN_MTU;
	dev->max_mtu		= PHONET_MAX_MTU;
	dev->hard_header_len	= 1;
	dev->addr_len		= 1;
	dev_addr_set(dev, &addr);
	dev->tx_queue_len	= 3;

	dev->needs_free_netdev	= true;
}

/*
 * USB driver callbacks
 */
static const struct usb_device_id usbpn_ids[] = {
	{
		.match_flags = USB_DEVICE_ID_MATCH_VENDOR
			| USB_DEVICE_ID_MATCH_INT_CLASS
			| USB_DEVICE_ID_MATCH_INT_SUBCLASS,
		.idVendor = 0x0421, /* Nokia */
		.bInterfaceClass = USB_CLASS_COMM,
		.bInterfaceSubClass = 0xFE,
	},
	{ },
};

MODULE_DEVICE_TABLE(usb, usbpn_ids);

static struct usb_driver usbpn_driver;

static int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	static const char ifname[] = "usbpn%d";
	const struct usb_cdc_union_desc *union_header = NULL;
	const struct usb_host_interface *data_desc;
	struct usb_interface *data_intf;
	struct usb_device *usbdev = interface_to_usbdev(intf);
	struct net_device *dev;
	struct usbpn_dev *pnd;
	u8 *data;
	int phonet = 0;
	int len, err;
	struct usb_cdc_parsed_header hdr;

	data = intf->altsetting->extra;
	len = intf->altsetting->extralen;
	cdc_parse_cdc_header(&hdr, intf, data, len);
	union_header = hdr.usb_cdc_union_desc;
	phonet = hdr.phonet_magic_present;

	if (!union_header || !phonet)
		return -EINVAL;

	data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0);
	if (data_intf == NULL)
		return -ENODEV;
	/* Data interface has one inactive and one active setting */
	if (data_intf->num_altsetting != 2)
		return -EINVAL;
	if (data_intf->altsetting[0].desc.bNumEndpoints == 0 &&
	    data_intf->altsetting[1].desc.bNumEndpoints == 2)
		data_desc = data_intf->altsetting + 1;
	else
	if (data_intf->altsetting[0].desc.bNumEndpoints == 2 &&
	    data_intf->altsetting[1].desc.bNumEndpoints == 0)
		data_desc = data_intf->altsetting;
	else
		return -EINVAL;

	dev = alloc_netdev(struct_size(pnd, urbs, rxq_size), ifname,
			   NET_NAME_UNKNOWN, usbpn_setup);
	if (!dev)
		return -ENOMEM;

Annotation

Implementation Notes