Mesh: Add dependency on ELL & JSON-C
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / oal-mesh.c
1 /*
2  * Open Adaptation Layer (OAL)
3  *
4  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
5  *
6  * @author: Anupam Roy <anupam.r@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 #include <dlog.h>
22 #include <bluetooth.h>
23 #include "bt_mesh.h"
24
25 #include "oal-event.h"
26 #include "oal-internal.h"
27 #include "oal-manager.h"
28 #include "oal-adapter-mgr.h"
29 #include "oal-utils.h"
30 #include "oal-mesh.h"
31 #include "oal-common.h"
32
33
34 static const bt_interface_t *blued_api;
35 static const btmesh_interface_t *mesh_api;
36
37 #define CHECK_OAL_MESH_ENABLED() \
38         do { \
39                 if (mesh_api == NULL) { \
40                         BT_ERR("Mesh Not Enabled"); \
41                         return OAL_STATUS_NOT_READY; \
42                 } \
43         } while (0)
44
45 /* Forward declaration: Callbacks from HAL */
46 static void mesh_network_attached_callback(bt_status_t status,
47                 bt_mesh_token_t *token, bt_uuid_t *uuid);
48 static void mesh_network_scan_status_callback(bt_mesh_scan_state_t scan_state,
49                 bt_status_t status, bt_uuid_t *net_uuid);
50 static void mesh_network_scan_result_callback(bt_status_t status,
51                 bt_uuid_t *net_uuid, bt_mesh_scan_result_t *result);
52 static void mesh_network_provisioning_status_callback(bt_status_t status,
53                 bt_uuid_t *net_uuid, bt_uuid_t *dev_uuid);
54 static void mesh_network_provisioning_finished_callback(bt_status_t status,
55                 int reason, bt_uuid_t *net_uuid,
56                         bt_uuid_t *dev_uuid, uint16_t unicast, uint8_t count);
57 static void mesh_network_provisioning_data_requested_callback(
58                 bt_uuid_t *net_uuid, uint8_t count);
59 static void mesh_network_authentication_requested_callback(bt_uuid_t *net_uuid,
60                 bt_hal_mesh_auth_variant_e auth_type, char auth_value[]);
61 static void mesh_network_netkey_execute_callback(bt_status_t status,
62                 bt_uuid_t *net_uuid, uint8_t key_event, uint16_t netkey_idx);
63 static void mesh_network_appkey_execute_callback(bt_status_t status,
64                 bt_uuid_t *net_uuid, uint8_t key_event, uint16_t netkey_idx, uint16_t appkey_idx);
65 static void mesh_network_appkey_execute_callback(bt_status_t status,
66                 bt_uuid_t *net_uuid, uint8_t key_event, uint16_t netkey_idx, uint16_t appkey_idx);
67 static void mesh_devkey_message_received_callback(bt_uuid_t *net_uuid,
68                 uint16_t source_addr, bool is_remote_devkey,
69                         uint16_t netkey_idx, uint16_t ata_len, uint8_t *data);
70
71
72 static btmesh_callbacks_t sBluetoothMeshCallbacks = {
73         .size = sizeof(sBluetoothMeshCallbacks),
74         .network_attached_cb = mesh_network_attached_callback,
75         .scan_status_cb = mesh_network_scan_status_callback,
76         .scan_result_cb = mesh_network_scan_result_callback,
77         .provisioning_status_cb = mesh_network_provisioning_status_callback,
78         .provisioning_finished_cb = mesh_network_provisioning_finished_callback,
79         .provisioning_data_requested_cb = mesh_network_provisioning_data_requested_callback,
80         .authentication_requested_cb = mesh_network_authentication_requested_callback,
81         .netkey_execute_cb = mesh_network_netkey_execute_callback,
82         .appkey_execute_cb = mesh_network_appkey_execute_callback,
83         .devkey_msg_cb = mesh_devkey_message_received_callback,
84 };
85
86 /* Mesh HAL event handlers */
87 static void mesh_network_attached_callback(bt_status_t status,
88                 bt_mesh_token_t *token, bt_uuid_t *uuid)
89 {
90         event_mesh_network_attached_t *event = g_new0(event_mesh_network_attached_t, 1);
91
92         event->status = convert_to_oal_status(status);
93         BT_INFO("Mesh Event: Network Attached, status: [%s]",
94                 status2string(status));
95
96         memcpy(event->token, token->token, sizeof(bt_mesh_token_t));
97         memcpy(event->uuid.uuid, uuid->uu, sizeof(bt_uuid_t));
98
99         send_event_bda_trace(OAL_EVENT_MESH_NETWORK_ATTACHED,
100                 event, sizeof(event_mesh_network_attached_t), NULL);
101 }
102
103 static void mesh_network_scan_status_callback(bt_mesh_scan_state_t scan_state,
104                 bt_status_t status, bt_uuid_t *net_uuid)
105 {
106         event_mesh_scan_status_t *event_data = g_new0(event_mesh_scan_status_t, 1);
107         oal_event_t event;
108
109         event_data->status = convert_to_oal_status(status);
110         BT_INFO("Mesh Event: Scan status: [%s] state [%d]",
111                 status2string(status), scan_state);
112
113         memcpy(event_data->net_uuid.uuid, net_uuid->uu, sizeof(bt_uuid_t));
114
115         event = (BT_MESH_SCAN_STARTED == scan_state) ? \
116                 OAL_EVENT_MESH_SCAN_STARTED : OAL_EVENT_MESH_SCAN_FINISHED;
117         send_event_bda_trace(event, event_data,
118                 sizeof(event_mesh_scan_status_t), NULL);
119 }
120
121 static void mesh_network_provisioning_status_callback(bt_status_t status,
122                 bt_uuid_t *net_uuid, bt_uuid_t *dev_uuid)
123 {
124         event_mesh_provisioning_status_t *event = g_new0(event_mesh_provisioning_status_t, 1);
125
126         event->status = convert_to_oal_status(status);
127         BT_INFO("Mesh Event: Provisioning status: [%s]",
128                 status2string(status));
129
130         memcpy(event->net_uuid.uuid, net_uuid->uu, sizeof(bt_uuid_t));
131         memcpy(event->dev_uuid.uuid, dev_uuid->uu, sizeof(bt_uuid_t));
132
133         if (event->status == OAL_STATUS_SUCCESS)
134                 send_event_bda_trace(OAL_EVENT_MESH_PROVISIONING_STARTED,
135                         event, sizeof(event_mesh_provisioning_status_t), NULL);
136         else
137                 send_event_bda_trace(OAL_EVENT_MESH_PROVISIONING_FAILED,
138                         event, sizeof(event_mesh_provisioning_status_t), NULL);
139 }
140
141 static void mesh_network_provisioning_finished_callback(bt_status_t status,
142                 int reason, bt_uuid_t *net_uuid,
143                         bt_uuid_t *dev_uuid, uint16_t unicast, uint8_t count)
144 {
145         event_mesh_provisioning_finished_t *event = \
146                 g_new0(event_mesh_provisioning_finished_t, 1);
147
148         event->status = convert_to_oal_status(status);
149         event->reason = reason;
150         BT_INFO("Mesh Event: Provisioning Completed Result: [%s]",
151                 status2string(status));
152
153         memcpy(event->net_uuid.uuid, net_uuid->uu, sizeof(bt_uuid_t));
154         memcpy(event->dev_uuid.uuid, dev_uuid->uu, sizeof(bt_uuid_t));
155         event->unicast = unicast;
156         event->count = count;
157
158         send_event_bda_trace(OAL_EVENT_MESH_PROVISIONING_FINISHED,
159                 event, sizeof(event_mesh_provisioning_finished_t), NULL);
160 }
161
162 static void mesh_network_provisioning_data_requested_callback(
163                 bt_uuid_t *net_uuid, uint8_t count)
164 {
165         event_mesh_provisioning_data_requested_t *event = \
166                 g_new0(event_mesh_provisioning_data_requested_t, 1);
167
168         BT_INFO("Mesh Event: Provisioning Data requested");
169
170         memcpy(event->net_uuid.uuid, net_uuid->uu, sizeof(bt_uuid_t));
171         event->count = count;
172
173         send_event_bda_trace(OAL_EVENT_MESH_PROVISIONING_DATA_REQUESTED,
174                 event, sizeof(event_mesh_provisioning_data_requested_t), NULL);
175 }
176
177 static void mesh_network_authentication_requested_callback(bt_uuid_t *net_uuid,
178                 bt_hal_mesh_auth_variant_e auth_type,
179                         char auth_value[])
180 {
181         event_mesh_authentication_requested_t *event = \
182                 g_new0(event_mesh_authentication_requested_t, 1);
183
184         BT_INFO("Mesh Event: Authentication requested");
185
186         memcpy(event->net_uuid.uuid, net_uuid->uu, sizeof(bt_uuid_t));
187         event->auth_type = auth_type;
188         g_strlcpy(event->auth_value, auth_value, sizeof(event->auth_value));
189
190         send_event_bda_trace(OAL_EVENT_MESH_AUTHENTICATION_REQUESTED,
191                 event, sizeof(event_mesh_provisioning_data_requested_t), NULL);
192 }
193
194 static void mesh_network_netkey_execute_callback(bt_status_t status,
195                 bt_uuid_t *net_uuid, uint8_t key_event, uint16_t index)
196 {
197         event_mesh_netkey_operation_t *event = \
198                 g_new0(event_mesh_netkey_operation_t, 1);
199
200         event->status = convert_to_oal_status(status);
201         BT_INFO("Mesh Event: NetKey Execute Event");
202
203         memcpy(event->net_uuid.uuid, net_uuid->uu, sizeof(bt_uuid_t));
204         event->op = (oal_mesh_key_op_e)key_event;
205         event->key_idx = index;
206
207         send_event_bda_trace(OAL_EVENT_MESH_NETKEY_EXECUTE_EVENT,
208                 event, sizeof(event_mesh_netkey_operation_t), NULL);
209 }
210
211 static void mesh_network_appkey_execute_callback(bt_status_t status,
212                 bt_uuid_t *net_uuid, uint8_t key_event,
213                         uint16_t net_idx, uint16_t app_idx)
214 {
215         event_mesh_appkey_operation_t *event = \
216                 g_new0(event_mesh_appkey_operation_t, 1);
217
218         event->status = convert_to_oal_status(status);
219         BT_INFO("Mesh Event: AppKey Execute Event");
220
221         memcpy(event->net_uuid.uuid, net_uuid->uu, sizeof(bt_uuid_t));
222         event->op = (oal_mesh_key_op_e)key_event;
223         event->net_idx = net_idx;
224         event->app_idx = app_idx;
225
226         send_event_bda_trace(OAL_EVENT_MESH_APPKEY_EXECUTE_EVENT,
227                 event, sizeof(event_mesh_appkey_operation_t), NULL);
228 }
229
230 static void mesh_network_scan_result_callback(bt_status_t status,
231                 bt_uuid_t *net_uuid, bt_mesh_scan_result_t *result)
232 {
233         event_mesh_scan_result_t *event = g_new0(event_mesh_scan_result_t, 1);
234
235         event->status = convert_to_oal_status(status);
236         BT_INFO("Mesh Event: Scan Result status: [%s]",
237                 status2string(status));
238
239         memcpy(event->net_uuid.uuid, net_uuid->uu, sizeof(bt_uuid_t));
240         memcpy(&event->result, result, sizeof(bt_mesh_scan_result_t));
241
242         send_event_bda_trace(OAL_EVENT_MESH_SCAN_RESULT,
243                 event, sizeof(event_mesh_scan_result_t), NULL);
244 }
245
246 static void mesh_devkey_message_received_callback(bt_uuid_t *net_uuid,
247                 uint16_t source_addr,
248                         bool is_remote_devkey, uint16_t netkey_idx,
249                                 uint16_t data_len, uint8_t *data)
250 {
251         event_mesh_devkey_message_t *event = g_new0(event_mesh_devkey_message_t, 1);
252
253         BT_INFO("Mesh Event: Dev Key Message Received");
254         event->source = source_addr;
255         event->remote = is_remote_devkey;
256         event->subnet = netkey_idx;
257         event->data_len = data_len;
258         memcpy(event->net_uuid.uuid, net_uuid->uu, sizeof(bt_uuid_t));
259         memcpy(event->data, data, data_len);
260
261         send_event_bda_trace(OAL_EVENT_MESH_DEVKEY_MESSAGE_RECEIVED, event,
262                 sizeof(event_mesh_devkey_message_t), NULL);
263 }
264
265 oal_status_t mesh_enable(void)
266 {
267         int ret;
268         API_TRACE();
269
270         /* Get stack interface */
271         blued_api = (const bt_interface_t *) adapter_get_stack_interface();
272
273         if (blued_api == NULL) {
274                 BT_ERR("Stack is not initialized");
275                 return OAL_STATUS_NOT_READY;
276         }
277
278         if (mesh_api) {
279                 BT_WARN("MESH Interface is already initialized...");
280                 return OAL_STATUS_ALREADY_DONE;
281         }
282
283         mesh_api = (const btmesh_interface_t *)blued_api->get_profile_interface(BT_PROFILE_MESH_ID);
284         if (mesh_api == NULL) {
285                 BT_ERR("MESH interface failed");
286                 return OAL_STATUS_INTERNAL_ERROR;
287         }
288
289         if ((ret = mesh_api->init(&sBluetoothMeshCallbacks)) != BT_STATUS_SUCCESS) {
290                 BT_ERR("Error: Unable to initialise MESH :%s", status2string(ret));
291                 mesh_api->cleanup();
292                 mesh_api = NULL;
293                 return convert_to_oal_status(ret);
294         }
295
296         BT_INFO("MESH successfully initialized");
297         return OAL_STATUS_SUCCESS;
298 }
299
300 oal_status_t mesh_disable(void)
301 {
302         API_TRACE();
303         CHECK_OAL_MESH_ENABLED();
304
305         mesh_api->cleanup();
306
307         mesh_api = NULL;
308         return OAL_STATUS_SUCCESS;
309 }
310
311 oal_status_t mesh_register_node(oal_mesh_node_t *node,
312                 GSList *model_list, bool is_provisioner)
313 {
314         int ret = BT_STATUS_SUCCESS;
315         API_TRACE();
316         CHECK_OAL_MESH_ENABLED();
317
318         BT_INFO("Mesh: Send create network request to stack");
319         ret = mesh_api->create((bt_hal_mesh_node_t*)node, model_list, is_provisioner);
320         if (ret != BT_STATUS_SUCCESS) {
321                 BT_ERR("MESH: Create Network failed :failed: %s", status2string(ret));
322                 return convert_to_oal_status(ret);
323         }
324
325         BT_INFO("Mesh: Request sent to stack");
326         return OAL_STATUS_SUCCESS;
327 }
328
329 oal_status_t mesh_network_start_scan(oal_uuid_t* network_uuid,
330                 oal_mesh_scan_params_t *params)
331 {
332         int ret = BT_STATUS_SUCCESS;
333         API_TRACE();
334         CHECK_OAL_MESH_ENABLED();
335
336         ret = mesh_api->scan((bt_uuid_t*)network_uuid,
337                 (bt_hal_mesh_scan_param_t*)params);
338         if (ret != BT_STATUS_SUCCESS) {
339                 BT_ERR("MESH: Start Scan failed: %s", status2string(ret));
340                 return convert_to_oal_status(ret);
341         }
342
343         return OAL_STATUS_SUCCESS;
344 }
345
346 oal_status_t mesh_network_scan_cancel(oal_uuid_t* network_uuid)
347 {
348         int ret = BT_STATUS_SUCCESS;
349         API_TRACE();
350         CHECK_OAL_MESH_ENABLED();
351
352         ret = mesh_api->scan_cancel((bt_uuid_t*)network_uuid);
353         if (ret != BT_STATUS_SUCCESS) {
354                 BT_ERR("MESH: Scan Cancel failed: %s", status2string(ret));
355                 return convert_to_oal_status(ret);
356         }
357
358         return OAL_STATUS_SUCCESS;
359 }
360
361 oal_status_t mesh_network_set_provisioning_capabilities(
362                 oal_uuid_t *network_uuid,
363                          oal_mesh_capabilities_t *caps)
364 {
365         int ret = BT_STATUS_SUCCESS;
366         API_TRACE();
367         CHECK_OAL_MESH_ENABLED();
368
369         ret = mesh_api->capability((bt_uuid_t*)network_uuid,
370                 (bt_hal_mesh_prov_caps_t*)caps);
371         if (ret != BT_STATUS_SUCCESS) {
372                 BT_ERR("MESH: Set Provisioning capabilities :failed: %s",
373                         status2string(ret));
374                 return convert_to_oal_status(ret);
375         }
376
377         return OAL_STATUS_SUCCESS;
378 }
379
380 oal_status_t mesh_conf_send_message(oal_uuid_t *network_uuid,
381                 uint16_t dest, bool is_devkey_remote,
382                         uint16_t netkey_idx, uint8_t *buf, int len)
383 {
384         int ret = BT_STATUS_SUCCESS;
385         API_TRACE();
386         CHECK_OAL_MESH_ENABLED();
387
388         ret = mesh_api->config_send((bt_uuid_t*)network_uuid,
389                         dest, is_devkey_remote, netkey_idx, buf, len);
390         if (ret != BT_STATUS_SUCCESS) {
391                 BT_ERR("MESH: Configuration Message sending failed: %s",
392                         status2string(ret));
393                 return convert_to_oal_status(ret);
394         }
395
396         return OAL_STATUS_SUCCESS;
397 }
398
399 oal_status_t mesh_conf_send_key_message(oal_uuid_t *network_uuid,
400                 uint16_t dest, bool is_netkey,
401                         bool is_update, int key_idx, int netkey_idx)
402 {
403         int ret = BT_STATUS_SUCCESS;
404         API_TRACE();
405         CHECK_OAL_MESH_ENABLED();
406
407         ret = mesh_api->key_send((bt_uuid_t*)network_uuid, dest,
408                         is_netkey, is_update, key_idx, netkey_idx);
409         if (ret != BT_STATUS_SUCCESS) {
410                 BT_ERR("MESH: Key Configuration Message sending failed: %s",
411                         status2string(ret));
412                 return convert_to_oal_status(ret);
413         }
414
415         return OAL_STATUS_SUCCESS;
416 }
417
418 oal_status_t mesh_network_provision_device(oal_uuid_t* network_uuid,
419                 oal_uuid_t *dev_uuid)
420 {
421         int ret = BT_STATUS_SUCCESS;
422         API_TRACE();
423         CHECK_OAL_MESH_ENABLED();
424
425         ret = mesh_api->provision((bt_uuid_t*)network_uuid, (bt_uuid_t *)dev_uuid);
426         if (ret != BT_STATUS_SUCCESS) {
427                 BT_ERR("MESH: Device Provisioning :failed: %s",
428                         status2string(ret));
429                 return convert_to_oal_status(ret);
430         }
431
432         return OAL_STATUS_SUCCESS;
433 }
434
435 oal_status_t mesh_network_send_provisioning_data(oal_uuid_t* network_uuid,
436                 uint16_t netkey_idx, uint16_t unicast)
437 {
438         int ret = BT_STATUS_SUCCESS;
439         API_TRACE();
440         CHECK_OAL_MESH_ENABLED();
441
442         ret = mesh_api->provision_data((bt_uuid_t*)network_uuid, netkey_idx, unicast);
443         if (ret != BT_STATUS_SUCCESS) {
444                 BT_ERR("MESH: Device Provisioning :failed: %s",
445                         status2string(ret));
446                 return convert_to_oal_status(ret);
447         }
448
449         return OAL_STATUS_SUCCESS;
450 }
451
452 oal_status_t mesh_network_subnet_execute(oal_uuid_t* network_uuid,
453                 oal_mesh_key_op_e operation, uint16_t net_index)
454 {
455         int ret = BT_STATUS_SUCCESS;
456         API_TRACE();
457         CHECK_OAL_MESH_ENABLED();
458
459         ret = mesh_api->subnet_execute((bt_uuid_t*)network_uuid,
460                 (bt_mesh_key_op_e)operation, net_index);
461         if (ret != BT_STATUS_SUCCESS) {
462                 BT_ERR("MESH: Create Subnet :failed: %s", status2string(ret));
463                 return convert_to_oal_status(ret);
464         }
465
466         return OAL_STATUS_SUCCESS;
467 }
468
469 oal_status_t mesh_network_appkey_execute(oal_uuid_t* network_uuid,
470                 oal_mesh_key_op_e operation,
471                         uint16_t net_index, uint16_t app_index)
472 {
473         int ret = BT_STATUS_SUCCESS;
474         API_TRACE();
475         CHECK_OAL_MESH_ENABLED();
476
477         ret = mesh_api->appkey_execute((bt_uuid_t*)network_uuid,
478                 (bt_mesh_key_op_e)operation,
479                         net_index, app_index);
480         if (ret != BT_STATUS_SUCCESS) {
481                 BT_ERR("MESH: Create Subnet :failed: %s",
482                         status2string(ret));
483                 return convert_to_oal_status(ret);
484         }
485
486         return OAL_STATUS_SUCCESS;
487 }
488
489 oal_status_t mesh_authentication_reply(
490                 oal_mesh_variant_authentication_e auth_type,
491                         const char* auth_value)
492 {
493         int ret = BT_STATUS_SUCCESS;
494         API_TRACE();
495         CHECK_OAL_MESH_ENABLED();
496
497         ret = mesh_api->auth_reply((bt_hal_mesh_auth_variant_e)auth_type,
498                         auth_value);
499         if (ret != BT_STATUS_SUCCESS) {
500                 BT_ERR("MESH: Device Provisioning :failed: %s",
501                         status2string(ret));
502                 return convert_to_oal_status(ret);
503         }
504
505         return OAL_STATUS_SUCCESS;
506 }