drivers/net/usb/hso.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/usb/hso.c
Extension
.c
Size
83901 bytes
Lines
3271
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 hso_netdev_ops = {
	.ndo_open	= hso_net_open,
	.ndo_stop	= hso_net_close,
	.ndo_start_xmit = hso_net_start_xmit,
	.ndo_tx_timeout = hso_net_tx_timeout,
};

/* initialize the network interface */
static void hso_net_init(struct net_device *net)
{
	struct hso_net *hso_net = netdev_priv(net);

	hso_dbg(0x1, "sizeof hso_net is %zu\n", sizeof(*hso_net));

	/* fill in the other fields */
	net->netdev_ops = &hso_netdev_ops;
	net->watchdog_timeo = HSO_NET_TX_TIMEOUT;
	net->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
	net->type = ARPHRD_NONE;
	net->mtu = DEFAULT_MTU - 14;
	net->tx_queue_len = 10;
	net->ethtool_ops = &ops;

	/* and initialize the semaphore */
	spin_lock_init(&hso_net->net_lock);
}

/* Adds a network device in the network device table */
static int add_net_device(struct hso_device *hso_dev)
{
	int i;

	for (i = 0; i < HSO_MAX_NET_DEVICES; i++) {
		if (network_table[i] == NULL) {
			network_table[i] = hso_dev;
			break;
		}
	}
	if (i == HSO_MAX_NET_DEVICES)
		return -1;
	return 0;
}

static int hso_rfkill_set_block(void *data, bool blocked)
{
	struct hso_device *hso_dev = data;
	int enabled = !blocked;
	int rv;

	mutex_lock(&hso_dev->mutex);
	if (hso_dev->usb_gone)
		rv = 0;
	else
		rv = usb_control_msg(hso_dev->usb, usb_sndctrlpipe(hso_dev->usb, 0),
				       enabled ? 0x82 : 0x81, 0x40, 0, 0, NULL, 0,
				       USB_CTRL_SET_TIMEOUT);
	mutex_unlock(&hso_dev->mutex);
	return rv;
}

static const struct rfkill_ops hso_rfkill_ops = {
	.set_block = hso_rfkill_set_block,
};

/* Creates and sets up everything for rfkill */
static void hso_create_rfkill(struct hso_device *hso_dev,
			     struct usb_interface *interface)
{
	struct hso_net *hso_net = dev2net(hso_dev);
	struct device *dev = &hso_net->net->dev;
	static u32 rfkill_counter;

	snprintf(hso_net->name, sizeof(hso_net->name), "hso-%d",
		 rfkill_counter++);

	hso_net->rfkill = rfkill_alloc(hso_net->name,
				       &interface_to_usbdev(interface)->dev,
				       RFKILL_TYPE_WWAN,
				       &hso_rfkill_ops, hso_dev);
	if (!hso_net->rfkill)
		return;

	if (rfkill_register(hso_net->rfkill) < 0) {
		rfkill_destroy(hso_net->rfkill);
		hso_net->rfkill = NULL;
		dev_err(dev, "%s - Failed to register rfkill\n", __func__);
		return;
	}
}

Annotation

Implementation Notes