[Nut-upsdev] [PATCH 2/3] Add generic facility to override HID report descriptor in usbhid-ups
Russell King
rmk at armlinux.org.uk
Sun Feb 4 00:19:40 UTC 2018
Some UPSes contain HID report descriptors that fail to correctly
describe the contents of reports. For example, the OpenUPS
descriptor fails to set the units, logical maximum and logical
minimum before the corresponding `main item' as required by the HID
specification.
This commit allows an override HID report descriptor to be given to
usbhid-ups which replaces the one produced by the UPS, allowing the
report descriptors to be properly parsed.
With an appropriately fixed report descriptor, OpenUPS reports correct
battery current (+ve for charging, -ve for discharging.)
---
drivers/usbhid-ups.c | 40 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c
index 954fa54..5a4d6db 100644
--- a/drivers/usbhid-ups.c
+++ b/drivers/usbhid-ups.c
@@ -748,6 +748,8 @@ void upsdrv_makevartable(void)
#else
addvar(VAR_VALUE, "notification", "Set notification type, (ignored, only for backward compatibility)");
#endif
+
+ addvar(VAR_VALUE, "hid_descriptor", "Replacement HID descriptor file");
}
#define MAX_EVENT_NUM 32
@@ -1093,16 +1095,52 @@ static void process_boolean_info(const char *nutvalue)
static int callback(hid_dev_handle_t udev, HIDDevice_t *hd, unsigned char *rdbuf, int rdlen)
{
int i;
- const char *mfr = NULL, *model = NULL, *serial = NULL;
+ const char *mfr = NULL, *model = NULL, *serial = NULL, *descfile;
#ifndef SHUT_MODE
int ret;
#endif
upsdebugx(2, "Report Descriptor size = %d", rdlen);
upsdebug_hex(3, "Report Descriptor", rdbuf, rdlen);
+ /* Check whether we have an override descriptor */
+ descfile = getval("hid_descriptor");
+ if (descfile) {
+ unsigned char *buf;
+ size_t size;
+ FILE *f;
+
+ f = fopen(descfile, "r");
+ if (!f) {
+ upslog_with_errno(LOG_ERR, "Can't open %s", descfile);
+ return 0;
+ }
+
+ fseek(f, 0, SEEK_END);
+ size = ftell(f);
+
+ fseek(f, 0, SEEK_SET);
+
+ buf = xmalloc(size);
+
+ if (fread(buf, size, 1, f) != 1) {
+ upslog_with_errno(LOG_CRIT, "Short read of %s", descfile);
+ fclose(f);
+ free(buf);
+ return 0;
+ }
+ fclose(f);
+
+ rdbuf = buf;
+ rdlen = size;
+ }
+
/* Parse Report Descriptor */
Free_ReportDesc(pDesc);
pDesc = Parse_ReportDesc(rdbuf, rdlen);
+
+ if (descfile)
+ free(rdbuf);
+
if (!pDesc) {
upsdebug_with_errno(1, "Failed to parse report descriptor!");
return 0;
--
2.7.4
--
Russell King
More information about the Nut-upsdev
mailing list