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