1 /* $OpenBSD: uhidpp.c,v 1.16 2021/07/28 09:56:54 anton Exp $ */ 2 3 /* 4 * Copyright (c) 2021 Anton Lindqvist <anton@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/systm.h> 21 #include <sys/kernel.h> 22 #include <sys/device.h> 23 #include <sys/mutex.h> 24 #include <sys/sensors.h> 25 26 #include <dev/usb/usb.h> 27 #include <dev/usb/usbhid.h> 28 #include <dev/usb/usbdi.h> 29 #include <dev/usb/usbdevs.h> 30 #include <dev/usb/uhidev.h> 31 32 /* #define UHIDPP_DEBUG */ 33 #ifdef UHIDPP_DEBUG 34 35 #define DPRINTF(x...) do { \ 36 if (uhidpp_debug) \ 37 printf(x); \ 38 } while (0) 39 40 #define DREPORT(prefix, repid, buf, len) do { \ 41 if (uhidpp_debug) \ 42 uhidd_dump_report((prefix), (repid), (buf), (len)); \ 43 } while (0) 44 45 void uhidd_dump_report(const char *, uint8_t, const unsigned char *, u_int); 46 47 int uhidpp_debug = 1; 48 49 #else 50 51 #define DPRINTF(x...) 52 #define DREPORT(prefix, repid, buf, len) 53 54 #endif 55 56 #define HIDPP_LINK_STATUS(x) ((x) & (1 << 7)) 57 58 #define HIDPP_REPORT_ID_SHORT 0x10 59 #define HIDPP_REPORT_ID_LONG 0x11 60 61 /* 62 * Length of reports. Note that the effective length is always +1 as 63 * uhidev_set_report() prepends the report ID. 64 */ 65 #define HIDPP_REPORT_SHORT_LENGTH (7 - 1) 66 #define HIDPP_REPORT_LONG_LENGTH (20 - 1) 67 68 /* 69 * Maximum number of allowed parameters for reports. Note, the parameters always 70 * starts at offset 3 for both RAP and FAP reports. 71 */ 72 #define HIDPP_REPORT_SHORT_PARAMS_MAX (HIDPP_REPORT_SHORT_LENGTH - 3) 73 #define HIDPP_REPORT_LONG_PARAMS_MAX (HIDPP_REPORT_LONG_LENGTH - 3) 74 75 #define HIDPP_DEVICE_ID_RECEIVER 0xff 76 77 #define HIDPP_FEAT_ROOT_IDX 0x00 78 #define HIDPP_FEAT_ROOT_PING_FUNC 0x01 79 #define HIDPP_FEAT_ROOT_PING_DATA 0x5a 80 81 #define HIDPP_SET_REGISTER 0x80 82 #define HIDPP_GET_REGISTER 0x81 83 #define HIDPP_SET_LONG_REGISTER 0x82 84 #define HIDPP_GET_LONG_REGISTER 0x83 85 86 #define HIDPP_REG_ENABLE_REPORTS 0x00 87 #define HIDPP_REG_PAIRING_INFORMATION 0xb5 88 89 #define HIDPP_NOTIF_DEVICE_BATTERY_STATUS (1 << 4) 90 #define HIDPP_NOTIF_RECEIVER_WIRELESS (1 << 0) 91 #define HIDPP_NOTIF_RECEIVER_SOFTWARE_PRESENT (1 << 3) 92 93 /* HID++ 1.0 error codes. */ 94 #define HIDPP_ERROR 0x8f 95 #define HIDPP_ERROR_SUCCESS 0x00 96 #define HIDPP_ERROR_INVALID_SUBID 0x01 97 #define HIDPP_ERROR_INVALID_ADRESS 0x02 98 #define HIDPP_ERROR_INVALID_VALUE 0x03 99 #define HIDPP_ERROR_CONNECT_FAIL 0x04 100 #define HIDPP_ERROR_TOO_MANY_DEVICES 0x05 101 #define HIDPP_ERROR_ALREADY_EXISTS 0x06 102 #define HIDPP_ERROR_BUSY 0x07 103 #define HIDPP_ERROR_UNKNOWN_DEVICE 0x08 104 #define HIDPP_ERROR_RESOURCE_ERROR 0x09 105 #define HIDPP_ERROR_REQUEST_UNAVAILABLE 0x0a 106 #define HIDPP_ERROR_INVALID_PARAM_VALUE 0x0b 107 #define HIDPP_ERROR_WRONG_PIN_CODE 0x0c 108 109 /* 110 * The software ID is added to feature access reports (FAP) and used to 111 * distinguish responses from notifications. Note, the software ID must be 112 * greater than zero which is reserved for notifications. 113 */ 114 #define HIDPP_SOFTWARE_ID 0x01 115 #define HIDPP_SOFTWARE_ID_LEN 4 116 117 #define HIDPP20_FEAT_ROOT_ID 0x0000 118 #define HIDPP20_FEAT_ROOT_GET_FEATURE_FUNC 0x0000 119 120 #define HIDPP20_FEAT_FEATURE_ID 0x0001 121 #define HIDPP20_FEAT_FEATURE_COUNT_FUNC 0x0000 122 #define HIDPP20_FEAT_FEATURE_ID_FUNC 0x0001 123 124 #define HIDPP20_FEAT_BATTERY_ID 0x1000 125 #define HIDPP20_FEAT_BATTERY_LEVEL_FUNC 0x0000 126 #define HIDPP20_FEAT_BATTERY_CAPABILITY_FUNC 0x0001 127 128 /* HID++ 2.0 error codes. */ 129 #define HIDPP20_ERROR 0xff 130 #define HIDPP20_ERROR_NO_ERROR 0x00 131 #define HIDPP20_ERROR_UNKNOWN 0x01 132 #define HIDPP20_ERROR_INVALID_ARGUMENT 0x02 133 #define HIDPP20_ERROR_OUT_OF_RANGE 0x03 134 #define HIDPP20_ERROR_HARDWARE_ERROR 0x04 135 #define HIDPP20_ERROR_LOGITECH_INTERNAL 0x05 136 #define HIDPP20_ERROR_INVALID_FEATURE_INDEX 0x06 137 #define HIDPP20_ERROR_INVALID_FUNCTION_ID 0x07 138 #define HIDPP20_ERROR_BUSY 0x08 139 #define HIDPP20_ERROR_UNSUPPORTED 0x09 140 141 /* 142 * Sentinels used for interrupt response synchronization. The values must be 143 * disjoint from existing report IDs. 144 */ 145 #define UHIDPP_RESP_NONE 0 146 #define UHIDPP_RESP_WAIT 1 147 #define UHIDPP_RESP_ERROR 2 148 149 /* Maximum number of devices associated with a single receiver. */ 150 #define UHIDPP_NDEVICES 6 151 152 /* Maximum number of pending notifications. */ 153 #define UHIDPP_NNOTIFICATIONS 4 154 155 /* Number of sensors per paired device. */ 156 #define UHIDPP_NSENSORS 2 157 158 /* Feature access report used by the HID++ 2.0 (and greater) protocol. */ 159 struct fap { 160 uint8_t feature_idx; 161 uint8_t funcidx_swid; 162 uint8_t params[HIDPP_REPORT_LONG_PARAMS_MAX]; 163 }; 164 165 /* 166 * Register access report used by the HID++ 1.0 protocol. Receivers always uses 167 * this type of report. 168 */ 169 struct rap { 170 uint8_t sub_id; 171 uint8_t reg_address; 172 uint8_t params[HIDPP_REPORT_LONG_PARAMS_MAX]; 173 }; 174 175 struct uhidpp_report { 176 uint8_t device_id; 177 union { 178 struct fap fap; 179 struct rap rap; 180 }; 181 } __packed; 182 183 struct uhidpp_notification { 184 struct uhidpp_report n_rep; 185 unsigned int n_id; 186 }; 187 188 struct uhidpp_device { 189 uint8_t d_id; 190 uint8_t d_connected; 191 uint8_t d_major; 192 uint8_t d_minor; 193 uint8_t d_features; 194 #define UHIDPP_DEVICE_FEATURE_ROOT 0x01 195 #define UHIDPP_DEVICE_FEATURE_BATTERY 0x02 196 197 struct { 198 struct ksensor b_sens[UHIDPP_NSENSORS]; 199 uint8_t b_feature_idx; 200 uint8_t b_level; 201 uint8_t b_next_level; 202 uint8_t b_status; 203 uint8_t b_nlevels; 204 } d_battery; 205 }; 206 207 /* 208 * Locking: 209 * [m] sc_mtx 210 */ 211 struct uhidpp_softc { 212 struct uhidev sc_hdev; 213 struct usbd_device *sc_udev; 214 215 struct mutex sc_mtx; 216 217 struct uhidpp_device sc_devices[UHIDPP_NDEVICES]; 218 /* [m] connected devices */ 219 220 struct uhidpp_notification sc_notifications[UHIDPP_NNOTIFICATIONS]; 221 /* [m] pending notifications */ 222 223 struct usb_task sc_task; /* [m] notification task */ 224 225 struct ksensordev sc_sensdev; /* [m] */ 226 struct sensor_task *sc_senstsk; /* [m] */ 227 228 struct uhidpp_report *sc_req; /* [m] synchronous request buffer */ 229 struct uhidpp_report *sc_resp; /* [m] synchronous response buffer */ 230 u_int sc_resp_state; /* [m] synchronous response state */ 231 232 }; 233 234 int uhidpp_match(struct device *, void *, void *); 235 void uhidpp_attach(struct device *, struct device *, void *); 236 int uhidpp_detach(struct device *, int flags); 237 void uhidpp_intr(struct uhidev *addr, void *ibuf, u_int len); 238 void uhidpp_refresh(void *); 239 void uhidpp_task(void *); 240 int uhidpp_sleep(struct uhidpp_softc *, uint64_t); 241 242 void uhidpp_device_connect(struct uhidpp_softc *, struct uhidpp_device *); 243 void uhidpp_device_refresh(struct uhidpp_softc *, struct uhidpp_device *); 244 int uhidpp_device_features(struct uhidpp_softc *, struct uhidpp_device *); 245 246 struct uhidpp_notification *uhidpp_claim_notification(struct uhidpp_softc *); 247 int uhidpp_consume_notification(struct uhidpp_softc *, struct uhidpp_report *); 248 int uhidpp_is_notification(struct uhidpp_softc *, struct uhidpp_report *); 249 250 static int uhidpp_has_sensors(struct uhidpp_softc *); 251 252 int hidpp_get_protocol_version(struct uhidpp_softc *, uint8_t, uint8_t *, 253 uint8_t *); 254 255 int hidpp10_get_name(struct uhidpp_softc *, uint8_t, char *, size_t); 256 int hidpp10_get_serial(struct uhidpp_softc *, uint8_t, uint8_t *, size_t); 257 int hidpp10_get_type(struct uhidpp_softc *, uint8_t, const char **); 258 int hidpp10_enable_notifications(struct uhidpp_softc *, uint8_t); 259 260 int hidpp20_root_get_feature(struct uhidpp_softc *, uint8_t, uint16_t, 261 uint8_t *, uint8_t *); 262 int hidpp20_feature_get_count(struct uhidpp_softc *, uint8_t, uint8_t, 263 uint8_t *); 264 int hidpp20_feature_get_id(struct uhidpp_softc *, uint8_t, uint8_t, uint8_t, 265 uint16_t *, uint8_t *); 266 int hidpp20_battery_get_level_status(struct uhidpp_softc *, uint8_t, uint8_t, 267 uint8_t *, uint8_t *, uint8_t *); 268 int hidpp20_battery_get_capability(struct uhidpp_softc *, uint8_t, uint8_t, 269 uint8_t *); 270 271 int hidpp_send_validate(uint8_t, int); 272 int hidpp_send_rap_report(struct uhidpp_softc *, uint8_t, uint8_t, 273 uint8_t, uint8_t, uint8_t *, int, struct uhidpp_report *); 274 int hidpp_send_fap_report(struct uhidpp_softc *, uint8_t, uint8_t, uint8_t, 275 uint8_t, uint8_t *, int, struct uhidpp_report *); 276 int hidpp_send_report(struct uhidpp_softc *, uint8_t, struct uhidpp_report *, 277 struct uhidpp_report *); 278 279 struct cfdriver uhidpp_cd = { 280 NULL, "uhidpp", DV_DULL 281 }; 282 283 const struct cfattach uhidpp_ca = { 284 sizeof(struct uhidpp_softc), 285 uhidpp_match, 286 uhidpp_attach, 287 uhidpp_detach, 288 }; 289 290 static const struct usb_devno uhidpp_devs[] = { 291 { USB_VENDOR_LOGITECH, USB_PRODUCT_ANY }, 292 }; 293 294 int 295 uhidpp_match(struct device *parent, void *match, void *aux) 296 { 297 struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; 298 void *desc; 299 int descsiz, siz; 300 301 if (uha->reportid != HIDPP_REPORT_ID_SHORT && 302 uha->reportid != HIDPP_REPORT_ID_LONG) 303 return UMATCH_NONE; 304 305 if (usb_lookup(uhidpp_devs, 306 uha->uaa->vendor, uha->uaa->product) == NULL) 307 return UMATCH_NONE; 308 309 uhidev_get_report_desc(uha->parent, &desc, &descsiz); 310 siz = hid_report_size(desc, descsiz, hid_output, HIDPP_REPORT_ID_SHORT); 311 if (siz != HIDPP_REPORT_SHORT_LENGTH) 312 return UMATCH_NONE; 313 siz = hid_report_size(desc, descsiz, hid_output, HIDPP_REPORT_ID_LONG); 314 if (siz != HIDPP_REPORT_LONG_LENGTH) 315 return UMATCH_NONE; 316 317 return UMATCH_VENDOR_PRODUCT; 318 } 319 320 void 321 uhidpp_attach(struct device *parent, struct device *self, void *aux) 322 { 323 struct uhidpp_softc *sc = (struct uhidpp_softc *)self; 324 struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; 325 struct usb_attach_arg *uaa = uha->uaa; 326 int error, i; 327 int npaired = 0; 328 329 sc->sc_hdev.sc_intr = uhidpp_intr; 330 sc->sc_hdev.sc_udev = uaa->device; 331 sc->sc_hdev.sc_parent = uha->parent; 332 sc->sc_hdev.sc_report_id = uha->reportid; 333 /* The largest supported report dictates the sizes. */ 334 sc->sc_hdev.sc_isize = HIDPP_REPORT_LONG_LENGTH; 335 sc->sc_hdev.sc_osize = HIDPP_REPORT_LONG_LENGTH; 336 337 sc->sc_udev = uaa->device; 338 339 mtx_init(&sc->sc_mtx, IPL_USB); 340 341 sc->sc_resp = NULL; 342 sc->sc_resp_state = UHIDPP_RESP_NONE; 343 344 error = uhidev_open(&sc->sc_hdev); 345 if (error) { 346 printf(" open error %d\n", error); 347 return; 348 } 349 350 usb_init_task(&sc->sc_task, uhidpp_task, sc, USB_TASK_TYPE_GENERIC); 351 352 mtx_enter(&sc->sc_mtx); 353 354 /* 355 * Wire up report device handlers before issuing commands to the device 356 * in order to receive responses. Necessary as uhidev by default 357 * performs the wiring after the attach routine has returned. 358 */ 359 error = uhidev_set_report_dev(sc->sc_hdev.sc_parent, &sc->sc_hdev, 360 HIDPP_REPORT_ID_SHORT); 361 if (error) { 362 printf(" short report error %d\n", error); 363 return; 364 } 365 error = uhidev_set_report_dev(sc->sc_hdev.sc_parent, &sc->sc_hdev, 366 HIDPP_REPORT_ID_LONG); 367 if (error) { 368 printf(" long report error %d\n", error); 369 return; 370 } 371 372 /* Probe paired devices. */ 373 for (i = 0; i < UHIDPP_NDEVICES; i++) { 374 char name[16]; 375 uint8_t serial[4]; 376 struct uhidpp_device *dev = &sc->sc_devices[i]; 377 const char *type; 378 uint8_t device_id = i + 1; 379 380 dev->d_id = device_id; 381 382 if (hidpp10_get_serial(sc, device_id, serial, sizeof(serial)) || 383 hidpp10_get_type(sc, device_id, &type) || 384 hidpp10_get_name(sc, device_id, name, sizeof(name))) 385 continue; 386 387 if (npaired > 0) 388 printf(","); 389 printf(" device %d", device_id); 390 printf(" %s", type); 391 printf(" \"%s\"", name); 392 printf(" serial %02x-%02x-%02x-%02x", 393 serial[0], serial[1], serial[2], serial[3]); 394 npaired++; 395 } 396 if (npaired == 0) 397 goto out; 398 399 /* Enable notifications for the receiver. */ 400 error = hidpp10_enable_notifications(sc, HIDPP_DEVICE_ID_RECEIVER); 401 if (error) 402 printf(" error %d", error); 403 404 out: 405 mtx_leave(&sc->sc_mtx); 406 printf("\n"); 407 } 408 409 int 410 uhidpp_detach(struct device *self, int flags) 411 { 412 struct uhidpp_softc *sc = (struct uhidpp_softc *)self; 413 int i, j; 414 415 usb_rem_wait_task(sc->sc_udev, &sc->sc_task); 416 417 if (sc->sc_senstsk != NULL) 418 sensor_task_unregister(sc->sc_senstsk); 419 420 KASSERT(sc->sc_resp_state == UHIDPP_RESP_NONE); 421 422 if (uhidpp_has_sensors(sc)) 423 sensordev_deinstall(&sc->sc_sensdev); 424 425 for (i = 0; i < UHIDPP_NDEVICES; i++) { 426 struct uhidpp_device *dev = &sc->sc_devices[i]; 427 428 if (!dev->d_connected) 429 continue; 430 431 for (j = 0; j < UHIDPP_NSENSORS; j++) 432 sensor_detach(&sc->sc_sensdev, &dev->d_battery.b_sens[j]); 433 } 434 435 uhidev_close(&sc->sc_hdev); 436 437 return 0; 438 } 439 440 void 441 uhidpp_intr(struct uhidev *addr, void *buf, u_int len) 442 { 443 struct uhidpp_softc *sc = (struct uhidpp_softc *)addr; 444 struct uhidpp_report *rep = buf; 445 int dowake = 0; 446 uint8_t repid; 447 448 /* 449 * Ugliness ahead as the report ID is stripped of by uhidev_intr() but 450 * needed to determine if an error occurred. 451 * Note that an error response is always a short report even if the 452 * command that caused the error is a long report. 453 */ 454 repid = ((uint8_t *)buf)[-1]; 455 456 DREPORT(__func__, repid, buf, len); 457 458 mtx_enter(&sc->sc_mtx); 459 if (uhidpp_is_notification(sc, rep)) { 460 struct uhidpp_notification *ntf; 461 462 ntf = uhidpp_claim_notification(sc); 463 if (ntf != NULL) { 464 memcpy(&ntf->n_rep, buf, len); 465 usb_add_task(sc->sc_udev, &sc->sc_task); 466 } else { 467 DPRINTF("%s: too many notifications", __func__); 468 } 469 } else { 470 KASSERT(sc->sc_resp_state == UHIDPP_RESP_WAIT); 471 dowake = 1; 472 sc->sc_resp_state = repid; 473 memcpy(sc->sc_resp, buf, len); 474 } 475 mtx_leave(&sc->sc_mtx); 476 if (dowake) 477 wakeup(sc); 478 } 479 480 void 481 uhidpp_refresh(void *arg) 482 { 483 struct uhidpp_softc *sc = arg; 484 int i; 485 486 mtx_enter(&sc->sc_mtx); 487 for (i = 0; i < UHIDPP_NDEVICES; i++) { 488 struct uhidpp_device *dev = &sc->sc_devices[i]; 489 490 if (dev->d_connected) 491 uhidpp_device_refresh(sc, dev); 492 } 493 mtx_leave(&sc->sc_mtx); 494 } 495 496 void 497 uhidpp_task(void *arg) 498 { 499 struct uhidpp_softc *sc = arg; 500 501 mtx_enter(&sc->sc_mtx); 502 for (;;) { 503 struct uhidpp_report rep; 504 struct uhidpp_device *dev; 505 506 if (uhidpp_consume_notification(sc, &rep)) 507 break; 508 509 DPRINTF("%s: device_id=%d, sub_id=%02x\n", 510 __func__, rep.device_id, rep.rap.sub_id); 511 512 if (rep.device_id == 0 || rep.device_id > UHIDPP_NDEVICES) { 513 DPRINTF("%s: invalid device\n", __func__); 514 continue; 515 } 516 dev = &sc->sc_devices[rep.device_id - 1]; 517 518 switch (rep.rap.sub_id) { 519 case 0x0e: /* leds */ 520 case 0x40: /* disconnect */ 521 case 0x4b: /* pairing accepted */ 522 break; 523 case 0x41: /* connect */ 524 /* 525 * Do nothing if the link is reported to be out of 526 * range. This happens when a device has been idle for a 527 * while. 528 */ 529 if (HIDPP_LINK_STATUS(rep.rap.params[0])) 530 uhidpp_device_connect(sc, dev); 531 break; 532 } 533 } 534 mtx_leave(&sc->sc_mtx); 535 } 536 537 int 538 uhidpp_sleep(struct uhidpp_softc *sc, uint64_t nsecs) 539 { 540 return msleep_nsec(sc, &sc->sc_mtx, PZERO, "uhidpp", nsecs); 541 } 542 543 void 544 uhidpp_device_connect(struct uhidpp_softc *sc, struct uhidpp_device *dev) 545 { 546 struct ksensor *sens; 547 int error; 548 uint8_t feature_type; 549 550 MUTEX_ASSERT_LOCKED(&sc->sc_mtx); 551 552 /* A connected device will continously send connect events. */ 553 if (dev->d_connected) 554 return; 555 556 /* 557 * If features are already present, it must be a device lacking battery 558 * support. 559 */ 560 if (dev->d_features) 561 return; 562 563 error = hidpp_get_protocol_version(sc, dev->d_id, 564 &dev->d_major, &dev->d_minor); 565 if (error) { 566 DPRINTF("%s: protocol version failure: device_id=%d, " 567 "error=%d\n", 568 __func__, dev->d_id, error); 569 return; 570 } 571 572 DPRINTF("%s: device_id=%d, version=%d.%d\n", 573 __func__, dev->d_id, dev->d_major, dev->d_minor); 574 575 if (dev->d_major >= 2) { 576 error = uhidpp_device_features(sc, dev); 577 if (error) { 578 DPRINTF("%s: features failure: device_id=%d, " 579 "error=%d\n", 580 __func__, dev->d_id, error); 581 return; 582 } 583 584 error = hidpp20_root_get_feature(sc, dev->d_id, 585 HIDPP20_FEAT_BATTERY_ID, 586 &dev->d_battery.b_feature_idx, &feature_type); 587 if (error) { 588 DPRINTF("%s: battery feature index failure: " 589 "device_id=%d, error=%d\n", 590 __func__, dev->d_id, error); 591 return; 592 } 593 594 error = hidpp20_battery_get_capability(sc, dev->d_id, 595 dev->d_battery.b_feature_idx, &dev->d_battery.b_nlevels); 596 if (error) { 597 DPRINTF("%s: battery capability failure: device_id=%d, " 598 "error=%d\n", __func__, dev->d_id, error); 599 return; 600 } 601 602 } else { 603 return; 604 } 605 606 dev->d_connected = 1; 607 608 /* 609 * Delay installation of sensors until a device with battery support is 610 * connected. Allows sensorsd(8) to pick up hotplugged devices. 611 */ 612 if (!uhidpp_has_sensors(sc)) { 613 strlcpy(sc->sc_sensdev.xname, sc->sc_hdev.sc_dev.dv_xname, 614 sizeof(sc->sc_sensdev.xname)); 615 sensordev_install(&sc->sc_sensdev); 616 } 617 618 sens = &dev->d_battery.b_sens[0]; 619 strlcpy(sens->desc, "battery level", sizeof(sens->desc)); 620 sens->type = SENSOR_PERCENT; 621 sens->flags = SENSOR_FUNKNOWN; 622 sensor_attach(&sc->sc_sensdev, sens); 623 624 sens = &dev->d_battery.b_sens[1]; 625 strlcpy(sens->desc, "number of battery levels", sizeof(sens->desc)); 626 sens->type = SENSOR_INTEGER; 627 sens->value = dev->d_battery.b_nlevels; 628 sensor_attach(&sc->sc_sensdev, sens); 629 630 if (sc->sc_senstsk == NULL) { 631 /* 632 * The mutex must be temporarily released while calling 633 * sensor_task_register() as it might end up sleeping. 634 */ 635 mtx_leave(&sc->sc_mtx); 636 sc->sc_senstsk = sensor_task_register(sc, uhidpp_refresh, 30); 637 mtx_enter(&sc->sc_mtx); 638 } 639 640 uhidpp_device_refresh(sc, dev); 641 } 642 643 void 644 uhidpp_device_refresh(struct uhidpp_softc *sc, struct uhidpp_device *dev) 645 { 646 int error; 647 648 MUTEX_ASSERT_LOCKED(&sc->sc_mtx); 649 650 if (dev->d_major >= 2) { 651 error = hidpp20_battery_get_level_status(sc, dev->d_id, 652 dev->d_battery.b_feature_idx, 653 &dev->d_battery.b_level, &dev->d_battery.b_next_level, 654 &dev->d_battery.b_status); 655 if (error) { 656 DPRINTF("%s: battery status failure: device_id=%d, " 657 "error=%d\n", 658 __func__, dev->d_id, error); 659 return; 660 } 661 662 dev->d_battery.b_sens[0].value = dev->d_battery.b_level * 1000; 663 dev->d_battery.b_sens[0].flags &= ~SENSOR_FUNKNOWN; 664 if (dev->d_battery.b_nlevels < 10) { 665 /* 666 * According to the HID++ 2.0 specification, less than 667 * 10 levels should be mapped to the following 4 levels: 668 * 669 * [0, 10] critical 670 * [11, 30] low 671 * [31, 80] good 672 * [81, 100] full 673 * 674 * Since sensors are limited to 3 valid statuses, clamp 675 * it even further. 676 */ 677 if (dev->d_battery.b_level <= 10) 678 dev->d_battery.b_sens[0].status = SENSOR_S_CRIT; 679 else if (dev->d_battery.b_level <= 30) 680 dev->d_battery.b_sens[0].status = SENSOR_S_WARN; 681 else 682 dev->d_battery.b_sens[0].status = SENSOR_S_OK; 683 } else { 684 /* 685 * XXX the device supports battery mileage. The current 686 * level must be checked against resp.fap.params[3] 687 * given by hidpp20_battery_get_capability(). 688 */ 689 dev->d_battery.b_sens[0].status = SENSOR_S_UNKNOWN; 690 } 691 } 692 } 693 694 /* 695 * Enumerate all supported HID++ 2.0 features for the given device. 696 */ 697 int 698 uhidpp_device_features(struct uhidpp_softc *sc, struct uhidpp_device *dev) 699 { 700 int error; 701 uint8_t count, feature_idx, feature_type, i; 702 703 /* All devices support the root feature. */ 704 dev->d_features |= UHIDPP_DEVICE_FEATURE_ROOT; 705 706 error = hidpp20_root_get_feature(sc, dev->d_id, 707 HIDPP20_FEAT_FEATURE_ID, 708 &feature_idx, &feature_type); 709 if (error) { 710 DPRINTF("%s: feature index failure: device_id=%d, error=%d\n", 711 __func__, dev->d_id, error); 712 return error; 713 } 714 715 error = hidpp20_feature_get_count(sc, dev->d_id, feature_idx, &count); 716 if (error) { 717 DPRINTF("%s: feature count failure: device_id=%d, error=%d\n", 718 __func__, dev->d_id, error); 719 return error; 720 } 721 722 for (i = 1; i <= count; i++) { 723 uint16_t id; 724 uint8_t type; 725 726 error = hidpp20_feature_get_id(sc, dev->d_id, feature_idx, i, 727 &id, &type); 728 if (error) 729 continue; 730 731 if (id == HIDPP20_FEAT_BATTERY_ID) 732 dev->d_features |= UHIDPP_DEVICE_FEATURE_BATTERY; 733 734 DPRINTF("%s: idx=%d, id=%x, type=%x device_id=%d\n", 735 __func__, i, id, type, dev->d_id); 736 } 737 DPRINTF("%s: device_id=%d, count=%d, features=%x\n", 738 __func__, dev->d_id, count, dev->d_features); 739 740 if ((dev->d_features & UHIDPP_DEVICE_FEATURE_BATTERY) == 0) 741 return -ENODEV; 742 return 0; 743 } 744 745 /* 746 * Returns the next available notification slot, if available. 747 */ 748 struct uhidpp_notification * 749 uhidpp_claim_notification(struct uhidpp_softc *sc) 750 { 751 struct uhidpp_notification *ntf = NULL; 752 int nclaimed = 0; 753 int i; 754 755 MUTEX_ASSERT_LOCKED(&sc->sc_mtx); 756 757 for (i = 0; i < UHIDPP_NNOTIFICATIONS; i++) { 758 struct uhidpp_notification *tmp = &sc->sc_notifications[i]; 759 760 if (tmp->n_id > 0) 761 nclaimed++; 762 else if (ntf == NULL) 763 ntf = tmp; 764 } 765 766 if (ntf == NULL) 767 return NULL; 768 ntf->n_id = nclaimed + 1; 769 return ntf; 770 } 771 772 /* 773 * Consume the first unhandled notification, if present. 774 */ 775 int 776 uhidpp_consume_notification(struct uhidpp_softc *sc, struct uhidpp_report *rep) 777 { 778 struct uhidpp_notification *ntf = NULL; 779 int i; 780 781 MUTEX_ASSERT_LOCKED(&sc->sc_mtx); 782 783 for (i = 0; i < UHIDPP_NNOTIFICATIONS; i++) { 784 struct uhidpp_notification *tmp = &sc->sc_notifications[i]; 785 786 if (tmp->n_id > 0 && (ntf == NULL || tmp->n_id < ntf->n_id)) 787 ntf = tmp; 788 } 789 if (ntf == NULL) 790 return 1; 791 792 memcpy(rep, &ntf->n_rep, sizeof(*rep)); 793 ntf->n_id = 0; 794 return 0; 795 } 796 797 798 /* 799 * Returns non-zero if the given report is a notification. Otherwise, it must be 800 * a response. 801 */ 802 int 803 uhidpp_is_notification(struct uhidpp_softc *sc, struct uhidpp_report *rep) 804 { 805 /* Not waiting for a response. */ 806 if (sc->sc_req == NULL) 807 return 1; 808 809 /* Everything except the parameters must be repeated in a response. */ 810 if (sc->sc_req->device_id == rep->device_id && 811 sc->sc_req->rap.sub_id == rep->rap.sub_id && 812 sc->sc_req->rap.reg_address == rep->rap.reg_address) 813 return 0; 814 815 /* An error must always be a response. */ 816 if ((rep->rap.sub_id == HIDPP_ERROR || 817 rep->fap.feature_idx == HIDPP20_ERROR) && 818 rep->fap.funcidx_swid == sc->sc_req->fap.feature_idx && 819 rep->fap.params[0] == sc->sc_req->fap.funcidx_swid) 820 return 0; 821 822 return 1; 823 } 824 825 static int 826 uhidpp_has_sensors(struct uhidpp_softc *sc) 827 { 828 return sc->sc_sensdev.xname[0] != '\0'; 829 } 830 831 int 832 hidpp_get_protocol_version(struct uhidpp_softc *sc, uint8_t device_id, 833 uint8_t *major, uint8_t *minor) 834 { 835 struct uhidpp_report resp; 836 uint8_t params[3] = { 0, 0, HIDPP_FEAT_ROOT_PING_DATA }; 837 int error; 838 839 error = hidpp_send_fap_report(sc, 840 HIDPP_REPORT_ID_SHORT, 841 device_id, 842 HIDPP_FEAT_ROOT_IDX, 843 HIDPP_FEAT_ROOT_PING_FUNC, 844 params, sizeof(params), &resp); 845 if (error == HIDPP_ERROR_INVALID_SUBID) { 846 *major = 1; 847 *minor = 0; 848 return 0; 849 } 850 if (error) 851 return error; 852 if (resp.rap.params[2] != HIDPP_FEAT_ROOT_PING_DATA) 853 return -EPROTO; 854 855 *major = resp.fap.params[0]; 856 *minor = resp.fap.params[1]; 857 return 0; 858 } 859 860 int 861 hidpp10_get_name(struct uhidpp_softc *sc, uint8_t device_id, 862 char *buf, size_t bufsiz) 863 { 864 struct uhidpp_report resp; 865 int error; 866 uint8_t params[1] = { 0x40 + (device_id - 1) }; 867 uint8_t len; 868 869 error = hidpp_send_rap_report(sc, 870 HIDPP_REPORT_ID_SHORT, 871 HIDPP_DEVICE_ID_RECEIVER, 872 HIDPP_GET_LONG_REGISTER, 873 HIDPP_REG_PAIRING_INFORMATION, 874 params, sizeof(params), &resp); 875 if (error) 876 return error; 877 878 len = resp.rap.params[1]; 879 if (len + 2 > sizeof(resp.rap.params)) 880 return -ENAMETOOLONG; 881 if (len > bufsiz - 1) 882 len = bufsiz - 1; 883 memcpy(buf, &resp.rap.params[2], len); 884 buf[len] = '\0'; 885 return 0; 886 } 887 888 int 889 hidpp10_get_serial(struct uhidpp_softc *sc, uint8_t device_id, 890 uint8_t *buf, size_t bufsiz) 891 { 892 struct uhidpp_report resp; 893 int error; 894 uint8_t params[1] = { 0x30 + (device_id - 1) }; 895 uint8_t len; 896 897 error = hidpp_send_rap_report(sc, 898 HIDPP_REPORT_ID_SHORT, 899 HIDPP_DEVICE_ID_RECEIVER, 900 HIDPP_GET_LONG_REGISTER, 901 HIDPP_REG_PAIRING_INFORMATION, 902 params, sizeof(params), &resp); 903 if (error) 904 return error; 905 906 len = 4; 907 if (bufsiz < len) 908 len = bufsiz; 909 memcpy(buf, &resp.rap.params[1], len); 910 return 0; 911 } 912 913 int 914 hidpp10_get_type(struct uhidpp_softc *sc, uint8_t device_id, const char **type) 915 { 916 struct uhidpp_report resp; 917 int error; 918 uint8_t params[1] = { 0x20 + (device_id - 1) }; 919 920 error = hidpp_send_rap_report(sc, 921 HIDPP_REPORT_ID_SHORT, 922 HIDPP_DEVICE_ID_RECEIVER, 923 HIDPP_GET_LONG_REGISTER, 924 HIDPP_REG_PAIRING_INFORMATION, 925 params, sizeof(params), &resp); 926 if (error) 927 return error; 928 929 switch (resp.rap.params[7]) { 930 case 0x00: 931 *type = "unknown"; 932 return 0; 933 case 0x01: 934 *type = "keyboard"; 935 return 0; 936 case 0x02: 937 *type = "mouse"; 938 return 0; 939 case 0x03: 940 *type = "numpad"; 941 return 0; 942 case 0x04: 943 *type = "presenter"; 944 return 0; 945 case 0x08: 946 *type = "trackball"; 947 return 0; 948 case 0x09: 949 *type = "touchpad"; 950 return 0; 951 } 952 return -ENOENT; 953 } 954 955 int 956 hidpp10_enable_notifications(struct uhidpp_softc *sc, uint8_t device_id) 957 { 958 struct uhidpp_report resp; 959 uint8_t params[3]; 960 961 /* Device reporting flags. */ 962 params[0] = HIDPP_NOTIF_DEVICE_BATTERY_STATUS; 963 /* Receiver reporting flags. */ 964 params[1] = HIDPP_NOTIF_RECEIVER_WIRELESS | 965 HIDPP_NOTIF_RECEIVER_SOFTWARE_PRESENT; 966 /* Device reporting flags (continued). */ 967 params[2] = 0; 968 969 return hidpp_send_rap_report(sc, 970 HIDPP_REPORT_ID_SHORT, 971 device_id, 972 HIDPP_SET_REGISTER, 973 HIDPP_REG_ENABLE_REPORTS, 974 params, sizeof(params), &resp); 975 } 976 977 int 978 hidpp20_root_get_feature(struct uhidpp_softc *sc, uint8_t device_id, 979 uint16_t feature, uint8_t *feature_idx, uint8_t *feature_type) 980 { 981 struct uhidpp_report resp; 982 uint8_t params[2] = { feature >> 8, feature & 0xff }; 983 int error; 984 985 error = hidpp_send_fap_report(sc, 986 HIDPP_REPORT_ID_LONG, 987 device_id, 988 HIDPP20_FEAT_ROOT_ID, 989 HIDPP20_FEAT_ROOT_GET_FEATURE_FUNC, 990 params, sizeof(params), &resp); 991 if (error) 992 return error; 993 994 if (resp.fap.params[0] == 0) 995 return -ENOENT; 996 997 *feature_idx = resp.fap.params[0]; 998 *feature_type = resp.fap.params[1]; 999 return 0; 1000 } 1001 1002 int 1003 hidpp20_feature_get_count(struct uhidpp_softc *sc, uint8_t device_id, 1004 uint8_t feature_idx, uint8_t *count) 1005 { 1006 struct uhidpp_report resp; 1007 int error; 1008 1009 error = hidpp_send_fap_report(sc, 1010 HIDPP_REPORT_ID_LONG, 1011 device_id, 1012 feature_idx, 1013 HIDPP20_FEAT_FEATURE_COUNT_FUNC, 1014 NULL, 0, &resp); 1015 if (error) 1016 return error; 1017 1018 *count = resp.fap.params[0]; 1019 return 0; 1020 } 1021 1022 int 1023 hidpp20_feature_get_id(struct uhidpp_softc *sc, uint8_t device_id, 1024 uint8_t feature_idx, uint8_t idx, uint16_t *id, uint8_t *type) 1025 { 1026 struct uhidpp_report resp; 1027 uint8_t params[1] = { idx }; 1028 int error; 1029 1030 error = hidpp_send_fap_report(sc, 1031 HIDPP_REPORT_ID_LONG, 1032 device_id, 1033 feature_idx, 1034 HIDPP20_FEAT_FEATURE_ID_FUNC, 1035 params, sizeof(params), &resp); 1036 if (error) 1037 return error; 1038 1039 *id = bemtoh16(resp.fap.params); 1040 *type = resp.fap.params[2]; 1041 return 0; 1042 } 1043 1044 int 1045 hidpp20_battery_get_level_status(struct uhidpp_softc *sc, uint8_t device_id, 1046 uint8_t feature_idx, uint8_t *level, uint8_t *next_level, uint8_t *status) 1047 { 1048 struct uhidpp_report resp; 1049 int error; 1050 1051 error = hidpp_send_fap_report(sc, 1052 HIDPP_REPORT_ID_LONG, 1053 device_id, 1054 feature_idx, 1055 HIDPP20_FEAT_BATTERY_LEVEL_FUNC, 1056 NULL, 0, &resp); 1057 if (error) 1058 return error; 1059 1060 *level = resp.fap.params[0]; 1061 *next_level = resp.fap.params[1]; 1062 *status = resp.fap.params[2]; 1063 return 0; 1064 } 1065 1066 int 1067 hidpp20_battery_get_capability(struct uhidpp_softc *sc, uint8_t device_id, 1068 uint8_t feature_idx, uint8_t *nlevels) 1069 { 1070 struct uhidpp_report resp; 1071 int error; 1072 1073 error = hidpp_send_fap_report(sc, 1074 HIDPP_REPORT_ID_LONG, 1075 device_id, 1076 feature_idx, 1077 HIDPP20_FEAT_BATTERY_CAPABILITY_FUNC, 1078 NULL, 0, &resp); 1079 if (error) 1080 return error; 1081 *nlevels = resp.fap.params[0]; 1082 return 0; 1083 } 1084 1085 int 1086 hidpp_send_validate(uint8_t report_id, int nparams) 1087 { 1088 if (report_id == HIDPP_REPORT_ID_SHORT) { 1089 if (nparams > HIDPP_REPORT_SHORT_PARAMS_MAX) 1090 return -EMSGSIZE; 1091 } else if (report_id == HIDPP_REPORT_ID_LONG) { 1092 if (nparams > HIDPP_REPORT_LONG_PARAMS_MAX) 1093 return -EMSGSIZE; 1094 } else { 1095 return -EINVAL; 1096 } 1097 return 0; 1098 } 1099 1100 int 1101 hidpp_send_fap_report(struct uhidpp_softc *sc, uint8_t report_id, 1102 uint8_t device_id, uint8_t feature_idx, uint8_t funcidx_swid, 1103 uint8_t *params, int nparams, struct uhidpp_report *resp) 1104 { 1105 struct uhidpp_report req; 1106 int error; 1107 1108 error = hidpp_send_validate(report_id, nparams); 1109 if (error) 1110 return error; 1111 1112 memset(&req, 0, sizeof(req)); 1113 req.device_id = device_id; 1114 req.fap.feature_idx = feature_idx; 1115 req.fap.funcidx_swid = 1116 (funcidx_swid << HIDPP_SOFTWARE_ID_LEN) | HIDPP_SOFTWARE_ID; 1117 memcpy(req.fap.params, params, nparams); 1118 return hidpp_send_report(sc, report_id, &req, resp); 1119 } 1120 1121 int 1122 hidpp_send_rap_report(struct uhidpp_softc *sc, uint8_t report_id, 1123 uint8_t device_id, uint8_t sub_id, uint8_t reg_address, 1124 uint8_t *params, int nparams, struct uhidpp_report *resp) 1125 { 1126 struct uhidpp_report req; 1127 int error; 1128 1129 error = hidpp_send_validate(report_id, nparams); 1130 if (error) 1131 return error; 1132 1133 memset(&req, 0, sizeof(req)); 1134 req.device_id = device_id; 1135 req.rap.sub_id = sub_id; 1136 req.rap.reg_address = reg_address; 1137 memcpy(req.rap.params, params, nparams); 1138 return hidpp_send_report(sc, report_id, &req, resp); 1139 } 1140 1141 int 1142 hidpp_send_report(struct uhidpp_softc *sc, uint8_t report_id, 1143 struct uhidpp_report *req, struct uhidpp_report *resp) 1144 { 1145 int error, len, n; 1146 1147 MUTEX_ASSERT_LOCKED(&sc->sc_mtx); 1148 1149 if (report_id == HIDPP_REPORT_ID_SHORT) 1150 len = HIDPP_REPORT_SHORT_LENGTH; 1151 else if (report_id == HIDPP_REPORT_ID_LONG) 1152 len = HIDPP_REPORT_LONG_LENGTH; 1153 else 1154 return -EINVAL; 1155 1156 DREPORT(__func__, report_id, (const unsigned char *)req, len); 1157 1158 /* Wait until any ongoing command has completed. */ 1159 while (sc->sc_resp_state != UHIDPP_RESP_NONE) 1160 uhidpp_sleep(sc, INFSLP); 1161 sc->sc_req = req; 1162 sc->sc_resp = resp; 1163 sc->sc_resp_state = UHIDPP_RESP_WAIT; 1164 /* 1165 * The mutex must be temporarily released while calling 1166 * uhidev_set_report() as it might end up sleeping. 1167 */ 1168 mtx_leave(&sc->sc_mtx); 1169 1170 n = uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT, 1171 report_id, req, len); 1172 1173 mtx_enter(&sc->sc_mtx); 1174 if (len != n) { 1175 error = -EBUSY; 1176 goto out; 1177 } 1178 /* 1179 * The interrupt could already have been received while the mutex was 1180 * released. Otherwise, wait for it. 1181 */ 1182 if (sc->sc_resp_state == UHIDPP_RESP_WAIT) { 1183 /* Timeout taken from the hid-logitech-hidpp Linux driver. */ 1184 error = uhidpp_sleep(sc, SEC_TO_NSEC(5)); 1185 if (error) { 1186 error = -error; 1187 goto out; 1188 } 1189 } 1190 1191 if (sc->sc_resp_state == UHIDPP_RESP_ERROR) 1192 error = -EIO; 1193 else if (sc->sc_resp_state == HIDPP_REPORT_ID_SHORT && 1194 resp->rap.sub_id == HIDPP_ERROR) 1195 error = resp->rap.params[1]; 1196 else if (sc->sc_resp_state == HIDPP_REPORT_ID_LONG && 1197 resp->fap.feature_idx == HIDPP20_ERROR) 1198 error = resp->fap.params[1]; 1199 1200 out: 1201 sc->sc_req = NULL; 1202 sc->sc_resp = NULL; 1203 sc->sc_resp_state = UHIDPP_RESP_NONE; 1204 wakeup(sc); 1205 return error; 1206 } 1207 1208 #ifdef UHIDPP_DEBUG 1209 1210 void 1211 uhidd_dump_report(const char *prefix, uint8_t repid, const unsigned char *buf, 1212 u_int buflen) 1213 { 1214 u_int i; 1215 1216 printf("%s: %02x ", prefix, repid); 1217 for (i = 0; i < buflen; i++) { 1218 printf("%02x%s", buf[i], 1219 i == 2 ? " [" : (i + 1 < buflen ? " " : "")); 1220 } 1221 printf("]\n"); 1222 } 1223 1224 #endif 1225