xref: /btstack/src/mesh/mesh_node.c (revision 293fd5fb21e86fbb29e9789cc0a2c06dafbbf1b3)
1 /*
2  * Copyright (C) 2019 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define BTSTACK_FILE__ "mesh_node.c"
39 
40 #include "bluetooth_company_id.h"
41 #include "mesh/mesh_foundation.h"
42 
43 #include "mesh/mesh_node.h"
44 
45 #include <stddef.h>
46 #include <string.h>
47 
48 static uint16_t primary_element_address;
49 
50 static mesh_element_t primary_element;
51 
52 static uint16_t mesh_element_index_next;
53 
54 static btstack_linked_list_t mesh_elements;
55 
56 static uint16_t mid_counter;
57 
58 static uint8_t mesh_node_device_uuid[16];
59 static int     mesh_node_have_device_uuid;
60 
61 void mesh_node_primary_element_address_set(uint16_t unicast_address){
62     primary_element_address = unicast_address;
63 }
64 
65 uint16_t mesh_node_get_primary_element_address(void){
66     return primary_element_address;
67 }
68 
69 void mesh_node_init(void){
70     // dd Primary Element to list of elements
71     mesh_node_add_element(&primary_element);
72 }
73 
74 void mesh_node_add_element(mesh_element_t * element){
75     element->element_index = mesh_element_index_next++;
76     btstack_linked_list_add_tail(&mesh_elements, (void*) element);
77 }
78 
79 uint16_t mesh_node_element_count(void){
80 	return (uint16_t) btstack_linked_list_count(&mesh_elements);
81 }
82 
83 mesh_element_t * mesh_node_get_primary_element(void){
84     return &primary_element;
85 }
86 
87 
88 void mesh_node_set_element_location(mesh_element_t * element, uint16_t location){
89     element->loc = location;
90 }
91 
92 void mesh_node_set_primary_element_location(uint16_t location){
93     mesh_node_set_element_location(&primary_element, location);
94 }
95 
96 mesh_element_t * mesh_node_element_for_index(uint16_t element_index){
97     btstack_linked_list_iterator_t it;
98     btstack_linked_list_iterator_init(&it, &mesh_elements);
99     while (btstack_linked_list_iterator_has_next(&it)){
100         mesh_element_t * element = (mesh_element_t *) btstack_linked_list_iterator_next(&it);
101         if (element->element_index != element_index) continue;
102         return element;
103     }
104     return NULL;
105 }
106 
107 mesh_element_t * mesh_node_element_for_unicast_address(uint16_t unicast_address){
108     uint16_t element_index = unicast_address - mesh_node_get_primary_element_address();
109     return mesh_node_element_for_index(element_index);
110 }
111 
112 void mesh_element_iterator_init(mesh_element_iterator_t * iterator){
113     btstack_linked_list_iterator_init(&iterator->it, &mesh_elements);
114 }
115 
116 int mesh_element_iterator_has_next(mesh_element_iterator_t * iterator){
117     return btstack_linked_list_iterator_has_next(&iterator->it);
118 }
119 
120 mesh_element_t * mesh_element_iterator_next(mesh_element_iterator_t * iterator){
121     return (mesh_element_t *) btstack_linked_list_iterator_next(&iterator->it);
122 }
123 
124 // Mesh Node Element functions
125 uint8_t mesh_access_get_element_index(mesh_model_t * mesh_model){
126     return mesh_model->element->element_index;
127 }
128 
129 uint16_t mesh_access_get_element_address(mesh_model_t * mesh_model){
130     return mesh_node_get_primary_element_address() + mesh_model->element->element_index;
131 }
132 
133 // Model Identifier utilities
134 
135 uint32_t mesh_model_get_model_identifier(uint16_t vendor_id, uint16_t model_id){
136     return (vendor_id << 16) | model_id;
137 }
138 
139 uint32_t mesh_model_get_model_identifier_bluetooth_sig(uint16_t model_id){
140     return (BLUETOOTH_COMPANY_ID_BLUETOOTH_SIG_INC << 16) | model_id;
141 }
142 
143 uint16_t mesh_model_get_model_id(uint32_t model_identifier){
144     return model_identifier & 0xFFFFu;
145 }
146 
147 uint16_t mesh_model_get_vendor_id(uint32_t model_identifier){
148     return model_identifier >> 16;
149 }
150 
151 int mesh_model_is_bluetooth_sig(uint32_t model_identifier){
152     return mesh_model_get_vendor_id(model_identifier) == BLUETOOTH_COMPANY_ID_BLUETOOTH_SIG_INC;
153 }
154 
155 mesh_model_t * mesh_model_get_configuration_server(void){
156     return mesh_model_get_by_identifier(mesh_node_get_primary_element(), mesh_model_get_model_identifier_bluetooth_sig(MESH_SIG_MODEL_ID_CONFIGURATION_SERVER));
157 }
158 
159 void mesh_model_reset_appkeys(mesh_model_t * mesh_model){
160     uint16_t i;
161     for (i=0;i<MAX_NR_MESH_APPKEYS_PER_MODEL;i++){
162         mesh_model->appkey_indices[i] = MESH_APPKEY_INVALID;
163     }
164 }
165 
166 void mesh_element_add_model(mesh_element_t * element, mesh_model_t * mesh_model){
167     // reset app keys
168     mesh_model_reset_appkeys(mesh_model);
169 
170     if (mesh_model_is_bluetooth_sig(mesh_model->model_identifier)){
171         element->models_count_sig++;
172     } else {
173         element->models_count_vendor++;
174     }
175     mesh_model->mid = mid_counter++;
176     mesh_model->element = element;
177     btstack_linked_list_add_tail(&element->models, (btstack_linked_item_t *) mesh_model);
178 }
179 
180 void mesh_model_iterator_init(mesh_model_iterator_t * iterator, mesh_element_t * element){
181     btstack_linked_list_iterator_init(&iterator->it, &element->models);
182 }
183 
184 int mesh_model_iterator_has_next(mesh_model_iterator_t * iterator){
185     return btstack_linked_list_iterator_has_next(&iterator->it);
186 }
187 
188 mesh_model_t * mesh_model_iterator_next(mesh_model_iterator_t * iterator){
189     return (mesh_model_t *) btstack_linked_list_iterator_next(&iterator->it);
190 }
191 
192 mesh_model_t * mesh_model_get_by_identifier(mesh_element_t * element, uint32_t model_identifier){
193     mesh_model_iterator_t it;
194     mesh_model_iterator_init(&it, element);
195     while (mesh_model_iterator_has_next(&it)){
196         mesh_model_t * model = mesh_model_iterator_next(&it);
197         if (model->model_identifier != model_identifier) continue;
198         return model;
199     }
200     return NULL;
201 }
202 
203 mesh_model_t * mesh_access_model_for_address_and_model_identifier(uint16_t element_address, uint32_t model_identifier, uint8_t * status){
204     mesh_element_t * element = mesh_node_element_for_unicast_address(element_address);
205     if (element == NULL){
206         *status = MESH_FOUNDATION_STATUS_INVALID_ADDRESS;
207         return NULL;
208     }
209     mesh_model_t * model = mesh_model_get_by_identifier(element, model_identifier);
210     if (model == NULL) {
211         *status = MESH_FOUNDATION_STATUS_INVALID_MODEL;
212     } else {
213         *status = MESH_FOUNDATION_STATUS_SUCCESS;
214     }
215     return model;
216 }
217 // Mesh Model Subscription
218 int mesh_model_contains_subscription(mesh_model_t * mesh_model, uint16_t address){
219     uint16_t i;
220     for (i=0;i<MAX_NR_MESH_SUBSCRIPTION_PER_MODEL;i++){
221         if (mesh_model->subscriptions[i] == address) return 1;
222     }
223     return 0;
224 }
225 
226 void mesh_node_set_device_uuid(const uint8_t * device_uuid){
227     memcpy(mesh_node_device_uuid, device_uuid, 16);
228     mesh_node_have_device_uuid = 1;
229 }
230 
231 /**
232  * @brief Get Device UUID
233  */
234 const uint8_t * mesh_node_get_device_uuid(void){
235     if (mesh_node_have_device_uuid == 0) return NULL;
236     return mesh_node_device_uuid;
237 }
238 
239