10 Commits

Author SHA1 Message Date
p fa4bfd80df Update README.adoc
Alpine 3.23 Success
2026-07-20 04:17:05 +02:00
p 2b9d655656 upscat: fix device filtering
Alpine 3.23 Success
Static allocation is a gift that keeps on giving.

Windows should now work fine in the non-Input polling mode.
2026-07-07 14:25:07 +02:00
p 74af8e884c Update README.adoc, upscat touch-ups
Alpine 3.23 Success
The tool only works on Windows with my CyberPower UPS.
2026-07-07 13:49:26 +02:00
p 8b5aff8081 upscat: touch-ups
Alpine 3.23 Success
2026-07-06 20:58:56 +02:00
p f2e586906f upscat: touch-ups
Alpine 3.23 Scripts failed
2026-07-06 20:53:33 +02:00
p 2c30ddfa3d Add upscat
Alpine 3.23 Scripts failed
This is a simple utility to track UPS status.
2026-07-06 20:45:17 +02:00
p 97b86c168e eizoctl: fix error reporting 2026-07-06 19:23:46 +02:00
p 41e928da52 eizoctl: handle usage ranges better 2026-07-06 09:16:16 +02:00
p ae195bf855 eizoctl: quote formatted strings 2026-07-06 07:42:13 +02:00
p 5035750647 elksmart-comm: detach any kernel driver
Alpine 3.23 Success
2026-03-07 07:26:52 +01:00
11 changed files with 1854 additions and 18 deletions
+20
View File
@@ -35,6 +35,7 @@ endif ()
# Dependencies
set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/liberty/cmake)
include (IconUtils)
include (CTest)
find_package (PkgConfig REQUIRED)
pkg_check_modules (libusb libusb-1.0)
@@ -95,6 +96,25 @@ if (WITH_HIDAPI)
target_include_directories (eizoctl PUBLIC ${hidapi_INCLUDE_DIRS})
target_link_directories (eizoctl PUBLIC ${hidapi_LIBRARY_DIRS})
target_link_libraries (eizoctl ${hidapi_LIBRARIES})
list (APPEND targets upscat)
add_executable (upscat upscat.c)
target_include_directories (upscat PUBLIC ${hidapi_INCLUDE_DIRS})
target_link_directories (upscat PUBLIC ${hidapi_LIBRARY_DIRS})
target_link_libraries (upscat ${hidapi_LIBRARIES})
endif ()
if (WITH_HIDAPI AND BUILD_TESTING)
add_executable (test-upscat $<TARGET_PROPERTY:upscat,SOURCES>)
set_target_properties (test-upscat PROPERTIES COMPILE_DEFINITIONS TESTING)
target_include_directories (test-upscat
PUBLIC $<TARGET_PROPERTY:upscat,INCLUDE_DIRECTORIES>)
target_link_directories (test-upscat
PUBLIC $<TARGET_PROPERTY:upscat,LINK_DIRECTORIES>)
target_link_libraries (test-upscat
PUBLIC $<TARGET_PROPERTY:upscat,LINK_LIBRARIES>)
add_test (NAME test-upscat
COMMAND test-upscat upscat-eaton3p.bin upscat-cyberpower.bin
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}")
endif ()
if (WITH_HIDAPI AND WIN32)
list (APPEND targets_gui eizoctltray)
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2013, 2024 - 2025, Přemysl Eric Janouch <p@janouch.name>
Copyright (c) 2013, 2024 - 2026, Přemysl Eric Janouch <p@janouch.name>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
+5
View File
@@ -1,3 +1,8 @@
Unreleased
* Added upscat for streaming status from UPS devices
1.2.0 (2026-01-04)
* eizoctl: added a --quiet option to suppress information and/or errors
+27
View File
@@ -102,6 +102,31 @@ Make sure to let the Windows Razer Synapse tool upgrade the firmware to the
newest version before running the program. There might be some issues otherwise
due to protocol changes, although I don't really deem it very probable.
upscat
~~~~~~
_upscat_ streams the basic status of UPS devices that use the USB HID protocol,
in CSV format. You'll get the power status, remaining capacity, run time,
and load percentage. It's been verified with Eaton 3S/3P series and CyberPower
BR1200ELCD, both working quite differently.
This program is meant to be a simple replacement for NUT:
```sh
upscat | awk -F, '
BEGIN {
getline
for (i = 1; i <= NF; i++) csv[$i] = i
}
!$csv["AC Present"] && $csv["Remaining Capacity"] < 50 {
print "On battery with " $csv["Remaining Capacity"] "% left, shutting down"
system("systemctl poweroff")
exit
}'
```
Beware that in my experience, merely having Eatons connected over USB can
mess with your system's ability to suspend.
Packages
--------
Regular releases are sporadic. git master should be stable enough.
@@ -110,6 +135,8 @@ as a https://git.janouch.name/p/nixexprs[Nix derivation].
Windows/macOS binaries can be downloaded from
https://git.janouch.name/p/usb-drivers/releases[the Releases page on Gitea].
They aren't signed/trusted--feel free to either rebuild them yourself,
or contact me about a donation to change that.
Building
--------
+6 -6
View File
@@ -142,7 +142,6 @@ struct parser {
struct parser_state_local {
uint32_t usage;
uint32_t usage_minimum;
uint32_t usage_maximum;
uint32_t designator_index;
uint32_t designator_minimum;
uint32_t designator_maximum;
@@ -266,7 +265,8 @@ parse_item(
break; case PARSER_ITEM_TAG_LOCAL_USAGE_MINIMUM:
parser->local.usage_minimum = u;
break; case PARSER_ITEM_TAG_LOCAL_USAGE_MAXIMUM:
parser->local.usage_maximum = u;
// This adds to usages from parser->local.usage_minimum through u.
return "usage ranges are not supported";
break; case PARSER_ITEM_TAG_LOCAL_DESIGNATOR_INDEX:
parser->local.designator_index = u;
break; case PARSER_ITEM_TAG_LOCAL_DESIGNATOR_MINIMUM:
@@ -1003,7 +1003,7 @@ eizo_watch(struct eizo_monitor *m, print_fn output, print_fn error)
int res = 0;
while (true) {
if ((res = hid_read(m->dev, buf, sizeof buf)) < 0)
return eizo_monitor_failf(m, "watch: %ls", hid_error(m->dev));
return eizo_monitor_failf(m, "watch: %ls", hid_read_error(m->dev));
if (buf[0] != EIZO_REPORT_ID_GET &&
buf[0] != EIZO_REPORT_ID_GET_LONG) {
@@ -1018,12 +1018,12 @@ eizo_watch(struct eizo_monitor *m, print_fn output, print_fn error)
const struct parser_report *r = eizo_monitor_subreport(m, usage);
if (!r) {
output(catf(&message, " unknown usage\n"));
output("%s", catf(&message, " unknown usage\n"));
continue;
}
size_t rlen = r->report_size / 8 * r->report_count;
if ((size_t) res < 7 + rlen) {
output(catf(&message, " received data too short\n"));
output("%s", catf(&message, " received data too short\n"));
continue;
}
if (r->report_size == 16)
@@ -1032,7 +1032,7 @@ eizo_watch(struct eizo_monitor *m, print_fn output, print_fn error)
else
for (size_t i = 0; i < rlen; i++)
catf(&message, " %02x", buf[7 + i]);
output(catf(&message, "\n"));
output("%s", catf(&message, "\n"));
}
}
+16 -11
View File
@@ -306,20 +306,25 @@ init_device_from_desc(struct libusb_config_descriptor *desc, struct error **e)
static bool
init_device(libusb_device_handle *device, struct error **e)
{
int result = libusb_kernel_driver_active(device, USB_INTERFACE);
if (result == 1) {
// macOS for some reason claims the interface and we need to detach it
// before the following call to libusb_get_active_config_descriptor().
if ((result = libusb_detach_kernel_driver(device, USB_INTERFACE)))
return error_set(e, "cannot detach kernel driver: %s",
libusb_strerror(result));
print_debug("detached the kernel driver");
} else if (result) {
return error_set(e, "%s", libusb_strerror(result));
}
struct libusb_config_descriptor *desc = NULL;
int result =
libusb_get_active_config_descriptor(libusb_get_device(device), &desc);
if (result)
if ((result = libusb_get_active_config_descriptor(
libusb_get_device(device), &desc)))
return error_set(e, "%s", libusb_strerror(result));
bool ok = true;
if ((result = libusb_kernel_driver_active(device, USB_INTERFACE)) == 1)
ok = error_set(e, "device is claimed by a kernel driver");
else if (result)
ok = error_set(e, "%s", libusb_strerror(result));
else
ok = init_device_from_desc(desc, e);
bool ok = init_device_from_desc(desc, e);
libusb_free_config_descriptor(desc);
return ok;
}
Binary file not shown.
Binary file not shown.
+153
View File
@@ -0,0 +1,153 @@
#!/bin/sh -e
# upscat-gen-usb.sh: convert tables from the USB HID specification to C code
#
# Copyright (c) 2026, Přemysl Eric Janouch <p@janouch.name>
# SPDX-License-Identifier: 0BSD
if [ ! -e hut1_7.pdf ]
then curl -LO https://www.usb.org/sites/default/files/hut1_7.pdf
fi
# Our program doesn't need all of them, so we're filtering them here.
process() (qpdf --show-attachment=HidUsageTables.json hut1_7.pdf \
| jq -r '.UsagePages[] | select(.Name | IN("Battery System", "Power")) |
'"$1"' | @tsv' | sort -n -k 1,1 -k 2,2 | awk -F'\t' '
function ident(s) { gsub(/[^[:alnum:]]/, "_", s); return s } '"{ $2 }")
pages='[.Id, .Name]'
usages='. as $page | $page.UsageIds[] |
[$page.Id, .Id, $page.Name, (.Name | gsub("\\\\_"; "_")),
(.Kinds | join("/"))]'
generated='. as $page | .UsageIdGenerator | select(.) |
[$page.Id, .StartUsageId, .EndUsageId, $page.Name, .NamePrefix,
(.Kinds | join("/"))]'
cat <<EOF >upscat-usb.h
// Code generated by $0. DO NOT EDIT.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
enum {
USB_HID_COLLECTION_PHYSICAL = 0x00,
USB_HID_COLLECTION_APPLICATION = 0x01,
USB_HID_COLLECTION_LOGICAL = 0x02,
USB_HID_COLLECTION_REPORT = 0x03,
USB_HID_COLLECTION_NAMED_ARRAY = 0x04,
USB_HID_COLLECTION_USAGE_SWITCH = 0x05,
USB_HID_COLLECTION_USAGE_MODIFIER = 0x06,
};
enum {
$(process "$pages" '
printf("\t/// %s\n", $2)
printf("\tUSB_HID_USAGE_PAGE__%s = 0x%04x,\n", toupper(ident($2)), $1)
')
};
static const struct usb_hid_usage_page_info {
uint16_t usage_page;
const char *name;
} usb_hid_usage_pages[] = {
$(process "$pages" 'printf("\t{0x%04x, \"%s\"},\n", $1, $2)')
};
$(process "$usages" '
printf("/// %s: %s (%s)\n", $3, $4, $5)
printf("#define USB_HID_USAGE__%s__%s 0x%04x%04x\n",
toupper(ident($3)), toupper(ident($4)), $1, $2)
')
static const struct usb_hid_usage_info {
uint32_t usage;
const char *name;
} usb_hid_usages[] = {
$(process "$usages" 'printf("\t{0x%04x%04x, \"%s\"},\n", $1, $2, $4)')
};
static const struct usb_hid_usage_range_info {
uint32_t usage_start;
uint32_t usage_end;
const char *name_prefix;
} usb_hid_usages_ranged[] = {
$(process "$generated" '
printf("\t// %s (%s)\n", $4, $6)
printf("\t{0x%04x%04x, 0x%04x%04x, \"%s\"},\n", $1, $2, $1, $3, $5)
')
};
static int
usb_hid_usage_pages_cmp(const void *a, const void *b)
{
const uint16_t *key = a;
const struct usb_hid_usage_page_info *entry = b;
return (*key > entry->usage_page) - (*key < entry->usage_page);
}
static int
usb_hid_usages_cmp(const void *a, const void *b)
{
const uint32_t *key = a;
const struct usb_hid_usage_info *entry = b;
return (*key > entry->usage) - (*key < entry->usage);
}
static int
usb_hid_usages_ranged_cmp(const void *a, const void *b)
{
const uint32_t *key = a;
const struct usb_hid_usage_range_info *entry = b;
return (*key > entry->usage_end) - (*key < entry->usage_start);
}
static const char *
usb_hid_usage_page_to_string(uint16_t usage_page)
{
const struct usb_hid_usage_page_info *entry = bsearch(
&usage_page, usb_hid_usage_pages,
sizeof usb_hid_usage_pages / sizeof usb_hid_usage_pages[0],
sizeof usb_hid_usage_pages[0], usb_hid_usage_pages_cmp);
if (entry)
return entry->name;
static char buffer[32];
snprintf(buffer, sizeof buffer, "%04x", usage_page);
return buffer;
}
static const char *
usb_hid_usage_to_string(uint32_t usage)
{
const struct usb_hid_usage_info *info = bsearch(
&usage, usb_hid_usages,
sizeof usb_hid_usages / sizeof usb_hid_usages[0],
sizeof usb_hid_usages[0], usb_hid_usages_cmp);
if (info)
return info->name;
static char buffer[64];
const struct usb_hid_usage_range_info *range = bsearch(
&usage, usb_hid_usages_ranged,
sizeof usb_hid_usages_ranged / sizeof usb_hid_usages_ranged[0],
sizeof usb_hid_usages_ranged[0], usb_hid_usages_ranged_cmp);
if (range) {
snprintf(buffer, sizeof buffer,
"%s %u", range->name_prefix, (unsigned) (usage & 0xffff));
return buffer;
}
snprintf(buffer, sizeof buffer, "%04x", (unsigned) (usage & 0xffff));
return buffer;
}
static const char *
usb_hid_usage_to_string_full(uint32_t usage)
{
static char buffer[128];
snprintf(buffer, sizeof buffer, "%s: %s",
usb_hid_usage_page_to_string(usage >> 16),
usb_hid_usage_to_string(usage));
return buffer;
}
EOF
+623
View File
@@ -0,0 +1,623 @@
// Code generated by ./upscat-gen-usb.sh. DO NOT EDIT.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
enum {
USB_HID_COLLECTION_PHYSICAL = 0x00,
USB_HID_COLLECTION_APPLICATION = 0x01,
USB_HID_COLLECTION_LOGICAL = 0x02,
USB_HID_COLLECTION_REPORT = 0x03,
USB_HID_COLLECTION_NAMED_ARRAY = 0x04,
USB_HID_COLLECTION_USAGE_SWITCH = 0x05,
USB_HID_COLLECTION_USAGE_MODIFIER = 0x06,
};
enum {
/// Power
USB_HID_USAGE_PAGE__POWER = 0x0084,
/// Battery System
USB_HID_USAGE_PAGE__BATTERY_SYSTEM = 0x0085,
};
static const struct usb_hid_usage_page_info {
uint16_t usage_page;
const char *name;
} usb_hid_usage_pages[] = {
{0x0084, "Power"},
{0x0085, "Battery System"},
};
/// Power: iName (SV)
#define USB_HID_USAGE__POWER__INAME 0x00840001
/// Power: Present Status (CL)
#define USB_HID_USAGE__POWER__PRESENT_STATUS 0x00840002
/// Power: Changed Status (CL)
#define USB_HID_USAGE__POWER__CHANGED_STATUS 0x00840003
/// Power: UPS (CA)
#define USB_HID_USAGE__POWER__UPS 0x00840004
/// Power: Power Supply (CA)
#define USB_HID_USAGE__POWER__POWER_SUPPLY 0x00840005
/// Power: Battery System (CP)
#define USB_HID_USAGE__POWER__BATTERY_SYSTEM 0x00840010
/// Power: Battery System Id (SV)
#define USB_HID_USAGE__POWER__BATTERY_SYSTEM_ID 0x00840011
/// Power: Battery (CP)
#define USB_HID_USAGE__POWER__BATTERY 0x00840012
/// Power: Battery Id (SV)
#define USB_HID_USAGE__POWER__BATTERY_ID 0x00840013
/// Power: Charger (CP)
#define USB_HID_USAGE__POWER__CHARGER 0x00840014
/// Power: Charger Id (SV)
#define USB_HID_USAGE__POWER__CHARGER_ID 0x00840015
/// Power: Power Converter (CP)
#define USB_HID_USAGE__POWER__POWER_CONVERTER 0x00840016
/// Power: Power Converter Id (SV)
#define USB_HID_USAGE__POWER__POWER_CONVERTER_ID 0x00840017
/// Power: Outlet System (CP)
#define USB_HID_USAGE__POWER__OUTLET_SYSTEM 0x00840018
/// Power: Outlet System Id (SV)
#define USB_HID_USAGE__POWER__OUTLET_SYSTEM_ID 0x00840019
/// Power: Input (CP)
#define USB_HID_USAGE__POWER__INPUT 0x0084001a
/// Power: Input Id (SV)
#define USB_HID_USAGE__POWER__INPUT_ID 0x0084001b
/// Power: Output (CP)
#define USB_HID_USAGE__POWER__OUTPUT 0x0084001c
/// Power: Output Id (SV)
#define USB_HID_USAGE__POWER__OUTPUT_ID 0x0084001d
/// Power: Flow (CP)
#define USB_HID_USAGE__POWER__FLOW 0x0084001e
/// Power: Flow Id (SV)
#define USB_HID_USAGE__POWER__FLOW_ID 0x0084001f
/// Power: Outlet (CP)
#define USB_HID_USAGE__POWER__OUTLET 0x00840020
/// Power: Outlet Id (SV)
#define USB_HID_USAGE__POWER__OUTLET_ID 0x00840021
/// Power: Gang (CL/CP)
#define USB_HID_USAGE__POWER__GANG 0x00840022
/// Power: Gang Id (SV)
#define USB_HID_USAGE__POWER__GANG_ID 0x00840023
/// Power: Power Summary (CL/CP)
#define USB_HID_USAGE__POWER__POWER_SUMMARY 0x00840024
/// Power: Power Summary Id (SV)
#define USB_HID_USAGE__POWER__POWER_SUMMARY_ID 0x00840025
/// Power: Voltage (DV)
#define USB_HID_USAGE__POWER__VOLTAGE 0x00840030
/// Power: Current (DV)
#define USB_HID_USAGE__POWER__CURRENT 0x00840031
/// Power: Frequency (DV)
#define USB_HID_USAGE__POWER__FREQUENCY 0x00840032
/// Power: Apparent Power (DV)
#define USB_HID_USAGE__POWER__APPARENT_POWER 0x00840033
/// Power: Active Power (DV)
#define USB_HID_USAGE__POWER__ACTIVE_POWER 0x00840034
/// Power: Percent Load (DV)
#define USB_HID_USAGE__POWER__PERCENT_LOAD 0x00840035
/// Power: Temperature (DV)
#define USB_HID_USAGE__POWER__TEMPERATURE 0x00840036
/// Power: Humidity (DV)
#define USB_HID_USAGE__POWER__HUMIDITY 0x00840037
/// Power: Bad Count (DV)
#define USB_HID_USAGE__POWER__BAD_COUNT 0x00840038
/// Power: Config Voltage (SV/DV)
#define USB_HID_USAGE__POWER__CONFIG_VOLTAGE 0x00840040
/// Power: Config Current (SV/DV)
#define USB_HID_USAGE__POWER__CONFIG_CURRENT 0x00840041
/// Power: Config Frequency (SV/DV)
#define USB_HID_USAGE__POWER__CONFIG_FREQUENCY 0x00840042
/// Power: Config Apparent Power (SV/DV)
#define USB_HID_USAGE__POWER__CONFIG_APPARENT_POWER 0x00840043
/// Power: Config Active Power (SV/DV)
#define USB_HID_USAGE__POWER__CONFIG_ACTIVE_POWER 0x00840044
/// Power: Config Percent Load (SV/DV)
#define USB_HID_USAGE__POWER__CONFIG_PERCENT_LOAD 0x00840045
/// Power: Config Temperature (SV/DV)
#define USB_HID_USAGE__POWER__CONFIG_TEMPERATURE 0x00840046
/// Power: Config Humidity (SV/DV)
#define USB_HID_USAGE__POWER__CONFIG_HUMIDITY 0x00840047
/// Power: Switch On Control (DV)
#define USB_HID_USAGE__POWER__SWITCH_ON_CONTROL 0x00840050
/// Power: Switch Off Control (DV)
#define USB_HID_USAGE__POWER__SWITCH_OFF_CONTROL 0x00840051
/// Power: Toggle Control (DV)
#define USB_HID_USAGE__POWER__TOGGLE_CONTROL 0x00840052
/// Power: Low Voltage Transfer (DV)
#define USB_HID_USAGE__POWER__LOW_VOLTAGE_TRANSFER 0x00840053
/// Power: High Voltage Transfer (DV)
#define USB_HID_USAGE__POWER__HIGH_VOLTAGE_TRANSFER 0x00840054
/// Power: Delay Before Reboot (DV)
#define USB_HID_USAGE__POWER__DELAY_BEFORE_REBOOT 0x00840055
/// Power: Delay Before Startup (DV)
#define USB_HID_USAGE__POWER__DELAY_BEFORE_STARTUP 0x00840056
/// Power: Delay Before Shutdown (DV)
#define USB_HID_USAGE__POWER__DELAY_BEFORE_SHUTDOWN 0x00840057
/// Power: Test (DV)
#define USB_HID_USAGE__POWER__TEST 0x00840058
/// Power: Module Reset (DV)
#define USB_HID_USAGE__POWER__MODULE_RESET 0x00840059
/// Power: Audible Alarm Control (DV)
#define USB_HID_USAGE__POWER__AUDIBLE_ALARM_CONTROL 0x0084005a
/// Power: Present (DF)
#define USB_HID_USAGE__POWER__PRESENT 0x00840060
/// Power: Good (DF)
#define USB_HID_USAGE__POWER__GOOD 0x00840061
/// Power: Internal Failure (DF)
#define USB_HID_USAGE__POWER__INTERNAL_FAILURE 0x00840062
/// Power: Voltag Out Of Range (DF)
#define USB_HID_USAGE__POWER__VOLTAG_OUT_OF_RANGE 0x00840063
/// Power: Frequency Out Of Range (DF)
#define USB_HID_USAGE__POWER__FREQUENCY_OUT_OF_RANGE 0x00840064
/// Power: Overload (DF)
#define USB_HID_USAGE__POWER__OVERLOAD 0x00840065
/// Power: Over Charged (DF)
#define USB_HID_USAGE__POWER__OVER_CHARGED 0x00840066
/// Power: Over Temperature (DF)
#define USB_HID_USAGE__POWER__OVER_TEMPERATURE 0x00840067
/// Power: Shutdown Requested (DF)
#define USB_HID_USAGE__POWER__SHUTDOWN_REQUESTED 0x00840068
/// Power: Shutdown Imminent (DF)
#define USB_HID_USAGE__POWER__SHUTDOWN_IMMINENT 0x00840069
/// Power: Switch On/Off (DF)
#define USB_HID_USAGE__POWER__SWITCH_ON_OFF 0x0084006b
/// Power: Switchable (DF)
#define USB_HID_USAGE__POWER__SWITCHABLE 0x0084006c
/// Power: Used (DF)
#define USB_HID_USAGE__POWER__USED 0x0084006d
/// Power: Boost (DF)
#define USB_HID_USAGE__POWER__BOOST 0x0084006e
/// Power: Buck (DF)
#define USB_HID_USAGE__POWER__BUCK 0x0084006f
/// Power: Initialized (DF)
#define USB_HID_USAGE__POWER__INITIALIZED 0x00840070
/// Power: Tested (DF)
#define USB_HID_USAGE__POWER__TESTED 0x00840071
/// Power: Awaiting Power (DF)
#define USB_HID_USAGE__POWER__AWAITING_POWER 0x00840072
/// Power: Communication Lost (DF)
#define USB_HID_USAGE__POWER__COMMUNICATION_LOST 0x00840073
/// Power: iManufacturer (SV)
#define USB_HID_USAGE__POWER__IMANUFACTURER 0x008400fd
/// Power: iProduct (SV)
#define USB_HID_USAGE__POWER__IPRODUCT 0x008400fe
/// Power: iSerialNumber (SV)
#define USB_HID_USAGE__POWER__ISERIALNUMBER 0x008400ff
/// Battery System: Smart Battery Battery Mode (CL)
#define USB_HID_USAGE__BATTERY_SYSTEM__SMART_BATTERY_BATTERY_MODE 0x00850001
/// Battery System: Smart Battery Battery Status (NAry)
#define USB_HID_USAGE__BATTERY_SYSTEM__SMART_BATTERY_BATTERY_STATUS 0x00850002
/// Battery System: Smart Battery Alarm Warning (NAry)
#define USB_HID_USAGE__BATTERY_SYSTEM__SMART_BATTERY_ALARM_WARNING 0x00850003
/// Battery System: Smart Battery Charger Mode (CL)
#define USB_HID_USAGE__BATTERY_SYSTEM__SMART_BATTERY_CHARGER_MODE 0x00850004
/// Battery System: Smart Battery Charger Status (CL)
#define USB_HID_USAGE__BATTERY_SYSTEM__SMART_BATTERY_CHARGER_STATUS 0x00850005
/// Battery System: Smart Battery Charger Spec Info (CL)
#define USB_HID_USAGE__BATTERY_SYSTEM__SMART_BATTERY_CHARGER_SPEC_INFO 0x00850006
/// Battery System: Smart Battery Selector State (CL)
#define USB_HID_USAGE__BATTERY_SYSTEM__SMART_BATTERY_SELECTOR_STATE 0x00850007
/// Battery System: Smart Battery Selector Presets (CL)
#define USB_HID_USAGE__BATTERY_SYSTEM__SMART_BATTERY_SELECTOR_PRESETS 0x00850008
/// Battery System: Smart Battery Selector Info (CL)
#define USB_HID_USAGE__BATTERY_SYSTEM__SMART_BATTERY_SELECTOR_INFO 0x00850009
/// Battery System: Optional Mfg Function 1 (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__OPTIONAL_MFG_FUNCTION_1 0x00850010
/// Battery System: Optional Mfg Function 2 (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__OPTIONAL_MFG_FUNCTION_2 0x00850011
/// Battery System: Optional Mfg Function 3 (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__OPTIONAL_MFG_FUNCTION_3 0x00850012
/// Battery System: Optional Mfg Function 4 (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__OPTIONAL_MFG_FUNCTION_4 0x00850013
/// Battery System: Optional Mfg Function 5 (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__OPTIONAL_MFG_FUNCTION_5 0x00850014
/// Battery System: Connection To SM Bus (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__CONNECTION_TO_SM_BUS 0x00850015
/// Battery System: Output Connection (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__OUTPUT_CONNECTION 0x00850016
/// Battery System: Charger Connection (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__CHARGER_CONNECTION 0x00850017
/// Battery System: Battery Insertion (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__BATTERY_INSERTION 0x00850018
/// Battery System: Use Next (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__USE_NEXT 0x00850019
/// Battery System: OK To Use (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__OK_TO_USE 0x0085001a
/// Battery System: Battery Supported (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__BATTERY_SUPPORTED 0x0085001b
/// Battery System: Selector Revision (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__SELECTOR_REVISION 0x0085001c
/// Battery System: Charging Indicator (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__CHARGING_INDICATOR 0x0085001d
/// Battery System: Manufacturer Access (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__MANUFACTURER_ACCESS 0x00850028
/// Battery System: Remaining Capacity Limit (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__REMAINING_CAPACITY_LIMIT 0x00850029
/// Battery System: Remaining Time Limit (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__REMAINING_TIME_LIMIT 0x0085002a
/// Battery System: At Rate (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__AT_RATE 0x0085002b
/// Battery System: Capacity Mode (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__CAPACITY_MODE 0x0085002c
/// Battery System: Broadcast To Charger (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__BROADCAST_TO_CHARGER 0x0085002d
/// Battery System: Primary Battery (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__PRIMARY_BATTERY 0x0085002e
/// Battery System: Charge Controller (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__CHARGE_CONTROLLER 0x0085002f
/// Battery System: Terminate Charge (Sel)
#define USB_HID_USAGE__BATTERY_SYSTEM__TERMINATE_CHARGE 0x00850040
/// Battery System: Terminate Discharge (Sel)
#define USB_HID_USAGE__BATTERY_SYSTEM__TERMINATE_DISCHARGE 0x00850041
/// Battery System: Below Remaining Capacity Limit (Sel)
#define USB_HID_USAGE__BATTERY_SYSTEM__BELOW_REMAINING_CAPACITY_LIMIT 0x00850042
/// Battery System: Remaining Time Limit Expired (Sel)
#define USB_HID_USAGE__BATTERY_SYSTEM__REMAINING_TIME_LIMIT_EXPIRED 0x00850043
/// Battery System: Charging (Sel)
#define USB_HID_USAGE__BATTERY_SYSTEM__CHARGING 0x00850044
/// Battery System: Discharging (Sel)
#define USB_HID_USAGE__BATTERY_SYSTEM__DISCHARGING 0x00850045
/// Battery System: Fully Charged (Sel)
#define USB_HID_USAGE__BATTERY_SYSTEM__FULLY_CHARGED 0x00850046
/// Battery System: Fully Discharged (Sel)
#define USB_HID_USAGE__BATTERY_SYSTEM__FULLY_DISCHARGED 0x00850047
/// Battery System: Conditioning Flag (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__CONDITIONING_FLAG 0x00850048
/// Battery System: At Rate OK (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__AT_RATE_OK 0x00850049
/// Battery System: Smart Battery Error Code (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__SMART_BATTERY_ERROR_CODE 0x0085004a
/// Battery System: Need Replacement (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__NEED_REPLACEMENT 0x0085004b
/// Battery System: At Rate Time To Full (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__AT_RATE_TIME_TO_FULL 0x00850060
/// Battery System: At Rate Time To Empty (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__AT_RATE_TIME_TO_EMPTY 0x00850061
/// Battery System: Average Current (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__AVERAGE_CURRENT 0x00850062
/// Battery System: Max Error (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__MAX_ERROR 0x00850063
/// Battery System: Relative State Of Charge (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__RELATIVE_STATE_OF_CHARGE 0x00850064
/// Battery System: Absolute State Of Charge (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__ABSOLUTE_STATE_OF_CHARGE 0x00850065
/// Battery System: Remaining Capacity (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__REMAINING_CAPACITY 0x00850066
/// Battery System: Full Charge Capacity (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__FULL_CHARGE_CAPACITY 0x00850067
/// Battery System: Run Time To Empty (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__RUN_TIME_TO_EMPTY 0x00850068
/// Battery System: Average Time To Empty (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__AVERAGE_TIME_TO_EMPTY 0x00850069
/// Battery System: Average Time To Full (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__AVERAGE_TIME_TO_FULL 0x0085006a
/// Battery System: Cycle Count (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__CYCLE_COUNT 0x0085006b
/// Battery System: Battery Pack Model Level (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__BATTERY_PACK_MODEL_LEVEL 0x00850080
/// Battery System: Internal Charge Controller (SF)
#define USB_HID_USAGE__BATTERY_SYSTEM__INTERNAL_CHARGE_CONTROLLER 0x00850081
/// Battery System: Primary Battery Support (SF)
#define USB_HID_USAGE__BATTERY_SYSTEM__PRIMARY_BATTERY_SUPPORT 0x00850082
/// Battery System: Design Capacity (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__DESIGN_CAPACITY 0x00850083
/// Battery System: Specification Info (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__SPECIFICATION_INFO 0x00850084
/// Battery System: Manufacture Date (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__MANUFACTURE_DATE 0x00850085
/// Battery System: Serial Number (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__SERIAL_NUMBER 0x00850086
/// Battery System: iManufacturer Name (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__IMANUFACTURER_NAME 0x00850087
/// Battery System: iDevice Name (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__IDEVICE_NAME 0x00850088
/// Battery System: iDevice Chemistry (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__IDEVICE_CHEMISTRY 0x00850089
/// Battery System: Manufacturer Data (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__MANUFACTURER_DATA 0x0085008a
/// Battery System: Rechargable (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__RECHARGABLE 0x0085008b
/// Battery System: Warning Capacity Limit (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__WARNING_CAPACITY_LIMIT 0x0085008c
/// Battery System: Capacity Granularity 1 (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__CAPACITY_GRANULARITY_1 0x0085008d
/// Battery System: Capacity Granularity 2 (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__CAPACITY_GRANULARITY_2 0x0085008e
/// Battery System: iOEM Information (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__IOEM_INFORMATION 0x0085008f
/// Battery System: Inhibit Charge (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__INHIBIT_CHARGE 0x008500c0
/// Battery System: Enable Polling (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__ENABLE_POLLING 0x008500c1
/// Battery System: Reset To Zero (DF)
#define USB_HID_USAGE__BATTERY_SYSTEM__RESET_TO_ZERO 0x008500c2
/// Battery System: AC Present (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__AC_PRESENT 0x008500d0
/// Battery System: Battery Present (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__BATTERY_PRESENT 0x008500d1
/// Battery System: Power Fail (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__POWER_FAIL 0x008500d2
/// Battery System: Alarm Inhibited (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__ALARM_INHIBITED 0x008500d3
/// Battery System: Thermistor Under Range (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__THERMISTOR_UNDER_RANGE 0x008500d4
/// Battery System: Thermistor Hot (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__THERMISTOR_HOT 0x008500d5
/// Battery System: Thermistor Cold (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__THERMISTOR_COLD 0x008500d6
/// Battery System: Thermistor Over Range (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__THERMISTOR_OVER_RANGE 0x008500d7
/// Battery System: Voltage Out Of Range (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__VOLTAGE_OUT_OF_RANGE 0x008500d8
/// Battery System: Current Out Of Range (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__CURRENT_OUT_OF_RANGE 0x008500d9
/// Battery System: Current Not Regulated (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__CURRENT_NOT_REGULATED 0x008500da
/// Battery System: Voltage Not Regulated (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__VOLTAGE_NOT_REGULATED 0x008500db
/// Battery System: Master Mode (DV)
#define USB_HID_USAGE__BATTERY_SYSTEM__MASTER_MODE 0x008500dc
/// Battery System: Charger Selector Support (SF)
#define USB_HID_USAGE__BATTERY_SYSTEM__CHARGER_SELECTOR_SUPPORT 0x008500f0
/// Battery System: Charger Spec (SV)
#define USB_HID_USAGE__BATTERY_SYSTEM__CHARGER_SPEC 0x008500f1
/// Battery System: Level 2 (SF)
#define USB_HID_USAGE__BATTERY_SYSTEM__LEVEL_2 0x008500f2
/// Battery System: Level 3 (SF)
#define USB_HID_USAGE__BATTERY_SYSTEM__LEVEL_3 0x008500f3
static const struct usb_hid_usage_info {
uint32_t usage;
const char *name;
} usb_hid_usages[] = {
{0x00840001, "iName"},
{0x00840002, "Present Status"},
{0x00840003, "Changed Status"},
{0x00840004, "UPS"},
{0x00840005, "Power Supply"},
{0x00840010, "Battery System"},
{0x00840011, "Battery System Id"},
{0x00840012, "Battery"},
{0x00840013, "Battery Id"},
{0x00840014, "Charger"},
{0x00840015, "Charger Id"},
{0x00840016, "Power Converter"},
{0x00840017, "Power Converter Id"},
{0x00840018, "Outlet System"},
{0x00840019, "Outlet System Id"},
{0x0084001a, "Input"},
{0x0084001b, "Input Id"},
{0x0084001c, "Output"},
{0x0084001d, "Output Id"},
{0x0084001e, "Flow"},
{0x0084001f, "Flow Id"},
{0x00840020, "Outlet"},
{0x00840021, "Outlet Id"},
{0x00840022, "Gang"},
{0x00840023, "Gang Id"},
{0x00840024, "Power Summary"},
{0x00840025, "Power Summary Id"},
{0x00840030, "Voltage"},
{0x00840031, "Current"},
{0x00840032, "Frequency"},
{0x00840033, "Apparent Power"},
{0x00840034, "Active Power"},
{0x00840035, "Percent Load"},
{0x00840036, "Temperature"},
{0x00840037, "Humidity"},
{0x00840038, "Bad Count"},
{0x00840040, "Config Voltage"},
{0x00840041, "Config Current"},
{0x00840042, "Config Frequency"},
{0x00840043, "Config Apparent Power"},
{0x00840044, "Config Active Power"},
{0x00840045, "Config Percent Load"},
{0x00840046, "Config Temperature"},
{0x00840047, "Config Humidity"},
{0x00840050, "Switch On Control"},
{0x00840051, "Switch Off Control"},
{0x00840052, "Toggle Control"},
{0x00840053, "Low Voltage Transfer"},
{0x00840054, "High Voltage Transfer"},
{0x00840055, "Delay Before Reboot"},
{0x00840056, "Delay Before Startup"},
{0x00840057, "Delay Before Shutdown"},
{0x00840058, "Test"},
{0x00840059, "Module Reset"},
{0x0084005a, "Audible Alarm Control"},
{0x00840060, "Present"},
{0x00840061, "Good"},
{0x00840062, "Internal Failure"},
{0x00840063, "Voltag Out Of Range"},
{0x00840064, "Frequency Out Of Range"},
{0x00840065, "Overload"},
{0x00840066, "Over Charged"},
{0x00840067, "Over Temperature"},
{0x00840068, "Shutdown Requested"},
{0x00840069, "Shutdown Imminent"},
{0x0084006b, "Switch On/Off"},
{0x0084006c, "Switchable"},
{0x0084006d, "Used"},
{0x0084006e, "Boost"},
{0x0084006f, "Buck"},
{0x00840070, "Initialized"},
{0x00840071, "Tested"},
{0x00840072, "Awaiting Power"},
{0x00840073, "Communication Lost"},
{0x008400fd, "iManufacturer"},
{0x008400fe, "iProduct"},
{0x008400ff, "iSerialNumber"},
{0x00850001, "Smart Battery Battery Mode"},
{0x00850002, "Smart Battery Battery Status"},
{0x00850003, "Smart Battery Alarm Warning"},
{0x00850004, "Smart Battery Charger Mode"},
{0x00850005, "Smart Battery Charger Status"},
{0x00850006, "Smart Battery Charger Spec Info"},
{0x00850007, "Smart Battery Selector State"},
{0x00850008, "Smart Battery Selector Presets"},
{0x00850009, "Smart Battery Selector Info"},
{0x00850010, "Optional Mfg Function 1"},
{0x00850011, "Optional Mfg Function 2"},
{0x00850012, "Optional Mfg Function 3"},
{0x00850013, "Optional Mfg Function 4"},
{0x00850014, "Optional Mfg Function 5"},
{0x00850015, "Connection To SM Bus"},
{0x00850016, "Output Connection"},
{0x00850017, "Charger Connection"},
{0x00850018, "Battery Insertion"},
{0x00850019, "Use Next"},
{0x0085001a, "OK To Use"},
{0x0085001b, "Battery Supported"},
{0x0085001c, "Selector Revision"},
{0x0085001d, "Charging Indicator"},
{0x00850028, "Manufacturer Access"},
{0x00850029, "Remaining Capacity Limit"},
{0x0085002a, "Remaining Time Limit"},
{0x0085002b, "At Rate"},
{0x0085002c, "Capacity Mode"},
{0x0085002d, "Broadcast To Charger"},
{0x0085002e, "Primary Battery"},
{0x0085002f, "Charge Controller"},
{0x00850040, "Terminate Charge"},
{0x00850041, "Terminate Discharge"},
{0x00850042, "Below Remaining Capacity Limit"},
{0x00850043, "Remaining Time Limit Expired"},
{0x00850044, "Charging"},
{0x00850045, "Discharging"},
{0x00850046, "Fully Charged"},
{0x00850047, "Fully Discharged"},
{0x00850048, "Conditioning Flag"},
{0x00850049, "At Rate OK"},
{0x0085004a, "Smart Battery Error Code"},
{0x0085004b, "Need Replacement"},
{0x00850060, "At Rate Time To Full"},
{0x00850061, "At Rate Time To Empty"},
{0x00850062, "Average Current"},
{0x00850063, "Max Error"},
{0x00850064, "Relative State Of Charge"},
{0x00850065, "Absolute State Of Charge"},
{0x00850066, "Remaining Capacity"},
{0x00850067, "Full Charge Capacity"},
{0x00850068, "Run Time To Empty"},
{0x00850069, "Average Time To Empty"},
{0x0085006a, "Average Time To Full"},
{0x0085006b, "Cycle Count"},
{0x00850080, "Battery Pack Model Level"},
{0x00850081, "Internal Charge Controller"},
{0x00850082, "Primary Battery Support"},
{0x00850083, "Design Capacity"},
{0x00850084, "Specification Info"},
{0x00850085, "Manufacture Date"},
{0x00850086, "Serial Number"},
{0x00850087, "iManufacturer Name"},
{0x00850088, "iDevice Name"},
{0x00850089, "iDevice Chemistry"},
{0x0085008a, "Manufacturer Data"},
{0x0085008b, "Rechargable"},
{0x0085008c, "Warning Capacity Limit"},
{0x0085008d, "Capacity Granularity 1"},
{0x0085008e, "Capacity Granularity 2"},
{0x0085008f, "iOEM Information"},
{0x008500c0, "Inhibit Charge"},
{0x008500c1, "Enable Polling"},
{0x008500c2, "Reset To Zero"},
{0x008500d0, "AC Present"},
{0x008500d1, "Battery Present"},
{0x008500d2, "Power Fail"},
{0x008500d3, "Alarm Inhibited"},
{0x008500d4, "Thermistor Under Range"},
{0x008500d5, "Thermistor Hot"},
{0x008500d6, "Thermistor Cold"},
{0x008500d7, "Thermistor Over Range"},
{0x008500d8, "Voltage Out Of Range"},
{0x008500d9, "Current Out Of Range"},
{0x008500da, "Current Not Regulated"},
{0x008500db, "Voltage Not Regulated"},
{0x008500dc, "Master Mode"},
{0x008500f0, "Charger Selector Support"},
{0x008500f1, "Charger Spec"},
{0x008500f2, "Level 2"},
{0x008500f3, "Level 3"},
};
static const struct usb_hid_usage_range_info {
uint32_t usage_start;
uint32_t usage_end;
const char *name_prefix;
} usb_hid_usages_ranged[] = {
};
static int
usb_hid_usage_pages_cmp(const void *a, const void *b)
{
const uint16_t *key = a;
const struct usb_hid_usage_page_info *entry = b;
return (*key > entry->usage_page) - (*key < entry->usage_page);
}
static int
usb_hid_usages_cmp(const void *a, const void *b)
{
const uint32_t *key = a;
const struct usb_hid_usage_info *entry = b;
return (*key > entry->usage) - (*key < entry->usage);
}
static int
usb_hid_usages_ranged_cmp(const void *a, const void *b)
{
const uint32_t *key = a;
const struct usb_hid_usage_range_info *entry = b;
return (*key > entry->usage_end) - (*key < entry->usage_start);
}
static const char *
usb_hid_usage_page_to_string(uint16_t usage_page)
{
const struct usb_hid_usage_page_info *entry = bsearch(
&usage_page, usb_hid_usage_pages,
sizeof usb_hid_usage_pages / sizeof usb_hid_usage_pages[0],
sizeof usb_hid_usage_pages[0], usb_hid_usage_pages_cmp);
if (entry)
return entry->name;
static char buffer[32];
snprintf(buffer, sizeof buffer, "%04x", usage_page);
return buffer;
}
static const char *
usb_hid_usage_to_string(uint32_t usage)
{
const struct usb_hid_usage_info *info = bsearch(
&usage, usb_hid_usages,
sizeof usb_hid_usages / sizeof usb_hid_usages[0],
sizeof usb_hid_usages[0], usb_hid_usages_cmp);
if (info)
return info->name;
static char buffer[64];
const struct usb_hid_usage_range_info *range = bsearch(
&usage, usb_hid_usages_ranged,
sizeof usb_hid_usages_ranged / sizeof usb_hid_usages_ranged[0],
sizeof usb_hid_usages_ranged[0], usb_hid_usages_ranged_cmp);
if (range) {
snprintf(buffer, sizeof buffer,
"%s %u", range->name_prefix, (unsigned) (usage & 0xffff));
return buffer;
}
snprintf(buffer, sizeof buffer, "%04x", (unsigned) (usage & 0xffff));
return buffer;
}
static const char *
usb_hid_usage_to_string_full(uint32_t usage)
{
static char buffer[128];
snprintf(buffer, sizeof buffer, "%s: %s",
usb_hid_usage_page_to_string(usage >> 16),
usb_hid_usage_to_string(usage));
return buffer;
}
+1003
View File
File diff suppressed because it is too large Load Diff