1 /*
2 * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8 #include <errno.h>
9
10 #include "btc_ble_mesh_time_scene_model.h"
11
12 #include "mesh_config.h"
13 #include "model_opcode.h"
14
15 #if CONFIG_BLE_MESH_TIME_SCENE_CLIENT
16 #include "time_scene_client.h"
17
18 /* The followings are the macro definitions of Time Scene client
19 * model message length, and a message is composed of 3 parts:
20 * Opcode + Payload + MIC
21 */
22 /* Time client messages length */
23 #define BLE_MESH_TIME_SET_MSG_LEN (1 + 10 + 4)
24 #define BLE_MESH_TIME_ZONE_SET_MSG_LEN (2 + 6 + 4)
25 #define BLE_MESH_TAI_UTC_DELTA_SET_MSG_LEN (2 + 7 + 4)
26 #define BLE_MESH_TIME_ROLE_SET_MSG_LEN (2 + 1 + 4)
27
28 /* Scene client messages length */
29 #define BLE_MESH_SCENE_STORE_MSG_LEN (2 + 2 + 4)
30 #define BLE_MESH_SCENE_RECALL_MSG_LEN (2 + 5 + 4)
31 #define BLE_MESH_SCENE_GET_MSG_LEN (2 + 0 + 4)
32 #define BLE_MESH_SCENE_REGISTER_GET_MSG_LEN (2 + 0 + 4)
33 #define BLE_MESH_SCENE_DELETE_MSG_LEN (2 + 2 + 4)
34
35 /* Scheduler client messages length */
36 #define BLE_MESH_SCHEDULER_ACT_GET_MSG_LEN (2 + 1 + 4)
37 #define BLE_MESH_SCHEDULER_ACT_SET_MSG_LEN (1 + 10 + 4)
38
39 #define BLE_MESH_SCENE_GET_STATE_MSG_LEN (2 + 1 + 4)
40 #define BLE_MESH_SCENE_ACT_STATE_MSG_LEN (2 + 2 + 4)
41
42 static const bt_mesh_client_op_pair_t time_scene_op_pair[] = {
43 { BLE_MESH_MODEL_OP_TIME_GET, BLE_MESH_MODEL_OP_TIME_STATUS },
44 { BLE_MESH_MODEL_OP_TIME_SET, BLE_MESH_MODEL_OP_TIME_STATUS },
45 { BLE_MESH_MODEL_OP_TIME_ZONE_GET, BLE_MESH_MODEL_OP_TIME_ZONE_STATUS },
46 { BLE_MESH_MODEL_OP_TIME_ZONE_SET, BLE_MESH_MODEL_OP_TIME_ZONE_STATUS },
47 { BLE_MESH_MODEL_OP_TAI_UTC_DELTA_GET, BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS },
48 { BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET, BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS },
49 { BLE_MESH_MODEL_OP_TIME_ROLE_GET, BLE_MESH_MODEL_OP_TIME_ROLE_STATUS },
50 { BLE_MESH_MODEL_OP_TIME_ROLE_SET, BLE_MESH_MODEL_OP_TIME_ROLE_STATUS },
51 { BLE_MESH_MODEL_OP_SCENE_STORE, BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS },
52 { BLE_MESH_MODEL_OP_SCENE_RECALL, BLE_MESH_MODEL_OP_SCENE_STATUS },
53 { BLE_MESH_MODEL_OP_SCENE_GET, BLE_MESH_MODEL_OP_SCENE_STATUS },
54 { BLE_MESH_MODEL_OP_SCENE_REGISTER_GET, BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS },
55 { BLE_MESH_MODEL_OP_SCENE_DELETE, BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS },
56 { BLE_MESH_MODEL_OP_SCHEDULER_GET, BLE_MESH_MODEL_OP_SCHEDULER_STATUS },
57 { BLE_MESH_MODEL_OP_SCHEDULER_ACT_GET, BLE_MESH_MODEL_OP_SCHEDULER_ACT_STATUS },
58 { BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET, BLE_MESH_MODEL_OP_SCHEDULER_ACT_STATUS },
59 };
60
61 static bt_mesh_mutex_t time_scene_client_lock;
62
bt_mesh_time_scene_client_mutex_new(void)63 static inline void bt_mesh_time_scene_client_mutex_new(void)
64 {
65 if (!time_scene_client_lock.mutex) {
66 bt_mesh_mutex_create(&time_scene_client_lock);
67 }
68 }
69
70 #if CONFIG_BLE_MESH_DEINIT
bt_mesh_time_scene_client_mutex_free(void)71 static inline void bt_mesh_time_scene_client_mutex_free(void)
72 {
73 bt_mesh_mutex_free(&time_scene_client_lock);
74 }
75 #endif /* CONFIG_BLE_MESH_DEINIT */
76
bt_mesh_time_scene_client_lock(void)77 static inline void bt_mesh_time_scene_client_lock(void)
78 {
79 bt_mesh_mutex_lock(&time_scene_client_lock);
80 }
81
bt_mesh_time_scene_client_unlock(void)82 static inline void bt_mesh_time_scene_client_unlock(void)
83 {
84 bt_mesh_mutex_unlock(&time_scene_client_lock);
85 }
86
timeout_handler(struct k_work * work)87 static void timeout_handler(struct k_work *work)
88 {
89 struct k_delayed_work *timer = NULL;
90 bt_mesh_client_node_t *node = NULL;
91 struct bt_mesh_msg_ctx ctx = {0};
92 uint32_t opcode = 0U;
93
94 BT_WARN("Receive time scene status message timeout");
95
96 bt_mesh_time_scene_client_lock();
97
98 timer = CONTAINER_OF(work, struct k_delayed_work, work);
99
100 if (timer && !k_delayed_work_free(timer)) {
101 node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
102 if (node) {
103 memcpy(&ctx, &node->ctx, sizeof(ctx));
104 opcode = node->opcode;
105 bt_mesh_client_free_node(node);
106 bt_mesh_time_scene_client_cb_evt_to_btc(
107 opcode, BTC_BLE_MESH_EVT_TIME_SCENE_CLIENT_TIMEOUT, ctx.model, &ctx, NULL, 0);
108 }
109 }
110
111 bt_mesh_time_scene_client_unlock();
112
113 return;
114 }
115
time_scene_status(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)116 static void time_scene_status(struct bt_mesh_model *model,
117 struct bt_mesh_msg_ctx *ctx,
118 struct net_buf_simple *buf)
119 {
120 bt_mesh_client_node_t *node = NULL;
121 uint8_t *val = NULL;
122 uint8_t evt = 0xFF;
123 size_t len = 0U;
124
125 BT_DBG("len %d, bytes %s", buf->len, bt_hex(buf->data, buf->len));
126
127 switch (ctx->recv_op) {
128 case BLE_MESH_MODEL_OP_TIME_STATUS: {
129 struct bt_mesh_time_status *status = NULL;
130 if (buf->len != 5 && buf->len != 10) {
131 BT_ERR("Invalid Time Status length %d", buf->len);
132 return;
133 }
134 status = bt_mesh_calloc(sizeof(struct bt_mesh_time_status));
135 if (!status) {
136 BT_ERR("%s, Out of memory", __func__);
137 return;
138 }
139 memcpy(status->tai_seconds, buf->data, 5);
140 net_buf_simple_pull(buf, 5);
141 status->sub_second = net_buf_simple_pull_u8(buf);
142 status->uncertainty = net_buf_simple_pull_u8(buf);
143 uint16_t temp = net_buf_simple_pull_le16(buf);
144 status->time_authority = temp & BIT(0);
145 status->tai_utc_delta = temp >> 15;
146 status->time_zone_offset = net_buf_simple_pull_u8(buf);
147 val = (uint8_t *)status;
148 len = sizeof(struct bt_mesh_time_status);
149 break;
150 }
151 case BLE_MESH_MODEL_OP_TIME_ZONE_STATUS: {
152 struct bt_mesh_time_zone_status *status = NULL;
153 if (buf->len != 7) {
154 BT_ERR("Invalid Time Zone Status length %d", buf->len);
155 return;
156 }
157 status = bt_mesh_calloc(sizeof(struct bt_mesh_time_zone_status));
158 if (!status) {
159 BT_ERR("%s, Out of memory", __func__);
160 return;
161 }
162 status->time_zone_offset_curr = net_buf_simple_pull_u8(buf);
163 status->time_zone_offset_new = net_buf_simple_pull_u8(buf);
164 memcpy(status->tai_zone_change, buf->data, 5);
165 net_buf_simple_pull(buf, 5);
166 val = (uint8_t *)status;
167 len = sizeof(struct bt_mesh_time_zone_status);
168 break;
169 }
170 case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS: {
171 struct bt_mesh_tai_utc_delta_status *status = NULL;
172 if (buf->len != 9) {
173 BT_ERR("Invalid TAI UTC Delta Status length %d", buf->len);
174 return;
175 }
176 status = bt_mesh_calloc(sizeof(struct bt_mesh_tai_utc_delta_status));
177 if (!status) {
178 BT_ERR("%s, Out of memory", __func__);
179 return;
180 }
181 uint16_t temp = net_buf_simple_pull_le16(buf);
182 status->tai_utc_delta_curr = temp & BIT_MASK(15);
183 status->padding_1 = (temp >> 15) & BIT(0);
184 temp = net_buf_simple_pull_le16(buf);
185 status->tai_utc_delta_new = temp & BIT_MASK(15);
186 status->padding_2 = (temp >> 15) & BIT(0);
187 memcpy(status->tai_delta_change, buf->data, 5);
188 net_buf_simple_pull(buf, 5);
189 val = (uint8_t *)status;
190 len = sizeof(struct bt_mesh_tai_utc_delta_status);
191 break;
192 }
193 case BLE_MESH_MODEL_OP_TIME_ROLE_STATUS: {
194 struct bt_mesh_time_role_status *status = NULL;
195 if (buf->len != 1) {
196 BT_ERR("Invalid Time Role Status length %d", buf->len);
197 return;
198 }
199 status = bt_mesh_calloc(sizeof(struct bt_mesh_time_role_status));
200 if (!status) {
201 BT_ERR("%s, Out of memory", __func__);
202 return;
203 }
204 status->time_role = net_buf_simple_pull_u8(buf);
205 val = (uint8_t *)status;
206 len = sizeof(struct bt_mesh_time_role_status);
207 break;
208 }
209 case BLE_MESH_MODEL_OP_SCENE_STATUS: {
210 struct bt_mesh_scene_status *status = NULL;
211 if (buf->len != 3 && buf->len != 6) {
212 BT_ERR("Invalid Scene Status length %d", buf->len);
213 return;
214 }
215 status = bt_mesh_calloc(sizeof(struct bt_mesh_scene_status));
216 if (!status) {
217 BT_ERR("%s, Out of memory", __func__);
218 return;
219 }
220 status->status_code = net_buf_simple_pull_u8(buf);
221 status->current_scene = net_buf_simple_pull_le16(buf);
222 if (buf->len) {
223 status->op_en = true;
224 status->target_scene = net_buf_simple_pull_le16(buf);
225 status->remain_time = net_buf_simple_pull_u8(buf);
226 }
227 val = (uint8_t *)status;
228 len = sizeof(struct bt_mesh_scene_status);
229 break;
230 }
231 case BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS: {
232 struct bt_mesh_scene_register_status *status = NULL;
233 status = bt_mesh_calloc(sizeof(struct bt_mesh_scene_register_status));
234 if (!status) {
235 BT_ERR("%s, Out of memory", __func__);
236 return;
237 }
238 status->status_code = net_buf_simple_pull_u8(buf);
239 status->current_scene = net_buf_simple_pull_le16(buf);
240 status->scenes = bt_mesh_alloc_buf(buf->len);
241 if (!status->scenes) {
242 BT_ERR("%s, Out of memory", __func__);
243 bt_mesh_free(status);
244 return;
245 }
246 net_buf_simple_add_mem(status->scenes, buf->data, buf->len);
247 val = (uint8_t *)status;
248 len = sizeof(struct bt_mesh_scene_register_status);
249 break;
250 }
251 case BLE_MESH_MODEL_OP_SCHEDULER_STATUS: {
252 struct bt_mesh_scheduler_status *status = NULL;
253 if (buf->len != 2) {
254 BT_ERR("Invalid Scheduler Status length %d", buf->len);
255 return;
256 }
257 status = bt_mesh_calloc(sizeof(struct bt_mesh_scheduler_status));
258 if (!status) {
259 BT_ERR("%s, Out of memory", __func__);
260 return;
261 }
262 status->schedules = net_buf_simple_pull_le16(buf);
263 val = (uint8_t *)status;
264 len = sizeof(struct bt_mesh_scheduler_status);
265 break;
266 }
267 case BLE_MESH_MODEL_OP_SCHEDULER_ACT_STATUS: {
268 struct bt_mesh_scheduler_act_status *status = NULL;
269 if (buf->len != 10) {
270 BT_ERR("Invalid Scheduler Action Status length %d", buf->len);
271 return;
272 }
273 status = bt_mesh_calloc(sizeof(struct bt_mesh_scheduler_act_status));
274 if (!status) {
275 BT_ERR("%s, Out of memory", __func__);
276 return;
277 }
278 memcpy(status, buf->data, offsetof(struct bt_mesh_scheduler_act_status, scene_number));
279 net_buf_simple_pull(buf, offsetof(struct bt_mesh_scheduler_act_status, scene_number));
280 status->scene_number = net_buf_simple_pull_le16(buf);
281 val = (uint8_t *)status;
282 len = sizeof(struct bt_mesh_scheduler_act_status);
283 break;
284 }
285 default:
286 BT_ERR("Invalid Time Scene Status opcode 0x%04x", ctx->recv_op);
287 return;
288 }
289
290 buf->data = val;
291 buf->len = len;
292
293 bt_mesh_time_scene_client_lock();
294
295 node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true);
296 if (!node) {
297 BT_DBG("Unexpected Time Scene Status 0x%04x", ctx->recv_op);
298 } else {
299 switch (node->opcode) {
300 case BLE_MESH_MODEL_OP_TIME_GET:
301 case BLE_MESH_MODEL_OP_TIME_ZONE_GET:
302 case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_GET:
303 case BLE_MESH_MODEL_OP_TIME_ROLE_GET:
304 case BLE_MESH_MODEL_OP_SCENE_GET:
305 case BLE_MESH_MODEL_OP_SCENE_REGISTER_GET:
306 case BLE_MESH_MODEL_OP_SCHEDULER_GET:
307 case BLE_MESH_MODEL_OP_SCHEDULER_ACT_GET:
308 evt = BTC_BLE_MESH_EVT_TIME_SCENE_CLIENT_GET_STATE;
309 break;
310 case BLE_MESH_MODEL_OP_TIME_SET:
311 case BLE_MESH_MODEL_OP_TIME_ZONE_SET:
312 case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET:
313 case BLE_MESH_MODEL_OP_TIME_ROLE_SET:
314 case BLE_MESH_MODEL_OP_SCENE_STORE:
315 case BLE_MESH_MODEL_OP_SCENE_RECALL:
316 case BLE_MESH_MODEL_OP_SCENE_DELETE:
317 case BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET:
318 evt = BTC_BLE_MESH_EVT_TIME_SCENE_CLIENT_SET_STATE;
319 break;
320 default:
321 break;
322 }
323
324 if (!k_delayed_work_free(&node->timer)) {
325 uint32_t opcode = node->opcode;
326 bt_mesh_client_free_node(node);
327 bt_mesh_time_scene_client_cb_evt_to_btc(opcode, evt, model, ctx, val, len);
328 }
329 }
330
331 bt_mesh_time_scene_client_unlock();
332
333 switch (ctx->recv_op) {
334 case BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS: {
335 struct bt_mesh_scene_register_status *status;
336 status = (struct bt_mesh_scene_register_status *)val;
337 bt_mesh_free_buf(status->scenes);
338 break;
339 }
340 default:
341 break;
342 }
343
344 bt_mesh_free(val);
345
346 return;
347 }
348
349 const struct bt_mesh_model_op bt_mesh_time_cli_op[] = {
350 { BLE_MESH_MODEL_OP_TIME_STATUS, 5, time_scene_status },
351 { BLE_MESH_MODEL_OP_TIME_ZONE_STATUS, 7, time_scene_status },
352 { BLE_MESH_MODEL_OP_TAI_UTC_DELTA_STATUS, 9, time_scene_status },
353 { BLE_MESH_MODEL_OP_TIME_ROLE_STATUS, 1, time_scene_status },
354 BLE_MESH_MODEL_OP_END,
355 };
356
357 const struct bt_mesh_model_op bt_mesh_scene_cli_op[] = {
358 { BLE_MESH_MODEL_OP_SCENE_STATUS, 3, time_scene_status },
359 { BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS, 3, time_scene_status },
360 BLE_MESH_MODEL_OP_END,
361 };
362
363 const struct bt_mesh_model_op bt_mesh_scheduler_cli_op[] = {
364 { BLE_MESH_MODEL_OP_SCHEDULER_STATUS, 2, time_scene_status },
365 { BLE_MESH_MODEL_OP_SCHEDULER_ACT_STATUS, 10, time_scene_status },
366 BLE_MESH_MODEL_OP_END,
367 };
368
time_scene_get_state(bt_mesh_client_common_param_t * common,void * value)369 static int time_scene_get_state(bt_mesh_client_common_param_t *common, void *value)
370 {
371 NET_BUF_SIMPLE_DEFINE(msg, BLE_MESH_SCENE_GET_STATE_MSG_LEN);
372
373 bt_mesh_model_msg_init(&msg, common->opcode);
374
375 if (value) {
376 switch (common->opcode) {
377 case BLE_MESH_MODEL_OP_SCHEDULER_ACT_GET: {
378 struct bt_mesh_scheduler_act_get *get;
379 get = (struct bt_mesh_scheduler_act_get *)value;
380 net_buf_simple_add_u8(&msg, get->index);
381 break;
382 }
383 default:
384 BT_DBG("No parameters for Time Scene Get 0x%04x", common->opcode);
385 break;
386 }
387 }
388
389 return bt_mesh_client_send_msg(common, &msg, true, timeout_handler);
390 }
391
time_scene_set_state(bt_mesh_client_common_param_t * common,void * value,uint16_t value_len,bool need_ack)392 static int time_scene_set_state(bt_mesh_client_common_param_t *common,
393 void *value, uint16_t value_len, bool need_ack)
394 {
395 struct net_buf_simple *msg = NULL;
396 int err = 0;
397
398 msg = bt_mesh_alloc_buf(value_len);
399 if (!msg) {
400 BT_ERR("%s, Out of memory", __func__);
401 return -ENOMEM;
402 }
403
404 bt_mesh_model_msg_init(msg, common->opcode);
405
406 switch (common->opcode) {
407 case BLE_MESH_MODEL_OP_TIME_SET: {
408 struct bt_mesh_time_set *set;
409 set = (struct bt_mesh_time_set *)value;
410 net_buf_simple_add_mem(msg, set->tai_seconds, 5);
411 net_buf_simple_add_u8(msg, set->sub_second);
412 net_buf_simple_add_u8(msg, set->uncertainty);
413 net_buf_simple_add_le16(msg, set->tai_utc_delta << 1 | set->time_authority);
414 net_buf_simple_add_u8(msg, set->time_zone_offset);
415 break;
416 }
417 case BLE_MESH_MODEL_OP_TIME_ZONE_SET: {
418 struct bt_mesh_time_zone_set *set;
419 set = (struct bt_mesh_time_zone_set *)value;
420 net_buf_simple_add_u8(msg, set->time_zone_offset_new);
421 net_buf_simple_add_mem(msg, set->tai_zone_change, 5);
422 break;
423 }
424 case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET: {
425 struct bt_mesh_tai_utc_delta_set *set;
426 set = (struct bt_mesh_tai_utc_delta_set *)value;
427 net_buf_simple_add_le16(msg, set->padding << 15 | set->tai_utc_delta_new);
428 net_buf_simple_add_mem(msg, set->tai_delta_change, 5);
429 break;
430 }
431 case BLE_MESH_MODEL_OP_TIME_ROLE_SET: {
432 struct bt_mesh_time_role_set *set;
433 set = (struct bt_mesh_time_role_set *)value;
434 net_buf_simple_add_u8(msg, set->time_role);
435 break;
436 }
437 case BLE_MESH_MODEL_OP_SCENE_STORE:
438 case BLE_MESH_MODEL_OP_SCENE_STORE_UNACK: {
439 struct bt_mesh_scene_store *set;
440 set = (struct bt_mesh_scene_store *)value;
441 net_buf_simple_add_le16(msg, set->scene_number);
442 break;
443 }
444 case BLE_MESH_MODEL_OP_SCENE_RECALL:
445 case BLE_MESH_MODEL_OP_SCENE_RECALL_UNACK: {
446 struct bt_mesh_scene_recall *set;
447 set = (struct bt_mesh_scene_recall *)value;
448 net_buf_simple_add_le16(msg, set->scene_number);
449 net_buf_simple_add_u8(msg, set->tid);
450 if (set->op_en) {
451 net_buf_simple_add_u8(msg, set->trans_time);
452 net_buf_simple_add_u8(msg, set->delay);
453 }
454 break;
455 }
456 case BLE_MESH_MODEL_OP_SCENE_DELETE:
457 case BLE_MESH_MODEL_OP_SCENE_DELETE_UNACK: {
458 struct bt_mesh_scene_delete *set;
459 set = (struct bt_mesh_scene_delete *)value;
460 net_buf_simple_add_le16(msg, set->scene_number);
461 break;
462 }
463 case BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET:
464 case BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET_UNACK: {
465 struct bt_mesh_scheduler_act_set *set;
466 set = (struct bt_mesh_scheduler_act_set *)value;
467 net_buf_simple_add_mem(msg, set, offsetof(struct bt_mesh_scheduler_act_set, scene_number));
468 net_buf_simple_add_le16(msg, set->scene_number);
469 break;
470 }
471 default:
472 BT_ERR("Invalid Time Scene Set opcode 0x%04x", common->opcode);
473 err = -EINVAL;
474 goto end;
475 }
476
477 err = bt_mesh_client_send_msg(common, msg, need_ack, timeout_handler);
478
479 end:
480 bt_mesh_free_buf(msg);
481 return err;
482 }
483
bt_mesh_time_scene_client_get_state(bt_mesh_client_common_param_t * common,void * get)484 int bt_mesh_time_scene_client_get_state(bt_mesh_client_common_param_t *common, void *get)
485 {
486 bt_mesh_time_scene_client_t *client = NULL;
487
488 if (!common || !common->model) {
489 BT_ERR("%s, Invalid parameter", __func__);
490 return -EINVAL;
491 }
492
493 client = (bt_mesh_time_scene_client_t *)common->model->user_data;
494 if (!client || !client->internal_data) {
495 BT_ERR("Invalid Time Scene client data");
496 return -EINVAL;
497 }
498
499 switch (common->opcode) {
500 case BLE_MESH_MODEL_OP_TIME_GET:
501 case BLE_MESH_MODEL_OP_TIME_ZONE_GET:
502 case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_GET:
503 case BLE_MESH_MODEL_OP_TIME_ROLE_GET:
504 case BLE_MESH_MODEL_OP_SCENE_GET:
505 case BLE_MESH_MODEL_OP_SCENE_REGISTER_GET:
506 case BLE_MESH_MODEL_OP_SCHEDULER_GET:
507 break;
508 case BLE_MESH_MODEL_OP_SCHEDULER_ACT_GET:
509 if (!get) {
510 BT_ERR("Invalid Scheduler Action Get");
511 return -EINVAL;
512 }
513 break;
514 default:
515 BT_ERR("Invalid Time Scene Get opcode 0x%04x", common->opcode);
516 return -EINVAL;
517 }
518
519 return time_scene_get_state(common, get);
520 }
521
bt_mesh_time_scene_client_set_state(bt_mesh_client_common_param_t * common,void * set)522 int bt_mesh_time_scene_client_set_state(bt_mesh_client_common_param_t *common, void *set)
523 {
524 bt_mesh_time_scene_client_t *client = NULL;
525 uint16_t length = 0U;
526 bool need_ack = false;
527
528 if (!common || !common->model || !set) {
529 BT_ERR("%s, Invalid parameter", __func__);
530 return -EINVAL;
531 }
532
533 client = (bt_mesh_time_scene_client_t *)common->model->user_data;
534 if (!client || !client->internal_data) {
535 BT_ERR("Invalid Time Scene client data");
536 return -EINVAL;
537 }
538
539 switch (common->opcode) {
540 case BLE_MESH_MODEL_OP_TIME_SET:
541 need_ack = true;
542 length = BLE_MESH_TIME_SET_MSG_LEN;
543 break;
544 case BLE_MESH_MODEL_OP_TIME_ZONE_SET:
545 need_ack = true;
546 length = BLE_MESH_TIME_ZONE_SET_MSG_LEN;
547 break;
548 case BLE_MESH_MODEL_OP_TAI_UTC_DELTA_SET: {
549 struct bt_mesh_tai_utc_delta_set *value;
550 value = (struct bt_mesh_tai_utc_delta_set *)set;
551 if (value->padding) {
552 BT_ERR("Non-zero padding value is prohibited");
553 return -EINVAL;
554 }
555 need_ack = true;
556 length = BLE_MESH_TAI_UTC_DELTA_SET_MSG_LEN;
557 break;
558 }
559 case BLE_MESH_MODEL_OP_TIME_ROLE_SET: {
560 struct bt_mesh_time_role_set *value;
561 value = (struct bt_mesh_time_role_set *)set;
562 if (value->time_role > 0x03) {
563 BT_ERR("Time role 0x%02x is prohibited", value->time_role);
564 return -EINVAL;
565 }
566 need_ack = true;
567 length = BLE_MESH_TIME_ROLE_SET_MSG_LEN;
568 break;
569 }
570 case BLE_MESH_MODEL_OP_SCENE_STORE:
571 need_ack = true;
572 case BLE_MESH_MODEL_OP_SCENE_STORE_UNACK: {
573 struct bt_mesh_scene_store *value;
574 value = (struct bt_mesh_scene_store *)set;
575 if (!value->scene_number) {
576 BT_ERR("Scene Store scene number 0x0000 is prohibited");
577 return -EINVAL;
578 }
579 length = BLE_MESH_SCENE_STORE_MSG_LEN;
580 break;
581 }
582 case BLE_MESH_MODEL_OP_SCENE_RECALL:
583 need_ack = true;
584 case BLE_MESH_MODEL_OP_SCENE_RECALL_UNACK: {
585 struct bt_mesh_scene_recall *value;
586 value = (struct bt_mesh_scene_recall *)set;
587 if (!value->scene_number) {
588 BT_ERR("Scene Recall scene number 0x0000 is prohibited");
589 return -EINVAL;
590 }
591 if (value->op_en) {
592 if ((value->trans_time & 0x3F) > 0x3E) {
593 BT_ERR("Invalid Scene Recall transition time");
594 return -EINVAL;
595 }
596 }
597 length = BLE_MESH_SCENE_RECALL_MSG_LEN;
598 break;
599 }
600 case BLE_MESH_MODEL_OP_SCENE_DELETE:
601 need_ack = true;
602 case BLE_MESH_MODEL_OP_SCENE_DELETE_UNACK: {
603 length = BLE_MESH_SCENE_DELETE_MSG_LEN;
604 break;
605 }
606 case BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET:
607 need_ack = true;
608 case BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET_UNACK: {
609 struct bt_mesh_scheduler_act_set *value;
610 value = (struct bt_mesh_scheduler_act_set *)set;
611 if (value->year > 0x64) {
612 BT_ERR("Scheduler Register year 0x%02x is prohibited", value->year);
613 return -EINVAL;
614 }
615 if (value->hour > 0x19) {
616 BT_ERR("Scheduler Register hour 0x%02x is prohibited", value->hour);
617 return -EINVAL;
618 }
619 length = BLE_MESH_SCHEDULER_ACT_SET_MSG_LEN;
620 break;
621 }
622 default:
623 BT_ERR("Invalid Time Scene Set opcode 0x%04x", common->opcode);
624 return -EINVAL;
625 }
626
627 return time_scene_set_state(common, set, length, need_ack);
628 }
629
time_scene_client_init(struct bt_mesh_model * model)630 static int time_scene_client_init(struct bt_mesh_model *model)
631 {
632 time_scene_internal_data_t *internal = NULL;
633 bt_mesh_time_scene_client_t *client = NULL;
634
635 if (!model) {
636 BT_ERR("Invalid Time Scene client model");
637 return -EINVAL;
638 }
639
640 client = (bt_mesh_time_scene_client_t *)model->user_data;
641 if (!client) {
642 BT_ERR("No Time Scene client context provided");
643 return -EINVAL;
644 }
645
646 if (!client->internal_data) {
647 internal = bt_mesh_calloc(sizeof(time_scene_internal_data_t));
648 if (!internal) {
649 BT_ERR("%s, Out of memory", __func__);
650 return -ENOMEM;
651 }
652
653 sys_slist_init(&internal->queue);
654
655 client->model = model;
656 client->op_pair_size = ARRAY_SIZE(time_scene_op_pair);
657 client->op_pair = time_scene_op_pair;
658 client->internal_data = internal;
659 } else {
660 bt_mesh_client_clear_list(client->internal_data);
661 }
662
663 bt_mesh_time_scene_client_mutex_new();
664
665 return 0;
666 }
667
668 #if CONFIG_BLE_MESH_DEINIT
time_scene_client_deinit(struct bt_mesh_model * model)669 static int time_scene_client_deinit(struct bt_mesh_model *model)
670 {
671 bt_mesh_time_scene_client_t *client = NULL;
672
673 if (!model) {
674 BT_ERR("Invalid Time Scene client model");
675 return -EINVAL;
676 }
677
678 client = (bt_mesh_time_scene_client_t *)model->user_data;
679 if (!client) {
680 BT_ERR("No Time Scene client context provided");
681 return -EINVAL;
682 }
683
684 if (client->internal_data) {
685 /* Remove items from the list */
686 bt_mesh_client_clear_list(client->internal_data);
687
688 /* Free the allocated internal data */
689 bt_mesh_free(client->internal_data);
690 client->internal_data = NULL;
691 }
692
693 bt_mesh_time_scene_client_mutex_free();
694
695 return 0;
696 }
697 #endif /* CONFIG_BLE_MESH_DEINIT */
698
699 const struct bt_mesh_model_cb bt_mesh_time_scene_client_cb = {
700 .init = time_scene_client_init,
701 #if CONFIG_BLE_MESH_DEINIT
702 .deinit = time_scene_client_deinit,
703 #endif /* CONFIG_BLE_MESH_DEINIT */
704 };
705
706 #endif /* CONFIG_BLE_MESH_TIME_SCENE_CLIENT */
707