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