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