112ccb71bSMatthias Ringwald /* 212ccb71bSMatthias Ringwald * Copyright (C) 2017 BlueKitchen GmbH 312ccb71bSMatthias Ringwald * 412ccb71bSMatthias Ringwald * Redistribution and use in source and binary forms, with or without 512ccb71bSMatthias Ringwald * modification, are permitted provided that the following conditions 612ccb71bSMatthias Ringwald * are met: 712ccb71bSMatthias Ringwald * 812ccb71bSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 912ccb71bSMatthias Ringwald * notice, this list of conditions and the following disclaimer. 1012ccb71bSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 1112ccb71bSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 1212ccb71bSMatthias Ringwald * documentation and/or other materials provided with the distribution. 1312ccb71bSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 1412ccb71bSMatthias Ringwald * contributors may be used to endorse or promote products derived 1512ccb71bSMatthias Ringwald * from this software without specific prior written permission. 1612ccb71bSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 1712ccb71bSMatthias Ringwald * personal benefit and not for any commercial purpose or for 1812ccb71bSMatthias Ringwald * monetary gain. 1912ccb71bSMatthias Ringwald * 2012ccb71bSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 2112ccb71bSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2212ccb71bSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 232fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 242fca4dadSMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2512ccb71bSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2612ccb71bSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 2712ccb71bSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2812ccb71bSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2912ccb71bSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 3012ccb71bSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3112ccb71bSMatthias Ringwald * SUCH DAMAGE. 3212ccb71bSMatthias Ringwald * 3312ccb71bSMatthias Ringwald * Please inquire about commercial licensing options at 3412ccb71bSMatthias Ringwald * [email protected] 3512ccb71bSMatthias Ringwald * 3612ccb71bSMatthias Ringwald */ 3712ccb71bSMatthias Ringwald 38fe5a6c4eSMilanka Ringwald /** 39fe5a6c4eSMilanka Ringwald * @title HID Parser 4012ccb71bSMatthias Ringwald * 41fe5a6c4eSMilanka Ringwald * Single-pass HID Report Parser: HID Report is directly parsed without preprocessing HID Descriptor to minimize memory. 42fe5a6c4eSMilanka Ringwald * 4312ccb71bSMatthias Ringwald */ 4412ccb71bSMatthias Ringwald 4580e33422SMatthias Ringwald #ifndef BTSTACK_HID_PARSER_H 4680e33422SMatthias Ringwald #define BTSTACK_HID_PARSER_H 4712ccb71bSMatthias Ringwald 4812ccb71bSMatthias Ringwald #include <stdint.h> 491a05cde1SMatthias Ringwald #include "btstack_bool.h" 503cbedd43SMatthias Ringwald #include "btstack_hid.h" 5112ccb71bSMatthias Ringwald 5212ccb71bSMatthias Ringwald #if defined __cplusplus 5312ccb71bSMatthias Ringwald extern "C" { 5412ccb71bSMatthias Ringwald #endif 5512ccb71bSMatthias Ringwald 56fada7179SMilanka Ringwald typedef enum { 57fada7179SMilanka Ringwald Main=0, 58fada7179SMilanka Ringwald Global, 59fada7179SMilanka Ringwald Local, 60fada7179SMilanka Ringwald Reserved 61fada7179SMilanka Ringwald } TagType; 62fada7179SMilanka Ringwald 63fada7179SMilanka Ringwald typedef enum { 64fada7179SMilanka Ringwald Input=8, 65fada7179SMilanka Ringwald Output, 66fada7179SMilanka Ringwald Coll, 67fada7179SMilanka Ringwald Feature, 68fada7179SMilanka Ringwald EndColl 69fada7179SMilanka Ringwald } MainItemTag; 70fada7179SMilanka Ringwald 71fada7179SMilanka Ringwald typedef enum { 72fada7179SMilanka Ringwald UsagePage, 73fada7179SMilanka Ringwald LogicalMinimum, 74fada7179SMilanka Ringwald LogicalMaximum, 75fada7179SMilanka Ringwald PhysicalMinimum, 76fada7179SMilanka Ringwald PhysicalMaximum, 77fada7179SMilanka Ringwald UnitExponent, 78fada7179SMilanka Ringwald Unit, 79fada7179SMilanka Ringwald ReportSize, 80fada7179SMilanka Ringwald ReportID, 81fada7179SMilanka Ringwald ReportCount, 82fada7179SMilanka Ringwald Push, 83fada7179SMilanka Ringwald Pop 84fada7179SMilanka Ringwald } GlobalItemTag; 85fada7179SMilanka Ringwald 86fada7179SMilanka Ringwald typedef enum { 87fada7179SMilanka Ringwald Usage, 88fada7179SMilanka Ringwald UsageMinimum, 89fada7179SMilanka Ringwald UsageMaximum, 90fada7179SMilanka Ringwald DesignatorIndex, 91fada7179SMilanka Ringwald DesignatorMinimum, 92fada7179SMilanka Ringwald DesignatorMaximum, 93fada7179SMilanka Ringwald StringIndex, 94fada7179SMilanka Ringwald StringMinimum, 95fada7179SMilanka Ringwald StringMaximum, 96fada7179SMilanka Ringwald Delimiter 97fada7179SMilanka Ringwald } LocalItemTag; 98fada7179SMilanka Ringwald 9912ccb71bSMatthias Ringwald typedef struct { 10012ccb71bSMatthias Ringwald int32_t item_value; 10112ccb71bSMatthias Ringwald uint16_t item_size; 10212ccb71bSMatthias Ringwald uint8_t item_type; 10312ccb71bSMatthias Ringwald uint8_t item_tag; 10412ccb71bSMatthias Ringwald uint8_t data_size; 10512ccb71bSMatthias Ringwald } hid_descriptor_item_t; 10612ccb71bSMatthias Ringwald 1070c7e4a25SMatthias Ringwald typedef struct { 1080c7e4a25SMatthias Ringwald // Descriptor 1090c7e4a25SMatthias Ringwald const uint8_t * descriptor; 1100c7e4a25SMatthias Ringwald uint16_t descriptor_pos; 1110c7e4a25SMatthias Ringwald uint16_t descriptor_len; 1120c7e4a25SMatthias Ringwald // parsed item 1130c7e4a25SMatthias Ringwald bool item_ready; 1140c7e4a25SMatthias Ringwald bool valid; 1150c7e4a25SMatthias Ringwald hid_descriptor_item_t descriptor_item; 1160c7e4a25SMatthias Ringwald } btstack_hid_descriptor_iterator_t; 117dbcaefc7SMilanka Ringwald 118c4241e61SMatthias Ringwald 119cc770b38SMatthias Ringwald typedef enum { 120cc770b38SMatthias Ringwald BTSTACK_HID_USAGE_ITERATOR_STATE_SCAN_FOR_REPORT_ITEM, 121cc770b38SMatthias Ringwald BTSTACK_HID_USAGE_ITERATOR_USAGES_AVAILABLE, 122cc770b38SMatthias Ringwald BTSTACK_HID_USAGE_ITERATOR_PARSER_COMPLETE, 123cc770b38SMatthias Ringwald } btstack_hid_usage_iterator_state_t; 124cc770b38SMatthias Ringwald 12512ccb71bSMatthias Ringwald typedef struct { 12612ccb71bSMatthias Ringwald // Descriptor 12712ccb71bSMatthias Ringwald const uint8_t * descriptor; 12812ccb71bSMatthias Ringwald uint16_t descriptor_len; 129c45181feSMatthias Ringwald btstack_hid_descriptor_iterator_t descriptor_iterator; 13012ccb71bSMatthias Ringwald 13112ccb71bSMatthias Ringwald // State 132cc770b38SMatthias Ringwald btstack_hid_usage_iterator_state_t state; 13312ccb71bSMatthias Ringwald 13412ccb71bSMatthias Ringwald hid_descriptor_item_t descriptor_item; 13512ccb71bSMatthias Ringwald 136c4241e61SMatthias Ringwald hid_report_type_t report_type; 137619253e6SMatthias Ringwald 138619253e6SMatthias Ringwald // report bit pos does not include the optional Report ID 13912ccb71bSMatthias Ringwald uint16_t report_pos_in_bit; 14012ccb71bSMatthias Ringwald 14112ccb71bSMatthias Ringwald // usage pos and usage_page after last main item, used to find next usage 14212ccb71bSMatthias Ringwald uint16_t usage_pos; 14312ccb71bSMatthias Ringwald uint16_t usage_page; 14412ccb71bSMatthias Ringwald 14512ccb71bSMatthias Ringwald // usage generator 14612ccb71bSMatthias Ringwald uint32_t usage_minimum; 14712ccb71bSMatthias Ringwald uint32_t usage_maximum; 14812ccb71bSMatthias Ringwald uint16_t available_usages; 1491a05cde1SMatthias Ringwald uint16_t required_usages; 1501a05cde1SMatthias Ringwald bool usage_range; 15112ccb71bSMatthias Ringwald uint8_t active_record; 15212ccb71bSMatthias Ringwald 15312ccb71bSMatthias Ringwald // global 15412ccb71bSMatthias Ringwald int32_t global_logical_minimum; 15512ccb71bSMatthias Ringwald int32_t global_logical_maximum; 15612ccb71bSMatthias Ringwald uint16_t global_usage_page; 15712ccb71bSMatthias Ringwald uint8_t global_report_size; 15812ccb71bSMatthias Ringwald uint8_t global_report_count; 15986360e59SMatthias Ringwald uint16_t global_report_id; 1600ba748f2SMatthias Ringwald 161c4241e61SMatthias Ringwald } btstack_hid_usage_iterator_t; 162c4241e61SMatthias Ringwald 163c4241e61SMatthias Ringwald typedef struct { 164c4241e61SMatthias Ringwald uint16_t report_id; // 8-bit report ID or 0xffff if not set 165c4241e61SMatthias Ringwald uint16_t bit_pos; // position in bit 166c4241e61SMatthias Ringwald uint16_t usage_page; 167c4241e61SMatthias Ringwald uint16_t usage; 168c4241e61SMatthias Ringwald uint8_t size; // in bit 169c4241e61SMatthias Ringwald 170c4241e61SMatthias Ringwald // cached values of relevant descriptor item (input,output,feature) 171c4241e61SMatthias Ringwald hid_descriptor_item_t descriptor_item; 172c4241e61SMatthias Ringwald int32_t global_logical_minimum; 173c4241e61SMatthias Ringwald } btstack_hid_usage_item_t; 174c4241e61SMatthias Ringwald 175c4241e61SMatthias Ringwald 176c4241e61SMatthias Ringwald typedef struct { 177c4241e61SMatthias Ringwald btstack_hid_usage_iterator_t usage_iterator; 178c4241e61SMatthias Ringwald 179c4241e61SMatthias Ringwald const uint8_t * report; 180c4241e61SMatthias Ringwald uint16_t report_len; 181c4241e61SMatthias Ringwald 1820ba748f2SMatthias Ringwald bool have_report_usage_ready; 183a05e6df3SMatthias Ringwald btstack_hid_usage_item_t descriptor_usage_item; 184c4241e61SMatthias Ringwald 18512ccb71bSMatthias Ringwald } btstack_hid_parser_t; 18612ccb71bSMatthias Ringwald 1870c7e4a25SMatthias Ringwald 18812ccb71bSMatthias Ringwald /* API_START */ 18912ccb71bSMatthias Ringwald 1900ba748f2SMatthias Ringwald // HID Descriptor Iterator 1910ba748f2SMatthias Ringwald 19212ccb71bSMatthias Ringwald /** 1930c7e4a25SMatthias Ringwald * @brief Init HID Descriptor iterator 1940c7e4a25SMatthias Ringwald * @param iterator 1950c7e4a25SMatthias Ringwald * @param hid_descriptor 1960c7e4a25SMatthias Ringwald * @param hid_descriptor_len 1970c7e4a25SMatthias Ringwald */ 1980c7e4a25SMatthias Ringwald void btstack_hid_descriptor_iterator_init(btstack_hid_descriptor_iterator_t * iterator, const uint8_t * hid_descriptor, uint16_t hid_descriptor_len); 1990c7e4a25SMatthias Ringwald 2000c7e4a25SMatthias Ringwald /** 2010c7e4a25SMatthias Ringwald * @brief Check if HID Descriptor Items are available 2020c7e4a25SMatthias Ringwald * @param iterator 2030c7e4a25SMatthias Ringwald * @return 2040c7e4a25SMatthias Ringwald */ 2050c7e4a25SMatthias Ringwald bool btstack_hid_descriptor_iterator_has_more(btstack_hid_descriptor_iterator_t * iterator); 2060c7e4a25SMatthias Ringwald 2070c7e4a25SMatthias Ringwald /** 2080c7e4a25SMatthias Ringwald * @brief Get next HID Descriptor Item 2090c7e4a25SMatthias Ringwald * @param iterator 2100c7e4a25SMatthias Ringwald * @return 2110c7e4a25SMatthias Ringwald */ 212*3465b19cSDirk Helbig const hid_descriptor_item_t * btstack_hid_descriptor_iterator_get_item(btstack_hid_descriptor_iterator_t * iterator); 2130c7e4a25SMatthias Ringwald 2140c7e4a25SMatthias Ringwald /** 2150c7e4a25SMatthias Ringwald * @brief Returns if HID Descriptor was well formed 2160c7e4a25SMatthias Ringwald * @param iterator 2170c7e4a25SMatthias Ringwald * @return 2180c7e4a25SMatthias Ringwald */ 2190c7e4a25SMatthias Ringwald bool btstack_hid_descriptor_iterator_valid(btstack_hid_descriptor_iterator_t * iterator); 2200c7e4a25SMatthias Ringwald 221cdb96ae5SMatthias Ringwald 2220ba748f2SMatthias Ringwald // HID Descriptor Usage Iterator 2230ba748f2SMatthias Ringwald 224cdb96ae5SMatthias Ringwald /** 225cdb96ae5SMatthias Ringwald * @brief Initialize usages iterator for HID Descriptor and report type 226cdb96ae5SMatthias Ringwald * @param parser 227cdb96ae5SMatthias Ringwald * @param hid_descriptor 228cdb96ae5SMatthias Ringwald * @param hid_descriptor_len 229cdb96ae5SMatthias Ringwald * @param hid_report_type 230cdb96ae5SMatthias Ringwald */ 231c4241e61SMatthias Ringwald void btstack_hid_usage_iterator_init(btstack_hid_usage_iterator_t * iterator, const uint8_t * hid_descriptor, uint16_t hid_descriptor_len, hid_report_type_t hid_report_type); 232cdb96ae5SMatthias Ringwald 233cdb96ae5SMatthias Ringwald /** 234cdb96ae5SMatthias Ringwald * @brief Checks if more usages are available 235cdb96ae5SMatthias Ringwald * @param parser 236cdb96ae5SMatthias Ringwald */ 237c4241e61SMatthias Ringwald bool btstack_hid_usage_iterator_has_more(btstack_hid_usage_iterator_t * iterator); 238cdb96ae5SMatthias Ringwald 239cdb96ae5SMatthias Ringwald /** 240cdb96ae5SMatthias Ringwald * @brief Get current usage item 241cdb96ae5SMatthias Ringwald * @param parser 242cdb96ae5SMatthias Ringwald * @param item 243cdb96ae5SMatthias Ringwald */ 244c4241e61SMatthias Ringwald void btstack_hid_usage_iterator_get_item(btstack_hid_usage_iterator_t * iterator, btstack_hid_usage_item_t * item); 245cdb96ae5SMatthias Ringwald 246cdb96ae5SMatthias Ringwald 2470ba748f2SMatthias Ringwald // HID Report Iterator 2480ba748f2SMatthias Ringwald 2490c7e4a25SMatthias Ringwald /** 25012ccb71bSMatthias Ringwald * @brief Initialize HID Parser. 25112ccb71bSMatthias Ringwald * @param parser state 25212ccb71bSMatthias Ringwald * @param hid_descriptor 25312ccb71bSMatthias Ringwald * @param hid_descriptor_len 25412ccb71bSMatthias Ringwald * @param hid_report_type 25512ccb71bSMatthias Ringwald * @param hid_report 25612ccb71bSMatthias Ringwald * @param hid_report_len 25712ccb71bSMatthias Ringwald */ 258662cddc2SMilanka Ringwald 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); 25912ccb71bSMatthias Ringwald 26012ccb71bSMatthias Ringwald /** 26112ccb71bSMatthias Ringwald * @brief Checks if more fields are available 26212ccb71bSMatthias Ringwald * @param parser 26312ccb71bSMatthias Ringwald */ 264088c59dfSMatthias Ringwald bool btstack_hid_parser_has_more(btstack_hid_parser_t * parser); 26512ccb71bSMatthias Ringwald 26612ccb71bSMatthias Ringwald /** 26712ccb71bSMatthias Ringwald * @brief Get next field 26812ccb71bSMatthias Ringwald * @param parser 26912ccb71bSMatthias Ringwald * @param usage_page 27012ccb71bSMatthias Ringwald * @param usage 27112ccb71bSMatthias Ringwald * @param value provided in HID report 27212ccb71bSMatthias Ringwald */ 27312ccb71bSMatthias Ringwald void btstack_hid_parser_get_field(btstack_hid_parser_t * parser, uint16_t * usage_page, uint16_t * usage, int32_t * value); 27412ccb71bSMatthias Ringwald 2750c7e4a25SMatthias Ringwald 276fada7179SMilanka Ringwald /** 277fada7179SMilanka Ringwald * @brief Parses descriptor and returns report size for given report ID and report type 278279225e6SMatthias Ringwald * @param report_id or HID_REPORT_ID_UNDEFINED 279fada7179SMilanka Ringwald * @param report_type 280fada7179SMilanka Ringwald * @param hid_descriptor 2812cca3b08SMatthias Ringwald * @param hid_descriptor_len 2823a1d5296SMatthias Ringwald * @return report size in bytes or 0 on parsing error 283fada7179SMilanka Ringwald */ 2842cca3b08SMatthias Ringwald int btstack_hid_get_report_size_for_id(uint16_t report_id, hid_report_type_t report_type, const uint8_t *hid_descriptor, 2852cca3b08SMatthias Ringwald uint16_t hid_descriptor_len); 286dbcaefc7SMilanka Ringwald 287dbcaefc7SMilanka Ringwald /** 2880e7cc963SMatthias Ringwald * @brief Parses descriptor and returns status for given report ID 289dbcaefc7SMilanka Ringwald * @param report_id 290dbcaefc7SMilanka Ringwald * @param hid_descriptor 291279225e6SMatthias Ringwald * @param hid_descriptor_len 2920e7cc963SMatthias Ringwald * @return status for report id 293dbcaefc7SMilanka Ringwald */ 294279225e6SMatthias Ringwald hid_report_id_status_t btstack_hid_report_id_valid(uint16_t report_id, const uint8_t * hid_descriptor, uint16_t hid_descriptor_len); 295dbcaefc7SMilanka Ringwald 296dbcaefc7SMilanka Ringwald /** 297c17118d0SMatthias Ringwald * @brief Parses descriptor and returns true if report ID found 298dbcaefc7SMilanka Ringwald * @param hid_descriptor 2992cca3b08SMatthias Ringwald * @param hid_descriptor_len 300c17118d0SMatthias Ringwald * @return true if report ID declared in descriptor 301dbcaefc7SMilanka Ringwald */ 3022cca3b08SMatthias Ringwald bool btstack_hid_report_id_declared(const uint8_t *hid_descriptor, uint16_t hid_descriptor_len); 3030c7e4a25SMatthias Ringwald 3040ba748f2SMatthias Ringwald 30512ccb71bSMatthias Ringwald /* API_END */ 30612ccb71bSMatthias Ringwald 30712ccb71bSMatthias Ringwald #if defined __cplusplus 30812ccb71bSMatthias Ringwald } 30912ccb71bSMatthias Ringwald #endif 31012ccb71bSMatthias Ringwald 31180e33422SMatthias Ringwald #endif // BTSTACK_HID_PARSER_H 312