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