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
ihidev_match(device_t parent,cfdata_t match,void * aux)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
ihidev_attach(device_t parent,device_t self,void * aux)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
ihidev_detach(device_t self,int flags)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
ihidev_suspend(device_t self,const pmf_qual_t * q)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
ihidev_resume(device_t self,const pmf_qual_t * q)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
ihidev_hid_command(struct ihidev_softc * sc,int hidcmd,void * arg,bool poll)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
ihidev_poweron(struct ihidev_softc * sc,bool poll)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
ihidev_reset(struct ihidev_softc * sc,bool poll)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
ihidev_hid_desc_parse(struct ihidev_softc * sc)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
ihidev_intr_init(struct ihidev_softc * sc)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
ihidev_intr_fini(struct ihidev_softc * sc)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
ihidev_intr_mask(struct ihidev_softc * const sc)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
ihidev_intr_unmask(struct ihidev_softc * const sc)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
ihidev_intr(void * arg)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
ihidev_work(struct work * wk,void * arg)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
ihidev_maxrepid(void * buf,int len)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
ihidev_print(void * aux,const char * pnp)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
ihidev_submatch(device_t parent,cfdata_t cf,const int * locs,void * aux)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
ihidev_open(struct ihidev * scd)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
ihidev_close(struct ihidev * scd)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
ihidev_get_report_desc(struct ihidev_softc * sc,void ** desc,int * size)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
ihidev_report_type_conv(int hid_type_id)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
ihidev_get_report(struct device * dev,int type,int id,void * data,int len)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
ihidev_set_report(struct device * dev,int type,int id,void * data,int len)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
ihidev_acpi_get_info(struct ihidev_softc * sc)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