xref: /openbsd/sys/dev/i2c/ihidev.c (revision 73471bf0)
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