From 05610d1564c9ea75d7e10780e2c0f8973e5795ab Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 14 Sep 2023 22:31:26 +0200 Subject: [PATCH 01/28] common/common.c: extend xbasename(), xstrdup() and xrealloc() definition to return NULL if input was NULL (and log it) [#2052] Signed-off-by: Jim Klimov --- common/common.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/common/common.c b/common/common.c index 0864f28b23..3949dbd016 100644 --- a/common/common.c +++ b/common/common.c @@ -643,11 +643,21 @@ int sendsignal(const char *progname, const char * sig) const char *xbasename(const char *file) { + const char *p; +#ifdef WIN32 + const char *r; +#endif + + if (file == NULL) { + upsdebugx(1, "%s: got null input", __func__); + return NULL; + } + #ifndef WIN32 - const char *p = strrchr(file, '/'); + p = strrchr(file, '/'); #else - const char *p = strrchr(file, '\\'); - const char *r = strrchr(file, '/'); + p = strrchr(file, '\\'); + r = strrchr(file, '/'); /* if not found, try '/' */ if( r > p ) { p = r; @@ -1729,7 +1739,14 @@ void *xcalloc(size_t number, size_t size) void *xrealloc(void *ptr, size_t size) { - void *p = realloc(ptr, size); + void *p; + + if (ptr == NULL) { + upsdebugx(1, "%s: got null input", __func__); + return NULL; + } + + p = realloc(ptr, size); if (p == NULL) fatal_with_errno(EXIT_FAILURE, "%s", oom_msg); @@ -1738,7 +1755,14 @@ void *xrealloc(void *ptr, size_t size) char *xstrdup(const char *string) { - char *p = strdup(string); + char *p; + + if (string == NULL) { + upsdebugx(1, "%s: got null input", __func__); + return NULL; + } + + p = strdup(string); if (p == NULL) fatal_with_errno(EXIT_FAILURE, "%s", oom_msg); From fde7672eff2a2f9b50f5d3353e89e70712f3554f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 14 Sep 2023 22:39:15 +0200 Subject: [PATCH 02/28] clients/upsclient.c: fix strdup()=>xstrdup() to not segfault with bad inputs [#2052] Signed-off-by: Jim Klimov --- clients/upsclient.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/clients/upsclient.c b/clients/upsclient.c index 6a823fa57c..f6dea627a5 100644 --- a/clients/upsclient.c +++ b/clients/upsclient.c @@ -1161,7 +1161,7 @@ int upscli_tryconnect(UPSCONN_t *ups, const char *host, uint16_t port, int flags pconf_init(&ups->pc_ctx, NULL); - ups->host = strdup(host); + ups->host = xstrdup(host); if (!ups->host) { ups->upserror = UPSCLI_ERR_NOMEM; @@ -1618,15 +1618,15 @@ int upscli_splitname(const char *buf, char **upsname, char **hostname, uint16_t s = strchr(tmp, '@'); - if ((*upsname = strdup(strtok_r(tmp, "@", &last))) == NULL) { - fprintf(stderr, "upscli_splitname: strdup failed\n"); + if ((*upsname = xstrdup(strtok_r(tmp, "@", &last))) == NULL) { + fprintf(stderr, "upscli_splitname: xstrdup failed\n"); return -1; } /* only a upsname is specified, fill in defaults */ if (s == NULL) { - if ((*hostname = strdup("localhost")) == NULL) { - fprintf(stderr, "upscli_splitname: strdup failed\n"); + if ((*hostname = xstrdup("localhost")) == NULL) { + fprintf(stderr, "upscli_splitname: xstrdup failed\n"); return -1; } @@ -1659,8 +1659,8 @@ int upscli_splitaddr(const char *buf, char **hostname, uint16_t *port) return -1; } - if ((*hostname = strdup(strtok_r(tmp+1, "]", &last))) == NULL) { - fprintf(stderr, "upscli_splitaddr: strdup failed\n"); + if ((*hostname = xstrdup(strtok_r(tmp+1, "]", &last))) == NULL) { + fprintf(stderr, "upscli_splitaddr: xstrdup failed\n"); return -1; } @@ -1672,8 +1672,8 @@ int upscli_splitaddr(const char *buf, char **hostname, uint16_t *port) } else { s = strchr(tmp, ':'); - if ((*hostname = strdup(strtok_r(tmp, ":", &last))) == NULL) { - fprintf(stderr, "upscli_splitaddr: strdup failed\n"); + if ((*hostname = xstrdup(strtok_r(tmp, ":", &last))) == NULL) { + fprintf(stderr, "upscli_splitaddr: xstrdup failed\n"); return -1; } From 048876f33f3f405c54b30db6f6ab59c5b6b32872 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 14 Sep 2023 22:43:08 +0200 Subject: [PATCH 03/28] NEWS.adoc: update for issue #2052 fix Signed-off-by: Jim Klimov --- NEWS.adoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.adoc b/NEWS.adoc index 171eb2349b..dbef0108fa 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -114,6 +114,10 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. seems to have confused the MGE SHUT (Serial HID UPS Transfer) driver support [#2022] + - An issue was identified which could cause `libupsclient` parser of device + and host names to crash upon bad inputs (e.g. poorly resolved environment + variables in scripts). Now it should fail more gracefully [#2052] + - New `configure --enable-inplace-runtime` option should set default values for `--sysconfdir`, `--with-user` and `--with-group` options to match an existing NUT deployment -- for users who are trying if a custom build From d2857f693c8447034818672c171beb59c12e18d2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 14 Sep 2023 23:28:04 +0200 Subject: [PATCH 04/28] clients/upsclient.c: upscli_splitname(): add explicit checks for empty upsname and/or hostname[:port] parts, to report problems as such [#2052] Signed-off-by: Jim Klimov --- clients/upsclient.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/clients/upsclient.c b/clients/upsclient.c index f6dea627a5..cd30fedf67 100644 --- a/clients/upsclient.c +++ b/clients/upsclient.c @@ -1618,11 +1618,28 @@ int upscli_splitname(const char *buf, char **upsname, char **hostname, uint16_t s = strchr(tmp, '@'); + /* someone passed a "@hostname" string? */ + if (s == tmp) { + fprintf(stderr, "upscli_splitname: got empty upsname string\n"); + return -1; + } + if ((*upsname = xstrdup(strtok_r(tmp, "@", &last))) == NULL) { fprintf(stderr, "upscli_splitname: xstrdup failed\n"); return -1; } + /* someone passed a "@hostname" string (take two)? */ + if (!**upsname) { + fprintf(stderr, "upscli_splitname: got empty upsname string\n"); + return -1; + } + + /* + fprintf(stderr, "upscli_splitname3: got buf='%s', tmp='%s', upsname='%s', possible hostname:port='%s'\n", + NUT_STRARG(buf), NUT_STRARG(tmp), NUT_STRARG(*upsname), NUT_STRARG((s ? s+1 : s))); + */ + /* only a upsname is specified, fill in defaults */ if (s == NULL) { if ((*hostname = xstrdup("localhost")) == NULL) { @@ -1634,6 +1651,12 @@ int upscli_splitname(const char *buf, char **upsname, char **hostname, uint16_t return 0; } + /* someone passed a "upsname@" string? */ + if (!(*(s+1))) { + fprintf(stderr, "upscli_splitname: got the @ separator and then an empty hostname[:port] string\n"); + return -1; + } + return upscli_splitaddr(s+1, hostname, port); } From 05edad73910a9b0cd59c732b94c303bfe15ea688 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:18:38 +0200 Subject: [PATCH 05/28] Revert "common/common.c: extend xbasename(), xstrdup() and xrealloc() definition to return NULL if input was NULL (and log it) [#2052]" This reverts commit 05610d1564c9ea75d7e10780e2c0f8973e5795ab. Seems to cause segfaults on its own, maybe something relied on older behavior (non-NULLs returned in case of bad inputs?) To investigate separately later... --- common/common.c | 34 +++++----------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/common/common.c b/common/common.c index 3949dbd016..0864f28b23 100644 --- a/common/common.c +++ b/common/common.c @@ -643,21 +643,11 @@ int sendsignal(const char *progname, const char * sig) const char *xbasename(const char *file) { - const char *p; -#ifdef WIN32 - const char *r; -#endif - - if (file == NULL) { - upsdebugx(1, "%s: got null input", __func__); - return NULL; - } - #ifndef WIN32 - p = strrchr(file, '/'); + const char *p = strrchr(file, '/'); #else - p = strrchr(file, '\\'); - r = strrchr(file, '/'); + const char *p = strrchr(file, '\\'); + const char *r = strrchr(file, '/'); /* if not found, try '/' */ if( r > p ) { p = r; @@ -1739,14 +1729,7 @@ void *xcalloc(size_t number, size_t size) void *xrealloc(void *ptr, size_t size) { - void *p; - - if (ptr == NULL) { - upsdebugx(1, "%s: got null input", __func__); - return NULL; - } - - p = realloc(ptr, size); + void *p = realloc(ptr, size); if (p == NULL) fatal_with_errno(EXIT_FAILURE, "%s", oom_msg); @@ -1755,14 +1738,7 @@ void *xrealloc(void *ptr, size_t size) char *xstrdup(const char *string) { - char *p; - - if (string == NULL) { - upsdebugx(1, "%s: got null input", __func__); - return NULL; - } - - p = strdup(string); + char *p = strdup(string); if (p == NULL) fatal_with_errno(EXIT_FAILURE, "%s", oom_msg); From 7c59cf182e0a4eb35ddcc09488180959401838b0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:22:06 +0200 Subject: [PATCH 06/28] common/common.c: extend xstrdup() definition to return NULL if input was NULL (and log it) [#2052] Signed-off-by: Jim Klimov --- common/common.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/common/common.c b/common/common.c index 0864f28b23..f96584db60 100644 --- a/common/common.c +++ b/common/common.c @@ -1738,7 +1738,14 @@ void *xrealloc(void *ptr, size_t size) char *xstrdup(const char *string) { - char *p = strdup(string); + char *p; + + if (string == NULL) { + upsdebugx(1, "%s: got null input", __func__); + return NULL; + } + + p = strdup(string); if (p == NULL) fatal_with_errno(EXIT_FAILURE, "%s", oom_msg); From d5d5d4dc0dd3781c3983fa76935ae30853f9d15c Mon Sep 17 00:00:00 2001 From: fa Date: Fri, 15 Sep 2023 23:41:03 +0300 Subject: [PATCH 07/28] Update blazer_usb.c, libusb0.c, and 7 more files... --- drivers/blazer_usb.c | 8 +++++++- drivers/libusb0.c | 18 ++++++++++++++++++ drivers/libusb1.c | 28 ++++++++++++++++++++++++++++ drivers/nutdrv_qx.c | 11 ++++++++++- drivers/riello_usb.c | 8 +++++++- drivers/tripplite_usb.c | 8 +++++++- drivers/usb-common.c | 28 +++++++++++++++++++++++++--- drivers/usb-common.h | 8 ++++++++ drivers/usbhid-ups.c | 8 +++++++- 9 files changed, 117 insertions(+), 8 deletions(-) diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 6cb3337ad7..f7c391a810 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -597,7 +597,7 @@ void upsdrv_initups(void) #ifndef TESTING int ret, langid; char tbuf[255]; /* Some devices choke on size > 255 */ - char *regex_array[7]; + char *regex_array[REGEXP_ARRAY_LIMIT]; char *subdrv = getval("subdriver"); warn_if_bad_usb_port_filename(device_path); @@ -609,6 +609,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); +#ifdef WITH_USB_BUSPORT + regex_array[7] = getval("busport"); +#endif /* check for language ID workaround (#1) */ if (getval("langid_fix")) { @@ -724,6 +727,9 @@ void upsdrv_cleanup(void) free(usbdevice.Product); free(usbdevice.Serial); free(usbdevice.Bus); +#ifdef WITH_USB_BUSPORT + free(usbdevice.BusPort); +#endif free(usbdevice.Device); #endif /* TESTING */ } diff --git a/drivers/libusb0.c b/drivers/libusb0.c index b07a363c0c..62e23ca4f9 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -287,6 +287,9 @@ static int libusb_open(usb_dev_handle **udevp, free(curDevice->Serial); free(curDevice->Bus); free(curDevice->Device); +#ifdef WITH_USB_BUSPORT + free(curDevice->BusPort); +#endif memset(curDevice, '\0', sizeof(*curDevice)); /* Keep the list of items in sync with those matched by @@ -298,6 +301,18 @@ static int libusb_open(usb_dev_handle **udevp, curDevice->Device = xstrdup(dev->filename); curDevice->bcdDevice = dev->descriptor.bcdDevice; + upsdebugx(2, "dev->filename: %s", dev->filename); + upsdebugx(2, "bus->dirname: %s", bus->dirname); + +#ifdef WITH_USB_BUSPORT + curDevice->BusPort = (char *)malloc(4); + if (curDevice->BusPort == NULL) { + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } + // always zero + sprintf(curDevice->BusPort, "%03d", 0); +#endif + if (dev->descriptor.iManufacturer) { retries = MAX_RETRY; while (retries > 0) { @@ -347,6 +362,9 @@ static int libusb_open(usb_dev_handle **udevp, upsdebugx(2, "- Serial Number: %s", curDevice->Serial ? curDevice->Serial : "unknown"); upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown"); upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); +#ifdef WITH_USB_BUSPORT + upsdebugx(2, "- Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); +#endif upsdebugx(2, "- Device release number: %04x", curDevice->bcdDevice); /* FIXME: extend to Eaton OEMs (HP, IBM, ...) */ diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 522d8a183d..95511195ad 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -66,6 +66,9 @@ void nut_usb_addvars(void) addvar(VAR_VALUE, "bus", "Regular expression to match USB bus name"); addvar(VAR_VALUE, "device", "Regular expression to match USB device name"); +#ifdef WITH_USB_BUSPORT + addvar(VAR_VALUE, "busport", "Regular expression to match USB bus port name"); +#endif /* Warning: this feature is inherently non-deterministic! * If you only care to know that at least one of your no-name UPSes is online, @@ -163,6 +166,9 @@ static int nut_libusb_open(libusb_device_handle **udevp, const struct libusb_interface_descriptor *if_desc; libusb_device_handle *udev; uint8_t bus_num, device_addr; +#ifdef WITH_USB_BUSPORT + uint8_t bus_port; +#endif int ret, res; unsigned char buf[20]; const unsigned char *p; @@ -237,6 +243,9 @@ static int nut_libusb_open(libusb_device_handle **udevp, free(curDevice->Serial); free(curDevice->Bus); free(curDevice->Device); +#ifdef WITH_USB_BUSPORT + free(curDevice->BusPort); +#endif memset(curDevice, '\0', sizeof(*curDevice)); /* Keep the list of items in sync with those matched by @@ -278,6 +287,22 @@ static int nut_libusb_open(libusb_device_handle **udevp, } } +#ifdef WITH_USB_BUSPORT + + bus_port = libusb_get_port_number(device); + curDevice->BusPort = (char *)malloc(4); + if (curDevice->BusPort == NULL) { + libusb_free_device_list(devlist, 1); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } + if (bus_port > 0) { + sprintf(curDevice->BusPort, "%03d", bus_port); + } else { + upsdebugx(1, "%s: invalid libusb bus number %i", + __func__, bus_port); + } +#endif + curDevice->VendorID = dev_desc.idVendor; curDevice->ProductID = dev_desc.idProduct; curDevice->bcdDevice = dev_desc.bcdDevice; @@ -342,6 +367,9 @@ static int nut_libusb_open(libusb_device_handle **udevp, upsdebugx(2, "- Product: %s", curDevice->Product ? curDevice->Product : "unknown"); upsdebugx(2, "- Serial Number: %s", curDevice->Serial ? curDevice->Serial : "unknown"); upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown"); +#ifdef WITH_USB_BUSPORT + upsdebugx(2, "- Bus Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); +#endif upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); upsdebugx(2, "- Device release number: %04x", curDevice->bcdDevice); diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 83ab443a87..52d29db85f 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3016,6 +3016,9 @@ void upsdrv_initups(void) getval("serial") || getval("bus") || getval("langid_fix") +#ifdef WITH_USB_BUSPORT + || getval("busport") +#endif ) { /* USB */ is_usb = 1; @@ -3110,7 +3113,7 @@ void upsdrv_initups(void) #ifndef TESTING int ret, langid; char tbuf[255]; /* Some devices choke on size > 255 */ - char *regex_array[7]; + char *regex_array[REGEXP_ARRAY_LIMIT]; char *subdrv = getval("subdriver"); @@ -3121,6 +3124,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); +#ifdef WITH_USB_BUSPORT + regex_array[7] = getval("busport"); +#endif /* Check for language ID workaround (#1) */ if (getval("langid_fix")) { @@ -3284,6 +3290,9 @@ void upsdrv_cleanup(void) free(usbdevice.Product); free(usbdevice.Serial); free(usbdevice.Bus); +#ifdef WITH_USB_BUSPORT + free(usbdevice.BusPort); +#endif free(usbdevice.Device); #ifdef QX_SERIAL diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index b0c6a51b5a..93655887d4 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -851,7 +851,7 @@ void upsdrv_initups(void) }; int ret; - char *regex_array[7]; + char *regex_array[REGEXP_ARRAY_LIMIT]; char *subdrv = getval("subdriver"); @@ -864,6 +864,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); +#ifdef WITH_USB_BUSPORT + regex_array[7] = getval("busport"); +#endif /* pick up the subdriver name if set explicitly */ if (subdrv) { @@ -1232,5 +1235,8 @@ void upsdrv_cleanup(void) free(usbdevice.Product); free(usbdevice.Serial); free(usbdevice.Bus); +#ifdef WITH_USB_BUSPORT + free(usbdevice.BusPort); +#endif free(usbdevice.Device); } diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 84508f8f2e..ff32cb775b 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -1568,7 +1568,7 @@ void upsdrv_makevartable(void) */ void upsdrv_initups(void) { - char *regex_array[7]; + char *regex_array[REGEXP_ARRAY_LIMIT]; char *value; int r; @@ -1582,6 +1582,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); /* probably won't see this */ regex_array[5] = getval("bus"); regex_array[6] = getval("device"); +#ifdef WITH_USB_BUSPORT + regex_array[7] = getval("busport"); +#endif r = USBNewRegexMatcher(®ex_matcher, regex_array, REG_ICASE | REG_EXTENDED); if (r==-1) { @@ -1655,5 +1658,8 @@ void upsdrv_cleanup(void) free(curDevice.Product); free(curDevice.Serial); free(curDevice.Bus); +#ifdef WITH_USB_BUSPORT + free(curDevice.BusPort); +#endif free(curDevice.Device); } diff --git a/drivers/usb-common.c b/drivers/usb-common.c index a45a621168..9500c7dbac 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -119,6 +119,15 @@ static int match_function_exact(USBDevice_t *hd, void *privdata) return 0; } #endif +#ifdef WITH_USB_BUSPORT + #ifdef DEBUG_EXACT_MATCH_BUSPORT + if (strcmp_null(hd->BusPort, data->BusPort) != 0) { + upsdebugx(2, "%s: failed match of %s: %s != %s", + __func__, "BusPort", hd->BusPort, data->BusPort); + return 0; + } + #endif +#endif #ifdef DEBUG_EXACT_MATCH_DEVICE if (strcmp_null(hd->Device, data->Device) != 0) { upsdebugx(2, "%s: failed match of %s: %s != %s", @@ -300,7 +309,7 @@ static int match_regex_hex(regex_t *preg, int n) /* private data type: hold a set of compiled regular expressions. */ typedef struct regex_matcher_data_s { - regex_t *regex[7]; + regex_t *regex[8]; } regex_matcher_data_t; /* private callback function for regex matches */ @@ -390,6 +399,19 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) __func__, "Device", hd->Device); return r; } + +#ifdef WITH_USB_BUSPORT + r = match_regex(data->regex[7], hd->BusPort); + if (r != 1) { +/* + upsdebugx(2, "%s: failed match of %s: %s !~ %s", + __func__, "Device", hd->Device, data->regex[6]); +*/ + upsdebugx(2, "%s: failed match of %s: %s", + __func__, "Bus Port", hd->BusPort); + return r; + } +#endif return 1; } @@ -426,7 +448,7 @@ int USBNewRegexMatcher(USBDeviceMatcher_t **matcher, char **regex, int cflags) m->privdata = (void *)data; m->next = NULL; - for (i=0; i<7; i++) { + for (i=0; iregex[i], regex[i], cflags); if (r == -2) { r = i+1; @@ -453,7 +475,7 @@ void USBFreeRegexMatcher(USBDeviceMatcher_t *matcher) data = (regex_matcher_data_t *)matcher->privdata; - for (i = 0; i < 7; i++) { + for (i = 0; i < 8; i++) { if (!data->regex[i]) { continue; } diff --git a/drivers/usb-common.h b/drivers/usb-common.h index a3513adf0d..ae7647f33c 100644 --- a/drivers/usb-common.h +++ b/drivers/usb-common.h @@ -460,6 +460,11 @@ /* USB standard timeout [ms] */ #define USB_TIMEOUT 5000 +#ifdef WITH_USB_BUSPORT +#define REGEXP_ARRAY_LIMIT 8 +#else +#define REGEXP_ARRAY_LIMIT 7 +#endif /*! * USBDevice_t: Describe a USB device. This structure contains exactly @@ -482,6 +487,9 @@ typedef struct USBDevice_s { char *Bus; /*!< Bus name, e.g. "003" */ uint16_t bcdDevice; /*!< Device release number */ char *Device; /*!< Device name on the bus, e.g. "001" */ +#ifdef WITH_USB_BUSPORT + char *BusPort; /*!< Port name, e.g. "001" */ +#endif } USBDevice_t; /*! diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 2074970865..c5b16f30c4 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -1023,7 +1023,7 @@ void upsdrv_initups(void) subdriver_matcher = device_path; #else /* !SHUT_MODE => USB */ - char *regex_array[7]; + char *regex_array[REGEXP_ARRAY_LIMIT]; upsdebugx(1, "upsdrv_initups (non-SHUT)..."); @@ -1054,6 +1054,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); +#ifdef WITH_USB_BUSPORT + regex_array[7] = getval("busport"); +#endif ret = USBNewRegexMatcher(®ex_matcher, regex_array, REG_ICASE | REG_EXTENDED); switch(ret) @@ -1176,6 +1179,9 @@ void upsdrv_cleanup(void) free(curDevice.Product); free(curDevice.Serial); free(curDevice.Bus); +#ifdef WITH_USB_BUSPORT + free(curDevice.BusPort); +#endif free(curDevice.Device); #endif /* !SHUT_MODE => USB */ } From ab2032f8f31b601be24cf2cabf4fa17eda3e7b9b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:43:35 +0200 Subject: [PATCH 08/28] Rename REGEXP_ARRAY_LIMIT=>USBMATCHER_REGEXP_ARRAY_LIMIT [#2043] Signed-off-by: Jim Klimov --- drivers/blazer_usb.c | 2 +- drivers/nutdrv_qx.c | 2 +- drivers/riello_usb.c | 2 +- drivers/tripplite_usb.c | 2 +- drivers/usb-common.c | 2 +- drivers/usb-common.h | 4 ++-- drivers/usbhid-ups.c | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index f7c391a810..7dbaef9103 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -597,7 +597,7 @@ void upsdrv_initups(void) #ifndef TESTING int ret, langid; char tbuf[255]; /* Some devices choke on size > 255 */ - char *regex_array[REGEXP_ARRAY_LIMIT]; + char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; char *subdrv = getval("subdriver"); warn_if_bad_usb_port_filename(device_path); diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 52d29db85f..8925bc1d16 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3113,7 +3113,7 @@ void upsdrv_initups(void) #ifndef TESTING int ret, langid; char tbuf[255]; /* Some devices choke on size > 255 */ - char *regex_array[REGEXP_ARRAY_LIMIT]; + char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; char *subdrv = getval("subdriver"); diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index 93655887d4..d72fc91492 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -851,7 +851,7 @@ void upsdrv_initups(void) }; int ret; - char *regex_array[REGEXP_ARRAY_LIMIT]; + char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; char *subdrv = getval("subdriver"); diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index ff32cb775b..3185c8b996 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -1568,7 +1568,7 @@ void upsdrv_makevartable(void) */ void upsdrv_initups(void) { - char *regex_array[REGEXP_ARRAY_LIMIT]; + char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; char *value; int r; diff --git a/drivers/usb-common.c b/drivers/usb-common.c index 9500c7dbac..b110d03b16 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -448,7 +448,7 @@ int USBNewRegexMatcher(USBDeviceMatcher_t **matcher, char **regex, int cflags) m->privdata = (void *)data; m->next = NULL; - for (i=0; iregex[i], regex[i], cflags); if (r == -2) { r = i+1; diff --git a/drivers/usb-common.h b/drivers/usb-common.h index ae7647f33c..5f94697b7d 100644 --- a/drivers/usb-common.h +++ b/drivers/usb-common.h @@ -461,9 +461,9 @@ /* USB standard timeout [ms] */ #define USB_TIMEOUT 5000 #ifdef WITH_USB_BUSPORT -#define REGEXP_ARRAY_LIMIT 8 +# define USBMATCHER_REGEXP_ARRAY_LIMIT 8 #else -#define REGEXP_ARRAY_LIMIT 7 +# define USBMATCHER_REGEXP_ARRAY_LIMIT 7 #endif /*! diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index c5b16f30c4..21b6da3c38 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -1023,7 +1023,7 @@ void upsdrv_initups(void) subdriver_matcher = device_path; #else /* !SHUT_MODE => USB */ - char *regex_array[REGEXP_ARRAY_LIMIT]; + char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; upsdebugx(1, "upsdrv_initups (non-SHUT)..."); From 182445251e5a688a0216fcbbdf4727061fb585d0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:45:04 +0200 Subject: [PATCH 09/28] Revise "ifdef" indentations Signed-off-by: Jim Klimov --- drivers/blazer_usb.c | 10 +++++----- drivers/libusb1.c | 1 - drivers/nutdrv_qx.c | 33 ++++++++++++++++----------------- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 7dbaef9103..0563e69012 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -609,9 +609,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -#ifdef WITH_USB_BUSPORT +# ifdef WITH_USB_BUSPORT regex_array[7] = getval("busport"); -#endif +# endif /* check for language ID workaround (#1) */ if (getval("langid_fix")) { @@ -727,9 +727,9 @@ void upsdrv_cleanup(void) free(usbdevice.Product); free(usbdevice.Serial); free(usbdevice.Bus); -#ifdef WITH_USB_BUSPORT - free(usbdevice.BusPort); -#endif free(usbdevice.Device); +# ifdef WITH_USB_BUSPORT + free(usbdevice.BusPort); +# endif #endif /* TESTING */ } diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 95511195ad..ad494433ca 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -288,7 +288,6 @@ static int nut_libusb_open(libusb_device_handle **udevp, } #ifdef WITH_USB_BUSPORT - bus_port = libusb_get_port_number(device); curDevice->BusPort = (char *)malloc(4); if (curDevice->BusPort == NULL) { diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 8925bc1d16..7366bbe9c6 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3110,7 +3110,7 @@ void upsdrv_initups(void) warn_if_bad_usb_port_filename(device_path); - #ifndef TESTING +# ifndef TESTING int ret, langid; char tbuf[255]; /* Some devices choke on size > 255 */ char *regex_array[USBMATCHER_REGEXP_ARRAY_LIMIT]; @@ -3124,9 +3124,9 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -#ifdef WITH_USB_BUSPORT +# ifdef WITH_USB_BUSPORT regex_array[7] = getval("busport"); -#endif +# endif /* Check for language ID workaround (#1) */ if (getval("langid_fix")) { @@ -3242,11 +3242,11 @@ void upsdrv_initups(void) } } - #endif /* TESTING */ +# endif /* TESTING */ - #ifdef QX_SERIAL +# ifdef QX_SERIAL } /* is_usb */ - #endif /* QX_SERIAL */ +# endif /* QX_SERIAL */ #endif /* QX_USB */ @@ -3266,23 +3266,22 @@ void upsdrv_cleanup(void) #ifndef TESTING -#ifdef QX_SERIAL +# ifdef QX_SERIAL - #ifdef QX_USB +# ifdef QX_USB if (!is_usb) { - #endif /* QX_USB */ +# endif /* QX_USB */ ser_set_dtr(upsfd, 0); ser_close(upsfd, device_path); - #ifdef QX_USB +# ifdef QX_USB } else { /* is_usb */ - #endif /* QX_USB */ +# endif /* QX_USB */ -#endif /* QX_SERIAL */ - -#ifdef QX_USB +# endif /* QX_SERIAL */ +# ifdef QX_USB usb->close_dev(udev); USBFreeExactMatcher(reopen_matcher); USBFreeRegexMatcher(regex_matcher); @@ -3295,11 +3294,11 @@ void upsdrv_cleanup(void) #endif free(usbdevice.Device); - #ifdef QX_SERIAL +# ifdef QX_SERIAL } /* is_usb */ - #endif /* QX_SERIAL */ +# endif /* QX_SERIAL */ -#endif /* QX_USB */ +# endif /* QX_USB */ #endif /* TESTING */ From 5c3fe5bcd07e9a2547c61c89f80d39bd8a633521 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:45:36 +0200 Subject: [PATCH 10/28] drivers/libusb0.c: log a notice that BusPort==0 for libusb0 [#2043] Signed-off-by: Jim Klimov --- drivers/libusb0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 62e23ca4f9..72ead3b308 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -309,7 +309,7 @@ static int libusb_open(usb_dev_handle **udevp, if (curDevice->BusPort == NULL) { fatal_with_errno(EXIT_FAILURE, "Out of memory"); } - // always zero + upsdebugx(2, "%s: NOTE: BusPort is always zero with libusb0", __func__); sprintf(curDevice->BusPort, "%03d", 0); #endif From e37d2cf5d169b5a35fb8b355410a30487361ee31 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:46:38 +0200 Subject: [PATCH 11/28] drivers/libusb1.c: allow configuring "busport" always, just note it may be ignored in certain builds [#2043] Signed-off-by: Jim Klimov --- drivers/libusb1.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/libusb1.c b/drivers/libusb1.c index ad494433ca..e1c7096467 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -66,9 +66,11 @@ void nut_usb_addvars(void) addvar(VAR_VALUE, "bus", "Regular expression to match USB bus name"); addvar(VAR_VALUE, "device", "Regular expression to match USB device name"); -#ifdef WITH_USB_BUSPORT - addvar(VAR_VALUE, "busport", "Regular expression to match USB bus port name"); + addvar(VAR_VALUE, "busport", "Regular expression to match USB bus port name" +#ifndef WITH_USB_BUSPORT + " (tolerated but ignored in this build)" #endif + ); /* Warning: this feature is inherently non-deterministic! * If you only care to know that at least one of your no-name UPSes is online, From d8eeaece1f65147c70c7ddb3fde679e2f6b81c7e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 18:51:57 +0200 Subject: [PATCH 12/28] drivers/libusb{0,1}.c: allow configuring "busport" in ups.conf always, just note it may be ignored in certain builds [#2043] Signed-off-by: Jim Klimov --- drivers/libusb0.c | 5 +++++ drivers/libusb1.c | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 72ead3b308..afc76c8db6 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -76,6 +76,11 @@ void nut_usb_addvars(void) addvar(VAR_VALUE, "bus", "Regular expression to match USB bus name"); addvar(VAR_VALUE, "device", "Regular expression to match USB device name"); + /* Not supported by libusb0, but let's not crash config + * parsing on unknown keywords due to such nuances! :) */ + addvar(VAR_VALUE, "busport", "Regular expression to match USB bus port name" + " (tolerated but ignored in this build)" + ); /* Warning: this feature is inherently non-deterministic! * If you only care to know that at least one of your no-name UPSes is online, diff --git a/drivers/libusb1.c b/drivers/libusb1.c index e1c7096467..90a618eb5d 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -68,6 +68,10 @@ void nut_usb_addvars(void) addvar(VAR_VALUE, "device", "Regular expression to match USB device name"); addvar(VAR_VALUE, "busport", "Regular expression to match USB bus port name" #ifndef WITH_USB_BUSPORT + /* Not supported by this version of libusb1, + * but let's not crash config parsing on + * unknown keywords due to such nuances! :) + */ " (tolerated but ignored in this build)" #endif ); From e5b3e971ae3204a716886866543e3710bafa86b8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:04:34 +0200 Subject: [PATCH 13/28] USB drivers: warn if "busport" is configured but will be ignored by current build [#2043] Signed-off-by: Jim Klimov --- drivers/blazer_usb.c | 4 ++++ drivers/nutdrv_qx.c | 4 ++++ drivers/riello_usb.c | 4 ++++ drivers/usbhid-ups.c | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 0563e69012..187b35d738 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -611,6 +611,10 @@ void upsdrv_initups(void) regex_array[6] = getval("device"); # ifdef WITH_USB_BUSPORT regex_array[7] = getval("busport"); +# else + if (getval("busport")) { + upslogx(LOG_WARNING, "\"busport\" is configured for the device, but is not actually handled by current build combination of NUT and libusb (ignored)"); + } # endif /* check for language ID workaround (#1) */ diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 7366bbe9c6..5c01ac868d 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3126,6 +3126,10 @@ void upsdrv_initups(void) regex_array[6] = getval("device"); # ifdef WITH_USB_BUSPORT regex_array[7] = getval("busport"); +# else + if (getval("busport")) { + upslogx(LOG_WARNING, "\"busport\" is configured for the device, but is not actually handled by current build combination of NUT and libusb (ignored)"); + } # endif /* Check for language ID workaround (#1) */ diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index d72fc91492..32062a089b 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -866,6 +866,10 @@ void upsdrv_initups(void) regex_array[6] = getval("device"); #ifdef WITH_USB_BUSPORT regex_array[7] = getval("busport"); +#else + if (getval("busport")) { + upslogx(LOG_WARNING, "\"busport\" is configured for the device, but is not actually handled by current build combination of NUT and libusb (ignored)"); + } #endif /* pick up the subdriver name if set explicitly */ diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 21b6da3c38..48da548534 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -1056,6 +1056,10 @@ void upsdrv_initups(void) regex_array[6] = getval("device"); #ifdef WITH_USB_BUSPORT regex_array[7] = getval("busport"); +#else + if (getval("busport")) { + upslogx(LOG_WARNING, "\"busport\" is configured for the device, but is not actually handled by current build combination of NUT and libusb (ignored)"); + } #endif ret = USBNewRegexMatcher(®ex_matcher, regex_array, REG_ICASE | REG_EXTENDED); From 92f3e151679dc4fda76c6a0e3764b867da8b3b30 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:06:27 +0200 Subject: [PATCH 14/28] USB drivers: bump versions due to new "busport" config option support; free the variables in order of definition (ease maintenance) [#2043] Signed-off-by: Jim Klimov --- drivers/blazer_usb.c | 2 +- drivers/libusb0.c | 2 +- drivers/libusb1.c | 2 +- drivers/nutdrv_qx.c | 8 ++++---- drivers/riello_usb.c | 4 ++-- drivers/tripplite_usb.c | 2 +- drivers/usbhid-ups.c | 8 ++++---- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 187b35d738..53f202a1b7 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -37,7 +37,7 @@ #endif #define DRIVER_NAME "Megatec/Q1 protocol USB driver" -#define DRIVER_VERSION "0.16" +#define DRIVER_VERSION "0.17" /* driver description structure */ upsdrv_info_t upsdrv_info = { diff --git a/drivers/libusb0.c b/drivers/libusb0.c index afc76c8db6..bc575a6fed 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -37,7 +37,7 @@ #endif #define USB_DRIVER_NAME "USB communication driver (libusb 0.1)" -#define USB_DRIVER_VERSION "0.44" +#define USB_DRIVER_VERSION "0.45" /* driver description structure */ upsdrv_info_t comm_upsdrv_info = { diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 90a618eb5d..3e68571d1c 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -33,7 +33,7 @@ #include "nut_stdint.h" #define USB_DRIVER_NAME "USB communication driver (libusb 1.0)" -#define USB_DRIVER_VERSION "0.45" +#define USB_DRIVER_VERSION "0.46" /* driver description structure */ upsdrv_info_t comm_upsdrv_info = { diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 5c01ac868d..f136d9d948 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -57,7 +57,7 @@ #define DRIVER_NAME "Generic Q* Serial driver" #endif /* QX_USB */ -#define DRIVER_VERSION "0.35" +#define DRIVER_VERSION "0.36" #ifdef QX_SERIAL #include "serial.h" @@ -3293,10 +3293,10 @@ void upsdrv_cleanup(void) free(usbdevice.Product); free(usbdevice.Serial); free(usbdevice.Bus); -#ifdef WITH_USB_BUSPORT - free(usbdevice.BusPort); -#endif free(usbdevice.Device); +# ifdef WITH_USB_BUSPORT + free(usbdevice.BusPort); +# endif # ifdef QX_SERIAL } /* is_usb */ diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index 32062a089b..e85c208e8a 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -34,7 +34,7 @@ #include "riello.h" #define DRIVER_NAME "Riello USB driver" -#define DRIVER_VERSION "0.09" +#define DRIVER_VERSION "0.10" #define DEFAULT_OFFDELAY 5 /*!< seconds (max 0xFF) */ #define DEFAULT_BOOTDELAY 5 /*!< seconds (max 0xFF) */ @@ -1239,8 +1239,8 @@ void upsdrv_cleanup(void) free(usbdevice.Product); free(usbdevice.Serial); free(usbdevice.Bus); + free(usbdevice.Device); #ifdef WITH_USB_BUSPORT free(usbdevice.BusPort); #endif - free(usbdevice.Device); } diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 3185c8b996..0f767e6fac 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -1658,8 +1658,8 @@ void upsdrv_cleanup(void) free(curDevice.Product); free(curDevice.Serial); free(curDevice.Bus); + free(curDevice.Device); #ifdef WITH_USB_BUSPORT free(curDevice.BusPort); #endif - free(curDevice.Device); } diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 48da548534..d83f989e3c 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -28,7 +28,7 @@ */ #define DRIVER_NAME "Generic HID driver" -#define DRIVER_VERSION "0.50" +#define DRIVER_VERSION "0.51" #define HU_VAR_WAITBEFORERECONNECT "waitbeforereconnect" @@ -1183,10 +1183,10 @@ void upsdrv_cleanup(void) free(curDevice.Product); free(curDevice.Serial); free(curDevice.Bus); -#ifdef WITH_USB_BUSPORT - free(curDevice.BusPort); -#endif free(curDevice.Device); +# ifdef WITH_USB_BUSPORT + free(curDevice.BusPort); +# endif #endif /* !SHUT_MODE => USB */ } From a388e125a828d7d02c93f85c706f1c4df9f22556 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:08:14 +0200 Subject: [PATCH 15/28] drivers/usb-common.c: constrain regex_matcher_data_t array size to USBMATCHER_REGEXP_ARRAY_LIMIT too (not a hardcoded number like before) [#2043] Signed-off-by: Jim Klimov --- drivers/usb-common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb-common.c b/drivers/usb-common.c index b110d03b16..7e5a307945 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -309,7 +309,7 @@ static int match_regex_hex(regex_t *preg, int n) /* private data type: hold a set of compiled regular expressions. */ typedef struct regex_matcher_data_s { - regex_t *regex[8]; + regex_t *regex[USBMATCHER_REGEXP_ARRAY_LIMIT]; } regex_matcher_data_t; /* private callback function for regex matches */ @@ -475,7 +475,7 @@ void USBFreeRegexMatcher(USBDeviceMatcher_t *matcher) data = (regex_matcher_data_t *)matcher->privdata; - for (i = 0; i < 8; i++) { + for (i = 0; i < USBMATCHER_REGEXP_ARRAY_LIMIT; i++) { if (!data->regex[i]) { continue; } From f79a362da86944d9bfab053e1c14a0cca312bacf Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:19:15 +0200 Subject: [PATCH 16/28] drivers/libshut.c: update with formal support of "busport" (no-op for serial mode) [#2043] Signed-off-by: Jim Klimov --- drivers/libshut.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/libshut.c b/drivers/libshut.c index 79acd0ade8..ffc1614bc8 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -468,12 +468,24 @@ static int libshut_open( free(curDevice->Serial); free(curDevice->Bus); free(curDevice->Device); +#ifdef WITH_USB_BUSPORT + free(curDevice->BusPort); +#endif memset(curDevice, '\0', sizeof(*curDevice)); curDevice->VendorID = dev_descriptor->idVendor; curDevice->ProductID = dev_descriptor->idProduct; curDevice->Bus = strdup("serial"); curDevice->Device = strdup(arg_device_path); +#ifdef WITH_USB_BUSPORT + curDevice->BusPort = (char *)malloc(4); + if (curDevice->BusPort == NULL) { + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } + upsdebugx(2, "%s: NOTE: BusPort is always zero with libshut", __func__); + sprintf(curDevice->BusPort, "%03d", 0); +#endif + curDevice->bcdDevice = dev_descriptor->bcdDevice; curDevice->Vendor = strdup("Eaton"); if (dev_descriptor->iManufacturer) { @@ -514,6 +526,9 @@ static int libshut_open( upsdebugx(2, "- Product: %s", curDevice->Product); upsdebugx(2, "- Serial Number: %s", curDevice->Serial); upsdebugx(2, "- Bus: %s", curDevice->Bus); +#ifdef WITH_USB_BUSPORT + upsdebugx(2, "- Bus Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); +#endif upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); upsdebugx(2, "- Device release number: %04x", curDevice->bcdDevice); upsdebugx(2, "Device matches"); From 705e6c72f74e635c85580799a23aac957a673309 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:19:31 +0200 Subject: [PATCH 17/28] drivers/libshut.c: avoid potential small memory leak Signed-off-by: Jim Klimov --- drivers/libshut.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/libshut.c b/drivers/libshut.c index ffc1614bc8..ae48dc67ba 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -43,7 +43,7 @@ #include "common.h" /* for xmalloc, upsdebugx prototypes */ #define SHUT_DRIVER_NAME "SHUT communication driver" -#define SHUT_DRIVER_VERSION "0.87" +#define SHUT_DRIVER_VERSION "0.88" /* communication driver description structure */ upsdrv_info_t comm_upsdrv_info = { @@ -487,7 +487,7 @@ static int libshut_open( #endif curDevice->bcdDevice = dev_descriptor->bcdDevice; - curDevice->Vendor = strdup("Eaton"); + curDevice->Vendor = NULL; if (dev_descriptor->iManufacturer) { ret = shut_get_string_simple(*arg_upsfd, dev_descriptor->iManufacturer, string, MAX_STRING_SIZE); @@ -495,6 +495,9 @@ static int libshut_open( curDevice->Vendor = strdup(string); } } + if (curDevice->Vendor == NULL) { + curDevice->Vendor = strdup("Eaton"); + } /* ensure iProduct retrieval */ if (dev_descriptor->iProduct) { From 72f918cd51ca22b2bd6b9345d14ad81073d6be94 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:21:06 +0200 Subject: [PATCH 18/28] drivers/libusb0.c: use logging for bus port consistent with other USB-related libs [#2043] Signed-off-by: Jim Klimov --- drivers/libusb0.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/libusb0.c b/drivers/libusb0.c index bc575a6fed..8318301fe1 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -306,9 +306,6 @@ static int libusb_open(usb_dev_handle **udevp, curDevice->Device = xstrdup(dev->filename); curDevice->bcdDevice = dev->descriptor.bcdDevice; - upsdebugx(2, "dev->filename: %s", dev->filename); - upsdebugx(2, "bus->dirname: %s", bus->dirname); - #ifdef WITH_USB_BUSPORT curDevice->BusPort = (char *)malloc(4); if (curDevice->BusPort == NULL) { @@ -368,7 +365,7 @@ static int libusb_open(usb_dev_handle **udevp, upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown"); upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); #ifdef WITH_USB_BUSPORT - upsdebugx(2, "- Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); + upsdebugx(2, "- Bus Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); #endif upsdebugx(2, "- Device release number: %04x", curDevice->bcdDevice); From dbc15b3340c287016ef762bd539b4191b92f8ea2 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:25:25 +0200 Subject: [PATCH 19/28] NEWS.adoc: document the addition of "busport" config option [#2043] Signed-off-by: Jim Klimov --- NEWS.adoc | 5 +++++ docs/nut.dict | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/NEWS.adoc b/NEWS.adoc index 171eb2349b..7e0265c776 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -233,6 +233,11 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution. of all USB drivers using these options to include the same description [#1766] + - Added a "busport" USB matching option (if supported by the hardware, OS and + libusb on the particular deployment, it should allow to specify physical + port numbers on an USB hub, rather than logical "device" enumeration values, + and in turn -- this should be less volatile across reboots etc.) [#2043] + - Added an `allow_duplicates` flag for common USB matching options which may help monitor several related no-name devices (although without knowing reliably which one is which... better than nothing) [#1756] diff --git a/docs/nut.dict b/docs/nut.dict index 34573c555a..d25aae15a6 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3222 utf-8 +personal_ws-1.1 en 3223 utf-8 AAS ABI ACFAIL @@ -1639,6 +1639,7 @@ bugfixes buildbots builddir bullseye +busport busybox bv bypassvolts From 73e8923ca77a2d5642540975b2f035aeb72bf138 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:34:25 +0200 Subject: [PATCH 20/28] docs/man/nut_usb_addvars.txt: fix typo about Linux path to usb device info Signed-off-by: Jim Klimov --- docs/man/nut_usb_addvars.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index c9a9c5d1d9..7908aedd47 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -56,15 +56,15 @@ Examples: Select a UPS on a specific USB bus or group of buses. The argument is a regular expression that must match the bus name where the UPS is -connected (e.g. `bus="002"` or `bus="00[2-3]"`) as seen in -`/proc/bus/usb/devices` or *lsusb(8)*; including leading zeroes. +connected (e.g. `bus="002"` or `bus="00[2-3]"`) as seen on Linux in +`/sys/bus/usb/devices` or *lsusb(8)*; including leading zeroes. *device =* 'regex':: Select a UPS on a specific USB device or group of devices. The argument is a regular expression that must match the device name where the UPS is -connected (e.g. `device="001"` or `device="00[1-2]"`) as seen in -`/proc/bus/usb/devices` or *lsusb(8)*; including leading zeroes. +connected (e.g. `device="001"` or `device="00[1-2]"`) as seen on Linux +in `/sys/bus/usb/devices` or *lsusb(8)*; including leading zeroes. Note that device numbers are not guaranteed by the OS to be stable across re-boots or device re-plugging. From 1eef3173812b54ddd05c689db42c75a8fa9e4f9e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:34:43 +0200 Subject: [PATCH 21/28] docs/man/nut_usb_addvars.txt: add "busport" info [#2043] Signed-off-by: Jim Klimov --- docs/man/nut_usb_addvars.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index 7908aedd47..74a8886ae3 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -68,6 +68,17 @@ in `/sys/bus/usb/devices` or *lsusb(8)*; including leading zeroes. Note that device numbers are not guaranteed by the OS to be stable across re-boots or device re-plugging. +*busport =* 'regex':: + +If supported by the hardware, OS and libusb on the particular deployment, +this option should allow to specify physical port numbers on an USB hub, +rather than logical `device` enumeration values, and in turn -- this should +be less volatile across reboots or re-plugging. ++ +NOTE: this option is not practically supported by some NUT builds +(it should be ignored with a warning then), and not by all systems +that NUT can run on. + *allow_duplicates*:: If you have several UPS devices which may not be uniquely identified by From 844f91a37c2a878ce2ce6f530846cbb080cf43f3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:36:50 +0200 Subject: [PATCH 22/28] docs/man/nut_usb_addvars.txt: fix markup for a NOTE about "device" value Signed-off-by: Jim Klimov --- docs/man/nut_usb_addvars.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index 74a8886ae3..b96b252d8d 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -65,7 +65,8 @@ Select a UPS on a specific USB device or group of devices. The argument is a regular expression that must match the device name where the UPS is connected (e.g. `device="001"` or `device="00[1-2]"`) as seen on Linux in `/sys/bus/usb/devices` or *lsusb(8)*; including leading zeroes. -Note that device numbers are not guaranteed by the OS to be stable across ++ +NOTE: device numbers are not guaranteed by the OS to be stable across re-boots or device re-plugging. *busport =* 'regex':: From 5db58c9ec45e49f2921a6aba096416bf68de6d49 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:47:21 +0200 Subject: [PATCH 23/28] m4/nut_check_libusb.m4: detect if we can support "busport" USB matching value [#2043] Signed-off-by: Jim Klimov --- m4/nut_check_libusb.m4 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/m4/nut_check_libusb.m4 b/m4/nut_check_libusb.m4 index 98b0ad0c59..5b042b0790 100644 --- a/m4/nut_check_libusb.m4 +++ b/m4/nut_check_libusb.m4 @@ -286,6 +286,7 @@ if test -z "${nut_have_libusb_seen}"; then nut_have_libusb=no fi + nut_with_usb_busport=no AS_IF([test "${nut_have_libusb}" = "yes"], [ dnl ---------------------------------------------------------------------- dnl additional USB-related checks @@ -318,12 +319,27 @@ if test -z "${nut_have_libusb_seen}"; then ] ) + dnl AC_MSG_CHECKING([for libusb bus port support]) + dnl Per https://github.com/networkupstools/nut/issues/2043#issuecomment-1721856494 : + dnl #if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102) + dnl DEFINE WITH_USB_BUSPORT + dnl #endif + AC_CHECK_FUNCS(libusb_get_port_number, [nut_with_usb_busport=yes]) + dnl # With USB we can match desired devices by regex; dnl # and currently have no other use for the library: AC_SEARCH_LIBS(regcomp, regex) ]) AC_LANG_POP([C]) + AS_IF([test x"${nut_with_usb_busport}" = xyes], [ + AC_DEFINE(WITH_USB_BUSPORT, 1, + [Define to 1 for libusb versions where we can support "busport" USB matching value.]) + ], [ + AC_DEFINE(WITH_USB_BUSPORT, 0, + [Define to 1 for libusb versions where we can support "busport" USB matching value.]) + ]) + AS_IF([test "${nut_have_libusb}" = "yes"], [ LIBUSB_CFLAGS="${CFLAGS}" LIBUSB_LIBS="${LIBS}" From cee9d327b3255cca52e01b7bf1af214ef41a0781 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 19:57:10 +0200 Subject: [PATCH 24/28] USB driver: adjust to WITH_USB_BUSPORT normally being always defined, just not always active [#2043] Signed-off-by: Jim Klimov --- drivers/blazer_usb.c | 4 ++-- drivers/libshut.c | 6 +++--- drivers/libusb0.c | 6 +++--- drivers/libusb1.c | 10 +++++----- drivers/nutdrv_qx.c | 6 +++--- drivers/riello_usb.c | 4 ++-- drivers/tripplite_usb.c | 4 ++-- drivers/usb-common.c | 4 ++-- drivers/usb-common.h | 4 ++-- drivers/usbhid-ups.c | 4 ++-- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 53f202a1b7..2bc9c28258 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -609,7 +609,7 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -# ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) regex_array[7] = getval("busport"); # else if (getval("busport")) { @@ -732,7 +732,7 @@ void upsdrv_cleanup(void) free(usbdevice.Serial); free(usbdevice.Bus); free(usbdevice.Device); -# ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(usbdevice.BusPort); # endif #endif /* TESTING */ diff --git a/drivers/libshut.c b/drivers/libshut.c index ae48dc67ba..3601c0c344 100644 --- a/drivers/libshut.c +++ b/drivers/libshut.c @@ -468,7 +468,7 @@ static int libshut_open( free(curDevice->Serial); free(curDevice->Bus); free(curDevice->Device); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(curDevice->BusPort); #endif memset(curDevice, '\0', sizeof(*curDevice)); @@ -477,7 +477,7 @@ static int libshut_open( curDevice->ProductID = dev_descriptor->idProduct; curDevice->Bus = strdup("serial"); curDevice->Device = strdup(arg_device_path); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) curDevice->BusPort = (char *)malloc(4); if (curDevice->BusPort == NULL) { fatal_with_errno(EXIT_FAILURE, "Out of memory"); @@ -529,7 +529,7 @@ static int libshut_open( upsdebugx(2, "- Product: %s", curDevice->Product); upsdebugx(2, "- Serial Number: %s", curDevice->Serial); upsdebugx(2, "- Bus: %s", curDevice->Bus); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) upsdebugx(2, "- Bus Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); #endif upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); diff --git a/drivers/libusb0.c b/drivers/libusb0.c index 8318301fe1..86072bbba7 100644 --- a/drivers/libusb0.c +++ b/drivers/libusb0.c @@ -292,7 +292,7 @@ static int libusb_open(usb_dev_handle **udevp, free(curDevice->Serial); free(curDevice->Bus); free(curDevice->Device); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(curDevice->BusPort); #endif memset(curDevice, '\0', sizeof(*curDevice)); @@ -306,7 +306,7 @@ static int libusb_open(usb_dev_handle **udevp, curDevice->Device = xstrdup(dev->filename); curDevice->bcdDevice = dev->descriptor.bcdDevice; -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) curDevice->BusPort = (char *)malloc(4); if (curDevice->BusPort == NULL) { fatal_with_errno(EXIT_FAILURE, "Out of memory"); @@ -364,7 +364,7 @@ static int libusb_open(usb_dev_handle **udevp, upsdebugx(2, "- Serial Number: %s", curDevice->Serial ? curDevice->Serial : "unknown"); upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown"); upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) upsdebugx(2, "- Bus Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); #endif upsdebugx(2, "- Device release number: %04x", curDevice->bcdDevice); diff --git a/drivers/libusb1.c b/drivers/libusb1.c index 3e68571d1c..84d5ebdbc3 100644 --- a/drivers/libusb1.c +++ b/drivers/libusb1.c @@ -67,7 +67,7 @@ void nut_usb_addvars(void) addvar(VAR_VALUE, "bus", "Regular expression to match USB bus name"); addvar(VAR_VALUE, "device", "Regular expression to match USB device name"); addvar(VAR_VALUE, "busport", "Regular expression to match USB bus port name" -#ifndef WITH_USB_BUSPORT +#if (!defined WITH_USB_BUSPORT) || (!WITH_USB_BUSPORT) /* Not supported by this version of libusb1, * but let's not crash config parsing on * unknown keywords due to such nuances! :) @@ -172,7 +172,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, const struct libusb_interface_descriptor *if_desc; libusb_device_handle *udev; uint8_t bus_num, device_addr; -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) uint8_t bus_port; #endif int ret, res; @@ -249,7 +249,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, free(curDevice->Serial); free(curDevice->Bus); free(curDevice->Device); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(curDevice->BusPort); #endif memset(curDevice, '\0', sizeof(*curDevice)); @@ -293,7 +293,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, } } -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) bus_port = libusb_get_port_number(device); curDevice->BusPort = (char *)malloc(4); if (curDevice->BusPort == NULL) { @@ -372,7 +372,7 @@ static int nut_libusb_open(libusb_device_handle **udevp, upsdebugx(2, "- Product: %s", curDevice->Product ? curDevice->Product : "unknown"); upsdebugx(2, "- Serial Number: %s", curDevice->Serial ? curDevice->Serial : "unknown"); upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown"); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) upsdebugx(2, "- Bus Port: %s", curDevice->BusPort ? curDevice->BusPort : "unknown"); #endif upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown"); diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index f136d9d948..f394ce5213 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -3016,7 +3016,7 @@ void upsdrv_initups(void) getval("serial") || getval("bus") || getval("langid_fix") -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) || getval("busport") #endif ) { @@ -3124,7 +3124,7 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -# ifdef WITH_USB_BUSPORT +# if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) regex_array[7] = getval("busport"); # else if (getval("busport")) { @@ -3294,7 +3294,7 @@ void upsdrv_cleanup(void) free(usbdevice.Serial); free(usbdevice.Bus); free(usbdevice.Device); -# ifdef WITH_USB_BUSPORT +# if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(usbdevice.BusPort); # endif diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index e85c208e8a..1a7fe7d4f3 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -864,7 +864,7 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) regex_array[7] = getval("busport"); #else if (getval("busport")) { @@ -1240,7 +1240,7 @@ void upsdrv_cleanup(void) free(usbdevice.Serial); free(usbdevice.Bus); free(usbdevice.Device); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(usbdevice.BusPort); #endif } diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 0f767e6fac..858b93dcd0 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -1582,7 +1582,7 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); /* probably won't see this */ regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) regex_array[7] = getval("busport"); #endif @@ -1659,7 +1659,7 @@ void upsdrv_cleanup(void) free(curDevice.Serial); free(curDevice.Bus); free(curDevice.Device); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(curDevice.BusPort); #endif } diff --git a/drivers/usb-common.c b/drivers/usb-common.c index 7e5a307945..d3bc96748b 100644 --- a/drivers/usb-common.c +++ b/drivers/usb-common.c @@ -119,7 +119,7 @@ static int match_function_exact(USBDevice_t *hd, void *privdata) return 0; } #endif -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) #ifdef DEBUG_EXACT_MATCH_BUSPORT if (strcmp_null(hd->BusPort, data->BusPort) != 0) { upsdebugx(2, "%s: failed match of %s: %s != %s", @@ -400,7 +400,7 @@ static int match_function_regex(USBDevice_t *hd, void *privdata) return r; } -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) r = match_regex(data->regex[7], hd->BusPort); if (r != 1) { /* diff --git a/drivers/usb-common.h b/drivers/usb-common.h index 5f94697b7d..d1de6d23d5 100644 --- a/drivers/usb-common.h +++ b/drivers/usb-common.h @@ -460,7 +460,7 @@ /* USB standard timeout [ms] */ #define USB_TIMEOUT 5000 -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) # define USBMATCHER_REGEXP_ARRAY_LIMIT 8 #else # define USBMATCHER_REGEXP_ARRAY_LIMIT 7 @@ -487,7 +487,7 @@ typedef struct USBDevice_s { char *Bus; /*!< Bus name, e.g. "003" */ uint16_t bcdDevice; /*!< Device release number */ char *Device; /*!< Device name on the bus, e.g. "001" */ -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) char *BusPort; /*!< Port name, e.g. "001" */ #endif } USBDevice_t; diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index d83f989e3c..7a7ab370e0 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -1054,7 +1054,7 @@ void upsdrv_initups(void) regex_array[4] = getval("serial"); regex_array[5] = getval("bus"); regex_array[6] = getval("device"); -#ifdef WITH_USB_BUSPORT +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) regex_array[7] = getval("busport"); #else if (getval("busport")) { @@ -1184,7 +1184,7 @@ void upsdrv_cleanup(void) free(curDevice.Serial); free(curDevice.Bus); free(curDevice.Device); -# ifdef WITH_USB_BUSPORT +# if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) free(curDevice.BusPort); # endif #endif /* !SHUT_MODE => USB */ From d450a563f888dcb05b6cb0bacef8ca5d0d1b932b Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 20:20:32 +0200 Subject: [PATCH 25/28] tools/nut-scanner/scan_usb.c: add support for "busport" discovery where possible [#2043] Signed-off-by: Jim Klimov --- tools/nut-scanner/scan_usb.c | 78 ++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index 2a8c116bfe..a56c54cf8a 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -54,6 +54,7 @@ static int (*nut_usb_get_string_simple)(libusb_device_handle *dev, int index, static void (*nut_usb_free_device_list)(libusb_device **list, int unref_devices); static uint8_t (*nut_usb_get_bus_number)(libusb_device *dev); static uint8_t (*nut_usb_get_device_address)(libusb_device *dev); + static uint8_t (*nut_usb_get_port_number)(libusb_device *dev); static int (*nut_usb_get_device_descriptor)(libusb_device *dev, struct libusb_device_descriptor *desc); #else /* => WITH_LIBUSB_0_1 */ @@ -157,6 +158,20 @@ int nutscan_load_usb_library(const char *libname_path) goto err; } + /* This method may be absent in some libusb versions, and we should + * tolerate that! In run-time driver code see also blocks fenced by: + * #if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) + */ + *(void **) (&nut_usb_get_port_number) = lt_dlsym(dl_handle, + "libusb_get_port_number"); + if ((dl_error = lt_dlerror()) != NULL) { + fprintf(stderr, + "While loading USB library (%s), failed to find libusb_get_port_number() : %s. " + "The \"busport\" USB matching option will be disabled.\n", + libname_path, dl_error); + nut_usb_get_port_number = NULL; + } + *(void **) (&nut_usb_get_device_descriptor) = lt_dlsym(dl_handle, "libusb_get_device_descriptor"); if ((dl_error = lt_dlerror()) != NULL) { @@ -251,7 +266,8 @@ nutscan_device_t * nutscan_scan_usb() /* device_port physical meaning: connection port on that bus; * different consumers plugged into same socket should have * the same port value. However in practice such functionality - * depends on platform and HW involved. + * depends on platform and HW involved and may mean logical + * enumeration results. * In libusb1 API: first libusb_get_port_numbers() earlier known * as libusb_get_port_path() for physical port number on the bus, see * https://libusb.sourceforge.io/api-1.0/group__libusb__dev.html#ga14879a0ea7daccdcddb68852d86c00c4 @@ -267,6 +283,12 @@ nutscan_device_t * nutscan_scan_usb() libusb_device *dev; libusb_device **devlist; uint8_t bus_num; + /* Sort of like device_port above, but different (should be + * more closely about physical port number than logical device + * enumeration results). Uses libusb_get_port_number() where + * available in libusb (and hoping the OS and HW honour it). + */ + char *bus_port = NULL; #else /* => WITH_LIBUSB_0_1 */ struct usb_device *dev; struct usb_bus *bus; @@ -339,6 +361,22 @@ nutscan_device_t * nutscan_scan_usb() } } + if (nut_usb_get_port_number != NULL) { + bus_port = (char *)malloc(4); + if (bus_port == NULL) { + (*nut_usb_free_device_list)(devlist, 1); + (*nut_usb_exit)(NULL); + fatal_with_errno(EXIT_FAILURE, "Out of memory"); + } else { + uint8_t port_num = (*nut_usb_get_port_number)(dev); + if (port_num > 0) { + snprintf(bus_port, 4, "%03d", port_num); + } else { + snprintf(bus_port, 4, ".*"); + } + } + } + bcdDevice = dev_desc.bcdDevice; #else /* => WITH_LIBUSB_0_1 */ # ifndef WIN32 @@ -367,8 +405,8 @@ nutscan_device_t * nutscan_scan_usb() ret = (*nut_usb_open)(dev, &udev); if (!udev || ret != LIBUSB_SUCCESS) { fprintf(stderr, "Failed to open device " - "bus '%s' device/port '%s', skipping: %s\n", - busname, device_port, + "bus '%s' device/port '%s' bus/port '%s', skipping: %s\n", + busname, device_port, bus_port, (*nut_usb_strerror)(ret)); /* Note: closing is not applicable @@ -379,6 +417,10 @@ nutscan_device_t * nutscan_scan_usb() free(busname); free(device_port); + if (bus_port != NULL) { + free(bus_port); + bus_port = NULL; + } continue; } @@ -405,6 +447,10 @@ nutscan_device_t * nutscan_scan_usb() #if WITH_LIBUSB_1_0 free(busname); free(device_port); + if (bus_port != NULL) { + free(bus_port); + bus_port = NULL; + } (*nut_usb_free_device_list)(devlist, 1); (*nut_usb_exit)(NULL); #endif /* WITH_LIBUSB_1_0 */ @@ -425,6 +471,10 @@ nutscan_device_t * nutscan_scan_usb() #if WITH_LIBUSB_1_0 free(busname); free(device_port); + if (bus_port != NULL) { + free(bus_port); + bus_port = NULL; + } (*nut_usb_free_device_list)(devlist, 1); (*nut_usb_exit)(NULL); #endif /* WITH_LIBUSB_1_0 */ @@ -446,6 +496,10 @@ nutscan_device_t * nutscan_scan_usb() #if WITH_LIBUSB_1_0 free(busname); free(device_port); + if (bus_port != NULL) { + free(bus_port); + bus_port = NULL; + } (*nut_usb_free_device_list)(devlist, 1); (*nut_usb_exit)(NULL); #endif /* WITH_LIBUSB_1_0 */ @@ -466,6 +520,10 @@ nutscan_device_t * nutscan_scan_usb() #if WITH_LIBUSB_1_0 free(busname); free(device_port); + if (bus_port != NULL) { + free(bus_port); + bus_port = NULL; + } (*nut_usb_free_device_list)(devlist, 1); (*nut_usb_exit)(NULL); #endif /* WITH_LIBUSB_1_0 */ @@ -520,6 +578,16 @@ nutscan_device_t * nutscan_scan_usb() "device", device_port); +#if WITH_LIBUSB_1_0 + if (bus_port) { + nutscan_add_option_to_device(nut_dev, + "busport", + bus_port); + free(bus_port); + bus_port = NULL; + } +#endif /* WITH_LIBUSB_1_0 */ + /* Not currently matched by drivers, hence commented for now: */ sprintf(string, "%04X", bcdDevice); nutscan_add_option_to_device(nut_dev, @@ -540,6 +608,10 @@ nutscan_device_t * nutscan_scan_usb() #else /* not WITH_LIBUSB_0_1 */ free(busname); free(device_port); + if (bus_port != NULL) { + free(bus_port); + bus_port = NULL; + } } (*nut_usb_free_device_list)(devlist, 1); From e2699889506a1102dc40b3b24e7221352dbabfd4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 21:02:21 +0200 Subject: [PATCH 26/28] drivers/libshut.h: update with formal support of "busport" (no-op for serial mode) [#2043] Signed-off-by: Jim Klimov --- drivers/libshut.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/libshut.h b/drivers/libshut.h index 84da1af1ed..caa0780ce8 100644 --- a/drivers/libshut.h +++ b/drivers/libshut.h @@ -116,7 +116,7 @@ typedef int usb_ctrl_timeout_msec; /* in milliseconds */ /*! * SHUTDevice_t: Describe a SHUT device. This structure contains exactly - * the 5 pieces of information by which a SHUT device identifies + * the 5 or more pieces of information by which a SHUT device identifies * itself, so it serves as a kind of "fingerprint" of the device. This * information must be matched exactly when reopening a device, and * therefore must not be "improved" or updated by a client @@ -132,6 +132,9 @@ typedef struct SHUTDevice_s { char* Bus; /*!< Bus name, e.g. "003" */ uint16_t bcdDevice; /*!< Device release number */ char *Device; /*!< Device name on the bus, e.g. "001" */ +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) + char *BusPort; /*!< Port name, e.g. "001" */ +#endif } SHUTDevice_t; /*! From b2c99e1f0e51542582534e9802b36d3d2277a31e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 16 Sep 2023 21:04:43 +0200 Subject: [PATCH 27/28] drivers/usbhid-ups.c: initialize BusPort where used [#2043] Signed-off-by: Jim Klimov --- drivers/usbhid-ups.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index 7a7ab370e0..36748c66fb 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -118,7 +118,11 @@ static subdriver_t *subdriver = NULL; /* Global vars */ static HIDDevice_t *hd = NULL; -static HIDDevice_t curDevice = { 0x0000, 0x0000, NULL, NULL, NULL, NULL, 0, NULL }; +static HIDDevice_t curDevice = { 0x0000, 0x0000, NULL, NULL, NULL, NULL, 0, NULL +#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) + , NULL +#endif +}; static HIDDeviceMatcher_t *subdriver_matcher = NULL; #if !((defined SHUT_MODE) && SHUT_MODE) static HIDDeviceMatcher_t *exact_matcher = NULL; From 573f93b61d31036daa6c84e3c85284cb8b1e6690 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 17 Sep 2023 00:47:21 +0200 Subject: [PATCH 28/28] scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in: detect USB drivers by "busport" among config options [#2043] Signed-off-by: Jim Klimov --- scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in index b237c03423..2d2c126dbb 100755 --- a/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in +++ b/scripts/upsdrvsvcctl/nut-driver-enumerator.sh.in @@ -490,7 +490,7 @@ upsconf_getDriverMedia() { printf '%s\n%s\n' "$CURR_DRV" "usb" ; return ;; /dev/*) # See drivers/nutdrv_qx.c :: upsdrv_initups() for a list - if [ -n "`upsconf_getValue "$1" 'subdriver' 'vendorid' 'productid' 'vendor' 'product' 'serial' 'bus' 'langid_fix'`" ] \ + if [ -n "`upsconf_getValue "$1" 'subdriver' 'vendorid' 'productid' 'vendor' 'product' 'serial' 'bus' 'busport' 'langid_fix'`" ] \ ; then printf '%s\n%s\n' "$CURR_DRV" "usb" ; return else