Date: Wed, 23 Dec 2020 22:29:37 GMT From: Vladimir Kondratyev <wulf@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 7eae6aab7d79 - wmt(4): Fetch and parse HID report descriptor only one time Message-ID: <202012232229.0BNMTbFZ083108@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by wulf: URL: https://cgit.FreeBSD.org/src/commit/?id=7eae6aab7d79eea0f30cd1a0be145404867c0a2f commit 7eae6aab7d79eea0f30cd1a0be145404867c0a2f Author: Vladimir Kondratyev <wulf@FreeBSD.org> AuthorDate: 2020-12-23 22:18:18 +0000 Commit: Vladimir Kondratyev <wulf@FreeBSD.org> CommitDate: 2020-12-23 22:21:53 +0000 wmt(4): Fetch and parse HID report descriptor only one time Do it at probe stage and reuse results during attach. Obtained from: sysutils/iichid --- sys/dev/usb/input/wmt.c | 110 +++++++++++++++++------------------------------- 1 file changed, 39 insertions(+), 71 deletions(-) diff --git a/sys/dev/usb/input/wmt.c b/sys/dev/usb/input/wmt.c index 3d4663693f5f..b3fbd8c82a13 100644 --- a/sys/dev/usb/input/wmt.c +++ b/sys/dev/usb/input/wmt.c @@ -185,9 +185,10 @@ struct wmt_absinfo { int32_t res; }; -struct wmt_softc -{ +struct wmt_softc { device_t dev; + bool supported; + struct mtx mtx; struct wmt_absinfo ai[WMT_N_USAGES]; struct hid_location locs[MAX_MT_SLOTS][WMT_N_USAGES]; @@ -260,6 +261,7 @@ static int wmt_probe(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); + struct wmt_softc *sc = device_get_softc(dev); void *d_ptr; uint16_t d_len; int err; @@ -278,11 +280,20 @@ wmt_probe(device_t dev) if (err) return (ENXIO); - if (wmt_hid_parse(NULL, d_ptr, d_len)) + /* Check if report descriptor belongs to a HID multitouch device */ + if (!sc->supported) + sc->supported = wmt_hid_parse(sc, d_ptr, d_len); + if (sc->supported) err = BUS_PROBE_DEFAULT; else err = ENXIO; + /* Check HID report length */ + if (sc->supported && (sc->isize <= 0 || sc->isize > WMT_BSIZE)) { + DPRINTF("Input size invalid or too large: %d\n", sc->isize); + err = ENXIO; + } + free(d_ptr, M_TEMP); return (err); } @@ -292,36 +303,12 @@ wmt_attach(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); struct wmt_softc *sc = device_get_softc(dev); - void *d_ptr; - uint16_t d_len; size_t i; int err; - bool hid_ok; device_set_usb_desc(dev); sc->dev = dev; - /* Get HID descriptor */ - err = usbd_req_get_hid_desc(uaa->device, NULL, - &d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex); - if (err) { - DPRINTF("usbd_req_get_hid_desc error=%s\n", usbd_errstr(err)); - return (ENXIO); - } - - hid_ok = wmt_hid_parse(sc, d_ptr, d_len); - free(d_ptr, M_TEMP); - if (!hid_ok) { - DPRINTF("multi-touch HID descriptor not found\n"); - return (ENXIO); - } - - /* Check HID report length */ - if (sc->isize <= 0 || sc->isize > WMT_BSIZE) { - DPRINTF("Input size invalid or too large: %d\n", sc->isize); - return (ENXIO); - } - /* Fetch and parse "Contact count maximum" feature report */ if (sc->cont_max_rlen > 0 && sc->cont_max_rlen <= WMT_BSIZE) { err = usbd_req_get_report(uaa->device, NULL, sc->buf, @@ -373,6 +360,18 @@ wmt_attach(device_t dev) if (err) goto detach; + /* Announce information about the touch device */ + device_printf(sc->dev, + "%d contacts and [%s%s%s%s%s]. Report range [%d:%d] - [%d:%d]\n", + (int)sc->ai[WMT_SLOT].max + 1, + USAGE_SUPPORTED(sc->caps, WMT_IN_RANGE) ? "R" : "", + USAGE_SUPPORTED(sc->caps, WMT_CONFIDENCE) ? "C" : "", + USAGE_SUPPORTED(sc->caps, WMT_WIDTH) ? "W" : "", + USAGE_SUPPORTED(sc->caps, WMT_HEIGHT) ? "H" : "", + USAGE_SUPPORTED(sc->caps, WMT_PRESSURE) ? "P" : "", + (int)sc->ai[WMT_X].min, (int)sc->ai[WMT_Y].min, + (int)sc->ai[WMT_X].max, (int)sc->ai[WMT_Y].max); + return (0); detach: @@ -648,11 +647,8 @@ wmt_hid_parse(struct wmt_softc *sc, const void *d_ptr, uint16_t d_len) struct hid_data *hd; size_t i; size_t cont = 0; - uint32_t caps = 0; int32_t cont_count_max = 0; uint8_t report_id = 0; - uint8_t cont_max_rid = 0; - uint8_t thqa_cert_rid = 0; bool touch_coll = false; bool finger_coll = false; bool cont_count_found = false; @@ -678,15 +674,14 @@ wmt_hid_parse(struct wmt_softc *sc, const void *d_ptr, uint16_t d_len) case hid_feature: if (hi.collevel == 1 && touch_coll && hi.usage == HID_USAGE2(HUP_MICROSOFT, HUMS_THQA_CERT)) { - thqa_cert_rid = hi.report_ID; + sc->thqa_cert_rid = hi.report_ID; break; } if (hi.collevel == 1 && touch_coll && hi.usage == HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACT_MAX)) { cont_count_max = hi.logical_maximum; - cont_max_rid = hi.report_ID; - if (sc != NULL) - sc->cont_max_loc = hi.loc; + sc->cont_max_rid = hi.report_ID; + sc->cont_max_loc = hi.loc; } break; default: @@ -696,7 +691,7 @@ wmt_hid_parse(struct wmt_softc *sc, const void *d_ptr, uint16_t d_len) hid_end_parse(hd); /* Maximum contact count is required usage */ - if (cont_max_rid == 0) + if (sc->cont_max_rid == 0) return (false); touch_coll = false; @@ -735,8 +730,7 @@ wmt_hid_parse(struct wmt_softc *sc, const void *d_ptr, uint16_t d_len) if (hi.collevel == 1 && hi.usage == HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACTCOUNT)) { cont_count_found = true; - if (sc != NULL) - sc->cont_count_loc = hi.loc; + sc->cont_count_loc = hi.loc; break; } /* Scan time is required but clobbered by evdev */ @@ -748,8 +742,6 @@ wmt_hid_parse(struct wmt_softc *sc, const void *d_ptr, uint16_t d_len) if (!finger_coll || hi.collevel != 2) break; - if (sc == NULL && cont > 0) - break; if (cont >= MAX_MT_SLOTS) { DPRINTF("Finger %zu ignored\n", cont); break; @@ -757,12 +749,6 @@ wmt_hid_parse(struct wmt_softc *sc, const void *d_ptr, uint16_t d_len) for (i = 0; i < WMT_N_USAGES; i++) { if (hi.usage == wmt_hid_map[i].usage) { - if (sc == NULL) { - if (USAGE_SUPPORTED(caps, i)) - continue; - caps |= 1 << i; - break; - } /* * HUG_X usage is an array mapped to * both ABS_MT_POSITION and ABS_MT_TOOL @@ -779,7 +765,7 @@ wmt_hid_parse(struct wmt_softc *sc, const void *d_ptr, uint16_t d_len) */ if (cont > 0) break; - caps |= 1 << i; + sc->caps |= 1 << i; sc->ai[i] = (struct wmt_absinfo) { .max = hi.logical_maximum, .min = hi.logical_minimum, @@ -799,14 +785,10 @@ wmt_hid_parse(struct wmt_softc *sc, const void *d_ptr, uint16_t d_len) if (!cont_count_found || !scan_time_found || cont == 0) return (false); for (i = 0; i < WMT_N_USAGES; i++) { - if (wmt_hid_map[i].required && !USAGE_SUPPORTED(caps, i)) + if (wmt_hid_map[i].required && !USAGE_SUPPORTED(sc->caps, i)) return (false); } - /* Stop probing here */ - if (sc == NULL) - return (true); - /* * According to specifications 'Contact Count Maximum' should be read * from Feature Report rather than from HID descriptor. Set sane @@ -827,9 +809,9 @@ wmt_hid_parse(struct wmt_softc *sc, const void *d_ptr, uint16_t d_len) }; /* Report touch orientation if both width and height are supported */ - if (USAGE_SUPPORTED(caps, WMT_WIDTH) && - USAGE_SUPPORTED(caps, WMT_HEIGHT)) { - caps |= (1 << WMT_ORIENTATION); + if (USAGE_SUPPORTED(sc->caps, WMT_WIDTH) && + USAGE_SUPPORTED(sc->caps, WMT_HEIGHT)) { + sc->caps |= 1 << WMT_ORIENTATION; sc->ai[WMT_ORIENTATION].max = 1; } @@ -837,28 +819,14 @@ wmt_hid_parse(struct wmt_softc *sc, const void *d_ptr, uint16_t d_len) sc->report_len = wmt_hid_report_size(d_ptr, d_len, hid_input, report_id); sc->cont_max_rlen = wmt_hid_report_size(d_ptr, d_len, hid_feature, - cont_max_rid); - if (thqa_cert_rid > 0) + sc->cont_max_rid); + if (sc->thqa_cert_rid > 0) sc->thqa_cert_rlen = wmt_hid_report_size(d_ptr, d_len, - hid_feature, thqa_cert_rid); + hid_feature, sc->thqa_cert_rid); sc->report_id = report_id; - sc->caps = caps; sc->nconts_per_report = cont; - sc->cont_max_rid = cont_max_rid; - sc->thqa_cert_rid = thqa_cert_rid; - /* Announce information about the touch device */ - device_printf(sc->dev, - "%d contacts and [%s%s%s%s%s]. Report range [%d:%d] - [%d:%d]\n", - (int)cont_count_max, - USAGE_SUPPORTED(sc->caps, WMT_IN_RANGE) ? "R" : "", - USAGE_SUPPORTED(sc->caps, WMT_CONFIDENCE) ? "C" : "", - USAGE_SUPPORTED(sc->caps, WMT_WIDTH) ? "W" : "", - USAGE_SUPPORTED(sc->caps, WMT_HEIGHT) ? "H" : "", - USAGE_SUPPORTED(sc->caps, WMT_PRESSURE) ? "P" : "", - (int)sc->ai[WMT_X].min, (int)sc->ai[WMT_Y].min, - (int)sc->ai[WMT_X].max, (int)sc->ai[WMT_Y].max); return (true); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202012232229.0BNMTbFZ083108>