Mesh: Add mesh model support
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / services / mesh / bt-service-mesh-model.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
5  *
6  * @author: Abhay Agarwal <ay.agarwal@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 <glib.h>
22 #include <dlog.h>
23 #include <fcntl.h>
24 #include <dirent.h>
25 #include <errno.h>
26 #include <limits.h>
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
30 #include <ell/ell.h>
31
32 #include "bt-service-common.h"
33 #include "bt-service-core-adapter.h"
34 #include "bt-service-event-receiver.h"
35 #include "bt-request-handler.h"
36 #include "bluetooth-api.h"
37
38 #include "bluetooth-api.h"
39 #include "bluetooth-mesh-api.h"
40 #include "bt-internal-types.h"
41 #include "bt-service-util.h"
42 #include "bt-service-common.h"
43 #include "bt-service-core-adapter.h"
44 #include "bt-service-event-receiver.h"
45 #include "bt-request-handler.h"
46 #include "bluetooth-api.h"
47 #include "bt-service-event.h"
48
49 #include "bt-service-mesh-network.h"
50 #include "bt-service-mesh-cdb.h"
51 #include "bt-service-mesh-nodes.h"
52 #include "bt-service-mesh-keys.h"
53 #include "bt-service-mesh-util.h"
54 #include "bt-service-mesh-config-client.h"
55
56 #include <oal-hardware.h>
57 #include <oal-manager.h>
58 #include <oal-event.h>
59 #include <oal-adapter-mgr.h>
60 #include <oal-device-mgr.h>
61 #include <oal-mesh.h>
62
63 #include "bt-internal-types.h"
64
65 #define MESH_CONFIG_BUFFER_MAX_LEN 100
66
67 static void __bt_mesh_handle_pending_msg_request_info(int result,
68                 int service_function, void *param,
69                         unsigned int size);
70
71 struct mesh_msg_cmd {
72         uint32_t opcode;
73         uint32_t response;
74         const char *descriptor;
75 };
76
77 static struct l_queue *pending_msg_requests;
78
79 struct mesh_pending_request {
80         struct l_timeout *timer;
81         const struct mesh_msg_cmd *cmd;
82         uint8_t net_uuid[16];
83         uint16_t addr;
84         void *data;
85 };
86
87 static struct mesh_msg_cmd commands[] = {
88         { MESH_OPCODE_MODEL_GENERIC_ONOFF_GET, MESH_OPCODE_MODEL_GENERIC_ONOFF_STATUS, "ModelGenericOnoffGet" },
89         { MESH_OPCODE_MODEL_GENERIC_ONOFF_SET, MESH_OPCODE_MODEL_GENERIC_ONOFF_STATUS, "ModelGenericOnoffSet" },
90         { MESH_OPCODE_MODEL_GENERIC_ONOFF_SET_UNACK, MESH_RESPONSE_NONE, "ModelGenericOnoffSetUnack" },
91         { MESH_OPCODE_MODEL_GENERIC_ONOFF_STATUS, MESH_RESPONSE_NONE, "ModelGenericOnoffStatus" }
92 };
93
94
95 static const struct mesh_msg_cmd *__mesh_get_command(uint32_t opcode)
96 {
97         uint32_t n;
98
99         for (n = 0; n < L_ARRAY_SIZE(commands); n++) {
100                 if (opcode == commands[n].opcode)
101                         return &commands[n];
102         }
103
104         return NULL;
105 }
106
107 static const char *__mesh_get_opcode_string(uint32_t opcode)
108 {
109         const struct mesh_msg_cmd *cmd;
110
111         cmd = __mesh_get_command(opcode);
112         if (!cmd)
113                 return "Unknown Command Received";
114
115         return cmd->descriptor;
116 }
117
118 static void __mesh_request_remove(void *a)
119 {
120         struct mesh_pending_request *req = a;
121
122         if (req->data)
123                 l_free(req->data);
124         l_timeout_remove(req->timer);
125         l_free(req);
126 }
127
128 static void __bt_mesh_wait_response_timeout(
129                 struct l_timeout *timeout, void *user_data)
130 {
131         struct mesh_pending_request *req = user_data;
132
133         BT_INFO("Mesh: No response for \"%s\" from %4.4x\n",
134                         req->cmd->descriptor, req->addr);
135
136
137         switch(req->cmd->opcode) {
138         case MESH_OPCODE_MODEL_GENERIC_ONOFF_GET:
139         case MESH_OPCODE_MODEL_GENERIC_ONOFF_SET:
140                 /* Send event with timeout */
141                  __bt_mesh_handle_pending_msg_request_info(
142                         BLUETOOTH_ERROR_TIMEOUT,
143                                 BT_MESH_MODEL_EXECUTE_MSG, req->data,
144                                         sizeof(bluetooth_mesh_model_msg_t));
145                 break;
146         default:
147                 break;
148         }
149         BT_INFO("Mesh: Number of pending requests [%u] Remove the req",
150                 l_queue_length(pending_msg_requests));
151         l_queue_remove(pending_msg_requests, req);
152         __mesh_request_remove(req);
153 }
154
155 static void __bt_mesh_add_request(uint32_t opcode, uint16_t dest,
156                         uint8_t net_uuid[], void *data)
157 {
158         struct mesh_pending_request *req;
159         const struct mesh_msg_cmd *cmd;
160         char uuid_str[33];
161
162         cmd = __mesh_get_command(opcode);
163         if (!cmd)
164                 return;
165         _bt_mesh_util_convert_hex_to_string((uint8_t *) net_uuid, 16, uuid_str,
166                 BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
167         BT_INFO("Mesh: Net UUID[%s]",uuid_str);
168
169         BT_INFO("Mesh: Adding command opcode [0x%2.2x] response [0x%2.2x]",
170                         cmd->opcode, cmd->response);
171         req = l_new(struct mesh_pending_request, 1);
172         req->cmd = cmd;
173         req->addr = dest;
174         req->data = data;
175         memcpy(req->net_uuid, net_uuid, 16);
176         req->timer = l_timeout_create(MESH_DEFAULT_RESPONSE_TIMEOUT,
177                         __bt_mesh_wait_response_timeout, req, NULL);
178
179         if (!pending_msg_requests)
180                 pending_msg_requests = l_queue_new();
181         l_queue_push_tail(pending_msg_requests, req);
182         BT_INFO("Mesh: Number of pending requests [%u]", l_queue_length(pending_msg_requests));
183 }
184
185 static struct mesh_pending_request *__bt_mesh_get_request_by_response(
186                 uint16_t addr, uint8_t net_uuid[],
187                         uint32_t response)
188 {
189         const struct l_queue_entry *entry;
190         char uuid_str[33];
191         char uuid_str1[33];
192
193         BT_INFO("Mesh: Number of pending requests [%u]", l_queue_length(pending_msg_requests));
194         entry = l_queue_get_entries(pending_msg_requests);
195
196         for (; entry; entry = entry->next) {
197                 struct mesh_pending_request *req = entry->data;
198
199                 /* Test */
200                 BT_INFO("Mesh: Req addr [0x%4.4x] req opcode [0x%4.4x] res [0x%4.4x]", req->addr, req->cmd->opcode, req->cmd->response);
201                 BT_INFO("Mesh: Current req addr [0x%4.4x] res [0x%4.4x]", addr, response);
202                 _bt_mesh_util_convert_hex_to_string((uint8_t *) net_uuid, 16, uuid_str,
203                                 BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
204                 BT_INFO("Mesh: Net UUID[%s]",uuid_str);
205
206                 _bt_mesh_util_convert_hex_to_string((uint8_t *) req->net_uuid, 16, uuid_str1,
207                                 BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
208                 BT_INFO("Mesh: Net UUID1[%s]",uuid_str1);
209                 if (!memcmp(net_uuid, req->net_uuid, 16) &&
210                                 req->addr == addr &&
211                                 req->cmd->response == response)
212                         return req;
213         }
214
215         return NULL;
216 }
217
218 bool _bt_mesh_check_pending_request(uint32_t opcode,
219                 uint16_t dest, uint8_t net_uuid[])
220 {
221         const struct mesh_msg_cmd *cmd;
222         cmd = __mesh_get_command(opcode);
223
224         if (!cmd)
225                 return false;
226
227         if (__bt_mesh_get_request_by_response(dest,
228                                 net_uuid, cmd->response)) {
229                 BT_ERR("Mesh:Another command is pending\n");
230                 return true;
231         }
232         return false;
233 }
234
235 static void __bt_mesh_send_model_msg_event(int result,
236                 bluetooth_mesh_model_msg_t *evt)
237 {
238         GVariant *out_var = NULL, *param = NULL;
239         GArray *info = NULL;
240
241         if (BLUETOOTH_ERROR_NONE == result) {
242                 /* Send event */
243                 info = g_array_new(FALSE, FALSE, sizeof(gchar));
244                 g_array_append_vals(info, evt,
245                                 sizeof(bluetooth_mesh_model_msg_t));
246
247                 out_var = g_variant_new_from_data((const GVariantType *)"ay",
248                                 info->data, info->len,
249                                 TRUE, NULL, NULL);
250
251                 param = g_variant_new("(iv)", result, out_var);
252                 _bt_send_event(BT_MESH_EVENT,
253                                 BLUETOOTH_EVENT_MESH_MODEL_MSG_EXECUTED,
254                                 param);
255         }
256 }
257
258 static void __bt_mesh_handle_pending_msg_request_info(int result,
259                 int service_function, void *param, unsigned int size)
260 {
261         GSList *l;
262         GArray *out_param;
263         invocation_info_t *req_info = NULL;
264
265         for (l = _bt_get_invocation_list(); l != NULL; ) {
266                 req_info = l->data;
267                 l = g_slist_next(l);
268                 if (req_info == NULL ||
269                                 req_info->service_function != service_function)
270                         continue;
271
272                 switch (service_function) {
273                 case BT_MESH_MODEL_EXECUTE_MSG: {
274                         bluetooth_mesh_model_msg_t *event;
275                         bluetooth_mesh_model_msg_t *req;
276
277                         event = (bluetooth_mesh_model_msg_t*) param;
278                         req = (bluetooth_mesh_model_msg_t*)req_info->user_data;
279
280                         BT_DBG("Request Sender: [%s]", req_info->sender);
281                         /* Match Network and Remote Node unicast*/
282                         if (!g_strcmp0(event->net_uuid, req->net_uuid) &&
283                                 event->primary_unicast == req->primary_unicast) {
284                                 event->elem_index = req->elem_index;
285
286                                 /* Send Event */
287                                 __bt_mesh_send_model_msg_event(result, event);
288
289                                 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
290                                 g_array_append_vals(out_param, event, sizeof(bluetooth_mesh_model_msg_t));
291
292                                 /* Return DBUS Invocation*/
293                                 _bt_service_method_return(req_info->context, out_param, result);
294                                 _bt_free_info_from_invocation_list(req_info);
295                                 g_array_free(out_param, TRUE);
296                         }
297                         break;
298                         }
299                 default:
300                         BT_DBG("Unknown function(%d)", service_function);
301                         break;
302                 }
303         }
304 }
305
306 void _bt_mesh_msg_handler(event_mesh_message_t *event)
307 {
308         uint32_t opcode;
309         uint16_t data_len = event->data_len;
310         uint8_t *data = event->data;
311         int n;
312         const struct mesh_msg_cmd *cmd;
313         struct mesh_pending_request *req;
314
315         int result = BLUETOOTH_ERROR_NONE;
316
317         if (_bt_mesh_util_opcode_get(data, data_len, &opcode, &n)) {
318                 BT_INFO("Mesh: Opcode of response data [0x%2.2x], actual data len [%d]", opcode, n);
319                 data_len -= n;
320                 data += n;
321         } else
322                 return;
323
324         for (int msg_idx = 0; msg_idx < data_len; msg_idx++ ) {
325                 BT_INFO("Mesh: Message data[%d]: [%2.2X]", msg_idx, data[msg_idx]);
326         }
327
328         BT_INFO("Mesh: Received %s (len %u) opcode [0x%2.2x]",
329                 __mesh_get_opcode_string(opcode), data_len, opcode);
330
331         req = __bt_mesh_get_request_by_response(event->source,
332                 event->net_uuid.uuid, (opcode & ~MESH_OPCODE_UNRELIABLE));
333
334         if (req) {
335                 BT_INFO("Mesh: Got Request");
336                 cmd = req->cmd;
337                 __mesh_request_remove(req);
338                 l_queue_remove(pending_msg_requests, req);
339         } else
340                 cmd = NULL;
341
342         bluetooth_mesh_model_msg_t param;
343         memset(&param, 0x00, sizeof(bluetooth_mesh_model_msg_t));
344
345         _bt_mesh_util_convert_hex_to_string(
346                 (uint8_t *) event->net_uuid.uuid, 16, param.net_uuid,
347                         BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
348
349         param.primary_unicast = event->source;
350         param.elem_index = 0;
351         param.appkey_idx = event->key_idx;
352         param.msg_len = data_len*2;
353         _bt_mesh_util_convert_hex_to_string(
354                 (uint8_t *) data, data_len, param.msg,
355                         param.msg_len + 1);
356
357         param.appkey_idx = event->key_idx;
358         param.opcode = opcode;
359         BT_INFO("Send response");
360
361         switch (opcode & ~MESH_OPCODE_UNRELIABLE) {
362                 default:
363                         return;
364         case MESH_OPCODE_MODEL_GENERIC_ONOFF_STATUS: {
365                 BT_INFO("Received Generic On off status");
366
367                 BT_INFO("Mesh: Node %4.4x", event->source);
368                 if (!cmd) {
369                         BT_INFO("No pending req for this status");
370                         break;
371                 }
372                 if (cmd->opcode == MESH_OPCODE_MODEL_GENERIC_ONOFF_GET) {
373                         BT_INFO("Mesh: Resp recvd: MESH_OPCODE_MODEL_GENERIC_ONOFF_GET");
374                 } else if (cmd->opcode == MESH_OPCODE_MODEL_GENERIC_ONOFF_SET) {
375                         BT_INFO("Mesh: Resp recvd: MESH_OPCODE_MODEL_GENERIC_ONOFF_SET");
376                 } else {
377                         BT_INFO("Request opcode do not match !");
378                 }
379         }
380         }
381         __bt_mesh_handle_pending_msg_request_info(result,
382                 BT_MESH_MODEL_EXECUTE_MSG, &param,
383                 sizeof(bluetooth_mesh_model_msg_t));
384
385 }
386
387 int _bt_mesh_node_model_execute_msg(const char *app_cred, const char *sender,
388         bluetooth_mesh_model_msg_t *req)
389 {
390         int ret = OAL_STATUS_SUCCESS;
391         uint16_t appkey_idx;
392         oal_uuid_t net_uuid;
393         uint16_t data_len;
394         uint32_t opcode = 0;
395         uint8_t buffer[MESH_CONFIG_BUFFER_MAX_LEN];
396         uint8_t msg[BLUETOOTH_MESH_MODEL_MSG_LENGTH_MAX + 1];
397
398         /* If Scanning is going on */
399         if (_bt_mesh_is_provisioning() ||
400                         _bt_mesh_is_scanning()) {
401                 BT_ERR("Device is buzy..");
402                 return BLUETOOTH_ERROR_DEVICE_BUSY;
403         }
404
405         /* Check pending request */
406         opcode = req->opcode;
407         if (_bt_mesh_check_pending_request(opcode, req->primary_unicast,
408                 net_uuid.uuid)) {
409                 BT_ERR("Device is buzy..");
410                 return BLUETOOTH_ERROR_DEVICE_BUSY;
411         }
412
413         _bt_mesh_util_convert_string_to_hex(req->net_uuid, strlen(req->net_uuid), net_uuid.uuid, 16);
414
415         appkey_idx = req->appkey_idx;
416
417         /* Update data buffer */
418         data_len = _bt_mesh_util_opcode_set(req->opcode, buffer);
419
420         BT_DBG("Mesh: Model string msg opcode: 0x%2.2X msg_len: %d",
421                 req->opcode, req->msg_len);
422         if (req->msg_len > 0) {
423                 /* Convert Mesh msg to hex*/
424                 BT_DBG("Mesh: Model string msg opcode: 0x%2.2X msg_len: %d, msg: %s",
425                         req->opcode, strlen(req->msg), req->msg);
426                 _bt_mesh_util_convert_string_to_hex(req->msg, strlen(req->msg), msg, (req->msg_len)/2);
427
428                 for (int msg_idx = 0; msg_idx < (req->msg_len)/2; msg_idx++)
429                         BT_DBG("Mesh: Model hex msg[%d]: msg: 0x%2.2X", msg_idx, msg[msg_idx]);
430
431                 /* Append model msg */
432                 if (req->msg_len > 0) {
433                         memcpy(buffer + data_len, msg, req->msg_len);
434                         data_len += req->msg_len;
435                 }
436         }
437
438         ret = mesh_model_send_message(&net_uuid, req->primary_unicast, appkey_idx, buffer, data_len);
439
440         if (ret != OAL_STATUS_SUCCESS) {
441                 BT_ERR("ret: %d", ret);
442                 return BLUETOOTH_ERROR_INTERNAL;
443         }
444
445         /* Queue the request with timeout */
446         __bt_mesh_add_request(opcode, req->primary_unicast, net_uuid.uuid,
447                         g_memdup(req, sizeof(bluetooth_mesh_model_msg_t)));
448
449         return BLUETOOTH_ERROR_NONE;
450 }