1 /*- 2 * Copyright (c) 2014-2017 Vladimir Kondratyev <wulf@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 /* 31 * MS Windows 7/8/10 compatible USB HID Multi-touch Device driver. 32 * https://msdn.microsoft.com/en-us/library/windows/hardware/jj151569(v=vs.85).aspx 33 * https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt 34 */ 35 36 #include <sys/param.h> 37 #include <sys/bus.h> 38 #include <sys/conf.h> 39 #include <sys/kernel.h> 40 #include <sys/lock.h> 41 #include <sys/malloc.h> 42 #include <sys/module.h> 43 #include <sys/mutex.h> 44 #include <sys/stddef.h> 45 #include <sys/sysctl.h> 46 #include <sys/systm.h> 47 48 #include "usbdevs.h" 49 #include <dev/usb/usb.h> 50 #include <dev/usb/usbdi.h> 51 #include <dev/usb/usbdi_util.h> 52 #include <dev/usb/usbhid.h> 53 54 #include <dev/usb/quirk/usb_quirk.h> 55 56 #include <dev/evdev/evdev.h> 57 #include <dev/evdev/input.h> 58 59 #define USB_DEBUG_VAR wmt_debug 60 #include <dev/usb/usb_debug.h> 61 62 static SYSCTL_NODE(_hw_usb, OID_AUTO, wmt, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 63 "USB MSWindows 7/8/10 compatible Multi-touch Device"); 64 #ifdef USB_DEBUG 65 static int wmt_debug = 0; 66 SYSCTL_INT(_hw_usb_wmt, OID_AUTO, debug, CTLFLAG_RWTUN, 67 &wmt_debug, 1, "Debug level"); 68 #endif 69 static bool wmt_timestamps = 0; 70 SYSCTL_BOOL(_hw_usb_wmt, OID_AUTO, timestamps, CTLFLAG_RDTUN, 71 &wmt_timestamps, 1, "Enable hardware timestamp reporting"); 72 73 #define WMT_BSIZE 1024 /* bytes, buffer size */ 74 #define WMT_BTN_MAX 8 /* Number of buttons supported */ 75 76 enum { 77 WMT_INTR_DT, 78 WMT_N_TRANSFER, 79 }; 80 81 enum wmt_type { 82 WMT_TYPE_UNKNOWN = 0, /* HID report descriptor is not probed */ 83 WMT_TYPE_UNSUPPORTED, /* Repdescr does not belong to MT device */ 84 WMT_TYPE_TOUCHPAD, 85 WMT_TYPE_TOUCHSCREEN, 86 }; 87 88 enum wmt_input_mode { 89 WMT_INPUT_MODE_MOUSE = 0x0, 90 WMT_INPUT_MODE_MT_TOUCHSCREEN = 0x2, 91 WMT_INPUT_MODE_MT_TOUCHPAD = 0x3, 92 }; 93 94 enum { 95 WMT_TIP_SWITCH, 96 #define WMT_SLOT WMT_TIP_SWITCH 97 WMT_WIDTH, 98 #define WMT_MAJOR WMT_WIDTH 99 WMT_HEIGHT, 100 #define WMT_MINOR WMT_HEIGHT 101 WMT_ORIENTATION, 102 WMT_X, 103 WMT_Y, 104 WMT_CONTACTID, 105 WMT_PRESSURE, 106 WMT_IN_RANGE, 107 WMT_CONFIDENCE, 108 WMT_TOOL_X, 109 WMT_TOOL_Y, 110 WMT_N_USAGES, 111 }; 112 113 #define WMT_NO_CODE (ABS_MAX + 10) 114 #define WMT_NO_USAGE -1 115 116 struct wmt_hid_map_item { 117 char name[5]; 118 int32_t usage; /* HID usage */ 119 uint32_t code; /* Evdev event code */ 120 bool required; /* Required for MT Digitizers */ 121 }; 122 123 static const struct wmt_hid_map_item wmt_hid_map[WMT_N_USAGES] = { 124 [WMT_TIP_SWITCH] = { /* WMT_SLOT */ 125 .name = "TIP", 126 .usage = HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_SWITCH), 127 .code = ABS_MT_SLOT, 128 .required = true, 129 }, 130 [WMT_WIDTH] = { /* WMT_MAJOR */ 131 .name = "WDTH", 132 .usage = HID_USAGE2(HUP_DIGITIZERS, HUD_WIDTH), 133 .code = ABS_MT_TOUCH_MAJOR, 134 .required = false, 135 }, 136 [WMT_HEIGHT] = { /* WMT_MINOR */ 137 .name = "HGHT", 138 .usage = HID_USAGE2(HUP_DIGITIZERS, HUD_HEIGHT), 139 .code = ABS_MT_TOUCH_MINOR, 140 .required = false, 141 }, 142 [WMT_ORIENTATION] = { 143 .name = "ORIE", 144 .usage = WMT_NO_USAGE, 145 .code = ABS_MT_ORIENTATION, 146 .required = false, 147 }, 148 [WMT_X] = { 149 .name = "X", 150 .usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), 151 .code = ABS_MT_POSITION_X, 152 .required = true, 153 }, 154 [WMT_Y] = { 155 .name = "Y", 156 .usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), 157 .code = ABS_MT_POSITION_Y, 158 .required = true, 159 }, 160 [WMT_CONTACTID] = { 161 .name = "C_ID", 162 .usage = HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACTID), 163 .code = ABS_MT_TRACKING_ID, 164 .required = true, 165 }, 166 [WMT_PRESSURE] = { 167 .name = "PRES", 168 .usage = HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_PRESSURE), 169 .code = ABS_MT_PRESSURE, 170 .required = false, 171 }, 172 [WMT_IN_RANGE] = { 173 .name = "RANG", 174 .usage = HID_USAGE2(HUP_DIGITIZERS, HUD_IN_RANGE), 175 .code = ABS_MT_DISTANCE, 176 .required = false, 177 }, 178 [WMT_CONFIDENCE] = { 179 .name = "CONF", 180 .usage = HID_USAGE2(HUP_DIGITIZERS, HUD_CONFIDENCE), 181 .code = WMT_NO_CODE, 182 .required = false, 183 }, 184 [WMT_TOOL_X] = { /* Shares HID usage with WMT_X */ 185 .name = "TL_X", 186 .usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), 187 .code = ABS_MT_TOOL_X, 188 .required = false, 189 }, 190 [WMT_TOOL_Y] = { /* Shares HID usage with WMT_Y */ 191 .name = "TL_Y", 192 .usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), 193 .code = ABS_MT_TOOL_Y, 194 .required = false, 195 }, 196 }; 197 198 struct wmt_absinfo { 199 int32_t min; 200 int32_t max; 201 int32_t res; 202 }; 203 204 struct wmt_softc { 205 device_t dev; 206 enum wmt_type type; 207 208 struct mtx mtx; 209 struct wmt_absinfo ai[WMT_N_USAGES]; 210 struct hid_location locs[MAX_MT_SLOTS][WMT_N_USAGES]; 211 struct hid_location cont_count_loc; 212 struct hid_location btn_loc[WMT_BTN_MAX]; 213 struct hid_location int_btn_loc; 214 struct hid_location scan_time_loc; 215 int32_t scan_time_max; 216 int32_t scan_time; 217 int32_t timestamp; 218 bool touch; 219 bool prev_touch; 220 221 struct usb_xfer *xfer[WMT_N_TRANSFER]; 222 struct evdev_dev *evdev; 223 224 uint32_t slot_data[WMT_N_USAGES]; 225 uint8_t caps[howmany(WMT_N_USAGES, 8)]; 226 uint8_t buttons[howmany(WMT_BTN_MAX, 8)]; 227 uint32_t isize; 228 uint32_t nconts_per_report; 229 uint32_t nconts_todo; 230 uint32_t report_len; 231 uint8_t report_id; 232 uint32_t max_button; 233 bool has_int_button; 234 bool is_clickpad; 235 bool do_timestamps; 236 237 struct hid_location cont_max_loc; 238 uint32_t cont_max_rlen; 239 uint8_t cont_max_rid; 240 struct hid_location btn_type_loc; 241 uint32_t btn_type_rlen; 242 uint8_t btn_type_rid; 243 uint32_t thqa_cert_rlen; 244 uint8_t thqa_cert_rid; 245 struct hid_location input_mode_loc; 246 uint32_t input_mode_rlen; 247 uint8_t input_mode_rid; 248 249 uint8_t buf[WMT_BSIZE] __aligned(4); 250 }; 251 252 #define WMT_FOREACH_USAGE(caps, usage) \ 253 for ((usage) = 0; (usage) < WMT_N_USAGES; ++(usage)) \ 254 if (isset((caps), (usage))) 255 256 static enum wmt_type wmt_hid_parse(struct wmt_softc *, const void *, uint16_t); 257 static int wmt_set_input_mode(struct wmt_softc *, enum wmt_input_mode); 258 259 static usb_callback_t wmt_intr_callback; 260 261 static device_probe_t wmt_probe; 262 static device_attach_t wmt_attach; 263 static device_detach_t wmt_detach; 264 265 #if __FreeBSD_version >= 1200077 266 static evdev_open_t wmt_ev_open; 267 static evdev_close_t wmt_ev_close; 268 #else 269 static evdev_open_t wmt_ev_open_11; 270 static evdev_close_t wmt_ev_close_11; 271 #endif 272 273 static const struct evdev_methods wmt_evdev_methods = { 274 #if __FreeBSD_version >= 1200077 275 .ev_open = &wmt_ev_open, 276 .ev_close = &wmt_ev_close, 277 #else 278 .ev_open = &wmt_ev_open_11, 279 .ev_close = &wmt_ev_close_11, 280 #endif 281 }; 282 283 static const struct usb_config wmt_config[WMT_N_TRANSFER] = { 284 [WMT_INTR_DT] = { 285 .type = UE_INTERRUPT, 286 .endpoint = UE_ADDR_ANY, 287 .direction = UE_DIR_IN, 288 .flags = { .pipe_bof = 1, .short_xfer_ok = 1 }, 289 .bufsize = WMT_BSIZE, 290 .callback = &wmt_intr_callback, 291 }, 292 }; 293 294 static int 295 wmt_probe(device_t dev) 296 { 297 struct usb_attach_arg *uaa = device_get_ivars(dev); 298 struct wmt_softc *sc = device_get_softc(dev); 299 void *d_ptr; 300 uint16_t d_len; 301 int err; 302 303 if (uaa->usb_mode != USB_MODE_HOST) 304 return (ENXIO); 305 306 if (uaa->info.bInterfaceClass != UICLASS_HID) 307 return (ENXIO); 308 309 if (usb_test_quirk(uaa, UQ_WMT_IGNORE)) 310 return (ENXIO); 311 312 err = usbd_req_get_hid_desc(uaa->device, NULL, 313 &d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex); 314 if (err) 315 return (ENXIO); 316 317 /* Check if report descriptor belongs to a HID multitouch device */ 318 if (sc->type == WMT_TYPE_UNKNOWN) 319 sc->type = wmt_hid_parse(sc, d_ptr, d_len); 320 if (sc->type != WMT_TYPE_UNSUPPORTED) 321 err = BUS_PROBE_DEFAULT; 322 else 323 err = ENXIO; 324 325 /* Check HID report length */ 326 if (sc->type != WMT_TYPE_UNSUPPORTED && 327 (sc->isize <= 0 || sc->isize > WMT_BSIZE)) { 328 DPRINTF("Input size invalid or too large: %d\n", sc->isize); 329 err = ENXIO; 330 } 331 332 free(d_ptr, M_TEMP); 333 return (err); 334 } 335 336 static int 337 wmt_attach(device_t dev) 338 { 339 struct usb_attach_arg *uaa = device_get_ivars(dev); 340 struct wmt_softc *sc = device_get_softc(dev); 341 uint32_t cont_count_max; 342 int nbuttons, btn; 343 size_t i; 344 int err; 345 346 device_set_usb_desc(dev); 347 sc->dev = dev; 348 349 /* Fetch and parse "Contact count maximum" feature report */ 350 if (sc->cont_max_rlen > 0 && sc->cont_max_rlen <= WMT_BSIZE) { 351 err = usbd_req_get_report(uaa->device, NULL, sc->buf, 352 sc->cont_max_rlen, uaa->info.bIfaceIndex, 353 UHID_FEATURE_REPORT, sc->cont_max_rid); 354 if (err == USB_ERR_NORMAL_COMPLETION) { 355 cont_count_max = hid_get_data_unsigned(sc->buf + 1, 356 sc->cont_max_rlen - 1, &sc->cont_max_loc); 357 /* 358 * Feature report is a primary source of 359 * 'Contact Count Maximum' 360 */ 361 if (cont_count_max > 0) 362 sc->ai[WMT_SLOT].max = cont_count_max - 1; 363 } else 364 DPRINTF("usbd_req_get_report error=(%s)\n", 365 usbd_errstr(err)); 366 } else 367 DPRINTF("Feature report %hhu size invalid or too large: %u\n", 368 sc->cont_max_rid, sc->cont_max_rlen); 369 370 /* Fetch and parse "Button type" feature report */ 371 if (sc->btn_type_rlen > 1 && sc->btn_type_rlen <= WMT_BSIZE && 372 sc->btn_type_rid != sc->cont_max_rid) { 373 bzero(sc->buf, sc->btn_type_rlen); 374 err = usbd_req_get_report(uaa->device, NULL, sc->buf, 375 sc->btn_type_rlen, uaa->info.bIfaceIndex, 376 UHID_FEATURE_REPORT, sc->btn_type_rid); 377 } 378 if (sc->btn_type_rlen > 1) { 379 if (err == 0) 380 sc->is_clickpad = hid_get_data_unsigned(sc->buf + 1, 381 sc->btn_type_rlen - 1, &sc->btn_type_loc) == 0; 382 else 383 DPRINTF("usbd_req_get_report error=%d\n", err); 384 } 385 386 /* Fetch THQA certificate to enable some devices like WaveShare */ 387 if (sc->thqa_cert_rlen > 0 && sc->thqa_cert_rlen <= WMT_BSIZE && 388 sc->thqa_cert_rid != sc->cont_max_rid) 389 (void)usbd_req_get_report(uaa->device, NULL, sc->buf, 390 sc->thqa_cert_rlen, uaa->info.bIfaceIndex, 391 UHID_FEATURE_REPORT, sc->thqa_cert_rid); 392 393 /* Switch touchpad in to absolute multitouch mode */ 394 if (sc->type == WMT_TYPE_TOUCHPAD) { 395 err = wmt_set_input_mode(sc, WMT_INPUT_MODE_MT_TOUCHPAD); 396 if (err != 0) 397 DPRINTF("Failed to set input mode: %d\n", err); 398 } 399 400 /* Cap contact count maximum to MAX_MT_SLOTS */ 401 if (sc->ai[WMT_SLOT].max >= MAX_MT_SLOTS) { 402 DPRINTF("Hardware reported %d contacts while only %d is " 403 "supported\n", (int)sc->ai[WMT_SLOT].max+1, MAX_MT_SLOTS); 404 sc->ai[WMT_SLOT].max = MAX_MT_SLOTS - 1; 405 } 406 407 if (/*usb_test_quirk(hw, UQ_MT_TIMESTAMP) ||*/ wmt_timestamps) 408 sc->do_timestamps = true; 409 410 mtx_init(&sc->mtx, "wmt lock", NULL, MTX_DEF); 411 412 err = usbd_transfer_setup(uaa->device, &uaa->info.bIfaceIndex, 413 sc->xfer, wmt_config, WMT_N_TRANSFER, sc, &sc->mtx); 414 if (err != USB_ERR_NORMAL_COMPLETION) { 415 DPRINTF("usbd_transfer_setup error=%s\n", usbd_errstr(err)); 416 goto detach; 417 } 418 419 sc->evdev = evdev_alloc(); 420 evdev_set_name(sc->evdev, device_get_desc(dev)); 421 evdev_set_phys(sc->evdev, device_get_nameunit(dev)); 422 evdev_set_id(sc->evdev, BUS_USB, uaa->info.idVendor, 423 uaa->info.idProduct, 0); 424 evdev_set_serial(sc->evdev, usb_get_serial(uaa->device)); 425 evdev_set_methods(sc->evdev, sc, &wmt_evdev_methods); 426 evdev_set_flag(sc->evdev, EVDEV_FLAG_MT_STCOMPAT); 427 switch (sc->type) { 428 case WMT_TYPE_TOUCHSCREEN: 429 evdev_support_prop(sc->evdev, INPUT_PROP_DIRECT); 430 break; 431 case WMT_TYPE_TOUCHPAD: 432 evdev_support_prop(sc->evdev, INPUT_PROP_POINTER); 433 if (sc->is_clickpad) 434 evdev_support_prop(sc->evdev, INPUT_PROP_BUTTONPAD); 435 break; 436 default: 437 KASSERT(0, ("wmt_attach: unsupported touch device type")); 438 } 439 evdev_support_event(sc->evdev, EV_SYN); 440 evdev_support_event(sc->evdev, EV_ABS); 441 if (sc->do_timestamps) { 442 evdev_support_event(sc->evdev, EV_MSC); 443 evdev_support_msc(sc->evdev, MSC_TIMESTAMP); 444 } 445 nbuttons = 0; 446 if (sc->max_button != 0 || sc->has_int_button) { 447 evdev_support_event(sc->evdev, EV_KEY); 448 if (sc->has_int_button) 449 evdev_support_key(sc->evdev, BTN_LEFT); 450 for (btn = 0; btn < sc->max_button; ++btn) { 451 if (isset(sc->buttons, btn)) { 452 evdev_support_key(sc->evdev, BTN_MOUSE + btn); 453 nbuttons++; 454 } 455 } 456 } 457 WMT_FOREACH_USAGE(sc->caps, i) { 458 if (wmt_hid_map[i].code != WMT_NO_CODE) 459 evdev_support_abs(sc->evdev, wmt_hid_map[i].code, 0, 460 sc->ai[i].min, sc->ai[i].max, 0, 0, sc->ai[i].res); 461 } 462 463 err = evdev_register_mtx(sc->evdev, &sc->mtx); 464 if (err) 465 goto detach; 466 467 /* Announce information about the touch device */ 468 device_printf(sc->dev, "Multitouch %s with %d external button%s%s\n", 469 sc->type == WMT_TYPE_TOUCHSCREEN ? "touchscreen" : "touchpad", 470 nbuttons, nbuttons != 1 ? "s" : "", 471 sc->is_clickpad ? ", click-pad" : ""); 472 device_printf(sc->dev, 473 "%d contacts and [%s%s%s%s%s]. Report range [%d:%d] - [%d:%d]\n", 474 (int)sc->ai[WMT_SLOT].max + 1, 475 isset(sc->caps, WMT_IN_RANGE) ? "R" : "", 476 isset(sc->caps, WMT_CONFIDENCE) ? "C" : "", 477 isset(sc->caps, WMT_WIDTH) ? "W" : "", 478 isset(sc->caps, WMT_HEIGHT) ? "H" : "", 479 isset(sc->caps, WMT_PRESSURE) ? "P" : "", 480 (int)sc->ai[WMT_X].min, (int)sc->ai[WMT_Y].min, 481 (int)sc->ai[WMT_X].max, (int)sc->ai[WMT_Y].max); 482 483 return (0); 484 485 detach: 486 wmt_detach(dev); 487 return (ENXIO); 488 } 489 490 static int 491 wmt_detach(device_t dev) 492 { 493 struct wmt_softc *sc = device_get_softc(dev); 494 495 evdev_free(sc->evdev); 496 usbd_transfer_unsetup(sc->xfer, WMT_N_TRANSFER); 497 mtx_destroy(&sc->mtx); 498 return (0); 499 } 500 501 static void 502 wmt_process_report(struct wmt_softc *sc, uint8_t *buf, int len) 503 { 504 size_t usage; 505 uint32_t *slot_data = sc->slot_data; 506 uint32_t cont, btn; 507 uint32_t cont_count; 508 uint32_t width; 509 uint32_t height; 510 uint32_t int_btn = 0; 511 uint32_t left_btn = 0; 512 int32_t slot; 513 uint32_t scan_time; 514 int32_t delta; 515 516 /* 517 * "In Parallel mode, devices report all contact information in a 518 * single packet. Each physical contact is represented by a logical 519 * collection that is embedded in the top-level collection." 520 * 521 * Since additional contacts that were not present will still be in the 522 * report with contactid=0 but contactids are zero-based, find 523 * contactcount first. 524 */ 525 cont_count = hid_get_data_unsigned(buf, len, &sc->cont_count_loc); 526 /* 527 * "In Hybrid mode, the number of contacts that can be reported in one 528 * report is less than the maximum number of contacts that the device 529 * supports. For example, a device that supports a maximum of 530 * 4 concurrent physical contacts, can set up its top-level collection 531 * to deliver a maximum of two contacts in one report. If four contact 532 * points are present, the device can break these up into two serial 533 * reports that deliver two contacts each. 534 * 535 * "When a device delivers data in this manner, the Contact Count usage 536 * value in the first report should reflect the total number of 537 * contacts that are being delivered in the hybrid reports. The other 538 * serial reports should have a contact count of zero (0)." 539 */ 540 if (cont_count != 0) 541 sc->nconts_todo = cont_count; 542 543 #ifdef USB_DEBUG 544 DPRINTFN(6, "cont_count:%2u", (unsigned)cont_count); 545 if (wmt_debug >= 6) { 546 WMT_FOREACH_USAGE(sc->caps, usage) { 547 if (wmt_hid_map[usage].usage != WMT_NO_USAGE) 548 printf(" %-4s", wmt_hid_map[usage].name); 549 } 550 printf("\n"); 551 } 552 #endif 553 554 /* Find the number of contacts reported in current report */ 555 cont_count = MIN(sc->nconts_todo, sc->nconts_per_report); 556 557 /* Use protocol Type B for reporting events */ 558 for (cont = 0; cont < cont_count; cont++) { 559 bzero(slot_data, sizeof(sc->slot_data)); 560 WMT_FOREACH_USAGE(sc->caps, usage) { 561 if (sc->locs[cont][usage].size > 0) 562 slot_data[usage] = hid_get_data_unsigned( 563 buf, len, &sc->locs[cont][usage]); 564 } 565 566 slot = evdev_get_mt_slot_by_tracking_id(sc->evdev, 567 slot_data[WMT_CONTACTID]); 568 569 #ifdef USB_DEBUG 570 DPRINTFN(6, "cont%01x: data = ", cont); 571 if (wmt_debug >= 6) { 572 WMT_FOREACH_USAGE(sc->caps, usage) { 573 if (wmt_hid_map[usage].usage != WMT_NO_USAGE) 574 printf("%04x ", slot_data[usage]); 575 } 576 printf("slot = %d\n", (int)slot); 577 } 578 #endif 579 580 if (slot == -1) { 581 DPRINTF("Slot overflow for contact_id %u\n", 582 (unsigned)slot_data[WMT_CONTACTID]); 583 continue; 584 } 585 586 if (slot_data[WMT_TIP_SWITCH] != 0 && 587 !(isset(sc->caps, WMT_CONFIDENCE) && 588 slot_data[WMT_CONFIDENCE] == 0)) { 589 /* This finger is in proximity of the sensor */ 590 sc->touch = true; 591 slot_data[WMT_SLOT] = slot; 592 slot_data[WMT_IN_RANGE] = !slot_data[WMT_IN_RANGE]; 593 /* Divided by two to match visual scale of touch */ 594 width = slot_data[WMT_WIDTH] >> 1; 595 height = slot_data[WMT_HEIGHT] >> 1; 596 slot_data[WMT_ORIENTATION] = width > height; 597 slot_data[WMT_MAJOR] = MAX(width, height); 598 slot_data[WMT_MINOR] = MIN(width, height); 599 600 WMT_FOREACH_USAGE(sc->caps, usage) 601 if (wmt_hid_map[usage].code != WMT_NO_CODE) 602 evdev_push_abs(sc->evdev, 603 wmt_hid_map[usage].code, 604 slot_data[usage]); 605 } else { 606 evdev_push_abs(sc->evdev, ABS_MT_SLOT, slot); 607 evdev_push_abs(sc->evdev, ABS_MT_TRACKING_ID, -1); 608 } 609 } 610 611 sc->nconts_todo -= cont_count; 612 if (sc->do_timestamps && sc->nconts_todo == 0) { 613 /* HUD_SCAN_TIME is measured in 100us, convert to us. */ 614 scan_time = 615 hid_get_data_unsigned(buf, len, &sc->scan_time_loc); 616 if (sc->prev_touch) { 617 delta = scan_time - sc->scan_time; 618 if (delta < 0) 619 delta += sc->scan_time_max; 620 } else 621 delta = 0; 622 sc->scan_time = scan_time; 623 sc->timestamp += delta * 100; 624 evdev_push_msc(sc->evdev, MSC_TIMESTAMP, sc->timestamp); 625 sc->prev_touch = sc->touch; 626 sc->touch = false; 627 if (!sc->prev_touch) 628 sc->timestamp = 0; 629 } 630 if (sc->nconts_todo == 0) { 631 /* Report both the click and external left btns as BTN_LEFT */ 632 if (sc->has_int_button) 633 int_btn = hid_get_data(buf, len, &sc->int_btn_loc); 634 if (isset(sc->buttons, 0)) 635 left_btn = hid_get_data(buf, len, &sc->btn_loc[0]); 636 if (sc->has_int_button || isset(sc->buttons, 0)) 637 evdev_push_key(sc->evdev, BTN_LEFT, 638 (int_btn != 0) | (left_btn != 0)); 639 for (btn = 1; btn < sc->max_button; ++btn) { 640 if (isset(sc->buttons, btn)) 641 evdev_push_key(sc->evdev, BTN_MOUSE + btn, 642 hid_get_data(buf, 643 len, 644 &sc->btn_loc[btn]) != 0); 645 } 646 evdev_sync(sc->evdev); 647 } 648 } 649 650 static void 651 wmt_intr_callback(struct usb_xfer *xfer, usb_error_t error) 652 { 653 struct wmt_softc *sc = usbd_xfer_softc(xfer); 654 struct usb_page_cache *pc; 655 uint8_t *buf = sc->buf; 656 int len; 657 658 usbd_xfer_status(xfer, &len, NULL, NULL, NULL); 659 660 switch (USB_GET_STATE(xfer)) { 661 case USB_ST_TRANSFERRED: 662 pc = usbd_xfer_get_frame(xfer, 0); 663 664 DPRINTFN(6, "sc=%p actlen=%d\n", sc, len); 665 666 if (len >= (int)sc->report_len || 667 (len > 0 && sc->report_id != 0)) { 668 /* Limit report length to the maximum */ 669 if (len > (int)sc->report_len) 670 len = sc->report_len; 671 672 usbd_copy_out(pc, 0, buf, len); 673 674 /* Ignore irrelevant reports */ 675 if (sc->report_id && *buf != sc->report_id) 676 goto tr_ignore; 677 678 /* Make sure we don't process old data */ 679 if (len < sc->report_len) 680 bzero(buf + len, sc->report_len - len); 681 682 /* Strip leading "report ID" byte */ 683 if (sc->report_id) { 684 len--; 685 buf++; 686 } 687 688 wmt_process_report(sc, buf, len); 689 } else { 690 tr_ignore: 691 DPRINTF("Ignored transfer, %d bytes\n", len); 692 } 693 694 case USB_ST_SETUP: 695 tr_setup: 696 usbd_xfer_set_frame_len(xfer, 0, sc->isize); 697 usbd_transfer_submit(xfer); 698 break; 699 default: 700 if (error != USB_ERR_CANCELLED) { 701 /* Try clear stall first */ 702 usbd_xfer_set_stall(xfer); 703 goto tr_setup; 704 } 705 break; 706 } 707 } 708 709 static void 710 wmt_ev_close_11(struct evdev_dev *evdev, void *ev_softc) 711 { 712 struct wmt_softc *sc = ev_softc; 713 714 mtx_assert(&sc->mtx, MA_OWNED); 715 usbd_transfer_stop(sc->xfer[WMT_INTR_DT]); 716 } 717 718 static int 719 wmt_ev_open_11(struct evdev_dev *evdev, void *ev_softc) 720 { 721 struct wmt_softc *sc = ev_softc; 722 723 mtx_assert(&sc->mtx, MA_OWNED); 724 usbd_transfer_start(sc->xfer[WMT_INTR_DT]); 725 726 return (0); 727 } 728 729 #if __FreeBSD_version >= 1200077 730 static int 731 wmt_ev_close(struct evdev_dev *evdev) 732 { 733 struct wmt_softc *sc = evdev_get_softc(evdev); 734 735 wmt_ev_close_11(evdev, sc); 736 737 return (0); 738 } 739 740 static int 741 wmt_ev_open(struct evdev_dev *evdev) 742 { 743 struct wmt_softc *sc = evdev_get_softc(evdev); 744 745 return (wmt_ev_open_11(evdev, sc)); 746 747 } 748 #endif 749 750 /* port of userland hid_report_size() from usbhid(3) to kernel */ 751 static int 752 wmt_hid_report_size(const void *buf, uint16_t len, enum hid_kind k, uint8_t id) 753 { 754 struct hid_data *d; 755 struct hid_item h; 756 uint32_t temp; 757 uint32_t hpos; 758 uint32_t lpos; 759 int report_id = 0; 760 761 hpos = 0; 762 lpos = 0xFFFFFFFF; 763 764 for (d = hid_start_parse(buf, len, 1 << k); hid_get_item(d, &h);) { 765 if (h.kind == k && h.report_ID == id) { 766 /* compute minimum */ 767 if (lpos > h.loc.pos) 768 lpos = h.loc.pos; 769 /* compute end position */ 770 temp = h.loc.pos + (h.loc.size * h.loc.count); 771 /* compute maximum */ 772 if (hpos < temp) 773 hpos = temp; 774 if (h.report_ID != 0) 775 report_id = 1; 776 } 777 } 778 hid_end_parse(d); 779 780 /* safety check - can happen in case of currupt descriptors */ 781 if (lpos > hpos) 782 temp = 0; 783 else 784 temp = hpos - lpos; 785 786 /* return length in bytes rounded up */ 787 return ((temp + 7) / 8 + report_id); 788 } 789 790 static enum wmt_type 791 wmt_hid_parse(struct wmt_softc *sc, const void *d_ptr, uint16_t d_len) 792 { 793 struct hid_item hi; 794 struct hid_data *hd; 795 size_t i; 796 size_t cont = 0; 797 enum wmt_type type = WMT_TYPE_UNSUPPORTED; 798 uint32_t left_btn, btn; 799 int32_t cont_count_max = 0; 800 uint8_t report_id = 0; 801 bool touch_coll = false; 802 bool finger_coll = false; 803 bool cont_count_found = false; 804 bool scan_time_found = false; 805 bool has_int_button = false; 806 807 #define WMT_HI_ABSOLUTE(hi) \ 808 (((hi).flags & (HIO_CONST|HIO_VARIABLE|HIO_RELATIVE)) == HIO_VARIABLE) 809 #define HUMS_THQA_CERT 0xC5 810 811 /* Parse features for maximum contact count */ 812 hd = hid_start_parse(d_ptr, d_len, 1 << hid_feature); 813 while (hid_get_item(hd, &hi)) { 814 switch (hi.kind) { 815 case hid_collection: 816 if (hi.collevel == 1 && hi.usage == 817 HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCHSCREEN)) { 818 touch_coll = true; 819 type = WMT_TYPE_TOUCHSCREEN; 820 left_btn = 1; 821 break; 822 } 823 if (hi.collevel == 1 && hi.usage == 824 HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCHPAD)) { 825 touch_coll = true; 826 type = WMT_TYPE_TOUCHPAD; 827 left_btn = 2; 828 } 829 break; 830 case hid_endcollection: 831 if (hi.collevel == 0 && touch_coll) 832 touch_coll = false; 833 break; 834 case hid_feature: 835 if (hi.collevel == 1 && touch_coll && hi.usage == 836 HID_USAGE2(HUP_MICROSOFT, HUMS_THQA_CERT)) { 837 sc->thqa_cert_rid = hi.report_ID; 838 break; 839 } 840 if (hi.collevel == 1 && touch_coll && hi.usage == 841 HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACT_MAX)) { 842 cont_count_max = hi.logical_maximum; 843 sc->cont_max_rid = hi.report_ID; 844 sc->cont_max_loc = hi.loc; 845 break; 846 } 847 if (hi.collevel == 1 && touch_coll && hi.usage == 848 HID_USAGE2(HUP_DIGITIZERS, HUD_BUTTON_TYPE)) { 849 sc->btn_type_rid = hi.report_ID; 850 sc->btn_type_loc = hi.loc; 851 } 852 break; 853 default: 854 break; 855 } 856 } 857 hid_end_parse(hd); 858 859 if (type == WMT_TYPE_UNSUPPORTED) 860 return (WMT_TYPE_UNSUPPORTED); 861 /* Maximum contact count is required usage */ 862 if (sc->cont_max_rid == 0) 863 return (WMT_TYPE_UNSUPPORTED); 864 865 touch_coll = false; 866 867 /* Parse input for other parameters */ 868 hd = hid_start_parse(d_ptr, d_len, 1 << hid_input); 869 while (hid_get_item(hd, &hi)) { 870 switch (hi.kind) { 871 case hid_collection: 872 if (hi.collevel == 1 && hi.usage == 873 HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCHSCREEN)) 874 touch_coll = true; 875 else if (touch_coll && hi.collevel == 2 && 876 (report_id == 0 || report_id == hi.report_ID) && 877 hi.usage == HID_USAGE2(HUP_DIGITIZERS, HUD_FINGER)) 878 finger_coll = true; 879 break; 880 case hid_endcollection: 881 if (hi.collevel == 1 && finger_coll) { 882 finger_coll = false; 883 cont++; 884 } else if (hi.collevel == 0 && touch_coll) 885 touch_coll = false; 886 break; 887 case hid_input: 888 /* 889 * Ensure that all usages are located within the same 890 * report and proper collection. 891 */ 892 if (WMT_HI_ABSOLUTE(hi) && touch_coll && 893 (report_id == 0 || report_id == hi.report_ID)) 894 report_id = hi.report_ID; 895 else 896 break; 897 898 if (hi.collevel == 1 && left_btn == 2 && 899 hi.usage == HID_USAGE2(HUP_BUTTON, 1)) { 900 has_int_button = true; 901 sc->int_btn_loc = hi.loc; 902 break; 903 } 904 if (hi.collevel == 1 && 905 hi.usage >= HID_USAGE2(HUP_BUTTON, left_btn) && 906 hi.usage <= HID_USAGE2(HUP_BUTTON, WMT_BTN_MAX)) { 907 btn = (hi.usage & 0xFFFF) - left_btn; 908 setbit(sc->buttons, btn); 909 sc->btn_loc[btn] = hi.loc; 910 if (btn >= sc->max_button) 911 sc->max_button = btn + 1; 912 break; 913 } 914 if (hi.collevel == 1 && hi.usage == 915 HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACTCOUNT)) { 916 cont_count_found = true; 917 sc->cont_count_loc = hi.loc; 918 break; 919 } 920 /* Scan time is required but clobbered by evdev */ 921 if (hi.collevel == 1 && hi.usage == 922 HID_USAGE2(HUP_DIGITIZERS, HUD_SCAN_TIME)) { 923 scan_time_found = true; 924 sc->scan_time_loc = hi.loc; 925 sc->scan_time_max = hi.logical_maximum; 926 break; 927 } 928 929 if (!finger_coll || hi.collevel != 2) 930 break; 931 if (cont >= MAX_MT_SLOTS) { 932 DPRINTF("Finger %zu ignored\n", cont); 933 break; 934 } 935 936 for (i = 0; i < WMT_N_USAGES; i++) { 937 if (hi.usage == wmt_hid_map[i].usage) { 938 /* 939 * HUG_X usage is an array mapped to 940 * both ABS_MT_POSITION and ABS_MT_TOOL 941 * events. So don`t stop search if we 942 * already have HUG_X mapping done. 943 */ 944 if (sc->locs[cont][i].size) 945 continue; 946 sc->locs[cont][i] = hi.loc; 947 /* 948 * Hid parser returns valid logical and 949 * physical sizes for first finger only 950 * at least on ElanTS 0x04f3:0x0012. 951 */ 952 if (cont > 0) 953 break; 954 setbit(sc->caps, i); 955 sc->ai[i] = (struct wmt_absinfo) { 956 .max = hi.logical_maximum, 957 .min = hi.logical_minimum, 958 .res = hid_item_resolution(&hi), 959 }; 960 break; 961 } 962 } 963 break; 964 default: 965 break; 966 } 967 } 968 hid_end_parse(hd); 969 970 /* Check for required HID Usages */ 971 if (!cont_count_found || !scan_time_found || cont == 0) 972 return (WMT_TYPE_UNSUPPORTED); 973 for (i = 0; i < WMT_N_USAGES; i++) { 974 if (wmt_hid_map[i].required && isclr(sc->caps, i)) 975 return (WMT_TYPE_UNSUPPORTED); 976 } 977 978 /* Touchpads must have at least one button */ 979 if (type == WMT_TYPE_TOUCHPAD && !sc->max_button && !has_int_button) 980 return (WMT_TYPE_UNSUPPORTED); 981 982 /* 983 * According to specifications 'Contact Count Maximum' should be read 984 * from Feature Report rather than from HID descriptor. Set sane 985 * default value now to handle the case of 'Get Report' request failure 986 */ 987 if (cont_count_max < 1) 988 cont_count_max = cont; 989 990 /* Set number of MT protocol type B slots */ 991 sc->ai[WMT_SLOT] = (struct wmt_absinfo) { 992 .min = 0, 993 .max = cont_count_max - 1, 994 .res = 0, 995 }; 996 997 /* Report touch orientation if both width and height are supported */ 998 if (isset(sc->caps, WMT_WIDTH) && isset(sc->caps, WMT_HEIGHT)) { 999 setbit(sc->caps, WMT_ORIENTATION); 1000 sc->ai[WMT_ORIENTATION].max = 1; 1001 } 1002 1003 sc->isize = hid_report_size(d_ptr, d_len, hid_input, NULL); 1004 sc->report_len = wmt_hid_report_size(d_ptr, d_len, hid_input, 1005 report_id); 1006 sc->cont_max_rlen = wmt_hid_report_size(d_ptr, d_len, hid_feature, 1007 sc->cont_max_rid); 1008 if (sc->btn_type_rid > 0) 1009 sc->btn_type_rlen = wmt_hid_report_size(d_ptr, d_len, 1010 hid_feature, sc->btn_type_rid); 1011 if (sc->thqa_cert_rid > 0) 1012 sc->thqa_cert_rlen = wmt_hid_report_size(d_ptr, d_len, 1013 hid_feature, sc->thqa_cert_rid); 1014 1015 sc->report_id = report_id; 1016 sc->nconts_per_report = cont; 1017 sc->has_int_button = has_int_button; 1018 1019 return (type); 1020 } 1021 1022 static int 1023 wmt_set_input_mode(struct wmt_softc *sc, enum wmt_input_mode mode) 1024 { 1025 struct usb_attach_arg *uaa = device_get_ivars(sc->dev); 1026 int err; 1027 1028 if (sc->input_mode_rlen < 3 || sc->input_mode_rlen > WMT_BSIZE) { 1029 DPRINTF("Feature report %hhu size invalid or too large: %u\n", 1030 sc->input_mode_rid, sc->input_mode_rlen); 1031 return (USB_ERR_BAD_BUFSIZE); 1032 } 1033 1034 /* Input Mode report is not strictly required to be readable */ 1035 err = usbd_req_get_report(uaa->device, NULL, sc->buf, 1036 sc->input_mode_rlen, uaa->info.bIfaceIndex, 1037 UHID_FEATURE_REPORT, sc->input_mode_rid); 1038 if (err != USB_ERR_NORMAL_COMPLETION) 1039 bzero(sc->buf + 1, sc->input_mode_rlen - 1); 1040 1041 sc->buf[0] = sc->input_mode_rid; 1042 hid_put_data_unsigned(sc->buf + 1, sc->input_mode_rlen - 1, 1043 &sc->input_mode_loc, mode); 1044 err = usbd_req_set_report(uaa->device, NULL, sc->buf, 1045 sc->input_mode_rlen, uaa->info.bIfaceIndex, 1046 UHID_FEATURE_REPORT, sc->input_mode_rid); 1047 1048 return (err); 1049 } 1050 1051 static const STRUCT_USB_HOST_ID wmt_devs[] = { 1052 /* generic HID class w/o boot interface */ 1053 {USB_IFACE_CLASS(UICLASS_HID), 1054 USB_IFACE_SUBCLASS(0),}, 1055 }; 1056 1057 static devclass_t wmt_devclass; 1058 1059 static device_method_t wmt_methods[] = { 1060 DEVMETHOD(device_probe, wmt_probe), 1061 DEVMETHOD(device_attach, wmt_attach), 1062 DEVMETHOD(device_detach, wmt_detach), 1063 1064 DEVMETHOD_END 1065 }; 1066 1067 static driver_t wmt_driver = { 1068 .name = "wmt", 1069 .methods = wmt_methods, 1070 .size = sizeof(struct wmt_softc), 1071 }; 1072 1073 DRIVER_MODULE(wmt, uhub, wmt_driver, wmt_devclass, NULL, 0); 1074 MODULE_DEPEND(wmt, usb, 1, 1, 1); 1075 MODULE_DEPEND(wmt, evdev, 1, 1, 1); 1076 MODULE_VERSION(wmt, 1); 1077 USB_PNP_HOST_INFO(wmt_devs); 1078