1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2020 Vladimir Kondratyev <[email protected]> 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, M_WAITOK); 455 do_free = true; 456 } else 457 bzero (caps, HIDMAP_CAPS_SZ(nitems_map)); 458 459 /* Parse inputs */ 460 hd = hid_start_parse(d_ptr, d_len, 1 << hid_input); 461 HIDBUS_FOREACH_ITEM(hd, &hi, tlc_index) { 462 if (hi.kind != hid_input) 463 continue; 464 if (hi.flags & HIO_CONST) 465 continue; 466 for (i = 0; i < hi.loc.count; i++, hi.loc.pos += hi.loc.size) 467 if (hidmap_probe_hid_item(&hi, map, nitems_map, caps)) 468 items++; 469 } 470 hid_end_parse(hd); 471 472 /* Take finalizing callbacks in to account */ 473 for (i = 0; i < nitems_map; i++) { 474 if (map[i].has_cb && map[i].final_cb && 475 map[i].cb(NULL, NULL, (union hidmap_cb_ctx){}) == 0) { 476 setbit(caps, i); 477 items++; 478 } 479 } 480 481 /* Check that all mandatory usages are present in report descriptor */ 482 if (items != 0) { 483 for (i = 0; i < nitems_map; i++) { 484 KASSERT(!(map[i].required && map[i].forbidden), 485 ("both required & forbidden item flags are set")); 486 if ((map[i].required && isclr(caps, i)) || 487 (map[i].forbidden && isset(caps, i))) { 488 items = 0; 489 break; 490 } 491 } 492 } 493 494 if (do_free) 495 free(caps, M_DEVBUF); 496 497 return (items); 498 } 499 500 uint32_t 501 hidmap_add_map(struct hidmap *hm, const struct hidmap_item *map, 502 int nitems_map, hidmap_caps_t caps) 503 { 504 void *d_ptr; 505 uint32_t items; 506 int i, error; 507 hid_size_t d_len; 508 uint8_t tlc_index = hidbus_get_index(hm->dev); 509 510 /* Avoid double-adding of map in probe() handler */ 511 for (i = 0; i < hm->nmaps; i++) 512 if (hm->map[i] == map) 513 return (0); 514 515 error = hid_get_report_descr(hm->dev, &d_ptr, &d_len); 516 if (error != 0) { 517 device_printf(hm->dev, "could not retrieve report descriptor " 518 "from device: %d\n", error); 519 return (error); 520 } 521 522 hm->cb_state = HIDMAP_CB_IS_PROBING; 523 items = hidmap_probe_hid_descr(d_ptr, d_len, tlc_index, map, 524 nitems_map, caps); 525 if (items == 0) 526 return (ENXIO); 527 528 KASSERT(hm->nmaps < HIDMAP_MAX_MAPS, 529 ("Not more than %d maps is supported", HIDMAP_MAX_MAPS)); 530 hm->nhid_items += items; 531 hm->map[hm->nmaps] = map; 532 hm->nmap_items[hm->nmaps] = nitems_map; 533 hm->nmaps++; 534 535 return (0); 536 } 537 538 static bool 539 hidmap_parse_hid_item(struct hidmap *hm, struct hid_item *hi, 540 struct hidmap_hid_item *item) 541 { 542 const struct hidmap_item *mi; 543 struct hidmap_hid_item hi_temp; 544 uint32_t i; 545 uint16_t uoff; 546 bool found = false; 547 548 HIDMAP_FOREACH_ITEM(hm, mi, uoff) { 549 if (can_map_callback(hi, mi, uoff)) { 550 bzero(&hi_temp, sizeof(hi_temp)); 551 hi_temp.cb = mi->cb; 552 hi_temp.type = HIDMAP_TYPE_CALLBACK; 553 /* 554 * Values returned by probe- and attach-stage 555 * callbacks MUST be identical. 556 */ 557 if (mi->cb(hm, &hi_temp, 558 (union hidmap_cb_ctx){.hi = hi}) != 0) 559 break; 560 bcopy(&hi_temp, item, sizeof(hi_temp)); 561 goto mapped; 562 } 563 } 564 565 if (hi->flags & HIO_VARIABLE) { 566 HIDMAP_FOREACH_ITEM(hm, mi, uoff) { 567 if (can_map_variable(hi, mi, uoff)) { 568 item->evtype = mi->type; 569 item->code = mi->code + uoff; 570 item->type = hi->flags & HIO_NULLSTATE 571 ? HIDMAP_TYPE_VAR_NULLST 572 : HIDMAP_TYPE_VARIABLE; 573 item->last_val = 0; 574 item->invert_value = mi->invert_value; 575 switch (mi->type) { 576 case EV_KEY: 577 hidmap_support_key(hm, item->code); 578 break; 579 case EV_REL: 580 evdev_support_event(hm->evdev, EV_REL); 581 evdev_support_rel(hm->evdev, 582 item->code); 583 break; 584 case EV_ABS: 585 evdev_support_event(hm->evdev, EV_ABS); 586 evdev_support_abs(hm->evdev, 587 item->code, 588 hi->logical_minimum, 589 hi->logical_maximum, 590 mi->fuzz, 591 mi->flat, 592 hid_item_resolution(hi)); 593 break; 594 case EV_SW: 595 evdev_support_event(hm->evdev, EV_SW); 596 evdev_support_sw(hm->evdev, 597 item->code); 598 break; 599 default: 600 KASSERT(0, ("Unsupported event type")); 601 } 602 goto mapped; 603 } 604 } 605 return (false); 606 } 607 608 if (hi->usage_minimum != 0 || hi->usage_maximum != 0) { 609 HIDMAP_FOREACH_ITEM(hm, mi, uoff) { 610 if (can_map_arr_range(hi, mi, uoff)) { 611 hidmap_support_key(hm, mi->code + uoff); 612 found = true; 613 } 614 } 615 if (!found) 616 return (false); 617 item->umin = hi->usage_minimum; 618 item->type = HIDMAP_TYPE_ARR_RANGE; 619 item->last_key = KEY_RESERVED; 620 goto mapped; 621 } 622 623 for (i = 0; i < hi->nusages; i++) { 624 HIDMAP_FOREACH_ITEM(hm, mi, uoff) { 625 if (can_map_arr_list(hi, mi, hi->usages[i], uoff)) { 626 hidmap_support_key(hm, mi->code + uoff); 627 if (item->codes == NULL) 628 item->codes = malloc( 629 hi->nusages * sizeof(uint16_t), 630 M_DEVBUF, M_WAITOK | M_ZERO); 631 item->codes[i] = mi->code + uoff; 632 found = true; 633 break; 634 } 635 } 636 } 637 if (!found) 638 return (false); 639 item->type = HIDMAP_TYPE_ARR_LIST; 640 item->last_key = KEY_RESERVED; 641 642 mapped: 643 item->id = hi->report_ID; 644 item->loc = hi->loc; 645 item->loc.count = 1; 646 item->lmin = hi->logical_minimum; 647 item->lmax = hi->logical_maximum; 648 649 DPRINTFN(hm, 6, "usage=%04x id=%d loc=%u/%u type=%d item=%*D\n", 650 hi->usage, hi->report_ID, hi->loc.pos, hi->loc.size, item->type, 651 (int)sizeof(item->cb), &item->cb, " "); 652 653 return (true); 654 } 655 656 static int 657 hidmap_parse_hid_descr(struct hidmap *hm, uint8_t tlc_index) 658 { 659 const struct hidmap_item *map; 660 struct hidmap_hid_item *item = hm->hid_items; 661 void *d_ptr; 662 struct hid_data *hd; 663 struct hid_item hi; 664 int i, error; 665 hid_size_t d_len; 666 667 error = hid_get_report_descr(hm->dev, &d_ptr, &d_len); 668 if (error != 0) { 669 DPRINTF(hm, "could not retrieve report descriptor from " 670 "device: %d\n", error); 671 return (error); 672 } 673 674 /* Parse inputs */ 675 hd = hid_start_parse(d_ptr, d_len, 1 << hid_input); 676 HIDBUS_FOREACH_ITEM(hd, &hi, tlc_index) { 677 if (hi.kind != hid_input) 678 continue; 679 if (hi.flags & HIO_CONST) 680 continue; 681 for (i = 0; i < hi.loc.count; i++, hi.loc.pos += hi.loc.size) 682 if (hidmap_parse_hid_item(hm, &hi, item)) 683 item++; 684 KASSERT(item <= hm->hid_items + hm->nhid_items, 685 ("Parsed HID item array overflow")); 686 } 687 hid_end_parse(hd); 688 689 /* Add finalizing callbacks to the end of list */ 690 for (i = 0; i < hm->nmaps; i++) { 691 for (map = hm->map[i]; 692 map < hm->map[i] + hm->nmap_items[i]; 693 map++) { 694 if (map->has_cb && map->final_cb && 695 map->cb(hm, item, (union hidmap_cb_ctx){}) == 0) { 696 item->cb = map->cb; 697 item->type = HIDMAP_TYPE_FINALCB; 698 item++; 699 } 700 } 701 } 702 703 /* 704 * Resulting number of parsed HID items can be less than expected as 705 * map items might be duplicated in different maps. Save real number. 706 */ 707 if (hm->nhid_items != item - hm->hid_items) 708 DPRINTF(hm, "Parsed HID item number mismatch: expected=%u " 709 "result=%td\n", hm->nhid_items, item - hm->hid_items); 710 hm->nhid_items = item - hm->hid_items; 711 712 if (HIDMAP_WANT_MERGE_KEYS(hm)) 713 bzero(hm->key_press, howmany(KEY_CNT, 8)); 714 715 return (0); 716 } 717 718 int 719 hidmap_probe(struct hidmap* hm, device_t dev, 720 const struct hid_device_id *id, int nitems_id, 721 const struct hidmap_item *map, int nitems_map, 722 const char *suffix, hidmap_caps_t caps) 723 { 724 int error; 725 726 error = hidbus_lookup_driver_info(dev, id, nitems_id); 727 if (error != 0) 728 return (error); 729 730 hidmap_set_dev(hm, dev); 731 732 error = hidmap_add_map(hm, map, nitems_map, caps); 733 if (error != 0) 734 return (error); 735 736 hidbus_set_desc(dev, suffix); 737 738 return (BUS_PROBE_DEFAULT); 739 } 740 741 int 742 hidmap_attach(struct hidmap* hm) 743 { 744 const struct hid_device_info *hw = hid_get_device_info(hm->dev); 745 #ifdef HID_DEBUG 746 char tunable[40]; 747 #endif 748 int error; 749 750 #ifdef HID_DEBUG 751 if (hm->debug_var == NULL) { 752 hm->debug_var = &hm->debug_level; 753 snprintf(tunable, sizeof(tunable), "hw.hid.%s.debug", 754 device_get_name(hm->dev)); 755 TUNABLE_INT_FETCH(tunable, &hm->debug_level); 756 SYSCTL_ADD_INT(device_get_sysctl_ctx(hm->dev), 757 SYSCTL_CHILDREN(device_get_sysctl_tree(hm->dev)), 758 OID_AUTO, "debug", CTLFLAG_RWTUN, 759 &hm->debug_level, 0, "Verbosity level"); 760 } 761 #endif 762 763 DPRINTFN(hm, 11, "hm=%p\n", hm); 764 765 hm->cb_state = HIDMAP_CB_IS_ATTACHING; 766 767 hm->hid_items = malloc(hm->nhid_items * sizeof(struct hid_item), 768 M_DEVBUF, M_WAITOK | M_ZERO); 769 770 hidbus_set_intr(hm->dev, hidmap_intr, hm); 771 hm->evdev_methods = (struct evdev_methods) { 772 .ev_open = &hidmap_ev_open, 773 .ev_close = &hidmap_ev_close, 774 }; 775 776 hm->evdev = evdev_alloc(); 777 evdev_set_name(hm->evdev, device_get_desc(hm->dev)); 778 evdev_set_phys(hm->evdev, device_get_nameunit(hm->dev)); 779 evdev_set_id(hm->evdev, hw->idBus, hw->idVendor, hw->idProduct, 780 hw->idVersion); 781 evdev_set_serial(hm->evdev, hw->serial); 782 evdev_set_flag(hm->evdev, EVDEV_FLAG_EXT_EPOCH); /* hidbus child */ 783 evdev_support_event(hm->evdev, EV_SYN); 784 error = hidmap_parse_hid_descr(hm, hidbus_get_index(hm->dev)); 785 if (error) { 786 DPRINTF(hm, "error=%d\n", error); 787 hidmap_detach(hm); 788 return (ENXIO); 789 } 790 791 evdev_set_methods(hm->evdev, hm->dev, &hm->evdev_methods); 792 hm->cb_state = HIDMAP_CB_IS_RUNNING; 793 794 error = evdev_register(hm->evdev); 795 if (error) { 796 DPRINTF(hm, "error=%d\n", error); 797 hidmap_detach(hm); 798 return (ENXIO); 799 } 800 801 return (0); 802 } 803 804 int 805 hidmap_detach(struct hidmap* hm) 806 { 807 struct hidmap_hid_item *hi; 808 809 DPRINTFN(hm, 11, "\n"); 810 811 hm->cb_state = HIDMAP_CB_IS_DETACHING; 812 813 evdev_free(hm->evdev); 814 if (hm->hid_items != NULL) { 815 for (hi = hm->hid_items; 816 hi < hm->hid_items + hm->nhid_items; 817 hi++) 818 if (hi->type == HIDMAP_TYPE_FINALCB || 819 hi->type == HIDMAP_TYPE_CALLBACK) 820 hi->cb(hm, hi, (union hidmap_cb_ctx){}); 821 else if (hi->type == HIDMAP_TYPE_ARR_LIST) 822 free(hi->codes, M_DEVBUF); 823 free(hm->hid_items, M_DEVBUF); 824 } 825 826 free(hm->key_press, M_DEVBUF); 827 free(hm->key_rel, M_DEVBUF); 828 829 return (0); 830 } 831 832 MODULE_DEPEND(hidmap, hid, 1, 1, 1); 833 MODULE_DEPEND(hidmap, hidbus, 1, 1, 1); 834 MODULE_DEPEND(hidmap, evdev, 1, 1, 1); 835 MODULE_VERSION(hidmap, 1); 836