1*1e2cd7c0SMilanka Ringwald /*
2*1e2cd7c0SMilanka Ringwald * Copyright (C) 2021 BlueKitchen GmbH
3*1e2cd7c0SMilanka Ringwald *
4*1e2cd7c0SMilanka Ringwald * Redistribution and use in source and binary forms, with or without
5*1e2cd7c0SMilanka Ringwald * modification, are permitted provided that the following conditions
6*1e2cd7c0SMilanka Ringwald * are met:
7*1e2cd7c0SMilanka Ringwald *
8*1e2cd7c0SMilanka Ringwald * 1. Redistributions of source code must retain the above copyright
9*1e2cd7c0SMilanka Ringwald * notice, this list of conditions and the following disclaimer.
10*1e2cd7c0SMilanka Ringwald * 2. Redistributions in binary form must reproduce the above copyright
11*1e2cd7c0SMilanka Ringwald * notice, this list of conditions and the following disclaimer in the
12*1e2cd7c0SMilanka Ringwald * documentation and/or other materials provided with the distribution.
13*1e2cd7c0SMilanka Ringwald * 3. Neither the name of the copyright holders nor the names of
14*1e2cd7c0SMilanka Ringwald * contributors may be used to endorse or promote products derived
15*1e2cd7c0SMilanka Ringwald * from this software without specific prior written permission.
16*1e2cd7c0SMilanka Ringwald *
17*1e2cd7c0SMilanka Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
18*1e2cd7c0SMilanka Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*1e2cd7c0SMilanka Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20*1e2cd7c0SMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
21*1e2cd7c0SMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22*1e2cd7c0SMilanka Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23*1e2cd7c0SMilanka Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24*1e2cd7c0SMilanka Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25*1e2cd7c0SMilanka Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26*1e2cd7c0SMilanka Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27*1e2cd7c0SMilanka Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*1e2cd7c0SMilanka Ringwald * SUCH DAMAGE.
29*1e2cd7c0SMilanka Ringwald *
30*1e2cd7c0SMilanka Ringwald */
31*1e2cd7c0SMilanka Ringwald
32*1e2cd7c0SMilanka Ringwald #define BTSTACK_FILE__ "btstack_tlv_memory.c"
33*1e2cd7c0SMilanka Ringwald
34*1e2cd7c0SMilanka Ringwald #include <stdint.h>
35*1e2cd7c0SMilanka Ringwald #include <string.h>
36*1e2cd7c0SMilanka Ringwald #include <stdlib.h>
37*1e2cd7c0SMilanka Ringwald #include "btstack_linked_list.h"
38*1e2cd7c0SMilanka Ringwald #include "btstack_tlv.h"
39*1e2cd7c0SMilanka Ringwald #include "btstack_util.h"
40*1e2cd7c0SMilanka Ringwald #include "btstack_debug.h"
41*1e2cd7c0SMilanka Ringwald
42*1e2cd7c0SMilanka Ringwald #include "mock_btstack_tlv.h"
43*1e2cd7c0SMilanka Ringwald
44*1e2cd7c0SMilanka Ringwald #define MAX_TLV_VALUE_SIZE 200
45*1e2cd7c0SMilanka Ringwald #define DUMMY_SIZE 4
46*1e2cd7c0SMilanka Ringwald typedef struct tlv_entry {
47*1e2cd7c0SMilanka Ringwald void * next;
48*1e2cd7c0SMilanka Ringwald uint32_t tag;
49*1e2cd7c0SMilanka Ringwald uint32_t len;
50*1e2cd7c0SMilanka Ringwald uint8_t value[DUMMY_SIZE]; // dummy size
51*1e2cd7c0SMilanka Ringwald } tlv_entry_t;
52*1e2cd7c0SMilanka Ringwald
mock_btstack_tlv_find_entry(mock_btstack_tlv_t * self,uint32_t tag)53*1e2cd7c0SMilanka Ringwald static tlv_entry_t * mock_btstack_tlv_find_entry(mock_btstack_tlv_t * self, uint32_t tag){
54*1e2cd7c0SMilanka Ringwald btstack_linked_list_iterator_t it;
55*1e2cd7c0SMilanka Ringwald btstack_linked_list_iterator_init(&it, &self->entry_list);
56*1e2cd7c0SMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){
57*1e2cd7c0SMilanka Ringwald tlv_entry_t * entry = (tlv_entry_t*) btstack_linked_list_iterator_next(&it);
58*1e2cd7c0SMilanka Ringwald if (entry->tag != tag) continue;
59*1e2cd7c0SMilanka Ringwald return entry;
60*1e2cd7c0SMilanka Ringwald }
61*1e2cd7c0SMilanka Ringwald return NULL;
62*1e2cd7c0SMilanka Ringwald }
63*1e2cd7c0SMilanka Ringwald
64*1e2cd7c0SMilanka Ringwald /**
65*1e2cd7c0SMilanka Ringwald * Get Value for Tag
66*1e2cd7c0SMilanka Ringwald * @param tag
67*1e2cd7c0SMilanka Ringwald * @param buffer
68*1e2cd7c0SMilanka Ringwald * @param buffer_size
69*1e2cd7c0SMilanka Ringwald * @return size of value
70*1e2cd7c0SMilanka Ringwald */
mock_btstack_tlv_get_tag(void * context,uint32_t tag,uint8_t * buffer,uint32_t buffer_size)71*1e2cd7c0SMilanka Ringwald static int mock_btstack_tlv_get_tag(void * context, uint32_t tag, uint8_t * buffer, uint32_t buffer_size){
72*1e2cd7c0SMilanka Ringwald mock_btstack_tlv_t * self = (mock_btstack_tlv_t *) context;
73*1e2cd7c0SMilanka Ringwald tlv_entry_t * entry = mock_btstack_tlv_find_entry(self, tag);
74*1e2cd7c0SMilanka Ringwald // not found
75*1e2cd7c0SMilanka Ringwald if (!entry) return 0;
76*1e2cd7c0SMilanka Ringwald // return len if buffer = NULL
77*1e2cd7c0SMilanka Ringwald if (!buffer) return entry->len;
78*1e2cd7c0SMilanka Ringwald // otherwise copy data into buffer
79*1e2cd7c0SMilanka Ringwald uint16_t bytes_to_copy = btstack_min(buffer_size, entry->len);
80*1e2cd7c0SMilanka Ringwald memcpy(buffer, &entry->value[0], bytes_to_copy);
81*1e2cd7c0SMilanka Ringwald return bytes_to_copy;
82*1e2cd7c0SMilanka Ringwald }
83*1e2cd7c0SMilanka Ringwald
84*1e2cd7c0SMilanka Ringwald /**
85*1e2cd7c0SMilanka Ringwald * Store Tag
86*1e2cd7c0SMilanka Ringwald * @param tag
87*1e2cd7c0SMilanka Ringwald * @param data
88*1e2cd7c0SMilanka Ringwald * @param data_size
89*1e2cd7c0SMilanka Ringwald */
mock_btstack_tlv_store_tag(void * context,uint32_t tag,const uint8_t * data,uint32_t data_size)90*1e2cd7c0SMilanka Ringwald static int mock_btstack_tlv_store_tag(void * context, uint32_t tag, const uint8_t * data, uint32_t data_size){
91*1e2cd7c0SMilanka Ringwald mock_btstack_tlv_t * self = (mock_btstack_tlv_t *) context;
92*1e2cd7c0SMilanka Ringwald
93*1e2cd7c0SMilanka Ringwald // enforce arbitrary max value size
94*1e2cd7c0SMilanka Ringwald btstack_assert(data_size <= MAX_TLV_VALUE_SIZE);
95*1e2cd7c0SMilanka Ringwald
96*1e2cd7c0SMilanka Ringwald // remove old entry
97*1e2cd7c0SMilanka Ringwald tlv_entry_t * old_entry = mock_btstack_tlv_find_entry(self, tag);
98*1e2cd7c0SMilanka Ringwald if (old_entry){
99*1e2cd7c0SMilanka Ringwald btstack_linked_list_remove(&self->entry_list, (btstack_linked_item_t *) old_entry);
100*1e2cd7c0SMilanka Ringwald free(old_entry);
101*1e2cd7c0SMilanka Ringwald }
102*1e2cd7c0SMilanka Ringwald
103*1e2cd7c0SMilanka Ringwald // create new entry
104*1e2cd7c0SMilanka Ringwald uint32_t entry_size = sizeof(tlv_entry_t) - DUMMY_SIZE + data_size;
105*1e2cd7c0SMilanka Ringwald tlv_entry_t * new_entry = (tlv_entry_t *) malloc(entry_size);
106*1e2cd7c0SMilanka Ringwald if (!new_entry) return 0;
107*1e2cd7c0SMilanka Ringwald memset(new_entry, 0, entry_size);
108*1e2cd7c0SMilanka Ringwald new_entry->tag = tag;
109*1e2cd7c0SMilanka Ringwald new_entry->len = data_size;
110*1e2cd7c0SMilanka Ringwald memcpy(&new_entry->value[0], data, data_size);
111*1e2cd7c0SMilanka Ringwald
112*1e2cd7c0SMilanka Ringwald // append new entry
113*1e2cd7c0SMilanka Ringwald btstack_linked_list_add(&self->entry_list, (btstack_linked_item_t *) new_entry);
114*1e2cd7c0SMilanka Ringwald return 0;
115*1e2cd7c0SMilanka Ringwald }
116*1e2cd7c0SMilanka Ringwald
117*1e2cd7c0SMilanka Ringwald /**
118*1e2cd7c0SMilanka Ringwald * Delete Tag
119*1e2cd7c0SMilanka Ringwald * @param tag
120*1e2cd7c0SMilanka Ringwald */
mock_btstack_tlv_delete_tag(void * context,uint32_t tag)121*1e2cd7c0SMilanka Ringwald static void mock_btstack_tlv_delete_tag(void * context, uint32_t tag){
122*1e2cd7c0SMilanka Ringwald mock_btstack_tlv_t * self = (mock_btstack_tlv_t *) context;
123*1e2cd7c0SMilanka Ringwald btstack_linked_list_iterator_t it;
124*1e2cd7c0SMilanka Ringwald btstack_linked_list_iterator_init(&it, &self->entry_list);
125*1e2cd7c0SMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){
126*1e2cd7c0SMilanka Ringwald tlv_entry_t * entry = (tlv_entry_t*) btstack_linked_list_iterator_next(&it);
127*1e2cd7c0SMilanka Ringwald if (entry->tag != tag) continue;
128*1e2cd7c0SMilanka Ringwald btstack_linked_list_iterator_remove(&it);
129*1e2cd7c0SMilanka Ringwald free(entry);
130*1e2cd7c0SMilanka Ringwald return;
131*1e2cd7c0SMilanka Ringwald }
132*1e2cd7c0SMilanka Ringwald }
133*1e2cd7c0SMilanka Ringwald
134*1e2cd7c0SMilanka Ringwald static const btstack_tlv_t mock_btstack_tlv = {
135*1e2cd7c0SMilanka Ringwald /* int (*get_tag)(..); */ &mock_btstack_tlv_get_tag,
136*1e2cd7c0SMilanka Ringwald /* int (*store_tag)(..); */ &mock_btstack_tlv_store_tag,
137*1e2cd7c0SMilanka Ringwald /* void (*delete_tag)(v..); */ &mock_btstack_tlv_delete_tag,
138*1e2cd7c0SMilanka Ringwald };
139*1e2cd7c0SMilanka Ringwald
140*1e2cd7c0SMilanka Ringwald /**
141*1e2cd7c0SMilanka Ringwald * Init Tag Length Value Store
142*1e2cd7c0SMilanka Ringwald */
mock_btstack_tlv_init_instance(mock_btstack_tlv_t * self)143*1e2cd7c0SMilanka Ringwald const btstack_tlv_t * mock_btstack_tlv_init_instance(mock_btstack_tlv_t * self){
144*1e2cd7c0SMilanka Ringwald memset(self, 0, sizeof(mock_btstack_tlv_t));
145*1e2cd7c0SMilanka Ringwald return &mock_btstack_tlv;
146*1e2cd7c0SMilanka Ringwald }
147*1e2cd7c0SMilanka Ringwald
148*1e2cd7c0SMilanka Ringwald /**
149*1e2cd7c0SMilanka Ringwald * Free TLV entries
150*1e2cd7c0SMilanka Ringwald * @param self
151*1e2cd7c0SMilanka Ringwald */
mock_btstack_tlv_deinit(mock_btstack_tlv_t * self)152*1e2cd7c0SMilanka Ringwald void mock_btstack_tlv_deinit(mock_btstack_tlv_t * self){
153*1e2cd7c0SMilanka Ringwald // free all entries
154*1e2cd7c0SMilanka Ringwald btstack_linked_list_iterator_t it;
155*1e2cd7c0SMilanka Ringwald btstack_linked_list_iterator_init(&it, &self->entry_list);
156*1e2cd7c0SMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){
157*1e2cd7c0SMilanka Ringwald tlv_entry_t * entry = (tlv_entry_t*) btstack_linked_list_iterator_next(&it);
158*1e2cd7c0SMilanka Ringwald btstack_linked_list_iterator_remove(&it);
159*1e2cd7c0SMilanka Ringwald free(entry);
160*1e2cd7c0SMilanka Ringwald }
161*1e2cd7c0SMilanka Ringwald }
162