can: gs_usb: add support for reading error counters
authorJeroen Hofstee <jhofstee@victronenergy.com>
Sun, 28 Aug 2022 10:25:02 +0000 (12:25 +0200)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Thu, 20 Oct 2022 09:59:44 +0000 (11:59 +0200)
Add support for reading the device state and CAN error counters, using
the GS_USB_BREQ_GET_STATE control message, if supported by the device,
indicated by the GS_CAN_FEATURE_GET_STATE feature flag.

Signed-off-by: Jeroen Hofstee <jhofstee@victronenergy.com>
Link: https://lore.kernel.org/all/20221019221016.1659260-8-mkl@pengutronix.de
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/usb/gs_usb.c

index 3f00e8d..ccb1a29 100644 (file)
@@ -961,6 +961,42 @@ static int gs_can_open(struct net_device *netdev)
        return 0;
 }
 
+static int gs_usb_get_state(const struct net_device *netdev,
+                           struct can_berr_counter *bec,
+                           enum can_state *state)
+{
+       struct gs_can *dev = netdev_priv(netdev);
+       struct gs_device_state ds;
+       int rc;
+
+       rc = usb_control_msg_recv(interface_to_usbdev(dev->iface), 0,
+                                 GS_USB_BREQ_GET_STATE,
+                                 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                                 dev->channel, 0,
+                                 &ds, sizeof(ds),
+                                 USB_CTRL_GET_TIMEOUT,
+                                 GFP_KERNEL);
+       if (rc)
+               return rc;
+
+       if (le32_to_cpu(ds.state) >= CAN_STATE_MAX)
+               return -EOPNOTSUPP;
+
+       *state = le32_to_cpu(ds.state);
+       bec->txerr = le32_to_cpu(ds.txerr);
+       bec->rxerr = le32_to_cpu(ds.rxerr);
+
+       return 0;
+}
+
+static int gs_usb_can_get_berr_counter(const struct net_device *netdev,
+                                      struct can_berr_counter *bec)
+{
+       enum can_state state;
+
+       return gs_usb_get_state(netdev, bec, &state);
+}
+
 static int gs_can_close(struct net_device *netdev)
 {
        int rc;
@@ -1235,6 +1271,9 @@ static struct gs_can *gs_make_candev(unsigned int channel,
        if (feature & GS_CAN_FEATURE_BERR_REPORTING)
                dev->can.ctrlmode_supported |= CAN_CTRLMODE_BERR_REPORTING;
 
+       if (feature & GS_CAN_FEATURE_GET_STATE)
+               dev->can.do_get_berr_counter = gs_usb_can_get_berr_counter;
+
        /* The CANtact Pro from LinkLayer Labs is based on the
         * LPC54616 µC, which is affected by the NXP LPC USB transfer
         * erratum. However, the current firmware (version 2) doesn't