1 /* $OpenBSD: ihidev.c,v 1.39 2025/01/13 15:33:34 kirill Exp $ */ 2 /* 3 * HID-over-i2c driver 4 * 5 * https://msdn.microsoft.com/en-us/library/windows/hardware/dn642101%28v=vs.85%29.aspx 6 * 7 * Copyright (c) 2015, 2016 joshua stein <jcs@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <sys/param.h> 23 #include <sys/systm.h> 24 #include <sys/device.h> 25 #include <sys/malloc.h> 26 #include <sys/stdint.h> 27 28 #include <dev/i2c/i2cvar.h> 29 #include <dev/i2c/ihidev.h> 30 31 #include <dev/hid/hid.h> 32 33 /* #define IHIDEV_DEBUG */ 34 35 #ifdef IHIDEV_DEBUG 36 #define DPRINTF(x) printf x 37 #else 38 #define DPRINTF(x) 39 #endif 40 41 #define SLOW_POLL_MS 200 42 #define FAST_POLL_MS 10 43 44 /* 7.2 */ 45 enum { 46 I2C_HID_CMD_DESCR = 0x0, 47 I2C_HID_CMD_RESET = 0x1, 48 I2C_HID_CMD_GET_REPORT = 0x2, 49 I2C_HID_CMD_SET_REPORT = 0x3, 50 I2C_HID_CMD_GET_IDLE = 0x4, 51 I2C_HID_CMD_SET_IDLE = 0x5, 52 I2C_HID_CMD_GET_PROTO = 0x6, 53 I2C_HID_CMD_SET_PROTO = 0x7, 54 I2C_HID_CMD_SET_POWER = 0x8, 55 56 /* pseudo commands */ 57 I2C_HID_REPORT_DESCR = 0x100, 58 I2C_HID_RESET_RESPONSE = 0x101, 59 }; 60 61 static int I2C_HID_POWER_ON = 0x0; 62 static int I2C_HID_POWER_OFF = 0x1; 63 64 int ihidev_match(struct device *, void *, void *); 65 void ihidev_attach(struct device *, struct device *, void *); 66 int ihidev_detach(struct device *, int); 67 int ihidev_activate(struct device *, int); 68 69 int ihidev_hid_command(struct ihidev_softc *, int, void *); 70 int ihidev_intr(void *); 71 int ihidev_poweron(struct ihidev_softc *); 72 int ihidev_reset(struct ihidev_softc *); 73 int ihidev_hid_desc_parse(struct ihidev_softc *); 74 75 int ihidev_maxrepid(void *buf, int len); 76 int ihidev_print(void *aux, const char *pnp); 77 int ihidev_submatch(struct device *parent, void *cf, void *aux); 78 79 #define IHIDEV_QUIRK_RE_POWER_ON 0x1 80 81 const struct ihidev_quirks { 82 uint16_t ihq_vid; 83 uint16_t ihq_pid; 84 int ihq_quirks; 85 } ihidev_devs[] = { 86 /* HONOR MagicBook Art 14 Touchpad (QTEC0002) */ 87 { 0x35cc, 0x0104, IHIDEV_QUIRK_RE_POWER_ON }, 88 }; 89 90 const struct cfattach ihidev_ca = { 91 sizeof(struct ihidev_softc), 92 ihidev_match, 93 ihidev_attach, 94 ihidev_detach, 95 ihidev_activate, 96 }; 97 98 struct cfdriver ihidev_cd = { 99 NULL, "ihidev", DV_DULL 100 }; 101 102 int 103 ihidev_match(struct device *parent, void *match, void *aux) 104 { 105 struct i2c_attach_args *ia = aux; 106 107 if (strcmp(ia->ia_name, "ihidev") == 0) 108 return (1); 109 110 return (0); 111 } 112 113 int 114 ihidev_quirks(struct ihidev_softc *sc) 115 { 116 const struct ihidev_quirks *q; 117 uint16_t vid, pid; 118 int i, nent; 119 120 nent = nitems(ihidev_devs); 121 122 vid = letoh16(sc->hid_desc.wVendorID); 123 pid = letoh16(sc->hid_desc.wProductID); 124 125 for (i = 0, q = ihidev_devs; i < nent; i++, q++) 126 if (vid == q->ihq_vid && pid == q->ihq_pid) 127 return (q->ihq_quirks); 128 129 return (0); 130 } 131 132 void 133 ihidev_attach(struct device *parent, struct device *self, void *aux) 134 { 135 struct ihidev_softc *sc = (struct ihidev_softc *)self; 136 struct i2c_attach_args *ia = aux; 137 struct ihidev_attach_arg iha; 138 struct device *dev; 139 int repid, repsz; 140 int repsizes[256]; 141 142 sc->sc_tag = ia->ia_tag; 143 sc->sc_addr = ia->ia_addr; 144 sc->sc_hid_desc_addr = ia->ia_size; 145 146 if (ihidev_hid_command(sc, I2C_HID_CMD_DESCR, NULL) || 147 ihidev_hid_desc_parse(sc)) { 148 printf(", failed fetching initial HID descriptor\n"); 149 return; 150 } 151 152 sc->sc_nrepid = ihidev_maxrepid(sc->sc_report, sc->sc_reportlen); 153 if (sc->sc_nrepid < 0) 154 return; 155 156 sc->sc_nrepid++; 157 sc->sc_subdevs = mallocarray(sc->sc_nrepid, sizeof(struct ihidev *), 158 M_DEVBUF, M_WAITOK | M_ZERO); 159 160 /* find largest report size and allocate memory for input buffer */ 161 sc->sc_isize = letoh16(sc->hid_desc.wMaxInputLength); 162 for (repid = 0; repid < sc->sc_nrepid; repid++) { 163 repsz = hid_report_size(sc->sc_report, sc->sc_reportlen, 164 hid_input, repid); 165 repsizes[repid] = repsz; 166 if (repsz > sc->sc_isize) 167 sc->sc_isize = repsz; 168 if (repsz != 0) 169 DPRINTF(("%s: repid %d size %d\n", sc->sc_dev.dv_xname, 170 repid, repsz)); 171 } 172 sc->sc_ibuf = malloc(sc->sc_isize, M_DEVBUF, M_WAITOK | M_ZERO); 173 174 if (ia->ia_intr) { 175 printf(" %s", iic_intr_string(sc->sc_tag, ia->ia_intr)); 176 177 sc->sc_ih = iic_intr_establish(sc->sc_tag, ia->ia_intr, 178 IPL_TTY, ihidev_intr, sc, sc->sc_dev.dv_xname); 179 if (sc->sc_ih == NULL) 180 printf("%s: can't establish interrupt\n", 181 sc->sc_dev.dv_xname); 182 } 183 184 if (ia->ia_poll || !sc->sc_ih) { 185 printf(" (polling)"); 186 sc->sc_poll = 1; 187 sc->sc_fastpoll = 1; 188 } 189 190 printf(", vendor 0x%x product 0x%x, %s\n", 191 letoh16(sc->hid_desc.wVendorID), letoh16(sc->hid_desc.wProductID), 192 (char *)ia->ia_cookie); 193 194 printf("%s: %d report id%s\n", sc->sc_dev.dv_xname, (sc->sc_nrepid - 1), 195 (sc->sc_nrepid - 1) > 1 ? "s" : ""); 196 197 iha.iaa = ia; 198 iha.parent = sc; 199 200 /* Look for a driver claiming multiple report IDs first. */ 201 iha.reportid = IHIDEV_CLAIM_MULTIPLEID; 202 iha.nclaims = 0; 203 dev = config_found_sm((struct device *)sc, &iha, NULL, 204 ihidev_submatch); 205 if (dev != NULL) { 206 for (repid = 0; repid < iha.nclaims; repid++) { 207 sc->sc_subdevs[iha.claims[repid]] = 208 (struct ihidev *)dev; 209 } 210 } 211 212 for (repid = 0; repid < sc->sc_nrepid; repid++) { 213 if (sc->sc_subdevs[repid] != NULL) 214 continue; 215 216 if (hid_report_size(sc->sc_report, sc->sc_reportlen, hid_input, 217 repid) == 0 && 218 hid_report_size(sc->sc_report, sc->sc_reportlen, 219 hid_output, repid) == 0 && 220 hid_report_size(sc->sc_report, sc->sc_reportlen, 221 hid_feature, repid) == 0) 222 continue; 223 224 iha.reportid = repid; 225 dev = config_found_sm(self, &iha, ihidev_print, 226 ihidev_submatch); 227 sc->sc_subdevs[repid] = (struct ihidev *)dev; 228 } 229 230 if (sc->sc_refcnt > 0) 231 return; 232 233 /* power down until we're opened */ 234 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, &I2C_HID_POWER_OFF)) { 235 printf("%s: failed to power down\n", sc->sc_dev.dv_xname); 236 return; 237 } 238 } 239 240 int 241 ihidev_detach(struct device *self, int flags) 242 { 243 struct ihidev_softc *sc = (struct ihidev_softc *)self; 244 245 if (sc->sc_ih != NULL) { 246 iic_intr_disestablish(sc->sc_tag, sc->sc_ih); 247 sc->sc_ih = NULL; 248 } 249 250 if (sc->sc_ibuf != NULL) { 251 free(sc->sc_ibuf, M_DEVBUF, sc->sc_isize); 252 sc->sc_ibuf = NULL; 253 } 254 255 if (sc->sc_report != NULL) 256 free(sc->sc_report, M_DEVBUF, sc->sc_reportlen); 257 258 return (0); 259 } 260 261 int 262 ihidev_activate(struct device *self, int act) 263 { 264 struct ihidev_softc *sc = (struct ihidev_softc *)self; 265 int rv; 266 267 DPRINTF(("%s(%d)\n", __func__, act)); 268 269 switch (act) { 270 case DVACT_QUIESCE: 271 rv = config_activate_children(self, act); 272 sc->sc_dying = 1; 273 if (sc->sc_poll && timeout_initialized(&sc->sc_timer)) { 274 DPRINTF(("%s: cancelling polling\n", 275 sc->sc_dev.dv_xname)); 276 timeout_del_barrier(&sc->sc_timer); 277 } 278 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, 279 &I2C_HID_POWER_OFF)) 280 printf("%s: failed to power down\n", 281 sc->sc_dev.dv_xname); 282 break; 283 case DVACT_WAKEUP: 284 ihidev_poweron(sc); 285 sc->sc_dying = 0; 286 if (sc->sc_poll && timeout_initialized(&sc->sc_timer)) 287 timeout_add(&sc->sc_timer, 2000); 288 rv = config_activate_children(self, act); 289 break; 290 default: 291 rv = config_activate_children(self, act); 292 break; 293 } 294 return rv; 295 } 296 297 void 298 ihidev_sleep(struct ihidev_softc *sc, int ms) 299 { 300 if (cold) 301 delay(ms * 1000); 302 else 303 tsleep_nsec(&sc, PWAIT, "ihidev", MSEC_TO_NSEC(ms)); 304 } 305 306 int 307 ihidev_hid_command(struct ihidev_softc *sc, int hidcmd, void *arg) 308 { 309 int i, res = 1; 310 311 iic_acquire_bus(sc->sc_tag, 0); 312 313 switch (hidcmd) { 314 case I2C_HID_CMD_DESCR: { 315 /* 316 * 5.2.2 - HID Descriptor Retrieval 317 * register is passed from the controller 318 */ 319 uint8_t cmd[] = { 320 htole16(sc->sc_hid_desc_addr) & 0xff, 321 htole16(sc->sc_hid_desc_addr) >> 8, 322 }; 323 324 DPRINTF(("%s: HID command I2C_HID_CMD_DESCR at 0x%x\n", 325 sc->sc_dev.dv_xname, htole16(sc->sc_hid_desc_addr))); 326 327 /* 20 00 */ 328 res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 329 &cmd, sizeof(cmd), &sc->hid_desc_buf, 330 sizeof(struct i2c_hid_desc), 0); 331 332 DPRINTF(("%s: HID descriptor:", sc->sc_dev.dv_xname)); 333 for (i = 0; i < sizeof(struct i2c_hid_desc); i++) 334 DPRINTF((" %.2x", sc->hid_desc_buf[i])); 335 DPRINTF(("\n")); 336 337 break; 338 } 339 case I2C_HID_CMD_RESET: { 340 uint8_t cmd[] = { 341 htole16(sc->hid_desc.wCommandRegister) & 0xff, 342 htole16(sc->hid_desc.wCommandRegister) >> 8, 343 0, 344 I2C_HID_CMD_RESET, 345 }; 346 347 DPRINTF(("%s: HID command I2C_HID_CMD_RESET\n", 348 sc->sc_dev.dv_xname)); 349 350 /* 22 00 00 01 */ 351 res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 352 &cmd, sizeof(cmd), NULL, 0, 0); 353 354 break; 355 } 356 case I2C_HID_CMD_GET_REPORT: { 357 struct i2c_hid_report_request *rreq = 358 (struct i2c_hid_report_request *)arg; 359 360 uint8_t cmd[] = { 361 htole16(sc->hid_desc.wCommandRegister) & 0xff, 362 htole16(sc->hid_desc.wCommandRegister) >> 8, 363 0, 364 I2C_HID_CMD_GET_REPORT, 365 0, 0, 0, 366 }; 367 int cmdlen = 7; 368 int dataoff = 4; 369 int report_id = rreq->id; 370 int report_id_len = 1; 371 int report_len = rreq->len + 2; 372 int d; 373 uint8_t *tmprep; 374 375 DPRINTF(("%s: HID command I2C_HID_CMD_GET_REPORT %d " 376 "(type %d, len %d)\n", sc->sc_dev.dv_xname, report_id, 377 rreq->type, rreq->len)); 378 379 /* 380 * 7.2.2.4 - "The protocol is optimized for Report < 15. If a 381 * report ID >= 15 is necessary, then the Report ID in the Low 382 * Byte must be set to 1111 and a Third Byte is appended to the 383 * protocol. This Third Byte contains the entire/actual report 384 * ID." 385 */ 386 if (report_id >= 15) { 387 cmd[dataoff++] = report_id; 388 report_id = 15; 389 report_id_len = 2; 390 } else 391 cmdlen--; 392 393 cmd[2] = report_id | rreq->type << 4; 394 395 cmd[dataoff++] = sc->hid_desc.wDataRegister & 0xff; 396 cmd[dataoff] = sc->hid_desc.wDataRegister >> 8; 397 398 /* 399 * 7.2.2.2 - Response will be a 2-byte length value, the report 400 * id with length determined above, and then the report. 401 * Allocate rreq->len + 2 + 2 bytes, read into that temporary 402 * buffer, and then copy only the report back out to 403 * rreq->data. 404 */ 405 report_len += report_id_len; 406 tmprep = malloc(report_len, M_DEVBUF, M_WAITOK | M_ZERO); 407 408 /* type 3 id 8: 22 00 38 02 23 00 */ 409 res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 410 &cmd, cmdlen, tmprep, report_len, 0); 411 412 d = tmprep[0] | tmprep[1] << 8; 413 if (d != report_len) 414 DPRINTF(("%s: response size %d != expected length %d\n", 415 sc->sc_dev.dv_xname, d, report_len)); 416 417 if (report_id_len == 2) 418 d = tmprep[2] | tmprep[3] << 8; 419 else 420 d = tmprep[2]; 421 422 if (d != rreq->id) { 423 DPRINTF(("%s: response report id %d != %d\n", 424 sc->sc_dev.dv_xname, d, rreq->id)); 425 iic_release_bus(sc->sc_tag, 0); 426 free(tmprep, M_DEVBUF, report_len); 427 return (1); 428 } 429 430 DPRINTF(("%s: response:", sc->sc_dev.dv_xname)); 431 for (i = 0; i < report_len; i++) 432 DPRINTF((" %.2x", tmprep[i])); 433 DPRINTF(("\n")); 434 435 memcpy(rreq->data, tmprep + 2 + report_id_len, rreq->len); 436 free(tmprep, M_DEVBUF, report_len); 437 438 break; 439 } 440 case I2C_HID_CMD_SET_REPORT: { 441 struct i2c_hid_report_request *rreq = 442 (struct i2c_hid_report_request *)arg; 443 444 uint8_t cmd[] = { 445 htole16(sc->hid_desc.wCommandRegister) & 0xff, 446 htole16(sc->hid_desc.wCommandRegister) >> 8, 447 0, 448 I2C_HID_CMD_SET_REPORT, 449 0, 0, 0, 0, 0, 0, 450 }; 451 int cmdlen = sizeof(cmd); 452 int report_id = rreq->id; 453 int report_len = 2 + (report_id ? 1 : 0) + rreq->len; 454 int dataoff; 455 uint8_t *finalcmd; 456 457 DPRINTF(("%s: HID command I2C_HID_CMD_SET_REPORT %d " 458 "(type %d, len %d):", sc->sc_dev.dv_xname, report_id, 459 rreq->type, rreq->len)); 460 for (i = 0; i < rreq->len; i++) 461 DPRINTF((" %.2x", ((uint8_t *)rreq->data)[i])); 462 DPRINTF(("\n")); 463 464 /* 465 * 7.2.3.4 - "The protocol is optimized for Report < 15. If a 466 * report ID >= 15 is necessary, then the Report ID in the Low 467 * Byte must be set to 1111 and a Third Byte is appended to the 468 * protocol. This Third Byte contains the entire/actual report 469 * ID." 470 */ 471 dataoff = 4; 472 if (report_id >= 15) { 473 cmd[dataoff++] = report_id; 474 report_id = 15; 475 } else 476 cmdlen--; 477 478 cmd[2] = report_id | rreq->type << 4; 479 480 cmd[dataoff++] = htole16(sc->hid_desc.wDataRegister) & 0xff; 481 cmd[dataoff++] = htole16(sc->hid_desc.wDataRegister) >> 8; 482 483 cmd[dataoff++] = report_len & 0xff; 484 cmd[dataoff++] = report_len >> 8; 485 cmd[dataoff] = rreq->id; 486 487 finalcmd = malloc(cmdlen + rreq->len, M_DEVBUF, 488 M_WAITOK | M_ZERO); 489 490 memcpy(finalcmd, cmd, cmdlen); 491 memcpy(finalcmd + cmdlen, rreq->data, rreq->len); 492 493 /* type 3 id 4: 22 00 34 03 23 00 04 00 04 03 */ 494 res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 495 finalcmd, cmdlen + rreq->len, NULL, 0, 0); 496 497 free(finalcmd, M_DEVBUF, cmdlen + rreq->len); 498 499 break; 500 } 501 502 case I2C_HID_CMD_SET_POWER: { 503 int power = *(int *)arg; 504 uint8_t cmd[] = { 505 htole16(sc->hid_desc.wCommandRegister) & 0xff, 506 htole16(sc->hid_desc.wCommandRegister) >> 8, 507 power, 508 I2C_HID_CMD_SET_POWER, 509 }; 510 511 DPRINTF(("%s: HID command I2C_HID_CMD_SET_POWER(%d)\n", 512 sc->sc_dev.dv_xname, power)); 513 514 /* 22 00 00 08 */ 515 res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 516 &cmd, sizeof(cmd), NULL, 0, 0); 517 518 break; 519 } 520 case I2C_HID_REPORT_DESCR: { 521 uint8_t cmd[] = { 522 htole16(sc->hid_desc.wReportDescRegister) & 0xff, 523 htole16(sc->hid_desc.wReportDescRegister) >> 8, 524 }; 525 526 DPRINTF(("%s: HID command I2C_HID_REPORT_DESCR at 0x%x with " 527 "size %d\n", sc->sc_dev.dv_xname, cmd[0], 528 sc->sc_reportlen)); 529 530 /* 20 00 */ 531 res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 532 &cmd, sizeof(cmd), sc->sc_report, sc->sc_reportlen, 0); 533 534 DPRINTF(("%s: HID report descriptor:", sc->sc_dev.dv_xname)); 535 for (i = 0; i < sc->sc_reportlen; i++) 536 DPRINTF((" %.2x", sc->sc_report[i])); 537 DPRINTF(("\n")); 538 539 break; 540 } 541 case I2C_HID_RESET_RESPONSE: { 542 int i; 543 uint8_t buf[2] = { 0xff, 0xff }; 544 545 DPRINTF(("%s: HID command I2C_HID_RESET_RESPONSE\n", 546 sc->sc_dev.dv_xname)); 547 548 /* 549 * 7.2.1 states that a device should response for RESET 550 * in less than 5 seconds. It uses poll instead of 551 * tsleep because interrupts are blocked during autoconf. 552 */ 553 for (i = 0; i < 50; i++) { 554 ihidev_sleep(sc, 100); 555 res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 556 sc->sc_addr, NULL, 0, buf, sizeof(buf), 0); 557 DPRINTF(("%s: read attempt %d: 0x%x, 0x%x, res: %d\n", 558 sc->sc_dev.dv_xname, i, buf[0], buf[1], res)); 559 if (!res) 560 res = (buf[0] != 0x00 || buf[1] != 0x00); 561 if (!res) 562 break; 563 } 564 565 break; 566 } 567 default: 568 printf("%s: unknown command %d\n", sc->sc_dev.dv_xname, 569 hidcmd); 570 } 571 572 iic_release_bus(sc->sc_tag, 0); 573 574 return (res); 575 } 576 577 int 578 ihidev_poweron(struct ihidev_softc *sc) 579 { 580 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, &I2C_HID_POWER_ON)) { 581 printf("%s: failed to power on\n", sc->sc_dev.dv_xname); 582 return (1); 583 } 584 585 ihidev_sleep(sc, 100); 586 587 return 0; 588 } 589 590 591 int 592 ihidev_reset(struct ihidev_softc *sc) 593 { 594 DPRINTF(("%s: resetting\n", sc->sc_dev.dv_xname)); 595 596 if (ihidev_poweron(sc)) 597 return (1); 598 599 if (ihidev_hid_command(sc, I2C_HID_CMD_RESET, 0)) { 600 printf("%s: failed to reset hardware\n", sc->sc_dev.dv_xname); 601 602 ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, 603 &I2C_HID_POWER_OFF); 604 605 return (1); 606 } 607 608 if (ihidev_hid_command(sc, I2C_HID_RESET_RESPONSE, 0)) { 609 printf("%s: unexpected reset response\n", 610 sc->sc_dev.dv_xname); 611 return (1); 612 } 613 614 return (0); 615 } 616 617 /* 618 * 5.2.2 - HID Descriptor Retrieval 619 * 620 * parse HID Descriptor that has already been read into hid_desc with 621 * I2C_HID_CMD_DESCR 622 */ 623 int 624 ihidev_hid_desc_parse(struct ihidev_softc *sc) 625 { 626 sc->sc_quirks = ihidev_quirks(sc); 627 628 /* must be v01.00 */ 629 if (letoh16(sc->hid_desc.bcdVersion) != 0x0100) { 630 printf("%s: bad HID descriptor bcdVersion (0x%x)\n", 631 sc->sc_dev.dv_xname, 632 letoh16(sc->hid_desc.bcdVersion)); 633 return (1); 634 } 635 636 /* must be 30 bytes for v1.00 */ 637 if (letoh16(sc->hid_desc.wHIDDescLength != 638 sizeof(struct i2c_hid_desc))) { 639 printf("%s: bad HID descriptor size (%d != %zu)\n", 640 sc->sc_dev.dv_xname, 641 letoh16(sc->hid_desc.wHIDDescLength), 642 sizeof(struct i2c_hid_desc)); 643 return (1); 644 } 645 646 if (letoh16(sc->hid_desc.wReportDescLength) <= 0) { 647 printf("%s: bad HID report descriptor size (%d)\n", 648 sc->sc_dev.dv_xname, 649 letoh16(sc->hid_desc.wReportDescLength)); 650 return (1); 651 } 652 653 if (ihidev_reset(sc)) 654 return (1); 655 656 sc->sc_reportlen = letoh16(sc->hid_desc.wReportDescLength); 657 sc->sc_report = malloc(sc->sc_reportlen, M_DEVBUF, M_WAITOK | M_ZERO); 658 659 if (ihidev_hid_command(sc, I2C_HID_REPORT_DESCR, 0)) { 660 printf("%s: failed fetching HID report\n", 661 sc->sc_dev.dv_xname); 662 return (1); 663 } 664 665 if (sc->sc_quirks & IHIDEV_QUIRK_RE_POWER_ON) { 666 if (ihidev_poweron(sc)) 667 return (1); 668 669 /* 670 * 7.2.8 states that a device shall not respond back 671 * after receiving the power on command, and must ensure 672 * that it transitions to power on state in less than 1 673 * second. The ihidev_poweron function uses a shorter 674 * sleep, sufficient for the ON-RESET sequence. Here, 675 * however, it sleeps for the full second to accommodate 676 * cold boot scenarios on affected devices. 677 */ 678 679 ihidev_sleep(sc, 1000); 680 } 681 682 return (0); 683 } 684 685 void 686 ihidev_poll(void *arg) 687 { 688 struct ihidev_softc *sc = arg; 689 690 sc->sc_frompoll = 1; 691 ihidev_intr(sc); 692 sc->sc_frompoll = 0; 693 } 694 695 int 696 ihidev_intr(void *arg) 697 { 698 struct ihidev_softc *sc = arg; 699 struct ihidev *scd; 700 int psize, res, i, fast = 0; 701 u_char *p; 702 u_int rep = 0; 703 704 if (sc->sc_poll && !sc->sc_frompoll) { 705 DPRINTF(("%s: received interrupt while polling, disabling " 706 "polling\n", sc->sc_dev.dv_xname)); 707 sc->sc_poll = 0; 708 timeout_del_barrier(&sc->sc_timer); 709 } 710 711 /* 712 * XXX: force I2C_F_POLL for now to avoid dwiic interrupting 713 * while we are interrupting 714 */ 715 716 iic_acquire_bus(sc->sc_tag, I2C_F_POLL); 717 res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, NULL, 0, 718 sc->sc_ibuf, letoh16(sc->hid_desc.wMaxInputLength), I2C_F_POLL); 719 iic_release_bus(sc->sc_tag, I2C_F_POLL); 720 721 /* 722 * 6.1.1 - First two bytes are the packet length, which must be less 723 * than or equal to wMaxInputLength 724 */ 725 psize = sc->sc_ibuf[0] | sc->sc_ibuf[1] << 8; 726 if (psize <= 2 || psize > sc->sc_isize) { 727 if (sc->sc_poll) { 728 /* 729 * TODO: all fingers are up, should we pass to hid 730 * layer? 731 */ 732 sc->sc_fastpoll = 0; 733 goto more_polling; 734 } else 735 DPRINTF(("%s: %s: invalid packet size (%d vs. %d)\n", 736 sc->sc_dev.dv_xname, __func__, psize, 737 sc->sc_isize)); 738 return (1); 739 } 740 741 /* 3rd byte is the report id */ 742 p = sc->sc_ibuf + 2; 743 psize -= 2; 744 if (sc->sc_nrepid != 1) 745 rep = *p++, psize--; 746 747 if (rep >= sc->sc_nrepid) { 748 printf("%s: %s: bad report id %d\n", sc->sc_dev.dv_xname, 749 __func__, rep); 750 if (sc->sc_poll) { 751 sc->sc_fastpoll = 0; 752 goto more_polling; 753 } 754 return (1); 755 } 756 757 DPRINTF(("%s: %s: hid input (rep %d):", sc->sc_dev.dv_xname, __func__, 758 rep)); 759 for (i = 0; i < psize; i++) { 760 if (i > 0 && p[i] != 0 && p[i] != 0xff) { 761 fast = 1; 762 } 763 DPRINTF((" %.2x", p[i])); 764 } 765 DPRINTF(("\n")); 766 767 scd = sc->sc_subdevs[rep]; 768 if (scd == NULL || !(scd->sc_state & IHIDEV_OPEN)) { 769 if (sc->sc_poll) { 770 if (sc->sc_fastpoll) { 771 DPRINTF(("%s: fast->slow polling\n", 772 sc->sc_dev.dv_xname)); 773 sc->sc_fastpoll = 0; 774 } 775 goto more_polling; 776 } 777 return (1); 778 } 779 780 if (!sc->sc_dying) 781 scd->sc_intr(scd, p, psize); 782 783 if (sc->sc_poll && (fast != sc->sc_fastpoll)) { 784 DPRINTF(("%s: %s->%s polling\n", sc->sc_dev.dv_xname, 785 sc->sc_fastpoll ? "fast" : "slow", 786 fast ? "fast" : "slow")); 787 sc->sc_fastpoll = fast; 788 } 789 790 more_polling: 791 if (sc->sc_poll && sc->sc_refcnt && !sc->sc_dying && 792 !timeout_pending(&sc->sc_timer)) 793 timeout_add_msec(&sc->sc_timer, 794 sc->sc_fastpoll ? FAST_POLL_MS : SLOW_POLL_MS); 795 796 return (1); 797 } 798 799 int 800 ihidev_maxrepid(void *buf, int len) 801 { 802 struct hid_data *d; 803 struct hid_item h; 804 int maxid; 805 806 maxid = -1; 807 h.report_ID = 0; 808 for (d = hid_start_parse(buf, len, hid_all); hid_get_item(d, &h);) 809 if (h.report_ID > maxid) 810 maxid = h.report_ID; 811 hid_end_parse(d); 812 813 return (maxid); 814 } 815 816 int 817 ihidev_print(void *aux, const char *pnp) 818 { 819 struct ihidev_attach_arg *iha = aux; 820 821 if (pnp) 822 printf("hid at %s", pnp); 823 824 if (iha->reportid != 0) 825 printf(" reportid %d", iha->reportid); 826 827 return (UNCONF); 828 } 829 830 int 831 ihidev_submatch(struct device *parent, void *match, void *aux) 832 { 833 struct ihidev_attach_arg *iha = aux; 834 struct cfdata *cf = match; 835 836 if (cf->ihidevcf_reportid != IHIDEV_UNK_REPORTID && 837 cf->ihidevcf_reportid != iha->reportid) 838 return (0); 839 840 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 841 } 842 843 int 844 ihidev_open(struct ihidev *scd) 845 { 846 struct ihidev_softc *sc = scd->sc_parent; 847 848 DPRINTF(("%s: %s: state=%d refcnt=%d\n", sc->sc_dev.dv_xname, 849 __func__, scd->sc_state, sc->sc_refcnt)); 850 851 if (scd->sc_state & IHIDEV_OPEN) 852 return (EBUSY); 853 854 scd->sc_state |= IHIDEV_OPEN; 855 856 if (sc->sc_refcnt++ || sc->sc_isize == 0) 857 return (0); 858 859 /* power on */ 860 ihidev_poweron(sc); 861 862 if (sc->sc_poll) { 863 if (!timeout_initialized(&sc->sc_timer)) 864 timeout_set(&sc->sc_timer, (void *)ihidev_poll, sc); 865 if (!timeout_pending(&sc->sc_timer)) 866 timeout_add(&sc->sc_timer, FAST_POLL_MS); 867 } 868 869 return (0); 870 } 871 872 void 873 ihidev_close(struct ihidev *scd) 874 { 875 struct ihidev_softc *sc = scd->sc_parent; 876 877 DPRINTF(("%s: %s: state=%d refcnt=%d\n", sc->sc_dev.dv_xname, 878 __func__, scd->sc_state, sc->sc_refcnt)); 879 880 if (!(scd->sc_state & IHIDEV_OPEN)) 881 return; 882 883 scd->sc_state &= ~IHIDEV_OPEN; 884 885 if (--sc->sc_refcnt) 886 return; 887 888 /* no sub-devices open, conserve power */ 889 890 if (sc->sc_poll && timeout_pending(&sc->sc_timer)) 891 timeout_del(&sc->sc_timer); 892 893 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, &I2C_HID_POWER_OFF)) 894 printf("%s: failed to power down\n", sc->sc_dev.dv_xname); 895 } 896 897 int 898 ihidev_ioctl(struct ihidev *sc, u_long cmd, caddr_t addr, int flag, 899 struct proc *p) 900 { 901 return -1; 902 } 903 904 void 905 ihidev_get_report_desc(struct ihidev_softc *sc, void **desc, int *size) 906 { 907 *desc = sc->sc_report; 908 *size = sc->sc_reportlen; 909 } 910 911 int 912 ihidev_report_type_conv(int hid_type_id) 913 { 914 switch (hid_type_id) { 915 case hid_input: 916 return I2C_HID_REPORT_TYPE_INPUT; 917 case hid_output: 918 return I2C_HID_REPORT_TYPE_OUTPUT; 919 case hid_feature: 920 return I2C_HID_REPORT_TYPE_FEATURE; 921 default: 922 return -1; 923 } 924 } 925 926 int 927 ihidev_get_report(struct device *dev, int type, int id, void *data, int len) 928 { 929 struct ihidev_softc *sc = (struct ihidev_softc *)dev; 930 struct i2c_hid_report_request rreq; 931 932 rreq.type = type; 933 rreq.id = id; 934 rreq.data = data; 935 rreq.len = len; 936 937 if (ihidev_hid_command(sc, I2C_HID_CMD_GET_REPORT, &rreq)) { 938 printf("%s: failed fetching report\n", sc->sc_dev.dv_xname); 939 return (1); 940 } 941 942 return 0; 943 } 944 945 int 946 ihidev_set_report(struct device *dev, int type, int id, void *data, int len) 947 { 948 struct ihidev_softc *sc = (struct ihidev_softc *)dev; 949 struct i2c_hid_report_request rreq; 950 951 rreq.type = type; 952 rreq.id = id; 953 rreq.data = data; 954 rreq.len = len; 955 956 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_REPORT, &rreq)) { 957 printf("%s: failed setting report\n", sc->sc_dev.dv_xname); 958 return (1); 959 } 960 961 return 0; 962 } 963 964 int 965 ihidev_send_report(struct device *dev, int repid, void *data, int data_len) 966 { 967 struct ihidev_softc *sc = (struct ihidev_softc *)dev; 968 uint8_t *finalcmd, cmd[5]; 969 int cmd_len, report_len, res; 970 971 cmd_len = sizeof(cmd); 972 report_len = 2 + 1 + data_len; 973 974 cmd[0] = htole16(sc->hid_desc.wOutputRegister) & 0xff; 975 cmd[1] = htole16(sc->hid_desc.wOutputRegister) >> 8; 976 cmd[2] = report_len & 0xff; 977 cmd[3] = report_len >> 8; 978 cmd[4] = repid; 979 980 finalcmd = malloc(cmd_len + data_len, M_DEVBUF, M_NOWAIT | M_ZERO); 981 if (finalcmd == NULL) 982 return ENOMEM; 983 984 memcpy(finalcmd, cmd, cmd_len); 985 memcpy(finalcmd + cmd_len, data, data_len); 986 987 res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 988 finalcmd, cmd_len + data_len, NULL, 0, 0); 989 990 free(finalcmd, M_DEVBUF, cmd_len + data_len); 991 992 return res; 993 } 994