This patch adds under /sys/class/net/canX a new group named "peak_usb" which contains a "dev_num" entry accessible for reading (display in decimal of the numerical value stored in non-volatile memory of the USB device) and also for writing (modification by the user of this value). Signed-off-by: Stephane Grosjean <s.grosjean@xxxxxxxxxxxxxxx> --- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 76 ++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index ad9f435fc57e..08d1db988d81 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -53,6 +53,17 @@ static const struct usb_device_id peak_usb_table[] = { MODULE_DEVICE_TABLE(usb, peak_usb_table); +/* sysfs shortcuts */ +#define PEAK_USB_DEVICE_ATTR_RW(_name) \ + struct device_attribute peak_usb_attr_##_name = \ + __ATTR(_name, 0644, \ + peak_usb_##_name##_show, peak_usb_##_name##_store) + +#define PEAK_USB_DEVICE_ATTR_RO(_name) \ + struct device_attribute peak_usb_attr_##_name = \ + __ATTR(_name, 0444, \ + peak_usb_##_name##_show, NULL) + /* * dump memory */ @@ -784,6 +795,61 @@ static const struct net_device_ops peak_usb_netdev_ops = { .ndo_change_mtu = can_change_mtu, }; +static inline struct peak_usb_device *to_peak_usb_device(struct device *dev) +{ + return netdev_priv(to_net_dev(dev)); +} + +static ssize_t peak_usb_dev_num_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct peak_usb_device *pdev = to_peak_usb_device(dev); + + if (!pdev->adapter->dev_get_user_devid) + return -EOPNOTSUPP; + + pdev->adapter->dev_get_user_devid(pdev, &pdev->device_number); + + return snprintf(buf, PAGE_SIZE, "%u\n", pdev->device_number); +} + +static ssize_t peak_usb_dev_num_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct peak_usb_device *pdev = to_peak_usb_device(dev); + unsigned long devid; + int err; + + if (!pdev->adapter->dev_set_user_devid) + return -EOPNOTSUPP; + + err = kstrtoul(buf, 0, &devid); + if (err) + return err; + + err = pdev->adapter->dev_set_user_devid(pdev, devid); + if (err) + return err; + + /* on success, update cached value */ + pdev->device_number = devid; + + return count; +} + +static PEAK_USB_DEVICE_ATTR_RW(dev_num); + +static const struct attribute *const peak_usb_net_attrs[] = { + &peak_usb_attr_dev_num.attr, + NULL, +}; + +static const struct attribute_group peak_usb_net_attrs_group = { + .name = PCAN_USB_DRIVER_NAME, + .attrs = (struct attribute **)peak_usb_net_attrs, +}; + /* * create one device which is attached to CAN controller #ctrl_idx of the * usb adapter. @@ -886,6 +952,12 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter, if (dev->adapter->dev_get_user_devid) dev->adapter->dev_get_user_devid(dev, &dev->device_number); + /* add our own attrs to /sys/class/net/canX node */ + err = sysfs_create_group(&netdev->dev.kobj, &peak_usb_net_attrs_group); + if (err) + netdev_warn(netdev, + "can't add sysfs features (err %d)\n", err); + netdev_info(netdev, "attached to %s channel %u (device %u)\n", peak_usb_adapter->name, ctrl_idx, dev->device_number); @@ -925,6 +997,9 @@ static void peak_usb_disconnect(struct usb_interface *intf) dev->state &= ~PCAN_USB_STATE_CONNECTED; strlcpy(name, netdev->name, IFNAMSIZ); + sysfs_remove_group(&netdev->dev.kobj, + &peak_usb_net_attrs_group); + unregister_candev(netdev); kfree(dev->cmd_buf); @@ -958,6 +1033,7 @@ static int peak_usb_probe(struct usb_interface *intf, return err; } + /* create one CAN device for each CAN controller */ for (i = 0; i < peak_usb_adapter->ctrl_count; i++) { err = peak_usb_create_dev(peak_usb_adapter, intf, i); if (err) { -- 2.25.1