1 /* 2 * Copyright (C) 2017 BlueKitchen GmbH 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 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 /* 39 * btstack_hid_parser.h 40 * 41 * Single-pass HID Report Parser: HID Report is directly parsed without preprocessing HID Descriptor to minimize memory 42 */ 43 44 #ifndef BTSTACK_HID_PARSER_H 45 #define BTSTACK_HID_PARSER_H 46 47 #include <stdint.h> 48 49 #if defined __cplusplus 50 extern "C" { 51 #endif 52 53 typedef enum { 54 Main=0, 55 Global, 56 Local, 57 Reserved 58 } TagType; 59 60 typedef enum { 61 Input=8, 62 Output, 63 Coll, 64 Feature, 65 EndColl 66 } MainItemTag; 67 68 typedef enum { 69 UsagePage, 70 LogicalMinimum, 71 LogicalMaximum, 72 PhysicalMinimum, 73 PhysicalMaximum, 74 UnitExponent, 75 Unit, 76 ReportSize, 77 ReportID, 78 ReportCount, 79 Push, 80 Pop 81 } GlobalItemTag; 82 83 typedef enum { 84 Usage, 85 UsageMinimum, 86 UsageMaximum, 87 DesignatorIndex, 88 DesignatorMinimum, 89 DesignatorMaximum, 90 StringIndex, 91 StringMinimum, 92 StringMaximum, 93 Delimiter 94 } LocalItemTag; 95 96 typedef struct { 97 int32_t item_value; 98 uint16_t item_size; 99 uint8_t item_type; 100 uint8_t item_tag; 101 uint8_t data_size; 102 } hid_descriptor_item_t; 103 104 typedef enum { 105 BTSTACK_HID_PARSER_SCAN_FOR_REPORT_ITEM, 106 BTSTACK_HID_PARSER_USAGES_AVAILABLE, 107 BTSTACK_HID_PARSER_COMPLETE, 108 } btstack_hid_parser_state_t; 109 110 typedef enum { 111 HID_REPORT_TYPE_RESERVED = 0, 112 HID_REPORT_TYPE_INPUT, 113 HID_REPORT_TYPE_OUTPUT, 114 HID_REPORT_TYPE_FEATURE 115 } hid_report_type_t; 116 117 typedef enum { 118 HID_REPORT_ID_UNDECLARED, 119 HID_REPORT_ID_VALID, 120 HID_REPORT_ID_INVALID 121 } hid_report_id_status_t; 122 123 typedef struct { 124 125 // Descriptor 126 const uint8_t * descriptor; 127 uint16_t descriptor_len; 128 129 // Report 130 hid_report_type_t report_type; 131 const uint8_t * report; 132 uint16_t report_len; 133 134 // State 135 btstack_hid_parser_state_t state; 136 137 hid_descriptor_item_t descriptor_item; 138 139 uint16_t descriptor_pos; 140 uint16_t report_pos_in_bit; 141 142 // usage pos and usage_page after last main item, used to find next usage 143 uint16_t usage_pos; 144 uint16_t usage_page; 145 146 // usage generator 147 uint32_t usage_minimum; 148 uint32_t usage_maximum; 149 uint16_t available_usages; 150 uint8_t required_usages; 151 uint8_t active_record; 152 uint8_t have_usage_min; 153 uint8_t have_usage_max; 154 155 // global 156 int32_t global_logical_minimum; 157 int32_t global_logical_maximum; 158 uint16_t global_usage_page; 159 uint8_t global_report_size; 160 uint8_t global_report_count; 161 uint8_t global_report_id; 162 } btstack_hid_parser_t; 163 164 /* API_START */ 165 166 /** 167 * @brief Initialize HID Parser. 168 * @param parser state 169 * @param hid_descriptor 170 * @param hid_descriptor_len 171 * @param hid_report_type 172 * @param hid_report 173 * @param hid_report_len 174 */ 175 void btstack_hid_parser_init(btstack_hid_parser_t * parser, const uint8_t * hid_descriptor, uint16_t hid_descriptor_len, hid_report_type_t hid_report_type, const uint8_t * hid_report, uint16_t hid_report_len); 176 177 /** 178 * @brief Checks if more fields are available 179 * @param parser 180 */ 181 int btstack_hid_parser_has_more(btstack_hid_parser_t * parser); 182 183 /** 184 * @brief Get next field 185 * @param parser 186 * @param usage_page 187 * @param usage 188 * @param value provided in HID report 189 */ 190 void btstack_hid_parser_get_field(btstack_hid_parser_t * parser, uint16_t * usage_page, uint16_t * usage, int32_t * value); 191 192 /** 193 * @brief Parses descriptor item 194 * @param item 195 * @param hid_descriptor 196 * @param hid_descriptor_len 197 */ 198 void btstack_hid_parse_descriptor_item(hid_descriptor_item_t * item, const uint8_t * hid_descriptor, uint16_t hid_descriptor_len); 199 200 /** 201 * @brief Parses descriptor and returns report size for given report ID and report type 202 * @param report_id 203 * @param report_type 204 * @param hid_descriptor_len 205 * @param hid_descriptor 206 */ 207 int btstack_hid_get_report_size_for_id(int report_id, hid_report_type_t report_type, uint16_t hid_descriptor_len, const uint8_t * hid_descriptor); 208 209 /** 210 * @brief Parses descriptor and returns report size for given report ID and report type 211 * @param report_id 212 * @param hid_descriptor_len 213 * @param hid_descriptor 214 */ 215 hid_report_id_status_t btstack_hid_id_valid(int report_id, uint16_t hid_descriptor_len, const uint8_t * hid_descriptor); 216 217 /** 218 * @brief Parses descriptor and returns 1 if report ID found 219 * @param hid_descriptor_len 220 * @param hid_descriptor 221 */ 222 int btstack_hid_report_id_declared(uint16_t hid_descriptor_len, const uint8_t * hid_descriptor); 223 /* API_END */ 224 225 #if defined __cplusplus 226 } 227 #endif 228 229 #endif // BTSTACK_HID_PARSER_H 230