From owner-dev-commits-src-main@freebsd.org Thu Jan 7 23:21:00 2021 Return-Path: Delivered-To: dev-commits-src-main@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 9B0D94DEBB3; Thu, 7 Jan 2021 23:20:54 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4DBj044vXTz4Sw9; Thu, 7 Jan 2021 23:20:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 111D61934D; Thu, 7 Jan 2021 23:20:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 107NKpjN063443; Thu, 7 Jan 2021 23:20:51 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 107NKpQM063442; Thu, 7 Jan 2021 23:20:51 GMT (envelope-from git) Date: Thu, 7 Jan 2021 23:20:51 GMT Message-Id: <202101072320.107NKpQM063442@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Vladimir Kondratyev Subject: git: 95e1f0d68470 - main - Allow HID report descriptor parser to return more then 1 usage per item MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: wulf X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 95e1f0d6847060f9c7d90b6b7655b64029929efd Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-main@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for the main branch of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Jan 2021 23:21:01 -0000 The branch main has been updated by wulf: URL: https://cgit.FreeBSD.org/src/commit/?id=95e1f0d6847060f9c7d90b6b7655b64029929efd commit 95e1f0d6847060f9c7d90b6b7655b64029929efd Author: Vladimir Kondratyev AuthorDate: 2020-12-24 11:46:24 +0000 Commit: Vladimir Kondratyev CommitDate: 2021-01-07 23:18:41 +0000 Allow HID report descriptor parser to return more then 1 usage per item This handles parsing of following descriptor, containing array of usages: 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x80, // Usage (Sys Control) 0xA1, 0x01, // Collection (Application) 0x75, 0x02, // Report Size (2) 0x95, 0x01, // Report Count (1) 0x15, 0x01, // Logical Minimum (1) 0x25, 0x03, // Logical Maximum (3) 0x09, 0x82, // Usage (Sys Sleep) 0x09, 0x81, // Usage (Sys Power Down) 0x09, 0x83, // Usage (Sys Wake Up) 0x81, 0x60, // Input (Data,Array,Abs) 0x75, 0x06, // Report Size (6) 0x81, 0x03, // Input (Const,Var,Abs) 0xC0, // End Collection Our current parser returns only first usage (Sys Sleep) and loses next two. Set HID_ITEM_MAXUSAGE limit relatively low as existing code usually allocates hid_item on stack. Also tweak hid_locate() to support hid items with multiple usages. Reviewed by: hselasky Differential Revision: https://reviews.freebsd.org/D27748 --- sys/dev/usb/usb_hid.c | 39 +++++++++++++++++++++++++++------------ sys/dev/usb/usbhid.h | 8 +++++++- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/sys/dev/usb/usb_hid.c b/sys/dev/usb/usb_hid.c index dd0c8d4b42ac..22e5fb5446c3 100644 --- a/sys/dev/usb/usb_hid.c +++ b/sys/dev/usb/usb_hid.c @@ -111,7 +111,8 @@ hid_clear_local(struct hid_item *c) c->loc.count = 0; c->loc.size = 0; - c->usage = 0; + c->nusages = 0; + memset(c->usages, 0, sizeof(c->usages)); c->usage_minimum = 0; c->usage_maximum = 0; c->designator_index = 0; @@ -273,6 +274,16 @@ hid_get_item(struct hid_data *s, struct hid_item *h) DPRINTFN(1, "Using last usage\n"); dval = s->usage_last; } + c->nusages = 1; + /* array type HID item may have multiple usages */ + while ((c->flags & HIO_VARIABLE) == 0 && s->ousage == 0 && + s->iusage < s->nusage && c->nusages < HID_ITEM_MAXUSAGE) + c->usages[c->nusages++] = s->usages_min[s->iusage++]; + if ((c->flags & HIO_VARIABLE) == 0 && s->ousage == 0 && + s->iusage < s->nusage) + DPRINTFN(0, "HID_ITEM_MAXUSAGE should be increased " + "up to %hhu to parse the HID report descriptor\n", + s->nusage); s->icount ++; /* * Only copy HID item, increment position and return @@ -381,6 +392,7 @@ hid_get_item(struct hid_data *s, struct hid_item *h) c->collection = dval; c->collevel++; c->usage = s->usage_last; + c->nusages = 1; *h = *c; return (1); case 11: /* Feature */ @@ -620,19 +632,22 @@ hid_locate(const void *desc, usb_size_t size, int32_t u, enum hid_kind k, { struct hid_data *d; struct hid_item h; + int i; for (d = hid_start_parse(desc, size, 1 << k); hid_get_item(d, &h);) { - if (h.kind == k && h.usage == u) { - if (index--) - continue; - if (loc != NULL) - *loc = h.loc; - if (flags != NULL) - *flags = h.flags; - if (id != NULL) - *id = h.report_ID; - hid_end_parse(d); - return (1); + for (i = 0; i < h.nusages; i++) { + if (h.kind == k && h.usages[i] == u) { + if (index--) + break; + if (loc != NULL) + *loc = h.loc; + if (flags != NULL) + *flags = h.flags; + if (id != NULL) + *id = h.report_ID; + hid_end_parse(d); + return (1); + } } } if (loc != NULL) diff --git a/sys/dev/usb/usbhid.h b/sys/dev/usb/usbhid.h index 30949ea9a62a..926c404dca55 100644 --- a/sys/dev/usb/usbhid.h +++ b/sys/dev/usb/usbhid.h @@ -208,6 +208,8 @@ struct usb_hid_descriptor { #if defined(_KERNEL) || defined(_STANDALONE) struct usb_config_descriptor; +#define HID_ITEM_MAXUSAGE 4 + enum hid_kind { hid_input, hid_output, hid_feature, hid_collection, hid_endcollection }; @@ -229,7 +231,11 @@ struct hid_item { int32_t unit; int32_t report_ID; /* Local */ - int32_t usage; + int nusages; + union { + int32_t usage; + int32_t usages[HID_ITEM_MAXUSAGE]; + }; int32_t usage_minimum; int32_t usage_maximum; int32_t designator_index;