xref: /btstack/src/btstack_hid_parser.h (revision c4241e61df634d103b90a40fb5ece7fd4bb9b48f)
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 
118*c4241e61SMatthias 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 
136*c4241e61SMatthias Ringwald     hid_report_type_t report_type;
13712ccb71bSMatthias Ringwald     uint16_t        report_pos_in_bit;
13812ccb71bSMatthias Ringwald 
13912ccb71bSMatthias Ringwald     // usage pos and usage_page after last main item, used to find next usage
14012ccb71bSMatthias Ringwald     uint16_t        usage_pos;
14112ccb71bSMatthias Ringwald     uint16_t        usage_page;
14212ccb71bSMatthias Ringwald 
14312ccb71bSMatthias Ringwald     // usage generator
14412ccb71bSMatthias Ringwald     uint32_t        usage_minimum;
14512ccb71bSMatthias Ringwald     uint32_t        usage_maximum;
14612ccb71bSMatthias Ringwald     uint16_t        available_usages;
1471a05cde1SMatthias Ringwald     uint16_t        required_usages;
1481a05cde1SMatthias Ringwald     bool            usage_range;
14912ccb71bSMatthias Ringwald     uint8_t         active_record;
15012ccb71bSMatthias Ringwald 
15112ccb71bSMatthias Ringwald     // global
15212ccb71bSMatthias Ringwald     int32_t         global_logical_minimum;
15312ccb71bSMatthias Ringwald     int32_t         global_logical_maximum;
15412ccb71bSMatthias Ringwald     uint16_t        global_usage_page;
15512ccb71bSMatthias Ringwald     uint8_t         global_report_size;
15612ccb71bSMatthias Ringwald     uint8_t         global_report_count;
15786360e59SMatthias Ringwald     uint16_t        global_report_id;
1580ba748f2SMatthias Ringwald 
159*c4241e61SMatthias Ringwald } btstack_hid_usage_iterator_t;
160*c4241e61SMatthias Ringwald 
161*c4241e61SMatthias Ringwald typedef struct {
162*c4241e61SMatthias Ringwald     uint16_t report_id; // 8-bit report ID or 0xffff if not set
163*c4241e61SMatthias Ringwald     uint16_t bit_pos;   // position in bit
164*c4241e61SMatthias Ringwald     uint16_t usage_page;
165*c4241e61SMatthias Ringwald     uint16_t usage;
166*c4241e61SMatthias Ringwald     uint8_t  size;      // in bit
167*c4241e61SMatthias Ringwald 
168*c4241e61SMatthias Ringwald     // cached values of relevant descriptor item (input,output,feature)
169*c4241e61SMatthias Ringwald     hid_descriptor_item_t descriptor_item;
170*c4241e61SMatthias Ringwald     int32_t               global_logical_minimum;
171*c4241e61SMatthias Ringwald } btstack_hid_usage_item_t;
172*c4241e61SMatthias Ringwald 
173*c4241e61SMatthias Ringwald 
174*c4241e61SMatthias Ringwald typedef struct {
175*c4241e61SMatthias Ringwald     btstack_hid_usage_iterator_t usage_iterator;
176*c4241e61SMatthias Ringwald 
177*c4241e61SMatthias Ringwald     const uint8_t *   report;
178*c4241e61SMatthias Ringwald     uint16_t          report_len;
179*c4241e61SMatthias Ringwald 
1800ba748f2SMatthias Ringwald     bool have_report_usage_ready;
1810ba748f2SMatthias Ringwald     btstack_hid_usage_item_t descriptor__usage_item;
182*c4241e61SMatthias Ringwald 
18312ccb71bSMatthias Ringwald } btstack_hid_parser_t;
18412ccb71bSMatthias Ringwald 
1850c7e4a25SMatthias Ringwald 
18612ccb71bSMatthias Ringwald /* API_START */
18712ccb71bSMatthias Ringwald 
1880ba748f2SMatthias Ringwald // HID Descriptor Iterator
1890ba748f2SMatthias Ringwald 
19012ccb71bSMatthias Ringwald /**
1910c7e4a25SMatthias Ringwald  * @brief Init HID Descriptor iterator
1920c7e4a25SMatthias Ringwald  * @param iterator
1930c7e4a25SMatthias Ringwald  * @param hid_descriptor
1940c7e4a25SMatthias Ringwald  * @param hid_descriptor_len
1950c7e4a25SMatthias Ringwald  */
1960c7e4a25SMatthias Ringwald void btstack_hid_descriptor_iterator_init(btstack_hid_descriptor_iterator_t * iterator, const uint8_t * hid_descriptor, uint16_t hid_descriptor_len);
1970c7e4a25SMatthias Ringwald 
1980c7e4a25SMatthias Ringwald /**
1990c7e4a25SMatthias Ringwald  * @brief Check if HID Descriptor Items are available
2000c7e4a25SMatthias Ringwald  * @param iterator
2010c7e4a25SMatthias Ringwald  * @return
2020c7e4a25SMatthias Ringwald  */
2030c7e4a25SMatthias Ringwald bool btstack_hid_descriptor_iterator_has_more(btstack_hid_descriptor_iterator_t * iterator);
2040c7e4a25SMatthias Ringwald 
2050c7e4a25SMatthias Ringwald /**
2060c7e4a25SMatthias Ringwald  * @brief Get next HID Descriptor Item
2070c7e4a25SMatthias Ringwald  * @param iterator
2080c7e4a25SMatthias Ringwald  * @return
2090c7e4a25SMatthias Ringwald  */
2100c7e4a25SMatthias Ringwald const hid_descriptor_item_t * const btstack_hid_descriptor_iterator_get_item(btstack_hid_descriptor_iterator_t * iterator);
2110c7e4a25SMatthias Ringwald 
2120c7e4a25SMatthias Ringwald /**
2130c7e4a25SMatthias Ringwald  * @brief Returns if HID Descriptor was well formed
2140c7e4a25SMatthias Ringwald  * @param iterator
2150c7e4a25SMatthias Ringwald  * @return
2160c7e4a25SMatthias Ringwald  */
2170c7e4a25SMatthias Ringwald bool btstack_hid_descriptor_iterator_valid(btstack_hid_descriptor_iterator_t * iterator);
2180c7e4a25SMatthias Ringwald 
219cdb96ae5SMatthias Ringwald 
2200ba748f2SMatthias Ringwald // HID Descriptor Usage Iterator
2210ba748f2SMatthias Ringwald 
222cdb96ae5SMatthias Ringwald /**
223cdb96ae5SMatthias Ringwald  * @brief Initialize usages iterator for HID Descriptor and report type
224cdb96ae5SMatthias Ringwald  * @param parser
225cdb96ae5SMatthias Ringwald  * @param hid_descriptor
226cdb96ae5SMatthias Ringwald  * @param hid_descriptor_len
227cdb96ae5SMatthias Ringwald  * @param hid_report_type
228cdb96ae5SMatthias Ringwald  */
229*c4241e61SMatthias 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);
230cdb96ae5SMatthias Ringwald 
231cdb96ae5SMatthias Ringwald /**
232cdb96ae5SMatthias Ringwald  * @brief Checks if more usages are available
233cdb96ae5SMatthias Ringwald  * @param parser
234cdb96ae5SMatthias Ringwald  */
235*c4241e61SMatthias Ringwald bool btstack_hid_usage_iterator_has_more(btstack_hid_usage_iterator_t * iterator);
236cdb96ae5SMatthias Ringwald 
237cdb96ae5SMatthias Ringwald /**
238cdb96ae5SMatthias Ringwald  * @brief Get current usage item
239cdb96ae5SMatthias Ringwald  * @param parser
240cdb96ae5SMatthias Ringwald  * @param item
241cdb96ae5SMatthias Ringwald  */
242*c4241e61SMatthias Ringwald void btstack_hid_usage_iterator_get_item(btstack_hid_usage_iterator_t * iterator, btstack_hid_usage_item_t * item);
243cdb96ae5SMatthias Ringwald 
244cdb96ae5SMatthias Ringwald 
2450ba748f2SMatthias Ringwald // HID Report Iterator
2460ba748f2SMatthias Ringwald 
2470c7e4a25SMatthias Ringwald /**
24812ccb71bSMatthias Ringwald  * @brief Initialize HID Parser.
24912ccb71bSMatthias Ringwald  * @param parser state
25012ccb71bSMatthias Ringwald  * @param hid_descriptor
25112ccb71bSMatthias Ringwald  * @param hid_descriptor_len
25212ccb71bSMatthias Ringwald  * @param hid_report_type
25312ccb71bSMatthias Ringwald  * @param hid_report
25412ccb71bSMatthias Ringwald  * @param hid_report_len
25512ccb71bSMatthias Ringwald  */
256662cddc2SMilanka 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);
25712ccb71bSMatthias Ringwald 
25812ccb71bSMatthias Ringwald /**
25912ccb71bSMatthias Ringwald  * @brief Checks if more fields are available
26012ccb71bSMatthias Ringwald  * @param parser
26112ccb71bSMatthias Ringwald  */
262088c59dfSMatthias Ringwald bool btstack_hid_parser_has_more(btstack_hid_parser_t * parser);
26312ccb71bSMatthias Ringwald 
26412ccb71bSMatthias Ringwald /**
26512ccb71bSMatthias Ringwald  * @brief Get next field
26612ccb71bSMatthias Ringwald  * @param parser
26712ccb71bSMatthias Ringwald  * @param usage_page
26812ccb71bSMatthias Ringwald  * @param usage
26912ccb71bSMatthias Ringwald  * @param value provided in HID report
27012ccb71bSMatthias Ringwald  */
27112ccb71bSMatthias Ringwald void btstack_hid_parser_get_field(btstack_hid_parser_t * parser, uint16_t * usage_page, uint16_t * usage, int32_t * value);
27212ccb71bSMatthias Ringwald 
2730c7e4a25SMatthias Ringwald 
274fada7179SMilanka Ringwald /**
275fada7179SMilanka Ringwald  * @brief Parses descriptor item
276fada7179SMilanka Ringwald  * @param item
277fada7179SMilanka Ringwald  * @param hid_descriptor
278fada7179SMilanka Ringwald  * @param hid_descriptor_len
27976fa2448SMatthias Ringwald  * @return true if item has been parsed successfully
280fada7179SMilanka Ringwald  */
28176fa2448SMatthias Ringwald bool btstack_hid_parse_descriptor_item(hid_descriptor_item_t * item, const uint8_t * hid_descriptor, uint16_t hid_descriptor_len);
282fada7179SMilanka Ringwald 
283fada7179SMilanka Ringwald /**
284fada7179SMilanka Ringwald  * @brief Parses descriptor and returns report size for given report ID and report type
285279225e6SMatthias Ringwald  * @param report_id or HID_REPORT_ID_UNDEFINED
286fada7179SMilanka Ringwald  * @param report_type
287fada7179SMilanka Ringwald  * @param hid_descriptor
2882cca3b08SMatthias Ringwald  * @param hid_descriptor_len
2893a1d5296SMatthias Ringwald  * @return report size in bytes or 0 on parsing error
290fada7179SMilanka Ringwald  */
2912cca3b08SMatthias Ringwald int btstack_hid_get_report_size_for_id(uint16_t report_id, hid_report_type_t report_type, const uint8_t *hid_descriptor,
2922cca3b08SMatthias Ringwald                                        uint16_t hid_descriptor_len);
293dbcaefc7SMilanka Ringwald 
294dbcaefc7SMilanka Ringwald /**
2950e7cc963SMatthias Ringwald  * @brief Parses descriptor and returns status for given report ID
296dbcaefc7SMilanka Ringwald  * @param report_id
297dbcaefc7SMilanka Ringwald  * @param hid_descriptor
298279225e6SMatthias Ringwald  * @param hid_descriptor_len
2990e7cc963SMatthias Ringwald  * @return status for report id
300dbcaefc7SMilanka Ringwald  */
301279225e6SMatthias 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);
302dbcaefc7SMilanka Ringwald 
303dbcaefc7SMilanka Ringwald /**
304c17118d0SMatthias Ringwald  * @brief Parses descriptor and returns true if report ID found
305dbcaefc7SMilanka Ringwald  * @param hid_descriptor
3062cca3b08SMatthias Ringwald  * @param hid_descriptor_len
307c17118d0SMatthias Ringwald  * @return true if report ID declared in descriptor
308dbcaefc7SMilanka Ringwald  */
3092cca3b08SMatthias Ringwald bool btstack_hid_report_id_declared(const uint8_t *hid_descriptor, uint16_t hid_descriptor_len);
3100c7e4a25SMatthias Ringwald 
3110ba748f2SMatthias Ringwald 
31212ccb71bSMatthias Ringwald /* API_END */
31312ccb71bSMatthias Ringwald 
31412ccb71bSMatthias Ringwald #if defined __cplusplus
31512ccb71bSMatthias Ringwald }
31612ccb71bSMatthias Ringwald #endif
31712ccb71bSMatthias Ringwald 
31880e33422SMatthias Ringwald #endif // BTSTACK_HID_PARSER_H
319