4 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
6 * @author: Abhay Agarwal <ay.agarwal@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
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"
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"
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"
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>
63 #include "bt-internal-types.h"
65 #define MESH_CONFIG_BUFFER_MAX_LEN 100
67 static void __bt_mesh_handle_pending_msg_request_info(int result,
68 int service_function, void *param,
74 const char *descriptor;
77 static struct l_queue *pending_msg_requests;
79 struct mesh_pending_request {
80 struct l_timeout *timer;
81 const struct mesh_msg_cmd *cmd;
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" }
95 static const struct mesh_msg_cmd *__mesh_get_command(uint32_t opcode)
99 for (n = 0; n < L_ARRAY_SIZE(commands); n++) {
100 if (opcode == commands[n].opcode)
107 static const char *__mesh_get_opcode_string(uint32_t opcode)
109 const struct mesh_msg_cmd *cmd;
111 cmd = __mesh_get_command(opcode);
113 return "Unknown Command Received";
115 return cmd->descriptor;
118 static void __mesh_request_remove(void *a)
120 struct mesh_pending_request *req = a;
124 l_timeout_remove(req->timer);
128 static void __bt_mesh_wait_response_timeout(
129 struct l_timeout *timeout, void *user_data)
131 struct mesh_pending_request *req = user_data;
133 BT_INFO("Mesh: No response for \"%s\" from %4.4x\n",
134 req->cmd->descriptor, req->addr);
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));
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);
155 static void __bt_mesh_add_request(uint32_t opcode, uint16_t dest,
156 uint8_t net_uuid[], void *data)
158 struct mesh_pending_request *req;
159 const struct mesh_msg_cmd *cmd;
162 cmd = __mesh_get_command(opcode);
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);
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);
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);
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));
185 static struct mesh_pending_request *__bt_mesh_get_request_by_response(
186 uint16_t addr, uint8_t net_uuid[],
189 const struct l_queue_entry *entry;
193 BT_INFO("Mesh: Number of pending requests [%u]", l_queue_length(pending_msg_requests));
194 entry = l_queue_get_entries(pending_msg_requests);
196 for (; entry; entry = entry->next) {
197 struct mesh_pending_request *req = entry->data;
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);
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) &&
211 req->cmd->response == response)
218 bool _bt_mesh_check_pending_request(uint32_t opcode,
219 uint16_t dest, uint8_t net_uuid[])
221 const struct mesh_msg_cmd *cmd;
222 cmd = __mesh_get_command(opcode);
227 if (__bt_mesh_get_request_by_response(dest,
228 net_uuid, cmd->response)) {
229 BT_ERR("Mesh:Another command is pending\n");
235 static void __bt_mesh_send_model_msg_event(int result,
236 bluetooth_mesh_model_msg_t *evt)
238 GVariant *out_var = NULL, *param = NULL;
241 if (BLUETOOTH_ERROR_NONE == result) {
243 info = g_array_new(FALSE, FALSE, sizeof(gchar));
244 g_array_append_vals(info, evt,
245 sizeof(bluetooth_mesh_model_msg_t));
247 out_var = g_variant_new_from_data((const GVariantType *)"ay",
248 info->data, info->len,
251 param = g_variant_new("(iv)", result, out_var);
252 _bt_send_event(BT_MESH_EVENT,
253 BLUETOOTH_EVENT_MESH_MODEL_MSG_EXECUTED,
258 static void __bt_mesh_handle_pending_msg_request_info(int result,
259 int service_function, void *param, unsigned int size)
263 invocation_info_t *req_info = NULL;
265 for (l = _bt_get_invocation_list(); l != NULL; ) {
268 if (req_info == NULL ||
269 req_info->service_function != service_function)
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;
277 event = (bluetooth_mesh_model_msg_t*) param;
278 req = (bluetooth_mesh_model_msg_t*)req_info->user_data;
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;
287 __bt_mesh_send_model_msg_event(result, event);
289 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
290 g_array_append_vals(out_param, event, sizeof(bluetooth_mesh_model_msg_t));
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);
300 BT_DBG("Unknown function(%d)", service_function);
306 void _bt_mesh_msg_handler(event_mesh_message_t *event)
309 uint16_t data_len = event->data_len;
310 uint8_t *data = event->data;
312 const struct mesh_msg_cmd *cmd;
313 struct mesh_pending_request *req;
315 int result = BLUETOOTH_ERROR_NONE;
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);
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]);
328 BT_INFO("Mesh: Received %s (len %u) opcode [0x%2.2x]",
329 __mesh_get_opcode_string(opcode), data_len, opcode);
331 req = __bt_mesh_get_request_by_response(event->source,
332 event->net_uuid.uuid, (opcode & ~MESH_OPCODE_UNRELIABLE));
335 BT_INFO("Mesh: Got Request");
337 __mesh_request_remove(req);
338 l_queue_remove(pending_msg_requests, req);
342 bluetooth_mesh_model_msg_t param;
343 memset(¶m, 0x00, sizeof(bluetooth_mesh_model_msg_t));
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);
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,
357 param.appkey_idx = event->key_idx;
358 param.opcode = opcode;
359 BT_INFO("Send response");
361 switch (opcode & ~MESH_OPCODE_UNRELIABLE) {
364 case MESH_OPCODE_MODEL_GENERIC_ONOFF_STATUS: {
365 BT_INFO("Received Generic On off status");
367 BT_INFO("Mesh: Node %4.4x", event->source);
369 BT_INFO("No pending req for this status");
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");
377 BT_INFO("Request opcode do not match !");
381 __bt_mesh_handle_pending_msg_request_info(result,
382 BT_MESH_MODEL_EXECUTE_MSG, ¶m,
383 sizeof(bluetooth_mesh_model_msg_t));
387 int _bt_mesh_node_model_execute_msg(const char *app_cred, const char *sender,
388 bluetooth_mesh_model_msg_t *req)
390 int ret = OAL_STATUS_SUCCESS;
395 uint8_t buffer[MESH_CONFIG_BUFFER_MAX_LEN];
396 uint8_t msg[BLUETOOTH_MESH_MODEL_MSG_LENGTH_MAX + 1];
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;
405 /* Check pending request */
406 opcode = req->opcode;
407 if (_bt_mesh_check_pending_request(opcode, req->primary_unicast,
409 BT_ERR("Device is buzy..");
410 return BLUETOOTH_ERROR_DEVICE_BUSY;
413 _bt_mesh_util_convert_string_to_hex(req->net_uuid, strlen(req->net_uuid), net_uuid.uuid, 16);
415 appkey_idx = req->appkey_idx;
417 /* Update data buffer */
418 data_len = _bt_mesh_util_opcode_set(req->opcode, buffer);
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);
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]);
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;
438 ret = mesh_model_send_message(&net_uuid, req->primary_unicast, appkey_idx, buffer, data_len);
440 if (ret != OAL_STATUS_SUCCESS) {
441 BT_ERR("ret: %d", ret);
442 return BLUETOOTH_ERROR_INTERNAL;
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)));
449 return BLUETOOTH_ERROR_NONE;