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