drivers/net/usb/kaweth.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/usb/kaweth.c
Extension
.c
Size
33123 bytes
Lines
1127
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 kaweth_netdev_ops = {
	.ndo_open =			kaweth_open,
	.ndo_stop =			kaweth_close,
	.ndo_start_xmit =		kaweth_start_xmit,
	.ndo_tx_timeout =		kaweth_tx_timeout,
	.ndo_set_rx_mode =		kaweth_set_rx_mode,
	.ndo_set_mac_address =		eth_mac_addr,
	.ndo_validate_addr =		eth_validate_addr,
};

static int kaweth_probe(
		struct usb_interface *intf,
		const struct usb_device_id *id      /* from id_table */
	)
{
	struct device *dev = &intf->dev;
	struct usb_device *udev = interface_to_usbdev(intf);
	struct kaweth_device *kaweth;
	struct net_device *netdev;
	const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
	int result = 0;
	int rv = -EIO;
	static const u8 bulk_ep_addr[] = {
		1 | USB_DIR_IN,
		2 | USB_DIR_OUT,
		0};
	static const u8 int_ep_addr[] = {
		3 | USB_DIR_IN,
		0};

	dev_dbg(dev,
		"Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x\n",
		udev->devnum, le16_to_cpu(udev->descriptor.idVendor),
		le16_to_cpu(udev->descriptor.idProduct),
		le16_to_cpu(udev->descriptor.bcdDevice));

	dev_dbg(dev, "Device at %p\n", udev);

	dev_dbg(dev, "Descriptor length: %x type: %x\n",
		(int)udev->descriptor.bLength,
		(int)udev->descriptor.bDescriptorType);

	if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
	    !usb_check_int_endpoints(intf, int_ep_addr)) {
		dev_err(dev, "couldn't find required endpoints\n");
		return -ENODEV;
	}

	netdev = alloc_etherdev(sizeof(*kaweth));
	if (!netdev)
		return -ENOMEM;

	kaweth = netdev_priv(netdev);
	kaweth->dev = udev;
	kaweth->net = netdev;
	kaweth->intf = intf;

	spin_lock_init(&kaweth->device_lock);
	init_waitqueue_head(&kaweth->term_wait);

	dev_dbg(dev, "Resetting.\n");

	kaweth_reset(kaweth);

	/*
	 * If high byte of bcdDevice is nonzero, firmware is already
	 * downloaded. Don't try to do it again, or we'll hang the device.
	 */

	if (le16_to_cpu(udev->descriptor.bcdDevice) >> 8) {
		dev_info(dev, "Firmware present in device.\n");
	} else {
		/* Download the firmware */
		dev_info(dev, "Downloading firmware...\n");
		kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL);
		if (!kaweth->firmware_buf) {
			rv = -ENOMEM;
			goto err_free_netdev;
		}
		if ((result = kaweth_download_firmware(kaweth,
						      "kaweth/new_code.bin",
						      100,
						      2)) < 0) {
			dev_err(dev, "Error downloading firmware (%d)\n",
				result);
			goto err_fw;
		}

		if ((result = kaweth_download_firmware(kaweth,
						      "kaweth/new_code_fix.bin",

Annotation

Implementation Notes