1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 /* 32 * Abstract 1 to 1 HID input usage to evdev event mapper driver. 33 */ 34 35 #include "opt_hid.h" 36 37 #include <sys/param.h> 38 #include <sys/bus.h> 39 #include <sys/kernel.h> 40 #include <sys/lock.h> 41 #include <sys/malloc.h> 42 #include <sys/module.h> 43 #include <sys/sysctl.h> 44 #include <sys/systm.h> 45 46 #include <dev/evdev/input.h> 47 #include <dev/evdev/evdev.h> 48 49 #include <dev/hid/hid.h> 50 #include <dev/hid/hidbus.h> 51 #include <dev/hid/hidmap.h> 52 53 #ifdef HID_DEBUG 54 #define DPRINTFN(hm, n, fmt, ...) do { \ 55 if ((hm)->debug_var != NULL && *(hm)->debug_var >= (n)) { \ 56 device_printf((hm)->dev, "%s: " fmt, \ 57 __FUNCTION__ ,##__VA_ARGS__); \ 58 } \ 59 } while (0) 60 #define DPRINTF(hm, ...) DPRINTFN(hm, 1, __VA_ARGS__) 61 #else 62 #define DPRINTF(...) do { } while (0) 63 #define DPRINTFN(...) do { } while (0) 64 #endif 65 66 static evdev_open_t hidmap_ev_open; 67 static evdev_close_t hidmap_ev_close; 68 69 #define HIDMAP_WANT_MERGE_KEYS(hm) ((hm)->key_rel != NULL) 70 71 #define HIDMAP_FOREACH_ITEM(hm, mi, uoff) \ 72 for (u_int _map = 0, _item = 0, _uoff_priv = -1; \ 73 ((mi) = hidmap_get_next_map_item( \ 74 (hm), &_map, &_item, &_uoff_priv, &(uoff))) != NULL;) 75 76 static inline bool 77 hidmap_get_next_map_index(const struct hidmap_item *map, int nmap_items, 78 uint32_t *index, uint16_t *usage_offset) 79 { 80 81 ++*usage_offset; 82 if ((*index != 0 || *usage_offset != 0) && 83 *usage_offset >= map[*index].nusages) { 84 ++*index; 85 *usage_offset = 0; 86 } 87 88 return (*index < nmap_items); 89 } 90 91 static inline const struct hidmap_item * 92 hidmap_get_next_map_item(struct hidmap *hm, u_int *map, u_int *item, 93 u_int *uoff_priv, uint16_t *uoff) 94 { 95 96 *uoff = *uoff_priv; 97 while (!hidmap_get_next_map_index( 98 hm->map[*map], hm->nmap_items[*map], item, uoff)) { 99 ++*map; 100 *item = 0; 101 *uoff = -1; 102 if (*map >= hm->nmaps) 103 return (NULL); 104 } 105 *uoff_priv = *uoff; 106 107 return (hm->map[*map] + *item); 108 } 109 110 void 111 _hidmap_set_debug_var(struct hidmap *hm, int *debug_var) 112 { 113 #ifdef HID_DEBUG 114 hm->debug_var = debug_var; 115 #endif 116 } 117 118 static int 119 hidmap_ev_close(struct evdev_dev *evdev) 120 { 121 return (hidbus_intr_stop(evdev_get_softc(evdev))); 122 } 123 124 static int 125 hidmap_ev_open(struct evdev_dev *evdev) 126 { 127 return (hidbus_intr_start(evdev_get_softc(evdev))); 128 } 129 130 void 131 hidmap_support_key(struct hidmap *hm, uint16_t key) 132 { 133 if (hm->key_press == NULL) { 134 hm->key_press = malloc(howmany(KEY_CNT, 8), M_DEVBUF, 135 M_ZERO | M_WAITOK); 136 evdev_support_event(hm->evdev, EV_KEY); 137 hm->key_min = key; 138 hm->key_max = key; 139 } 140 hm->key_min = MIN(hm->key_min, key); 141 hm->key_max = MAX(hm->key_max, key); 142 if (isset(hm->key_press, key)) { 143 if (hm->key_rel == NULL) 144 hm->key_rel = malloc(howmany(KEY_CNT, 8), M_DEVBUF, 145 M_ZERO | M_WAITOK); 146 } else { 147 setbit(hm->key_press, key); 148 evdev_support_key(hm->evdev, key); 149 } 150 } 151 152 void 153 hidmap_push_key(struct hidmap *hm, uint16_t key, int32_t value) 154 { 155 if (HIDMAP_WANT_MERGE_KEYS(hm)) 156 setbit(value != 0 ? hm->key_press : hm->key_rel, key); 157 else 158 evdev_push_key(hm->evdev, key, value); 159 } 160 161 static void 162 hidmap_sync_keys(struct hidmap *hm) 163 { 164 int i, j; 165 bool press, rel; 166 167 for (j = hm->key_min / 8; j <= hm->key_max / 8; j++) { 168 if (hm->key_press[j] != hm->key_rel[j]) { 169 for (i = j * 8; i < j * 8 + 8; i++) { 170 press = isset(hm->key_press, i); 171 rel = isset(hm->key_rel, i); 172 if (press != rel) 173 evdev_push_key(hm->evdev, i, press); 174 } 175 } 176 } 177 bzero(hm->key_press, howmany(KEY_CNT, 8)); 178 bzero(hm->key_rel, howmany(KEY_CNT, 8)); 179 } 180 181 void 182 hidmap_intr(void *context, void *buf, hid_size_t len) 183 { 184 struct hidmap *hm = context; 185 struct hidmap_hid_item *hi; 186 const struct hidmap_item *mi; 187 int32_t usage; 188 int32_t data; 189 uint16_t key, uoff; 190 uint8_t id = 0; 191 bool found, do_sync = false; 192 193 DPRINTFN(hm, 6, "hm=%p len=%d\n", hm, len); 194 DPRINTFN(hm, 6, "data = %*D\n", len, buf, " "); 195 196 /* Strip leading "report ID" byte */ 197 if (hm->hid_items[0].id) { 198 id = *(uint8_t *)buf; 199 len--; 200 buf = (uint8_t *)buf + 1; 201 } 202 203 hm->intr_buf = buf; 204 hm->intr_len = len; 205 206 for (hi = hm->hid_items; hi < hm->hid_items + hm->nhid_items; hi++) { 207 /* At first run callbacks that not tied to HID items */ 208 if (hi->type == HIDMAP_TYPE_FINALCB) { 209 DPRINTFN(hm, 6, "type=%d item=%*D\n", hi->type, 210 (int)sizeof(hi->cb), &hi->cb, " "); 211 if (hi->cb(hm, hi, (union hidmap_cb_ctx){.rid = id}) 212 == 0) 213 do_sync = true; 214 continue; 215 } 216 217 /* Ignore irrelevant reports */ 218 if (id != hi->id) 219 continue; 220 221 /* 222 * 5.8. If Logical Minimum and Logical Maximum are both 223 * positive values then the contents of a field can be assumed 224 * to be an unsigned value. Otherwise, all integer values are 225 * signed values represented in 2’s complement format. 226 */ 227 data = hi->lmin < 0 || hi->lmax < 0 228 ? hid_get_data(buf, len, &hi->loc) 229 : hid_get_udata(buf, len, &hi->loc); 230 231 DPRINTFN(hm, 6, "type=%d data=%d item=%*D\n", hi->type, data, 232 (int)sizeof(hi->cb), &hi->cb, " "); 233 234 if (hi->invert_value && hi->type < HIDMAP_TYPE_ARR_LIST) 235 data = hi->evtype == EV_REL 236 ? -data 237 : hi->lmin + hi->lmax - data; 238 239 switch (hi->type) { 240 case HIDMAP_TYPE_CALLBACK: 241 if (hi->cb(hm, hi, (union hidmap_cb_ctx){.data = data}) 242 != 0) 243 continue; 244 break; 245 246 case HIDMAP_TYPE_VAR_NULLST: 247 /* 248 * 5.10. If the host or the device receives an 249 * out-of-range value then the current value for the 250 * respective control will not be modified. 251 */ 252 if (data < hi->lmin || data > hi->lmax) 253 continue; 254 /* FALLTHROUGH */ 255 case HIDMAP_TYPE_VARIABLE: 256 /* 257 * Ignore reports for absolute data if the data did not 258 * change and for relative data if data is 0. 259 * Evdev layer filters out them anyway. 260 */ 261 if (data == (hi->evtype == EV_REL ? 0 : hi->last_val)) 262 continue; 263 if (hi->evtype == EV_KEY) 264 hidmap_push_key(hm, hi->code, data); 265 else 266 evdev_push_event(hm->evdev, hi->evtype, 267 hi->code, data); 268 hi->last_val = data; 269 break; 270 271 case HIDMAP_TYPE_ARR_LIST: 272 key = KEY_RESERVED; 273 /* 274 * 6.2.2.5. An out-of range value in an array field 275 * is considered no controls asserted. 276 */ 277 if (data < hi->lmin || data > hi->lmax) 278 goto report_key; 279 /* 280 * 6.2.2.5. Rather than returning a single bit for each 281 * button in the group, an array returns an index in 282 * each field that corresponds to the pressed button. 283 */ 284 key = hi->codes[data - hi->lmin]; 285 if (key == KEY_RESERVED) 286 DPRINTF(hm, "Can not map unknown HID " 287 "array index: %08x\n", data); 288 goto report_key; 289 290 case HIDMAP_TYPE_ARR_RANGE: 291 key = KEY_RESERVED; 292 /* 293 * 6.2.2.5. An out-of range value in an array field 294 * is considered no controls asserted. 295 */ 296 if (data < hi->lmin || data > hi->lmax) 297 goto report_key; 298 /* 299 * When the input field is an array and the usage is 300 * specified with a range instead of an ID, we have to 301 * derive the actual usage by using the item value as 302 * an index in the usage range list. 303 */ 304 usage = data - hi->lmin + hi->umin; 305 found = false; 306 HIDMAP_FOREACH_ITEM(hm, mi, uoff) { 307 if (usage == mi->usage + uoff && 308 mi->type == EV_KEY && !mi->has_cb) { 309 key = mi->code; 310 found = true; 311 break; 312 } 313 } 314 if (!found) 315 DPRINTF(hm, "Can not map unknown HID " 316 "usage: %08x\n", usage); 317 report_key: 318 if (key == HIDMAP_KEY_NULL || key == hi->last_key) 319 continue; 320 if (hi->last_key != KEY_RESERVED) 321 hidmap_push_key(hm, hi->last_key, 0); 322 if (key != KEY_RESERVED) 323 hidmap_push_key(hm, key, 1); 324 hi->last_key = key; 325 break; 326 327 default: 328 KASSERT(0, ("Unknown map type (%d)", hi->type)); 329 } 330 do_sync = true; 331 } 332 333 if (do_sync) { 334 if (HIDMAP_WANT_MERGE_KEYS(hm)) 335 hidmap_sync_keys(hm); 336 evdev_sync(hm->evdev); 337 } 338 } 339 340 static inline bool 341 can_map_callback(struct hid_item *hi, const struct hidmap_item *mi, 342 uint16_t usage_offset) 343 { 344 345 return (mi->has_cb && !mi->final_cb && 346 hi->usage == mi->usage + usage_offset && 347 (mi->relabs == HIDMAP_RELABS_ANY || 348 !(hi->flags & HIO_RELATIVE) == !(mi->relabs == HIDMAP_RELATIVE))); 349 } 350 351 static inline bool 352 can_map_variable(struct hid_item *hi, const struct hidmap_item *mi, 353 uint16_t usage_offset) 354 { 355 356 return ((hi->flags & HIO_VARIABLE) != 0 && !mi->has_cb && 357 hi->usage == mi->usage + usage_offset && 358 (mi->relabs == HIDMAP_RELABS_ANY || 359 !(hi->flags & HIO_RELATIVE) == !(mi->relabs == HIDMAP_RELATIVE))); 360 } 361 362 static inline bool 363 can_map_arr_range(struct hid_item *hi, const struct hidmap_item *mi, 364 uint16_t usage_offset) 365 { 366 367 return ((hi->flags & HIO_VARIABLE) == 0 && !mi->has_cb && 368 hi->usage_minimum <= mi->usage + usage_offset && 369 hi->usage_maximum >= mi->usage + usage_offset && 370 mi->type == EV_KEY && 371 (mi->code != KEY_RESERVED && mi->code != HIDMAP_KEY_NULL)); 372 } 373 374 static inline bool 375 can_map_arr_list(struct hid_item *hi, const struct hidmap_item *mi, 376 uint32_t usage, uint16_t usage_offset) 377 { 378 379 return ((hi->flags & HIO_VARIABLE) == 0 && !mi->has_cb && 380 usage == mi->usage + usage_offset && 381 mi->type == EV_KEY && 382 (mi->code != KEY_RESERVED && mi->code != HIDMAP_KEY_NULL)); 383 } 384 385 static bool 386 hidmap_probe_hid_item(struct hid_item *hi, const struct hidmap_item *map, 387 int nitems_map, hidmap_caps_t caps) 388 { 389 u_int i, j; 390 uint16_t uoff; 391 bool found = false; 392 393 #define HIDMAP_FOREACH_INDEX(map, nitems, idx, uoff) \ 394 for ((idx) = 0, (uoff) = -1; \ 395 hidmap_get_next_map_index((map), (nitems), &(idx), &(uoff));) 396 397 HIDMAP_FOREACH_INDEX(map, nitems_map, i, uoff) { 398 if (can_map_callback(hi, map + i, uoff)) { 399 if (map[i].cb(NULL, NULL, 400 (union hidmap_cb_ctx){.hi = hi}) != 0) 401 break; 402 setbit(caps, i); 403 return (true); 404 } 405 } 406 407 if (hi->flags & HIO_VARIABLE) { 408 HIDMAP_FOREACH_INDEX(map, nitems_map, i, uoff) { 409 if (can_map_variable(hi, map + i, uoff)) { 410 KASSERT(map[i].type == EV_KEY || 411 map[i].type == EV_REL || 412 map[i].type == EV_ABS || 413 map[i].type == EV_SW, 414 ("Unsupported event type")); 415 setbit(caps, i); 416 return (true); 417 } 418 } 419 return (false); 420 } 421 422 if (hi->usage_minimum != 0 || hi->usage_maximum != 0) { 423 HIDMAP_FOREACH_INDEX(map, nitems_map, i, uoff) { 424 if (can_map_arr_range(hi, map + i, uoff)) { 425 setbit(caps, i); 426 found = true; 427 } 428 } 429 return (found); 430 } 431 432 for (j = 0; j < hi->nusages; j++) { 433 HIDMAP_FOREACH_INDEX(map, nitems_map, i, uoff) { 434 if (can_map_arr_list(hi, map+i, hi->usages[j], uoff)) { 435 setbit(caps, i); 436 found = true; 437 } 438 } 439 } 440 441 return (found); 442 } 443 444 static uint32_t 445 hidmap_probe_hid_descr(void *d_ptr, hid_size_t d_len, uint8_t tlc_index, 446 const struct hidmap_item *map, int nitems_map, hidmap_caps_t caps) 447 { 448 struct hid_data *hd; 449 struct hid_item hi; 450 uint32_t i, items = 0; 451 bool do_free = false; 452 453 if (caps == NULL) { 454 caps = malloc(HIDMAP_CAPS_SZ(nitems_map), M_DEVBUF, 455 M_WAITOK | M_ZERO); 456 do_free = true; 457 } else 458 bzero (caps, HIDMAP_CAPS_SZ(nitems_map)); 459 460 /* Parse inputs */ 461 hd = hid_start_parse(d_ptr, d_len, 1 << hid_input); 462 HIDBUS_FOREACH_ITEM(hd, &hi, tlc_index) { 463 if (hi.kind != hid_input) 464 continue; 465 if (hi.flags & HIO_CONST) 466 continue; 467 for (i = 0; i < hi.loc.count; i++, hi.loc.pos += hi.loc.size) 468 if (hidmap_probe_hid_item(&hi, map, nitems_map, caps)) 469 items++; 470 } 471 hid_end_parse(hd); 472 473 /* Take finalizing callbacks in to account */ 474 for (i = 0; i < nitems_map; i++) { 475 if (map[i].has_cb && map[i].final_cb && 476 map[i].cb(NULL, NULL, (union hidmap_cb_ctx){}) == 0) { 477 setbit(caps, i); 478 items++; 479 } 480 } 481 482 /* Check that all mandatory usages are present in report descriptor */ 483 if (items != 0) { 484 for (i = 0; i < nitems_map; i++) { 485 KASSERT(!(map[i].required && map[i].forbidden), 486 ("both required & forbidden item flags are set")); 487 if ((map[i].required && isclr(caps, i)) || 488 (map[i].forbidden && isset(caps, i))) { 489 items = 0; 490 break; 491 } 492 } 493 } 494 495 if (do_free) 496 free(caps, M_DEVBUF); 497 498 return (items); 499 } 500 501 uint32_t 502 hidmap_add_map(struct hidmap *hm, const struct hidmap_item *map, 503 int nitems_map, hidmap_caps_t caps) 504 { 505 void *d_ptr; 506 uint32_t items; 507 int i, error; 508 hid_size_t d_len; 509 uint8_t tlc_index = hidbus_get_index(hm->dev); 510 511 /* Avoid double-adding of map in probe() handler */ 512 for (i = 0; i < hm->nmaps; i++) 513 if (hm->map[i] == map) 514 return (0); 515 516 error = hid_get_report_descr(hm->dev, &d_ptr, &d_len); 517 if (error != 0) { 518 device_printf(hm->dev, "could not retrieve report descriptor " 519 "from device: %d\n", error); 520 return (error); 521 } 522 523 hm->cb_state = HIDMAP_CB_IS_PROBING; 524 items = hidmap_probe_hid_descr(d_ptr, d_len, tlc_index, map, 525 nitems_map, caps); 526 if (items == 0) 527 return (ENXIO); 528 529 KASSERT(hm->nmaps < HIDMAP_MAX_MAPS, 530 ("Not more than %d maps is supported", HIDMAP_MAX_MAPS)); 531 hm->nhid_items += items; 532 hm->map[hm->nmaps] = map; 533 hm->nmap_items[hm->nmaps] = nitems_map; 534 hm->nmaps++; 535 536 return (0); 537 } 538 539 static bool 540 hidmap_parse_hid_item(struct hidmap *hm, struct hid_item *hi, 541 struct hidmap_hid_item *item) 542 { 543 const struct hidmap_item *mi; 544 struct hidmap_hid_item hi_temp; 545 uint32_t i; 546 uint16_t uoff; 547 bool found = false; 548 549 HIDMAP_FOREACH_ITEM(hm, mi, uoff) { 550 if (can_map_callback(hi, mi, uoff)) { 551 bzero(&hi_temp, sizeof(hi_temp)); 552 hi_temp.cb = mi->cb; 553 hi_temp.type = HIDMAP_TYPE_CALLBACK; 554 /* 555 * Values returned by probe- and attach-stage 556 * callbacks MUST be identical. 557 */ 558 if (mi->cb(hm, &hi_temp, 559 (union hidmap_cb_ctx){.hi = hi}) != 0) 560 break; 561 bcopy(&hi_temp, item, sizeof(hi_temp)); 562 goto mapped; 563 } 564 } 565 566 if (hi->flags & HIO_VARIABLE) { 567 HIDMAP_FOREACH_ITEM(hm, mi, uoff) { 568 if (can_map_variable(hi, mi, uoff)) { 569 item->evtype = mi->type; 570 item->code = mi->code + uoff; 571 item->type = hi->flags & HIO_NULLSTATE 572 ? HIDMAP_TYPE_VAR_NULLST 573 : HIDMAP_TYPE_VARIABLE; 574 item->last_val = 0; 575 item->invert_value = mi->invert_value; 576 switch (mi->type) { 577 case EV_KEY: 578 hidmap_support_key(hm, item->code); 579 break; 580 case EV_REL: 581 evdev_support_event(hm->evdev, EV_REL); 582 evdev_support_rel(hm->evdev, 583 item->code); 584 break; 585 case EV_ABS: 586 evdev_support_event(hm->evdev, EV_ABS); 587 evdev_support_abs(hm->evdev, 588 item->code, 589 hi->logical_minimum, 590 hi->logical_maximum, 591 mi->fuzz, 592 mi->flat, 593 hid_item_resolution(hi)); 594 break; 595 case EV_SW: 596 evdev_support_event(hm->evdev, EV_SW); 597 evdev_support_sw(hm->evdev, 598 item->code); 599 break; 600 default: 601 KASSERT(0, ("Unsupported event type")); 602 } 603 goto mapped; 604 } 605 } 606 return (false); 607 } 608 609 if (hi->usage_minimum != 0 || hi->usage_maximum != 0) { 610 HIDMAP_FOREACH_ITEM(hm, mi, uoff) { 611 if (can_map_arr_range(hi, mi, uoff)) { 612 hidmap_support_key(hm, mi->code + uoff); 613 found = true; 614 } 615 } 616 if (!found) 617 return (false); 618 item->umin = hi->usage_minimum; 619 item->type = HIDMAP_TYPE_ARR_RANGE; 620 item->last_key = KEY_RESERVED; 621 goto mapped; 622 } 623 624 for (i = 0; i < hi->nusages; i++) { 625 HIDMAP_FOREACH_ITEM(hm, mi, uoff) { 626 if (can_map_arr_list(hi, mi, hi->usages[i], uoff)) { 627 hidmap_support_key(hm, mi->code + uoff); 628 if (item->codes == NULL) 629 item->codes = malloc( 630 hi->nusages * sizeof(uint16_t), 631 M_DEVBUF, M_WAITOK | M_ZERO); 632 item->codes[i] = mi->code + uoff; 633 found = true; 634 break; 635 } 636 } 637 } 638 if (!found) 639 return (false); 640 item->type = HIDMAP_TYPE_ARR_LIST; 641 item->last_key = KEY_RESERVED; 642 643 mapped: 644 item->id = hi->report_ID; 645 item->loc = hi->loc; 646 item->loc.count = 1; 647 item->lmin = hi->logical_minimum; 648 item->lmax = hi->logical_maximum; 649 650 DPRINTFN(hm, 6, "usage=%04x id=%d loc=%u/%u type=%d item=%*D\n", 651 hi->usage, hi->report_ID, hi->loc.pos, hi->loc.size, item->type, 652 (int)sizeof(item->cb), &item->cb, " "); 653 654 return (true); 655 } 656 657 static int 658 hidmap_parse_hid_descr(struct hidmap *hm, uint8_t tlc_index) 659 { 660 const struct hidmap_item *map; 661 struct hidmap_hid_item *item = hm->hid_items; 662 void *d_ptr; 663 struct hid_data *hd; 664 struct hid_item hi; 665 int i, error; 666 hid_size_t d_len; 667 668 error = hid_get_report_descr(hm->dev, &d_ptr, &d_len); 669 if (error != 0) { 670 DPRINTF(hm, "could not retrieve report descriptor from " 671 "device: %d\n", error); 672 return (error); 673 } 674 675 /* Parse inputs */ 676 hd = hid_start_parse(d_ptr, d_len, 1 << hid_input); 677 HIDBUS_FOREACH_ITEM(hd, &hi, tlc_index) { 678 if (hi.kind != hid_input) 679 continue; 680 if (hi.flags & HIO_CONST) 681 continue; 682 for (i = 0; i < hi.loc.count; i++, hi.loc.pos += hi.loc.size) 683 if (hidmap_parse_hid_item(hm, &hi, item)) 684 item++; 685 KASSERT(item <= hm->hid_items + hm->nhid_items, 686 ("Parsed HID item array overflow")); 687 } 688 hid_end_parse(hd); 689 690 /* Add finalizing callbacks to the end of list */ 691 for (i = 0; i < hm->nmaps; i++) { 692 for (map = hm->map[i]; 693 map < hm->map[i] + hm->nmap_items[i]; 694 map++) { 695 if (map->has_cb && map->final_cb && 696 map->cb(hm, item, (union hidmap_cb_ctx){}) == 0) { 697 item->cb = map->cb; 698 item->type = HIDMAP_TYPE_FINALCB; 699 item++; 700 } 701 } 702 } 703 704 /* 705 * Resulting number of parsed HID items can be less than expected as 706 * map items might be duplicated in different maps. Save real number. 707 */ 708 if (hm->nhid_items != item - hm->hid_items) 709 DPRINTF(hm, "Parsed HID item number mismatch: expected=%u " 710 "result=%td\n", hm->nhid_items, item - hm->hid_items); 711 hm->nhid_items = item - hm->hid_items; 712 713 if (HIDMAP_WANT_MERGE_KEYS(hm)) 714 bzero(hm->key_press, howmany(KEY_CNT, 8)); 715 716 return (0); 717 } 718 719 int 720 hidmap_probe(struct hidmap* hm, device_t dev, 721 const struct hid_device_id *id, int nitems_id, 722 const struct hidmap_item *map, int nitems_map, 723 const char *suffix, hidmap_caps_t caps) 724 { 725 int error; 726 727 error = hidbus_lookup_driver_info(dev, id, nitems_id); 728 if (error != 0) 729 return (error); 730 731 hidmap_set_dev(hm, dev); 732 733 error = hidmap_add_map(hm, map, nitems_map, caps); 734 if (error != 0) 735 return (error); 736 737 hidbus_set_desc(dev, suffix); 738 739 return (BUS_PROBE_DEFAULT); 740 } 741 742 int 743 hidmap_attach(struct hidmap* hm) 744 { 745 const struct hid_device_info *hw = hid_get_device_info(hm->dev); 746 #ifdef HID_DEBUG 747 char tunable[40]; 748 #endif 749 int error; 750 751 #ifdef HID_DEBUG 752 if (hm->debug_var == NULL) { 753 hm->debug_var = &hm->debug_level; 754 snprintf(tunable, sizeof(tunable), "hw.hid.%s.debug", 755 device_get_name(hm->dev)); 756 TUNABLE_INT_FETCH(tunable, &hm->debug_level); 757 SYSCTL_ADD_INT(device_get_sysctl_ctx(hm->dev), 758 SYSCTL_CHILDREN(device_get_sysctl_tree(hm->dev)), 759 OID_AUTO, "debug", CTLFLAG_RWTUN, 760 &hm->debug_level, 0, "Verbosity level"); 761 } 762 #endif 763 764 DPRINTFN(hm, 11, "hm=%p\n", hm); 765 766 hm->cb_state = HIDMAP_CB_IS_ATTACHING; 767 768 hm->hid_items = malloc(hm->nhid_items * sizeof(struct hid_item), 769 M_DEVBUF, M_WAITOK | M_ZERO); 770 771 hidbus_set_intr(hm->dev, hidmap_intr, hm); 772 hm->evdev_methods = (struct evdev_methods) { 773 .ev_open = &hidmap_ev_open, 774 .ev_close = &hidmap_ev_close, 775 }; 776 777 hm->evdev = evdev_alloc(); 778 evdev_set_name(hm->evdev, device_get_desc(hm->dev)); 779 evdev_set_phys(hm->evdev, device_get_nameunit(hm->dev)); 780 evdev_set_id(hm->evdev, hw->idBus, hw->idVendor, hw->idProduct, 781 hw->idVersion); 782 evdev_set_serial(hm->evdev, hw->serial); 783 evdev_set_flag(hm->evdev, EVDEV_FLAG_EXT_EPOCH); /* hidbus child */ 784 evdev_support_event(hm->evdev, EV_SYN); 785 error = hidmap_parse_hid_descr(hm, hidbus_get_index(hm->dev)); 786 if (error) { 787 DPRINTF(hm, "error=%d\n", error); 788 hidmap_detach(hm); 789 return (ENXIO); 790 } 791 792 evdev_set_methods(hm->evdev, hm->dev, &hm->evdev_methods); 793 hm->cb_state = HIDMAP_CB_IS_RUNNING; 794 795 error = evdev_register(hm->evdev); 796 if (error) { 797 DPRINTF(hm, "error=%d\n", error); 798 hidmap_detach(hm); 799 return (ENXIO); 800 } 801 802 return (0); 803 } 804 805 int 806 hidmap_detach(struct hidmap* hm) 807 { 808 struct hidmap_hid_item *hi; 809 810 DPRINTFN(hm, 11, "\n"); 811 812 hm->cb_state = HIDMAP_CB_IS_DETACHING; 813 814 evdev_free(hm->evdev); 815 if (hm->hid_items != NULL) { 816 for (hi = hm->hid_items; 817 hi < hm->hid_items + hm->nhid_items; 818 hi++) 819 if (hi->type == HIDMAP_TYPE_FINALCB || 820 hi->type == HIDMAP_TYPE_CALLBACK) 821 hi->cb(hm, hi, (union hidmap_cb_ctx){}); 822 else if (hi->type == HIDMAP_TYPE_ARR_LIST) 823 free(hi->codes, M_DEVBUF); 824 free(hm->hid_items, M_DEVBUF); 825 } 826 827 free(hm->key_press, M_DEVBUF); 828 free(hm->key_rel, M_DEVBUF); 829 830 return (0); 831 } 832 833 MODULE_DEPEND(hidmap, hid, 1, 1, 1); 834 MODULE_DEPEND(hidmap, hidbus, 1, 1, 1); 835 MODULE_DEPEND(hidmap, evdev, 1, 1, 1); 836 MODULE_VERSION(hidmap, 1); 837