drivers/net/can/usb/peak_usb/pcan_usb_core.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/can/usb/peak_usb/pcan_usb_core.c
Extension
.c
Size
28452 bytes
Lines
1154
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 peak_usb_netdev_ops = {
	.ndo_open = peak_usb_ndo_open,
	.ndo_stop = peak_usb_ndo_stop,
	.ndo_start_xmit = peak_usb_ndo_start_xmit,
	.ndo_hwtstamp_get = peak_hwtstamp_get,
	.ndo_hwtstamp_set = peak_hwtstamp_set,
};

/* CAN-USB devices generally handle 32-bit CAN channel IDs.
 * In case one doesn't, then it have to overload this function.
 */
int peak_usb_get_eeprom_len(struct net_device *netdev)
{
	return sizeof(u32);
}

/* Every CAN-USB device exports the dev_get_can_channel_id() operation. It is used
 * here to fill the data buffer with the user defined CAN channel ID.
 */
int peak_usb_get_eeprom(struct net_device *netdev,
			struct ethtool_eeprom *eeprom, u8 *data)
{
	struct peak_usb_device *dev = netdev_priv(netdev);
	u32 ch_id;
	__le32 ch_id_le;
	int err;

	err = dev->adapter->dev_get_can_channel_id(dev, &ch_id);
	if (err)
		return err;

	/* ethtool operates on individual bytes. The byte order of the CAN
	 * channel id in memory depends on the kernel architecture. We
	 * convert the CAN channel id back to the native byte order of the PEAK
	 * device itself to ensure that the order is consistent for all
	 * host architectures.
	 */
	ch_id_le = cpu_to_le32(ch_id);
	memcpy(data, (u8 *)&ch_id_le + eeprom->offset, eeprom->len);

	/* update cached value */
	dev->can_channel_id = ch_id;
	return err;
}

/* Every CAN-USB device exports the dev_get_can_channel_id()/dev_set_can_channel_id()
 * operations. They are used here to set the new user defined CAN channel ID.
 */
int peak_usb_set_eeprom(struct net_device *netdev,
			struct ethtool_eeprom *eeprom, u8 *data)
{
	struct peak_usb_device *dev = netdev_priv(netdev);
	u32 ch_id;
	__le32 ch_id_le;
	int err;

	/* first, read the current user defined CAN channel ID */
	err = dev->adapter->dev_get_can_channel_id(dev, &ch_id);
	if (err) {
		netdev_err(netdev, "Failed to init CAN channel id (err %d)\n", err);
		return err;
	}

	/* do update the value with user given bytes.
	 * ethtool operates on individual bytes. The byte order of the CAN
	 * channel ID in memory depends on the kernel architecture. We
	 * convert the CAN channel ID back to the native byte order of the PEAK
	 * device itself to ensure that the order is consistent for all
	 * host architectures.
	 */
	ch_id_le = cpu_to_le32(ch_id);
	memcpy((u8 *)&ch_id_le + eeprom->offset, data, eeprom->len);
	ch_id = le32_to_cpu(ch_id_le);

	/* flash the new value now */
	err = dev->adapter->dev_set_can_channel_id(dev, ch_id);
	if (err) {
		netdev_err(netdev, "Failed to write new CAN channel id (err %d)\n",
			   err);
		return err;
	}

	/* update cached value with the new one */
	dev->can_channel_id = ch_id;

	return 0;
}

int pcan_get_ts_info(struct net_device *dev, struct kernel_ethtool_ts_info *info)
{

Annotation

Implementation Notes