summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorrakuco <rakuco@FreeBSD.org>2015-04-15 22:02:52 +0000
committerrakuco <rakuco@FreeBSD.org>2015-04-15 22:02:52 +0000
commit62386cb488bb5851e8c26f69319233cdcab89927 (patch)
tree85367f3d0f13829eb39802842187a42dd1cdd021 /usr.sbin
parent77f96f7deb629f2aeb9f51a59f85b62b3fec1737 (diff)
downloadFreeBSD-src-62386cb488bb5851e8c26f69319233cdcab89927.zip
FreeBSD-src-62386cb488bb5851e8c26f69319233cdcab89927.tar.gz
MFC r281116.
bthidd: Consider usage ranges when dealing with array inputs. So far, we were always using HID_USAGE() to determine the Usage ID of a certain HID report input item. This does not work as intended if a field is an array and the allowed usages are specified with a usage range, as HID_USAGE() will return 0. We need to use the field value as an index in the usage range list in this case instead. This makes the volume keys in a Microsoft Bluetooth Mobile Keyboard 5000 be properly recognized. The relevant part of the HID report looks like this: 0xA1, 0x01, // Collection (Application) 0x85, 0x07, // Report ID (7) 0x05, 0x0C, // Usage Page (Consumer) 0x19, 0x00, // Usage Minimum (Unassigned) 0x2A, 0xFF, 0x03, // Usage Maximum (0x03FF) 0x95, 0x01, // Report Count (1) 0x75, 0x10, // Report Size (16) 0x15, 0x00, // Logical Minimum (0) 0x27, 0xFF, 0x03, 0x00, 0x00, // Logical Maximum (1023) 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred // State,No Null Position) When a key such as "volume down" is pressed, the following data is transferred through Interrupt In: 0x07 0xEA 0x00 Differential Revision: https://reviews.freebsd.org/D2229
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bluetooth/bthidd/hid.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/usr.sbin/bluetooth/bthidd/hid.c b/usr.sbin/bluetooth/bthidd/hid.c
index c68865b..5eb7592 100644
--- a/usr.sbin/bluetooth/bthidd/hid.c
+++ b/usr.sbin/bluetooth/bthidd/hid.c
@@ -165,9 +165,21 @@ hid_interrupt(bthid_session_p s, uint8_t *data, int32_t len)
continue;
page = HID_PAGE(h.usage);
- usage = HID_USAGE(h.usage);
val = hid_get_data(data, &h);
+ /*
+ * When the input field is an array and the usage is specified
+ * with a range instead of an ID, we have to derive the actual
+ * usage by using the item value as an index in the usage range
+ * list.
+ */
+ if ((h.flags & HIO_VARIABLE)) {
+ usage = HID_USAGE(h.usage);
+ } else {
+ const uint32_t usage_offset = val - h.logical_minimum;
+ usage = HID_USAGE(h.usage_minimum + usage_offset);
+ }
+
switch (page) {
case HUP_GENERIC_DESKTOP:
switch (usage) {
OpenPOWER on IntegriCloud