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