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