xref: /openbsd-src/sys/dev/i2c/ihidev.c (revision 4b70baf6e17fc8b27fc1f7fa7929335753fa94c3)
1 /* $OpenBSD: ihidev.c,v 1.19 2019/04/08 17:50:45 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 
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 			free(tmprep, M_DEVBUF, report_len);
365 			return (1);
366 		}
367 
368 		DPRINTF(("%s: response:", sc->sc_dev.dv_xname));
369 		for (i = 0; i < report_len; i++)
370 			DPRINTF((" %.2x", tmprep[i]));
371 		DPRINTF(("\n"));
372 
373 		memcpy(rreq->data, tmprep + 2 + report_id_len, rreq->len);
374 		free(tmprep, M_DEVBUF, report_len);
375 
376 		break;
377 	}
378 	case I2C_HID_CMD_SET_REPORT: {
379 		struct i2c_hid_report_request *rreq =
380 		    (struct i2c_hid_report_request *)arg;
381 
382 		uint8_t cmd[] = {
383 			htole16(sc->hid_desc.wCommandRegister) & 0xff,
384 			htole16(sc->hid_desc.wCommandRegister) >> 8,
385 			0,
386 			I2C_HID_CMD_SET_REPORT,
387 			0, 0, 0, 0, 0, 0,
388 		};
389 		int cmdlen = sizeof(cmd);
390 		int report_id = rreq->id;
391 		int report_len = 2 + (report_id ? 1 : 0) + rreq->len;
392 		int dataoff;
393 		uint8_t *finalcmd;
394 
395 		DPRINTF(("%s: HID command I2C_HID_CMD_SET_REPORT %d "
396 		    "(type %d, len %d):", sc->sc_dev.dv_xname, report_id,
397 		    rreq->type, rreq->len));
398 		for (i = 0; i < rreq->len; i++)
399 			DPRINTF((" %.2x", ((uint8_t *)rreq->data)[i]));
400 		DPRINTF(("\n"));
401 
402 		/*
403 		 * 7.2.3.4 - "The protocol is optimized for Report < 15.  If a
404 		 * report ID >= 15 is necessary, then the Report ID in the Low
405 		 * Byte must be set to 1111 and a Third Byte is appended to the
406 		 * protocol.  This Third Byte contains the entire/actual report
407 		 * ID."
408 		 */
409 		dataoff = 4;
410 		if (report_id >= 15) {
411 			cmd[dataoff++] = report_id;
412 			report_id = 15;
413 		} else
414 			cmdlen--;
415 
416 		cmd[2] = report_id | rreq->type << 4;
417 
418 		if (rreq->type == I2C_HID_REPORT_TYPE_FEATURE) {
419 			cmd[dataoff++] = htole16(sc->hid_desc.wDataRegister)
420 			    & 0xff;
421 			cmd[dataoff++] = htole16(sc->hid_desc.wDataRegister)
422 			    >> 8;
423 		} else {
424 			cmd[dataoff++] = htole16(sc->hid_desc.wOutputRegister)
425 			    & 0xff;
426 			cmd[dataoff++] = htole16(sc->hid_desc.wOutputRegister)
427 			    >> 8;
428 		}
429 
430 		cmd[dataoff++] = report_len & 0xff;
431 		cmd[dataoff++] = report_len >> 8;
432 		cmd[dataoff] = rreq->id;
433 
434 		finalcmd = malloc(cmdlen + rreq->len, M_DEVBUF,
435 		    M_NOWAIT | M_ZERO);
436 
437 		memcpy(finalcmd, cmd, cmdlen);
438 		memcpy(finalcmd + cmdlen, rreq->data, rreq->len);
439 
440 		/* type 3 id 4: 22 00 34 03 23 00 04 00 04 03 */
441 		res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
442 		    finalcmd, cmdlen + rreq->len, NULL, 0, 0);
443 
444 		free(finalcmd, M_DEVBUF, cmdlen + rreq->len);
445 
446  		break;
447  	}
448 
449 	case I2C_HID_CMD_SET_POWER: {
450 		int power = *(int *)arg;
451 		uint8_t cmd[] = {
452 			htole16(sc->hid_desc.wCommandRegister) & 0xff,
453 			htole16(sc->hid_desc.wCommandRegister) >> 8,
454 			power,
455 			I2C_HID_CMD_SET_POWER,
456 		};
457 
458 		DPRINTF(("%s: HID command I2C_HID_CMD_SET_POWER(%d)\n",
459 		    sc->sc_dev.dv_xname, power));
460 
461 		/* 22 00 00 08 */
462 		res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
463 		    &cmd, sizeof(cmd), NULL, 0, 0);
464 
465 		break;
466 	}
467 	case I2C_HID_REPORT_DESCR: {
468 		uint8_t cmd[] = {
469 			htole16(sc->hid_desc.wReportDescRegister) & 0xff,
470 			htole16(sc->hid_desc.wReportDescRegister) >> 8,
471 		};
472 
473 		DPRINTF(("%s: HID command I2C_HID_REPORT_DESCR at 0x%x with "
474 		    "size %d\n", sc->sc_dev.dv_xname, cmd[0],
475 		    sc->sc_reportlen));
476 
477 		/* 20 00 */
478 		res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
479 		    &cmd, sizeof(cmd), sc->sc_report, sc->sc_reportlen, 0);
480 
481 		DPRINTF(("%s: HID report descriptor:", sc->sc_dev.dv_xname));
482 		for (i = 0; i < sc->sc_reportlen; i++)
483 			DPRINTF((" %.2x", sc->sc_report[i]));
484 		DPRINTF(("\n"));
485 
486 		break;
487 	}
488 	default:
489 		printf("%s: unknown command %d\n", sc->sc_dev.dv_xname,
490 		    hidcmd);
491 	}
492 
493 	iic_release_bus(sc->sc_tag, 0);
494 
495 	return (res);
496 }
497 
498 int
499 ihidev_reset(struct ihidev_softc *sc)
500 {
501 	DPRINTF(("%s: resetting\n", sc->sc_dev.dv_xname));
502 
503 	if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, &I2C_HID_POWER_ON)) {
504 		printf("%s: failed to power on\n", sc->sc_dev.dv_xname);
505 		return (1);
506 	}
507 
508 	ihidev_sleep(sc, 100);
509 
510 	if (ihidev_hid_command(sc, I2C_HID_CMD_RESET, 0)) {
511 		printf("%s: failed to reset hardware\n", sc->sc_dev.dv_xname);
512 
513 		ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER,
514 		    &I2C_HID_POWER_OFF);
515 
516 		return (1);
517 	}
518 
519 	ihidev_sleep(sc, 100);
520 
521 	return (0);
522 }
523 
524 /*
525  * 5.2.2 - HID Descriptor Retrieval
526  *
527  * parse HID Descriptor that has already been read into hid_desc with
528  * I2C_HID_CMD_DESCR
529  */
530 int
531 ihidev_hid_desc_parse(struct ihidev_softc *sc)
532 {
533 	int retries = 3;
534 
535 	/* must be v01.00 */
536 	if (letoh16(sc->hid_desc.bcdVersion) != 0x0100) {
537 		printf("%s: bad HID descriptor bcdVersion (0x%x)\n",
538 		    sc->sc_dev.dv_xname,
539 		    letoh16(sc->hid_desc.bcdVersion));
540 		return (1);
541 	}
542 
543 	/* must be 30 bytes for v1.00 */
544 	if (letoh16(sc->hid_desc.wHIDDescLength !=
545 	    sizeof(struct i2c_hid_desc))) {
546 		printf("%s: bad HID descriptor size (%d != %zu)\n",
547 		    sc->sc_dev.dv_xname,
548 		    letoh16(sc->hid_desc.wHIDDescLength),
549 		    sizeof(struct i2c_hid_desc));
550 		return (1);
551 	}
552 
553 	if (letoh16(sc->hid_desc.wReportDescLength) <= 0) {
554 		printf("%s: bad HID report descriptor size (%d)\n",
555 		    sc->sc_dev.dv_xname,
556 		    letoh16(sc->hid_desc.wReportDescLength));
557 		return (1);
558 	}
559 
560 	while (retries-- > 0) {
561 		if (ihidev_reset(sc)) {
562 			if (retries == 0)
563 				return(1);
564 
565 			ihidev_sleep(sc, 10);
566 		}
567 		else
568 			break;
569 	}
570 
571 	sc->sc_reportlen = letoh16(sc->hid_desc.wReportDescLength);
572 	sc->sc_report = malloc(sc->sc_reportlen, M_DEVBUF, M_NOWAIT | M_ZERO);
573 
574 	if (ihidev_hid_command(sc, I2C_HID_REPORT_DESCR, 0)) {
575 		printf("%s: failed fetching HID report\n",
576 		    sc->sc_dev.dv_xname);
577 		return (1);
578 	}
579 
580 	return (0);
581 }
582 
583 int
584 ihidev_intr(void *arg)
585 {
586 	struct ihidev_softc *sc = arg;
587 	struct ihidev *scd;
588 	int psize, 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 <= 2 || 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 int
791 ihidev_report_type_conv(int hid_type_id)
792 {
793 	switch (hid_type_id) {
794 	case hid_input:
795 		return I2C_HID_REPORT_TYPE_INPUT;
796 	case hid_output:
797 		return I2C_HID_REPORT_TYPE_OUTPUT;
798 	case hid_feature:
799 		return I2C_HID_REPORT_TYPE_FEATURE;
800 	default:
801 		return -1;
802 	}
803 }
804 
805 int
806 ihidev_get_report(struct device *dev, int type, int id, void *data, int len)
807 {
808 	struct ihidev_softc *sc = (struct ihidev_softc *)dev;
809 	struct i2c_hid_report_request rreq;
810 
811 	rreq.type = type;
812 	rreq.id = id;
813 	rreq.data = data;
814 	rreq.len = len;
815 
816 	if (ihidev_hid_command(sc, I2C_HID_CMD_GET_REPORT, &rreq)) {
817 		printf("%s: failed fetching report\n", sc->sc_dev.dv_xname);
818 		return (1);
819 	}
820 
821 	return 0;
822 }
823 
824 int
825 ihidev_set_report(struct device *dev, int type, int id, void *data, int len)
826 {
827 	struct ihidev_softc *sc = (struct ihidev_softc *)dev;
828 	struct i2c_hid_report_request rreq;
829 
830 	rreq.type = type;
831 	rreq.id = id;
832 	rreq.data = data;
833 	rreq.len = len;
834 
835 	if (ihidev_hid_command(sc, I2C_HID_CMD_SET_REPORT, &rreq)) {
836 		printf("%s: failed setting report\n", sc->sc_dev.dv_xname);
837 		return (1);
838 	}
839 
840 	return 0;
841 }
842