1 /* $NetBSD: hid.c,v 1.17 2001/11/13 06:24:53 lukem Exp $ */ 2 /*- 3 * SPDX-License-Identifier: BSD-2-Clause 4 * 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Lennart Augustsson (lennart@augustsson.net) at 10 * Carlstedt Research & Technology. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #ifdef USB_GLOBAL_INCLUDE_FILE 35 #include USB_GLOBAL_INCLUDE_FILE 36 #else 37 #include <sys/stdint.h> 38 #include <sys/stddef.h> 39 #include <sys/param.h> 40 #include <sys/queue.h> 41 #include <sys/types.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/bus.h> 45 #include <sys/module.h> 46 #include <sys/lock.h> 47 #include <sys/mutex.h> 48 #include <sys/condvar.h> 49 #include <sys/sysctl.h> 50 #include <sys/sx.h> 51 #include <sys/unistd.h> 52 #include <sys/callout.h> 53 #include <sys/malloc.h> 54 #include <sys/priv.h> 55 56 #include <dev/usb/usb.h> 57 #include <dev/usb/usbdi.h> 58 #include <dev/usb/usbdi_util.h> 59 #include <dev/usb/usbhid.h> 60 61 #define USB_DEBUG_VAR usb_debug 62 63 #include <dev/usb/usb_core.h> 64 #include <dev/usb/usb_debug.h> 65 #include <dev/usb/usb_process.h> 66 #include <dev/usb/usb_device.h> 67 #include <dev/usb/usb_request.h> 68 #endif /* USB_GLOBAL_INCLUDE_FILE */ 69 70 /*------------------------------------------------------------------------* 71 * hid_get_descriptor_from_usb 72 * 73 * This function will search for a HID descriptor between two USB 74 * interface descriptors. 75 * 76 * Return values: 77 * NULL: No more HID descriptors. 78 * Else: Pointer to HID descriptor. 79 *------------------------------------------------------------------------*/ 80 struct usb_hid_descriptor * 81 hid_get_descriptor_from_usb(struct usb_config_descriptor *cd, 82 struct usb_interface_descriptor *id) 83 { 84 struct usb_descriptor *desc = (void *)id; 85 86 if (desc == NULL) { 87 return (NULL); 88 } 89 while ((desc = usb_desc_foreach(cd, desc))) { 90 if ((desc->bDescriptorType == UDESC_HID) && 91 (desc->bLength >= USB_HID_DESCRIPTOR_SIZE(0))) { 92 return (void *)desc; 93 } 94 if (desc->bDescriptorType == UDESC_INTERFACE) { 95 break; 96 } 97 } 98 return (NULL); 99 } 100 101 /*------------------------------------------------------------------------* 102 * usbd_req_get_hid_desc 103 * 104 * This function will read out an USB report descriptor from the USB 105 * device. 106 * 107 * Return values: 108 * NULL: Failure. 109 * Else: Success. The pointer should eventually be passed to free(). 110 *------------------------------------------------------------------------*/ 111 usb_error_t 112 usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, 113 void **descp, uint16_t *sizep, 114 struct malloc_type *mem, uint8_t iface_index) 115 { 116 struct usb_interface *iface = usbd_get_iface(udev, iface_index); 117 struct usb_hid_descriptor *hid; 118 usb_error_t err; 119 120 if ((iface == NULL) || (iface->idesc == NULL)) { 121 return (USB_ERR_INVAL); 122 } 123 hid = hid_get_descriptor_from_usb 124 (usbd_get_config_descriptor(udev), iface->idesc); 125 126 if (hid == NULL) { 127 return (USB_ERR_IOERROR); 128 } 129 *sizep = UGETW(hid->descrs[0].wDescriptorLength); 130 if (*sizep == 0) { 131 return (USB_ERR_IOERROR); 132 } 133 if (mtx) 134 mtx_unlock(mtx); 135 136 *descp = malloc(*sizep, mem, M_ZERO | M_WAITOK); 137 138 if (mtx) 139 mtx_lock(mtx); 140 141 if (*descp == NULL) { 142 return (USB_ERR_NOMEM); 143 } 144 err = usbd_req_get_report_descriptor 145 (udev, mtx, *descp, *sizep, iface_index); 146 147 if (err) { 148 free(*descp, mem); 149 *descp = NULL; 150 return (err); 151 } 152 return (USB_ERR_NORMAL_COMPLETION); 153 } 154