1ac9a0d84SMatthias Ringwald /* 2ac9a0d84SMatthias Ringwald * Copyright (C) 2021 BlueKitchen GmbH 3ac9a0d84SMatthias Ringwald * 4ac9a0d84SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5ac9a0d84SMatthias Ringwald * modification, are permitted provided that the following conditions 6ac9a0d84SMatthias Ringwald * are met: 7ac9a0d84SMatthias Ringwald * 8ac9a0d84SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9ac9a0d84SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10ac9a0d84SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11ac9a0d84SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12ac9a0d84SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13ac9a0d84SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14ac9a0d84SMatthias Ringwald * contributors may be used to endorse or promote products derived 15ac9a0d84SMatthias Ringwald * from this software without specific prior written permission. 16ac9a0d84SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17ac9a0d84SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18ac9a0d84SMatthias Ringwald * monetary gain. 19ac9a0d84SMatthias Ringwald * 20ac9a0d84SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21ac9a0d84SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22ac9a0d84SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23ac9a0d84SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 24ac9a0d84SMatthias Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25ac9a0d84SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26ac9a0d84SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27ac9a0d84SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28ac9a0d84SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29ac9a0d84SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30ac9a0d84SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31ac9a0d84SMatthias Ringwald * SUCH DAMAGE. 32ac9a0d84SMatthias Ringwald * 33ac9a0d84SMatthias Ringwald * Please inquire about commercial licensing options at 34ac9a0d84SMatthias Ringwald * [email protected] 35ac9a0d84SMatthias Ringwald * 36ac9a0d84SMatthias Ringwald */ 37ac9a0d84SMatthias Ringwald 38ac9a0d84SMatthias Ringwald /** 39ac9a0d84SMatthias Ringwald * OBEX Parser 40ac9a0d84SMatthias Ringwald * Parser incoming arbitrarily chunked OBEX object 41ac9a0d84SMatthias Ringwald */ 42ac9a0d84SMatthias Ringwald 43ac9a0d84SMatthias Ringwald #ifndef OBEX_PARSER_H 44ac9a0d84SMatthias Ringwald #define OBEX_PARSER_H 45ac9a0d84SMatthias Ringwald 46ac9a0d84SMatthias Ringwald #if defined __cplusplus 47ac9a0d84SMatthias Ringwald extern "C" { 48ac9a0d84SMatthias Ringwald #endif 49ac9a0d84SMatthias Ringwald 50ac9a0d84SMatthias Ringwald #include <stdint.h> 51ac9a0d84SMatthias Ringwald 52ac9a0d84SMatthias Ringwald typedef enum { 53ac9a0d84SMatthias Ringwald OBEX_PARSER_STATE_W4_OPCODE, 54ac9a0d84SMatthias Ringwald OBEX_PARSER_STATE_W4_RESPONSE_CODE, 55ac9a0d84SMatthias Ringwald OBEX_PARSER_STATE_W4_PACKET_LEN, 56ac9a0d84SMatthias Ringwald OBEX_PARSER_STATE_W4_PARAMS, 57ac9a0d84SMatthias Ringwald OBEX_PARSER_STATE_W4_HEADER_ID, 58ac9a0d84SMatthias Ringwald OBEX_PARSER_STATE_W4_HEADER_LEN_FIRST, 59ac9a0d84SMatthias Ringwald OBEX_PARSER_STATE_W4_HEADER_LEN_SECOND, 60ac9a0d84SMatthias Ringwald OBEX_PARSER_STATE_W4_HEADER_VALUE, 61ac9a0d84SMatthias Ringwald OBEX_PARSER_STATE_COMPLETE, 62ac9a0d84SMatthias Ringwald OBEX_PARSER_STATE_OVERRUN, 63ac9a0d84SMatthias Ringwald OBEX_PARSER_STATE_INVALID, 64ac9a0d84SMatthias Ringwald } obex_parser_state_t; 65ac9a0d84SMatthias Ringwald 66ac9a0d84SMatthias Ringwald /* API_START */ 67ac9a0d84SMatthias Ringwald 68ac9a0d84SMatthias Ringwald /** 69ac9a0d84SMatthias Ringwald * Callback to process chunked data 70ac9a0d84SMatthias Ringwald * @param user_data provided in obex_parser_init 71ac9a0d84SMatthias Ringwald * @param header_id current OBEX header ID 72ac9a0d84SMatthias Ringwald * @param total_len of header 73ac9a0d84SMatthias Ringwald * @param data_offset 74ac9a0d84SMatthias Ringwald * @param data_len 75ac9a0d84SMatthias Ringwald * @param data_buffer 76ac9a0d84SMatthias Ringwald */ 77ac9a0d84SMatthias Ringwald typedef void (*obex_parser_callback_t)(void * user_data, uint8_t header_id, uint16_t total_len, uint16_t data_offset, const uint8_t * data_buffer, uint16_t data_len); 78ac9a0d84SMatthias Ringwald 79ac9a0d84SMatthias Ringwald typedef enum { 80ac9a0d84SMatthias Ringwald OBEX_PARSER_OBJECT_STATE_INCOMPLETE, 81ac9a0d84SMatthias Ringwald OBEX_PARSER_OBJECT_STATE_COMPLETE, 82ac9a0d84SMatthias Ringwald OBEX_PARSER_OBJECT_STATE_OVERRUN, 83ac9a0d84SMatthias Ringwald OBEX_PARSER_OBJECT_STATE_INVALID, 84ac9a0d84SMatthias Ringwald } obex_parser_object_state_t; 85ac9a0d84SMatthias Ringwald 86ac9a0d84SMatthias Ringwald typedef enum { 87ac9a0d84SMatthias Ringwald OBEX_PARSER_HEADER_INCOMPLETE, 88ac9a0d84SMatthias Ringwald OBEX_PARSER_HEADER_COMPLETE, 89ac9a0d84SMatthias Ringwald OBEX_PARSER_HEADER_OVERRUN, 90ac9a0d84SMatthias Ringwald } obex_parser_header_state_t; 91ac9a0d84SMatthias Ringwald 92ac9a0d84SMatthias Ringwald typedef struct { 93ac9a0d84SMatthias Ringwald uint8_t opcode; 94ac9a0d84SMatthias Ringwald uint8_t response_code; 95ac9a0d84SMatthias Ringwald // Connect only 96ac9a0d84SMatthias Ringwald uint8_t obex_version_number; 97ac9a0d84SMatthias Ringwald uint16_t max_packet_length; 98ac9a0d84SMatthias Ringwald // Connect + Set Path only 99ac9a0d84SMatthias Ringwald uint8_t flags; 100ac9a0d84SMatthias Ringwald } obex_parser_operation_info_t; 101ac9a0d84SMatthias Ringwald 102ac9a0d84SMatthias Ringwald typedef struct { 103ac9a0d84SMatthias Ringwald obex_parser_callback_t callback; 104ac9a0d84SMatthias Ringwald void * user_data; 105ac9a0d84SMatthias Ringwald uint16_t packet_size; 106ac9a0d84SMatthias Ringwald uint16_t packet_pos; 107ac9a0d84SMatthias Ringwald obex_parser_state_t state; 108ac9a0d84SMatthias Ringwald uint8_t opcode; 109ac9a0d84SMatthias Ringwald uint8_t response_code; 110ac9a0d84SMatthias Ringwald uint16_t item_len; 111ac9a0d84SMatthias Ringwald uint16_t item_pos; 112ac9a0d84SMatthias Ringwald uint8_t params[6]; // for connect and set path 113ac9a0d84SMatthias Ringwald uint8_t header_id; 114ac9a0d84SMatthias Ringwald } obex_parser_t; 115ac9a0d84SMatthias Ringwald 116ac9a0d84SMatthias Ringwald /** 1173a6b6ac9SMatthias Ringwald * Callback to process chunked data 1183a6b6ac9SMatthias Ringwald * @param user_data provided in obex_parser_init 1193a6b6ac9SMatthias Ringwald * @param header_id current OBEX header ID 1203a6b6ac9SMatthias Ringwald * @param total_len of header 1213a6b6ac9SMatthias Ringwald * @param data_offset 1223a6b6ac9SMatthias Ringwald * @param data_len 1233a6b6ac9SMatthias Ringwald * @param data_buffer 1243a6b6ac9SMatthias Ringwald */ 1253a6b6ac9SMatthias Ringwald typedef void (*obex_app_param_parser_callback_t)(void * user_data, uint8_t tag_id, uint8_t total_len, uint8_t data_offset, const uint8_t * data_buffer, uint8_t data_len); 1263a6b6ac9SMatthias Ringwald 1273a6b6ac9SMatthias Ringwald typedef enum { 1283a6b6ac9SMatthias Ringwald OBEX_APP_PARAM_PARSER_PARAMS_STATE_INCOMPLETE, 1293a6b6ac9SMatthias Ringwald OBEX_APP_PARAM_PARSER_PARAMS_STATE_COMPLETE, 1303a6b6ac9SMatthias Ringwald OBEX_APP_PARAM_PARSER_PARAMS_STATE_OVERRUN, 1313a6b6ac9SMatthias Ringwald OBEX_APP_PARAM_PARSER_PARAMS_STATE_INVALID, 1323a6b6ac9SMatthias Ringwald } obex_app_param_parser_params_state_t; 1333a6b6ac9SMatthias Ringwald 1343a6b6ac9SMatthias Ringwald typedef enum { 1353a6b6ac9SMatthias Ringwald OBEX_APP_PARAM_PARSER_TAG_INCOMPLETE, 1363a6b6ac9SMatthias Ringwald OBEX_APP_PARAM_PARSER_TAG_COMPLETE, 1373a6b6ac9SMatthias Ringwald OBEX_APP_PARAM_PARSER_TAG_OVERRUN, 1383a6b6ac9SMatthias Ringwald } obex_app_param_parser_tag_state_t; 1393a6b6ac9SMatthias Ringwald 1403a6b6ac9SMatthias Ringwald typedef enum { 1413a6b6ac9SMatthias Ringwald OBEX_APP_PARAM_PARSER_STATE_W4_TYPE = 0, 1423a6b6ac9SMatthias Ringwald OBEX_APP_PARAM_PARSER_STATE_W4_LEN, 1433a6b6ac9SMatthias Ringwald OBEX_APP_PARAM_PARSER_STATE_W4_VALUE, 1443a6b6ac9SMatthias Ringwald OBEX_APP_PARAM_PARSER_STATE_COMPLETE, 1453a6b6ac9SMatthias Ringwald OBEX_APP_PARAM_PARSER_STATE_INVALID, 1463a6b6ac9SMatthias Ringwald OBEX_APP_PARAM_PARSER_STATE_OVERRUN, 1473a6b6ac9SMatthias Ringwald } obex_app_param_parser_state_t; 1483a6b6ac9SMatthias Ringwald 1493a6b6ac9SMatthias Ringwald typedef struct { 1503a6b6ac9SMatthias Ringwald obex_app_param_parser_callback_t callback; 1513a6b6ac9SMatthias Ringwald obex_app_param_parser_state_t state; 1523a6b6ac9SMatthias Ringwald void * user_data; 1533a6b6ac9SMatthias Ringwald uint16_t param_size; 1543a6b6ac9SMatthias Ringwald uint16_t param_pos; 1553a6b6ac9SMatthias Ringwald uint16_t tag_len; 1563a6b6ac9SMatthias Ringwald uint16_t tag_pos; 1573a6b6ac9SMatthias Ringwald uint8_t tag_id; 1583a6b6ac9SMatthias Ringwald } obex_app_param_parser_t; 1593a6b6ac9SMatthias Ringwald 1603a6b6ac9SMatthias Ringwald /** 161ac9a0d84SMatthias Ringwald * Initialize OBEX Parser for next OBEX request 162ac9a0d84SMatthias Ringwald * @param obex_parser 1633a6b6ac9SMatthias Ringwald * @param function to call for field data 164ac9a0d84SMatthias Ringwald * @param user_data provided to callback function 165ac9a0d84SMatthias Ringwald */ 166ac9a0d84SMatthias Ringwald void obex_parser_init_for_request(obex_parser_t * obex_parser, obex_parser_callback_t obex_parser_callback, void * user_data); 167ac9a0d84SMatthias Ringwald 168ac9a0d84SMatthias Ringwald /** 169ac9a0d84SMatthias Ringwald * Initialize OBEX Parser for next OBEX response 170ac9a0d84SMatthias Ringwald * @param obex_parser 171ac9a0d84SMatthias Ringwald * @param opcode of request - needed as responses with additional fields like connect and set path 1723a6b6ac9SMatthias Ringwald * @param function to call for field data 173ac9a0d84SMatthias Ringwald * @param user_data provided to callback function 174ac9a0d84SMatthias Ringwald */ 175ac9a0d84SMatthias Ringwald void obex_parser_init_for_response(obex_parser_t * obex_parser, uint8_t opcode, obex_parser_callback_t obex_parser_callback, void * user_data); 176ac9a0d84SMatthias Ringwald 177ac9a0d84SMatthias Ringwald /** 178ac9a0d84SMatthias Ringwald * Process OBEX data 179ac9a0d84SMatthias Ringwald * @param obex_parser 180ac9a0d84SMatthias Ringwald * @param data_len 181ac9a0d84SMatthias Ringwald * @param data_buffer 182ac9a0d84SMatthias Ringwald * @return OBEX_PARSER_OBJECT_STATE_COMPLETE if packet has been completely parsed 183ac9a0d84SMatthias Ringwald */ 184ac9a0d84SMatthias Ringwald obex_parser_object_state_t obex_parser_process_data(obex_parser_t *obex_parser, const uint8_t *data_buffer, uint16_t data_len); 185ac9a0d84SMatthias Ringwald 186ac9a0d84SMatthias Ringwald /** 187ac9a0d84SMatthias Ringwald * Get operation info for request/response packets 188ac9a0d84SMatthias Ringwald * @param obex_parser 189ac9a0d84SMatthias Ringwald * @return 190ac9a0d84SMatthias Ringwald */ 191ac9a0d84SMatthias Ringwald void obex_parser_get_operation_info(obex_parser_t * obex_parser, obex_parser_operation_info_t * obex_operation_info); 192ac9a0d84SMatthias Ringwald 193ac9a0d84SMatthias Ringwald /** 194ac9a0d84SMatthias Ringwald * Helper to collect header chunks in fixed-size header buffer 195ac9a0d84SMatthias Ringwald * @param header_buffer 196ac9a0d84SMatthias Ringwald * @param buffer_size of header_buffer 197ac9a0d84SMatthias Ringwald * @param total_len of header value 1983a6b6ac9SMatthias Ringwald * @param data_offset of chunk to store 199ac9a0d84SMatthias Ringwald * @param data_buffer 200ac9a0d84SMatthias Ringwald * @param data_len chunk length 201ac9a0d84SMatthias Ringwald * @return OBEX_PARSER_HEADER_COMPLETE when header value complete 202ac9a0d84SMatthias Ringwald */ 203ac9a0d84SMatthias Ringwald obex_parser_header_state_t obex_parser_header_store(uint8_t * header_buffer, uint16_t buffer_size, uint16_t total_len, 204ac9a0d84SMatthias Ringwald uint16_t data_offset, const uint8_t * data_buffer, uint16_t data_len); 205ac9a0d84SMatthias Ringwald 2063a6b6ac9SMatthias Ringwald /** 2073a6b6ac9SMatthias Ringwald * Initialize OBEX Application Param Parser 2083a6b6ac9SMatthias Ringwald * @param parser 2093a6b6ac9SMatthias Ringwald * @param function to call for tag data 2103a6b6ac9SMatthias Ringwald * @param param_size of OBEX_HEADER_APPLICATION_PARAMETERS header 2113a6b6ac9SMatthias Ringwald * @param user_data provided to callback function 2123a6b6ac9SMatthias Ringwald */ 213*f4a7fdb5SMatthias Ringwald void obex_app_param_parser_init(obex_app_param_parser_t * parser, obex_app_param_parser_callback_t callback, uint16_t param_size, void * user_data); 2143a6b6ac9SMatthias Ringwald 2153a6b6ac9SMatthias Ringwald /** 2163a6b6ac9SMatthias Ringwald * Process OBEX App Param data 2173a6b6ac9SMatthias Ringwald * @param parser 2183a6b6ac9SMatthias Ringwald * @param data_len 2193a6b6ac9SMatthias Ringwald * @param data_buffer 2203a6b6ac9SMatthias Ringwald * @return OBEX_APP_PARAM_PARSER_PARAMS_STATE_COMPLETE if packet has been completely parsed 2213a6b6ac9SMatthias Ringwald */ 2223a6b6ac9SMatthias Ringwald obex_app_param_parser_params_state_t obex_app_param_parser_process_data(obex_app_param_parser_t *parser, const uint8_t *data_buffer, uint16_t data_len); 2233a6b6ac9SMatthias Ringwald 2243a6b6ac9SMatthias Ringwald /** 2253a6b6ac9SMatthias Ringwald * Helper to collect tag chunks in fixed-size data buffer 2263a6b6ac9SMatthias Ringwald * @param tag_buffer 2273a6b6ac9SMatthias Ringwald * @param buffer_size of data buffer 2283a6b6ac9SMatthias Ringwald * @param total_len of tag value 2293a6b6ac9SMatthias Ringwald * @param data_offset of chunk to store 2303a6b6ac9SMatthias Ringwald * @param data_buffer 2313a6b6ac9SMatthias Ringwald * @param data_len chunk length 2323a6b6ac9SMatthias Ringwald * @return OBEX_APP_PARAM_PARSER_TAG_COMPLETE when tag complete 2333a6b6ac9SMatthias Ringwald */ 2343a6b6ac9SMatthias Ringwald 2353a6b6ac9SMatthias Ringwald obex_app_param_parser_tag_state_t obex_app_param_parser_tag_store(uint8_t * tag_buffer, uint8_t buffer_size, uint8_t total_len, 2363a6b6ac9SMatthias Ringwald uint8_t data_offset, const uint8_t * data_buffer, uint8_t data_len); 2373a6b6ac9SMatthias Ringwald 238ac9a0d84SMatthias Ringwald 239ac9a0d84SMatthias Ringwald /* API_END */ 240ac9a0d84SMatthias Ringwald 241ac9a0d84SMatthias Ringwald #if defined __cplusplus 242ac9a0d84SMatthias Ringwald } 243ac9a0d84SMatthias Ringwald #endif 244ac9a0d84SMatthias Ringwald #endif 245