From nobody Wed Feb 26 23:46:11 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4Z3B1w2NLnz5pBqW; Wed, 26 Feb 2025 23:46:12 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Z3B1w141Qz3p8d; Wed, 26 Feb 2025 23:46:12 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1740613572; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=hoW6j/T1bnpGdYu4dkm0uF9s6pDA6YL7BaKTIzVczk0=; b=bg78bTcF5uHIhePnvYPlBulMrXTyPS6fRn0tldua0BCb/hXX6jyWXcvs5/ZzQOTFYB7jsu +ngn5GT3d46ZSdGbdwZSR29ohZIBZuEUxGt9vi+AOgN9MiH9JbwZuOTGTDfQvsnWAMxaJA KJ6yNo3VDWCOKgisiEQRShBm5f82Sq0yYueIP5dNtVF3kXDnVgcQvfXPF7D9yufH+YOasB 6azCAjwGXYV0llUz6TeA6B/qaak/UcEAwrXr1zSN4/9vrDFz/q0jQ07FKH2VBYT5HVwtmJ N4ixFguoPyLKNSksSZfWOCXVq7mwPz6/2YQ4kCRq+Hi0qVQgy/8Lbhj7JH2v9g== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1740613572; a=rsa-sha256; cv=none; b=xk0Js4Qb4ZaQJeWDSQUnRyAb+Vy+zL2XBx0TOOx6eFJw8SKJz/Q6HB6WkXTsEYtfx7eL2s IecdEoipMC8d7owEnX8GQTo9ZcN9EFepBFsylLbRCn2+hcdlE8ipgQFkmLMZZvyKWNvD3z ZO3Myk67/dvkL+ArEfR1bciT4RgoN2xUyq9UyPVNTHbs5Rnjj2nMRblr6B8otuytcedW24 3wFKT2WJS+SZ7xUSzpWMkVkP8BNTfOfxZybEEftSUlRe0IftrF/14CzJiD7n+v7s8HA7D1 ft7xlP3C+O45+YWk7dMCCw0wsoVNXn6Uw4PhUI89B5L3CLfxjb8MbgEWKmGt4w== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1740613572; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=hoW6j/T1bnpGdYu4dkm0uF9s6pDA6YL7BaKTIzVczk0=; b=yMtBtMFKf6rdXKdPgA0ff9ierDCYOVF1vaxDEkxeCdVybmcWpu6hh2qk3NLSglDMhbGS4t zIiur9nHObbhE9WaJjNegDKiSxjsV39VgFnOlNtc+a+wj5nyGGxZT8vxcUWyQxdLzyXwx8 Q5Tmj+D9B0n/8GOjK9XhoQgTf2wh/yNQk7O21tkRcnu+OoK5byM8Vc1lHRHR8RWulNRprO GvzxCvSwHl3iIU/BoCCJHF4ekUiwTzyImbB/xqIiZG4BByYLqqRa9pgY7x5nQP9Ev5cFRG emgCUP6j/6W5LLudnhligRu+3e3zcxwGoRFhkwJYyPnI9jC2l3QnxsMmGzVI8A== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Z3B1w0Lz3z34Q; Wed, 26 Feb 2025 23:46:12 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 51QNkBvl086482; Wed, 26 Feb 2025 23:46:11 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 51QNkBTj086479; Wed, 26 Feb 2025 23:46:11 GMT (envelope-from git) Date: Wed, 26 Feb 2025 23:46:11 GMT Message-Id: <202502262346.51QNkBTj086479@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: "Bjoern A. Zeeb" Subject: git: 7907a9276081 - stable/14 - usbconfig: add -l option to dump_device_desc for single line output List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bz X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 7907a9276081e9b1ccac839af91fe096e6779e9f Auto-Submitted: auto-generated The branch stable/14 has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=7907a9276081e9b1ccac839af91fe096e6779e9f commit 7907a9276081e9b1ccac839af91fe096e6779e9f Author: Bjoern A. Zeeb AuthorDate: 2025-02-12 22:53:06 +0000 Commit: Bjoern A. Zeeb CommitDate: 2025-02-26 23:45:57 +0000 usbconfig: add -l option to dump_device_desc for single line output Like pciconf -l add a -l to dump_device_desc for usbconfig which will fold most fields into a single line. We do filter out some we think will not be interesting in this case. While mangling with string output in ways not always anticipated when the program was initially written this should help to parse the available devices for programs like fwget(8). While I had this in mind for other bits for a while I got prompted by D48678 to finally do it. Sponsored by: The FreebSD Foundation Reviewed by: bapt (LGTM), ziaee (man) Differential Revision: https://reviews.freebsd.org/D48974 (cherry picked from commit c66308d7bcc3931b60a096bfe6ba0f50105e77de) --- usr.sbin/usbconfig/dump.c | 145 +++++++++++++++++++++++++++++++++++------ usr.sbin/usbconfig/dump.h | 5 +- usr.sbin/usbconfig/usbconfig.8 | 6 +- usr.sbin/usbconfig/usbconfig.c | 20 ++++-- 4 files changed, 148 insertions(+), 28 deletions(-) diff --git a/usr.sbin/usbconfig/dump.c b/usr.sbin/usbconfig/dump.c index 36f026bfc2fb..2a4a5300efeb 100644 --- a/usr.sbin/usbconfig/dump.c +++ b/usr.sbin/usbconfig/dump.c @@ -3,6 +3,10 @@ * * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. * Copyright (c) 2024 Baptiste Daroussin + * Copyright (c) 2025 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,22 +32,32 @@ #include +#include #include #include #include +#include #include #include #include #include #include +#include #include #include +#include + #include "dump.h" #include "pathnames.h" +#ifndef IOUSB +#define IOUSB(a) a +#endif + #define DUMP0(n,type,field,...) dump_field(pdev, " ", #field, n->field); +#define DUMP0L(n,type,field,...) dump_fieldl(pdev, " ", #field, n->field); #define DUMP1(n,type,field,...) dump_field(pdev, " ", #field, n->field); #define DUMP2(n,type,field,...) dump_field(pdev, " ", #field, n->field); #define DUMP3(n,type,field,...) dump_field(pdev, " ", #field, n->field); @@ -113,11 +127,21 @@ dump_power_mode(uint8_t value) } static void -dump_field(struct libusb20_device *pdev, const char *plevel, - const char *field, uint32_t value) +_dump_field(struct libusb20_device *pdev, const char *plevel, + const char *field, uint32_t value, bool list_mode) { uint8_t temp_string[256]; + if (list_mode) { + /* Skip fields we are not interested in. */ + if (strcmp(field, "bLength") == 0 || + strcmp(field, "bDescriptorType") == 0 || + strcmp(field, "bMaxPacketSize0") == 0) + return; + + printf("%s=%#06x ", field, value); + return; + } printf("%s%s = 0x%04x ", plevel, field, value); if (strlen(plevel) == 8) { @@ -257,6 +281,20 @@ dump_field(struct libusb20_device *pdev, const char *plevel, printf("\n"); } +static void +dump_field(struct libusb20_device *pdev, const char *plevel, + const char *field, uint32_t value) +{ + _dump_field(pdev, plevel, field, value, false); +} + +static void +dump_fieldl(struct libusb20_device *pdev, const char *plevel, + const char *field, uint32_t value) +{ + _dump_field(pdev, plevel, field, value, true); +} + static void dump_extra(struct libusb20_me_struct *str, const char *plevel) { @@ -396,16 +434,34 @@ load_vendors(void) return (usb_vendors); } +enum _device_descr_list_type { + _DEVICE_DESCR_LIST_TYPE_DEFAULT = 0, + _DEVICE_DESCR_LIST_TYPE_UGEN = 1, + _DEVICE_DESCR_LIST_TYPE_PRODUCT_VENDOR = 2, +}; + static char * -_device_desc(struct libusb20_device *pdev) +_device_desc(struct libusb20_device *pdev, + enum _device_descr_list_type list_type) { static struct usb_vendors *usb_vendors = NULL; char *desc = NULL; const char *vendor = NULL, *product = NULL; - uint16_t vid = libusb20_dev_get_device_desc(pdev)->idVendor; - uint16_t pid = libusb20_dev_get_device_desc(pdev)->idProduct; + uint16_t vid; + uint16_t pid; struct usb_vendor_info *vi; struct usb_product_info *pi; + struct usb_device_info devinfo; + + if (list_type == _DEVICE_DESCR_LIST_TYPE_UGEN) { + asprintf(&desc, "ugen%u.%u", + libusb20_dev_get_bus_number(pdev), + libusb20_dev_get_address(pdev)); + return (desc); + } + + vid = libusb20_dev_get_device_desc(pdev)->idVendor; + pid = libusb20_dev_get_device_desc(pdev)->idProduct; if (usb_vendors == NULL) usb_vendors = load_vendors(); @@ -424,6 +480,44 @@ _device_desc(struct libusb20_device *pdev) } } } + + /* + * Try to gather the information; libusb2 unfortunately seems to + * only build an entire string but not save vendor/product individually. + */ + if (vendor == NULL || product == NULL) { + char buf[64]; + int f; + + snprintf(buf, sizeof(buf), "/dev/" USB_GENERIC_NAME "%u.%u", + libusb20_dev_get_bus_number(pdev), + libusb20_dev_get_address(pdev)); + + f = open(buf, O_RDWR); + if (f < 0) + goto skip_vp_recovery; + + if (ioctl(f, IOUSB(USB_GET_DEVICEINFO), &devinfo)) + goto skip_vp_recovery; + + + if (vendor == NULL) + vendor = devinfo.udi_vendor; + if (product == NULL) + product = devinfo.udi_product; + +skip_vp_recovery: + if (f >= 0) + close(f); + } + + if (list_type == _DEVICE_DESCR_LIST_TYPE_PRODUCT_VENDOR) { + asprintf(&desc, "vendor='%s' product='%s'", + (vendor != NULL) ? vendor : "", + (product != NULL) ? product : ""); + return (desc); + } + if (vendor == NULL || product == NULL) return (NULL); @@ -433,12 +527,12 @@ _device_desc(struct libusb20_device *pdev) product, vendor, libusb20_dev_get_bus_number(pdev)); - return (desc); } void -dump_device_info(struct libusb20_device *pdev, uint8_t show_ifdrv) +dump_device_info(struct libusb20_device *pdev, uint8_t show_ifdrv, + bool list_mode) { char buf[128]; uint8_t n; @@ -447,18 +541,22 @@ dump_device_info(struct libusb20_device *pdev, uint8_t show_ifdrv) usage = libusb20_dev_get_power_usage(pdev); - desc = _device_desc(pdev); - - printf("%s, cfg=%u md=%s spd=%s pwr=%s (%umA)\n", - desc ? desc : libusb20_dev_get_desc(pdev), - libusb20_dev_get_config_index(pdev), - dump_mode(libusb20_dev_get_mode(pdev)), - dump_speed(libusb20_dev_get_speed(pdev)), - dump_power_mode(libusb20_dev_get_power_mode(pdev)), - usage); + desc = _device_desc(pdev, (list_mode) ? _DEVICE_DESCR_LIST_TYPE_UGEN : + _DEVICE_DESCR_LIST_TYPE_DEFAULT); + + if (list_mode) + printf("%s: ", desc); + else + printf("%s, cfg=%u md=%s spd=%s pwr=%s (%umA)\n", + desc ? desc : libusb20_dev_get_desc(pdev), + libusb20_dev_get_config_index(pdev), + dump_mode(libusb20_dev_get_mode(pdev)), + dump_speed(libusb20_dev_get_speed(pdev)), + dump_power_mode(libusb20_dev_get_power_mode(pdev)), + usage); free(desc); - if (!show_ifdrv) + if (list_mode || !show_ifdrv) return; for (n = 0; n != 255; n++) { @@ -531,12 +629,21 @@ dump_be_dev_quirks(struct libusb20_backend *pbe) } void -dump_device_desc(struct libusb20_device *pdev) +dump_device_desc(struct libusb20_device *pdev, bool list_mode) { struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; ddesc = libusb20_dev_get_device_desc(pdev); - LIBUSB20_DEVICE_DESC(DUMP0, ddesc); + if (list_mode) { + char *desc; + + LIBUSB20_DEVICE_DESC(DUMP0L, ddesc); + desc = _device_desc(pdev, _DEVICE_DESCR_LIST_TYPE_PRODUCT_VENDOR); + printf("%s\n", (desc != NULL) ? desc : ""); + free(desc); + } else { + LIBUSB20_DEVICE_DESC(DUMP0, ddesc); + } } void diff --git a/usr.sbin/usbconfig/dump.h b/usr.sbin/usbconfig/dump.h index 71adb47262ea..6adc8e54e5a9 100644 --- a/usr.sbin/usbconfig/dump.h +++ b/usr.sbin/usbconfig/dump.h @@ -32,10 +32,11 @@ const char *dump_mode(uint8_t value); const char *dump_speed(uint8_t value); const char *dump_power_mode(uint8_t value); void dump_string_by_index(struct libusb20_device *pdev, uint8_t index); -void dump_device_info(struct libusb20_device *pdev, uint8_t show_drv); +void dump_device_info(struct libusb20_device *pdev, uint8_t show_drv, + bool list_mode); void dump_be_quirk_names(struct libusb20_backend *pbe); void dump_be_dev_quirks(struct libusb20_backend *pbe); -void dump_device_desc(struct libusb20_device *pdev); +void dump_device_desc(struct libusb20_device *pdev, bool list_mode); void dump_device_stats(struct libusb20_device *pdev); void dump_config(struct libusb20_device *pdev, uint8_t all_cfg); diff --git a/usr.sbin/usbconfig/usbconfig.8 b/usr.sbin/usbconfig/usbconfig.8 index 3926b03747e5..511fa9c5dddb 100644 --- a/usr.sbin/usbconfig/usbconfig.8 +++ b/usr.sbin/usbconfig/usbconfig.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 29, 2022 +.Dd February 12, 2025 .Dt USBCONFIG 8 .Os .Sh NAME @@ -30,6 +30,7 @@ .Nd configure the USB subsystem .Sh SYNOPSIS .Nm +.Op Fl l .Op Fl v .Op Fl a Ar addr .Op Fl i Ar interface_index @@ -40,6 +41,7 @@ .Sm off .Oo Oo Cm /dev/ Oc Cm ugen Oc Ar unit Cm \&. Ar addr .Sm on +.Op Fl l .Op Fl v .Op Fl i Ar interface_index .Op Ar cmds ... @@ -70,6 +72,8 @@ Show help and available commands. Specify interface index as indicated by the command description. If this argument is not specified a value of zero will be used for the interface index. +.It Fl l Cm dump_device_desc +Show numeral only key=value output as one long line. .It Fl u Ar unit Limit device range to USB devices connected to the given USBUS unit. .It Fl v diff --git a/usr.sbin/usbconfig/usbconfig.c b/usr.sbin/usbconfig/usbconfig.c index 7d257fea52cd..9337effd835d 100644 --- a/usr.sbin/usbconfig/usbconfig.c +++ b/usr.sbin/usbconfig/usbconfig.c @@ -25,6 +25,7 @@ * SUCH DAMAGE. */ +#include #include #include #include @@ -91,6 +92,7 @@ struct options { uint8_t got_dump_string:1; uint8_t got_do_request:1; uint8_t got_detach_kernel_driver:1; + uint8_t opt_dump_in_list_mode:1; }; struct token { @@ -504,11 +506,13 @@ flush_command(struct libusb20_backend *pbe, struct options *opt) if (opt->got_list || dump_any) { dump_device_info(pdev, - opt->got_show_iface_driver); + opt->got_show_iface_driver, + opt->opt_dump_in_list_mode && opt->got_dump_device_desc); } if (opt->got_dump_device_desc) { - printf("\n"); - dump_device_desc(pdev); + if (!opt->opt_dump_in_list_mode) + printf("\n"); + dump_device_desc(pdev, opt->opt_dump_in_list_mode); } if (opt->got_dump_all_config) { printf("\n"); @@ -518,14 +522,14 @@ flush_command(struct libusb20_backend *pbe, struct options *opt) dump_config(pdev, 0); } else if (opt->got_dump_all_desc) { printf("\n"); - dump_device_desc(pdev); + dump_device_desc(pdev, false); dump_config(pdev, 1); } if (opt->got_dump_stats) { printf("\n"); dump_device_stats(pdev); } - if (dump_any) { + if (dump_any && !opt->opt_dump_in_list_mode) { printf("\n"); } if (libusb20_dev_close(pdev)) { @@ -559,7 +563,7 @@ main(int argc, char **argv) if (pbe == NULL) err(1, "could not access USB backend\n"); - while ((ch = getopt(argc, argv, "a:d:hi:u:v")) != -1) { + while ((ch = getopt(argc, argv, "a:d:hi:lu:v")) != -1) { switch (ch) { case 'a': opt->addr = num_id(optarg, "addr"); @@ -596,6 +600,10 @@ main(int argc, char **argv) opt->iface = num_id(optarg, "iface"); break; + case 'l': + opt->opt_dump_in_list_mode = 1; + break; + case 'u': opt->bus = num_id(optarg, "busnum"); opt->got_bus = 1;