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