Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ https://github.com/networkupstools/nut/milestone/12
fixed to use the same mapping helper as other subdrivers. [issue #3246]
* `powercom-hid` subdriver improved with a `powercom_hack_voltage_lkp` to
query `battery.voltage`. [issue #2766]
* `powercom-hid` subdriver now honours configured `offdelay` and `ondelay`
driver options in `ups.conf`, and prefers them (if present) over the
values received from the UPS itself (like `ups.delay.shutdown` and
`ups.delay.start`), to fix implementations of shutdown/stayoff/startup
instant commands. [PR #3288]
* Improved handling of transient `LIBUSB_ERROR_IO` failures during polling.
Some devices (CyberPower, etc.) have firmware bugs causing random I/O
errors on certain HID reports. The driver now skips failing reports and
Expand Down
48 changes: 43 additions & 5 deletions drivers/powercom-hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

#include <ctype.h> /* isdigit() */

#define POWERCOM_HID_VERSION "PowerCOM HID 0.73"
#define POWERCOM_HID_VERSION "PowerCOM HID 0.74"
/* FIXME: experimental flag to be put in upsdrv_info */

/* PowerCOM */
Expand Down Expand Up @@ -97,11 +97,23 @@ static const char *powercom_startup_fun(double value)
static double powercom_startup_nuf(const char *value)
{
const char *s = dstate_getinfo("ups.delay.start");
const char *cfg = getval("ondelay");
uint32_t val, command;
int iv;

/* Start with seconds "as is" - convert into whole minutes */
iv = atoi(value ? value : s) / 60; /* minutes */
/* Priority: 1) command value, 2) config ondelay, 3) UPS current, 4) default
* Note we start with seconds "as is" - convert into whole minutes for the device protocol
*/
if (value && *value) {
iv = atoi(value) / 60;
} else if (cfg && *cfg) {
iv = atoi(cfg) / 60;
} else if (s && *s) {
iv = atoi(s) / 60;
} else {
iv = 2; /* Default: 2 minutes (120 seconds) */
}

#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE) )
# pragma GCC diagnostic push
#endif
Expand Down Expand Up @@ -165,10 +177,23 @@ static const char *powercom_shutdown_fun(double value)
static double powercom_shutdown_nuf(const char *value)
{
const char *s = dstate_getinfo("ups.delay.shutdown");
const char *cfg = getval("offdelay");
uint16_t val, command;
int iv;

iv = atoi(value ? value : s); /* seconds */
/* Priority: 1) command value, 2) config offdelay, 3) UPS current, 4) default
* Note we start with seconds "as is" - convert into magic numbers for the device protocol below
*/
if (value && *value) {
iv = atoi(value);
} else if (cfg && *cfg) {
iv = atoi(cfg);
} else if (s && *s) {
iv = atoi(s);
} else {
iv = 60; /* Default: 60 seconds */
}

if (iv < 0 || (intmax_t)iv > (intmax_t)UINT16_MAX) {
upsdebugx(0, "%s: value = %d is not in uint16_t range", __func__, iv);
return 0;
Expand Down Expand Up @@ -219,11 +244,24 @@ static info_lkp_t powercom_shutdown_info[] = {
static double powercom_stayoff_nuf(const char *value)
{
const char *s = dstate_getinfo("ups.delay.shutdown");
const char *cfg = getval("offdelay");
uint16_t val, command;
int iv;

/* FIXME: Anything for powercom_sdcmd_discrete_delay? */
iv = atoi(value ? value : s);
/* Priority: 1) command value, 2) config offdelay, 3) UPS current, 4) default
* Note we start with seconds "as is" - convert into magic numbers for the device protocol below
*/
if (value && *value) {
iv = atoi(value);
} else if (cfg && *cfg) {
iv = atoi(cfg);
} else if (s && *s) {
iv = atoi(s);
} else {
iv = 60; /* Default: 60 seconds */
}

if (iv < 0 || (intmax_t)iv > (intmax_t)UINT16_MAX) {
upsdebugx(0, "%s: value = %d is not in uint16_t range", __func__, iv);
return 0;
Expand Down
Loading