ihidev.c revision 1.19.2.1 1 /* $NetBSD: ihidev.c,v 1.19.2.1 2021/05/08 15:44:12 thorpej 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 (at) 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 <sys/cdefs.h>
57 __KERNEL_RCSID(0, "$NetBSD: ihidev.c,v 1.19.2.1 2021/05/08 15:44:12 thorpej Exp $");
58
59 #include <sys/param.h>
60 #include <sys/systm.h>
61 #include <sys/device.h>
62 #include <sys/kmem.h>
63
64
65 #include <dev/i2c/i2cvar.h>
66 #include <dev/i2c/ihidev.h>
67
68 #include <dev/hid/hid.h>
69
70 #if defined(__i386__) || defined(__amd64__)
71 # include "acpica.h"
72 #endif
73 #if NACPICA > 0
74 #include <dev/acpi/acpivar.h>
75 #include <dev/acpi/acpi_intr.h>
76 #endif
77
78 #include "locators.h"
79
80 /* #define IHIDEV_DEBUG */
81
82 #ifdef IHIDEV_DEBUG
83 #define DPRINTF(x) printf x
84 #else
85 #define DPRINTF(x)
86 #endif
87
88 /* 7.2 */
89 enum {
90 I2C_HID_CMD_DESCR = 0x0,
91 I2C_HID_CMD_RESET = 0x1,
92 I2C_HID_CMD_GET_REPORT = 0x2,
93 I2C_HID_CMD_SET_REPORT = 0x3,
94 I2C_HID_CMD_GET_IDLE = 0x4,
95 I2C_HID_CMD_SET_IDLE = 0x5,
96 I2C_HID_CMD_GET_PROTO = 0x6,
97 I2C_HID_CMD_SET_PROTO = 0x7,
98 I2C_HID_CMD_SET_POWER = 0x8,
99
100 /* pseudo commands */
101 I2C_HID_REPORT_DESCR = 0x100,
102 };
103
104 static int I2C_HID_POWER_ON = 0x0;
105 static int I2C_HID_POWER_OFF = 0x1;
106
107 static int ihidev_match(device_t, cfdata_t, void *);
108 static void ihidev_attach(device_t, device_t, void *);
109 static int ihidev_detach(device_t, int);
110 CFATTACH_DECL_NEW(ihidev, sizeof(struct ihidev_softc),
111 ihidev_match, ihidev_attach, ihidev_detach, NULL);
112
113 static bool ihiddev_intr_init(struct ihidev_softc *);
114 static void ihiddev_intr_fini(struct ihidev_softc *);
115
116 static bool ihidev_suspend(device_t, const pmf_qual_t *);
117 static bool ihidev_resume(device_t, const pmf_qual_t *);
118 static int ihidev_hid_command(struct ihidev_softc *, int, void *, bool);
119 static int ihidev_intr(void *);
120 static void ihidev_softintr(void *);
121 static int ihidev_reset(struct ihidev_softc *, bool);
122 static int ihidev_hid_desc_parse(struct ihidev_softc *);
123
124 static int ihidev_maxrepid(void *, int);
125 static int ihidev_print(void *, const char *);
126 static int ihidev_submatch(device_t, cfdata_t, const int *, void *);
127
128 static bool ihidev_acpi_get_info(struct ihidev_softc *);
129
130 static const struct device_compatible_entry compat_data[] = {
131 { .compat = "PNP0C50" },
132 { .compat = "ACPI0C50" },
133 { .compat = "hid-over-i2c" },
134 DEVICE_COMPAT_EOL
135 };
136
137 static int
138 ihidev_match(device_t parent, cfdata_t match, void *aux)
139 {
140 struct i2c_attach_args * const ia = aux;
141 int match_result;
142
143 if (iic_use_direct_match(ia, match, compat_data, &match_result))
144 return I2C_MATCH_DIRECT_COMPATIBLE;
145
146 return 0;
147 }
148
149 static void
150 ihidev_attach(device_t parent, device_t self, void *aux)
151 {
152 struct ihidev_softc *sc = device_private(self);
153 struct i2c_attach_args *ia = aux;
154 struct ihidev_attach_arg iha;
155 device_t dev;
156 int repid, repsz;
157 int isize;
158 int locs[IHIDBUSCF_NLOCS];
159
160 sc->sc_dev = self;
161 sc->sc_tag = ia->ia_tag;
162 sc->sc_addr = ia->ia_addr;
163 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_VM);
164
165 if (devhandle_type(device_handle(self)) != DEVHANDLE_TYPE_ACPI) {
166 aprint_error(": unsupported device tree type\n");
167 return;
168 }
169 if (! ihidev_acpi_get_info(sc)) {
170 return;
171 }
172
173 if (ihidev_hid_command(sc, I2C_HID_CMD_DESCR, NULL, false) ||
174 ihidev_hid_desc_parse(sc)) {
175 aprint_error(": failed fetching initial HID descriptor\n");
176 return;
177 }
178
179 aprint_naive("\n");
180 aprint_normal(": vendor 0x%x product 0x%x, %s\n",
181 le16toh(sc->hid_desc.wVendorID), le16toh(sc->hid_desc.wProductID),
182 ia->ia_name);
183
184 sc->sc_nrepid = ihidev_maxrepid(sc->sc_report, sc->sc_reportlen);
185 if (sc->sc_nrepid < 0)
186 return;
187
188 aprint_normal_dev(self, "%d report id%s\n", sc->sc_nrepid,
189 sc->sc_nrepid > 1 ? "s" : "");
190
191 sc->sc_nrepid++;
192 sc->sc_subdevs = kmem_zalloc(sc->sc_nrepid * sizeof(struct ihidev *),
193 KM_SLEEP);
194
195 /* find largest report size and allocate memory for input buffer */
196 sc->sc_isize = le16toh(sc->hid_desc.wMaxInputLength);
197 for (repid = 0; repid < sc->sc_nrepid; repid++) {
198 repsz = hid_report_size(sc->sc_report, sc->sc_reportlen,
199 hid_input, repid);
200
201 isize = repsz + 2; /* two bytes for the length */
202 isize += (sc->sc_nrepid != 1); /* one byte for the report ID */
203 if (isize > sc->sc_isize)
204 sc->sc_isize = isize;
205
206 DPRINTF(("%s: repid %d size %d\n", sc->sc_dev.dv_xname, repid,
207 repsz));
208 }
209 sc->sc_ibuf = kmem_zalloc(sc->sc_isize, KM_SLEEP);
210 if (! ihiddev_intr_init(sc)) {
211 return;
212 }
213
214 iha.iaa = ia;
215 iha.parent = sc;
216
217 /* Look for a driver claiming all report IDs first. */
218 iha.reportid = IHIDEV_CLAIM_ALLREPORTID;
219 locs[IHIDBUSCF_REPORTID] = IHIDEV_CLAIM_ALLREPORTID;
220 dev = config_found(self, &iha, ihidev_print,
221 CFARG_SUBMATCH, ihidev_submatch,
222 CFARG_LOCATORS, locs,
223 CFARG_EOL);
224 if (dev != NULL) {
225 for (repid = 0; repid < sc->sc_nrepid; repid++)
226 sc->sc_subdevs[repid] = device_private(dev);
227 return;
228 }
229
230 for (repid = 0; repid < sc->sc_nrepid; repid++) {
231 if (hid_report_size(sc->sc_report, sc->sc_reportlen, hid_input,
232 repid) == 0 &&
233 hid_report_size(sc->sc_report, sc->sc_reportlen,
234 hid_output, repid) == 0 &&
235 hid_report_size(sc->sc_report, sc->sc_reportlen,
236 hid_feature, repid) == 0)
237 continue;
238
239 iha.reportid = repid;
240 locs[IHIDBUSCF_REPORTID] = repid;
241 dev = config_found(self, &iha, ihidev_print,
242 CFARG_SUBMATCH, ihidev_submatch,
243 CFARG_LOCATORS, locs,
244 CFARG_EOL);
245 sc->sc_subdevs[repid] = device_private(dev);
246 }
247
248 /* power down until we're opened */
249 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER, &I2C_HID_POWER_OFF, false)) {
250 aprint_error_dev(sc->sc_dev, "failed to power down\n");
251 return;
252 }
253 if (!pmf_device_register(self, ihidev_suspend, ihidev_resume))
254 aprint_error_dev(self, "couldn't establish power handler\n");
255 }
256
257 static int
258 ihidev_detach(device_t self, int flags)
259 {
260 struct ihidev_softc *sc = device_private(self);
261
262 mutex_enter(&sc->sc_intr_lock);
263 ihiddev_intr_fini(sc);
264 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER,
265 &I2C_HID_POWER_OFF, true))
266 aprint_error_dev(sc->sc_dev, "failed to power down\n");
267 mutex_exit(&sc->sc_intr_lock);
268 if (sc->sc_ibuf != NULL) {
269 kmem_free(sc->sc_ibuf, sc->sc_isize);
270 sc->sc_ibuf = NULL;
271 }
272
273 if (sc->sc_report != NULL)
274 kmem_free(sc->sc_report, sc->sc_reportlen);
275
276 pmf_device_deregister(self);
277 return (0);
278 }
279
280 static bool
281 ihidev_suspend(device_t self, const pmf_qual_t *q)
282 {
283 struct ihidev_softc *sc = device_private(self);
284
285 mutex_enter(&sc->sc_intr_lock);
286 if (sc->sc_refcnt > 0) {
287 printf("ihidev power off\n");
288 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER,
289 &I2C_HID_POWER_OFF, true))
290 aprint_error_dev(sc->sc_dev, "failed to power down\n");
291 }
292 mutex_exit(&sc->sc_intr_lock);
293 return true;
294 }
295
296 static bool
297 ihidev_resume(device_t self, const pmf_qual_t *q)
298 {
299 struct ihidev_softc *sc = device_private(self);
300
301 mutex_enter(&sc->sc_intr_lock);
302 if (sc->sc_refcnt > 0) {
303 printf("ihidev power reset\n");
304 ihidev_reset(sc, true);
305 }
306 mutex_exit(&sc->sc_intr_lock);
307 return true;
308 }
309
310 static int
311 ihidev_hid_command(struct ihidev_softc *sc, int hidcmd, void *arg, bool poll)
312 {
313 int i, res = 1;
314 int flags = poll ? I2C_F_POLL : 0;
315
316 iic_acquire_bus(sc->sc_tag, flags);
317
318 switch (hidcmd) {
319 case I2C_HID_CMD_DESCR: {
320 /*
321 * 5.2.2 - HID Descriptor Retrieval
322 * register is passed from the controller
323 */
324 uint8_t cmd[] = {
325 htole16(sc->sc_hid_desc_addr) & 0xff,
326 htole16(sc->sc_hid_desc_addr) >> 8,
327 };
328
329 DPRINTF(("%s: HID command I2C_HID_CMD_DESCR at 0x%x\n",
330 sc->sc_dev.dv_xname, htole16(sc->sc_hid_desc_addr)));
331
332 /* 20 00 */
333 res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
334 &cmd, sizeof(cmd), &sc->hid_desc_buf,
335 sizeof(struct i2c_hid_desc), flags);
336
337 DPRINTF(("%s: HID descriptor:", sc->sc_dev.dv_xname));
338 for (i = 0; i < sizeof(struct i2c_hid_desc); i++)
339 DPRINTF((" %.2x", sc->hid_desc_buf[i]));
340 DPRINTF(("\n"));
341
342 break;
343 }
344 case I2C_HID_CMD_RESET: {
345 uint8_t cmd[] = {
346 htole16(sc->hid_desc.wCommandRegister) & 0xff,
347 htole16(sc->hid_desc.wCommandRegister) >> 8,
348 0,
349 I2C_HID_CMD_RESET,
350 };
351
352 DPRINTF(("%s: HID command I2C_HID_CMD_RESET\n",
353 sc->sc_dev.dv_xname));
354
355 /* 22 00 00 01 */
356 res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
357 &cmd, sizeof(cmd), NULL, 0, flags);
358
359 break;
360 }
361 case I2C_HID_CMD_GET_REPORT: {
362 struct i2c_hid_report_request *rreq =
363 (struct i2c_hid_report_request *)arg;
364
365 uint8_t cmd[] = {
366 htole16(sc->hid_desc.wCommandRegister) & 0xff,
367 htole16(sc->hid_desc.wCommandRegister) >> 8,
368 0,
369 I2C_HID_CMD_GET_REPORT,
370 0, 0, 0,
371 };
372 int cmdlen = 7;
373 int dataoff = 4;
374 int report_id = rreq->id;
375 int report_id_len = 1;
376 int report_len = rreq->len + 2;
377 int d;
378 uint8_t *tmprep;
379
380 DPRINTF(("%s: HID command I2C_HID_CMD_GET_REPORT %d "
381 "(type %d, len %d)\n", sc->sc_dev.dv_xname, report_id,
382 rreq->type, rreq->len));
383
384 /*
385 * 7.2.2.4 - "The protocol is optimized for Report < 15. If a
386 * report ID >= 15 is necessary, then the Report ID in the Low
387 * Byte must be set to 1111 and a Third Byte is appended to the
388 * protocol. This Third Byte contains the entire/actual report
389 * ID."
390 */
391 if (report_id >= 15) {
392 cmd[dataoff++] = report_id;
393 report_id = 15;
394 report_id_len = 2;
395 } else
396 cmdlen--;
397
398 cmd[2] = report_id | rreq->type << 4;
399
400 cmd[dataoff++] = sc->hid_desc.wDataRegister & 0xff;
401 cmd[dataoff] = sc->hid_desc.wDataRegister >> 8;
402
403 /*
404 * 7.2.2.2 - Response will be a 2-byte length value, the report
405 * id with length determined above, and then the report.
406 * Allocate rreq->len + 2 + 2 bytes, read into that temporary
407 * buffer, and then copy only the report back out to
408 * rreq->data.
409 */
410 report_len += report_id_len;
411 tmprep = kmem_zalloc(report_len, KM_NOSLEEP);
412
413 /* type 3 id 8: 22 00 38 02 23 00 */
414 res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
415 &cmd, cmdlen, tmprep, report_len, flags);
416
417 d = tmprep[0] | tmprep[1] << 8;
418 if (d != report_len) {
419 DPRINTF(("%s: response size %d != expected length %d\n",
420 sc->sc_dev.dv_xname, d, report_len));
421 }
422
423 if (report_id_len == 2)
424 d = tmprep[2] | tmprep[3] << 8;
425 else
426 d = tmprep[2];
427
428 if (d != rreq->id) {
429 DPRINTF(("%s: response report id %d != %d\n",
430 sc->sc_dev.dv_xname, d, rreq->id));
431 iic_release_bus(sc->sc_tag, 0);
432 kmem_free(tmprep, report_len);
433 return (1);
434 }
435
436 DPRINTF(("%s: response:", sc->sc_dev.dv_xname));
437 for (i = 0; i < report_len; i++)
438 DPRINTF((" %.2x", tmprep[i]));
439 DPRINTF(("\n"));
440
441 memcpy(rreq->data, tmprep + 2 + report_id_len, rreq->len);
442 kmem_free(tmprep, report_len);
443
444 break;
445 }
446 case I2C_HID_CMD_SET_REPORT: {
447 struct i2c_hid_report_request *rreq =
448 (struct i2c_hid_report_request *)arg;
449
450 uint8_t cmd[] = {
451 htole16(sc->hid_desc.wCommandRegister) & 0xff,
452 htole16(sc->hid_desc.wCommandRegister) >> 8,
453 0,
454 I2C_HID_CMD_SET_REPORT,
455 0, 0, 0, 0, 0, 0,
456 };
457 int cmdlen = 10;
458 int report_id = rreq->id;
459 int report_len = 2 + (report_id ? 1 : 0) + rreq->len;
460 int dataoff;
461 uint8_t *finalcmd;
462
463 DPRINTF(("%s: HID command I2C_HID_CMD_SET_REPORT %d "
464 "(type %d, len %d):", sc->sc_dev.dv_xname, report_id,
465 rreq->type, rreq->len));
466 for (i = 0; i < rreq->len; i++)
467 DPRINTF((" %.2x", ((uint8_t *)rreq->data)[i]));
468 DPRINTF(("\n"));
469
470 /*
471 * 7.2.2.4 - "The protocol is optimized for Report < 15. If a
472 * report ID >= 15 is necessary, then the Report ID in the Low
473 * Byte must be set to 1111 and a Third Byte is appended to the
474 * protocol. This Third Byte contains the entire/actual report
475 * ID."
476 */
477 dataoff = 4;
478 if (report_id >= 15) {
479 cmd[dataoff++] = report_id;
480 report_id = 15;
481 } else
482 cmdlen--;
483
484 cmd[2] = report_id | rreq->type << 4;
485
486 if (rreq->type == I2C_HID_REPORT_TYPE_FEATURE) {
487 cmd[dataoff++] = htole16(sc->hid_desc.wDataRegister)
488 & 0xff;
489 cmd[dataoff++] = htole16(sc->hid_desc.wDataRegister)
490 >> 8;
491 } else {
492 cmd[dataoff++] = htole16(sc->hid_desc.wOutputRegister)
493 & 0xff;
494 cmd[dataoff++] = htole16(sc->hid_desc.wOutputRegister)
495 >> 8;
496 }
497
498 cmd[dataoff++] = report_len & 0xff;
499 cmd[dataoff++] = report_len >> 8;
500 cmd[dataoff] = rreq->id;
501
502 finalcmd = kmem_zalloc(cmdlen + rreq->len, KM_NOSLEEP);
503
504 memcpy(finalcmd, cmd, cmdlen);
505 memcpy(finalcmd + cmdlen, rreq->data, rreq->len);
506
507 /* type 3 id 4: 22 00 34 03 23 00 04 00 04 03 */
508 res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
509 finalcmd, cmdlen + rreq->len, NULL, 0, flags);
510 kmem_free(finalcmd, cmdlen + rreq->len);
511
512 break;
513 }
514
515 case I2C_HID_CMD_SET_POWER: {
516 int power = *(int *)arg;
517 uint8_t cmd[] = {
518 htole16(sc->hid_desc.wCommandRegister) & 0xff,
519 htole16(sc->hid_desc.wCommandRegister) >> 8,
520 power,
521 I2C_HID_CMD_SET_POWER,
522 };
523
524 DPRINTF(("%s: HID command I2C_HID_CMD_SET_POWER(%d)\n",
525 sc->sc_dev.dv_xname, power));
526
527 /* 22 00 00 08 */
528 res = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
529 &cmd, sizeof(cmd), NULL, 0, flags);
530
531 break;
532 }
533 case I2C_HID_REPORT_DESCR: {
534 uint8_t cmd[] = {
535 htole16(sc->hid_desc.wReportDescRegister) & 0xff,
536 htole16(sc->hid_desc.wReportDescRegister) >> 8,
537 };
538
539 DPRINTF(("%s: HID command I2C_HID_REPORT_DESCR at 0x%x with "
540 "size %d\n", sc->sc_dev.dv_xname, cmd[0],
541 sc->sc_reportlen));
542
543 /* 20 00 */
544 res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
545 &cmd, sizeof(cmd), sc->sc_report, sc->sc_reportlen, flags);
546
547 DPRINTF(("%s: HID report descriptor:", sc->sc_dev.dv_xname));
548 for (i = 0; i < sc->sc_reportlen; i++)
549 DPRINTF((" %.2x", sc->sc_report[i]));
550 DPRINTF(("\n"));
551
552 break;
553 }
554 default:
555 aprint_error_dev(sc->sc_dev, "unknown command %d\n",
556 hidcmd);
557 }
558
559 iic_release_bus(sc->sc_tag, flags);
560
561 return (res);
562 }
563
564 static int
565 ihidev_reset(struct ihidev_softc *sc, bool poll)
566 {
567 DPRINTF(("%s: resetting\n", sc->sc_dev.dv_xname));
568
569 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER,
570 &I2C_HID_POWER_ON, poll)) {
571 aprint_error_dev(sc->sc_dev, "failed to power on\n");
572 return (1);
573 }
574
575 DELAY(1000);
576
577 if (ihidev_hid_command(sc, I2C_HID_CMD_RESET, 0, poll)) {
578 aprint_error_dev(sc->sc_dev, "failed to reset hardware\n");
579
580 ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER,
581 &I2C_HID_POWER_OFF, poll);
582
583 return (1);
584 }
585
586 DELAY(1000);
587
588 return (0);
589 }
590
591 /*
592 * 5.2.2 - HID Descriptor Retrieval
593 *
594 * parse HID Descriptor that has already been read into hid_desc with
595 * I2C_HID_CMD_DESCR
596 */
597 static int
598 ihidev_hid_desc_parse(struct ihidev_softc *sc)
599 {
600 int retries = 3;
601
602 /* must be v01.00 */
603 if (le16toh(sc->hid_desc.bcdVersion) != 0x0100) {
604 aprint_error_dev(sc->sc_dev,
605 "bad HID descriptor bcdVersion (0x%x)\n",
606 le16toh(sc->hid_desc.bcdVersion));
607 return (1);
608 }
609
610 /* must be 30 bytes for v1.00 */
611 if (le16toh(sc->hid_desc.wHIDDescLength !=
612 sizeof(struct i2c_hid_desc))) {
613 aprint_error_dev(sc->sc_dev,
614 "bad HID descriptor size (%d != %zu)\n",
615 le16toh(sc->hid_desc.wHIDDescLength),
616 sizeof(struct i2c_hid_desc));
617 return (1);
618 }
619
620 if (le16toh(sc->hid_desc.wReportDescLength) <= 0) {
621 aprint_error_dev(sc->sc_dev,
622 "bad HID report descriptor size (%d)\n",
623 le16toh(sc->hid_desc.wReportDescLength));
624 return (1);
625 }
626
627 while (retries-- > 0) {
628 if (ihidev_reset(sc, false)) {
629 if (retries == 0)
630 return(1);
631
632 DELAY(1000);
633 }
634 else
635 break;
636 }
637
638 sc->sc_reportlen = le16toh(sc->hid_desc.wReportDescLength);
639 sc->sc_report = kmem_zalloc(sc->sc_reportlen, KM_NOSLEEP);
640
641 if (ihidev_hid_command(sc, I2C_HID_REPORT_DESCR, 0, false)) {
642 aprint_error_dev(sc->sc_dev, "failed fetching HID report\n");
643 return (1);
644 }
645
646 return (0);
647 }
648
649 static bool
650 ihiddev_intr_init(struct ihidev_softc *sc)
651 {
652 #if NACPICA > 0
653 ACPI_HANDLE hdl = devhandle_to_acpi(device_handle(sc->sc_dev));
654 struct acpi_resources res;
655 ACPI_STATUS rv;
656 char buf[100];
657
658 rv = acpi_resource_parse(sc->sc_dev, hdl, "_CRS", &res,
659 &acpi_resource_parse_ops_quiet);
660 if (ACPI_FAILURE(rv)) {
661 aprint_error_dev(sc->sc_dev, "can't parse '_CRS'\n");
662 return false;
663 }
664
665 const struct acpi_irq * const irq = acpi_res_irq(&res, 0);
666 if (irq == NULL) {
667 aprint_error_dev(sc->sc_dev, "no IRQ resource\n");
668 acpi_resource_cleanup(&res);
669 return false;
670 }
671
672 sc->sc_intr_type =
673 irq->ar_type == ACPI_EDGE_SENSITIVE ? IST_EDGE : IST_LEVEL;
674
675 acpi_resource_cleanup(&res);
676
677 sc->sc_ih = acpi_intr_establish(sc->sc_dev, (uint64_t)hdl, IPL_TTY,
678 false, ihidev_intr, sc, device_xname(sc->sc_dev));
679 if (sc->sc_ih == NULL) {
680 aprint_error_dev(sc->sc_dev, "can't establish interrupt\n");
681 return false;
682 }
683 aprint_normal_dev(sc->sc_dev, "interrupting at %s\n",
684 acpi_intr_string(sc->sc_ih, buf, sizeof(buf)));
685
686 sc->sc_sih = softint_establish(SOFTINT_SERIAL, ihidev_softintr, sc);
687 if (sc->sc_sih == NULL) {
688 aprint_error_dev(sc->sc_dev,
689 "can't establish soft interrupt\n");
690 return false;
691 }
692
693 return true;
694 #else
695 aprint_error_dev(sc->sc_dev, "can't establish interrupt\n");
696 return false;
697 #endif
698 }
699
700 static void
701 ihiddev_intr_fini(struct ihidev_softc *sc)
702 {
703 #if NACPICA > 0
704 if (sc->sc_ih != NULL) {
705 acpi_intr_disestablish(sc->sc_ih);
706 }
707 if (sc->sc_sih != NULL) {
708 softint_disestablish(sc->sc_sih);
709 }
710 #endif
711 }
712
713 static void
714 ihidev_intr_mask(struct ihidev_softc * const sc)
715 {
716
717 if (sc->sc_intr_type == IST_LEVEL) {
718 #if NACPICA > 0
719 acpi_intr_mask(sc->sc_ih);
720 #endif
721 }
722 }
723
724 static void
725 ihidev_intr_unmask(struct ihidev_softc * const sc)
726 {
727
728 if (sc->sc_intr_type == IST_LEVEL) {
729 #if NACPICA > 0
730 acpi_intr_unmask(sc->sc_ih);
731 #endif
732 }
733 }
734
735 static int
736 ihidev_intr(void *arg)
737 {
738 struct ihidev_softc * const sc = arg;
739
740 mutex_enter(&sc->sc_intr_lock);
741
742 /*
743 * Schedule our soft interrupt handler. If we're using a level-
744 * triggered interrupt, we have to mask it off while we wait
745 * for service.
746 */
747 softint_schedule(sc->sc_sih);
748 ihidev_intr_mask(sc);
749
750 mutex_exit(&sc->sc_intr_lock);
751
752 return 1;
753 }
754
755 static void
756 ihidev_softintr(void *arg)
757 {
758 struct ihidev_softc * const sc = arg;
759 struct ihidev *scd;
760 u_int psize;
761 int res, i;
762 u_char *p;
763 u_int rep = 0;
764
765 mutex_enter(&sc->sc_intr_lock);
766 iic_acquire_bus(sc->sc_tag, 0);
767 res = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, NULL, 0,
768 sc->sc_ibuf, sc->sc_isize, 0);
769 iic_release_bus(sc->sc_tag, 0);
770 mutex_exit(&sc->sc_intr_lock);
771
772 if (res != 0)
773 goto out;
774
775 /*
776 * 6.1.1 - First two bytes are the packet length, which must be less
777 * than or equal to wMaxInputLength
778 */
779 psize = sc->sc_ibuf[0] | sc->sc_ibuf[1] << 8;
780 if (!psize || psize > sc->sc_isize) {
781 DPRINTF(("%s: %s: invalid packet size (%d vs. %d)\n",
782 sc->sc_dev.dv_xname, __func__, psize, sc->sc_isize));
783 goto out;
784 }
785
786 /* 3rd byte is the report id */
787 p = sc->sc_ibuf + 2;
788 psize -= 2;
789 if (sc->sc_nrepid != 1)
790 rep = *p++, psize--;
791
792 if (rep >= sc->sc_nrepid) {
793 aprint_error_dev(sc->sc_dev, "%s: bad report id %d\n",
794 __func__, rep);
795 goto out;
796 }
797
798 DPRINTF(("%s: %s: hid input (rep %d):", sc->sc_dev.dv_xname,
799 __func__, rep));
800 for (i = 0; i < sc->sc_isize; i++)
801 DPRINTF((" %.2x", sc->sc_ibuf[i]));
802 DPRINTF(("\n"));
803
804 scd = sc->sc_subdevs[rep];
805 if (scd == NULL || !(scd->sc_state & IHIDEV_OPEN))
806 goto out;
807
808 scd->sc_intr(scd, p, psize);
809
810 out:
811 /*
812 * If our interrupt is level-triggered, re-enable it now.
813 */
814 ihidev_intr_unmask(sc);
815 }
816
817 static int
818 ihidev_maxrepid(void *buf, int len)
819 {
820 struct hid_data *d;
821 struct hid_item h;
822 int maxid;
823
824 maxid = -1;
825 h.report_ID = 0;
826 for (d = hid_start_parse(buf, len, hid_none); hid_get_item(d, &h); )
827 if ((int)h.report_ID > maxid)
828 maxid = h.report_ID;
829 hid_end_parse(d);
830
831 return (maxid);
832 }
833
834 static int
835 ihidev_print(void *aux, const char *pnp)
836 {
837 struct ihidev_attach_arg *iha = aux;
838
839 if (iha->reportid == IHIDEV_CLAIM_ALLREPORTID)
840 return (QUIET);
841
842 if (pnp)
843 aprint_normal("hid at %s", pnp);
844
845 if (iha->reportid != 0)
846 aprint_normal(" reportid %d", iha->reportid);
847
848 return (UNCONF);
849 }
850
851 static int
852 ihidev_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
853 {
854 struct ihidev_attach_arg *iha = aux;
855
856 if (cf->ihidevcf_reportid != IHIDEV_UNK_REPORTID &&
857 cf->ihidevcf_reportid != iha->reportid)
858 return (0);
859
860 return config_match(parent, cf, aux);
861 }
862
863 int
864 ihidev_open(struct ihidev *scd)
865 {
866 struct ihidev_softc *sc = scd->sc_parent;
867
868 DPRINTF(("%s: %s: state=%d refcnt=%d\n", sc->sc_dev.dv_xname,
869 __func__, scd->sc_state, sc->sc_refcnt));
870
871 if (scd->sc_state & IHIDEV_OPEN)
872 return (EBUSY);
873
874 scd->sc_state |= IHIDEV_OPEN;
875
876 if (sc->sc_refcnt++ || sc->sc_isize == 0)
877 return (0);
878
879 /* power on */
880 ihidev_reset(sc, false);
881
882 return (0);
883 }
884
885 void
886 ihidev_close(struct ihidev *scd)
887 {
888 struct ihidev_softc *sc = scd->sc_parent;
889
890 DPRINTF(("%s: %s: state=%d refcnt=%d\n", sc->sc_dev.dv_xname,
891 __func__, scd->sc_state, sc->sc_refcnt));
892
893 if (!(scd->sc_state & IHIDEV_OPEN))
894 return;
895
896 scd->sc_state &= ~IHIDEV_OPEN;
897
898 if (--sc->sc_refcnt)
899 return;
900
901 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_POWER,
902 &I2C_HID_POWER_OFF, false))
903 aprint_error_dev(sc->sc_dev, "failed to power down\n");
904 }
905
906 void
907 ihidev_get_report_desc(struct ihidev_softc *sc, void **desc, int *size)
908 {
909 *desc = sc->sc_report;
910 *size = sc->sc_reportlen;
911 }
912
913 /* convert hid_* constants used throughout HID code to i2c HID equivalents */
914 int
915 ihidev_report_type_conv(int hid_type_id)
916 {
917 switch (hid_type_id) {
918 case hid_input:
919 return I2C_HID_REPORT_TYPE_INPUT;
920 case hid_output:
921 return I2C_HID_REPORT_TYPE_OUTPUT;
922 case hid_feature:
923 return I2C_HID_REPORT_TYPE_FEATURE;
924 default:
925 return -1;
926 }
927 }
928
929 int
930 ihidev_get_report(struct device *dev, int type, int id, void *data, int len)
931 {
932 struct ihidev_softc *sc = (struct ihidev_softc *)dev;
933 struct i2c_hid_report_request rreq;
934 int ctype;
935
936 if ((ctype = ihidev_report_type_conv(type)) < 0)
937 return (1);
938
939 rreq.type = ctype;
940 rreq.id = id;
941 rreq.data = data;
942 rreq.len = len;
943
944 if (ihidev_hid_command(sc, I2C_HID_CMD_GET_REPORT, &rreq, false)) {
945 aprint_error_dev(sc->sc_dev, "failed fetching report\n");
946 return (1);
947 }
948
949 return 0;
950 }
951
952 int
953 ihidev_set_report(struct device *dev, int type, int id, void *data,
954 int len)
955 {
956 struct ihidev_softc *sc = (struct ihidev_softc *)dev;
957 struct i2c_hid_report_request rreq;
958 int ctype;
959
960 if ((ctype = ihidev_report_type_conv(type)) < 0)
961 return (1);
962
963 rreq.type = ctype;
964 rreq.id = id;
965 rreq.data = data;
966 rreq.len = len;
967
968 if (ihidev_hid_command(sc, I2C_HID_CMD_SET_REPORT, &rreq, false)) {
969 aprint_error_dev(sc->sc_dev, "failed setting report\n");
970 return (1);
971 }
972
973 return 0;
974 }
975
976 static bool
977 ihidev_acpi_get_info(struct ihidev_softc *sc)
978 {
979 ACPI_HANDLE hdl = devhandle_to_acpi(device_handle(sc->sc_dev));
980 ACPI_STATUS status;
981 ACPI_INTEGER val;
982
983 /* 3cdff6f7-4267-4555-ad05-b30a3d8938de */
984 uint8_t i2c_hid_guid[] = {
985 0xF7, 0xF6, 0xDF, 0x3C,
986 0x67, 0x42,
987 0x55, 0x45,
988 0xAD, 0x05,
989 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE,
990 };
991
992 status = acpi_dsm_integer(hdl, i2c_hid_guid, 1, 1, NULL, &val);
993 if (ACPI_FAILURE(status)) {
994 aprint_error_dev(sc->sc_dev,
995 "failed to get HidDescriptorAddress: %s\n",
996 AcpiFormatException(status));
997 return false;
998 }
999
1000 sc->sc_hid_desc_addr = (u_int)val;
1001
1002 return true;
1003 }
1004