xref: /netbsd-src/sys/dev/i2c/ihidev.c (revision 2bd3f9e549399f948ec0d6923d2701d016e7347f)
1 /* $NetBSD: ihidev.c,v 1.33 2024/12/09 22:06:31 jmcneill Exp $ */
2 /* $OpenBSD ihidev.c,v 1.13 2017/04/08 02:57:23 deraadt Exp $ */
3 
4 /*-
5  * Copyright (c) 2017 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Manuel Bouyer.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Copyright (c) 2015, 2016 joshua stein <jcs@openbsd.org>
35  *
36  * Permission to use, copy, modify, and distribute this software for any
37  * purpose with or without fee is hereby granted, provided that the above
38  * copyright notice and this permission notice appear in all copies.
39  *
40  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
41  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
42  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
43  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
44  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
45  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
46  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
47  */
48 
49 /*
50  * HID-over-i2c driver
51  *
52  * https://msdn.microsoft.com/en-us/library/windows/hardware/dn642101%28v=vs.85%29.aspx
53  *
54  */
55 
56 #include "gpio.h"
57 #include "acpica.h"
58 
59 #include <sys/cdefs.h>
60 __KERNEL_RCSID(0, "$NetBSD: ihidev.c,v 1.33 2024/12/09 22:06:31 jmcneill Exp $");
61 
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/device.h>
65 #include <sys/kmem.h>
66 #include <sys/workqueue.h>
67 
68 #include <dev/i2c/i2cvar.h>
69 #include <dev/i2c/ihidev.h>
70 
71 #include <dev/hid/hid.h>
72 
73 #if NACPICA > 0
74 #include <dev/acpi/acpivar.h>
75 #include <dev/acpi/acpi_intr.h>
76 #include <dev/acpi/acpi_gpio.h>
77 #endif
78 #if NGPIO > 0
79 #include <dev/gpio/gpiovar.h>
80 #endif
81 
82 #include "locators.h"
83 
84 /* #define IHIDEV_DEBUG */
85 
86 #ifdef IHIDEV_DEBUG
87 #define DPRINTF(x) printf x
88 #else
89 #define DPRINTF(x)
90 #endif
91 
92 /* 7.2 */
93 enum {
94 	I2C_HID_CMD_DESCR	= 0x0,
95 	I2C_HID_CMD_RESET	= 0x1,
96 	I2C_HID_CMD_GET_REPORT	= 0x2,
97 	I2C_HID_CMD_SET_REPORT	= 0x3,
98 	I2C_HID_CMD_GET_IDLE	= 0x4,
99 	I2C_HID_CMD_SET_IDLE	= 0x5,
100 	I2C_HID_CMD_GET_PROTO	= 0x6,
101 	I2C_HID_CMD_SET_PROTO	= 0x7,
102 	I2C_HID_CMD_SET_POWER	= 0x8,
103 
104 	/* pseudo commands */
105 	I2C_HID_REPORT_DESCR	= 0x100,
106 };
107 
108 static int I2C_HID_POWER_ON	= 0x0;
109 static int I2C_HID_POWER_OFF	= 0x1;
110 
111 static int	ihidev_match(device_t, cfdata_t, void *);
112 static void	ihidev_attach(device_t, device_t, void *);
113 static int	ihidev_detach(device_t, int);
114 CFATTACH_DECL_NEW(ihidev, sizeof(struct ihidev_softc),
115     ihidev_match, ihidev_attach, ihidev_detach, NULL);
116 
117 static bool	ihidev_intr_init(struct ihidev_softc *);
118 static void	ihidev_intr_fini(struct ihidev_softc *);
119 
120 static bool	ihidev_suspend(device_t, const pmf_qual_t *);
121 static bool	ihidev_resume(device_t, const pmf_qual_t *);
122 static int	ihidev_hid_command(struct ihidev_softc *, int, void *, bool);
123 #if NACPICA > 0
124 static int	ihidev_intr(void *);
125 static void	ihidev_work(struct work *, void *);
126 #endif
127 static int	ihidev_poweron(struct ihidev_softc *, bool);
128 static int	ihidev_reset(struct ihidev_softc *, bool);
129 static int	ihidev_hid_desc_parse(struct ihidev_softc *);
130 
131 static int	ihidev_maxrepid(void *, int);
132 static int	ihidev_print(void *, const char *);
133 static int	ihidev_submatch(device_t, cfdata_t, const int *, void *);
134 
135 static bool	ihidev_acpi_get_info(struct ihidev_softc *);
136 
137 static const struct device_compatible_entry compat_data[] = {
138 	{ .compat = "PNP0C50" },
139 	{ .compat = "ACPI0C50" },
140 	{ .compat = "hid-over-i2c" },
141 	DEVICE_COMPAT_EOL
142 };
143 
144 static int
145 ihidev_match(device_t parent, cfdata_t match, void *aux)
146 {
147 	struct i2c_attach_args * const ia = aux;
148 	int match_result;
149 
150 	if (iic_use_direct_match(ia, match, compat_data, &match_result))
151 		return match_result;
152 
153 	return 0;
154 }
155 
156 static void
157 ihidev_attach(device_t parent, device_t self, void *aux)
158 {
159 	struct ihidev_softc *sc = device_private(self);
160 	struct i2c_attach_args *ia = aux;
161 	struct ihidev_attach_arg iha;
162 	device_t dev;
163 	int repid, repsz;
164 	int isize;
165 	int locs[IHIDBUSCF_NLOCS];
166 
167 	sc->sc_dev = self;
168 	sc->sc_tag = ia->ia_tag;
169 	sc->sc_addr = ia->ia_addr;
170 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
171 
172 	sc->sc_phandle = ia->ia_cookie;
173 	if (ia->ia_cookietype != I2C_COOKIE_ACPI) {
174 		aprint_error(": unsupported device tree type\n");
175 		return;
176 	}
177 	if (!ihidev_acpi_get_info(sc)) {
178 		return;
179 	}
180 
181 	if (ihidev_hid_command(sc, I2C_HID_CMD_DESCR, NULL, false) ||
182 	    ihidev_hid_desc_parse(sc)) {
183 		aprint_error(": failed fetching initial HID descriptor\n");
184 		return;
185 	}
186 
187 	aprint_naive("\n");
188 	aprint_normal(": vendor 0x%x product 0x%x, %s\n",
189 	    le16toh(sc->hid_desc.wVendorID), le16toh(sc->hid_desc.wProductID),
190 	    ia->ia_name);
191 
192 	sc->sc_nrepid = ihidev_maxrepid(sc->sc_report, sc->sc_reportlen);
193 	if (sc->sc_nrepid < 0)
194 		return;
195 
196 	aprint_normal_dev(self, "%d report id%s\n", sc->sc_nrepid,
197 	    sc->sc_nrepid > 1 ? "s" : "");
198 
199 	sc->sc_nrepid++;
200 	sc->sc_subdevs = kmem_zalloc(sc->sc_nrepid * sizeof(struct ihidev *),
201 	    KM_SLEEP);
202 
203 	/* find largest report size and allocate memory for input buffer */
204 	sc->sc_isize = le16toh(sc->hid_desc.wMaxInputLength);
205 	for (repid = 0; repid < sc->sc_nrepid; repid++) {
206 		repsz = hid_report_size(sc->sc_report, sc->sc_reportlen,
207 		    hid_input, repid);
208 
209 		isize = repsz + 2; /* two bytes for the length */
210 		isize += (sc->sc_nrepid != 1); /* one byte for the report ID */
211 		if (isize > sc->sc_isize)
212 			sc->sc_isize = isize;
213 
214 		DPRINTF(("%s: repid %d size %d\n",
215 		    device_xname(sc->sc_dev), repid, repsz));
216 	}
217 	sc->sc_ibuf = kmem_zalloc(sc->sc_isize, KM_SLEEP);
218 	if (!ihidev_intr_init(sc)) {
219 		return;
220 	}
221 
222 	iha.iaa = ia;
223 	iha.parent = sc;
224 
225 	/* Look for a driver claiming all report IDs first. */
226 	iha.reportid = IHIDEV_CLAIM_ALLREPORTID;
227 	locs[IHIDBUSCF_REPORTID] = IHIDEV_CLAIM_ALLREPORTID;
228 	dev = config_found(self, &iha, ihidev_print,
229 	    CFARGS(.submatch = ihidev_submatch,
230 		   .locators = locs,
231 		   .iattr = "ihidbus"));
232 	if (dev != NULL) {
233 		for (repid = 0; repid < sc->sc_nrepid; repid++)
234 			sc->sc_subdevs[repid] = device_private(dev);
235 		return;
236 	}
237 
238 	for (repid = 0; repid < sc->sc_nrepid; repid++) {
239 		if (hid_report_size(sc->sc_report, sc->sc_reportlen, hid_input,
240 		    repid) == 0 &&
241 		    hid_report_size(sc->sc_report, sc->sc_reportlen,
242 		    hid_output, repid) == 0 &&
243 		    hid_report_size(sc->sc_report, sc->sc_reportlen,
244 		    hid_feature, repid) == 0)
245 			continue;
246 
247 		iha.reportid = repid;
248 		locs[IHIDBUSCF_REPORTID] = repid;
249 		dev = config_found(self, &iha, ihidev_print,
250 		    CFARGS(.submatch = ihidev_submatch,
251 			   .locators = locs,
252 			   .iattr = "ihidbus"));
253 		sc->sc_subdevs[repid] = device_private(dev);
254 	}
255 
256 	/* power down until we're opened */
257 	if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, &I2C_HID_POWER_OFF,
258 		false)) {
259 		aprint_error_dev(sc->sc_dev, "failed to power down\n");
260 		return;
261 	}
262 	if (!pmf_device_register(self, ihidev_suspend, ihidev_resume))
263 		aprint_error_dev(self, "couldn't establish power handler\n");
264 }
265 
266 static int
267 ihidev_detach(device_t self, int flags)
268 {
269 	struct ihidev_softc *sc = device_private(self);
270 	int error;
271 
272 	error = config_detach_children(self, flags);
273 	if (error)
274 		return error;
275 
276 	pmf_device_deregister(self);
277 	ihidev_intr_fini(sc);
278 
279 	if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, &I2C_HID_POWER_OFF,
280 		true))
281 		aprint_error_dev(sc->sc_dev, "failed to power down\n");
282 
283 	if (sc->sc_ibuf != NULL) {
284 		kmem_free(sc->sc_ibuf, sc->sc_isize);
285 		sc->sc_ibuf = NULL;
286 	}
287 
288 	if (sc->sc_report != NULL)
289 		kmem_free(sc->sc_report, sc->sc_reportlen);
290 
291 	mutex_destroy(&sc->sc_lock);
292 
293 	return 0;
294 }
295 
296 static bool
297 ihidev_suspend(device_t self, const pmf_qual_t *q)
298 {
299 	struct ihidev_softc *sc = device_private(self);
300 
301 	mutex_enter(&sc->sc_lock);
302 	if (sc->sc_refcnt > 0) {
303 		printf("ihidev power off\n");
304 		if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER,
305 		    &I2C_HID_POWER_OFF, true))
306 		aprint_error_dev(sc->sc_dev, "failed to power down\n");
307 	}
308 	mutex_exit(&sc->sc_lock);
309 	return true;
310 }
311 
312 static bool
313 ihidev_resume(device_t self, const pmf_qual_t *q)
314 {
315 	struct ihidev_softc *sc = device_private(self);
316 
317 	mutex_enter(&sc->sc_lock);
318 	if (sc->sc_refcnt > 0) {
319 		printf("ihidev power reset\n");
320 		ihidev_reset(sc, true);
321 	}
322 	mutex_exit(&sc->sc_lock);
323 	return true;
324 }
325 
326 static int
327 ihidev_hid_command(struct ihidev_softc *sc, int hidcmd, void *arg, bool poll)
328 {
329 	int i, res = 1;
330 	int flags = poll ? I2C_F_POLL : 0;
331 
332 	iic_acquire_bus(sc->sc_tag, flags);
333 
334 	switch (hidcmd) {
335 	case I2C_HID_CMD_DESCR: {
336 		/*
337 		 * 5.2.2 - HID Descriptor Retrieval
338 		 * register is passed from the controller
339 		 */
340 		uint8_t cmd[] = {
341 			htole16(sc->sc_hid_desc_addr) & 0xff,
342 			htole16(sc->sc_hid_desc_addr) >> 8,
343 		};
344 
345 		DPRINTF(("%s: HID command I2C_HID_CMD_DESCR at 0x%x\n",
346 		    device_xname(sc->sc_dev), htole16(sc->sc_hid_desc_addr)));
347 
348 		/* 20 00 */
349 		res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
350 		    &cmd, sizeof(cmd), &sc->hid_desc_buf,
351 		    sizeof(struct i2c_hid_desc), flags);
352 
353 		DPRINTF(("%s: HID descriptor:", device_xname(sc->sc_dev)));
354 		for (i = 0; i < sizeof(struct i2c_hid_desc); i++)
355 			DPRINTF((" %.2x", sc->hid_desc_buf[i]));
356 		DPRINTF(("\n"));
357 
358 		break;
359 	}
360 	case I2C_HID_CMD_RESET: {
361 		uint8_t cmd[] = {
362 			htole16(sc->hid_desc.wCommandRegister) & 0xff,
363 			htole16(sc->hid_desc.wCommandRegister) >> 8,
364 			0,
365 			I2C_HID_CMD_RESET,
366 		};
367 
368 		DPRINTF(("%s: HID command I2C_HID_CMD_RESET\n",
369 		    device_xname(sc->sc_dev)));
370 
371 		/* 22 00 00 01 */
372 		res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
373 		    &cmd, sizeof(cmd), NULL, 0, flags);
374 
375 		break;
376 	}
377 	case I2C_HID_CMD_GET_REPORT: {
378 		struct i2c_hid_report_request *rreq =
379 		    (struct i2c_hid_report_request *)arg;
380 
381 		uint8_t cmd[] = {
382 			htole16(sc->hid_desc.wCommandRegister) & 0xff,
383 			htole16(sc->hid_desc.wCommandRegister) >> 8,
384 			0,
385 			I2C_HID_CMD_GET_REPORT,
386 			0, 0, 0,
387 		};
388 		int cmdlen = 7;
389 		int dataoff = 4;
390 		int report_id = rreq->id;
391 		int report_id_len = 1;
392 		int report_len = rreq->len + 2;
393 		int d;
394 		uint8_t *tmprep;
395 
396 		DPRINTF(("%s: HID command I2C_HID_CMD_GET_REPORT %d "
397 		    "(type %d, len %d)\n", device_xname(sc->sc_dev), report_id,
398 		    rreq->type, rreq->len));
399 
400 		/*
401 		 * 7.2.2.4 - "The protocol is optimized for Report < 15.  If a
402 		 * report ID >= 15 is necessary, then the Report ID in the Low
403 		 * Byte must be set to 1111 and a Third Byte is appended to the
404 		 * protocol.  This Third Byte contains the entire/actual report
405 		 * ID."
406 		 */
407 		if (report_id >= 15) {
408 			cmd[dataoff++] = report_id;
409 			report_id = 15;
410 			report_id_len = 2;
411 		} else
412 			cmdlen--;
413 
414 		cmd[2] = report_id | rreq->type << 4;
415 
416 		cmd[dataoff++] = sc->hid_desc.wDataRegister & 0xff;
417 		cmd[dataoff] = sc->hid_desc.wDataRegister >> 8;
418 
419 		/*
420 		 * 7.2.2.2 - Response will be a 2-byte length value, the report
421 		 * id with length determined above, and then the report.
422 		 * Allocate rreq->len + 2 + 2 bytes, read into that temporary
423 		 * buffer, and then copy only the report back out to
424 		 * rreq->data.
425 		 */
426 		report_len += report_id_len;
427 		tmprep = kmem_zalloc(report_len, KM_NOSLEEP);
428 		if (tmprep == NULL) {
429 			/* XXX pool or preallocate? */
430 			DPRINTF(("%s: out of memory\n",
431 				device_xname(sc->sc_dev)));
432 			res = ENOMEM;
433 			break;
434 		}
435 
436 		/* type 3 id 8: 22 00 38 02 23 00 */
437 		res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
438 		    &cmd, cmdlen, tmprep, report_len, flags);
439 
440 		d = tmprep[0] | tmprep[1] << 8;
441 		if (d != report_len) {
442 			DPRINTF(("%s: response size %d != expected length %d\n",
443 			    device_xname(sc->sc_dev), d, report_len));
444 		}
445 
446 		if (report_id_len == 2)
447 			d = tmprep[2] | tmprep[3] << 8;
448 		else
449 			d = tmprep[2];
450 
451 		if (d != rreq->id) {
452 			DPRINTF(("%s: response report id %d != %d\n",
453 			    device_xname(sc->sc_dev), d, rreq->id));
454 			iic_release_bus(sc->sc_tag, 0);
455 			kmem_free(tmprep, report_len);
456 			return (1);
457 		}
458 
459 		DPRINTF(("%s: response:", device_xname(sc->sc_dev)));
460 		for (i = 0; i < report_len; i++)
461 			DPRINTF((" %.2x", tmprep[i]));
462 		DPRINTF(("\n"));
463 
464 		memcpy(rreq->data, tmprep + 2 + report_id_len, rreq->len);
465 		kmem_free(tmprep, report_len);
466 
467 		break;
468 	}
469 	case I2C_HID_CMD_SET_REPORT: {
470 		struct i2c_hid_report_request *rreq =
471 		    (struct i2c_hid_report_request *)arg;
472 
473 		uint8_t cmd[] = {
474 			htole16(sc->hid_desc.wCommandRegister) & 0xff,
475 			htole16(sc->hid_desc.wCommandRegister) >> 8,
476 			0,
477 			I2C_HID_CMD_SET_REPORT,
478 			0, 0, 0, 0, 0, 0,
479 		};
480 		int cmdlen = 10;
481 		int report_id = rreq->id;
482 		int report_len = 2 + (report_id ? 1 : 0) + rreq->len;
483 		int dataoff;
484 		uint8_t *finalcmd;
485 
486 		DPRINTF(("%s: HID command I2C_HID_CMD_SET_REPORT %d "
487 		    "(type %d, len %d):", device_xname(sc->sc_dev), report_id,
488 		    rreq->type, rreq->len));
489 		for (i = 0; i < rreq->len; i++)
490 			DPRINTF((" %.2x", ((uint8_t *)rreq->data)[i]));
491 		DPRINTF(("\n"));
492 
493 		/*
494 		 * 7.2.2.4 - "The protocol is optimized for Report < 15.  If a
495 		 * report ID >= 15 is necessary, then the Report ID in the Low
496 		 * Byte must be set to 1111 and a Third Byte is appended to the
497 		 * protocol.  This Third Byte contains the entire/actual report
498 		 * ID."
499 		 */
500 		dataoff = 4;
501 		if (report_id >= 15) {
502 			cmd[dataoff++] = report_id;
503 			report_id = 15;
504 		} else
505 			cmdlen--;
506 
507 		cmd[2] = report_id | rreq->type << 4;
508 
509 		if (rreq->type == I2C_HID_REPORT_TYPE_FEATURE) {
510 			cmd[dataoff++] = htole16(sc->hid_desc.wDataRegister)
511 			    & 0xff;
512 			cmd[dataoff++] = htole16(sc->hid_desc.wDataRegister)
513 			    >> 8;
514 		} else {
515 			cmd[dataoff++] = htole16(sc->hid_desc.wOutputRegister)
516 			    & 0xff;
517 			cmd[dataoff++] = htole16(sc->hid_desc.wOutputRegister)
518 			    >> 8;
519 		}
520 
521 		cmd[dataoff++] = report_len & 0xff;
522 		cmd[dataoff++] = report_len >> 8;
523 		cmd[dataoff] = rreq->id;
524 
525 		finalcmd = kmem_zalloc(cmdlen + rreq->len, KM_NOSLEEP);
526 		if (finalcmd == NULL) {
527 			res = ENOMEM;
528 			break;
529 		}
530 
531 		memcpy(finalcmd, cmd, cmdlen);
532 		memcpy(finalcmd + cmdlen, rreq->data, rreq->len);
533 
534 		/* type 3 id 4: 22 00 34 03 23 00 04 00 04 03 */
535 		res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
536 		    finalcmd, cmdlen + rreq->len, NULL, 0, flags);
537 		kmem_free(finalcmd, cmdlen + rreq->len);
538 
539  		break;
540  	}
541 
542 	case I2C_HID_CMD_SET_POWER: {
543 		int power = *(int *)arg;
544 		uint8_t cmd[] = {
545 			htole16(sc->hid_desc.wCommandRegister) & 0xff,
546 			htole16(sc->hid_desc.wCommandRegister) >> 8,
547 			power,
548 			I2C_HID_CMD_SET_POWER,
549 		};
550 
551 		DPRINTF(("%s: HID command I2C_HID_CMD_SET_POWER(%d)\n",
552 		    device_xname(sc->sc_dev), power));
553 
554 		/* 22 00 00 08 */
555 		res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
556 		    &cmd, sizeof(cmd), NULL, 0, flags);
557 
558 		break;
559 	}
560 	case I2C_HID_REPORT_DESCR: {
561 		uint8_t cmd[] = {
562 			htole16(sc->hid_desc.wReportDescRegister) & 0xff,
563 			htole16(sc->hid_desc.wReportDescRegister) >> 8,
564 		};
565 
566 		DPRINTF(("%s: HID command I2C_HID_REPORT_DESCR at 0x%x with "
567 		    "size %d\n", device_xname(sc->sc_dev), cmd[0],
568 		    sc->sc_reportlen));
569 
570 		/* 20 00 */
571 		res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
572 		    &cmd, sizeof(cmd), sc->sc_report, sc->sc_reportlen, flags);
573 
574 		DPRINTF(("%s: HID report descriptor:",
575 		    device_xname(sc->sc_dev)));
576 		for (i = 0; i < sc->sc_reportlen; i++)
577 			DPRINTF((" %.2x", sc->sc_report[i]));
578 		DPRINTF(("\n"));
579 
580 		break;
581 	}
582 	default:
583 		aprint_error_dev(sc->sc_dev, "unknown command %d\n",
584 		    hidcmd);
585 	}
586 
587 	iic_release_bus(sc->sc_tag, flags);
588 
589 	return (res);
590 }
591 
592 static int
593 ihidev_poweron(struct ihidev_softc *sc, bool poll)
594 {
595 	DPRINTF(("%s: poweron\n", device_xname(sc->sc_dev)));
596 
597 	if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER,
598 	    &I2C_HID_POWER_ON, poll)) {
599 		aprint_error_dev(sc->sc_dev, "failed to power on\n");
600 		return (1);
601 	}
602 
603 	DELAY(1000);
604 
605 	return (0);
606 }
607 
608 static int
609 ihidev_reset(struct ihidev_softc *sc, bool poll)
610 {
611 	DPRINTF(("%s: resetting\n", device_xname(sc->sc_dev)));
612 
613 	if (ihidev_hid_command(sc, I2C_HID_CMD_RESET, 0, poll)) {
614 		aprint_error_dev(sc->sc_dev, "failed to reset hardware\n");
615 
616 		ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER,
617 		    &I2C_HID_POWER_OFF, poll);
618 
619 		return (1);
620 	}
621 
622 	DELAY(1000);
623 
624 	return (0);
625 }
626 
627 /*
628  * 5.2.2 - HID Descriptor Retrieval
629  *
630  * parse HID Descriptor that has already been read into hid_desc with
631  * I2C_HID_CMD_DESCR
632  */
633 static int
634 ihidev_hid_desc_parse(struct ihidev_softc *sc)
635 {
636 	int retries = 3;
637 
638 	/* must be v01.00 */
639 	if (le16toh(sc->hid_desc.bcdVersion) != 0x0100) {
640 		aprint_error_dev(sc->sc_dev,
641 		    "bad HID descriptor bcdVersion (0x%x)\n",
642 		    le16toh(sc->hid_desc.bcdVersion));
643 		return (1);
644 	}
645 
646 	/* must be 30 bytes for v1.00 */
647 	if (le16toh(sc->hid_desc.wHIDDescLength !=
648 	    sizeof(struct i2c_hid_desc))) {
649 		aprint_error_dev(sc->sc_dev,
650 		    "bad HID descriptor size (%d != %zu)\n",
651 		    le16toh(sc->hid_desc.wHIDDescLength),
652 		    sizeof(struct i2c_hid_desc));
653 		return (1);
654 	}
655 
656 	if (le16toh(sc->hid_desc.wReportDescLength) <= 0) {
657 		aprint_error_dev(sc->sc_dev,
658 		    "bad HID report descriptor size (%d)\n",
659 		    le16toh(sc->hid_desc.wReportDescLength));
660 		return (1);
661 	}
662 
663 	while (retries-- > 0) {
664 		if (ihidev_reset(sc, false)) {
665 			if (retries == 0)
666 				return(1);
667 
668 			DELAY(1000);
669 		}
670 		else
671 			break;
672 	}
673 
674 	sc->sc_reportlen = le16toh(sc->hid_desc.wReportDescLength);
675 	sc->sc_report = kmem_zalloc(sc->sc_reportlen, KM_SLEEP);
676 
677 	if (ihidev_hid_command(sc, I2C_HID_REPORT_DESCR, 0, false)) {
678 		aprint_error_dev(sc->sc_dev, "failed fetching HID report\n");
679 		return (1);
680 	}
681 
682 	return (0);
683 }
684 
685 static bool
686 ihidev_intr_init(struct ihidev_softc *sc)
687 {
688 #if NACPICA > 0
689 	ACPI_HANDLE hdl = (void *)(uintptr_t)sc->sc_phandle;
690 	struct acpi_resources res;
691 	ACPI_STATUS rv;
692 	char buf[100];
693 
694 	rv = acpi_resource_parse(sc->sc_dev, hdl, "_CRS", &res,
695 	    &acpi_resource_parse_ops_quiet);
696 	if (ACPI_FAILURE(rv)) {
697 		aprint_error_dev(sc->sc_dev, "can't parse '_CRS'\n");
698 		return false;
699 	}
700 
701 	const struct acpi_irq * const irq = acpi_res_irq(&res, 0);
702 	if (irq == NULL) {
703 		aprint_debug_dev(sc->sc_dev, "no IRQ resource\n");
704 		acpi_resource_cleanup(&res);
705 #if NGPIO > 0
706 		goto try_gpioint;
707 #else
708 		return false;
709 #endif
710 	}
711 
712 	sc->sc_intr_type =
713 	    irq->ar_type == ACPI_EDGE_SENSITIVE ? IST_EDGE : IST_LEVEL;
714 
715 	acpi_resource_cleanup(&res);
716 
717 	sc->sc_ih = acpi_intr_establish(sc->sc_dev, sc->sc_phandle, IPL_TTY,
718 	    false, ihidev_intr, sc, device_xname(sc->sc_dev));
719 	if (sc->sc_ih == NULL) {
720 		aprint_error_dev(sc->sc_dev, "can't establish interrupt\n");
721 		return false;
722 	}
723 	aprint_normal_dev(sc->sc_dev, "interrupting at %s\n",
724 	    acpi_intr_string(sc->sc_ih, buf, sizeof(buf)));
725 
726 #if NGPIO > 0
727 try_gpioint:
728 	if (sc->sc_ih == NULL) {
729 		int pin, irqmode, error;
730 
731 		rv = acpi_gpio_get_int(hdl, 0, &sc->sc_ih_gpio, &pin, &irqmode);
732 		if (ACPI_FAILURE(rv)) {
733 			aprint_error_dev(sc->sc_dev,
734 			    "can't find gpioint resource\n");
735 			return false;
736 		}
737 
738 		sc->sc_ih_gpiomap.pm_map = sc->sc_ih_gpiopins;
739 		error = gpio_pin_map(sc->sc_ih_gpio, pin, 1,
740 		    &sc->sc_ih_gpiomap);
741 		if (error) {
742 			aprint_error_dev(sc->sc_dev, "can't map pin %d\n", pin);
743 			return false;
744 		}
745 
746 		sc->sc_ih = gpio_intr_establish(sc->sc_ih_gpio,
747 		    &sc->sc_ih_gpiomap, 0, IPL_VM, irqmode, ihidev_intr, sc);
748 		if (sc->sc_ih == NULL) {
749 			aprint_error_dev(sc->sc_dev,
750 			    "can't establish gpio interrupt\n");
751 			return false;
752 		}
753 
754 		sc->sc_intr_type = (irqmode & GPIO_INTR_LEVEL_MASK) ?
755 		    IST_LEVEL : IST_EDGE;
756 
757 		gpio_intr_str(sc->sc_ih_gpio, &sc->sc_ih_gpiomap, 0,
758 		    irqmode, buf, sizeof(buf));
759 		aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", buf);
760 	}
761 #endif
762 
763 	if (workqueue_create(&sc->sc_wq, device_xname(sc->sc_dev), ihidev_work,
764 		sc, PRI_NONE, IPL_TTY, WQ_MPSAFE)) {
765 		aprint_error_dev(sc->sc_dev,
766 		    "can't establish workqueue\n");
767 		return false;
768 	}
769 	sc->sc_work_pending = 0;
770 
771 	return true;
772 #else
773 	aprint_error_dev(sc->sc_dev, "can't establish interrupt\n");
774 	return false;
775 #endif
776 }
777 
778 static void
779 ihidev_intr_fini(struct ihidev_softc *sc)
780 {
781 #if NACPICA > 0
782 	if (sc->sc_ih != NULL) {
783 		if (sc->sc_ih_gpio != NULL) {
784 #if NGPIO > 0
785 			gpio_intr_disestablish(sc->sc_ih_gpio, sc->sc_ih);
786 #endif
787 		} else {
788 			acpi_intr_disestablish(sc->sc_ih);
789 		}
790 	}
791 	if (sc->sc_wq != NULL) {
792 		workqueue_destroy(sc->sc_wq);
793 	}
794 #endif
795 }
796 
797 #if NACPICA > 0
798 static void
799 ihidev_intr_mask(struct ihidev_softc * const sc)
800 {
801 
802 	if (sc->sc_intr_type == IST_LEVEL) {
803 		if (sc->sc_ih_gpio != NULL) {
804 #if NGPIO > 0
805 			gpio_intr_mask(sc->sc_ih_gpio, sc->sc_ih);
806 #endif
807 		} else {
808 			acpi_intr_mask(sc->sc_ih);
809 		}
810 	}
811 }
812 
813 static void
814 ihidev_intr_unmask(struct ihidev_softc * const sc)
815 {
816 
817 	if (sc->sc_intr_type == IST_LEVEL) {
818 		if (sc->sc_ih_gpio != NULL) {
819 #if NGPIO > 0
820 			gpio_intr_unmask(sc->sc_ih_gpio, sc->sc_ih);
821 #endif
822 		} else {
823 			acpi_intr_unmask(sc->sc_ih);
824 		}
825 	}
826 }
827 
828 static int
829 ihidev_intr(void *arg)
830 {
831 	struct ihidev_softc * const sc = arg;
832 
833 	/*
834 	 * Schedule our work.  If we're using a level-triggered
835 	 * interrupt, we have to mask it off while we wait for service.
836 	 */
837 	if (atomic_swap_uint(&sc->sc_work_pending, 1) == 0)
838 		workqueue_enqueue(sc->sc_wq, &sc->sc_work, NULL);
839 	ihidev_intr_mask(sc);
840 
841 	return 1;
842 }
843 
844 static void
845 ihidev_work(struct work *wk, void *arg)
846 {
847 	struct ihidev_softc * const sc = arg;
848 	struct ihidev *scd;
849 	u_int psize;
850 	int res, i;
851 	u_char *p;
852 	u_int rep = 0;
853 
854 	atomic_store_relaxed(&sc->sc_work_pending, 0);
855 
856 	mutex_enter(&sc->sc_lock);
857 
858 	iic_acquire_bus(sc->sc_tag, 0);
859 	res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, NULL, 0,
860 	    sc->sc_ibuf, sc->sc_isize, 0);
861 	iic_release_bus(sc->sc_tag, 0);
862 	if (res != 0)
863 		goto out;
864 
865 	/*
866 	 * 6.1.1 - First two bytes are the packet length, which must be less
867 	 * than or equal to wMaxInputLength
868 	 */
869 	psize = sc->sc_ibuf[0] | sc->sc_ibuf[1] << 8;
870 	if (!psize || psize > sc->sc_isize) {
871 		DPRINTF(("%s: %s: invalid packet size (%d vs. %d)\n",
872 		    device_xname(sc->sc_dev), __func__, psize, sc->sc_isize));
873 		goto out;
874 	}
875 
876 	/* 3rd byte is the report id */
877 	p = sc->sc_ibuf + 2;
878 	psize -= 2;
879 	if (sc->sc_nrepid != 1)
880 		rep = *p++, psize--;
881 
882 	if (rep >= sc->sc_nrepid) {
883 		aprint_error_dev(sc->sc_dev, "%s: bad report id %d\n",
884 		    __func__, rep);
885 		goto out;
886 	}
887 
888 	DPRINTF(("%s: %s: hid input (rep %d):", device_xname(sc->sc_dev),
889 	    __func__, rep));
890 	for (i = 0; i < sc->sc_isize; i++)
891 		DPRINTF((" %.2x", sc->sc_ibuf[i]));
892 	DPRINTF(("\n"));
893 
894 	scd = sc->sc_subdevs[rep];
895 	if (scd == NULL || !(scd->sc_state & IHIDEV_OPEN))
896 		goto out;
897 
898 	scd->sc_intr(scd, p, psize);
899 
900  out:
901 	mutex_exit(&sc->sc_lock);
902 
903 	/*
904 	 * If our interrupt is level-triggered, re-enable it now.
905 	 */
906 	ihidev_intr_unmask(sc);
907 }
908 #endif
909 
910 static int
911 ihidev_maxrepid(void *buf, int len)
912 {
913 	struct hid_data *d;
914 	struct hid_item h;
915 	int maxid;
916 
917 	maxid = -1;
918 	h.report_ID = 0;
919 	for (d = hid_start_parse(buf, len, hid_none); hid_get_item(d, &h); )
920 		if ((int)h.report_ID > maxid)
921 			maxid = h.report_ID;
922 	hid_end_parse(d);
923 
924 	return (maxid);
925 }
926 
927 static int
928 ihidev_print(void *aux, const char *pnp)
929 {
930 	struct ihidev_attach_arg *iha = aux;
931 
932 	if (iha->reportid == IHIDEV_CLAIM_ALLREPORTID)
933 		return (QUIET);
934 
935 	if (pnp)
936 		aprint_normal("hid at %s", pnp);
937 
938 	if (iha->reportid != 0)
939 		aprint_normal(" reportid %d", iha->reportid);
940 
941 	return (UNCONF);
942 }
943 
944 static int
945 ihidev_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
946 {
947 	struct ihidev_attach_arg *iha = aux;
948 
949 	if (cf->ihidevcf_reportid != IHIDEV_UNK_REPORTID &&
950 	    cf->ihidevcf_reportid != iha->reportid)
951 		return (0);
952 
953 	return config_match(parent, cf, aux);
954 }
955 
956 int
957 ihidev_open(struct ihidev *scd)
958 {
959 	struct ihidev_softc *sc = scd->sc_parent;
960 	int error;
961 
962 	DPRINTF(("%s: %s: state=%d refcnt=%d\n", device_xname(sc->sc_dev),
963 	    __func__, scd->sc_state, sc->sc_refcnt));
964 
965 	mutex_enter(&sc->sc_lock);
966 
967 	if (scd->sc_state & IHIDEV_OPEN || sc->sc_refcnt == INT_MAX) {
968 		error = EBUSY;
969 		goto out;
970 	}
971 
972 	scd->sc_state |= IHIDEV_OPEN;
973 
974 	if (sc->sc_refcnt++ || sc->sc_isize == 0) {
975 		error = 0;
976 		goto out;
977 	}
978 
979 	/* power on */
980 	ihidev_poweron(sc, false);
981 	error = 0;
982 
983 out:	mutex_exit(&sc->sc_lock);
984 	return error;
985 }
986 
987 void
988 ihidev_close(struct ihidev *scd)
989 {
990 	struct ihidev_softc *sc = scd->sc_parent;
991 
992 	DPRINTF(("%s: %s: state=%d refcnt=%d\n", device_xname(sc->sc_dev),
993 	    __func__, scd->sc_state, sc->sc_refcnt));
994 
995 	mutex_enter(&sc->sc_lock);
996 
997 	KASSERTMSG(scd->sc_state & IHIDEV_OPEN,
998 	    "%s: closing %s when not open",
999 	    device_xname(scd->sc_idev),
1000 	    device_xname(sc->sc_dev));
1001 	scd->sc_state &= ~IHIDEV_OPEN;
1002 
1003 	if (--sc->sc_refcnt)
1004 		goto out;
1005 
1006 	if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER,
1007 	    &I2C_HID_POWER_OFF, false))
1008 		aprint_error_dev(sc->sc_dev, "failed to power down\n");
1009 
1010 out:	mutex_exit(&sc->sc_lock);
1011 }
1012 
1013 void
1014 ihidev_get_report_desc(struct ihidev_softc *sc, void **desc, int *size)
1015 {
1016 	*desc = sc->sc_report;
1017 	*size = sc->sc_reportlen;
1018 }
1019 
1020 /* convert hid_* constants used throughout HID code to i2c HID equivalents */
1021 int
1022 ihidev_report_type_conv(int hid_type_id)
1023 {
1024 	switch (hid_type_id) {
1025 	case hid_input:
1026 		return I2C_HID_REPORT_TYPE_INPUT;
1027 	case hid_output:
1028 		return I2C_HID_REPORT_TYPE_OUTPUT;
1029 	case hid_feature:
1030 		return I2C_HID_REPORT_TYPE_FEATURE;
1031 	default:
1032 		return -1;
1033 	}
1034 }
1035 
1036 int
1037 ihidev_get_report(struct device *dev, int type, int id, void *data, int len)
1038 {
1039 	struct ihidev_softc *sc = (struct ihidev_softc *)dev;
1040 	struct i2c_hid_report_request rreq;
1041 	int ctype;
1042 
1043 	if ((ctype = ihidev_report_type_conv(type)) < 0)
1044 		return (1);
1045 
1046 	rreq.type = ctype;
1047 	rreq.id = id;
1048 	rreq.data = data;
1049 	rreq.len = len;
1050 
1051 	if (ihidev_hid_command(sc, I2C_HID_CMD_GET_REPORT, &rreq, false)) {
1052 		aprint_error_dev(sc->sc_dev, "failed fetching report\n");
1053 		return (1);
1054 	}
1055 
1056 	return 0;
1057 }
1058 
1059 int
1060 ihidev_set_report(struct device *dev, int type, int id, void *data,
1061     int len)
1062 {
1063 	struct ihidev_softc *sc = (struct ihidev_softc *)dev;
1064 	struct i2c_hid_report_request rreq;
1065 	int ctype;
1066 
1067 	if ((ctype = ihidev_report_type_conv(type)) < 0)
1068 		return (1);
1069 
1070 	rreq.type = ctype;
1071 	rreq.id = id;
1072 	rreq.data = data;
1073 	rreq.len = len;
1074 
1075 	if (ihidev_hid_command(sc, I2C_HID_CMD_SET_REPORT, &rreq, false)) {
1076 		aprint_error_dev(sc->sc_dev, "failed setting report\n");
1077 		return (1);
1078 	}
1079 
1080 	return 0;
1081 }
1082 
1083 static bool
1084 ihidev_acpi_get_info(struct ihidev_softc *sc)
1085 {
1086 #if NACPICA > 0
1087 	ACPI_HANDLE hdl = (void *)(uintptr_t)sc->sc_phandle;
1088 	ACPI_STATUS status;
1089 	ACPI_INTEGER val;
1090 
1091 	/* 3cdff6f7-4267-4555-ad05-b30a3d8938de */
1092 	uint8_t i2c_hid_guid[] = {
1093 		0xF7, 0xF6, 0xDF, 0x3C,
1094 		0x67, 0x42,
1095 		0x55, 0x45,
1096 		0xAD, 0x05,
1097 		0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE,
1098 	};
1099 
1100 	status = acpi_dsm_integer(hdl, i2c_hid_guid, 1, 1, NULL, &val);
1101 	if (ACPI_FAILURE(status)) {
1102 		aprint_error_dev(sc->sc_dev,
1103 		    "failed to get HidDescriptorAddress: %s\n",
1104 		    AcpiFormatException(status));
1105 		return false;
1106 	}
1107 
1108 	sc->sc_hid_desc_addr = (u_int)val;
1109 
1110 	return true;
1111 #else
1112 	return false;
1113 #endif
1114 }
1115