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