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