Date: Mon, 24 Feb 2025 00:59:57 GMT From: "Bjoern A. Zeeb" <bz@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: c66308d7bcc3 - main - usbconfig: add -l option to dump_device_desc for single line output Message-ID: <202502240059.51O0xvPY039757@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=c66308d7bcc3931b60a096bfe6ba0f50105e77de commit c66308d7bcc3931b60a096bfe6ba0f50105e77de Author: Bjoern A. Zeeb <bz@FreeBSD.org> AuthorDate: 2025-02-12 22:53:06 +0000 Commit: Bjoern A. Zeeb <bz@FreeBSD.org> CommitDate: 2025-02-24 00:59:06 +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 MFC after: 3 days Reviewed by: bapt (LGTM), ziaee (man) Differential Revision: https://reviews.freebsd.org/D48974 --- 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 <bapt@FreeBSD.org> + * 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 <sys/queue.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> +#include <unistd.h> #include <err.h> #include <string.h> #include <pwd.h> #include <grp.h> #include <ctype.h> +#include <fcntl.h> #include <libusb20.h> #include <libusb20_desc.h> +#include <dev/usb/usb_ioctl.h> + #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 e28f8de9f75c..7cab4a1354b1 100644 --- a/usr.sbin/usbconfig/usbconfig.c +++ b/usr.sbin/usbconfig/usbconfig.c @@ -25,6 +25,7 @@ * SUCH DAMAGE. */ +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> @@ -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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202502240059.51O0xvPY039757>