From e4d425ea0da611fdb93b7f34af32699fdbb2ff72 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 2 Oct 2024 13:31:11 +0200 Subject: [PATCH] drivers/main.c, docs, etc.: accept "LIBUSB_DEBUG=NUM" setting via ups.conf Signed-off-by: Jim Klimov --- NEWS.adoc | 5 ++++ conf/ups.conf.sample | 11 +++++++-- docs/man/nut_usb_addvars.txt | 19 +++++++++------- docs/man/ups.conf.txt | 25 ++++++++++++++++++++ drivers/main.c | 44 ++++++++++++++++++++++++++++++++++++ include/nutconf.hpp | 4 ++++ 6 files changed, 98 insertions(+), 10 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 3d1d0bdf41..86abcf1dd6 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -191,6 +191,11 @@ https://github.com/networkupstools/nut/milestone/11 of an UPS interface on a composite USB device or when looking at devices with non-default interface/endpoint/config numbers. [PR #2611] + - USB drivers should now accept a `LIBUSB_DEBUG=INTEGER` setting in `ups.conf` + (as well as an environment variable that can be generally set via `nut.conf` + or service unit methods or init script), to enable troubleshooting of LibUSB + itself. [issue #2616] + - Introduced a new driver concept for interaction with OS-reported hardware monitoring readings. Currently instantiated as `hwmon_ina219` specifically made for Texas Instruments INA219 chip as exposed in the Linux "hwmon" diff --git a/conf/ups.conf.sample b/conf/ups.conf.sample index 2eff376ca0..c9b011cd0a 100644 --- a/conf/ups.conf.sample +++ b/conf/ups.conf.sample @@ -82,8 +82,8 @@ # Set maxretry to 3 by default, this should mitigate race with slow devices: maxretry = 3 -# These directives can be set outside and inside a driver definition, with -# slightly different meanings per context: +# These directives can be set outside and inside a driver definition, +# sometimes with slightly different meanings per context: # # maxstartdelay: OPTIONAL. This can be set as a global variable # above your first UPS definition and it can also be @@ -111,6 +111,13 @@ maxretry = 3 # `debug_min` are set, the driver-level setting takes precedence. # Command-line option `-D` can only increase this verbosity level. # +# LIBUSB_DEBUG: OPTIONAL. For run-time troubleshooting of USB-capable NUT +# drivers, you can specify the verbosity of LibUSB specific +# debugging as a numeric value such as `4` ("All messages +# are emitted"). Should not have any practical impact on +# other NUT drivers. For more details, see the library's +# documentation at e.g. https://libusb.sourceforge.io/api-1.0/ +# # user, group: OPTIONAL. Overrides the compiled-in (also global-section, # when used in driver section) default unprivileged user/group # name for NUT device driver. Impacts access rights used for diff --git a/docs/man/nut_usb_addvars.txt b/docs/man/nut_usb_addvars.txt index 0ef343fead..af95a0aaf1 100644 --- a/docs/man/nut_usb_addvars.txt +++ b/docs/man/nut_usb_addvars.txt @@ -125,18 +125,21 @@ As a rule of thumb for `usb_hid_desc_index` discovery, you can see larger `wDescriptorLength` values (roughly 600+ bytes) in reports of `lsusb` or similar tools. -[NOTE] -====== +*LIBUSB_DEBUG =* 'INTEGER':: + Run-time troubleshooting of USB-capable NUT drivers can involve not only raising the common NUT debug verbosity (e.g. using the `DEBUG_MIN` setting in linkman:ups.conf[5] or protocol commands to change the `driver.debug` value), but may also benefit from LibUSB specific debugging. - -For the latter, currently you would have to export the environment variable -`LIBUSB_DEBUG` before starting a NUT driver (may be set and "exported" via -linkman:nut.conf[5]), to a numeric value such as `4` ("All messages are -emitted"). For more details, including the currently supported values, see: ++ +For the latter, you can set the `LIBUSB_DEBUG` driver option; alternatively +you can classically export the environment variable `LIBUSB_DEBUG` before +starting a NUT driver program (may be set and "exported" in driver init +script or service method, perhaps via linkman:nut.conf[5]), to a numeric +value such as `4` ("All messages are emitted"). ++ +For more details, including the currently supported values for your version +of the library, see e.g.: * https://libusb.sourceforge.io/api-1.0/ * https://libusb.sourceforge.io/api-1.0/group__libusb__lib.html -====== diff --git a/docs/man/ups.conf.txt b/docs/man/ups.conf.txt index 28c102ca11..50fea2d27f 100644 --- a/docs/man/ups.conf.txt +++ b/docs/man/ups.conf.txt @@ -156,6 +156,19 @@ troubleshooting a deployment, without impacting foreground or background running mode directly. Command-line option `-D` can only increase this verbosity level. +*LIBUSB_DEBUG* 'INTEGER':: + +Optional. For run-time troubleshooting of USB-capable NUT drivers, +you can specify verbosity of LibUSB specific debugging as a numeric +value such as `4` ("All messages are emitted"). Should not have any +practical impact on other NUT drivers. ++ +For more details, including the currently supported values for your +version of the library, see e.g.: + +* https://libusb.sourceforge.io/api-1.0/ +* https://libusb.sourceforge.io/api-1.0/group__libusb__lib.html + UPS FIELDS ---------- @@ -325,6 +338,18 @@ running mode directly. If the global `debug_min` is also set, this driver-level setting overrides it. Command-line option `-D` can only increase this verbosity level. +*LIBUSB_DEBUG* 'INTEGER':: + +Optional. For run-time troubleshooting of USB-capable NUT drivers, +you can specify verbosity of LibUSB specific debugging as a numeric +value such as `4` ("All messages are emitted"). ++ +For more details, including the currently supported values for your +version of the library, see e.g.: + +* https://libusb.sourceforge.io/api-1.0/ +* https://libusb.sourceforge.io/api-1.0/group__libusb__lib.html + INTEGRATION ----------- diff --git a/drivers/main.c b/drivers/main.c index c2c68bfe3c..cb21941146 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -1074,6 +1074,28 @@ static int main_arg(char *var, char *val) return 1; /* handled */ } + if (!strcmp(var, "LIBUSB_DEBUG")) { + int lvl = -1; /* https://libusb.sourceforge.io/api-1.0/group__libusb__lib.html#ga2d6144203f0fc6d373677f6e2e89d2d2 */ + int msglvl = 1; + char buf[SMALLBUF], *s = getenv("LIBUSB_DEBUG"); + + if (!str_to_int(val, &lvl, 10) || lvl < 0) { + lvl = 4; + upslogx(LOG_INFO, "WARNING : Invalid LIBUSB_DEBUG value found in ups.conf for the driver, defaulting to %d", lvl); + } + if (nut_debug_level < 1 && nut_debug_level_driver < 1 && nut_debug_level_global < 1) + msglvl = 0; + + if (s) + upsdebugx(msglvl, "Old value of LIBUSB_DEBUG=%s in envvars", s); + + snprintf(buf, sizeof(buf), "%d", lvl); + upsdebugx(msglvl, "Enabling LIBUSB_DEBUG=%s from ups.conf", buf); + setenv("LIBUSB_DEBUG", buf, 1); + + return 1; /* handled */ + } + return 0; /* unhandled, pass it through to the driver */ } @@ -1200,6 +1222,28 @@ static void do_global_args(const char *var, const char *val) return; } + if (!strcmp(var, "LIBUSB_DEBUG")) { + int lvl = -1; /* https://libusb.sourceforge.io/api-1.0/group__libusb__lib.html#ga2d6144203f0fc6d373677f6e2e89d2d2 */ + int msglvl = 1; + char *s = getenv("LIBUSB_DEBUG"); + + if (!str_to_int(val, &lvl, 10) || lvl < 0) { + lvl = 4; + upslogx(LOG_INFO, "WARNING : Invalid LIBUSB_DEBUG value found in ups.conf for the driver, defaulting to %d", lvl); + } + if (nut_debug_level < 1 && nut_debug_level_driver < 1 && nut_debug_level_global < 1) + msglvl = 0; + + if (s) + upsdebugx(msglvl, "Old value of LIBUSB_DEBUG=%s in envvars", s); + + snprintf(buf, sizeof(buf), "%d", lvl); + upsdebugx(msglvl, "Enabling LIBUSB_DEBUG=%s from ups.conf", buf); + setenv("LIBUSB_DEBUG", buf, 1); + + return; + } + /* unrecognized */ } diff --git a/include/nutconf.hpp b/include/nutconf.hpp index 02c50f271d..4c1907bb70 100644 --- a/include/nutconf.hpp +++ b/include/nutconf.hpp @@ -1667,6 +1667,7 @@ class UpsConfiguration : public GenericConfiguration inline bool getNoWait() const { return getFlag("nowait"); } inline long long int getDebugMin() const { return getInt("debug_min"); } + inline long long int getLibusbDebug() const { return getInt("LIBUSB_DEBUG"); } inline long long int getMaxRetry() const { return getInt("maxretry"); } inline long long int getMaxStartDelay() const { return getInt("maxstartdelay"); } inline long long int getPollInterval() const { return getInt("pollinterval", 5); } // TODO: check the default @@ -1681,6 +1682,7 @@ class UpsConfiguration : public GenericConfiguration inline void setNoWait(bool val = true) { setFlag("nowait", val); } inline void setDebugMin(long long int num) { setInt("debug_min", num); } + inline void setLibusbDebug(long long int num) { setInt("LIBUSB_DEBUG", num); } inline void setMaxRetry(long long int num) { setInt("maxretry", num); } inline void setMaxStartDelay(long long int delay) { setInt("maxstartdelay", delay); } inline void setPollInterval(long long int interval) { setInt("pollinterval", interval); } @@ -1848,6 +1850,7 @@ class UpsConfiguration : public GenericConfiguration inline long long int getDaysOff(const std::string & ups) const { return getInt(ups, "daysoff"); } // CHECKME inline long long int getDaySweek(const std::string & ups) const { return getInt(ups, "daysweek"); } // CHECKME inline long long int getDebugMin(const std::string & ups) const { return getInt(ups, "debug_min"); } + inline long long int getLibusbDebug(const std::string & ups) const { return getInt(ups, "LIBUSB_DEBUG"); } inline long long int getFrequency(const std::string & ups) const { return getInt(ups, "frequency"); } // CHECKME inline long long int getHourOff(const std::string & ups) const { return getInt(ups, "houroff"); } // CHECKME inline long long int getHourOn(const std::string & ups) const { return getInt(ups, "houron"); } // CHECKME @@ -2061,6 +2064,7 @@ class UpsConfiguration : public GenericConfiguration inline void setDaysOff(const std::string & ups, long long int daysoff) { setInt(ups, "daysoff", daysoff); } // CHECKME inline void setDaysWeek(const std::string & ups, long long int daysweek) { setInt(ups, "daysweek", daysweek); } // CHECKME inline void setDebugMin(const std::string & ups, long long int val) { setInt(ups, "debug_min", val); } + inline void setLibusbDebug(const std::string & ups, long long int val) { setInt(ups, "LIBUSB_DEBUG", val); } inline void setFrequency(const std::string & ups, long long int frequency) { setInt(ups, "frequency", frequency); } // CHECKME inline void setHourOff(const std::string & ups, long long int houroff) { setInt(ups, "houroff", houroff); } // CHECKME inline void setHourOn(const std::string & ups, long long int houron) { setInt(ups, "houron", houron); } // CHECKME