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