From patchwork Sun Nov 13 04:01:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vincent Mailhol X-Patchwork-Id: 13041432 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6A547C4332F for ; Sun, 13 Nov 2022 04:02:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235151AbiKMECp (ORCPT ); Sat, 12 Nov 2022 23:02:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60530 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235145AbiKMECm (ORCPT ); Sat, 12 Nov 2022 23:02:42 -0500 Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 904DFDFA0; Sat, 12 Nov 2022 20:02:41 -0800 (PST) Received: by mail-pj1-x102d.google.com with SMTP id e7-20020a17090a77c700b00216928a3917so10975100pjs.4; Sat, 12 Nov 2022 20:02:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=c6xstQC+oWBeL9AwJF0jL3DBXjH1eGPpeBG49uXCkMc=; b=VgkwktM/HL3nCI90zl2uv8vS1vPSCpE5RtTlaAa9072v6Br7A5muUYlZmRYvFr1ZbM UmFAugafSFGTbmHX/aNEDJu6Npq1ZZrx9QtyoE/j8UEpCnhA/HBoa55UcPd/iG1ymtV+ iTK9I5qHx+/x4+ymEcu2pwtZpdmDLsCE9AiyNrSx9pMfGm0/+j106qIxT1eOx5zULt/Y ugj/ucdtLOvgEJFwAHe6oueW6FaJFukayeCEc/7dOU3WY888vl2yteOVMqqJbC6waPMG aAwIYvOabahX2x7+tieJk2p2Y0YR52uXZZTVhEU4miXux8SNkjGJhzX7PasWPZqn3XpM XHtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=c6xstQC+oWBeL9AwJF0jL3DBXjH1eGPpeBG49uXCkMc=; b=PUqreZkv5MjIEQlgopQ/DucsmQrAJPJaxJrad5udkhXSWilOUwrEZBKtDyl2jilGon KFZ8nJeI1ZqrFaH+2kB8KzqEBG6rNfNa45Al0yUaa9BDSZ9NdtZzsHLR9qoTgUPPCLGn 5gyvKpfnpDUDYPKfsU7HosMd0G2sBKYgfcJE30+1CbY+GOD1qoHY3tmH2n5EpOXXFvSS UzsZDeKVelkKnc296bfgu05uaP9ErITc4FuZe8GbJjcFPfJV0EB9RkV7+ckhJNULHKeE 2GpAJZwlSSPkSe61yJfRb3TYoup+WDZ0w6OuJ0VkHepHZsm0j58PqeSU2BAA72XU3fAt DK7w== X-Gm-Message-State: ANoB5plWYgNcUmzZX0JBED+cp1d2XmliPxyNaTPc+xiRG6goINKZh4pQ QE2lgm4ywU33BWPHQmbDmAw= X-Google-Smtp-Source: AA0mqf5paTOxQOWiF4XUNC0+gFvm+JFkmjt0YP+KEpQw+D32KTSaVvSuqMHDuJTU6AA7rB9wHvZypQ== X-Received: by 2002:a17:902:b717:b0:186:6019:d49d with SMTP id d23-20020a170902b71700b001866019d49dmr8766697pls.140.1668312160993; Sat, 12 Nov 2022 20:02:40 -0800 (PST) Received: from localhost.localdomain (124x33x176x97.ap124.ftth.ucom.ne.jp. [124.33.176.97]) by smtp.gmail.com with ESMTPSA id n63-20020a17090a5ac500b00200461cfa99sm7122686pji.11.2022.11.12.20.02.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Nov 2022 20:02:40 -0800 (PST) Sender: Vincent Mailhol From: Vincent Mailhol To: Marc Kleine-Budde , linux-can@vger.kernel.org Cc: Greg Kroah-Hartman , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-usb@vger.kernel.org, Vincent Mailhol Subject: [PATCH v3 1/3] USB: core: export usb_cache_string() Date: Sun, 13 Nov 2022 13:01:06 +0900 Message-Id: <20221113040108.68249-2-mailhol.vincent@wanadoo.fr> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221113040108.68249-1-mailhol.vincent@wanadoo.fr> References: <20221104073659.414147-1-mailhol.vincent@wanadoo.fr> <20221113040108.68249-1-mailhol.vincent@wanadoo.fr> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org usb_cache_string() can also be useful for the drivers so export it. Signed-off-by: Vincent Mailhol Acked-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 1 + drivers/usb/core/usb.h | 1 - include/linux/usb.h | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 4d59d927ae3e..127fac1af676 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1037,6 +1037,7 @@ char *usb_cache_string(struct usb_device *udev, int index) } return smallbuf; } +EXPORT_SYMBOL_GPL(usb_cache_string); /* * usb_get_device_descriptor - (re)reads the device descriptor (usbcore) diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 82538daac8b8..0eac7d4285d1 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -47,7 +47,6 @@ extern int usb_get_device_descriptor(struct usb_device *dev, extern int usb_set_isoch_delay(struct usb_device *dev); extern int usb_get_bos_descriptor(struct usb_device *dev); extern void usb_release_bos_descriptor(struct usb_device *dev); -extern char *usb_cache_string(struct usb_device *udev, int index); extern int usb_set_configuration(struct usb_device *dev, int configuration); extern int usb_choose_configuration(struct usb_device *udev); extern int usb_generic_driver_probe(struct usb_device *udev); diff --git a/include/linux/usb.h b/include/linux/usb.h index 9ff1ad4dfad1..d2d2f41052c0 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1829,6 +1829,7 @@ static inline int usb_get_ptm_status(struct usb_device *dev, void *data) extern int usb_string(struct usb_device *dev, int index, char *buf, size_t size); +extern char *usb_cache_string(struct usb_device *udev, int index); /* wrappers that also update important state inside usbcore */ extern int usb_clear_halt(struct usb_device *dev, int pipe); From patchwork Sun Nov 13 04:01:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vincent Mailhol X-Patchwork-Id: 13041434 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E4E26C4167D for ; Sun, 13 Nov 2022 04:03:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235145AbiKMEDF (ORCPT ); Sat, 12 Nov 2022 23:03:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60776 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235171AbiKMEC4 (ORCPT ); Sat, 12 Nov 2022 23:02:56 -0500 Received: from mail-pf1-x436.google.com (mail-pf1-x436.google.com [IPv6:2607:f8b0:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A2C5813F5E; Sat, 12 Nov 2022 20:02:48 -0800 (PST) Received: by mail-pf1-x436.google.com with SMTP id m6so8247882pfb.0; Sat, 12 Nov 2022 20:02:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=tJBg5PwdywZBY7zF7Ud5t+PwmAlKrob+uTB2RMTOkrI=; b=VbNdGk9HXpySdCR92sMgx3mLV4UJ5FwV3J3yC4U5NtfLmLflbzSrQH4P4VkNhF4yfY Rd8LIX0vhhNQo+yhhyCysa7ERgzA24AI4QNSemunQHAtjy8NCFGIglVN6I+PsgMX/sYP U3FVpWg+Jn0JGWYlEpK6Dw5cVDNfx2jPom1+VYASyxn29mxTt1dnkQzRfWtdxU7Ftoit Cd5jE7JMDQ805LuqpXfWk22d9ayBjLZEmM43+2dcKeGVAUjDheei0RxqVDe3ONu6vSVD nK1PBMfzLAXTSmVRZ8SeYIxuZK7fJnvKXIrXxSqEVSZXFhC/hj2+pi5Uma4FgsAKyLGa 5Jxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=tJBg5PwdywZBY7zF7Ud5t+PwmAlKrob+uTB2RMTOkrI=; b=mSqSc8VRd2egroMSjf7usOoEucF0YgBoTx4hGVMYJqhXQaVhXc9V4A+g/BFiUuS0qp ZCFhAO93y2FI4A6O3IJrXb7IONmRKmc1aBtKL7LaiPjM9qqU69gtnXMu2IEP9jT4u0WD m+6IuEyY1lqCQAszLBa9+xVfF5kJrmpH8Jihgf0kc5m0sI80/HaFkPkj5/TQFKWREkln FSo9X07D1DUeh1W1d+9yRYSyNFhhJSn/a4eRN3OPxkzI230TxBpzxxghafBCYeFasoNe 41OmCeUDwgRs9JeROltvrN1h7gq+fKGvyA8q+j/PdW1VdQeS9tHasAuKB1w4Oq49m+m2 jSeQ== X-Gm-Message-State: ANoB5plYaMtcEQ5oKvdavNM0MB2WVbHXcB8fdOyR79kUDPDxE2OR2smv oDOpN70iDm+o4lAucAiJJaKaiiqc0OPs8g== X-Google-Smtp-Source: AA0mqf4QNaLAuXHsSPwOwAzQJmnBbgGW0GKeqzKAnRYwe+KW1WfYivzbY7hNbY7uNJspxZi5/KR9DQ== X-Received: by 2002:a63:4e16:0:b0:43c:4724:1719 with SMTP id c22-20020a634e16000000b0043c47241719mr7491893pgb.251.1668312166558; Sat, 12 Nov 2022 20:02:46 -0800 (PST) Received: from localhost.localdomain (124x33x176x97.ap124.ftth.ucom.ne.jp. [124.33.176.97]) by smtp.gmail.com with ESMTPSA id n63-20020a17090a5ac500b00200461cfa99sm7122686pji.11.2022.11.12.20.02.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Nov 2022 20:02:46 -0800 (PST) Sender: Vincent Mailhol From: Vincent Mailhol To: Marc Kleine-Budde , linux-can@vger.kernel.org Cc: Greg Kroah-Hartman , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-usb@vger.kernel.org, Vincent Mailhol Subject: [PATCH v3 2/3] can: etas_es58x: export firmware, bootloader and hardware versions in sysfs Date: Sun, 13 Nov 2022 13:01:07 +0900 Message-Id: <20221113040108.68249-3-mailhol.vincent@wanadoo.fr> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221113040108.68249-1-mailhol.vincent@wanadoo.fr> References: <20221104073659.414147-1-mailhol.vincent@wanadoo.fr> <20221113040108.68249-1-mailhol.vincent@wanadoo.fr> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org ES58x devices report below information in their usb product info string: * the firmware version * the bootloader version * the hardware revision Parse this string, store the results in struct es58x_dev and create three new sysfs entries. Those sysfs entries are not critical to use the device, if parsing fails, print an informative log message and continue to probe the device. Now that these value are available in sysfs, no more need to print them in the kernel log so remove es58x_get_product_info(). Signed-off-by: Vincent Mailhol --- drivers/net/can/usb/etas_es58x/Makefile | 2 +- drivers/net/can/usb/etas_es58x/es58x_core.c | 49 +--- drivers/net/can/usb/etas_es58x/es58x_core.h | 51 ++++ drivers/net/can/usb/etas_es58x/es58x_sysfs.c | 231 +++++++++++++++++++ 4 files changed, 286 insertions(+), 47 deletions(-) create mode 100644 drivers/net/can/usb/etas_es58x/es58x_sysfs.c diff --git a/drivers/net/can/usb/etas_es58x/Makefile b/drivers/net/can/usb/etas_es58x/Makefile index a129b4aa0215..8f37aa3e32d3 100644 --- a/drivers/net/can/usb/etas_es58x/Makefile +++ b/drivers/net/can/usb/etas_es58x/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CAN_ETAS_ES58X) += etas_es58x.o -etas_es58x-y = es58x_core.o es581_4.o es58x_fd.o +etas_es58x-y = es58x_core.o es581_4.o es58x_fd.o es58x_sysfs.o diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c index 25f863b4f5f0..c5109117f8e6 100644 --- a/drivers/net/can/usb/etas_es58x/es58x_core.c +++ b/drivers/net/can/usb/etas_es58x/es58x_core.c @@ -2119,48 +2119,6 @@ static void es58x_free_netdevs(struct es58x_device *es58x_dev) } } -/** - * es58x_get_product_info() - Get the product information and print them. - * @es58x_dev: ES58X device. - * - * Do a synchronous call to get the product information. - * - * Return: zero on success, errno when any error occurs. - */ -static int es58x_get_product_info(struct es58x_device *es58x_dev) -{ - struct usb_device *udev = es58x_dev->udev; - const int es58x_prod_info_idx = 6; - /* Empirical tests show a prod_info length of maximum 83, - * below should be more than enough. - */ - const size_t prod_info_len = 127; - char *prod_info; - int ret; - - prod_info = kmalloc(prod_info_len, GFP_KERNEL); - if (!prod_info) - return -ENOMEM; - - ret = usb_string(udev, es58x_prod_info_idx, prod_info, prod_info_len); - if (ret < 0) { - dev_err(es58x_dev->dev, - "%s: Could not read the product info: %pe\n", - __func__, ERR_PTR(ret)); - goto out_free; - } - if (ret >= prod_info_len - 1) { - dev_warn(es58x_dev->dev, - "%s: Buffer is too small, result might be truncated\n", - __func__); - } - dev_info(es58x_dev->dev, "Product info: %s\n", prod_info); - - out_free: - kfree(prod_info); - return ret < 0 ? ret : 0; -} - /** * es58x_init_es58x_dev() - Initialize the ES58X device. * @intf: USB interface. @@ -2243,10 +2201,6 @@ static int es58x_probe(struct usb_interface *intf, if (IS_ERR(es58x_dev)) return PTR_ERR(es58x_dev); - ret = es58x_get_product_info(es58x_dev); - if (ret) - return ret; - for (ch_idx = 0; ch_idx < es58x_dev->num_can_ch; ch_idx++) { ret = es58x_init_netdev(es58x_dev, ch_idx); if (ret) { @@ -2255,6 +2209,8 @@ static int es58x_probe(struct usb_interface *intf, } } + es58x_create_file(es58x_dev->dev); + return ret; } @@ -2272,6 +2228,7 @@ static void es58x_disconnect(struct usb_interface *intf) dev_info(&intf->dev, "Disconnecting %s %s\n", es58x_dev->udev->manufacturer, es58x_dev->udev->product); + es58x_remove_file(es58x_dev->dev); es58x_free_netdevs(es58x_dev); es58x_free_urbs(es58x_dev); usb_set_intfdata(intf, NULL); diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.h b/drivers/net/can/usb/etas_es58x/es58x_core.h index 640fe0a1df63..d3756ff07da5 100644 --- a/drivers/net/can/usb/etas_es58x/es58x_core.h +++ b/drivers/net/can/usb/etas_es58x/es58x_core.h @@ -356,6 +356,45 @@ struct es58x_operators { int (*get_timestamp)(struct es58x_device *es58x_dev); }; +/** + * struct es58x_sw_version - Version number of the firmware or the + * bootloader. + * @major: Version major number, represented on two digits. + * @minor: Version minor number, represented on two digits. + * @revision: Version revision number, represented on two digits. + * + * The firmware and the bootloader share the same format: "xx.xx.xx" + * where 'x' is a digit. Both can be retrieved from the product + * information string. + * + * If @major, @minor and @revision are all zero, the product string + * could not be parsed and the version number is invalid. + */ +struct es58x_sw_version { + u8 major; + u8 minor; + u8 revision; +}; + +/** + * struct es58x_hw_revision - Hardware revision number. + * @letter: Revision letter. + * @major: Version major number, represented on three digits. + * @minor: Version minor number, represented on three digits. + * + * The hardware revision uses its own format: "axxx/xxx" where 'a' is + * a letter and 'x' a digit. It can be retrieved from the product + * information string. + * + * If @letter, @major and @minor are all zero, the product string + * could not be parsed and the hardware revision number is invalid. + */ +struct es58x_hw_revision { + char letter; + u16 major; + u16 minor; +}; + /** * struct es58x_device - All information specific to an ES58X device. * @dev: Device information. @@ -373,6 +412,9 @@ struct es58x_operators { * queue wake/stop logic should prevent this URB from getting * empty. Please refer to es58x_get_tx_urb() for more details. * @tx_urbs_idle_cnt: number of urbs in @tx_urbs_idle. + * @firmware_version: The firmware version number. + * @bootloader_version: The bootloader version number. + * @hardware_revision: The hardware revision number. * @ktime_req_ns: kernel timestamp when es58x_set_realtime_diff_ns() * was called. * @realtime_diff_ns: difference in nanoseconds between the clocks of @@ -408,6 +450,10 @@ struct es58x_device { struct usb_anchor tx_urbs_idle; atomic_t tx_urbs_idle_cnt; + struct es58x_sw_version firmware_version; + struct es58x_sw_version bootloader_version; + struct es58x_hw_revision hardware_revision; + u64 ktime_req_ns; s64 realtime_diff_ns; @@ -674,6 +720,7 @@ static inline enum es58x_flag es58x_get_flags(const struct sk_buff *skb) return es58x_flags; } +/* Prototypes from es58x_core.c. */ int es58x_can_get_echo_skb(struct net_device *netdev, u32 packet_idx, u64 *tstamps, unsigned int pkts); int es58x_tx_ack_msg(struct net_device *netdev, u16 tx_free_entries, @@ -691,6 +738,10 @@ int es58x_rx_cmd_ret_u32(struct net_device *netdev, int es58x_send_msg(struct es58x_device *es58x_dev, u8 cmd_type, u8 cmd_id, const void *msg, u16 cmd_len, int channel_idx); +/* Prototypes from es58x_sysfs.c. */ +void es58x_create_file(struct device *dev); +void es58x_remove_file(struct device *dev); + extern const struct es58x_parameters es581_4_param; extern const struct es58x_operators es581_4_ops; diff --git a/drivers/net/can/usb/etas_es58x/es58x_sysfs.c b/drivers/net/can/usb/etas_es58x/es58x_sysfs.c new file mode 100644 index 000000000000..db1d57b6cda5 --- /dev/null +++ b/drivers/net/can/usb/etas_es58x/es58x_sysfs.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* Driver for ETAS GmbH ES58X USB CAN(-FD) Bus Interfaces. + * + * File es58x_sysfs.c: parse the product information string and + * populate sysfs. + * + * Copyright (c) 2022 Vincent Mailhol + */ + +#include +#include +#include +#include + +#include "es58x_core.h" + +/* USB descriptor index containing the product information string. */ +#define ES58X_PROD_INFO_IDX 6 + +/** + * es58x_parse_sw_version() - Extract boot loader or firmware version. + * @es58x_dev: ES58X device. + * @prod_info: USB custom string returned by the device. + * @prefix: Select which information should be parsed. Set it to "FW" + * to parse the firmware version or to "BL" to parse the + * bootloader version. + * + * The @prod_info string contains the firmware and the bootloader + * version number all prefixed by a magic string and concatenated with + * other numbers. Depending on the device, the firmware (bootloader) + * format is either "FW_Vxx.xx.xx" ("BL_Vxx.xx.xx") or "FW:xx.xx.xx" + * ("BL:xx.xx.xx") where 'x' represents a digit. @prod_info must + * contains the common part of those prefixes: "FW" or "BL". + * + * Parse @prod_info and store the version number in + * &es58x_dev.firmware_version or &es58x_dev.bootloader_version + * according to @prefix value. + * + * Return: zero on success, -EINVAL if @prefix contains an invalid + * value and -EBADMSG if @prod_info could not be parsed. + */ +static int es58x_parse_sw_version(struct es58x_device *es58x_dev, + const char *prod_info, const char *prefix) +{ + struct es58x_sw_version *version; + int major, minor, revision; + + if (!strcmp(prefix, "FW")) + version = &es58x_dev->firmware_version; + else if (!strcmp(prefix, "BL")) + version = &es58x_dev->bootloader_version; + else + return -EINVAL; + + /* Go to prefix */ + prod_info = strstr(prod_info, prefix); + if (!prod_info) + return -EBADMSG; + /* Go to beginning of the version number */ + while (!isdigit(*prod_info)) { + prod_info++; + if (!*prod_info) + return -EBADMSG; + } + + if (sscanf(prod_info, "%2u.%2u.%2u", &major, &minor, &revision) != 3) + return -EBADMSG; + + version->major = major; + version->minor = minor; + version->revision = revision; + + return 0; +} + +/** + * firmware_version_show() - Emit the firmware version in sysfs. + * @dev: Device. + * @attr: Device attribute, not used. + * @buf: Where to write the firmware version. + * + * Return: number of bytes written. + */ +static ssize_t firmware_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct es58x_device *es58x_dev = dev_get_drvdata(dev); + struct es58x_sw_version *fw_ver = &es58x_dev->firmware_version; + + return sysfs_emit(buf, "%02u.%02u.%02u\n", + fw_ver->major, fw_ver->minor, fw_ver->revision); +} +static DEVICE_ATTR_RO(firmware_version); + +/** + * bootloader_version_show() - Emit the bootloader version in sysfs. + * @dev: Device. + * @attr: Device attribute, not used. + * @buf: Where to write the bootloader version. + * + * Return: number of bytes written. + */ +static ssize_t bootloader_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct es58x_device *es58x_dev = dev_get_drvdata(dev); + struct es58x_sw_version *bl_ver = &es58x_dev->bootloader_version; + + return sysfs_emit(buf, "%02u.%02u.%02u\n", + bl_ver->major, bl_ver->minor, bl_ver->revision); +} +static DEVICE_ATTR_RO(bootloader_version); + +/** + * es58x_parse_hw_rev() - Extract hardware revision number + * @es58x_dev: ES58X device. + * @prod_info: USB custom string returned by the device. + * + * @prod_info contains the hardware revision prefixed by a magic + * string and conquenated together with other numbers. Depending on + * the device, the hardware revision format is either + * "HW_VER:axxx/xxx" or "HR:axxx/xxx" where 'a' represents a letter + * and 'x' a digit. + * + * Parse @prod_info and store the hardware revision number in + * &es58x_dev.hardware_revision. + * + * Return: zero on success, -EBADMSG if @prod_info could not be + * parsed. + */ +static int es58x_parse_hw_rev(struct es58x_device *es58x_dev, + const char *prod_info) +{ + char letter; + int major, minor; + + /* The only occurrence of 'H' is in the hardware revision prefix. */ + prod_info = strchr(prod_info, 'H'); + if (!prod_info) + return -EBADMSG; + /* Go to beginning of the hardware revision */ + prod_info = strchr(prod_info, ':'); + if (!prod_info) + return -EBADMSG; + prod_info++; + + if (sscanf(prod_info, "%c%3u/%3u", &letter, &major, &minor) != 3) + return -EBADMSG; + + es58x_dev->hardware_revision.letter = letter; + es58x_dev->hardware_revision.major = major; + es58x_dev->hardware_revision.minor = minor; + + return 0; +} + +/** + * hardware_revision_show() - Emit the hardware revision in sysfs. + * @dev: Device. + * @attr: Device attribute, not used. + * @buf: Where to write the hardware revision. + * + * Return: number of bytes written. + */ +static ssize_t hardware_revision_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct es58x_device *es58x_dev = dev_get_drvdata(dev); + struct es58x_hw_revision *hw_rev = &es58x_dev->hardware_revision; + + return sysfs_emit(buf, "%c%03u/%03u\n", + hw_rev->letter, hw_rev->major, hw_rev->minor); +} +static DEVICE_ATTR_RO(hardware_revision); + +/** + * es58x_create_file() - Expose the product information through sysfs. + * @dev: Device. + * + * Retrieve the product information string and parse it to extract the + * firmware version, the bootloader version and the hardware + * revision. Then create three sysfs entries. + * + * If the parsing fails, simply emit an informative log message and + * continue because these files are not critical for the driver to + * operate. + */ +void es58x_create_file(struct device *dev) +{ + struct es58x_device *es58x_dev = dev_get_drvdata(dev); + char *prod_info; + + prod_info = usb_cache_string(es58x_dev->udev, ES58X_PROD_INFO_IDX); + if (!prod_info) { + dev_warn(dev, "could not retrieve the product info string\n"); + return; + } + + if (!es58x_parse_sw_version(es58x_dev, prod_info, "FW")) + device_create_file(dev, &dev_attr_firmware_version); + else + dev_info(dev, "parsing error: can not create firmware_version sysfs entry\n"); + + if (!es58x_parse_sw_version(es58x_dev, prod_info, "BL")) + device_create_file(dev, &dev_attr_bootloader_version); + else + dev_info(dev, "parsing error: can not create bootloader_version sysfs entry\n"); + + if (!es58x_parse_hw_rev(es58x_dev, prod_info)) + device_create_file(dev, &dev_attr_hardware_revision); + else + dev_info(dev, "parsing error: can not create hardware_revision sysfs entry\n"); + + kfree(prod_info); +} + +/** + * es58x_remove_file() - Remove sysfs files created by es58x_create_file(). + * @dev: Device. + * + * device_remove_file() checks if the sysfs file exists before trying + * to remove it so it is safe to call it even if these files were not + * created by es58x_create_file() due of a parsing error. + */ +void es58x_remove_file(struct device *dev) +{ + device_remove_file(dev, &dev_attr_firmware_version); + device_remove_file(dev, &dev_attr_bootloader_version); + device_remove_file(dev, &dev_attr_hardware_revision); +} From patchwork Sun Nov 13 04:01:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vincent Mailhol X-Patchwork-Id: 13041433 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B657FC43217 for ; Sun, 13 Nov 2022 04:03:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235179AbiKMEDG (ORCPT ); Sat, 12 Nov 2022 23:03:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60912 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235174AbiKMEDC (ORCPT ); Sat, 12 Nov 2022 23:03:02 -0500 Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 19F8213F71; Sat, 12 Nov 2022 20:02:51 -0800 (PST) Received: by mail-pj1-x1032.google.com with SMTP id u8-20020a17090a5e4800b002106dcdd4a0so11002768pji.1; Sat, 12 Nov 2022 20:02:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date :message-id:reply-to; bh=hDuvicETB47o1CIVZJhl8/Y9cPAH0K8QGejUp0fFrIg=; b=PfhhcE1ybwFdUQ/LcvjTBXSkXd4uA29ayC9av6hO0Izwf1LYMSx0c6JarAgAdaVbRY r1OvZzyqnH7pprM173+rOSWqpWqpAI00Xj/EwbBOc117ctFCrgFmoUW1xM8YaJTJ9iAs A1flunV8MOILrgB0bI9WNUlHKWrKI4QpjSX0s3lBUdId2OL8DjIwrZxIYgW6e80JSoF2 zWIlAxaryArW4dU7fVBb07u2DICW7640/Tb8hoAXJ7iHELqNMxQz1h7Zb9allRp7jS8e an85URhYygnHVxCzuW3fWQ8ufC8/rIjoaL3ob7DbUJWdscd3vRcH/a/ogvfKvXHZRkiU ewxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=hDuvicETB47o1CIVZJhl8/Y9cPAH0K8QGejUp0fFrIg=; b=hsmp2XosM7cMGuH9/DelIVv23bYs2r0Jp1RvmDpgYvxtjSh6Fbt5HHKMVrgDNMpBek M0gU7CRfYd/xe8JGfDVGVf3MktMlgg1ilWG6ysnON0ZngrxdhwTz5eIOPVl87hbpbGxH tkXehden/u5k+ZHau1mRKhQfpP0Tl8UvuBldaVac9vg5mGMqYN79nw+zrAh18ju3fVhT FbzfavDuOHWy8zLWCLF5KJzYw2mRKXQJoxFAvfiOgH0oHd86JNJRadg8R7Jx60xnsE5S qDVDlicCCyw0gWRSK1lKeIpuJ8TruIC/M3QbjlM1GzQ8Yn+MpmJjblKgEEYWHlX3bJca JJMA== X-Gm-Message-State: ANoB5pkviWhPYsR243fjzrv0kWnm+rz38yZ6ZrfdC/u+G5bZTrbVE1pk YMl17ozJOZfcpir0PE+7k/k= X-Google-Smtp-Source: AA0mqf4eRIpKEXGVlu+vzC91odIvs50k4JA6h0gtI90ohrVjuqCvCCGAnQe+iGqWWCeZvX9HS/aoew== X-Received: by 2002:a17:90a:c702:b0:213:16b5:f45e with SMTP id o2-20020a17090ac70200b0021316b5f45emr8505607pjt.170.1668312170547; Sat, 12 Nov 2022 20:02:50 -0800 (PST) Received: from localhost.localdomain (124x33x176x97.ap124.ftth.ucom.ne.jp. [124.33.176.97]) by smtp.gmail.com with ESMTPSA id n63-20020a17090a5ac500b00200461cfa99sm7122686pji.11.2022.11.12.20.02.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Nov 2022 20:02:50 -0800 (PST) Sender: Vincent Mailhol From: Vincent Mailhol To: Marc Kleine-Budde , linux-can@vger.kernel.org Cc: Greg Kroah-Hartman , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linux-usb@vger.kernel.org, Vincent Mailhol Subject: [PATCH v3 3/3] can: etas_es58x: report firmware-version through ethtool Date: Sun, 13 Nov 2022 13:01:08 +0900 Message-Id: <20221113040108.68249-4-mailhol.vincent@wanadoo.fr> X-Mailer: git-send-email 2.37.4 In-Reply-To: <20221113040108.68249-1-mailhol.vincent@wanadoo.fr> References: <20221104073659.414147-1-mailhol.vincent@wanadoo.fr> <20221113040108.68249-1-mailhol.vincent@wanadoo.fr> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Implement ethtool_ops::get_drvinfo() in order to report the firmware version. Firmware version 0.0.0 has a special meaning and just means that we could not parse the product information string. In such case, do nothing (i.e. leave the .fw_version string empty). Signed-off-by: Vincent Mailhol --- *N.B.* Drivers had to also fill ethtool_drvinfo::driver and ethtool_drvinfo::bus_info. Starting this week, this is not needed anymore because of commit edaf5df22cb8 ("ethtool: ethtool_get_drvinfo: populate drvinfo fields even if callback exits"). https://git.kernel.org/netdev/net-next/c/edaf5df22cb8 --- drivers/net/can/usb/etas_es58x/es58x_core.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c index c5109117f8e6..a048e0d40c97 100644 --- a/drivers/net/can/usb/etas_es58x/es58x_core.c +++ b/drivers/net/can/usb/etas_es58x/es58x_core.c @@ -1978,7 +1978,28 @@ static const struct net_device_ops es58x_netdev_ops = { .ndo_eth_ioctl = can_eth_ioctl_hwts, }; +/** + * es58x_get_drvinfo() - Get the firmware version. + * @netdev: CAN network device. + * @drvinfo: Driver information. + * + * Populate @drvinfo with the firmware version. The core will populate + * the rest. + */ +static void es58x_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) +{ + struct es58x_device *es58x_dev = es58x_priv(netdev)->es58x_dev; + struct es58x_sw_version *fw_ver = &es58x_dev->firmware_version; + + if (fw_ver->major || fw_ver->minor || fw_ver->revision) + snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), + "%02u.%02u.%02u", + fw_ver->major, fw_ver->minor, fw_ver->revision); +} + static const struct ethtool_ops es58x_ethtool_ops = { + .get_drvinfo = es58x_get_drvinfo, .get_ts_info = can_ethtool_op_get_ts_info_hwts, };