drivers/net/can/usb/gs_usb.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/can/usb/gs_usb.c
Extension
.c
Size
44343 bytes
Lines
1679
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 gs_usb_netdev_ops = {
	.ndo_open = gs_can_open,
	.ndo_stop = gs_can_close,
	.ndo_start_xmit = gs_can_start_xmit,
	.ndo_hwtstamp_get = gs_can_hwtstamp_get,
	.ndo_hwtstamp_set = gs_can_hwtstamp_set,
};

static int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
{
	struct gs_can *dev = netdev_priv(netdev);
	struct gs_identify_mode imode;

	if (do_identify)
		imode.mode = cpu_to_le32(GS_CAN_IDENTIFY_ON);
	else
		imode.mode = cpu_to_le32(GS_CAN_IDENTIFY_OFF);

	return usb_control_msg_send(dev->udev, 0, GS_USB_BREQ_IDENTIFY,
				    USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
				    dev->channel, 0, &imode, sizeof(imode), 100,
				    GFP_KERNEL);
}

/* blink LED's for finding the this interface */
static int gs_usb_set_phys_id(struct net_device *netdev,
			      enum ethtool_phys_id_state state)
{
	const struct gs_can *dev = netdev_priv(netdev);
	int rc = 0;

	if (!(dev->feature & GS_CAN_FEATURE_IDENTIFY))
		return -EOPNOTSUPP;

	switch (state) {
	case ETHTOOL_ID_ACTIVE:
		rc = gs_usb_set_identify(netdev, GS_CAN_IDENTIFY_ON);
		break;
	case ETHTOOL_ID_INACTIVE:
		rc = gs_usb_set_identify(netdev, GS_CAN_IDENTIFY_OFF);
		break;
	default:
		break;
	}

	return rc;
}

static int gs_usb_get_ts_info(struct net_device *netdev,
			      struct kernel_ethtool_ts_info *info)
{
	struct gs_can *dev = netdev_priv(netdev);

	/* report if device supports HW timestamps */
	if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
		return can_ethtool_op_get_ts_info_hwts(netdev, info);

	return ethtool_op_get_ts_info(netdev, info);
}

static const struct ethtool_ops gs_usb_ethtool_ops = {
	.set_phys_id = gs_usb_set_phys_id,
	.get_ts_info = gs_usb_get_ts_info,
};

static int gs_usb_get_termination(struct net_device *netdev, u16 *term)
{
	struct gs_can *dev = netdev_priv(netdev);
	struct gs_device_termination_state term_state;
	int rc;

	rc = usb_control_msg_recv(dev->udev, 0, GS_USB_BREQ_GET_TERMINATION,
				  USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
				  dev->channel, 0,
				  &term_state, sizeof(term_state), 1000,
				  GFP_KERNEL);
	if (rc)
		return rc;

	if (term_state.state == cpu_to_le32(GS_CAN_TERMINATION_STATE_ON))
		*term = GS_USB_TERMINATION_ENABLED;
	else
		*term = GS_USB_TERMINATION_DISABLED;

	return 0;
}

static int gs_usb_set_termination(struct net_device *netdev, u16 term)
{
	struct gs_can *dev = netdev_priv(netdev);

Annotation

Implementation Notes