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