Commit 6d02f6da authored by Lukas Magel's avatar Lukas Magel Committed by Marc Kleine-Budde
Browse files

can: peak_usb: export PCAN CAN channel ID as sysfs device attribute



This patch exports the CAN channel ID as a sysfs attribute. The CAN
channel ID is a user-configurable u8/u32 identifier that can be set
individually for each CAN interface of a PEAK USB device.

Exporting the channel ID as a sysfs attribute allows users to easily read
the ID and to write udev rules that can match against the ID. This is
especially useful for PEAK USB devices that do not export a serial
number at SUB level.

Signed-off-by: default avatarStephane Grosjean <s.grosjean@peak-system.com>
Signed-off-by: default avatarLukas Magel <lukas.magel@posteo.net>
Link: https://lore.kernel.org/all/20230116200932.157769-7-lukas.magel@posteo.net


Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 36d007c6
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line

What:		/sys/class/net/<iface>/peak_usb/can_channel_id
Date:		November 2022
KernelVersion:	6.2
Contact:	Stephane Grosjean <s.grosjean@peak-system.com>
Description:
		PEAK PCAN-USB devices support user-configurable CAN channel
		identifiers. Contrary to a USB serial number, these identifiers
		are writable and can be set per CAN interface. This means that
		if a USB device exports multiple CAN interfaces, each of them
		can be assigned a unique channel ID.
		This attribute provides read-only access to the currently
		configured value of the channel identifier. Depending on the
		device type, the identifier has a length of 8 or 32 bit. The
		value read from this attribute is always an 8 digit 32 bit
		hexadecimal value in big endian format. If the device only
		supports an 8 bit identifier, the upper 24 bit of the value are
		set to zero.
+25 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
#include <linux/netdevice.h>
#include <linux/usb.h>
#include <linux/ethtool.h>
#include <linux/sysfs.h>
#include <linux/device.h>

#include <linux/can.h>
#include <linux/can/dev.h>
@@ -53,6 +55,26 @@ static const struct usb_device_id peak_usb_table[] = {

MODULE_DEVICE_TABLE(usb, peak_usb_table);

static ssize_t can_channel_id_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct net_device *netdev = to_net_dev(dev);
	struct peak_usb_device *peak_dev = netdev_priv(netdev);

	return sysfs_emit(buf, "%08X\n", peak_dev->can_channel_id);
}
static DEVICE_ATTR_RO(can_channel_id);

/* mutable to avoid cast in attribute_group */
static struct attribute *peak_usb_sysfs_attrs[] = {
	&dev_attr_can_channel_id.attr,
	NULL,
};

static const struct attribute_group peak_usb_sysfs_group = {
	.name	= "peak_usb",
	.attrs	= peak_usb_sysfs_attrs,
};

/*
 * dump memory
 */
@@ -961,6 +983,9 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter,
	/* add ethtool support */
	netdev->ethtool_ops = peak_usb_adapter->ethtool_ops;

	/* register peak_usb sysfs files */
	netdev->sysfs_groups[0] = &peak_usb_sysfs_group;

	init_usb_anchor(&dev->rx_submitted);

	init_usb_anchor(&dev->tx_submitted);