1 /* $OpenBSD: ihidev.c,v 1.29 2023/08/12 10:03:05 kettenis 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 }; 59 60 static int I2C_HID_POWER_ON = 0x0; 61 static int I2C_HID_POWER_OFF = 0x1; 62 63 int ihidev_match(struct device *, void *, void *); 64 void ihidev_attach(struct device *, struct device *, void *); 65 int ihidev_detach(struct device *, int); 66 int ihidev_activate(struct device *, int); 67 68 int ihidev_hid_command(struct ihidev_softc *, int, void *); 69 int ihidev_intr(void *); 70 int ihidev_reset(struct ihidev_softc *); 71 int ihidev_hid_desc_parse(struct ihidev_softc *); 72 73 int ihidev_maxrepid(void *buf, int len); 74 int ihidev_print(void *aux, const char *pnp); 75 int ihidev_submatch(struct device *parent, void *cf, void *aux); 76 77 const struct cfattach ihidev_ca = { 78 sizeof(struct ihidev_softc), 79 ihidev_match, 80 ihidev_attach, 81 ihidev_detach, 82 ihidev_activate, 83 }; 84 85 struct cfdriver ihidev_cd = { 86 NULL, "ihidev", DV_DULL 87 }; 88 89 int 90 ihidev_match(struct device *parent, void *match, void *aux) 91 { 92 struct i2c_attach_args *ia = aux; 93 94 if (strcmp(ia->ia_name, "ihidev") == 0) 95 return (1); 96 97 return (0); 98 } 99 100 void 101 ihidev_attach(struct device *parent, struct device *self, void *aux) 102 { 103 struct ihidev_softc *sc = (struct ihidev_softc *)self; 104 struct i2c_attach_args *ia = aux; 105 struct ihidev_attach_arg iha; 106 struct device *dev; 107 int repid, repsz; 108 int repsizes[256]; 109 110 sc->sc_tag = ia->ia_tag; 111 sc->sc_addr = ia->ia_addr; 112 sc->sc_hid_desc_addr = ia->ia_size; 113 114 if (ihidev_hid_command(sc, I2C_HID_CMD_DESCR, NULL) || 115 ihidev_hid_desc_parse(sc)) { 116 printf(", failed fetching initial HID descriptor\n"); 117 return; 118 } 119 120 if (ia->ia_intr) { 121 printf(" %s", iic_intr_string(sc->sc_tag, ia->ia_intr)); 122 123 sc->sc_ih = iic_intr_establish(sc->sc_tag, ia->ia_intr, 124 IPL_TTY, ihidev_intr, sc, sc->sc_dev.dv_xname); 125 if (sc->sc_ih == NULL) 126 printf(", can't establish interrupt"); 127 } 128 129 if (ia->ia_poll || !sc->sc_ih) { 130 printf(" (polling)"); 131 sc->sc_poll = 1; 132 sc->sc_fastpoll = 1; 133 } 134 135 printf(", vendor 0x%x product 0x%x, %s\n", 136 letoh16(sc->hid_desc.wVendorID), letoh16(sc->hid_desc.wProductID), 137 (char *)ia->ia_cookie); 138 139 sc->sc_nrepid = ihidev_maxrepid(sc->sc_report, sc->sc_reportlen); 140 if (sc->sc_nrepid < 0) 141 return; 142 143 printf("%s: %d report id%s\n", sc->sc_dev.dv_xname, sc->sc_nrepid, 144 sc->sc_nrepid > 1 ? "s" : ""); 145 146 sc->sc_nrepid++; 147 sc->sc_subdevs = mallocarray(sc->sc_nrepid, sizeof(struct ihidev *), 148 M_DEVBUF, M_NOWAIT | M_ZERO); 149 if (sc->sc_subdevs == NULL) { 150 printf("%s: failed allocating memory\n", sc->sc_dev.dv_xname); 151 return; 152 } 153 154 /* find largest report size and allocate memory for input buffer */ 155 sc->sc_isize = letoh16(sc->hid_desc.wMaxInputLength); 156 for (repid = 0; repid < sc->sc_nrepid; repid++) { 157 repsz = hid_report_size(sc->sc_report, sc->sc_reportlen, 158 hid_input, repid); 159 repsizes[repid] = repsz; 160 if (repsz > sc->sc_isize) 161 sc->sc_isize = repsz; 162 if (repsz != 0) 163 DPRINTF(("%s: repid %d size %d\n", sc->sc_dev.dv_xname, 164 repid, repsz)); 165 } 166 sc->sc_ibuf = malloc(sc->sc_isize, M_DEVBUF, M_NOWAIT | M_ZERO); 167 168 iha.iaa = ia; 169 iha.parent = sc; 170 171 /* Look for a driver claiming multiple report IDs first. */ 172 iha.reportid = IHIDEV_CLAIM_MULTIPLEID; 173 iha.nclaims = 0; 174 dev = config_found_sm((struct device *)sc, &iha, NULL, 175 ihidev_submatch); 176 if (dev != NULL) { 177 for (repid = 0; repid < iha.nclaims; repid++) { 178 sc->sc_subdevs[iha.claims[repid]] = 179 (struct ihidev *)dev; 180 } 181 } 182 183 for (repid = 0; repid < sc->sc_nrepid; repid++) { 184 if (sc->sc_subdevs[repid] != NULL) 185 continue; 186 187 if (hid_report_size(sc->sc_report, sc->sc_reportlen, hid_input, 188 repid) == 0 && 189 hid_report_size(sc->sc_report, sc->sc_reportlen, 190 hid_output, repid) == 0 && 191 hid_report_size(sc->sc_report, sc->sc_reportlen, 192 hid_feature, repid) == 0) 193 continue; 194 195 iha.reportid = repid; 196 dev = config_found_sm(self, &iha, ihidev_print, 197 ihidev_submatch); 198 sc->sc_subdevs[repid] = (struct ihidev *)dev; 199 } 200 201 if (sc->sc_refcnt > 0) 202 return; 203 204 /* power down until we're opened */ 205 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, &I2C_HID_POWER_OFF)) { 206 printf("%s: failed to power down\n", sc->sc_dev.dv_xname); 207 return; 208 } 209 } 210 211 int 212 ihidev_detach(struct device *self, int flags) 213 { 214 struct ihidev_softc *sc = (struct ihidev_softc *)self; 215 216 if (sc->sc_ih != NULL) { 217 iic_intr_disestablish(sc->sc_tag, sc->sc_ih); 218 sc->sc_ih = NULL; 219 } 220 221 if (sc->sc_ibuf != NULL) { 222 free(sc->sc_ibuf, M_DEVBUF, sc->sc_isize); 223 sc->sc_ibuf = NULL; 224 } 225 226 if (sc->sc_report != NULL) 227 free(sc->sc_report, M_DEVBUF, sc->sc_reportlen); 228 229 return (0); 230 } 231 232 int 233 ihidev_activate(struct device *self, int act) 234 { 235 struct ihidev_softc *sc = (struct ihidev_softc *)self; 236 237 DPRINTF(("%s(%d)\n", __func__, act)); 238 239 switch (act) { 240 case DVACT_QUIESCE: 241 sc->sc_dying = 1; 242 if (sc->sc_poll && timeout_initialized(&sc->sc_timer)) { 243 DPRINTF(("%s: cancelling polling\n", 244 sc->sc_dev.dv_xname)); 245 timeout_del_barrier(&sc->sc_timer); 246 } 247 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, 248 &I2C_HID_POWER_OFF)) 249 printf("%s: failed to power down\n", 250 sc->sc_dev.dv_xname); 251 break; 252 case DVACT_WAKEUP: 253 ihidev_reset(sc); 254 sc->sc_dying = 0; 255 if (sc->sc_poll && timeout_initialized(&sc->sc_timer)) 256 timeout_add(&sc->sc_timer, 2000); 257 break; 258 } 259 260 config_activate_children(self, act); 261 262 return 0; 263 } 264 265 void 266 ihidev_sleep(struct ihidev_softc *sc, int ms) 267 { 268 if (cold) 269 delay(ms * 1000); 270 else 271 tsleep_nsec(&sc, PWAIT, "ihidev", MSEC_TO_NSEC(ms)); 272 } 273 274 int 275 ihidev_hid_command(struct ihidev_softc *sc, int hidcmd, void *arg) 276 { 277 int i, res = 1; 278 279 iic_acquire_bus(sc->sc_tag, 0); 280 281 switch (hidcmd) { 282 case I2C_HID_CMD_DESCR: { 283 /* 284 * 5.2.2 - HID Descriptor Retrieval 285 * register is passed from the controller 286 */ 287 uint8_t cmd[] = { 288 htole16(sc->sc_hid_desc_addr) & 0xff, 289 htole16(sc->sc_hid_desc_addr) >> 8, 290 }; 291 292 DPRINTF(("%s: HID command I2C_HID_CMD_DESCR at 0x%x\n", 293 sc->sc_dev.dv_xname, htole16(sc->sc_hid_desc_addr))); 294 295 /* 20 00 */ 296 res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 297 &cmd, sizeof(cmd), &sc->hid_desc_buf, 298 sizeof(struct i2c_hid_desc), 0); 299 300 DPRINTF(("%s: HID descriptor:", sc->sc_dev.dv_xname)); 301 for (i = 0; i < sizeof(struct i2c_hid_desc); i++) 302 DPRINTF((" %.2x", sc->hid_desc_buf[i])); 303 DPRINTF(("\n")); 304 305 break; 306 } 307 case I2C_HID_CMD_RESET: { 308 uint8_t cmd[] = { 309 htole16(sc->hid_desc.wCommandRegister) & 0xff, 310 htole16(sc->hid_desc.wCommandRegister) >> 8, 311 0, 312 I2C_HID_CMD_RESET, 313 }; 314 315 DPRINTF(("%s: HID command I2C_HID_CMD_RESET\n", 316 sc->sc_dev.dv_xname)); 317 318 /* 22 00 00 01 */ 319 res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 320 &cmd, sizeof(cmd), NULL, 0, 0); 321 322 break; 323 } 324 case I2C_HID_CMD_GET_REPORT: { 325 struct i2c_hid_report_request *rreq = 326 (struct i2c_hid_report_request *)arg; 327 328 uint8_t cmd[] = { 329 htole16(sc->hid_desc.wCommandRegister) & 0xff, 330 htole16(sc->hid_desc.wCommandRegister) >> 8, 331 0, 332 I2C_HID_CMD_GET_REPORT, 333 0, 0, 0, 334 }; 335 int cmdlen = 7; 336 int dataoff = 4; 337 int report_id = rreq->id; 338 int report_id_len = 1; 339 int report_len = rreq->len + 2; 340 int d; 341 uint8_t *tmprep; 342 343 DPRINTF(("%s: HID command I2C_HID_CMD_GET_REPORT %d " 344 "(type %d, len %d)\n", sc->sc_dev.dv_xname, report_id, 345 rreq->type, rreq->len)); 346 347 /* 348 * 7.2.2.4 - "The protocol is optimized for Report < 15. If a 349 * report ID >= 15 is necessary, then the Report ID in the Low 350 * Byte must be set to 1111 and a Third Byte is appended to the 351 * protocol. This Third Byte contains the entire/actual report 352 * ID." 353 */ 354 if (report_id >= 15) { 355 cmd[dataoff++] = report_id; 356 report_id = 15; 357 report_id_len = 2; 358 } else 359 cmdlen--; 360 361 cmd[2] = report_id | rreq->type << 4; 362 363 cmd[dataoff++] = sc->hid_desc.wDataRegister & 0xff; 364 cmd[dataoff] = sc->hid_desc.wDataRegister >> 8; 365 366 /* 367 * 7.2.2.2 - Response will be a 2-byte length value, the report 368 * id with length determined above, and then the report. 369 * Allocate rreq->len + 2 + 2 bytes, read into that temporary 370 * buffer, and then copy only the report back out to 371 * rreq->data. 372 */ 373 report_len += report_id_len; 374 tmprep = malloc(report_len, M_DEVBUF, M_NOWAIT | M_ZERO); 375 376 /* type 3 id 8: 22 00 38 02 23 00 */ 377 res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 378 &cmd, cmdlen, tmprep, report_len, 0); 379 380 d = tmprep[0] | tmprep[1] << 8; 381 if (d != report_len) 382 DPRINTF(("%s: response size %d != expected length %d\n", 383 sc->sc_dev.dv_xname, d, report_len)); 384 385 if (report_id_len == 2) 386 d = tmprep[2] | tmprep[3] << 8; 387 else 388 d = tmprep[2]; 389 390 if (d != rreq->id) { 391 DPRINTF(("%s: response report id %d != %d\n", 392 sc->sc_dev.dv_xname, d, rreq->id)); 393 iic_release_bus(sc->sc_tag, 0); 394 free(tmprep, M_DEVBUF, report_len); 395 return (1); 396 } 397 398 DPRINTF(("%s: response:", sc->sc_dev.dv_xname)); 399 for (i = 0; i < report_len; i++) 400 DPRINTF((" %.2x", tmprep[i])); 401 DPRINTF(("\n")); 402 403 memcpy(rreq->data, tmprep + 2 + report_id_len, rreq->len); 404 free(tmprep, M_DEVBUF, report_len); 405 406 break; 407 } 408 case I2C_HID_CMD_SET_REPORT: { 409 struct i2c_hid_report_request *rreq = 410 (struct i2c_hid_report_request *)arg; 411 412 uint8_t cmd[] = { 413 htole16(sc->hid_desc.wCommandRegister) & 0xff, 414 htole16(sc->hid_desc.wCommandRegister) >> 8, 415 0, 416 I2C_HID_CMD_SET_REPORT, 417 0, 0, 0, 0, 0, 0, 418 }; 419 int cmdlen = sizeof(cmd); 420 int report_id = rreq->id; 421 int report_len = 2 + (report_id ? 1 : 0) + rreq->len; 422 int dataoff; 423 uint8_t *finalcmd; 424 425 DPRINTF(("%s: HID command I2C_HID_CMD_SET_REPORT %d " 426 "(type %d, len %d):", sc->sc_dev.dv_xname, report_id, 427 rreq->type, rreq->len)); 428 for (i = 0; i < rreq->len; i++) 429 DPRINTF((" %.2x", ((uint8_t *)rreq->data)[i])); 430 DPRINTF(("\n")); 431 432 /* 433 * 7.2.3.4 - "The protocol is optimized for Report < 15. If a 434 * report ID >= 15 is necessary, then the Report ID in the Low 435 * Byte must be set to 1111 and a Third Byte is appended to the 436 * protocol. This Third Byte contains the entire/actual report 437 * ID." 438 */ 439 dataoff = 4; 440 if (report_id >= 15) { 441 cmd[dataoff++] = report_id; 442 report_id = 15; 443 } else 444 cmdlen--; 445 446 cmd[2] = report_id | rreq->type << 4; 447 448 if (rreq->type == I2C_HID_REPORT_TYPE_FEATURE) { 449 cmd[dataoff++] = htole16(sc->hid_desc.wDataRegister) 450 & 0xff; 451 cmd[dataoff++] = htole16(sc->hid_desc.wDataRegister) 452 >> 8; 453 } else { 454 cmd[dataoff++] = htole16(sc->hid_desc.wOutputRegister) 455 & 0xff; 456 cmd[dataoff++] = htole16(sc->hid_desc.wOutputRegister) 457 >> 8; 458 } 459 460 cmd[dataoff++] = report_len & 0xff; 461 cmd[dataoff++] = report_len >> 8; 462 cmd[dataoff] = rreq->id; 463 464 finalcmd = malloc(cmdlen + rreq->len, M_DEVBUF, 465 M_NOWAIT | M_ZERO); 466 467 memcpy(finalcmd, cmd, cmdlen); 468 memcpy(finalcmd + cmdlen, rreq->data, rreq->len); 469 470 /* type 3 id 4: 22 00 34 03 23 00 04 00 04 03 */ 471 res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 472 finalcmd, cmdlen + rreq->len, NULL, 0, 0); 473 474 free(finalcmd, M_DEVBUF, cmdlen + rreq->len); 475 476 break; 477 } 478 479 case I2C_HID_CMD_SET_POWER: { 480 int power = *(int *)arg; 481 uint8_t cmd[] = { 482 htole16(sc->hid_desc.wCommandRegister) & 0xff, 483 htole16(sc->hid_desc.wCommandRegister) >> 8, 484 power, 485 I2C_HID_CMD_SET_POWER, 486 }; 487 488 DPRINTF(("%s: HID command I2C_HID_CMD_SET_POWER(%d)\n", 489 sc->sc_dev.dv_xname, power)); 490 491 /* 22 00 00 08 */ 492 res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 493 &cmd, sizeof(cmd), NULL, 0, 0); 494 495 break; 496 } 497 case I2C_HID_REPORT_DESCR: { 498 uint8_t cmd[] = { 499 htole16(sc->hid_desc.wReportDescRegister) & 0xff, 500 htole16(sc->hid_desc.wReportDescRegister) >> 8, 501 }; 502 503 DPRINTF(("%s: HID command I2C_HID_REPORT_DESCR at 0x%x with " 504 "size %d\n", sc->sc_dev.dv_xname, cmd[0], 505 sc->sc_reportlen)); 506 507 /* 20 00 */ 508 res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 509 &cmd, sizeof(cmd), sc->sc_report, sc->sc_reportlen, 0); 510 511 DPRINTF(("%s: HID report descriptor:", sc->sc_dev.dv_xname)); 512 for (i = 0; i < sc->sc_reportlen; i++) 513 DPRINTF((" %.2x", sc->sc_report[i])); 514 DPRINTF(("\n")); 515 516 break; 517 } 518 default: 519 printf("%s: unknown command %d\n", sc->sc_dev.dv_xname, 520 hidcmd); 521 } 522 523 iic_release_bus(sc->sc_tag, 0); 524 525 return (res); 526 } 527 528 int 529 ihidev_reset(struct ihidev_softc *sc) 530 { 531 DPRINTF(("%s: resetting\n", sc->sc_dev.dv_xname)); 532 533 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, &I2C_HID_POWER_ON)) { 534 printf("%s: failed to power on\n", sc->sc_dev.dv_xname); 535 return (1); 536 } 537 538 ihidev_sleep(sc, 100); 539 540 if (ihidev_hid_command(sc, I2C_HID_CMD_RESET, 0)) { 541 printf("%s: failed to reset hardware\n", sc->sc_dev.dv_xname); 542 543 ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, 544 &I2C_HID_POWER_OFF); 545 546 return (1); 547 } 548 549 ihidev_sleep(sc, 100); 550 551 return (0); 552 } 553 554 /* 555 * 5.2.2 - HID Descriptor Retrieval 556 * 557 * parse HID Descriptor that has already been read into hid_desc with 558 * I2C_HID_CMD_DESCR 559 */ 560 int 561 ihidev_hid_desc_parse(struct ihidev_softc *sc) 562 { 563 int retries = 3; 564 565 /* must be v01.00 */ 566 if (letoh16(sc->hid_desc.bcdVersion) != 0x0100) { 567 printf("%s: bad HID descriptor bcdVersion (0x%x)\n", 568 sc->sc_dev.dv_xname, 569 letoh16(sc->hid_desc.bcdVersion)); 570 return (1); 571 } 572 573 /* must be 30 bytes for v1.00 */ 574 if (letoh16(sc->hid_desc.wHIDDescLength != 575 sizeof(struct i2c_hid_desc))) { 576 printf("%s: bad HID descriptor size (%d != %zu)\n", 577 sc->sc_dev.dv_xname, 578 letoh16(sc->hid_desc.wHIDDescLength), 579 sizeof(struct i2c_hid_desc)); 580 return (1); 581 } 582 583 if (letoh16(sc->hid_desc.wReportDescLength) <= 0) { 584 printf("%s: bad HID report descriptor size (%d)\n", 585 sc->sc_dev.dv_xname, 586 letoh16(sc->hid_desc.wReportDescLength)); 587 return (1); 588 } 589 590 while (retries-- > 0) { 591 if (ihidev_reset(sc)) { 592 if (retries == 0) 593 return(1); 594 595 ihidev_sleep(sc, 10); 596 } 597 else 598 break; 599 } 600 601 sc->sc_reportlen = letoh16(sc->hid_desc.wReportDescLength); 602 sc->sc_report = malloc(sc->sc_reportlen, M_DEVBUF, M_NOWAIT | M_ZERO); 603 604 if (ihidev_hid_command(sc, I2C_HID_REPORT_DESCR, 0)) { 605 printf("%s: failed fetching HID report\n", 606 sc->sc_dev.dv_xname); 607 return (1); 608 } 609 610 return (0); 611 } 612 613 void 614 ihidev_poll(void *arg) 615 { 616 struct ihidev_softc *sc = arg; 617 618 sc->sc_frompoll = 1; 619 ihidev_intr(sc); 620 sc->sc_frompoll = 0; 621 } 622 623 int 624 ihidev_intr(void *arg) 625 { 626 struct ihidev_softc *sc = arg; 627 struct ihidev *scd; 628 int psize, res, i, fast = 0; 629 u_char *p; 630 u_int rep = 0; 631 632 if (sc->sc_dying) 633 return 1; 634 635 if (sc->sc_poll && !sc->sc_frompoll) { 636 DPRINTF(("%s: received interrupt while polling, disabling " 637 "polling\n", sc->sc_dev.dv_xname)); 638 sc->sc_poll = 0; 639 timeout_del_barrier(&sc->sc_timer); 640 } 641 642 /* 643 * XXX: force I2C_F_POLL for now to avoid dwiic interrupting 644 * while we are interrupting 645 */ 646 647 iic_acquire_bus(sc->sc_tag, I2C_F_POLL); 648 res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, NULL, 0, 649 sc->sc_ibuf, letoh16(sc->hid_desc.wMaxInputLength), I2C_F_POLL); 650 iic_release_bus(sc->sc_tag, I2C_F_POLL); 651 652 /* 653 * 6.1.1 - First two bytes are the packet length, which must be less 654 * than or equal to wMaxInputLength 655 */ 656 psize = sc->sc_ibuf[0] | sc->sc_ibuf[1] << 8; 657 if (psize <= 2 || psize > sc->sc_isize) { 658 if (sc->sc_poll) { 659 /* 660 * TODO: all fingers are up, should we pass to hid 661 * layer? 662 */ 663 sc->sc_fastpoll = 0; 664 goto more_polling; 665 } else 666 DPRINTF(("%s: %s: invalid packet size (%d vs. %d)\n", 667 sc->sc_dev.dv_xname, __func__, psize, 668 sc->sc_isize)); 669 return (1); 670 } 671 672 /* 3rd byte is the report id */ 673 p = sc->sc_ibuf + 2; 674 psize -= 2; 675 if (sc->sc_nrepid != 1) 676 rep = *p++, psize--; 677 678 if (rep >= sc->sc_nrepid) { 679 printf("%s: %s: bad report id %d\n", sc->sc_dev.dv_xname, 680 __func__, rep); 681 if (sc->sc_poll) { 682 sc->sc_fastpoll = 0; 683 goto more_polling; 684 } 685 return (1); 686 } 687 688 DPRINTF(("%s: %s: hid input (rep %d):", sc->sc_dev.dv_xname, __func__, 689 rep)); 690 for (i = 0; i < psize; i++) { 691 if (i > 0 && p[i] != 0 && p[i] != 0xff) { 692 fast = 1; 693 } 694 DPRINTF((" %.2x", p[i])); 695 } 696 DPRINTF(("\n")); 697 698 scd = sc->sc_subdevs[rep]; 699 if (scd == NULL || !(scd->sc_state & IHIDEV_OPEN)) { 700 if (sc->sc_poll) { 701 if (sc->sc_fastpoll) { 702 DPRINTF(("%s: fast->slow polling\n", 703 sc->sc_dev.dv_xname)); 704 sc->sc_fastpoll = 0; 705 } 706 goto more_polling; 707 } 708 return (1); 709 } 710 711 scd->sc_intr(scd, p, psize); 712 713 if (sc->sc_poll && (fast != sc->sc_fastpoll)) { 714 DPRINTF(("%s: %s->%s polling\n", sc->sc_dev.dv_xname, 715 sc->sc_fastpoll ? "fast" : "slow", 716 fast ? "fast" : "slow")); 717 sc->sc_fastpoll = fast; 718 } 719 720 more_polling: 721 if (sc->sc_poll && sc->sc_refcnt && !sc->sc_dying && 722 !timeout_pending(&sc->sc_timer)) 723 timeout_add_msec(&sc->sc_timer, 724 sc->sc_fastpoll ? FAST_POLL_MS : SLOW_POLL_MS); 725 726 return (1); 727 } 728 729 int 730 ihidev_maxrepid(void *buf, int len) 731 { 732 struct hid_data *d; 733 struct hid_item h; 734 int maxid; 735 736 maxid = -1; 737 h.report_ID = 0; 738 for (d = hid_start_parse(buf, len, hid_all); hid_get_item(d, &h);) 739 if (h.report_ID > maxid) 740 maxid = h.report_ID; 741 hid_end_parse(d); 742 743 return (maxid); 744 } 745 746 int 747 ihidev_print(void *aux, const char *pnp) 748 { 749 struct ihidev_attach_arg *iha = aux; 750 751 if (pnp) 752 printf("hid at %s", pnp); 753 754 if (iha->reportid != 0) 755 printf(" reportid %d", iha->reportid); 756 757 return (UNCONF); 758 } 759 760 int 761 ihidev_submatch(struct device *parent, void *match, void *aux) 762 { 763 struct ihidev_attach_arg *iha = aux; 764 struct cfdata *cf = match; 765 766 if (cf->ihidevcf_reportid != IHIDEV_UNK_REPORTID && 767 cf->ihidevcf_reportid != iha->reportid) 768 return (0); 769 770 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 771 } 772 773 int 774 ihidev_open(struct ihidev *scd) 775 { 776 struct ihidev_softc *sc = scd->sc_parent; 777 778 DPRINTF(("%s: %s: state=%d refcnt=%d\n", sc->sc_dev.dv_xname, 779 __func__, scd->sc_state, sc->sc_refcnt)); 780 781 if (scd->sc_state & IHIDEV_OPEN) 782 return (EBUSY); 783 784 scd->sc_state |= IHIDEV_OPEN; 785 786 if (sc->sc_refcnt++ || sc->sc_isize == 0) 787 return (0); 788 789 /* power on */ 790 ihidev_reset(sc); 791 792 if (sc->sc_poll) { 793 if (!timeout_initialized(&sc->sc_timer)) 794 timeout_set(&sc->sc_timer, (void *)ihidev_poll, sc); 795 if (!timeout_pending(&sc->sc_timer)) 796 timeout_add(&sc->sc_timer, FAST_POLL_MS); 797 } 798 799 return (0); 800 } 801 802 void 803 ihidev_close(struct ihidev *scd) 804 { 805 struct ihidev_softc *sc = scd->sc_parent; 806 807 DPRINTF(("%s: %s: state=%d refcnt=%d\n", sc->sc_dev.dv_xname, 808 __func__, scd->sc_state, sc->sc_refcnt)); 809 810 if (!(scd->sc_state & IHIDEV_OPEN)) 811 return; 812 813 scd->sc_state &= ~IHIDEV_OPEN; 814 815 if (--sc->sc_refcnt) 816 return; 817 818 /* no sub-devices open, conserve power */ 819 820 if (sc->sc_poll && timeout_pending(&sc->sc_timer)) 821 timeout_del(&sc->sc_timer); 822 823 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, &I2C_HID_POWER_OFF)) 824 printf("%s: failed to power down\n", sc->sc_dev.dv_xname); 825 } 826 827 int 828 ihidev_ioctl(struct ihidev *sc, u_long cmd, caddr_t addr, int flag, 829 struct proc *p) 830 { 831 return -1; 832 } 833 834 void 835 ihidev_get_report_desc(struct ihidev_softc *sc, void **desc, int *size) 836 { 837 *desc = sc->sc_report; 838 *size = sc->sc_reportlen; 839 } 840 841 int 842 ihidev_report_type_conv(int hid_type_id) 843 { 844 switch (hid_type_id) { 845 case hid_input: 846 return I2C_HID_REPORT_TYPE_INPUT; 847 case hid_output: 848 return I2C_HID_REPORT_TYPE_OUTPUT; 849 case hid_feature: 850 return I2C_HID_REPORT_TYPE_FEATURE; 851 default: 852 return -1; 853 } 854 } 855 856 int 857 ihidev_get_report(struct device *dev, int type, int id, void *data, int len) 858 { 859 struct ihidev_softc *sc = (struct ihidev_softc *)dev; 860 struct i2c_hid_report_request rreq; 861 862 rreq.type = type; 863 rreq.id = id; 864 rreq.data = data; 865 rreq.len = len; 866 867 if (ihidev_hid_command(sc, I2C_HID_CMD_GET_REPORT, &rreq)) { 868 printf("%s: failed fetching report\n", sc->sc_dev.dv_xname); 869 return (1); 870 } 871 872 return 0; 873 } 874 875 int 876 ihidev_set_report(struct device *dev, int type, int id, void *data, int len) 877 { 878 struct ihidev_softc *sc = (struct ihidev_softc *)dev; 879 struct i2c_hid_report_request rreq; 880 881 rreq.type = type; 882 rreq.id = id; 883 rreq.data = data; 884 rreq.len = len; 885 886 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_REPORT, &rreq)) { 887 printf("%s: failed setting report\n", sc->sc_dev.dv_xname); 888 return (1); 889 } 890 891 return 0; 892 } 893