| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: uhidev.c,v 1.91 2022/03/28 12:44:28 riastradh Exp $ */ | | 1 | /* $NetBSD: uhidev.c,v 1.92 2022/03/28 12:44:37 riastradh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Lennart Augustsson (lennart@augustsson.net) at | | 8 | * by Lennart Augustsson (lennart@augustsson.net) at |
9 | * Carlstedt Research & Technology and Matthew R. Green (mrg@eterna.com.au). | | 9 | * Carlstedt Research & Technology and Matthew R. Green (mrg@eterna.com.au). |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
| @@ -25,27 +25,27 @@ | | | @@ -25,27 +25,27 @@ |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 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 | | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 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 | | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
30 | * POSSIBILITY OF SUCH DAMAGE. | | 30 | * POSSIBILITY OF SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | /* | | 33 | /* |
34 | * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf | | 34 | * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf |
35 | */ | | 35 | */ |
36 | | | 36 | |
37 | #include <sys/cdefs.h> | | 37 | #include <sys/cdefs.h> |
38 | __KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.91 2022/03/28 12:44:28 riastradh Exp $"); | | 38 | __KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.92 2022/03/28 12:44:37 riastradh Exp $"); |
39 | | | 39 | |
40 | #ifdef _KERNEL_OPT | | 40 | #ifdef _KERNEL_OPT |
41 | #include "opt_usb.h" | | 41 | #include "opt_usb.h" |
42 | #endif | | 42 | #endif |
43 | | | 43 | |
44 | #include <sys/param.h> | | 44 | #include <sys/param.h> |
45 | #include <sys/types.h> | | 45 | #include <sys/types.h> |
46 | | | 46 | |
47 | #include <sys/atomic.h> | | 47 | #include <sys/atomic.h> |
48 | #include <sys/conf.h> | | 48 | #include <sys/conf.h> |
49 | #include <sys/device.h> | | 49 | #include <sys/device.h> |
50 | #include <sys/ioctl.h> | | 50 | #include <sys/ioctl.h> |
51 | #include <sys/kernel.h> | | 51 | #include <sys/kernel.h> |
| @@ -448,27 +448,27 @@ uhidev_attach(device_t parent, device_t | | | @@ -448,27 +448,27 @@ uhidev_attach(device_t parent, device_t |
448 | static int | | 448 | static int |
449 | uhidev_maxrepid(void *buf, int len) | | 449 | uhidev_maxrepid(void *buf, int len) |
450 | { | | 450 | { |
451 | struct hid_data *d; | | 451 | struct hid_data *d; |
452 | struct hid_item h; | | 452 | struct hid_item h; |
453 | int maxid; | | 453 | int maxid; |
454 | | | 454 | |
455 | maxid = -1; | | 455 | maxid = -1; |
456 | h.report_ID = 0; | | 456 | h.report_ID = 0; |
457 | for (d = hid_start_parse(buf, len, hid_none); hid_get_item(d, &h); ) | | 457 | for (d = hid_start_parse(buf, len, hid_none); hid_get_item(d, &h); ) |
458 | if ((int)h.report_ID > maxid) | | 458 | if ((int)h.report_ID > maxid) |
459 | maxid = h.report_ID; | | 459 | maxid = h.report_ID; |
460 | hid_end_parse(d); | | 460 | hid_end_parse(d); |
461 | return maxid; | | 461 | return MIN(maxid, UHIDEV_MAXREPID); |
462 | } | | 462 | } |
463 | | | 463 | |
464 | static int | | 464 | static int |
465 | uhidevprint(void *aux, const char *pnp) | | 465 | uhidevprint(void *aux, const char *pnp) |
466 | { | | 466 | { |
467 | struct uhidev_attach_arg *uha = aux; | | 467 | struct uhidev_attach_arg *uha = aux; |
468 | | | 468 | |
469 | if (pnp) | | 469 | if (pnp) |
470 | aprint_normal("uhid at %s", pnp); | | 470 | aprint_normal("uhid at %s", pnp); |
471 | if (uha->reportid != 0) | | 471 | if (uha->reportid != 0) |
472 | aprint_normal(" reportid %d", uha->reportid); | | 472 | aprint_normal(" reportid %d", uha->reportid); |
473 | return UNCONF; | | 473 | return UNCONF; |
474 | } | | 474 | } |
| @@ -661,61 +661,58 @@ uhidev_config_exit(struct uhidev_softc * | | | @@ -661,61 +661,58 @@ uhidev_config_exit(struct uhidev_softc * |
661 | * Ensure the pipes of the softc are open. Caller must hold | | 661 | * Ensure the pipes of the softc are open. Caller must hold |
662 | * sc_lock, which may be released and reacquired. | | 662 | * sc_lock, which may be released and reacquired. |
663 | */ | | 663 | */ |
664 | static int | | 664 | static int |
665 | uhidev_open_pipes(struct uhidev_softc *sc) | | 665 | uhidev_open_pipes(struct uhidev_softc *sc) |
666 | { | | 666 | { |
667 | usbd_status err; | | 667 | usbd_status err; |
668 | int error; | | 668 | int error; |
669 | | | 669 | |
670 | KASSERT(mutex_owned(&sc->sc_lock)); | | 670 | KASSERT(mutex_owned(&sc->sc_lock)); |
671 | | | 671 | |
672 | /* | | 672 | /* |
673 | * If the pipes are already open, just increment the reference | | 673 | * If the pipes are already open, just increment the reference |
674 | * count, or fail if it would overflow. | | 674 | * count. The reference count is limited by the number of |
| | | 675 | * report ids, so this can't overflow. |
675 | */ | | 676 | */ |
676 | if (sc->sc_refcnt) { | | 677 | if (sc->sc_refcnt) { |
677 | if (sc->sc_refcnt == INT_MAX) | | 678 | KASSERT(sc->sc_refcnt < UHIDEV_MAXREPID); |
678 | return EBUSY; | | | |
679 | sc->sc_refcnt++; | | 679 | sc->sc_refcnt++; |
680 | return 0; | | 680 | return 0; |
681 | } | | 681 | } |
682 | | | 682 | |
683 | /* | | 683 | /* |
684 | * If there's no input data to prepare, don't bother with the | | 684 | * If there's no input data to prepare, don't bother with the |
685 | * pipes. We assume any device that does output also does | | 685 | * pipes. We assume any device that does output also does |
686 | * input; if you have a device where this is wrong, then | | 686 | * input; if you have a device where this is wrong, then |
687 | * uhidev_write will fail gracefully (it checks sc->sc_opipe), | | 687 | * uhidev_write will fail gracefully (it checks sc->sc_opipe), |
688 | * and you can use that device to test the changes needed to | | 688 | * and you can use that device to test the changes needed to |
689 | * open the output pipe here. | | 689 | * open the output pipe here. |
690 | */ | | 690 | */ |
691 | if (sc->sc_isize == 0) | | 691 | if (sc->sc_isize == 0) |
692 | return 0; | | 692 | return 0; |
693 | | | 693 | |
694 | /* | | 694 | /* |
695 | * Lock the configuration and release sc_lock -- we may sleep | | 695 | * Lock the configuration and release sc_lock -- we may sleep |
696 | * to allocate. If someone else got in first, we're done; | | 696 | * to allocate. If someone else got in first, we're done; |
697 | * otherwise open the pipes. | | 697 | * otherwise open the pipes. |
698 | */ | | 698 | */ |
699 | error = uhidev_config_enter(sc); | | 699 | error = uhidev_config_enter(sc); |
700 | if (error) | | 700 | if (error) |
701 | goto out; | | 701 | goto out; |
702 | if (sc->sc_refcnt) { | | 702 | if (sc->sc_refcnt) { |
703 | if (sc->sc_refcnt == INT_MAX) { | | 703 | KASSERT(sc->sc_refcnt < UHIDEV_MAXREPID); |
704 | error = EBUSY; | | 704 | sc->sc_refcnt++; |
705 | } else { | | 705 | error = 0; |
706 | sc->sc_refcnt++; | | | |
707 | error = 0; | | | |
708 | } | | | |
709 | goto out0; | | 706 | goto out0; |
710 | } | | 707 | } |
711 | mutex_exit(&sc->sc_lock); | | 708 | mutex_exit(&sc->sc_lock); |
712 | | | 709 | |
713 | /* Allocate an input buffer. */ | | 710 | /* Allocate an input buffer. */ |
714 | sc->sc_ibuf = kmem_alloc(sc->sc_isize, KM_SLEEP); | | 711 | sc->sc_ibuf = kmem_alloc(sc->sc_isize, KM_SLEEP); |
715 | | | 712 | |
716 | /* Set up input interrupt pipe. */ | | 713 | /* Set up input interrupt pipe. */ |
717 | DPRINTF(("%s: isize=%d, ep=0x%02x\n", __func__, sc->sc_isize, | | 714 | DPRINTF(("%s: isize=%d, ep=0x%02x\n", __func__, sc->sc_isize, |
718 | sc->sc_iep_addr)); | | 715 | sc->sc_iep_addr)); |
719 | | | 716 | |
720 | err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_iep_addr, | | 717 | err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_iep_addr, |
721 | USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_ibuf, | | 718 | USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_ibuf, |