FreeBSD/Linux Kernel Cross Reference
sys/dev/hid/hidbus.c
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2019-2020 Vladimir Kondratyev <wulf@FreeBSD.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/param.h>
32 #include <sys/bus.h>
33 #include <sys/ck.h>
34 #include <sys/epoch.h>
35 #include <sys/kdb.h>
36 #include <sys/kernel.h>
37 #include <sys/libkern.h>
38 #include <sys/lock.h>
39 #include <sys/malloc.h>
40 #include <sys/module.h>
41 #include <sys/mutex.h>
42 #include <sys/proc.h>
43 #include <sys/systm.h>
44 #include <sys/sx.h>
45
46 #define HID_DEBUG_VAR hid_debug
47 #include <dev/hid/hid.h>
48 #include <dev/hid/hidbus.h>
49 #include <dev/hid/hidquirk.h>
50
51 #include "hid_if.h"
52
53 #define INPUT_EPOCH global_epoch_preempt
54 #define HID_RSIZE_MAX 1024
55
56 static hid_intr_t hidbus_intr;
57
58 static device_probe_t hidbus_probe;
59 static device_attach_t hidbus_attach;
60 static device_detach_t hidbus_detach;
61
62 struct hidbus_ivars {
63 int32_t usage;
64 uint8_t index;
65 uint32_t flags;
66 uintptr_t driver_info; /* for internal use */
67 struct mtx *mtx; /* child intr mtx */
68 hid_intr_t *intr_handler; /* executed under mtx*/
69 void *intr_ctx;
70 unsigned int refcnt; /* protected by mtx */
71 struct epoch_context epoch_ctx;
72 CK_STAILQ_ENTRY(hidbus_ivars) link;
73 };
74
75 struct hidbus_softc {
76 device_t dev;
77 struct sx sx;
78 struct mtx mtx;
79
80 bool nowrite;
81
82 struct hid_rdesc_info rdesc;
83 bool overloaded;
84 int nest; /* Child attach nesting lvl */
85 int nauto; /* Number of autochildren */
86
87 CK_STAILQ_HEAD(, hidbus_ivars) tlcs;
88 };
89
90 static int
91 hidbus_fill_rdesc_info(struct hid_rdesc_info *hri, const void *data,
92 hid_size_t len)
93 {
94 int error = 0;
95
96 hri->data = __DECONST(void *, data);
97 hri->len = len;
98
99 /*
100 * If report descriptor is not available yet, set maximal
101 * report sizes high enough to allow hidraw to work.
102 */
103 hri->isize = len == 0 ? HID_RSIZE_MAX :
104 hid_report_size_max(data, len, hid_input, &hri->iid);
105 hri->osize = len == 0 ? HID_RSIZE_MAX :
106 hid_report_size_max(data, len, hid_output, &hri->oid);
107 hri->fsize = len == 0 ? HID_RSIZE_MAX :
108 hid_report_size_max(data, len, hid_feature, &hri->fid);
109
110 if (hri->isize > HID_RSIZE_MAX) {
111 DPRINTF("input size is too large, %u bytes (truncating)\n",
112 hri->isize);
113 hri->isize = HID_RSIZE_MAX;
114 error = EOVERFLOW;
115 }
116 if (hri->osize > HID_RSIZE_MAX) {
117 DPRINTF("output size is too large, %u bytes (truncating)\n",
118 hri->osize);
119 hri->osize = HID_RSIZE_MAX;
120 error = EOVERFLOW;
121 }
122 if (hri->fsize > HID_RSIZE_MAX) {
123 DPRINTF("feature size is too large, %u bytes (truncating)\n",
124 hri->fsize);
125 hri->fsize = HID_RSIZE_MAX;
126 error = EOVERFLOW;
127 }
128
129 return (error);
130 }
131
132 int
133 hidbus_locate(const void *desc, hid_size_t size, int32_t u, enum hid_kind k,
134 uint8_t tlc_index, uint8_t index, struct hid_location *loc,
135 uint32_t *flags, uint8_t *id, struct hid_absinfo *ai)
136 {
137 struct hid_data *d;
138 struct hid_item h;
139 int i;
140
141 d = hid_start_parse(desc, size, 1 << k);
142 HIDBUS_FOREACH_ITEM(d, &h, tlc_index) {
143 for (i = 0; i < h.nusages; i++) {
144 if (h.kind == k && h.usages[i] == u) {
145 if (index--)
146 break;
147 if (loc != NULL)
148 *loc = h.loc;
149 if (flags != NULL)
150 *flags = h.flags;
151 if (id != NULL)
152 *id = h.report_ID;
153 if (ai != NULL && (h.flags&HIO_RELATIVE) == 0)
154 *ai = (struct hid_absinfo) {
155 .max = h.logical_maximum,
156 .min = h.logical_minimum,
157 .res = hid_item_resolution(&h),
158 };
159 hid_end_parse(d);
160 return (1);
161 }
162 }
163 }
164 if (loc != NULL)
165 loc->size = 0;
166 if (flags != NULL)
167 *flags = 0;
168 if (id != NULL)
169 *id = 0;
170 hid_end_parse(d);
171 return (0);
172 }
173
174 bool
175 hidbus_is_collection(const void *desc, hid_size_t size, int32_t usage,
176 uint8_t tlc_index)
177 {
178 struct hid_data *d;
179 struct hid_item h;
180 bool ret = false;
181
182 d = hid_start_parse(desc, size, 0);
183 HIDBUS_FOREACH_ITEM(d, &h, tlc_index) {
184 if (h.kind == hid_collection && h.usage == usage) {
185 ret = true;
186 break;
187 }
188 }
189 hid_end_parse(d);
190 return (ret);
191 }
192
193 static device_t
194 hidbus_add_child(device_t dev, u_int order, const char *name, int unit)
195 {
196 struct hidbus_softc *sc = device_get_softc(dev);
197 struct hidbus_ivars *tlc;
198 device_t child;
199
200 child = device_add_child_ordered(dev, order, name, unit);
201 if (child == NULL)
202 return (child);
203
204 tlc = malloc(sizeof(struct hidbus_ivars), M_DEVBUF, M_WAITOK | M_ZERO);
205 tlc->mtx = &sc->mtx;
206 device_set_ivars(child, tlc);
207 sx_xlock(&sc->sx);
208 CK_STAILQ_INSERT_TAIL(&sc->tlcs, tlc, link);
209 sx_unlock(&sc->sx);
210
211 return (child);
212 }
213
214 static int
215 hidbus_enumerate_children(device_t dev, const void* data, hid_size_t len)
216 {
217 struct hidbus_softc *sc = device_get_softc(dev);
218 struct hid_data *hd;
219 struct hid_item hi;
220 device_t child;
221 uint8_t index = 0;
222
223 if (data == NULL || len == 0)
224 return (ENXIO);
225
226 /* Add a child for each top level collection */
227 hd = hid_start_parse(data, len, 1 << hid_input);
228 while (hid_get_item(hd, &hi)) {
229 if (hi.kind != hid_collection || hi.collevel != 1)
230 continue;
231 child = BUS_ADD_CHILD(dev, 0, NULL, -1);
232 if (child == NULL) {
233 device_printf(dev, "Could not add HID device\n");
234 continue;
235 }
236 hidbus_set_index(child, index);
237 hidbus_set_usage(child, hi.usage);
238 hidbus_set_flags(child, HIDBUS_FLAG_AUTOCHILD);
239 index++;
240 DPRINTF("Add child TLC: 0x%04x:0x%04x\n",
241 HID_GET_USAGE_PAGE(hi.usage), HID_GET_USAGE(hi.usage));
242 }
243 hid_end_parse(hd);
244
245 if (index == 0)
246 return (ENXIO);
247
248 sc->nauto = index;
249
250 return (0);
251 }
252
253 static int
254 hidbus_attach_children(device_t dev)
255 {
256 struct hidbus_softc *sc = device_get_softc(dev);
257 int error;
258
259 HID_INTR_SETUP(device_get_parent(dev), hidbus_intr, sc, &sc->rdesc);
260
261 error = hidbus_enumerate_children(dev, sc->rdesc.data, sc->rdesc.len);
262 if (error != 0)
263 DPRINTF("failed to enumerate children: error %d\n", error);
264
265 /*
266 * hidbus_attach_children() can recurse through device_identify->
267 * hid_set_report_descr() call sequence. Do not perform children
268 * attach twice in that case.
269 */
270 sc->nest++;
271 bus_generic_probe(dev);
272 sc->nest--;
273 if (sc->nest != 0)
274 return (0);
275
276 if (hid_is_keyboard(sc->rdesc.data, sc->rdesc.len) != 0)
277 error = bus_generic_attach(dev);
278 else
279 error = bus_delayed_attach_children(dev);
280 if (error != 0)
281 device_printf(dev, "failed to attach child: error %d\n", error);
282
283 return (error);
284 }
285
286 static int
287 hidbus_detach_children(device_t dev)
288 {
289 device_t *children, bus;
290 bool is_bus;
291 int i, error;
292
293 error = 0;
294
295 is_bus = device_get_devclass(dev) == hidbus_devclass;
296 bus = is_bus ? dev : device_get_parent(dev);
297
298 KASSERT(device_get_devclass(bus) == hidbus_devclass,
299 ("Device is not hidbus or it's child"));
300
301 if (is_bus) {
302 /* If hidbus is passed, delete all children. */
303 bus_generic_detach(bus);
304 device_delete_children(bus);
305 } else {
306 /*
307 * If hidbus child is passed, delete all hidbus children
308 * except caller. Deleting the caller may result in deadlock.
309 */
310 error = device_get_children(bus, &children, &i);
311 if (error != 0)
312 return (error);
313 while (i-- > 0) {
314 if (children[i] == dev)
315 continue;
316 DPRINTF("Delete child. index=%d (%s)\n",
317 hidbus_get_index(children[i]),
318 device_get_nameunit(children[i]));
319 error = device_delete_child(bus, children[i]);
320 if (error) {
321 DPRINTF("Failed deleting %s\n",
322 device_get_nameunit(children[i]));
323 break;
324 }
325 }
326 free(children, M_TEMP);
327 }
328
329 HID_INTR_UNSETUP(device_get_parent(bus));
330
331 return (error);
332 }
333
334 static int
335 hidbus_probe(device_t dev)
336 {
337
338 device_set_desc(dev, "HID bus");
339
340 /* Allow other subclasses to override this driver. */
341 return (BUS_PROBE_GENERIC);
342 }
343
344 static int
345 hidbus_attach(device_t dev)
346 {
347 struct hidbus_softc *sc = device_get_softc(dev);
348 struct hid_device_info *devinfo = device_get_ivars(dev);
349 void *d_ptr = NULL;
350 hid_size_t d_len;
351 int error;
352
353 sc->dev = dev;
354 CK_STAILQ_INIT(&sc->tlcs);
355 mtx_init(&sc->mtx, "hidbus ivar lock", NULL, MTX_DEF);
356 sx_init(&sc->sx, "hidbus ivar list lock");
357
358 /*
359 * Ignore error. It is possible for non-HID device e.g. XBox360 gamepad
360 * to emulate HID through overloading of report descriptor.
361 */
362 d_len = devinfo->rdescsize;
363 if (d_len != 0) {
364 d_ptr = malloc(d_len, M_DEVBUF, M_ZERO | M_WAITOK);
365 error = hid_get_rdesc(dev, d_ptr, d_len);
366 if (error != 0) {
367 free(d_ptr, M_DEVBUF);
368 d_len = 0;
369 d_ptr = NULL;
370 }
371 }
372
373 hidbus_fill_rdesc_info(&sc->rdesc, d_ptr, d_len);
374
375 sc->nowrite = hid_test_quirk(devinfo, HQ_NOWRITE);
376
377 error = hidbus_attach_children(dev);
378 if (error != 0) {
379 hidbus_detach(dev);
380 return (ENXIO);
381 }
382
383 return (0);
384 }
385
386 static int
387 hidbus_detach(device_t dev)
388 {
389 struct hidbus_softc *sc = device_get_softc(dev);
390
391 hidbus_detach_children(dev);
392 sx_destroy(&sc->sx);
393 mtx_destroy(&sc->mtx);
394 free(sc->rdesc.data, M_DEVBUF);
395
396 return (0);
397 }
398
399 static void
400 hidbus_child_detached(device_t bus, device_t child)
401 {
402 struct hidbus_softc *sc = device_get_softc(bus);
403 struct hidbus_ivars *tlc = device_get_ivars(child);
404
405 KASSERT(tlc->refcnt == 0, ("Child device is running"));
406 tlc->mtx = &sc->mtx;
407 tlc->intr_handler = NULL;
408 tlc->flags &= ~HIDBUS_FLAG_CAN_POLL;
409 }
410
411 /*
412 * Epoch callback indicating tlc is safe to destroy
413 */
414 static void
415 hidbus_ivar_dtor(epoch_context_t ctx)
416 {
417 struct hidbus_ivars *tlc;
418
419 tlc = __containerof(ctx, struct hidbus_ivars, epoch_ctx);
420 free(tlc, M_DEVBUF);
421 }
422
423 static void
424 hidbus_child_deleted(device_t bus, device_t child)
425 {
426 struct hidbus_softc *sc = device_get_softc(bus);
427 struct hidbus_ivars *tlc = device_get_ivars(child);
428
429 sx_xlock(&sc->sx);
430 KASSERT(tlc->refcnt == 0, ("Child device is running"));
431 CK_STAILQ_REMOVE(&sc->tlcs, tlc, hidbus_ivars, link);
432 sx_unlock(&sc->sx);
433 epoch_call(INPUT_EPOCH, hidbus_ivar_dtor, &tlc->epoch_ctx);
434 }
435
436 static int
437 hidbus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
438 {
439 struct hidbus_softc *sc = device_get_softc(bus);
440 struct hidbus_ivars *tlc = device_get_ivars(child);
441
442 switch (which) {
443 case HIDBUS_IVAR_INDEX:
444 *result = tlc->index;
445 break;
446 case HIDBUS_IVAR_USAGE:
447 *result = tlc->usage;
448 break;
449 case HIDBUS_IVAR_FLAGS:
450 *result = tlc->flags;
451 break;
452 case HIDBUS_IVAR_DRIVER_INFO:
453 *result = tlc->driver_info;
454 break;
455 case HIDBUS_IVAR_LOCK:
456 *result = (uintptr_t)(tlc->mtx == &sc->mtx ? NULL : tlc->mtx);
457 break;
458 default:
459 return (EINVAL);
460 }
461 return (0);
462 }
463
464 static int
465 hidbus_write_ivar(device_t bus, device_t child, int which, uintptr_t value)
466 {
467 struct hidbus_softc *sc = device_get_softc(bus);
468 struct hidbus_ivars *tlc = device_get_ivars(child);
469
470 switch (which) {
471 case HIDBUS_IVAR_INDEX:
472 tlc->index = value;
473 break;
474 case HIDBUS_IVAR_USAGE:
475 tlc->usage = value;
476 break;
477 case HIDBUS_IVAR_FLAGS:
478 tlc->flags = value;
479 if ((value & HIDBUS_FLAG_CAN_POLL) != 0)
480 HID_INTR_SETUP(
481 device_get_parent(bus), NULL, NULL, NULL);
482 break;
483 case HIDBUS_IVAR_DRIVER_INFO:
484 tlc->driver_info = value;
485 break;
486 case HIDBUS_IVAR_LOCK:
487 tlc->mtx = (struct mtx *)value == NULL ?
488 &sc->mtx : (struct mtx *)value;
489 break;
490 default:
491 return (EINVAL);
492 }
493 return (0);
494 }
495
496 /* Location hint for devctl(8) */
497 static int
498 hidbus_child_location_str(device_t bus, device_t child, char *buf,
499 size_t buflen)
500 {
501 struct hidbus_ivars *tlc = device_get_ivars(child);
502
503 snprintf(buf, buflen, "index=%hhu", tlc->index);
504 return (0);
505 }
506
507 /* PnP information for devctl(8) */
508 static int
509 hidbus_child_pnpinfo_str(device_t bus, device_t child, char *buf,
510 size_t buflen)
511 {
512 struct hidbus_ivars *tlc = device_get_ivars(child);
513 struct hid_device_info *devinfo = device_get_ivars(bus);
514
515 snprintf(buf, buflen, "page=0x%04x usage=0x%04x bus=0x%02hx "
516 "vendor=0x%04hx product=0x%04hx version=0x%04hx%s%s",
517 HID_GET_USAGE_PAGE(tlc->usage), HID_GET_USAGE(tlc->usage),
518 devinfo->idBus, devinfo->idVendor, devinfo->idProduct,
519 devinfo->idVersion, devinfo->idPnP[0] == '\0' ? "" : " _HID=",
520 devinfo->idPnP[0] == '\0' ? "" : devinfo->idPnP);
521 return (0);
522 }
523
524 void
525 hidbus_set_desc(device_t child, const char *suffix)
526 {
527 device_t bus = device_get_parent(child);
528 struct hidbus_softc *sc = device_get_softc(bus);
529 struct hid_device_info *devinfo = device_get_ivars(bus);
530 struct hidbus_ivars *tlc = device_get_ivars(child);
531 char buf[80];
532
533 /* Do not add NULL suffix or if device name already contains it. */
534 if (suffix != NULL && strcasestr(devinfo->name, suffix) == NULL &&
535 (sc->nauto > 1 || (tlc->flags & HIDBUS_FLAG_AUTOCHILD) == 0)) {
536 snprintf(buf, sizeof(buf), "%s %s", devinfo->name, suffix);
537 device_set_desc_copy(child, buf);
538 } else
539 device_set_desc(child, devinfo->name);
540 }
541
542 device_t
543 hidbus_find_child(device_t bus, int32_t usage)
544 {
545 device_t *children, child;
546 int ccount, i;
547
548 GIANT_REQUIRED;
549
550 /* Get a list of all hidbus children */
551 if (device_get_children(bus, &children, &ccount) != 0)
552 return (NULL);
553
554 /* Scan through to find required TLC */
555 for (i = 0, child = NULL; i < ccount; i++) {
556 if (hidbus_get_usage(children[i]) == usage) {
557 child = children[i];
558 break;
559 }
560 }
561 free(children, M_TEMP);
562
563 return (child);
564 }
565
566 void
567 hidbus_intr(void *context, void *buf, hid_size_t len)
568 {
569 struct hidbus_softc *sc = context;
570 struct hidbus_ivars *tlc;
571 struct epoch_tracker et;
572
573 /*
574 * Broadcast input report to all subscribers.
575 * TODO: Add check for input report ID.
576 *
577 * Relock mutex on every TLC item as we can't hold any locks over whole
578 * TLC list here due to LOR with open()/close() handlers.
579 */
580 if (!HID_IN_POLLING_MODE())
581 epoch_enter_preempt(INPUT_EPOCH, &et);
582 CK_STAILQ_FOREACH(tlc, &sc->tlcs, link) {
583 if (tlc->refcnt == 0 || tlc->intr_handler == NULL)
584 continue;
585 if (HID_IN_POLLING_MODE()) {
586 if ((tlc->flags & HIDBUS_FLAG_CAN_POLL) != 0)
587 tlc->intr_handler(tlc->intr_ctx, buf, len);
588 } else {
589 mtx_lock(tlc->mtx);
590 tlc->intr_handler(tlc->intr_ctx, buf, len);
591 mtx_unlock(tlc->mtx);
592 }
593 }
594 if (!HID_IN_POLLING_MODE())
595 epoch_exit_preempt(INPUT_EPOCH, &et);
596 }
597
598 void
599 hidbus_set_intr(device_t child, hid_intr_t *handler, void *context)
600 {
601 struct hidbus_ivars *tlc = device_get_ivars(child);
602
603 tlc->intr_handler = handler;
604 tlc->intr_ctx = context;
605 }
606
607 int
608 hidbus_intr_start(device_t child)
609 {
610 device_t bus = device_get_parent(child);
611 struct hidbus_softc *sc = device_get_softc(bus);
612 struct hidbus_ivars *ivar = device_get_ivars(child);
613 struct hidbus_ivars *tlc;
614 int refcnt = 0;
615 int error;
616
617 if (sx_xlock_sig(&sc->sx) != 0)
618 return (EINTR);
619 CK_STAILQ_FOREACH(tlc, &sc->tlcs, link) {
620 refcnt += tlc->refcnt;
621 if (tlc == ivar) {
622 mtx_lock(tlc->mtx);
623 ++tlc->refcnt;
624 mtx_unlock(tlc->mtx);
625 }
626 }
627 error = refcnt != 0 ? 0 : HID_INTR_START(device_get_parent(bus));
628 sx_unlock(&sc->sx);
629
630 return (error);
631 }
632
633 int
634 hidbus_intr_stop(device_t child)
635 {
636 device_t bus = device_get_parent(child);
637 struct hidbus_softc *sc = device_get_softc(bus);
638 struct hidbus_ivars *ivar = device_get_ivars(child);
639 struct hidbus_ivars *tlc;
640 bool refcnt = 0;
641 int error;
642
643 if (sx_xlock_sig(&sc->sx) != 0)
644 return (EINTR);
645 CK_STAILQ_FOREACH(tlc, &sc->tlcs, link) {
646 if (tlc == ivar) {
647 mtx_lock(tlc->mtx);
648 MPASS(tlc->refcnt != 0);
649 --tlc->refcnt;
650 mtx_unlock(tlc->mtx);
651 }
652 refcnt += tlc->refcnt;
653 }
654 error = refcnt != 0 ? 0 : HID_INTR_STOP(device_get_parent(bus));
655 sx_unlock(&sc->sx);
656
657 return (error);
658 }
659
660 void
661 hidbus_intr_poll(device_t child)
662 {
663 device_t bus = device_get_parent(child);
664
665 HID_INTR_POLL(device_get_parent(bus));
666 }
667
668 struct hid_rdesc_info *
669 hidbus_get_rdesc_info(device_t child)
670 {
671 device_t bus = device_get_parent(child);
672 struct hidbus_softc *sc = device_get_softc(bus);
673
674 return (&sc->rdesc);
675 }
676
677 /*
678 * HID interface.
679 *
680 * Hidbus as well as any hidbus child can be passed as first arg.
681 */
682
683 /* Read cached report descriptor */
684 int
685 hid_get_report_descr(device_t dev, void **data, hid_size_t *len)
686 {
687 device_t bus;
688 struct hidbus_softc *sc;
689
690 bus = device_get_devclass(dev) == hidbus_devclass ?
691 dev : device_get_parent(dev);
692 sc = device_get_softc(bus);
693
694 /*
695 * Do not send request to a transport backend.
696 * Use cached report descriptor instead of it.
697 */
698 if (sc->rdesc.data == NULL || sc->rdesc.len == 0)
699 return (ENXIO);
700
701 if (data != NULL)
702 *data = sc->rdesc.data;
703 if (len != NULL)
704 *len = sc->rdesc.len;
705
706 return (0);
707 }
708
709 /*
710 * Replace cached report descriptor with top level driver provided one.
711 *
712 * It deletes all hidbus children except caller and enumerates them again after
713 * new descriptor has been registered. Currently it can not be called from
714 * autoenumerated (by report's TLC) child device context as it results in child
715 * duplication. To overcome this limitation hid_set_report_descr() should be
716 * called from device_identify driver's handler with hidbus itself passed as
717 * 'device_t dev' parameter.
718 */
719 int
720 hid_set_report_descr(device_t dev, const void *data, hid_size_t len)
721 {
722 struct hid_rdesc_info rdesc;
723 device_t bus;
724 struct hidbus_softc *sc;
725 bool is_bus;
726 int error;
727
728 GIANT_REQUIRED;
729
730 is_bus = device_get_devclass(dev) == hidbus_devclass;
731 bus = is_bus ? dev : device_get_parent(dev);
732 sc = device_get_softc(bus);
733
734 /*
735 * Do not overload already overloaded report descriptor in
736 * device_identify handler. It causes infinite recursion loop.
737 */
738 if (is_bus && sc->overloaded)
739 return(0);
740
741 DPRINTFN(5, "len=%d\n", len);
742 DPRINTFN(5, "data = %*D\n", len, data, " ");
743
744 error = hidbus_fill_rdesc_info(&rdesc, data, len);
745 if (error != 0)
746 return (error);
747
748 error = hidbus_detach_children(dev);
749 if (error != 0)
750 return(error);
751
752 /* Make private copy to handle a case of dynamicaly allocated data. */
753 rdesc.data = malloc(len, M_DEVBUF, M_ZERO | M_WAITOK);
754 bcopy(data, rdesc.data, len);
755 sc->overloaded = true;
756 free(sc->rdesc.data, M_DEVBUF);
757 bcopy(&rdesc, &sc->rdesc, sizeof(struct hid_rdesc_info));
758
759 error = hidbus_attach_children(bus);
760
761 return (error);
762 }
763
764 static int
765 hidbus_write(device_t dev, const void *data, hid_size_t len)
766 {
767 struct hidbus_softc *sc;
768 uint8_t id;
769
770 sc = device_get_softc(dev);
771 /*
772 * Output interrupt endpoint is often optional. If HID device
773 * does not provide it, send reports via control pipe.
774 */
775 if (sc->nowrite) {
776 /* try to extract the ID byte */
777 id = (sc->rdesc.oid & (len > 0)) ? *(const uint8_t*)data : 0;
778 return (hid_set_report(dev, data, len, HID_OUTPUT_REPORT, id));
779 }
780
781 return (hid_write(dev, data, len));
782 }
783
784 /*------------------------------------------------------------------------*
785 * hidbus_lookup_id
786 *
787 * This functions takes an array of "struct hid_device_id" and tries
788 * to match the entries with the information in "struct hid_device_info".
789 *
790 * Return values:
791 * NULL: No match found.
792 * Else: Pointer to matching entry.
793 *------------------------------------------------------------------------*/
794 const struct hid_device_id *
795 hidbus_lookup_id(device_t dev, const struct hid_device_id *id, int nitems_id)
796 {
797 const struct hid_device_id *id_end;
798 const struct hid_device_info *info;
799 int32_t usage;
800 bool is_child;
801
802 if (id == NULL) {
803 goto done;
804 }
805
806 id_end = id + nitems_id;
807 info = hid_get_device_info(dev);
808 is_child = device_get_devclass(dev) != hidbus_devclass;
809 if (is_child)
810 usage = hidbus_get_usage(dev);
811
812 /*
813 * Keep on matching array entries until we find a match or
814 * until we reach the end of the matching array:
815 */
816 for (; id != id_end; id++) {
817
818 if (is_child && (id->match_flag_page) &&
819 (id->page != HID_GET_USAGE_PAGE(usage))) {
820 continue;
821 }
822 if (is_child && (id->match_flag_usage) &&
823 (id->usage != HID_GET_USAGE(usage))) {
824 continue;
825 }
826 if ((id->match_flag_bus) &&
827 (id->idBus != info->idBus)) {
828 continue;
829 }
830 if ((id->match_flag_vendor) &&
831 (id->idVendor != info->idVendor)) {
832 continue;
833 }
834 if ((id->match_flag_product) &&
835 (id->idProduct != info->idProduct)) {
836 continue;
837 }
838 if ((id->match_flag_ver_lo) &&
839 (id->idVersion_lo > info->idVersion)) {
840 continue;
841 }
842 if ((id->match_flag_ver_hi) &&
843 (id->idVersion_hi < info->idVersion)) {
844 continue;
845 }
846 if (id->match_flag_pnp &&
847 strncmp(id->idPnP, info->idPnP, HID_PNP_ID_SIZE) != 0) {
848 continue;
849 }
850 /* We found a match! */
851 return (id);
852 }
853
854 done:
855 return (NULL);
856 }
857
858 /*------------------------------------------------------------------------*
859 * hidbus_lookup_driver_info - factored out code
860 *
861 * Return values:
862 * 0: Success
863 * Else: Failure
864 *------------------------------------------------------------------------*/
865 int
866 hidbus_lookup_driver_info(device_t child, const struct hid_device_id *id,
867 int nitems_id)
868 {
869
870 id = hidbus_lookup_id(child, id, nitems_id);
871 if (id) {
872 /* copy driver info */
873 hidbus_set_driver_info(child, id->driver_info);
874 return (0);
875 }
876 return (ENXIO);
877 }
878
879 const struct hid_device_info *
880 hid_get_device_info(device_t dev)
881 {
882 device_t bus;
883
884 bus = device_get_devclass(dev) == hidbus_devclass ?
885 dev : device_get_parent(dev);
886
887 return (device_get_ivars(bus));
888 }
889
890 static device_method_t hidbus_methods[] = {
891 /* device interface */
892 DEVMETHOD(device_probe, hidbus_probe),
893 DEVMETHOD(device_attach, hidbus_attach),
894 DEVMETHOD(device_detach, hidbus_detach),
895 DEVMETHOD(device_suspend, bus_generic_suspend),
896 DEVMETHOD(device_resume, bus_generic_resume),
897
898 /* bus interface */
899 DEVMETHOD(bus_add_child, hidbus_add_child),
900 DEVMETHOD(bus_child_detached, hidbus_child_detached),
901 DEVMETHOD(bus_child_deleted, hidbus_child_deleted),
902 DEVMETHOD(bus_read_ivar, hidbus_read_ivar),
903 DEVMETHOD(bus_write_ivar, hidbus_write_ivar),
904 DEVMETHOD(bus_child_pnpinfo_str,hidbus_child_pnpinfo_str),
905 DEVMETHOD(bus_child_location_str,hidbus_child_location_str),
906
907 /* hid interface */
908 DEVMETHOD(hid_get_rdesc, hid_get_rdesc),
909 DEVMETHOD(hid_read, hid_read),
910 DEVMETHOD(hid_write, hidbus_write),
911 DEVMETHOD(hid_get_report, hid_get_report),
912 DEVMETHOD(hid_set_report, hid_set_report),
913 DEVMETHOD(hid_set_idle, hid_set_idle),
914 DEVMETHOD(hid_set_protocol, hid_set_protocol),
915
916 DEVMETHOD_END
917 };
918
919 devclass_t hidbus_devclass;
920 driver_t hidbus_driver = {
921 "hidbus",
922 hidbus_methods,
923 sizeof(struct hidbus_softc),
924 };
925
926 MODULE_DEPEND(hidbus, hid, 1, 1, 1);
927 MODULE_VERSION(hidbus, 1);
928 DRIVER_MODULE(hidbus, iichid, hidbus_driver, hidbus_devclass, 0, 0);
929 DRIVER_MODULE(hidbus, usbhid, hidbus_driver, hidbus_devclass, 0, 0);
Cache object: c6476f49b818b3f784f0e155f1b4eef3
|