Reputation: 472
Also see my original question here: Custom HID UPS - the host does not update the data from reports
I'm currently experimenting with developing USB HID devices using the Raspberry Pi Pico microcontroller. Let's consider two cases:
char ReportDescriptor[48] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x09, 0x01, // USAGE (Button 1)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x07, // REPORT_SIZE (7)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x80, // LOGICAL_MINIMUM (-128)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x95, 0x02, // REPORT_COUNT (2)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
But the following one doesn't:
char ReportDescriptor[26] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x19, 0x30, // USAGE_MINIMUM (X)
0x29, 0x31, // USAGE_MAXIMUM (Y)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x15, 0x80, // LOGICAL_MINIMUM (-128)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
This leads me to think that operating systems require a mouse to have at least one button.
USAGE_PAGE (Power Device)
USAGE (UPS)
COLLECTION (Application)
USAGE (Battery System)
COLLECTION (Physical)
REPORT_ID (1)
REPORT_SIZE (8)
REPORT_COUNT (1)
USAGE (iManufacturer)
STRING_INDEX (1)
FEATURE (Constant Variable Absolute)
USAGE (iProduct)
STRING_INDEX (2)
FEATURE (Constant Variable Absolute)
USAGE (iSerialNumber)
STRING_INDEX (3)
FEATURE (Constant Variable Absolute)
USAGE (Battery)
COLLECTION (Physical)
REPORT_ID (2)
USAGE_PAGE (Battery System)
REPORT_SIZE (1)
REPORT_COUNT (4)
LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (1)
USAGE (Charging)
USAGE (Discharging)
USAGE (Fully Charged)
USAGE (Fully Discharged)
INPUT (Variable Absolute Volatile)
However, this one does not work, and I'm struggling to figure out whether it is caused by missing required usages.
So, my questions are as follows:
Any information would be appreciated.
Upvotes: 0
Views: 582
Reputation: 472
Looking at the source code of UPower, it has the following function in src/linux/up-device-hid.c
(https://gitlab.freedesktop.org/upower/upower/-/blob/master/src/linux/up-device-hid.c#L253):
static void
up_device_hid_fixup_state (UpDevice *device)
{
gdouble percentage;
/* map states the UPS cannot express */
g_object_get (device, "percentage", &percentage, NULL);
if (percentage < UP_DAEMON_EPSILON)
g_object_set (device, "state", UP_DEVICE_STATE_EMPTY, NULL);
if (percentage > (100.0 - UP_DAEMON_EPSILON))
g_object_set (device, "state", UP_DEVICE_STATE_FULLY_CHARGED, NULL);
}
So the UPS has to report a RemainingCapacity
(RelativeStateOfCharge
or AbsoluteStateOfCharge
aren't supported for some reason) which should be larger than 0. HID UPSes can actually report empty and fully charged states, so I don't quite understand why UPower is applying this logic unconditionally.
Even though I got the UPS working on Linux, it would still be great to get some information regarding the mouse report descriptor, as well as getting the UPS state recognized on Windows. As such, any amendments to this answer would be appreciated.
Upvotes: 0