drivers/net/can/usb/ucan.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/can/usb/ucan.c
Extension
.c
Size
40803 bytes
Lines
1583
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 ucan_netdev_ops = {
	.ndo_open = ucan_open,
	.ndo_stop = ucan_close,
	.ndo_start_xmit = ucan_start_xmit,
};

static const struct ethtool_ops ucan_ethtool_ops = {
	.get_ts_info = ethtool_op_get_ts_info,
};

/* Request to set bittiming
 *
 * This function generates an USB set bittiming message and transmits
 * it to the device
 */
static int ucan_set_bittiming(struct net_device *netdev)
{
	int ret;
	struct ucan_priv *up = netdev_priv(netdev);
	struct ucan_ctl_cmd_set_bittiming *cmd_set_bittiming;

	cmd_set_bittiming = &up->ctl_msg_buffer->cmd_set_bittiming;
	cmd_set_bittiming->tq = cpu_to_le32(up->can.bittiming.tq);
	cmd_set_bittiming->brp = cpu_to_le16(up->can.bittiming.brp);
	cmd_set_bittiming->sample_point =
	    cpu_to_le16(up->can.bittiming.sample_point);
	cmd_set_bittiming->prop_seg = up->can.bittiming.prop_seg;
	cmd_set_bittiming->phase_seg1 = up->can.bittiming.phase_seg1;
	cmd_set_bittiming->phase_seg2 = up->can.bittiming.phase_seg2;
	cmd_set_bittiming->sjw = up->can.bittiming.sjw;

	ret = ucan_ctrl_command_out(up, UCAN_COMMAND_SET_BITTIMING, 0,
				    sizeof(*cmd_set_bittiming));
	return (ret < 0) ? ret : 0;
}

/* Restart the device to get it out of BUS-OFF state.
 * Called when the user runs "ip link set can1 type can restart".
 */
static int ucan_set_mode(struct net_device *netdev, enum can_mode mode)
{
	int ret;
	unsigned long flags;
	struct ucan_priv *up = netdev_priv(netdev);

	switch (mode) {
	case CAN_MODE_START:
		netdev_dbg(up->netdev, "restarting device\n");

		ret = ucan_ctrl_command_out(up, UCAN_COMMAND_RESTART, 0, 0);
		up->can.state = CAN_STATE_ERROR_ACTIVE;

		/* check if queue can be restarted,
		 * up->available_tx_urbs must be protected by the
		 * lock
		 */
		spin_lock_irqsave(&up->context_lock, flags);

		if (up->available_tx_urbs > 0)
			netif_wake_queue(up->netdev);

		spin_unlock_irqrestore(&up->context_lock, flags);

		return ret;
	default:
		return -EOPNOTSUPP;
	}
}

/* Probe the device, reset it and gather general device information */
static int ucan_probe(struct usb_interface *intf,
		      const struct usb_device_id *id)
{
	int ret;
	u32 protocol_version;
	struct usb_device *udev;
	struct net_device *netdev;
	struct usb_host_interface *iface_desc;
	struct ucan_priv *up;
	struct usb_endpoint_descriptor *ep_in, *ep_out;
	u16 in_ep_size;
	u16 out_ep_size;
	u8 in_ep_addr;
	u8 out_ep_addr;
	union ucan_ctl_payload *ctl_msg_buffer;

	udev = interface_to_usbdev(intf);

	/* Stage 1 - Interface Parsing
	 * ---------------------------

Annotation

Implementation Notes