1 /*- 2 * Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #ifndef _HID_HIDBUS_H_ 27 #define _HID_HIDBUS_H_ 28 29 enum { 30 HIDBUS_IVAR_USAGE, 31 HIDBUS_IVAR_INDEX, 32 HIDBUS_IVAR_FLAGS, 33 #define HIDBUS_FLAG_AUTOCHILD (0<<1) /* Child is autodiscovered */ 34 #define HIDBUS_FLAG_CAN_POLL (1<<1) /* Child can work during panic */ 35 HIDBUS_IVAR_DRIVER_INFO, 36 HIDBUS_IVAR_LOCK, 37 }; 38 39 #define HIDBUS_ACCESSOR(A, B, T) \ 40 __BUS_ACCESSOR(hidbus, A, HIDBUS, B, T) 41 42 HIDBUS_ACCESSOR(usage, USAGE, int32_t) 43 HIDBUS_ACCESSOR(index, INDEX, uint8_t) 44 HIDBUS_ACCESSOR(flags, FLAGS, uint32_t) 45 HIDBUS_ACCESSOR(driver_info, DRIVER_INFO, uintptr_t) 46 HIDBUS_ACCESSOR(lock, LOCK, struct mtx *) 47 48 /* 49 * The following structure is used when looking up an HID driver for 50 * an HID device. It is inspired by the structure called "usb_device_id". 51 * which is originated in Linux and ported to FreeBSD. 52 */ 53 struct hid_device_id { 54 55 /* Select which fields to match against */ 56 #if BYTE_ORDER == LITTLE_ENDIAN 57 uint16_t 58 match_flag_page:1, 59 match_flag_usage:1, 60 match_flag_bus:1, 61 match_flag_vendor:1, 62 match_flag_product:1, 63 match_flag_ver_lo:1, 64 match_flag_ver_hi:1, 65 match_flag_pnp:1, 66 match_flag_unused:8; 67 #else 68 uint16_t 69 match_flag_unused:8, 70 match_flag_pnp:1, 71 match_flag_ver_hi:1, 72 match_flag_ver_lo:1, 73 match_flag_product:1, 74 match_flag_vendor:1, 75 match_flag_bus:1, 76 match_flag_usage:1, 77 match_flag_page:1; 78 #endif 79 80 /* Used for top level collection usage matches */ 81 uint16_t page; 82 uint16_t usage; 83 84 /* Used for product specific matches; the Version range is inclusive */ 85 uint8_t idBus; 86 uint16_t idVendor; 87 uint16_t idProduct; 88 uint16_t idVersion_lo; 89 uint16_t idVersion_hi; 90 char *idPnP; 91 92 /* Hook for driver specific information */ 93 uintptr_t driver_info; 94 }; 95 96 #define HID_STD_PNP_INFO \ 97 "M16:mask;U16:page;U16:usage;U8:bus;U16:vendor;U16:product;" \ 98 "L16:version;G16:version;Z:_HID" 99 #define HID_PNP_INFO(table) \ 100 MODULE_PNP_INFO(HID_STD_PNP_INFO, hidbus, table, table, nitems(table)) 101 102 #define HID_TLC(pg,usg) \ 103 .match_flag_page = 1, .match_flag_usage = 1, .page = (pg), .usage = (usg) 104 105 #define HID_BUS(bus) \ 106 .match_flag_bus = 1, .idBus = (bus) 107 108 #define HID_VENDOR(vend) \ 109 .match_flag_vendor = 1, .idVendor = (vend) 110 111 #define HID_PRODUCT(prod) \ 112 .match_flag_product = 1, .idProduct = (prod) 113 114 #define HID_VP(vend,prod) \ 115 HID_VENDOR(vend), HID_PRODUCT(prod) 116 117 #define HID_BVP(bus,vend,prod) \ 118 HID_BUS(bus), HID_VENDOR(vend), HID_PRODUCT(prod) 119 120 #define HID_BVPI(bus,vend,prod,info) \ 121 HID_BUS(bus), HID_VENDOR(vend), HID_PRODUCT(prod), HID_DRIVER_INFO(info) 122 123 #define HID_VERSION_GTEQ(lo) /* greater than or equal */ \ 124 .match_flag_ver_lo = 1, .idVersion_lo = (lo) 125 126 #define HID_VERSION_LTEQ(hi) /* less than or equal */ \ 127 .match_flag_ver_hi = 1, .idVersion_hi = (hi) 128 129 #define HID_PNP(pnp) \ 130 .match_flag_pnp = 1, .idPnP = (pnp) 131 132 #define HID_DRIVER_INFO(n) \ 133 .driver_info = (n) 134 135 #define HID_GET_DRIVER_INFO(did) \ 136 (did)->driver_info 137 138 #define HIDBUS_LOOKUP_ID(d, h) hidbus_lookup_id((d), (h), nitems(h)) 139 #define HIDBUS_LOOKUP_DRIVER_INFO(d, h) \ 140 hidbus_lookup_driver_info((d), (h), nitems(h)) 141 142 /* 143 * Walk through all HID items hi belonging Top Level Collection #tlc_index 144 */ 145 #define HIDBUS_FOREACH_ITEM(hd, hi, tlc_index) \ 146 for (uint8_t _iter = 0; \ 147 _iter <= (tlc_index) && hid_get_item((hd), (hi)); \ 148 _iter += (hi)->kind == hid_endcollection && (hi)->collevel == 0) \ 149 if (_iter == (tlc_index)) 150 151 int hidbus_locate(const void *desc, hid_size_t size, int32_t u, 152 enum hid_kind k, uint8_t tlc_index, uint8_t index, 153 struct hid_location *loc, uint32_t *flags, uint8_t *id, 154 struct hid_absinfo *ai); 155 bool hidbus_is_collection(const void *, hid_size_t, int32_t, uint8_t); 156 157 const struct hid_device_id *hidbus_lookup_id(device_t, 158 const struct hid_device_id *, int); 159 struct hid_rdesc_info *hidbus_get_rdesc_info(device_t); 160 int hidbus_lookup_driver_info(device_t, 161 const struct hid_device_id *, int); 162 void hidbus_set_intr(device_t, hid_intr_t*, void *); 163 int hidbus_intr_start(device_t); 164 int hidbus_intr_stop(device_t); 165 void hidbus_intr_poll(device_t); 166 void hidbus_set_desc(device_t, const char *); 167 device_t hidbus_find_child(device_t, int32_t); 168 169 /* hidbus HID interface */ 170 int hid_get_report_descr(device_t, void **, hid_size_t *); 171 int hid_set_report_descr(device_t, const void *, hid_size_t); 172 173 const struct hid_device_info *hid_get_device_info(device_t); 174 175 #endif /* _HID_HIDBUS_H_ */ 176