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_GENERIC_ONOFF_GET, MESH_OPCODE_GENERIC_ONOFF_STATUS, "GenericOnoffGet" },
89 { MESH_OPCODE_GENERIC_ONOFF_SET, MESH_OPCODE_GENERIC_ONOFF_STATUS, "GenericOnoffSet" },
90 { MESH_OPCODE_GENERIC_ONOFF_SET_UNACK, MESH_RESPONSE_NONE, "GenericOnoffSetUnack" },
91 { MESH_OPCODE_GENERIC_ONOFF_STATUS, MESH_RESPONSE_NONE, "GenericOnoffStatus" },
92 { MESH_OPCODE_GENERIC_LEVEL_GET, MESH_OPCODE_GENERIC_LEVEL_STATUS, "GenericLevelGet" },
93 { MESH_OPCODE_GENERIC_LEVEL_SET, MESH_OPCODE_GENERIC_LEVEL_STATUS, "GenericLevelSet" },
94 { MESH_OPCODE_GENERIC_LEVEL_SET_UNACK, MESH_RESPONSE_NONE, "GenericLevelSetUnack" },
95 { MESH_OPCODE_GENERIC_LEVEL_STATUS, MESH_RESPONSE_NONE, "GenericLevelStatus" },
96 { MESH_OPCODE_GENERIC_DELTA_SET, MESH_RESPONSE_NONE, "GenericDeltaGet" },
97 { MESH_OPCODE_GENERIC_DELTA_SET_UNACK, MESH_RESPONSE_NONE, "GenericDeltaSetUnack" },
98 { MESH_OPCODE_GENERIC_MOVE_SET, MESH_RESPONSE_NONE, "GenericMoveSet" },
99 { MESH_OPCODE_GENERIC_MOVE_SET_UNACK, MESH_RESPONSE_NONE, "GenericMoveSetUnack" },
100 { MESH_OPCODE_GENERIC_DEFAULT_TRANSITION_TIME_GET, MESH_OPCODE_GENERIC_DEFAULT_TRANSITION_TIME_STATUS, "GenericTransitionTimeGet" },
101 { MESH_OPCODE_GENERIC_DEFAULT_TRANSITION_TIME_SET, MESH_OPCODE_GENERIC_DEFAULT_TRANSITION_TIME_STATUS, "GenericTransitionTimeSet" },
102 { MESH_OPCODE_GENERIC_DEFAULT_TRANSITION_TIME_SET_UNACK, MESH_RESPONSE_NONE, "GenericTransitionTimeSetUnack" },
103 { MESH_OPCODE_GENERIC_DEFAULT_TRANSITION_TIME_STATUS, MESH_RESPONSE_NONE, "GenericTransitionTimeStatus" },
104 { MESH_OPCODE_GENERIC_ONPOWERUP_GET, MESH_OPCODE_GENERIC_ONPOWERUP_STATUS, "GenericOnPowerUpGet" },
105 { MESH_OPCODE_GENERIC_ONPOWERUP_STATUS, MESH_RESPONSE_NONE, "GenericOnPowerUpStatus" },
106 { MESH_OPCODE_GENERIC_ONPOWERUP_SET, MESH_OPCODE_GENERIC_ONPOWERUP_STATUS, "GenericOnPowerUpSet" },
107 { MESH_OPCODE_GENERIC_ONPOWERUP_SET_UNACK, MESH_RESPONSE_NONE, "GenericOnPowerUpSetUnack" },
108 { MESH_OPCODE_GENERIC_POWER_LEVEL_GET, MESH_OPCODE_GENERIC_POWER_LEVEL_STATUS, "GenericPowerLevelGet" },
109 { MESH_OPCODE_GENERIC_POWER_LEVEL_SET, MESH_OPCODE_GENERIC_POWER_LEVEL_STATUS, "GenericPowerLevelSet" },
110 { MESH_OPCODE_GENERIC_POWER_LEVEL_SET_UNACK, MESH_RESPONSE_NONE, "GenericPowerLevelSetUnack" },
111 { MESH_OPCODE_GENERIC_POWER_LEVEL_STATUS, MESH_RESPONSE_NONE, "GenericPowerLevelStatus" },
112 { MESH_OPCODE_GENERIC_POWER_LAST_GET, MESH_OPCODE_GENERIC_POWER_LAST_STATUS, "GenericPowerLastGet" },
113 { MESH_OPCODE_GENERIC_POWER_LAST_STATUS, MESH_RESPONSE_NONE, "GenericPowerLastStatus" },
114 { MESH_OPCODE_GENERIC_POWER_DEFAULT_GET, MESH_OPCODE_GENERIC_POWER_DEFAULT_STATUS, "GenericPowerDefaultGet" },
115 { MESH_OPCODE_GENERIC_POWER_DEFAULT_STATUS, MESH_RESPONSE_NONE, "GenericPowerDefaultStatus" },
116 { MESH_OPCODE_GENERIC_POWER_RANGE_GET, MESH_OPCODE_GENERIC_POWER_RANGE_STATUS, "GenericPowerRangeGet" },
117 { MESH_OPCODE_GENERIC_POWER_RANGE_STATUS, MESH_RESPONSE_NONE, "GenericPowerRangeStatus" },
118 { MESH_OPCODE_GENERIC_POWER_DEFAULT_SET, MESH_OPCODE_GENERIC_POWER_DEFAULT_STATUS, "GenericPowerDefaultSet" },
119 { MESH_OPCODE_GENERIC_POWER_DEFAULT_SET_UNACK, MESH_RESPONSE_NONE, "GenericPowerDefaultSetUnack" },
120 { MESH_OPCODE_GENERIC_POWER_RANGE_SET, MESH_OPCODE_GENERIC_POWER_RANGE_STATUS, "GenericPowerRangeSet" },
121 { MESH_OPCODE_GENERIC_POWER_RANGE_SET_UNACK, MESH_RESPONSE_NONE, "GenericPowerRangeSetUnack" },
122 { MESH_OPCODE_GENERIC_BATTERY_GET, MESH_OPCODE_GENERIC_BATTERY_STATUS, "GenericBatteryGet" },
123 { MESH_OPCODE_GENERIC_BATTERY_STATUS, MESH_RESPONSE_NONE, "GenericBatteryStatus" },
124 { MESH_OPCODE_GENERIC_LOCATION_GLOBAL_GET, MESH_OPCODE_GENERIC_LOCATION_GLOBAL_STATUS, "GenericLocationGlobalGet" },
125 { MESH_OPCODE_GENERIC_LOCATION_GLOBAL_STATUS, MESH_RESPONSE_NONE, "GenericLocationGlobalStatus" },
126 { MESH_OPCODE_GENERIC_LOCATION_LOCAL_GET, MESH_OPCODE_GENERIC_LOCATION_LOCAL_STATUS, "GenericLocationLocalGet" },
127 { MESH_OPCODE_GENERIC_LOCATION_LOCAL_STATUS, MESH_RESPONSE_NONE, "GenericLocationLocalStatus" },
128 { MESH_OPCODE_GENERIC_LOCATION_GLOBAL_SET, MESH_OPCODE_GENERIC_LOCATION_GLOBAL_STATUS, "GenericLocationGlobalSet" },
129 { MESH_OPCODE_GENERIC_LOCATION_GLOBAL_SET_UNACK, MESH_RESPONSE_NONE, "GenericLocationGlobalSetUnack" },
130 { MESH_OPCODE_GENERIC_LOCATION_LOCAL_SET, MESH_OPCODE_GENERIC_LOCATION_LOCAL_STATUS, "GenericLocationLocalSet" },
131 { MESH_OPCODE_GENERIC_LOCATION_LOCAL_SET_UNACK, MESH_RESPONSE_NONE, "GenericLocationLocalSetUnack" },
132 { MESH_OPCODE_GENERIC_MANUFACTURER_PROPERTIES_GET, MESH_OPCODE_GENERIC_MANUFACTURER_PROPERTIES_STATUS, "GenericManufacturerPropertiesGet" },
133 { MESH_OPCODE_GENERIC_MANUFACTURER_PROPERTIES_STATUS, MESH_RESPONSE_NONE, "GenericManufacturerPropertiesStatus" },
134 { MESH_OPCODE_GENERIC_MANUFACTURER_PROPERTY_GET, MESH_OPCODE_GENERIC_MANUFACTURER_PROPERTY_STATUS, "GenericManufacturerPropertyGet" },
135 { MESH_OPCODE_GENERIC_MANUFACTURER_PROPERTY_SET_UNACK, MESH_RESPONSE_NONE, "GenericManufacturerPropertySetUnack" },
136 { MESH_OPCODE_GENERIC_MANUFACTURER_PROPERTY_STATUS, MESH_RESPONSE_NONE, "GenericManufacturerPropertyStatus" },
137 { MESH_OPCODE_GENERIC_ADMIN_PROPERTIES_GET, MESH_OPCODE_GENERIC_ADMIN_PROPERTIES_STATUS, "GenericAdminPropertiesGet" },
138 { MESH_OPCODE_GENERIC_ADMIN_PROPERTIES_STATUS, MESH_RESPONSE_NONE, "GenericAdminPropertiesStatus" },
139 { MESH_OPCODE_GENERIC_ADMIN_PROPERTY_GET, MESH_OPCODE_GENERIC_ADMIN_PROPERTY_STATUS, "GenericAdminPropertyGet" },
140 { MESH_OPCODE_GENERIC_ADMIN_PROPERTY_SET, MESH_OPCODE_GENERIC_ADMIN_PROPERTY_STATUS, "GenericAdminPropertySet" },
141 { MESH_OPCODE_GENERIC_ADMIN_PROPERTY_SET_UNACK, MESH_RESPONSE_NONE, "GenericAdminPropertySetUnack" },
142 { MESH_OPCODE_GENERIC_ADMIN_PROPERTY_STATUS, MESH_RESPONSE_NONE, "GenericAdminPropertyStatus" },
143 { MESH_OPCODE_GENERIC_USER_PROPERTIES_GET, MESH_OPCODE_GENERIC_USER_PROPERTIES_STATUS, "GenericUserPropertiesGet" },
144 { MESH_OPCODE_GENERIC_USER_PROPERTIES_STATUS, MESH_RESPONSE_NONE, "GenericUserPropertiesStatus" },
145 { MESH_OPCODE_GENERIC_USER_PROPERTY_GET, MESH_OPCODE_GENERIC_USER_PROPERTY_STATUS, "GenericUserPropertyGet" },
146 { MESH_OPCODE_GENERIC_USER_PROPERTY_SET, MESH_OPCODE_GENERIC_USER_PROPERTY_STATUS, "GenericUserPropertySet" },
147 { MESH_OPCODE_GENERIC_USER_PROPERTY_SET_UNACK, MESH_RESPONSE_NONE, "GenericUserPropertySetUnack" },
148 { MESH_OPCODE_GENERIC_USER_PROPERTY_STATUS, MESH_RESPONSE_NONE, "GenericUserPropertyStatus" },
149 { MESH_OPCODE_GENERIC_CLIENT_PROPERTIES_GET, MESH_OPCODE_GENERIC_CLIENT_PROPERTIES_STATUS, "GenericClientPropertiesGet" },
150 { MESH_OPCODE_GENERIC_CLIENT_PROPERTIES_STATUS, MESH_RESPONSE_NONE, "GenericClientPropertiesStatus" },
154 static const struct mesh_msg_cmd *__mesh_get_command(uint32_t opcode)
158 for (n = 0; n < L_ARRAY_SIZE(commands); n++) {
159 if (opcode == commands[n].opcode)
166 static const char *__mesh_get_opcode_string(uint32_t opcode)
168 const struct mesh_msg_cmd *cmd;
170 cmd = __mesh_get_command(opcode);
172 return "Unknown Command Received";
174 return cmd->descriptor;
177 static void __mesh_request_remove(void *a)
179 struct mesh_pending_request *req = a;
183 l_timeout_remove(req->timer);
187 static void __bt_mesh_wait_response_timeout(
188 struct l_timeout *timeout, void *user_data)
190 struct mesh_pending_request *req = user_data;
192 BT_INFO("Mesh: No response for \"%s\" from %4.4x\n",
193 req->cmd->descriptor, req->addr);
195 switch (req->cmd->opcode) {
196 case MESH_OPCODE_GENERIC_ONOFF_GET:
197 case MESH_OPCODE_GENERIC_ONOFF_SET:
198 case MESH_OPCODE_GENERIC_LEVEL_GET:
199 case MESH_OPCODE_GENERIC_LEVEL_SET:
200 case MESH_OPCODE_GENERIC_DELTA_SET:
201 case MESH_OPCODE_GENERIC_MOVE_SET:
202 case MESH_OPCODE_GENERIC_DEFAULT_TRANSITION_TIME_GET:
203 case MESH_OPCODE_GENERIC_DEFAULT_TRANSITION_TIME_SET:
204 case MESH_OPCODE_GENERIC_ONPOWERUP_GET:
205 case MESH_OPCODE_GENERIC_ONPOWERUP_STATUS:
206 case MESH_OPCODE_GENERIC_ONPOWERUP_SET:
207 case MESH_OPCODE_GENERIC_POWER_LEVEL_GET:
208 case MESH_OPCODE_GENERIC_POWER_LEVEL_SET:
209 case MESH_OPCODE_GENERIC_POWER_LAST_GET:
210 case MESH_OPCODE_GENERIC_POWER_DEFAULT_GET:
211 case MESH_OPCODE_GENERIC_POWER_RANGE_GET:
212 case MESH_OPCODE_GENERIC_POWER_DEFAULT_SET:
213 case MESH_OPCODE_GENERIC_POWER_RANGE_SET:
214 case MESH_OPCODE_GENERIC_BATTERY_GET:
215 case MESH_OPCODE_GENERIC_LOCATION_GLOBAL_GET:
216 case MESH_OPCODE_GENERIC_LOCATION_LOCAL_GET:
217 case MESH_OPCODE_GENERIC_LOCATION_GLOBAL_SET:
218 case MESH_OPCODE_GENERIC_LOCATION_LOCAL_SET:
219 case MESH_OPCODE_GENERIC_MANUFACTURER_PROPERTIES_GET:
220 case MESH_OPCODE_GENERIC_MANUFACTURER_PROPERTY_GET:
221 case MESH_OPCODE_GENERIC_MANUFACTURER_PROPERTY_SET:
222 case MESH_OPCODE_GENERIC_ADMIN_PROPERTIES_GET:
223 case MESH_OPCODE_GENERIC_ADMIN_PROPERTY_GET:
224 case MESH_OPCODE_GENERIC_ADMIN_PROPERTY_SET:
225 case MESH_OPCODE_GENERIC_USER_PROPERTIES_GET:
226 case MESH_OPCODE_GENERIC_USER_PROPERTY_GET:
227 case MESH_OPCODE_GENERIC_USER_PROPERTY_SET:
228 case MESH_OPCODE_GENERIC_CLIENT_PROPERTIES_GET:
229 /* Send event with timeout */
230 __bt_mesh_handle_pending_msg_request_info(
231 BLUETOOTH_ERROR_TIMEOUT,
232 BT_MESH_MODEL_EXECUTE_MSG, req->data,
233 sizeof(bluetooth_mesh_model_msg_t));
238 BT_INFO("Mesh: Number of pending requests [%u] Remove the req",
239 l_queue_length(pending_msg_requests));
240 l_queue_remove(pending_msg_requests, req);
241 __mesh_request_remove(req);
244 static void __bt_mesh_add_request(uint32_t opcode, uint16_t dest,
245 uint8_t net_uuid[], void *data)
247 struct mesh_pending_request *req;
248 const struct mesh_msg_cmd *cmd;
251 cmd = __mesh_get_command(opcode);
254 _bt_mesh_util_convert_hex_to_string((uint8_t *) net_uuid, 16, uuid_str,
255 BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
256 BT_INFO("Mesh: Net UUID[%s]", uuid_str);
258 BT_INFO("Mesh: Adding command opcode [0x%2.2x] response [0x%2.2x]",
259 cmd->opcode, cmd->response);
260 req = l_new(struct mesh_pending_request, 1);
264 memcpy(req->net_uuid, net_uuid, 16);
265 req->timer = l_timeout_create(MESH_DEFAULT_RESPONSE_TIMEOUT,
266 __bt_mesh_wait_response_timeout, req, NULL);
268 if (!pending_msg_requests)
269 pending_msg_requests = l_queue_new();
270 l_queue_push_tail(pending_msg_requests, req);
271 BT_INFO("Mesh: Number of pending requests [%u]", l_queue_length(pending_msg_requests));
274 static struct mesh_pending_request *__bt_mesh_get_request_by_response(
275 uint16_t addr, uint8_t net_uuid[],
278 const struct l_queue_entry *entry;
282 BT_INFO("Mesh: Number of pending requests [%u]", l_queue_length(pending_msg_requests));
283 entry = l_queue_get_entries(pending_msg_requests);
285 for (; entry; entry = entry->next) {
286 struct mesh_pending_request *req = entry->data;
288 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);
289 BT_INFO("Mesh: Current req addr [0x%4.4x] res [0x%4.4x]", addr, response);
290 _bt_mesh_util_convert_hex_to_string((uint8_t *) net_uuid, 16, uuid_str,
291 BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
292 BT_INFO("Mesh: Net UUID[%s]", uuid_str);
294 _bt_mesh_util_convert_hex_to_string((uint8_t *) req->net_uuid, 16, uuid_str1,
295 BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
296 BT_INFO("Mesh: Net UUID1[%s]", uuid_str1);
297 /* Do not compare addr - In case of group message address may not match */
298 if (!memcmp(net_uuid, req->net_uuid, 16) &&
299 req->cmd->response == response)
306 bool _bt_mesh_check_pending_msg_request(uint32_t opcode,
307 uint16_t dest, uint8_t net_uuid[])
309 const struct mesh_msg_cmd *cmd;
310 cmd = __mesh_get_command(opcode);
315 if (__bt_mesh_get_request_by_response(dest,
316 net_uuid, cmd->response)) {
317 BT_ERR("Mesh:Another command is pending\n");
323 static void __bt_mesh_send_model_msg_event(int result,
324 bluetooth_mesh_model_msg_t *evt)
326 GVariant *out_var = NULL, *param = NULL;
329 if (BLUETOOTH_ERROR_NONE == result) {
331 info = g_array_new(FALSE, FALSE, sizeof(gchar));
332 g_array_append_vals(info, evt,
333 sizeof(bluetooth_mesh_model_msg_t));
335 out_var = g_variant_new_from_data((const GVariantType *)"ay",
336 info->data, info->len,
339 param = g_variant_new("(iv)", result, out_var);
340 _bt_send_event(BT_MESH_EVENT,
341 BLUETOOTH_EVENT_MESH_MODEL_MSG_EXECUTED,
346 static void __bt_mesh_handle_pending_msg_request_info(int result,
347 int service_function, void *param, unsigned int size)
351 invocation_info_t *req_info = NULL;
353 for (l = _bt_get_invocation_list(); l != NULL; ) {
356 if (req_info == NULL ||
357 req_info->service_function != service_function)
360 switch (service_function) {
361 case BT_MESH_MODEL_EXECUTE_MSG: {
362 bluetooth_mesh_model_msg_t *event;
363 bluetooth_mesh_model_msg_t *req;
365 event = (bluetooth_mesh_model_msg_t*) param;
366 req = (bluetooth_mesh_model_msg_t*)req_info->user_data;
368 BT_DBG("Request Sender: [%s]", req_info->sender);
369 /* Match Network and Remote Node unicast*/
370 if (!g_strcmp0(event->net_uuid, req->net_uuid)) {
371 event->elem_index = req->elem_index;
374 __bt_mesh_send_model_msg_event(result, event);
376 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
377 g_array_append_vals(out_param, event, sizeof(bluetooth_mesh_model_msg_t));
379 /* Return DBUS Invocation*/
380 _bt_service_method_return(req_info->context, out_param, result);
381 _bt_free_info_from_invocation_list(req_info);
382 g_array_free(out_param, TRUE);
387 BT_DBG("Unknown function(%d)", service_function);
393 void _bt_mesh_msg_handler(event_mesh_message_t *event)
396 uint16_t data_len = event->data_len;
397 uint8_t *data = event->data;
399 struct mesh_pending_request *req;
401 int result = BLUETOOTH_ERROR_NONE;
403 if (_bt_mesh_util_opcode_get(data, data_len, &opcode, &n)) {
404 BT_INFO("Mesh: Opcode of response data [0x%2.2x], actual data len [%d]", opcode, n);
410 for (int msg_idx = 0; msg_idx < data_len; msg_idx++)
411 BT_INFO("Mesh: Message data[%d]: [%2.2X]", msg_idx, data[msg_idx]);
413 BT_INFO("Mesh: Received %s (len %u) opcode [0x%2.2x]",
414 __mesh_get_opcode_string(opcode), data_len, opcode);
416 req = __bt_mesh_get_request_by_response(event->source,
417 event->net_uuid.uuid, (opcode & ~MESH_OPCODE_UNRELIABLE));
420 BT_INFO("Mesh: Got Request");
421 __mesh_request_remove(req);
422 l_queue_remove(pending_msg_requests, req);
425 bluetooth_mesh_model_msg_t param;
426 memset(¶m, 0x00, sizeof(bluetooth_mesh_model_msg_t));
428 _bt_mesh_util_convert_hex_to_string(
429 (uint8_t *) event->net_uuid.uuid, 16, param.net_uuid,
430 BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
432 param.primary_unicast = event->source;
433 param.elem_index = 0;
434 param.appkey_idx = event->key_idx;
435 param.msg_len = data_len*2;
436 _bt_mesh_util_convert_hex_to_string(
437 (uint8_t *) data, data_len, param.msg,
440 param.appkey_idx = event->key_idx;
441 param.opcode = opcode;
442 BT_INFO("Send response");
444 __bt_mesh_handle_pending_msg_request_info(result,
445 BT_MESH_MODEL_EXECUTE_MSG, ¶m,
446 sizeof(bluetooth_mesh_model_msg_t));
450 int _bt_mesh_model_execute_msg(const char *app_cred, const char *sender,
451 bluetooth_mesh_model_msg_t *req)
453 int ret = OAL_STATUS_SUCCESS;
457 uint16_t msg_hex_len = 0;
459 uint8_t buffer[MESH_CONFIG_BUFFER_MAX_LEN];
460 uint8_t msg[BLUETOOTH_MESH_MODEL_MSG_LENGTH_MAX + 1];
462 /* If Scanning is going on */
463 if (_bt_mesh_is_provisioning() ||
464 _bt_mesh_is_scanning()) {
465 BT_ERR("Device is buzy..");
466 return BLUETOOTH_ERROR_DEVICE_BUSY;
469 /* Check pending request */
470 opcode = req->opcode;
471 if (_bt_mesh_check_pending_msg_request(opcode, req->primary_unicast,
473 BT_ERR("Device is buzy..");
474 return BLUETOOTH_ERROR_DEVICE_BUSY;
477 _bt_mesh_util_convert_string_to_hex(req->net_uuid, strlen(req->net_uuid), net_uuid.uuid, 16);
479 appkey_idx = req->appkey_idx;
481 /* Update data buffer */
482 data_len = _bt_mesh_util_opcode_set(req->opcode, buffer);
484 BT_DBG("Mesh: Model string msg opcode: 0x%2.2X msg_len: %d",
485 req->opcode, req->msg_len);
486 if (req->msg_len > 0) {
487 /* Convert Mesh msg to hex*/
488 BT_DBG("Mesh: Model string msg_len: %zd, msg: %s", strlen(req->msg), req->msg);
489 msg_hex_len = req->msg_len/2;
490 _bt_mesh_util_convert_string_to_hex(req->msg, strlen(req->msg), msg, msg_hex_len);
492 for (int msg_idx = 0; msg_idx < msg_hex_len; msg_idx++)
493 BT_DBG("Mesh: Model hex msg[%d]: msg: 0x%2.2X", msg_idx, msg[msg_idx]);
495 /* Append model msg */
496 if (msg_hex_len > 0) {
497 memcpy(buffer + data_len, msg, msg_hex_len);
498 data_len += msg_hex_len;
502 ret = mesh_model_send_message(&net_uuid, req->primary_unicast, appkey_idx, buffer, data_len);
504 if (ret != OAL_STATUS_SUCCESS) {
505 BT_ERR("ret: %d", ret);
506 return BLUETOOTH_ERROR_INTERNAL;
509 /* Queue the request with timeout */
510 __bt_mesh_add_request(opcode, req->primary_unicast, net_uuid.uuid,
511 g_memdup(req, sizeof(bluetooth_mesh_model_msg_t)));
513 return BLUETOOTH_ERROR_NONE;