diff options
Diffstat (limited to 'drivers/net/can/usb/peak_usb/pcan_usb.c')
-rw-r--r-- | drivers/net/can/usb/peak_usb/pcan_usb.c | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 687dd542f7f6..b211b6e283a2 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -9,10 +9,11 @@ * Many thanks to Klaus Hitschler <klaus.hitschler@gmx.de> */ #include <asm/unaligned.h> + +#include <linux/ethtool.h> +#include <linux/module.h> #include <linux/netdevice.h> #include <linux/usb.h> -#include <linux/module.h> -#include <linux/ethtool.h> #include <linux/can.h> #include <linux/can/dev.h> @@ -381,23 +382,42 @@ static int pcan_usb_get_serial(struct peak_usb_device *dev, u32 *serial_number) } /* - * read device id from device + * read can channel id from device */ -static int pcan_usb_get_device_id(struct peak_usb_device *dev, u32 *device_id) +static int pcan_usb_get_can_channel_id(struct peak_usb_device *dev, u32 *can_ch_id) { u8 args[PCAN_USB_CMD_ARGS_LEN]; int err; err = pcan_usb_wait_rsp(dev, PCAN_USB_CMD_DEVID, PCAN_USB_GET, args); if (err) - netdev_err(dev->netdev, "getting device id failure: %d\n", err); + netdev_err(dev->netdev, "getting can channel id failure: %d\n", err); else - *device_id = args[0]; + *can_ch_id = args[0]; return err; } +/* set a new CAN channel id in the flash memory of the device */ +static int pcan_usb_set_can_channel_id(struct peak_usb_device *dev, u32 can_ch_id) +{ + u8 args[PCAN_USB_CMD_ARGS_LEN]; + + /* this kind of device supports 8-bit values only */ + if (can_ch_id > U8_MAX) + return -EINVAL; + + /* during the flash process the device disconnects during ~1.25 s.: + * prohibit access when interface is UP + */ + if (dev->netdev->flags & IFF_UP) + return -EBUSY; + + args[0] = can_ch_id; + return pcan_usb_send_cmd(dev, PCAN_USB_CMD_DEVID, PCAN_USB_SET, args); +} + /* * update current time ref with received timestamp */ @@ -963,9 +983,18 @@ static int pcan_usb_set_phys_id(struct net_device *netdev, return err; } +/* This device only handles 8-bit CAN channel id. */ +static int pcan_usb_get_eeprom_len(struct net_device *netdev) +{ + return sizeof(u8); +} + static const struct ethtool_ops pcan_usb_ethtool_ops = { .set_phys_id = pcan_usb_set_phys_id, .get_ts_info = pcan_get_ts_info, + .get_eeprom_len = pcan_usb_get_eeprom_len, + .get_eeprom = peak_usb_get_eeprom, + .set_eeprom = peak_usb_set_eeprom, }; /* @@ -1017,7 +1046,8 @@ const struct peak_usb_adapter pcan_usb = { .dev_init = pcan_usb_init, .dev_set_bus = pcan_usb_write_mode, .dev_set_bittiming = pcan_usb_set_bittiming, - .dev_get_device_id = pcan_usb_get_device_id, + .dev_get_can_channel_id = pcan_usb_get_can_channel_id, + .dev_set_can_channel_id = pcan_usb_set_can_channel_id, .dev_decode_buf = pcan_usb_decode_buf, .dev_encode_msg = pcan_usb_encode_msg, .dev_start = pcan_usb_start, |