xref: /btstack/src/btstack_ltv_builder.c (revision a36ca8dc904f7fa0f8c0925f1e6a3e1580c3e990)
1*a36ca8dcSMatthias Ringwald /*
2*a36ca8dcSMatthias Ringwald  * Copyright (C) 2024 BlueKitchen GmbH
3*a36ca8dcSMatthias Ringwald  *
4*a36ca8dcSMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*a36ca8dcSMatthias Ringwald  * modification, are permitted provided that the following conditions
6*a36ca8dcSMatthias Ringwald  * are met:
7*a36ca8dcSMatthias Ringwald  *
8*a36ca8dcSMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*a36ca8dcSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*a36ca8dcSMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*a36ca8dcSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*a36ca8dcSMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*a36ca8dcSMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*a36ca8dcSMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*a36ca8dcSMatthias Ringwald  *    from this software without specific prior written permission.
16*a36ca8dcSMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*a36ca8dcSMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*a36ca8dcSMatthias Ringwald  *    monetary gain.
19*a36ca8dcSMatthias Ringwald  *
20*a36ca8dcSMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*a36ca8dcSMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*a36ca8dcSMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*a36ca8dcSMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24*a36ca8dcSMatthias Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*a36ca8dcSMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*a36ca8dcSMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*a36ca8dcSMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*a36ca8dcSMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*a36ca8dcSMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*a36ca8dcSMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*a36ca8dcSMatthias Ringwald  * SUCH DAMAGE.
32*a36ca8dcSMatthias Ringwald  *
33*a36ca8dcSMatthias Ringwald  * Please inquire about commercial licensing options at
34*a36ca8dcSMatthias Ringwald  * [email protected]
35*a36ca8dcSMatthias Ringwald  *
36*a36ca8dcSMatthias Ringwald  */
37*a36ca8dcSMatthias Ringwald 
38*a36ca8dcSMatthias Ringwald #define BTSTACK_FILE__ "btstack_ltv_builder.c"
39*a36ca8dcSMatthias Ringwald 
40*a36ca8dcSMatthias Ringwald #include "btstack_ltv_builder.h"
41*a36ca8dcSMatthias Ringwald 
42*a36ca8dcSMatthias Ringwald #include "btstack_debug.h"
43*a36ca8dcSMatthias Ringwald #include "btstack_util.h"
44*a36ca8dcSMatthias Ringwald 
45*a36ca8dcSMatthias Ringwald #include <stdint.h>
46*a36ca8dcSMatthias Ringwald #include <string.h>
47*a36ca8dcSMatthias Ringwald 
btstack_ltv_builder_increase_tag(btstack_ltv_builder_context_t * context,uint16_t size)48*a36ca8dcSMatthias Ringwald static void btstack_ltv_builder_increase_tag(btstack_ltv_builder_context_t * context, uint16_t size){
49*a36ca8dcSMatthias Ringwald     btstack_assert((context->write_pos + size) < context->size);
50*a36ca8dcSMatthias Ringwald     context->write_pos += size;
51*a36ca8dcSMatthias Ringwald     btstack_assert((((uint16_t)context->buffer[context->len_pos]) + size) <= 255);
52*a36ca8dcSMatthias Ringwald     context->buffer[context->len_pos] += size;
53*a36ca8dcSMatthias Ringwald }
54*a36ca8dcSMatthias Ringwald 
btstack_ltv_builder_init(btstack_ltv_builder_context_t * context,uint8_t * buffer,uint16_t size)55*a36ca8dcSMatthias Ringwald void btstack_ltv_builder_init(btstack_ltv_builder_context_t * context, uint8_t * buffer, uint16_t size){
56*a36ca8dcSMatthias Ringwald     btstack_assert(buffer != NULL);
57*a36ca8dcSMatthias Ringwald     context->buffer = buffer;
58*a36ca8dcSMatthias Ringwald     context->size = size;
59*a36ca8dcSMatthias Ringwald     context->write_pos = 0;
60*a36ca8dcSMatthias Ringwald }
61*a36ca8dcSMatthias Ringwald 
btstack_ltv_builder_remaining_space(btstack_ltv_builder_context_t * context)62*a36ca8dcSMatthias Ringwald uint16_t btstack_ltv_builder_remaining_space(btstack_ltv_builder_context_t * context){
63*a36ca8dcSMatthias Ringwald     return context->size - context->write_pos;
64*a36ca8dcSMatthias Ringwald }
65*a36ca8dcSMatthias Ringwald 
btstack_ltv_builder_get_length(btstack_ltv_builder_context_t * context)66*a36ca8dcSMatthias Ringwald uint16_t btstack_ltv_builder_get_length(btstack_ltv_builder_context_t * context){
67*a36ca8dcSMatthias Ringwald     return context->write_pos;
68*a36ca8dcSMatthias Ringwald }
69*a36ca8dcSMatthias Ringwald 
btstack_ltv_builder_add_tag(btstack_ltv_builder_context_t * context,uint8_t tag)70*a36ca8dcSMatthias Ringwald void btstack_ltv_builder_add_tag(btstack_ltv_builder_context_t * context, uint8_t tag){
71*a36ca8dcSMatthias Ringwald     // update write pos
72*a36ca8dcSMatthias Ringwald     btstack_assert((context->write_pos + 2) < context->size);
73*a36ca8dcSMatthias Ringwald     // track len field position
74*a36ca8dcSMatthias Ringwald     context->len_pos = context->write_pos;
75*a36ca8dcSMatthias Ringwald     // add empty tag
76*a36ca8dcSMatthias Ringwald     context->buffer[context->write_pos++] = 0;
77*a36ca8dcSMatthias Ringwald     context->buffer[context->write_pos++] = tag;
78*a36ca8dcSMatthias Ringwald }
79*a36ca8dcSMatthias Ringwald 
btstack_ltv_builder_add_08(btstack_ltv_builder_context_t * context,uint8_t value)80*a36ca8dcSMatthias Ringwald void btstack_ltv_builder_add_08(btstack_ltv_builder_context_t * context, uint8_t value){
81*a36ca8dcSMatthias Ringwald     btstack_assert(context->write_pos != 0);
82*a36ca8dcSMatthias Ringwald     uint16_t write_pos = context->write_pos;
83*a36ca8dcSMatthias Ringwald     btstack_ltv_builder_increase_tag(context, 1);
84*a36ca8dcSMatthias Ringwald     context->buffer[write_pos] = value;
85*a36ca8dcSMatthias Ringwald }
86*a36ca8dcSMatthias Ringwald 
btstack_ltv_builder_add_little_endian_16(btstack_ltv_builder_context_t * context,uint16_t value)87*a36ca8dcSMatthias Ringwald void btstack_ltv_builder_add_little_endian_16(btstack_ltv_builder_context_t * context, uint16_t value) {
88*a36ca8dcSMatthias Ringwald     btstack_assert(context->write_pos != 0);
89*a36ca8dcSMatthias Ringwald     uint16_t write_pos = context->write_pos;
90*a36ca8dcSMatthias Ringwald     btstack_ltv_builder_increase_tag(context, 2);
91*a36ca8dcSMatthias Ringwald     little_endian_store_16(context->buffer, write_pos, value);
92*a36ca8dcSMatthias Ringwald }
93*a36ca8dcSMatthias Ringwald 
btstack_ltv_builder_add_little_endian_24(btstack_ltv_builder_context_t * context,uint32_t value)94*a36ca8dcSMatthias Ringwald void btstack_ltv_builder_add_little_endian_24(btstack_ltv_builder_context_t * context, uint32_t value) {
95*a36ca8dcSMatthias Ringwald     btstack_assert(context->write_pos != 0);
96*a36ca8dcSMatthias Ringwald     uint16_t write_pos = context->write_pos;
97*a36ca8dcSMatthias Ringwald     btstack_ltv_builder_increase_tag(context, 3);
98*a36ca8dcSMatthias Ringwald     little_endian_store_24(context->buffer, write_pos, value);
99*a36ca8dcSMatthias Ringwald }
100*a36ca8dcSMatthias Ringwald 
btstack_ltv_builder_add_little_endian_32(btstack_ltv_builder_context_t * context,uint32_t value)101*a36ca8dcSMatthias Ringwald void btstack_ltv_builder_add_little_endian_32(btstack_ltv_builder_context_t * context, uint32_t value) {
102*a36ca8dcSMatthias Ringwald     btstack_assert(context->write_pos != 0);
103*a36ca8dcSMatthias Ringwald     uint16_t write_pos = context->write_pos;
104*a36ca8dcSMatthias Ringwald     btstack_ltv_builder_increase_tag(context, 4);
105*a36ca8dcSMatthias Ringwald     little_endian_store_32(context->buffer, write_pos, value);
106*a36ca8dcSMatthias Ringwald }
107*a36ca8dcSMatthias Ringwald 
btstack_ltv_builder_add_bytes(btstack_ltv_builder_context_t * context,const uint8_t * data,uint16_t length)108*a36ca8dcSMatthias Ringwald void btstack_ltv_builder_add_bytes(btstack_ltv_builder_context_t * context, const uint8_t * data, uint16_t length) {
109*a36ca8dcSMatthias Ringwald     btstack_assert(context->write_pos != 0);
110*a36ca8dcSMatthias Ringwald     btstack_assert(data != NULL);
111*a36ca8dcSMatthias Ringwald     btstack_ltv_builder_increase_tag(context, length);
112*a36ca8dcSMatthias Ringwald     memcpy(&context->buffer[context->write_pos], data, length);
113*a36ca8dcSMatthias Ringwald     context->write_pos += length;
114*a36ca8dcSMatthias Ringwald }
115*a36ca8dcSMatthias Ringwald 
btstack_ltv_builder_add_string(btstack_ltv_builder_context_t * context,const char * text)116*a36ca8dcSMatthias Ringwald void btstack_ltv_builder_add_string(btstack_ltv_builder_context_t * context, const char * text) {
117*a36ca8dcSMatthias Ringwald     uint16_t length = (uint16_t)strlen(text);
118*a36ca8dcSMatthias Ringwald     btstack_ltv_builder_add_bytes(context, (const uint8_t *) text, length);
119*a36ca8dcSMatthias Ringwald }
120