1 /* Bluetooth: Mesh Lighting Server Models
2 *
3 * Copyright (c) 2018 Vikrant More
4 * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <errno.h>
10
11 #include "btc_ble_mesh_lighting_model.h"
12
13 #include "mesh_config.h"
14 #include "access.h"
15 #include "transport.h"
16 #include "model_opcode.h"
17 #include "state_transition.h"
18 #include "device_property.h"
19
20 #if CONFIG_BLE_MESH_LIGHTING_SERVER
21
22 static bt_mesh_mutex_t light_server_lock;
23
bt_mesh_light_server_mutex_new(void)24 static inline void bt_mesh_light_server_mutex_new(void)
25 {
26 if (!light_server_lock.mutex) {
27 bt_mesh_mutex_create(&light_server_lock);
28 }
29 }
30
31 #if CONFIG_BLE_MESH_DEINIT
bt_mesh_light_server_mutex_free(void)32 static inline void bt_mesh_light_server_mutex_free(void)
33 {
34 bt_mesh_mutex_free(&light_server_lock);
35 }
36 #endif /* CONFIG_BLE_MESH_DEINIT */
37
bt_mesh_light_server_lock(void)38 void bt_mesh_light_server_lock(void)
39 {
40 bt_mesh_mutex_lock(&light_server_lock);
41 }
42
bt_mesh_light_server_unlock(void)43 void bt_mesh_light_server_unlock(void)
44 {
45 bt_mesh_mutex_unlock(&light_server_lock);
46 }
47
48 /* message handlers (Start) */
49
50 /* Light Lightness Server/Setup Server message handlers */
51
send_light_lightness_status(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,bool publish,uint16_t opcode)52 static void send_light_lightness_status(struct bt_mesh_model *model,
53 struct bt_mesh_msg_ctx *ctx,
54 bool publish, uint16_t opcode)
55 {
56 struct net_buf_simple *msg = NULL;
57 uint8_t length = 2 + 5;
58
59 if (ctx == NULL && publish == false) {
60 BT_ERR("%s, Invalid parameter", __func__);
61 return;
62 }
63
64 if (publish == false) {
65 msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
66 if (msg == NULL) {
67 BT_ERR("%s, Out of memory", __func__);
68 return;
69 }
70 } else {
71 msg = bt_mesh_server_get_pub_msg(model, length);
72 if (msg == NULL) {
73 return;
74 }
75 }
76
77 bt_mesh_model_msg_init(msg, opcode);
78 switch (opcode) {
79 case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS: {
80 struct bt_mesh_light_lightness_srv *srv = model->user_data;
81 net_buf_simple_add_le16(msg, srv->state->lightness_actual);
82 if (srv->actual_transition.counter) {
83 bt_mesh_server_calc_remain_time(&srv->actual_transition);
84 net_buf_simple_add_le16(msg, srv->state->target_lightness_actual);
85 net_buf_simple_add_u8(msg, srv->actual_transition.remain_time);
86 }
87 break;
88 }
89 case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS: {
90 struct bt_mesh_light_lightness_srv *srv = model->user_data;
91 net_buf_simple_add_le16(msg, srv->state->lightness_linear);
92 if (srv->linear_transition.counter) {
93 bt_mesh_server_calc_remain_time(&srv->linear_transition);
94 net_buf_simple_add_le16(msg, srv->state->target_lightness_linear);
95 net_buf_simple_add_u8(msg, srv->linear_transition.remain_time);
96 }
97 break;
98 }
99 case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_STATUS: {
100 struct bt_mesh_light_lightness_srv *srv = model->user_data;
101 net_buf_simple_add_le16(msg, srv->state->lightness_last);
102 break;
103 }
104 case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_STATUS:
105 if (model->id == BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV) {
106 struct bt_mesh_light_lightness_srv *srv = model->user_data;
107 net_buf_simple_add_le16(msg, srv->state->lightness_default);
108 } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV) {
109 struct bt_mesh_light_lightness_setup_srv *srv = model->user_data;
110 net_buf_simple_add_le16(msg, srv->state->lightness_default);
111 }
112 break;
113 case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_STATUS:
114 if (model->id == BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV) {
115 struct bt_mesh_light_lightness_srv *srv = model->user_data;
116 net_buf_simple_add_u8(msg, srv->state->status_code);
117 net_buf_simple_add_le16(msg, srv->state->lightness_range_min);
118 net_buf_simple_add_le16(msg, srv->state->lightness_range_max);
119 } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV) {
120 struct bt_mesh_light_lightness_setup_srv *srv = model->user_data;
121 net_buf_simple_add_u8(msg, srv->state->status_code);
122 net_buf_simple_add_le16(msg, srv->state->lightness_range_min);
123 net_buf_simple_add_le16(msg, srv->state->lightness_range_max);
124 }
125 break;
126 default:
127 BT_WARN("Unknown Light Lightness status opcode 0x%04x", opcode);
128 if (publish == false) {
129 bt_mesh_free_buf(msg);
130 }
131 return;
132 }
133
134 if (publish == false) {
135 BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
136 bt_mesh_free_buf(msg);
137 } else {
138 BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
139 }
140 return;
141 }
142
light_lightness_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)143 static void light_lightness_get(struct bt_mesh_model *model,
144 struct bt_mesh_msg_ctx *ctx,
145 struct net_buf_simple *buf)
146 {
147 struct bt_mesh_light_lightness_srv *srv = model->user_data;
148 uint16_t opcode = 0U;
149
150 if (srv == NULL || srv->state == NULL) {
151 BT_ERR("%s, Invalid model user data", __func__);
152 return;
153 }
154
155 /* Callback the received message to the application layer */
156 if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
157 bt_mesh_lighting_server_cb_evt_to_btc(
158 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG, model, ctx, NULL, 0);
159 return;
160 }
161
162 switch (ctx->recv_op) {
163 case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_GET:
164 opcode = BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS;
165 break;
166 case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_GET:
167 opcode = BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS;
168 break;
169 case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_GET:
170 opcode = BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_STATUS;
171 break;
172 case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_GET:
173 opcode = BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_STATUS;
174 break;
175 case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_GET:
176 opcode = BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_STATUS;
177 break;
178 default:
179 BT_WARN("Unknown Light Lightness Get opcode 0x%04x", ctx->recv_op);
180 return;
181 }
182
183 send_light_lightness_status(model, ctx, false, opcode);
184 return;
185 }
186
light_lightness_publish(struct bt_mesh_model * model,uint16_t opcode)187 void light_lightness_publish(struct bt_mesh_model *model, uint16_t opcode)
188 {
189 if (model->user_data == NULL) {
190 BT_ERR("%s, Invalid model user data", __func__);
191 return;
192 }
193
194 switch (model->id) {
195 case BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV: {
196 struct bt_mesh_light_lightness_srv *srv = model->user_data;
197 if (srv->state == NULL) {
198 BT_ERR("Invalid Light Lightness Server state");
199 return;
200 }
201 break;
202 }
203 case BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV: {
204 struct bt_mesh_light_lightness_setup_srv *srv = model->user_data;
205 if (srv->state == NULL) {
206 BT_ERR("Invalid Light Lightness Setup Server state");
207 return;
208 }
209 break;
210 }
211 default:
212 BT_ERR("Invalid Light Lightness Server model 0x%04x", model->id);
213 return;
214 }
215
216 send_light_lightness_status(model, NULL, true, opcode);
217 return;
218 }
219
light_lightness_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)220 static void light_lightness_set(struct bt_mesh_model *model,
221 struct bt_mesh_msg_ctx *ctx,
222 struct net_buf_simple *buf)
223 {
224 struct bt_mesh_light_lightness_srv *srv = model->user_data;
225 uint8_t tid = 0U, trans_time = 0U, delay = 0U;
226 bool optional = false;
227 uint16_t actual = 0U;
228 int64_t now = 0;
229
230 if (srv == NULL || srv->state == NULL) {
231 BT_ERR("%s, Invalid model user data", __func__);
232 return;
233 }
234
235 actual = net_buf_simple_pull_le16(buf);
236 tid = net_buf_simple_pull_u8(buf);
237
238 if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
239 return;
240 }
241
242 /* Callback the received message to the application layer */
243 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
244 bt_mesh_light_server_recv_set_msg_t set = {
245 .lightness_set.op_en = optional,
246 .lightness_set.lightness = actual,
247 .lightness_set.tid = tid,
248 .lightness_set.trans_time = trans_time,
249 .lightness_set.delay = delay,
250 };
251 bt_mesh_lighting_server_cb_evt_to_btc(
252 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
253 return;
254 }
255
256 if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
257 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET) {
258 send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS);
259 }
260 send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS);
261 /* In this condition, no event will be callback to application layer */
262 return;
263 }
264
265 bt_mesh_light_server_lock();
266
267 bt_mesh_server_stop_transition(&srv->actual_transition);
268 bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
269
270 if (actual) {
271 if (srv->state->lightness_range_min && actual < srv->state->lightness_range_min) {
272 actual = srv->state->lightness_range_min;
273 } else if (srv->state->lightness_range_max && actual > srv->state->lightness_range_max) {
274 actual = srv->state->lightness_range_max;
275 }
276 }
277 srv->state->target_lightness_actual = actual;
278
279 /**
280 * If the target state is equal to the current state, the transition shall not be
281 * started and is considered complete.
282 */
283 if (srv->state->target_lightness_actual != srv->state->lightness_actual) {
284 light_lightness_actual_tt_values(srv, trans_time, delay);
285 } else {
286 bt_mesh_light_server_state_change_t change = {
287 .lightness_set.lightness = srv->state->lightness_actual,
288 };
289 bt_mesh_lighting_server_cb_evt_to_btc(
290 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
291
292 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET) {
293 send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS);
294 }
295 send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS);
296
297 bt_mesh_light_server_unlock();
298 return;
299 }
300
301 /* Copy the ctx of the received message */
302 if (srv->actual_transition.timer.work._reserved) {
303 memcpy(srv->actual_transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx));
304 }
305
306 /* For Instantaneous Transition */
307 if (srv->actual_transition.counter == 0U) {
308 srv->state->lightness_actual = srv->state->target_lightness_actual;
309 /**
310 * Whenever the Light Lightness Actual state is changed with a non-transactional
311 * message or a completed sequence of transactional messages to a non-zero value,
312 * the value of the Light Lightness Last shall be set to the value of the Light
313 * Lightness Actual.
314 */
315 if (srv->state->lightness_actual) {
316 srv->state->lightness_last = srv->state->lightness_actual;
317 }
318 }
319
320 srv->actual_transition.just_started = true;
321 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET) {
322 send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS);
323 }
324 send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS);
325
326 bt_mesh_light_server_unlock();
327
328 bt_mesh_server_start_transition(&srv->actual_transition);
329 return;
330 }
331
light_lightness_linear_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)332 static void light_lightness_linear_set(struct bt_mesh_model *model,
333 struct bt_mesh_msg_ctx *ctx,
334 struct net_buf_simple *buf)
335 {
336 struct bt_mesh_light_lightness_srv *srv = model->user_data;
337 uint8_t tid = 0U, trans_time = 0U, delay = 0U;
338 bool optional = false;
339 uint16_t linear = 0U;
340 int64_t now = 0;
341
342 if (srv == NULL || srv->state == NULL) {
343 BT_ERR("%s, Invalid model user data", __func__);
344 return;
345 }
346
347 linear = net_buf_simple_pull_le16(buf);
348 tid = net_buf_simple_pull_u8(buf);
349
350 if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
351 return;
352 }
353
354 /* Callback the received message to the application layer */
355 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
356 bt_mesh_light_server_recv_set_msg_t set = {
357 .lightness_linear_set.op_en = optional,
358 .lightness_linear_set.lightness = linear,
359 .lightness_linear_set.tid = tid,
360 .lightness_linear_set.trans_time = trans_time,
361 .lightness_linear_set.delay = delay,
362 };
363 bt_mesh_lighting_server_cb_evt_to_btc(
364 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
365 return;
366 }
367
368 if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
369 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET) {
370 send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS);
371 }
372 send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS);
373 /* In this condition, no event will be callback to application layer */
374 return;
375 }
376
377 bt_mesh_light_server_lock();
378
379 bt_mesh_server_stop_transition(&srv->linear_transition);
380 bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
381
382 srv->state->target_lightness_linear = linear;
383
384 /**
385 * If the target state is equal to the current state, the transition shall not
386 * be started and is considered complete.
387 */
388 if (srv->state->target_lightness_linear != srv->state->lightness_linear) {
389 light_lightness_linear_tt_values(srv, trans_time, delay);
390 } else {
391 bt_mesh_light_server_state_change_t change = {
392 .lightness_linear_set.lightness = srv->state->lightness_actual,
393 };
394 bt_mesh_lighting_server_cb_evt_to_btc(
395 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
396
397 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET) {
398 send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS);
399 }
400 send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS);
401
402 bt_mesh_light_server_unlock();
403 return;
404 }
405
406 /* Copy the ctx of the received message */
407 if (srv->linear_transition.timer.work._reserved) {
408 memcpy(srv->linear_transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx));
409 }
410
411 /* For Instantaneous Transition */
412 if (srv->linear_transition.counter == 0U) {
413 srv->state->lightness_linear = srv->state->target_lightness_linear;
414 }
415
416 srv->linear_transition.just_started = true;
417 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET) {
418 send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS);
419 }
420 send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS);
421
422 bt_mesh_light_server_unlock();
423
424 bt_mesh_server_start_transition(&srv->linear_transition);
425 return;
426 }
427
light_lightness_default_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)428 static void light_lightness_default_set(struct bt_mesh_model *model,
429 struct bt_mesh_msg_ctx *ctx,
430 struct net_buf_simple *buf)
431 {
432 struct bt_mesh_light_lightness_setup_srv *srv = model->user_data;
433 uint16_t lightness = 0U;
434
435 if (srv == NULL || srv->state == NULL) {
436 BT_ERR("%s, Invalid model user data", __func__);
437 return;
438 }
439
440 lightness = net_buf_simple_pull_le16(buf);
441
442 /* Callback the received message to the application layer */
443 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
444 bt_mesh_light_server_recv_set_msg_t set = {
445 .lightness_default_set.lightness = lightness,
446 };
447 bt_mesh_lighting_server_cb_evt_to_btc(
448 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
449 return;
450 }
451
452 if (srv->state->lightness_default != lightness) {
453 srv->state->lightness_default = lightness;
454
455 bt_mesh_light_server_state_change_t change = {
456 .lightness_default_set.lightness = lightness,
457 };
458 bt_mesh_lighting_server_cb_evt_to_btc(
459 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
460 }
461
462 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET) {
463 send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_STATUS);
464 }
465 send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_STATUS);
466
467 return;
468 }
469
light_lightness_range_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)470 static void light_lightness_range_set(struct bt_mesh_model *model,
471 struct bt_mesh_msg_ctx *ctx,
472 struct net_buf_simple *buf)
473 {
474 struct bt_mesh_light_lightness_setup_srv *srv = model->user_data;
475 uint16_t range_min = 0U, range_max = 0U;
476
477 if (srv == NULL || srv->state == NULL) {
478 BT_ERR("%s, Invalid model user data", __func__);
479 return;
480 }
481
482 range_min = net_buf_simple_pull_le16(buf);
483 range_max = net_buf_simple_pull_le16(buf);
484
485 if (range_min > range_max) {
486 BT_ERR("Range min 0x%04x is greater than range max 0x%04x",
487 range_min, range_max);
488 return;
489 }
490
491 /* Callback the received message to the application layer */
492 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
493 bt_mesh_light_server_recv_set_msg_t set = {
494 .lightness_range_set.range_min = range_min,
495 .lightness_range_set.range_max = range_max,
496 };
497 bt_mesh_lighting_server_cb_evt_to_btc(
498 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
499 return;
500 }
501
502 /**
503 * When a Light Lightness Setup Server receives a Light Lightness Range Set
504 * message or a Light Lightness Range Set Unacknowledged message with values
505 * that cannot be accepted, it shall set the status of the operation to a
506 * value representing the reason why the values cannot be accepted.
507 *
508 * TODO: 0x0000 for Light Range Min/Max is prohibited, but BQB test case
509 * MMDL/SR/LLNS/BI-01-C requires 'SUCCESS' when it sends a set message with
510 * Light Range Min set to 0x0000.
511 */
512 #if 0
513 srv->state->status_code = BLE_MESH_RANGE_UPDATE_SUCCESS;
514 #else
515 if (range_min == 0x0000) {
516 srv->state->status_code = BLE_MESH_CANNOT_SET_RANGE_MIN;
517 } else if (range_max == 0x0000) {
518 srv->state->status_code = BLE_MESH_CANNOT_SET_RANGE_MAX;
519 } else {
520 srv->state->status_code = BLE_MESH_RANGE_UPDATE_SUCCESS;
521 }
522 #endif
523
524 if (range_min && srv->state->lightness_range_min != range_min) {
525 srv->state->lightness_range_min = range_min;
526 }
527
528 if (range_max && srv->state->lightness_range_max != range_max) {
529 srv->state->lightness_range_max = range_max;
530 }
531
532 bt_mesh_light_server_state_change_t change = {
533 .lightness_range_set.range_min = srv->state->lightness_range_min,
534 .lightness_range_set.range_max = srv->state->lightness_range_max,
535 };
536 bt_mesh_lighting_server_cb_evt_to_btc(
537 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
538
539 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET) {
540 send_light_lightness_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_STATUS);
541 }
542 send_light_lightness_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_STATUS);
543
544 return;
545 }
546
547 /* Light CTL Server/Temperature Server/Setup Server message handlers */
548
send_light_ctl_status(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,bool publish,uint16_t opcode)549 static void send_light_ctl_status(struct bt_mesh_model *model,
550 struct bt_mesh_msg_ctx *ctx,
551 bool publish, uint16_t opcode)
552 {
553 struct net_buf_simple *msg = NULL;
554 uint8_t length = 2 + 9;
555
556 if (ctx == NULL && publish == false) {
557 BT_ERR("%s, Invalid parameter", __func__);
558 return;
559 }
560
561 if (publish == false) {
562 msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
563 if (msg == NULL) {
564 BT_ERR("%s, Out of memory", __func__);
565 return;
566 }
567 } else {
568 msg = bt_mesh_server_get_pub_msg(model, length);
569 if (msg == NULL) {
570 return;
571 }
572 }
573
574 bt_mesh_model_msg_init(msg, opcode);
575 switch (opcode) {
576 case BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS: {
577 struct bt_mesh_light_ctl_srv *srv = model->user_data;
578 net_buf_simple_add_le16(msg, srv->state->lightness);
579 net_buf_simple_add_le16(msg, srv->state->temperature);
580 if (srv->transition.counter) {
581 bt_mesh_server_calc_remain_time(&srv->transition);
582 net_buf_simple_add_le16(msg, srv->state->target_lightness);
583 net_buf_simple_add_le16(msg, srv->state->target_temperature);
584 net_buf_simple_add_u8(msg, srv->transition.remain_time);
585 }
586 break;
587 }
588 case BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_STATUS:
589 if (model->id == BLE_MESH_MODEL_ID_LIGHT_CTL_SRV) {
590 struct bt_mesh_light_ctl_srv *srv = model->user_data;
591 net_buf_simple_add_u8(msg, srv->state->status_code);
592 net_buf_simple_add_le16(msg, srv->state->temperature_range_min);
593 net_buf_simple_add_le16(msg, srv->state->temperature_range_max);
594 } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV) {
595 struct bt_mesh_light_ctl_setup_srv *srv = model->user_data;
596 net_buf_simple_add_u8(msg, srv->state->status_code);
597 net_buf_simple_add_le16(msg, srv->state->temperature_range_min);
598 net_buf_simple_add_le16(msg, srv->state->temperature_range_max);
599 }
600 break;
601 case BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_STATUS: {
602 if (model->id == BLE_MESH_MODEL_ID_LIGHT_CTL_SRV) {
603 struct bt_mesh_light_ctl_srv *srv = model->user_data;
604 net_buf_simple_add_le16(msg, srv->state->lightness_default);
605 net_buf_simple_add_le16(msg, srv->state->temperature_default);
606 net_buf_simple_add_le16(msg, srv->state->delta_uv_default);
607 } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV) {
608 struct bt_mesh_light_ctl_setup_srv *srv = model->user_data;
609 net_buf_simple_add_le16(msg, srv->state->lightness_default);
610 net_buf_simple_add_le16(msg, srv->state->temperature_default);
611 net_buf_simple_add_le16(msg, srv->state->delta_uv_default);
612 }
613 break;
614 }
615 case BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS: {
616 struct bt_mesh_light_ctl_temp_srv *srv = model->user_data;
617 net_buf_simple_add_le16(msg, srv->state->temperature);
618 net_buf_simple_add_le16(msg, srv->state->delta_uv);
619 if (srv->transition.counter) {
620 bt_mesh_server_calc_remain_time(&srv->transition);
621 net_buf_simple_add_le16(msg, srv->state->target_temperature);
622 net_buf_simple_add_le16(msg, srv->state->target_delta_uv);
623 net_buf_simple_add_u8(msg, srv->transition.remain_time);
624 }
625 break;
626 }
627 default:
628 BT_WARN("Unknown Light CTL status opcode 0x%04x", opcode);
629 if (publish == false) {
630 bt_mesh_free_buf(msg);
631 }
632 return;
633 }
634
635 if (publish == false) {
636 BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
637 bt_mesh_free_buf(msg);
638 } else {
639 BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
640 }
641 return;
642 }
643
light_ctl_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)644 static void light_ctl_get(struct bt_mesh_model *model,
645 struct bt_mesh_msg_ctx *ctx,
646 struct net_buf_simple *buf)
647 {
648 struct bt_mesh_server_rsp_ctrl *rsp_ctrl = NULL;
649 uint16_t opcode = 0U;
650
651 if (model->user_data == NULL) {
652 BT_ERR("%s, Invalid model user data", __func__);
653 return;
654 }
655
656 switch (model->id) {
657 case BLE_MESH_MODEL_ID_LIGHT_CTL_SRV: {
658 struct bt_mesh_light_ctl_srv *srv = model->user_data;
659 if (srv->state == NULL) {
660 BT_ERR("Invalid Light CTL Server state");
661 return;
662 }
663 rsp_ctrl = &srv->rsp_ctrl;
664 break;
665 }
666 case BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV: {
667 struct bt_mesh_light_ctl_temp_srv *srv = model->user_data;
668 if (srv->state == NULL) {
669 BT_ERR("Invalid Light CTL Temperature Server state");
670 return;
671 }
672 rsp_ctrl = &srv->rsp_ctrl;
673 break;
674 }
675 default:
676 BT_ERR("Invalid Light CTL Server model 0x%04x", model->id);
677 return;
678 }
679
680 /* Callback the received message to the application layer */
681 if (rsp_ctrl->get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
682 bt_mesh_lighting_server_cb_evt_to_btc(
683 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG, model, ctx, NULL, 0);
684 return;
685 }
686
687 switch (ctx->recv_op) {
688 case BLE_MESH_MODEL_OP_LIGHT_CTL_GET:
689 opcode = BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS;
690 break;
691 case BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_GET:
692 opcode = BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_STATUS;
693 break;
694 case BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_GET:
695 opcode = BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_STATUS;
696 break;
697 case BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_GET:
698 opcode = BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS;
699 break;
700 default:
701 BT_WARN("Unknown Light CTL Get opcode 0x%04x", ctx->recv_op);
702 return;
703 }
704
705 send_light_ctl_status(model, ctx, false, opcode);
706 return;
707 }
708
light_ctl_publish(struct bt_mesh_model * model,uint16_t opcode)709 void light_ctl_publish(struct bt_mesh_model *model, uint16_t opcode)
710 {
711 if (model->user_data == NULL) {
712 BT_ERR("%s, Invalid model user data", __func__);
713 return;
714 }
715
716 switch (model->id) {
717 case BLE_MESH_MODEL_ID_LIGHT_CTL_SRV: {
718 struct bt_mesh_light_ctl_srv *srv = model->user_data;
719 if (srv->state == NULL) {
720 BT_ERR("Invalid Light CTL Server state");
721 return;
722 }
723 break;
724 }
725 case BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV: {
726 struct bt_mesh_light_ctl_temp_srv *srv = model->user_data;
727 if (srv->state == NULL) {
728 BT_ERR("Invalid Light CTL Temperature Server state");
729 return;
730 }
731 break;
732 }
733 case BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV: {
734 struct bt_mesh_light_ctl_setup_srv *srv = model->user_data;
735 if (srv->state == NULL) {
736 BT_ERR("Invalid Light CTL Setup Server state");
737 return;
738 }
739 break;
740 }
741 default:
742 BT_ERR("Invalid Light CTL Server model 0x%04x", model->id);
743 return;
744 }
745
746 send_light_ctl_status(model, NULL, true, opcode);
747 return;
748 }
749
light_ctl_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)750 static void light_ctl_set(struct bt_mesh_model *model,
751 struct bt_mesh_msg_ctx *ctx,
752 struct net_buf_simple *buf)
753 {
754 struct bt_mesh_light_ctl_srv *srv = model->user_data;
755 uint16_t lightness = 0U, temperature = 0U;
756 uint8_t tid = 0U, trans_time = 0U, delay = 0U;
757 int16_t delta_uv = 0;
758 bool optional = false;
759 int64_t now = 0;
760
761 if (srv == NULL || srv->state == NULL) {
762 BT_ERR("%s, Invalid model user data", __func__);
763 return;
764 }
765
766 lightness = net_buf_simple_pull_le16(buf);
767 temperature = net_buf_simple_pull_le16(buf);
768 delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
769 tid = net_buf_simple_pull_u8(buf);
770
771 if (temperature < BLE_MESH_TEMPERATURE_MIN || temperature > BLE_MESH_TEMPERATURE_MAX) {
772 BT_ERR("Invalid temperature 0x%04x", temperature);
773 return;
774 }
775
776 if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
777 return;
778 }
779
780 /* Callback the received message to the application layer */
781 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
782 bt_mesh_light_server_recv_set_msg_t set = {
783 .ctl_set.op_en = optional,
784 .ctl_set.lightness = lightness,
785 .ctl_set.temperature = temperature,
786 .ctl_set.delta_uv = delta_uv,
787 .ctl_set.tid = tid,
788 .ctl_set.trans_time = trans_time,
789 .ctl_set.delay = delay,
790 };
791 bt_mesh_lighting_server_cb_evt_to_btc(
792 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
793 return;
794 }
795
796 if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
797 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_SET) {
798 send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS);
799 }
800 send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS);
801 /* In this condition, no event will be callback to application layer */
802 return;
803 }
804
805 bt_mesh_light_server_lock();
806
807 bt_mesh_server_stop_transition(&srv->transition);
808 bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
809
810 srv->state->target_lightness = lightness;
811 if (srv->state->temperature_range_min &&
812 srv->state->temperature_range_min != BLE_MESH_TEMPERATURE_UNKNOWN &&
813 temperature < srv->state->temperature_range_min) {
814 temperature = srv->state->temperature_range_min;
815 } else if (srv->state->temperature_range_max &&
816 srv->state->temperature_range_max != BLE_MESH_TEMPERATURE_UNKNOWN &&
817 temperature > srv->state->temperature_range_max) {
818 temperature = srv->state->temperature_range_max;
819 }
820 srv->state->target_temperature = temperature;
821 srv->state->target_delta_uv = delta_uv;
822
823 if (srv->state->target_lightness != srv->state->lightness ||
824 srv->state->target_temperature != srv->state->temperature ||
825 srv->state->target_delta_uv != srv->state->delta_uv) {
826 light_ctl_tt_values(srv, trans_time, delay);
827 } else {
828 bt_mesh_light_server_state_change_t change = {
829 .ctl_set.lightness = srv->state->lightness,
830 .ctl_set.temperature = srv->state->temperature,
831 .ctl_set.delta_uv = srv->state->delta_uv,
832 };
833 bt_mesh_lighting_server_cb_evt_to_btc(
834 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
835
836 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_SET) {
837 send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS);
838 }
839 send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS);
840
841 bt_mesh_light_server_unlock();
842 return;
843 }
844
845 /* Copy the ctx of the received message */
846 if (srv->transition.timer.work._reserved) {
847 memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx));
848 }
849
850 /* For Instantaneous Transition */
851 if (srv->transition.counter == 0U) {
852 srv->state->lightness = srv->state->target_lightness;
853 srv->state->temperature = srv->state->target_temperature;
854 srv->state->delta_uv = srv->state->target_delta_uv;
855 }
856
857 srv->transition.just_started = true;
858 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_SET) {
859 send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS);
860 }
861 send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS);
862
863 bt_mesh_light_server_unlock();
864
865 bt_mesh_server_start_transition(&srv->transition);
866 return;
867 }
868
light_ctl_default_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)869 static void light_ctl_default_set(struct bt_mesh_model *model,
870 struct bt_mesh_msg_ctx *ctx,
871 struct net_buf_simple *buf)
872 {
873 struct bt_mesh_light_ctl_setup_srv *srv = model->user_data;
874 uint16_t lightness = 0U, temperature = 0U;
875 int16_t delta_uv = 0;
876
877 if (srv == NULL || srv->state == NULL) {
878 BT_ERR("%s, Invalid model user data", __func__);
879 return;
880 }
881
882 lightness = net_buf_simple_pull_le16(buf);
883 temperature = net_buf_simple_pull_le16(buf);
884 delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
885
886 if (temperature < BLE_MESH_TEMPERATURE_MIN || temperature > BLE_MESH_TEMPERATURE_MAX) {
887 BT_ERR("Invalid temperature 0x%04x", temperature);
888 return;
889 }
890
891 /* Callback the received message to the application layer */
892 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
893 bt_mesh_light_server_recv_set_msg_t set = {
894 .ctl_default_set.lightness = lightness,
895 .ctl_default_set.temperature = temperature,
896 .ctl_default_set.delta_uv = delta_uv,
897 };
898 bt_mesh_lighting_server_cb_evt_to_btc(
899 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
900 return;
901 }
902
903 if (srv->state->temperature_range_min &&
904 srv->state->temperature_range_min != BLE_MESH_TEMPERATURE_UNKNOWN &&
905 temperature < srv->state->temperature_range_min) {
906 temperature = srv->state->temperature_range_min;
907 } else if (srv->state->temperature_range_max &&
908 srv->state->temperature_range_max != BLE_MESH_TEMPERATURE_UNKNOWN &&
909 temperature > srv->state->temperature_range_max) {
910 temperature = srv->state->temperature_range_max;
911 }
912
913 srv->state->lightness_default = lightness;
914 srv->state->temperature_default = temperature;
915 srv->state->delta_uv_default = delta_uv;
916
917 bt_mesh_light_server_state_change_t change = {
918 .ctl_default_set.lightness = srv->state->lightness_default,
919 .ctl_default_set.temperature = srv->state->temperature_default,
920 .ctl_default_set.delta_uv = srv->state->delta_uv_default,
921 };
922 bt_mesh_lighting_server_cb_evt_to_btc(
923 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
924
925 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET) {
926 send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_STATUS);
927 }
928 send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_STATUS);
929
930 return;
931 }
932
light_ctl_temp_range_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)933 static void light_ctl_temp_range_set(struct bt_mesh_model *model,
934 struct bt_mesh_msg_ctx *ctx,
935 struct net_buf_simple *buf)
936 {
937 struct bt_mesh_light_ctl_setup_srv *srv = model->user_data;
938 uint16_t min = 0U, max = 0U;
939
940 if (srv == NULL || srv->state == NULL) {
941 BT_ERR("%s, Invalid model user data", __func__);
942 return;
943 }
944
945 min = net_buf_simple_pull_le16(buf);
946 max = net_buf_simple_pull_le16(buf);
947
948 /* This is as per 6.1.3.1 in Mesh Model Specification */
949 if (min > max ||
950 min < BLE_MESH_TEMPERATURE_MIN || (min != BLE_MESH_TEMPERATURE_UNKNOWN && min > BLE_MESH_TEMPERATURE_MAX) ||
951 max < BLE_MESH_TEMPERATURE_MIN || (max != BLE_MESH_TEMPERATURE_UNKNOWN && max > BLE_MESH_TEMPERATURE_MAX)) {
952 BT_ERR("Invalid parameter, range min 0x%04x, range max 0x%04x",
953 min, max);
954 return;
955 }
956
957 /* Callback the received message to the application layer */
958 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
959 bt_mesh_light_server_recv_set_msg_t set = {
960 .ctl_temp_range_set.range_min = min,
961 .ctl_temp_range_set.range_max = max,
962 };
963 bt_mesh_lighting_server_cb_evt_to_btc(
964 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
965 return;
966 }
967
968 if (min == BLE_MESH_TEMPERATURE_UNKNOWN) {
969 srv->state->status_code = BLE_MESH_CANNOT_SET_RANGE_MIN;
970 } else if (max == BLE_MESH_TEMPERATURE_UNKNOWN ) {
971 srv->state->status_code = BLE_MESH_CANNOT_SET_RANGE_MAX;
972 } else {
973 srv->state->status_code = BLE_MESH_RANGE_UPDATE_SUCCESS;
974 }
975
976 if (min != BLE_MESH_TEMPERATURE_UNKNOWN && srv->state->temperature_range_min != min) {
977 srv->state->temperature_range_min = min;
978 }
979
980 if (max != BLE_MESH_TEMPERATURE_UNKNOWN && srv->state->temperature_range_max != max) {
981 srv->state->temperature_range_max = max;
982 }
983
984 bt_mesh_light_server_state_change_t change = {
985 .ctl_temp_range_set.range_min = srv->state->temperature_range_min,
986 .ctl_temp_range_set.range_max = srv->state->temperature_range_max,
987 };
988 bt_mesh_lighting_server_cb_evt_to_btc(
989 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
990
991 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET) {
992 send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_STATUS);
993 }
994 send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_STATUS);
995
996 return;
997 }
998
light_ctl_temp_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)999 static void light_ctl_temp_set(struct bt_mesh_model *model,
1000 struct bt_mesh_msg_ctx *ctx,
1001 struct net_buf_simple *buf)
1002 {
1003 struct bt_mesh_light_ctl_temp_srv *srv = model->user_data;
1004 uint8_t tid = 0U, trans_time = 0U, delay = 0U;
1005 uint16_t temperature = 0U;
1006 int16_t delta_uv = 0;
1007 bool optional = false;
1008 int64_t now = 0;
1009
1010 if (srv == NULL || srv->state == NULL) {
1011 BT_ERR("%s, Invalid model user data", __func__);
1012 return;
1013 }
1014
1015 temperature = net_buf_simple_pull_le16(buf);
1016 delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
1017 tid = net_buf_simple_pull_u8(buf);
1018
1019 if (temperature < BLE_MESH_TEMPERATURE_MIN || temperature > BLE_MESH_TEMPERATURE_MAX) {
1020 BT_ERR("Invalid temperature 0x%04x", temperature);
1021 return;
1022 }
1023
1024 if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
1025 return;
1026 }
1027
1028 /* Callback the received message to the application layer */
1029 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
1030 bt_mesh_light_server_recv_set_msg_t set = {
1031 .ctl_temp_set.op_en = optional,
1032 .ctl_temp_set.temperature = temperature,
1033 .ctl_temp_set.delta_uv = delta_uv,
1034 .ctl_temp_set.tid = tid,
1035 .ctl_temp_set.trans_time = trans_time,
1036 .ctl_temp_set.delay = delay,
1037 };
1038 bt_mesh_lighting_server_cb_evt_to_btc(
1039 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
1040 return;
1041 }
1042
1043 if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
1044 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET) {
1045 send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS);
1046 }
1047 send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS);
1048 /* In this condition, no event will be callback to application layer */
1049 return;
1050 }
1051
1052 bt_mesh_light_server_lock();
1053
1054 bt_mesh_server_stop_transition(&srv->transition);
1055 bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
1056
1057 if (srv->state->temperature_range_min &&
1058 srv->state->temperature_range_min != BLE_MESH_TEMPERATURE_UNKNOWN &&
1059 temperature < srv->state->temperature_range_min) {
1060 temperature = srv->state->temperature_range_min;
1061 } else if (srv->state->temperature_range_max &&
1062 srv->state->temperature_range_max != BLE_MESH_TEMPERATURE_UNKNOWN &&
1063 temperature > srv->state->temperature_range_max) {
1064 temperature = srv->state->temperature_range_max;
1065 }
1066 srv->state->target_temperature = temperature;
1067 srv->state->target_delta_uv = delta_uv;
1068
1069 if (srv->state->target_temperature != srv->state->temperature ||
1070 srv->state->target_delta_uv != srv->state->delta_uv) {
1071 light_ctl_temp_tt_values(srv, trans_time, delay);
1072 } else {
1073 bt_mesh_light_server_state_change_t change = {
1074 .ctl_temp_set.temperature = srv->state->temperature,
1075 .ctl_temp_set.delta_uv = srv->state->delta_uv,
1076 };
1077 bt_mesh_lighting_server_cb_evt_to_btc(
1078 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
1079
1080 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET) {
1081 send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS);
1082 }
1083 send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS);
1084
1085 bt_mesh_light_server_unlock();
1086 return;
1087 }
1088
1089 /* Copy the ctx of the received message */
1090 if (srv->transition.timer.work._reserved) {
1091 memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx));
1092 }
1093
1094 /* For Instantaneous Transition */
1095 if (srv->transition.counter == 0U) {
1096 srv->state->temperature = srv->state->target_temperature;
1097 srv->state->delta_uv = srv->state->target_delta_uv;
1098 }
1099
1100 srv->transition.just_started = true;
1101 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET) {
1102 send_light_ctl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS);
1103 }
1104 send_light_ctl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS);
1105
1106 bt_mesh_light_server_unlock();
1107
1108 bt_mesh_server_start_transition(&srv->transition);
1109 return;
1110 }
1111
1112 /* Light HSL Server/Hue Server/Saturation Server/Setup Server message handlers */
1113
send_light_hsl_status(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,bool publish,uint16_t opcode)1114 static void send_light_hsl_status(struct bt_mesh_model *model,
1115 struct bt_mesh_msg_ctx *ctx,
1116 bool publish, uint16_t opcode)
1117 {
1118 struct net_buf_simple *msg = NULL;
1119 uint8_t length = 2 + 9;
1120
1121 if (ctx == NULL && publish == false) {
1122 BT_ERR("%s, Invalid parameter", __func__);
1123 return;
1124 }
1125
1126 if (publish == false) {
1127 msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
1128 if (msg == NULL) {
1129 BT_ERR("%s, Out of memory", __func__);
1130 return;
1131 }
1132 } else {
1133 msg = bt_mesh_server_get_pub_msg(model, length);
1134 if (msg == NULL) {
1135 return;
1136 }
1137 }
1138
1139 bt_mesh_model_msg_init(msg, opcode);
1140 switch (opcode) {
1141 case BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS:
1142 case BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_STATUS: {
1143 struct bt_mesh_light_hsl_srv *srv = model->user_data;
1144 if (opcode == BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS) {
1145 net_buf_simple_add_le16(msg, srv->state->lightness);
1146 net_buf_simple_add_le16(msg, srv->state->hue);
1147 net_buf_simple_add_le16(msg, srv->state->saturation);
1148 if (srv->transition.counter) {
1149 bt_mesh_server_calc_remain_time(&srv->transition);
1150 net_buf_simple_add_u8(msg, srv->transition.remain_time);
1151 }
1152 } else if (opcode == BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_STATUS) {
1153 net_buf_simple_add_le16(msg, srv->state->target_lightness);
1154 net_buf_simple_add_le16(msg, srv->state->target_hue);
1155 net_buf_simple_add_le16(msg, srv->state->target_saturation);
1156 if (srv->transition.counter) {
1157 bt_mesh_server_calc_remain_time(&srv->transition);
1158 net_buf_simple_add_u8(msg, srv->transition.remain_time);
1159 }
1160 }
1161 break;
1162 }
1163 case BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_STATUS:
1164 if (model->id == BLE_MESH_MODEL_ID_LIGHT_HSL_SRV) {
1165 struct bt_mesh_light_hsl_srv *srv = model->user_data;
1166 net_buf_simple_add_le16(msg, srv->state->lightness_default);
1167 net_buf_simple_add_le16(msg, srv->state->hue_default);
1168 net_buf_simple_add_le16(msg, srv->state->saturation_default);
1169 } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV) {
1170 struct bt_mesh_light_hsl_setup_srv *srv = model->user_data;
1171 net_buf_simple_add_le16(msg, srv->state->lightness_default);
1172 net_buf_simple_add_le16(msg, srv->state->hue_default);
1173 net_buf_simple_add_le16(msg, srv->state->saturation_default);
1174 }
1175 break;
1176 case BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_STATUS:
1177 if (model->id == BLE_MESH_MODEL_ID_LIGHT_HSL_SRV) {
1178 struct bt_mesh_light_hsl_srv *srv = model->user_data;
1179 net_buf_simple_add_u8(msg, srv->state->status_code);
1180 net_buf_simple_add_le16(msg, srv->state->hue_range_min);
1181 net_buf_simple_add_le16(msg, srv->state->hue_range_max);
1182 net_buf_simple_add_le16(msg, srv->state->saturation_range_min);
1183 net_buf_simple_add_le16(msg, srv->state->saturation_range_max);
1184 } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV) {
1185 struct bt_mesh_light_hsl_setup_srv *srv = model->user_data;
1186 net_buf_simple_add_u8(msg, srv->state->status_code);
1187 net_buf_simple_add_le16(msg, srv->state->hue_range_min);
1188 net_buf_simple_add_le16(msg, srv->state->hue_range_max);
1189 net_buf_simple_add_le16(msg, srv->state->saturation_range_min);
1190 net_buf_simple_add_le16(msg, srv->state->saturation_range_max);
1191 }
1192 break;
1193 case BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS: {
1194 struct bt_mesh_light_hsl_hue_srv *srv = model->user_data;
1195 net_buf_simple_add_le16(msg, srv->state->hue);
1196 if (srv->transition.counter) {
1197 bt_mesh_server_calc_remain_time(&srv->transition);
1198 net_buf_simple_add_le16(msg, srv->state->target_hue);
1199 net_buf_simple_add_u8(msg, srv->transition.remain_time);
1200 }
1201 break;
1202 }
1203 case BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS: {
1204 struct bt_mesh_light_hsl_sat_srv *srv = model->user_data;
1205 net_buf_simple_add_le16(msg, srv->state->saturation);
1206 if (srv->transition.counter) {
1207 bt_mesh_server_calc_remain_time(&srv->transition);
1208 net_buf_simple_add_le16(msg, srv->state->target_saturation);
1209 net_buf_simple_add_u8(msg, srv->transition.remain_time);
1210 }
1211 break;
1212 }
1213 default:
1214 BT_WARN("Unknown Light HSL status opcode 0x%04x", opcode);
1215 if (publish == false) {
1216 bt_mesh_free_buf(msg);
1217 }
1218 return;
1219 }
1220
1221 if (publish == false) {
1222 BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
1223 bt_mesh_free_buf(msg);
1224 } else {
1225 BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
1226 }
1227 return;
1228 }
1229
light_hsl_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1230 static void light_hsl_get(struct bt_mesh_model *model,
1231 struct bt_mesh_msg_ctx *ctx,
1232 struct net_buf_simple *buf)
1233 {
1234 struct bt_mesh_server_rsp_ctrl *rsp_ctrl = NULL;
1235 uint16_t opcode = 0U;
1236
1237 if (model->user_data == NULL) {
1238 BT_ERR("%s, Invalid model user data", __func__);
1239 return;
1240 }
1241
1242 switch (model->id) {
1243 case BLE_MESH_MODEL_ID_LIGHT_HSL_SRV: {
1244 struct bt_mesh_light_hsl_srv *srv = model->user_data;
1245 if (srv->state == NULL) {
1246 BT_ERR("Invalid Light HSL Server state");
1247 return;
1248 }
1249 rsp_ctrl = &srv->rsp_ctrl;
1250 break;
1251 }
1252 case BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV: {
1253 struct bt_mesh_light_hsl_hue_srv *srv = model->user_data;
1254 if (srv->state == NULL) {
1255 BT_ERR("Invalid Light HSL Hue Server state");
1256 return;
1257 }
1258 rsp_ctrl = &srv->rsp_ctrl;
1259 break;
1260 }
1261 case BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV: {
1262 struct bt_mesh_light_hsl_sat_srv *srv = model->user_data;
1263 if (srv->state == NULL) {
1264 BT_ERR("Invalid Light HSL Saturation Server state");
1265 return;
1266 }
1267 rsp_ctrl = &srv->rsp_ctrl;
1268 break;
1269 }
1270 default:
1271 BT_ERR("Invalid Light HSL Server model 0x%04x", model->id);
1272 return;
1273 }
1274
1275 /* Callback the received message to the application layer */
1276 if (rsp_ctrl->get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
1277 bt_mesh_lighting_server_cb_evt_to_btc(
1278 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG, model, ctx, NULL, 0);
1279 return;
1280 }
1281
1282 switch (ctx->recv_op) {
1283 case BLE_MESH_MODEL_OP_LIGHT_HSL_GET:
1284 opcode = BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS;
1285 break;
1286 case BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_GET:
1287 opcode = BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_STATUS;
1288 break;
1289 case BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_GET:
1290 opcode = BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_STATUS;
1291 break;
1292 case BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_GET:
1293 opcode = BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_STATUS;
1294 break;
1295 case BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_GET:
1296 opcode = BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS;
1297 break;
1298 case BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_GET:
1299 opcode = BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS;
1300 break;
1301 default:
1302 BT_WARN("Unknown Light HSL Get opcode 0x%04x", ctx->recv_op);
1303 return;
1304 }
1305
1306 send_light_hsl_status(model, ctx, false, opcode);
1307 return;
1308 }
1309
light_hsl_publish(struct bt_mesh_model * model,uint16_t opcode)1310 void light_hsl_publish(struct bt_mesh_model *model, uint16_t opcode)
1311 {
1312 if (model->user_data == NULL) {
1313 BT_ERR("%s, Invalid model user data", __func__);
1314 return;
1315 }
1316
1317 switch (model->id) {
1318 case BLE_MESH_MODEL_ID_LIGHT_HSL_SRV: {
1319 struct bt_mesh_light_hsl_srv *srv = model->user_data;
1320 if (srv->state == NULL) {
1321 BT_ERR("Invalid Light HSL Server state");
1322 return;
1323 }
1324 break;
1325 }
1326 case BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV: {
1327 struct bt_mesh_light_hsl_hue_srv *srv = model->user_data;
1328 if (srv->state == NULL) {
1329 BT_ERR("Invalid Light HSL Hue Server state");
1330 return;
1331 }
1332 break;
1333 }
1334 case BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV: {
1335 struct bt_mesh_light_hsl_sat_srv *srv = model->user_data;
1336 if (srv->state == NULL) {
1337 BT_ERR("Invalid Light HSL Saturation Server state");
1338 return;
1339 }
1340 break;
1341 }
1342 case BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV: {
1343 struct bt_mesh_light_hsl_setup_srv *srv = model->user_data;
1344 if (srv->state == NULL) {
1345 BT_ERR("Invalid Light HSL Setup Server state");
1346 return;
1347 }
1348 break;
1349 }
1350 default:
1351 BT_ERR("Invalid Light HSL Server model 0x%04x", model->id);
1352 return;
1353 }
1354
1355 send_light_hsl_status(model, NULL, true, opcode);
1356 return;
1357 }
1358
light_hsl_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1359 static void light_hsl_set(struct bt_mesh_model *model,
1360 struct bt_mesh_msg_ctx *ctx,
1361 struct net_buf_simple *buf)
1362 {
1363 struct bt_mesh_light_hsl_srv *srv = model->user_data;
1364 uint16_t lightness = 0U, hue = 0U, saturation = 0U;
1365 uint8_t tid = 0U, trans_time = 0U, delay = 0U;
1366 bool optional = false;
1367 int64_t now = 0;
1368
1369 if (srv == NULL || srv->state == NULL) {
1370 BT_ERR("%s, Invalid model user data", __func__);
1371 return;
1372 }
1373
1374 lightness = net_buf_simple_pull_le16(buf);
1375 hue = net_buf_simple_pull_le16(buf);
1376 saturation = net_buf_simple_pull_le16(buf);
1377 tid = net_buf_simple_pull_u8(buf);
1378
1379 if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
1380 return;
1381 }
1382
1383 /* Callback the received message to the application layer */
1384 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
1385 bt_mesh_light_server_recv_set_msg_t set = {
1386 .hsl_set.op_en = optional,
1387 .hsl_set.lightness = lightness,
1388 .hsl_set.hue = hue,
1389 .hsl_set.saturation = saturation,
1390 .hsl_set.tid = tid,
1391 .hsl_set.trans_time = trans_time,
1392 .hsl_set.delay = delay,
1393 };
1394 bt_mesh_lighting_server_cb_evt_to_btc(
1395 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
1396 return;
1397 }
1398
1399 if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
1400 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_SET) {
1401 send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS);
1402 }
1403 send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS);
1404 /* In this condition, no event will be callback to application layer */
1405 return;
1406 }
1407
1408 bt_mesh_light_server_lock();
1409
1410 bt_mesh_server_stop_transition(&srv->transition);
1411 bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
1412
1413 srv->state->target_lightness = lightness;
1414 if (srv->state->hue_range_min && hue < srv->state->hue_range_min) {
1415 hue = srv->state->hue_range_min;
1416 } else if (srv->state->hue_range_max && hue > srv->state->hue_range_max) {
1417 hue = srv->state->hue_range_max;
1418 }
1419 srv->state->target_hue = hue;
1420 if (srv->state->saturation_range_min && saturation < srv->state->saturation_range_min) {
1421 saturation = srv->state->saturation_range_min;
1422 } else if (srv->state->saturation_range_max && saturation > srv->state->saturation_range_max) {
1423 saturation = srv->state->saturation_range_max;
1424 }
1425 srv->state->target_saturation = saturation;
1426
1427 /**
1428 * If the target state is equal to the current state, the transition shall not
1429 * be started and is considered complete.
1430 */
1431 if (srv->state->target_lightness != srv->state->lightness ||
1432 srv->state->target_hue != srv->state->hue ||
1433 srv->state->target_saturation != srv->state->saturation) {
1434 light_hsl_tt_values(srv, trans_time, delay);
1435 } else {
1436 bt_mesh_light_server_state_change_t change = {
1437 .hsl_set.lightness = srv->state->lightness,
1438 .hsl_set.hue = srv->state->hue,
1439 .hsl_set.saturation = srv->state->saturation,
1440 };
1441 bt_mesh_lighting_server_cb_evt_to_btc(
1442 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
1443
1444 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_SET) {
1445 send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS);
1446 }
1447 send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS);
1448
1449 bt_mesh_light_server_unlock();
1450 return;
1451 }
1452
1453 /* Copy the ctx of the received message */
1454 if (srv->transition.timer.work._reserved) {
1455 memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx));
1456 }
1457
1458 /* For Instantaneous Transition */
1459 if (srv->transition.counter == 0U) {
1460 srv->state->lightness = srv->state->target_lightness;
1461 srv->state->hue = srv->state->target_hue;
1462 srv->state->saturation = srv->state->target_saturation;
1463 }
1464
1465 srv->transition.just_started = true;
1466 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_SET) {
1467 send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS);
1468 }
1469 send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS);
1470
1471 bt_mesh_light_server_unlock();
1472
1473 bt_mesh_server_start_transition(&srv->transition);
1474 return;
1475 }
1476
light_hsl_default_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1477 static void light_hsl_default_set(struct bt_mesh_model *model,
1478 struct bt_mesh_msg_ctx *ctx,
1479 struct net_buf_simple *buf)
1480 {
1481 struct bt_mesh_light_hsl_setup_srv *srv = model->user_data;
1482 uint16_t lightness = 0U, hue = 0U, saturation = 0U;
1483
1484 if (srv == NULL || srv->state == NULL) {
1485 BT_ERR("%s, Invalid model user data", __func__);
1486 return;
1487 }
1488
1489 lightness = net_buf_simple_pull_le16(buf);
1490 hue = net_buf_simple_pull_le16(buf);
1491 saturation = net_buf_simple_pull_le16(buf);
1492
1493 /* Callback the received message to the application layer */
1494 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
1495 bt_mesh_light_server_recv_set_msg_t set = {
1496 .hsl_default_set.lightness = lightness,
1497 .hsl_default_set.hue = hue,
1498 .hsl_default_set.saturation = saturation,
1499 };
1500 bt_mesh_lighting_server_cb_evt_to_btc(
1501 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
1502 return;
1503 }
1504
1505 if (srv->state->hue_range_min && hue < srv->state->hue_range_min) {
1506 hue = srv->state->hue_range_min;
1507 } else if (srv->state->hue_range_max && hue > srv->state->hue_range_max) {
1508 hue = srv->state->hue_range_max;
1509 }
1510
1511 if (srv->state->saturation_range_min && saturation < srv->state->saturation_range_min) {
1512 saturation = srv->state->saturation_range_min;
1513 } else if (srv->state->saturation_range_max && saturation > srv->state->saturation_range_max) {
1514 saturation = srv->state->saturation_range_max;
1515 }
1516
1517 srv->state->lightness_default = lightness;
1518 srv->state->hue_default = hue;
1519 srv->state->saturation_default = saturation;
1520
1521 bt_mesh_light_server_state_change_t change = {
1522 .hsl_default_set.lightness = srv->state->lightness_default,
1523 .hsl_default_set.hue = srv->state->hue_default,
1524 .hsl_default_set.saturation = srv->state->saturation_default,
1525 };
1526 bt_mesh_lighting_server_cb_evt_to_btc(
1527 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
1528
1529 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET) {
1530 send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_STATUS);
1531 }
1532 send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_STATUS);
1533
1534 return;
1535 }
1536
light_hsl_range_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1537 static void light_hsl_range_set(struct bt_mesh_model *model,
1538 struct bt_mesh_msg_ctx *ctx,
1539 struct net_buf_simple *buf)
1540 {
1541 struct bt_mesh_light_hsl_setup_srv *srv = model->user_data;
1542 uint16_t hue_min = 0U, hue_max = 0U, saturation_min = 0U, saturation_max = 0U;
1543
1544 if (srv == NULL || srv->state == NULL) {
1545 BT_ERR("%s, Invalid model user data", __func__);
1546 return;
1547 }
1548
1549 hue_min = net_buf_simple_pull_le16(buf);
1550 hue_max = net_buf_simple_pull_le16(buf);
1551 saturation_min = net_buf_simple_pull_le16(buf);
1552 saturation_max = net_buf_simple_pull_le16(buf);
1553
1554 if (hue_min > hue_max) {
1555 BT_ERR("Invalid parameter, hue min 0x%04x, hue max 0x%04x",
1556 hue_min, hue_max);
1557 return;
1558 }
1559
1560 if (saturation_min > saturation_max) {
1561 BT_ERR("Invalid parameter, saturation min 0x%04x, saturation max 0x%04x",
1562 saturation_min, saturation_max);
1563 return;
1564 }
1565
1566 /* Callback the received message to the application layer */
1567 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
1568 bt_mesh_light_server_recv_set_msg_t set = {
1569 .hsl_range_set.hue_range_min = hue_min,
1570 .hsl_range_set.hue_range_max = hue_max,
1571 .hsl_range_set.sat_range_min = saturation_min,
1572 .hsl_range_set.sat_range_max = saturation_max,
1573 };
1574 bt_mesh_lighting_server_cb_evt_to_btc(
1575 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
1576 return;
1577 }
1578
1579 srv->state->status_code = BLE_MESH_RANGE_UPDATE_SUCCESS;
1580 srv->state->hue_range_min = hue_min;
1581 srv->state->hue_range_max = hue_max;
1582 srv->state->saturation_range_min = saturation_min;
1583 srv->state->saturation_range_max = saturation_max;
1584
1585 bt_mesh_light_server_state_change_t change = {
1586 .hsl_range_set.hue_range_min = srv->state->hue_range_min,
1587 .hsl_range_set.hue_range_max = srv->state->hue_range_max,
1588 .hsl_range_set.sat_range_min = srv->state->saturation_range_min,
1589 .hsl_range_set.sat_range_max = srv->state->saturation_range_max,
1590 };
1591 bt_mesh_lighting_server_cb_evt_to_btc(
1592 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
1593
1594 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET) {
1595 send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_STATUS);
1596 }
1597 send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_STATUS);
1598
1599 return;
1600 }
1601
light_hsl_hue_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1602 static void light_hsl_hue_set(struct bt_mesh_model *model,
1603 struct bt_mesh_msg_ctx *ctx,
1604 struct net_buf_simple *buf)
1605 {
1606 struct bt_mesh_light_hsl_hue_srv *srv = model->user_data;
1607 uint8_t tid = 0U, trans_time = 0U, delay = 0U;
1608 bool optional = false;
1609 uint16_t hue = 0U;
1610 int64_t now = 0;
1611
1612 if (srv == NULL || srv->state == NULL) {
1613 BT_ERR("%s, Invalid model user data", __func__);
1614 return;
1615 }
1616
1617 hue = net_buf_simple_pull_le16(buf);
1618 tid = net_buf_simple_pull_u8(buf);
1619
1620 if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
1621 return;
1622 }
1623
1624 /* Callback the received message to the application layer */
1625 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
1626 bt_mesh_light_server_recv_set_msg_t set = {
1627 .hsl_hue_set.op_en = optional,
1628 .hsl_hue_set.hue = hue,
1629 .hsl_hue_set.tid = tid,
1630 .hsl_hue_set.trans_time = trans_time,
1631 .hsl_hue_set.delay = delay,
1632 };
1633 bt_mesh_lighting_server_cb_evt_to_btc(
1634 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
1635 return;
1636 }
1637
1638 if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
1639 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET) {
1640 send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS);
1641 }
1642 send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS);
1643 /* In this condition, no event will be callback to application layer */
1644 return;
1645 }
1646
1647 bt_mesh_light_server_lock();
1648
1649 bt_mesh_server_stop_transition(&srv->transition);
1650 bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
1651
1652 if (srv->state->hue_range_min && hue < srv->state->hue_range_min) {
1653 hue = srv->state->hue_range_min;
1654 } else if (srv->state->hue_range_max && hue > srv->state->hue_range_max) {
1655 hue = srv->state->hue_range_max;
1656 }
1657 srv->state->target_hue = hue;
1658
1659 /**
1660 * If the target state is equal to the current state, the transition shall not
1661 * be started and is considered complete.
1662 */
1663 if (srv->state->target_hue != srv->state->hue) {
1664 light_hsl_hue_tt_values(srv, trans_time, delay);
1665 } else {
1666 bt_mesh_light_server_state_change_t change = {
1667 .hsl_hue_set.hue = srv->state->hue,
1668 };
1669 bt_mesh_lighting_server_cb_evt_to_btc(
1670 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
1671
1672 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET) {
1673 send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS);
1674 }
1675 send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS);
1676
1677 bt_mesh_light_server_unlock();
1678 return;
1679 }
1680
1681 /* Copy the ctx of the received message */
1682 if (srv->transition.timer.work._reserved) {
1683 memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx));
1684 }
1685
1686 /* For Instantaneous Transition */
1687 if (srv->transition.counter == 0U) {
1688 srv->state->hue = srv->state->target_hue;
1689 }
1690
1691 srv->transition.just_started = true;
1692 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET) {
1693 send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS);
1694 }
1695 send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS);
1696
1697 bt_mesh_light_server_unlock();
1698
1699 bt_mesh_server_start_transition(&srv->transition);
1700 return;
1701 }
1702
light_hsl_sat_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1703 static void light_hsl_sat_set(struct bt_mesh_model *model,
1704 struct bt_mesh_msg_ctx *ctx,
1705 struct net_buf_simple *buf)
1706 {
1707 struct bt_mesh_light_hsl_sat_srv *srv = model->user_data;
1708 uint8_t tid = 0U, trans_time = 0U, delay = 0U;
1709 uint16_t saturation = 0U;
1710 bool optional = false;
1711 int64_t now = 0;
1712
1713 if (srv == NULL || srv->state == NULL) {
1714 BT_ERR("%s, Invalid model user data", __func__);
1715 return;
1716 }
1717
1718 saturation = net_buf_simple_pull_le16(buf);
1719 tid = net_buf_simple_pull_u8(buf);
1720
1721 if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
1722 return;
1723 }
1724
1725 /* Callback the received message to the application layer */
1726 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
1727 bt_mesh_light_server_recv_set_msg_t set = {
1728 .hsl_saturation_set.op_en = optional,
1729 .hsl_saturation_set.saturation = saturation,
1730 .hsl_saturation_set.tid = tid,
1731 .hsl_saturation_set.trans_time = trans_time,
1732 .hsl_saturation_set.delay = delay,
1733 };
1734 bt_mesh_lighting_server_cb_evt_to_btc(
1735 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
1736 return;
1737 }
1738
1739 if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
1740 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET) {
1741 send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS);
1742 }
1743 send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS);
1744 /* In this condition, no event will be callback to application layer */
1745 return;
1746 }
1747
1748 bt_mesh_light_server_lock();
1749
1750 bt_mesh_server_stop_transition(&srv->transition);
1751 bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
1752
1753 if (srv->state->saturation_range_min && saturation < srv->state->saturation_range_min) {
1754 saturation = srv->state->saturation_range_min;
1755 } else if (srv->state->saturation_range_max && saturation > srv->state->saturation_range_max) {
1756 saturation = srv->state->saturation_range_max;
1757 }
1758 srv->state->target_saturation = saturation;
1759
1760 /**
1761 * If the target state is equal to the current state, the transition shall not
1762 * be started and is considered complete.
1763 */
1764 if (srv->state->target_saturation != srv->state->saturation) {
1765 light_hsl_sat_tt_values(srv, trans_time, delay);
1766 } else {
1767 bt_mesh_light_server_state_change_t change = {
1768 .hsl_saturation_set.saturation = srv->state->saturation,
1769 };
1770 bt_mesh_lighting_server_cb_evt_to_btc(
1771 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
1772
1773 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET) {
1774 send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS);
1775 }
1776 send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS);
1777
1778 bt_mesh_light_server_unlock();
1779 return;
1780 }
1781
1782 /* Copy the ctx of the received message */
1783 if (srv->transition.timer.work._reserved) {
1784 memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx));
1785 }
1786
1787 /* For Instantaneous Transition */
1788 if (srv->transition.counter == 0U) {
1789 srv->state->saturation = srv->state->target_saturation;
1790 }
1791
1792 srv->transition.just_started = true;
1793 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET) {
1794 send_light_hsl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS);
1795 }
1796 send_light_hsl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS);
1797
1798 bt_mesh_light_server_unlock();
1799
1800 bt_mesh_server_start_transition(&srv->transition);
1801 return;
1802 }
1803
1804 /* Light xyL Server/Setup Server message handlers */
1805
send_light_xyl_status(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,bool publish,uint16_t opcode)1806 static void send_light_xyl_status(struct bt_mesh_model *model,
1807 struct bt_mesh_msg_ctx *ctx,
1808 bool publish, uint16_t opcode)
1809 {
1810 struct net_buf_simple *msg = NULL;
1811 uint8_t length = 2 + 9;
1812
1813 if (ctx == NULL && publish == false) {
1814 BT_ERR("%s, Invalid parameter", __func__);
1815 return;
1816 }
1817
1818 if (publish == false) {
1819 msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
1820 if (msg == NULL) {
1821 BT_ERR("%s, Out of memory", __func__);
1822 return;
1823 }
1824 } else {
1825 msg = bt_mesh_server_get_pub_msg(model, length);
1826 if (msg == NULL) {
1827 return;
1828 }
1829 }
1830
1831 bt_mesh_model_msg_init(msg, opcode);
1832 switch (opcode) {
1833 case BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS:
1834 case BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_STATUS: {
1835 struct bt_mesh_light_xyl_srv *srv = model->user_data;
1836 if (opcode == BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS) {
1837 net_buf_simple_add_le16(msg, srv->state->lightness);
1838 net_buf_simple_add_le16(msg, srv->state->x);
1839 net_buf_simple_add_le16(msg, srv->state->y);
1840 if (srv->transition.counter) {
1841 bt_mesh_server_calc_remain_time(&srv->transition);
1842 net_buf_simple_add_u8(msg, srv->transition.remain_time);
1843 }
1844 } else if (opcode == BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_STATUS) {
1845 net_buf_simple_add_le16(msg, srv->state->target_lightness);
1846 net_buf_simple_add_le16(msg, srv->state->target_x);
1847 net_buf_simple_add_le16(msg, srv->state->target_y);
1848 if (srv->transition.counter) {
1849 bt_mesh_server_calc_remain_time(&srv->transition);
1850 net_buf_simple_add_u8(msg, srv->transition.remain_time);
1851 }
1852 }
1853 break;
1854 }
1855 case BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_STATUS:
1856 if (model->id == BLE_MESH_MODEL_ID_LIGHT_XYL_SRV) {
1857 struct bt_mesh_light_xyl_srv *srv = model->user_data;
1858 net_buf_simple_add_le16(msg, srv->state->lightness_default);
1859 net_buf_simple_add_le16(msg, srv->state->x_default);
1860 net_buf_simple_add_le16(msg, srv->state->y_default);
1861 } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV) {
1862 struct bt_mesh_light_xyl_setup_srv *srv = model->user_data;
1863 net_buf_simple_add_le16(msg, srv->state->lightness_default);
1864 net_buf_simple_add_le16(msg, srv->state->x_default);
1865 net_buf_simple_add_le16(msg, srv->state->y_default);
1866 }
1867 break;
1868 case BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_STATUS:
1869 if (model->id == BLE_MESH_MODEL_ID_LIGHT_XYL_SRV) {
1870 struct bt_mesh_light_xyl_srv *srv = model->user_data;
1871 net_buf_simple_add_u8(msg, srv->state->status_code);
1872 net_buf_simple_add_le16(msg, srv->state->x_range_min);
1873 net_buf_simple_add_le16(msg, srv->state->x_range_max);
1874 net_buf_simple_add_le16(msg, srv->state->y_range_min);
1875 net_buf_simple_add_le16(msg, srv->state->y_range_max);
1876 } else if (model->id == BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV) {
1877 struct bt_mesh_light_xyl_setup_srv *srv = model->user_data;
1878 net_buf_simple_add_u8(msg, srv->state->status_code);
1879 net_buf_simple_add_le16(msg, srv->state->x_range_min);
1880 net_buf_simple_add_le16(msg, srv->state->x_range_max);
1881 net_buf_simple_add_le16(msg, srv->state->y_range_min);
1882 net_buf_simple_add_le16(msg, srv->state->y_range_max);
1883 }
1884 break;
1885 default:
1886 BT_WARN("Unknown Light xyL status opcode 0x%04x", opcode);
1887 if (publish == false) {
1888 bt_mesh_free_buf(msg);
1889 }
1890 return;
1891 }
1892
1893 if (publish == false) {
1894 BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
1895 bt_mesh_free_buf(msg);
1896 } else {
1897 BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
1898 }
1899 return;
1900 }
1901
light_xyl_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1902 static void light_xyl_get(struct bt_mesh_model *model,
1903 struct bt_mesh_msg_ctx *ctx,
1904 struct net_buf_simple *buf)
1905 {
1906 struct bt_mesh_light_xyl_srv *srv = model->user_data;
1907 uint16_t opcode = 0U;
1908
1909 if (srv == NULL || srv->state == NULL) {
1910 BT_ERR("%s, Invalid model user data", __func__);
1911 return;
1912 }
1913
1914 /* Callback the received message to the application layer */
1915 if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
1916 bt_mesh_lighting_server_cb_evt_to_btc(
1917 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG, model, ctx, NULL, 0);
1918 return;
1919 }
1920
1921 switch (ctx->recv_op) {
1922 case BLE_MESH_MODEL_OP_LIGHT_XYL_GET:
1923 opcode = BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS;
1924 break;
1925 case BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_GET:
1926 opcode = BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_STATUS;
1927 break;
1928 case BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_GET:
1929 opcode = BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_STATUS;
1930 break;
1931 case BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_GET:
1932 opcode = BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_STATUS;
1933 break;
1934 default:
1935 BT_WARN("Unknown Light xyL Get opcode 0x%04x", ctx->recv_op);
1936 return;
1937 }
1938
1939 send_light_xyl_status(model, ctx, false, opcode);
1940 return;
1941 }
1942
light_xyl_publish(struct bt_mesh_model * model,uint16_t opcode)1943 void light_xyl_publish(struct bt_mesh_model *model, uint16_t opcode)
1944 {
1945 if (model->user_data == NULL) {
1946 BT_ERR("%s, Invalid model user data", __func__);
1947 return;
1948 }
1949
1950 switch (model->id) {
1951 case BLE_MESH_MODEL_ID_LIGHT_XYL_SRV: {
1952 struct bt_mesh_light_xyl_srv *srv = model->user_data;
1953 if (srv->state == NULL) {
1954 BT_ERR("Invalid Light xyL Server state");
1955 return;
1956 }
1957 break;
1958 }
1959 case BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV: {
1960 struct bt_mesh_light_xyl_setup_srv *srv = model->user_data;
1961 if (srv->state == NULL) {
1962 BT_ERR("Invalid Light xyL Setup Server state");
1963 return;
1964 }
1965 break;
1966 }
1967 default:
1968 BT_ERR("Invalid Light xyL Server model 0x%04x", model->id);
1969 return;
1970 }
1971
1972 send_light_xyl_status(model, NULL, true, opcode);
1973 return;
1974 }
1975
light_xyl_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1976 static void light_xyl_set(struct bt_mesh_model *model,
1977 struct bt_mesh_msg_ctx *ctx,
1978 struct net_buf_simple *buf)
1979 {
1980 struct bt_mesh_light_xyl_srv *srv = model->user_data;
1981 uint8_t tid = 0U, trans_time = 0U, delay = 0U;
1982 uint16_t lightness = 0U, x = 0U, y = 0U;
1983 bool optional = false;
1984 int64_t now = 0;
1985
1986 if (srv == NULL || srv->state == NULL) {
1987 BT_ERR("%s, Invalid model user data", __func__);
1988 return;
1989 }
1990
1991 lightness = net_buf_simple_pull_le16(buf);
1992 x = net_buf_simple_pull_le16(buf);
1993 y = net_buf_simple_pull_le16(buf);
1994 tid = net_buf_simple_pull_u8(buf);
1995
1996 if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
1997 return;
1998 }
1999
2000 /* Callback the received message to the application layer */
2001 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
2002 bt_mesh_light_server_recv_set_msg_t set = {
2003 .xyl_set.op_en = optional,
2004 .xyl_set.lightness = lightness,
2005 .xyl_set.x = x,
2006 .xyl_set.y = y,
2007 .xyl_set.tid = tid,
2008 .xyl_set.trans_time = trans_time,
2009 .xyl_set.delay = delay,
2010 };
2011 bt_mesh_lighting_server_cb_evt_to_btc(
2012 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
2013 return;
2014 }
2015
2016 if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
2017 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_XYL_SET) {
2018 send_light_xyl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS);
2019 }
2020 send_light_xyl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS);
2021 /* In this condition, no event will be callback to application layer */
2022 return;
2023 }
2024
2025 bt_mesh_light_server_lock();
2026
2027 bt_mesh_server_stop_transition(&srv->transition);
2028 bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
2029
2030 srv->state->target_lightness = lightness;
2031 if (srv->state->x_range_min && x < srv->state->x_range_min) {
2032 x = srv->state->x_range_min;
2033 } else if (srv->state->x_range_max && x > srv->state->x_range_max) {
2034 x = srv->state->x_range_max;
2035 }
2036 srv->state->target_x = x;
2037 if (srv->state->y_range_min && y < srv->state->y_range_min) {
2038 y = srv->state->y_range_min;
2039 } else if (srv->state->y_range_max && y > srv->state->y_range_max) {
2040 y = srv->state->y_range_max;
2041 }
2042 srv->state->target_y = y;
2043
2044 /**
2045 * If the target state is equal to the current state, the transition shall not
2046 * be started and is considered complete.
2047 */
2048 if (srv->state->target_lightness != srv->state->lightness ||
2049 srv->state->target_x != srv->state->x ||
2050 srv->state->target_y != srv->state->y) {
2051 light_xyl_tt_values(srv, trans_time, delay);
2052 } else {
2053 bt_mesh_light_server_state_change_t change = {
2054 .xyl_set.lightness = srv->state->lightness,
2055 .xyl_set.x = srv->state->x,
2056 .xyl_set.y = srv->state->y,
2057 };
2058 bt_mesh_lighting_server_cb_evt_to_btc(
2059 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
2060
2061 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_XYL_SET) {
2062 send_light_xyl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS);
2063 }
2064 send_light_xyl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS);
2065
2066 bt_mesh_light_server_unlock();
2067 return;
2068 }
2069
2070 /* Copy the ctx of the received message */
2071 if (srv->transition.timer.work._reserved) {
2072 memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx));
2073 }
2074
2075 /* For Instantaneous Transition */
2076 if (srv->transition.counter == 0U) {
2077 srv->state->lightness = srv->state->target_lightness;
2078 srv->state->x = srv->state->target_x;
2079 srv->state->y = srv->state->target_y;
2080 }
2081
2082 srv->transition.just_started = true;
2083 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_XYL_SET) {
2084 send_light_xyl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS);
2085 }
2086 send_light_xyl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS);
2087
2088 bt_mesh_light_server_unlock();
2089
2090 bt_mesh_server_start_transition(&srv->transition);
2091 return;
2092 }
2093
light_xyl_default_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2094 static void light_xyl_default_set(struct bt_mesh_model *model,
2095 struct bt_mesh_msg_ctx *ctx,
2096 struct net_buf_simple *buf)
2097 {
2098 struct bt_mesh_light_xyl_setup_srv *srv = model->user_data;
2099 uint16_t lightness = 0U, x = 0U, y = 0U;
2100
2101 if (srv == NULL || srv->state == NULL) {
2102 BT_ERR("%s, Invalid model user data", __func__);
2103 return;
2104 }
2105
2106 lightness = net_buf_simple_pull_le16(buf);
2107 x = net_buf_simple_pull_le16(buf);
2108 y = net_buf_simple_pull_le16(buf);
2109
2110 /* Callback the received message to the application layer */
2111 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
2112 bt_mesh_light_server_recv_set_msg_t set = {
2113 .xyl_default_set.lightness = lightness,
2114 .xyl_default_set.x = x,
2115 .xyl_default_set.y = y,
2116 };
2117 bt_mesh_lighting_server_cb_evt_to_btc(
2118 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
2119 return;
2120 }
2121
2122 if (srv->state->x_range_min && x < srv->state->x_range_min) {
2123 x = srv->state->x_range_min;
2124 } else if (srv->state->x_range_max && x > srv->state->x_range_max) {
2125 x = srv->state->x_range_max;
2126 }
2127
2128 if (srv->state->y_range_min && y < srv->state->y_range_min) {
2129 y = srv->state->y_range_min;
2130 } else if (srv->state->y_range_max && y > srv->state->y_range_max) {
2131 y = srv->state->y_range_max;
2132 }
2133
2134 srv->state->lightness_default = lightness;
2135 srv->state->x_default = x;
2136 srv->state->y_default = y;
2137
2138 bt_mesh_light_server_state_change_t change = {
2139 .xyl_default_set.lightness = srv->state->lightness_default,
2140 .xyl_default_set.x = srv->state->x_default,
2141 .xyl_default_set.y = srv->state->y_default,
2142 };
2143 bt_mesh_lighting_server_cb_evt_to_btc(
2144 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
2145
2146 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET) {
2147 send_light_xyl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_STATUS);
2148 }
2149 send_light_xyl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_STATUS);
2150
2151 return;
2152 }
2153
light_xyl_range_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2154 static void light_xyl_range_set(struct bt_mesh_model *model,
2155 struct bt_mesh_msg_ctx *ctx,
2156 struct net_buf_simple *buf)
2157 {
2158 struct bt_mesh_light_xyl_setup_srv *srv = model->user_data;
2159 uint16_t x_min = 0U, x_max = 0U, y_min = 0U, y_max = 0U;
2160
2161 if (srv == NULL || srv->state == NULL) {
2162 BT_ERR("%s, Invalid model user data", __func__);
2163 return;
2164 }
2165
2166 x_min = net_buf_simple_pull_le16(buf);
2167 x_max = net_buf_simple_pull_le16(buf);
2168 y_min = net_buf_simple_pull_le16(buf);
2169 y_max = net_buf_simple_pull_le16(buf);
2170
2171 if (x_min > x_max) {
2172 BT_ERR("Invalid parameter, x min 0x%04x, x max 0x%04x",
2173 x_min, x_max);
2174 return;
2175 }
2176
2177 if (y_min > y_max) {
2178 BT_ERR("Invalid parameter, y min 0x%04x, y max 0x%04x",
2179 y_min, y_max);
2180 return;
2181 }
2182
2183 /* Callback the received message to the application layer */
2184 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
2185 bt_mesh_light_server_recv_set_msg_t set = {
2186 .xyl_range_set.x_range_min = x_min,
2187 .xyl_range_set.x_range_max = x_max,
2188 .xyl_range_set.y_range_min = y_min,
2189 .xyl_range_set.y_range_max = y_max,
2190 };
2191 bt_mesh_lighting_server_cb_evt_to_btc(
2192 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
2193 return;
2194 }
2195
2196 srv->state->status_code = BLE_MESH_RANGE_UPDATE_SUCCESS;
2197 srv->state->x_range_min = x_min;
2198 srv->state->x_range_max = x_max;
2199 srv->state->y_range_min = y_min;
2200 srv->state->y_range_max = y_max;
2201
2202 bt_mesh_light_server_state_change_t change = {
2203 .xyl_range_set.x_range_min = srv->state->x_range_min,
2204 .xyl_range_set.x_range_max = srv->state->x_range_max,
2205 .xyl_range_set.y_range_min = srv->state->y_range_min,
2206 .xyl_range_set.y_range_max = srv->state->y_range_max,
2207 };
2208 bt_mesh_lighting_server_cb_evt_to_btc(
2209 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
2210
2211 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET) {
2212 send_light_xyl_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_STATUS);
2213 }
2214 send_light_xyl_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_STATUS);
2215
2216 return;
2217 }
2218
2219 /* Light LC Server/Setup Server message handlers */
send_light_lc_status(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,bool publish,uint16_t opcode)2220 static void send_light_lc_status(struct bt_mesh_model *model,
2221 struct bt_mesh_msg_ctx *ctx,
2222 bool publish, uint16_t opcode)
2223 {
2224 struct bt_mesh_light_lc_srv *srv = model->user_data;
2225 struct net_buf_simple *msg = NULL;
2226 uint8_t length = 2 + 3;
2227
2228 if (ctx == NULL && publish == false) {
2229 BT_ERR("%s, Invalid parameter", __func__);
2230 return;
2231 }
2232
2233 if (publish == false) {
2234 msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
2235 if (msg == NULL) {
2236 BT_ERR("%s, Out of memory", __func__);
2237 return;
2238 }
2239 } else {
2240 msg = bt_mesh_server_get_pub_msg(model, length);
2241 if (msg == NULL) {
2242 return;
2243 }
2244 }
2245
2246 bt_mesh_model_msg_init(msg, opcode);
2247 switch (opcode) {
2248 case BLE_MESH_MODEL_OP_LIGHT_LC_MODE_STATUS:
2249 net_buf_simple_add_u8(msg, srv->lc->state.mode);
2250 break;
2251 case BLE_MESH_MODEL_OP_LIGHT_LC_OM_STATUS:
2252 net_buf_simple_add_u8(msg, srv->lc->state.occupancy_mode);
2253 break;
2254 case BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS:
2255 net_buf_simple_add_u8(msg, srv->lc->state.light_onoff);
2256 if (srv->transition.counter) {
2257 bt_mesh_server_calc_remain_time(&srv->transition);
2258 net_buf_simple_add_u8(msg, srv->lc->state.target_light_onoff);
2259 net_buf_simple_add_u8(msg, srv->transition.remain_time);
2260 }
2261 break;
2262 default:
2263 BT_WARN("Unknown Light LC status opcode 0x%04x", opcode);
2264 if (publish == false) {
2265 bt_mesh_free_buf(msg);
2266 }
2267 return;
2268 }
2269
2270 if (publish == false) {
2271 BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
2272 bt_mesh_free_buf(msg);
2273 } else {
2274 BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
2275 }
2276 return;
2277 }
2278
light_lc_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2279 static void light_lc_get(struct bt_mesh_model *model,
2280 struct bt_mesh_msg_ctx *ctx,
2281 struct net_buf_simple *buf)
2282 {
2283 struct bt_mesh_light_lc_srv *srv = model->user_data;
2284 uint16_t opcode = 0U;
2285
2286 if (srv == NULL || srv->lc == NULL) {
2287 BT_ERR("%s, Invalid model user data", __func__);
2288 return;
2289 }
2290
2291 /* Callback the received message to the application layer */
2292 if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
2293 bt_mesh_lighting_server_cb_evt_to_btc(
2294 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG, model, ctx, NULL, 0);
2295 return;
2296 }
2297
2298 switch (ctx->recv_op) {
2299 case BLE_MESH_MODEL_OP_LIGHT_LC_MODE_GET:
2300 opcode = BLE_MESH_MODEL_OP_LIGHT_LC_MODE_STATUS;
2301 break;
2302 case BLE_MESH_MODEL_OP_LIGHT_LC_OM_GET:
2303 opcode = BLE_MESH_MODEL_OP_LIGHT_LC_OM_STATUS;
2304 break;
2305 case BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_GET:
2306 opcode = BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS;
2307 break;
2308 default:
2309 BT_WARN("Unknown Light LC Get opcode 0x%04x", ctx->recv_op);
2310 return;
2311 }
2312
2313 send_light_lc_status(model, ctx, false, opcode);
2314 return;
2315 }
2316
light_lc_publish(struct bt_mesh_model * model,uint16_t opcode)2317 void light_lc_publish(struct bt_mesh_model *model, uint16_t opcode)
2318 {
2319 struct bt_mesh_light_lc_srv *srv = model->user_data;
2320
2321 if (srv == NULL || srv->lc == NULL) {
2322 BT_ERR("%s, Invalid model user data", __func__);
2323 return;
2324 }
2325
2326 send_light_lc_status(model, NULL, true, opcode);
2327 return;
2328 }
2329
light_lc_mode_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2330 static void light_lc_mode_set(struct bt_mesh_model *model,
2331 struct bt_mesh_msg_ctx *ctx,
2332 struct net_buf_simple *buf)
2333 {
2334 struct bt_mesh_light_lc_srv *srv = model->user_data;
2335 uint8_t mode = 0U;
2336
2337 if (srv == NULL || srv->lc == NULL) {
2338 BT_ERR("%s, Invalid model user data", __func__);
2339 return;
2340 }
2341
2342 mode = net_buf_simple_pull_u8(buf);
2343 if (mode > BLE_MESH_STATE_ON) {
2344 BT_ERR("Invalid LC Mode 0x%02x", mode);
2345 return;
2346 }
2347
2348 /* Callback the received message to the application layer */
2349 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
2350 bt_mesh_light_server_recv_set_msg_t set = {
2351 .lc_mode_set.mode = mode,
2352 };
2353 bt_mesh_lighting_server_cb_evt_to_btc(
2354 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
2355 return;
2356 }
2357
2358 srv->lc->state.mode = mode;
2359
2360 bt_mesh_light_server_state_change_t change = {
2361 .lc_mode_set.mode = srv->lc->state.mode,
2362 };
2363 bt_mesh_lighting_server_cb_evt_to_btc(
2364 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
2365
2366 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET) {
2367 send_light_lc_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LC_MODE_STATUS);
2368 }
2369 send_light_lc_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LC_MODE_STATUS);
2370
2371 return;
2372 }
2373
light_lc_om_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2374 static void light_lc_om_set(struct bt_mesh_model *model,
2375 struct bt_mesh_msg_ctx *ctx,
2376 struct net_buf_simple *buf)
2377 {
2378 struct bt_mesh_light_lc_srv *srv = model->user_data;
2379 uint8_t om = 0U;
2380
2381 if (srv == NULL || srv->lc == NULL) {
2382 BT_ERR("%s, Invalid model user data", __func__);
2383 return;
2384 }
2385
2386 om = net_buf_simple_pull_u8(buf);
2387 if (om > BLE_MESH_STATE_ON) {
2388 BT_ERR("Invalid LC Occupancy Mode 0x%02x", om);
2389 return;
2390 }
2391
2392 /* Callback the received message to the application layer */
2393 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
2394 bt_mesh_light_server_recv_set_msg_t set = {
2395 .lc_om_set.mode = om,
2396 };
2397 bt_mesh_lighting_server_cb_evt_to_btc(
2398 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
2399 return;
2400 }
2401
2402 srv->lc->state.occupancy_mode = om;
2403
2404 bt_mesh_light_server_state_change_t change = {
2405 .lc_om_set.mode = srv->lc->state.occupancy_mode,
2406 };
2407 bt_mesh_lighting_server_cb_evt_to_btc(
2408 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
2409
2410 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET) {
2411 send_light_lc_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LC_OM_STATUS);
2412 }
2413 send_light_lc_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LC_OM_STATUS);
2414
2415 return;
2416 }
2417
light_lc_light_onoff_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2418 static void light_lc_light_onoff_set(struct bt_mesh_model *model,
2419 struct bt_mesh_msg_ctx *ctx,
2420 struct net_buf_simple *buf)
2421 {
2422 struct bt_mesh_light_lc_srv *srv = model->user_data;
2423 uint8_t tid = 0U, trans_time = 0U, delay = 0U;
2424 bool optional = false;
2425 uint8_t onoff = 0U;
2426 int64_t now = 0;
2427
2428 if (srv == NULL || srv->lc == NULL) {
2429 BT_ERR("%s, Invalid model user data", __func__);
2430 return;
2431 }
2432
2433 onoff = net_buf_simple_pull_u8(buf);
2434 tid = net_buf_simple_pull_u8(buf);
2435
2436 if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
2437 return;
2438 }
2439
2440 /* Callback the received message to the application layer */
2441 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
2442 bt_mesh_light_server_recv_set_msg_t set = {
2443 .lc_light_onoff_set.op_en = optional,
2444 .lc_light_onoff_set.light_onoff = onoff,
2445 .lc_light_onoff_set.tid = tid,
2446 .lc_light_onoff_set.trans_time = trans_time,
2447 .lc_light_onoff_set.delay = delay,
2448 };
2449 bt_mesh_lighting_server_cb_evt_to_btc(
2450 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
2451 return;
2452 }
2453
2454 if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
2455 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET) {
2456 send_light_lc_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS);
2457 }
2458 send_light_lc_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS);
2459 /* In this condition, no event will be callback to application layer */
2460 return;
2461 }
2462
2463 bt_mesh_light_server_lock();
2464
2465 bt_mesh_server_stop_transition(&srv->transition);
2466 bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
2467
2468 srv->lc->state.target_light_onoff = onoff;
2469
2470 if (srv->lc->state.target_light_onoff != srv->lc->state.light_onoff) {
2471 light_lc_tt_values(srv, trans_time, delay);
2472 } else {
2473 bt_mesh_light_server_state_change_t change = {
2474 .lc_light_onoff_set.onoff = srv->lc->state.light_onoff,
2475 };
2476 bt_mesh_lighting_server_cb_evt_to_btc(
2477 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
2478
2479 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET) {
2480 send_light_lc_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS);
2481 }
2482 send_light_lc_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS);
2483
2484 bt_mesh_light_server_unlock();
2485 return;
2486 }
2487
2488 /* Copy the ctx of the received message */
2489 if (srv->transition.timer.work._reserved) {
2490 memcpy(srv->transition.timer.work._reserved, ctx, sizeof(struct bt_mesh_msg_ctx));
2491 }
2492
2493 /* For Instantaneous Transition */
2494 if (srv->transition.counter == 0U) {
2495 srv->lc->state.light_onoff = srv->lc->state.target_light_onoff;
2496 }
2497
2498 srv->transition.just_started = true;
2499 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET) {
2500 send_light_lc_status(model, ctx, false, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS);
2501 }
2502 send_light_lc_status(model, NULL, true, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS);
2503
2504 bt_mesh_light_server_unlock();
2505
2506 bt_mesh_server_start_transition(&srv->transition);
2507 return;
2508 }
2509
light_lc_sensor_status(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2510 static void light_lc_sensor_status(struct bt_mesh_model *model,
2511 struct bt_mesh_msg_ctx *ctx,
2512 struct net_buf_simple *buf)
2513 {
2514 /**
2515 * When a Light LC Server receives a Sensor Status message, and if the message
2516 * Raw field contains a Raw Value for the Motion Sensed Property, and the value
2517 * is greater than 0, or a Raw Value for the People Count Property, and the
2518 * value is greater than 0, or a Raw Value for the Presence Detected Property,
2519 * and the value is greater than 0, then it shall set the Light LC Occupancy
2520 * state to 0b1.
2521 * If the message Raw field contains a Raw Value for the Time Since Motion Sensed
2522 * device property, which represents a value less than or equal to the value of
2523 * the Light LC Occupancy Delay state, it shall delay setting the Light LC Occupancy
2524 * state to 0b1 by the difference between the value of the Light LC Occupancy Delay
2525 * state and the received Time Since Motion value.
2526 * When a Light LC Server receives a Sensor Status message, and if the message Raw
2527 * field contains a Raw Value for the Present Ambient Light Level device property,
2528 * it shall set the Light LC Ambient LuxLevel state to the Represented Value of the
2529 * received Present Ambient Light Level.
2530 *
2531 * Motion Sensed: 1 octet, 0x0042
2532 * People Count: 2 octets, 0x004C
2533 * Presence Detected: 1 octet, 0x004D
2534 *
2535 * Time Since Motion Sensed: 2 octets, 0x0068
2536 *
2537 * Present Ambient Light Level: 4 octets, 0x004E
2538 */
2539 struct bt_mesh_light_lc_srv *srv = model->user_data;
2540 bt_mesh_light_server_state_change_t change = {0};
2541 uint16_t mpid = 0U, prop_id = 0U;
2542 uint8_t length = 0U;
2543
2544 if (srv == NULL || srv->lc == NULL) {
2545 BT_ERR("%s, Invalid model user data", __func__);
2546 return;
2547 }
2548
2549 if (srv->rsp_ctrl.status_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
2550 bt_mesh_light_server_recv_status_msg_t status = {
2551 .sensor_status.data = buf,
2552 };
2553 bt_mesh_lighting_server_cb_evt_to_btc(
2554 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_STATUS_MSG, model, ctx, (const uint8_t *)&status, sizeof(status));
2555 return;
2556 }
2557
2558 mpid = net_buf_simple_pull_le16(buf);
2559 if (mpid & BIT(0)) {
2560 length = (uint8_t)((mpid & 0xff) >> 1);
2561 uint8_t msb = net_buf_simple_pull_u8(buf);
2562 prop_id = (uint16_t)(msb << 8) | (uint16_t)(mpid >> 8);
2563 } else {
2564 length = (uint8_t)((mpid & 0x1f) >> 1);
2565 prop_id = (uint16_t)(mpid >> 5);
2566 }
2567
2568 change.sensor_status.property_id = prop_id;
2569
2570 switch (prop_id) {
2571 case BLE_MESH_MOTION_SENSED: {
2572 if (length != BLE_MESH_MOTION_SENSED_LEN || length != buf->len) {
2573 BT_WARN("Invalid Motion Sensed Property length %d", length);
2574 return;
2575 }
2576 uint8_t val = net_buf_simple_pull_u8(buf);
2577 if (val > 0) {
2578 srv->lc->state.occupancy = BLE_MESH_STATE_ON;
2579
2580 change.sensor_status.state.occupancy = srv->lc->state.occupancy;
2581 bt_mesh_lighting_server_cb_evt_to_btc(
2582 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
2583 }
2584 break;
2585 }
2586 case BLE_MESH_PEOPLE_COUNT: {
2587 if (length != BLE_MESH_PEOPLE_COUNT_LEN || length != buf->len) {
2588 BT_WARN("Invalid Motion Sensed Property length %d", length);
2589 return;
2590 }
2591 uint16_t val = net_buf_simple_pull_le16(buf);
2592 if (val > 0) {
2593 srv->lc->state.occupancy = BLE_MESH_STATE_ON;
2594
2595 change.sensor_status.state.occupancy = srv->lc->state.occupancy;
2596 bt_mesh_lighting_server_cb_evt_to_btc(
2597 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
2598 }
2599 break;
2600 }
2601 case BLE_MESH_PRESENCE_DETECTED: {
2602 if (length != BLE_MESH_PRESENCE_DETECTED_LEN || length != buf->len) {
2603 BT_WARN("Invalid Motion Sensed Property length %d", length);
2604 return;
2605 }
2606 uint8_t val = net_buf_simple_pull_u8(buf);
2607 if (val > 0) {
2608 srv->lc->state.occupancy = BLE_MESH_STATE_ON;
2609
2610 change.sensor_status.state.occupancy = srv->lc->state.occupancy;
2611 bt_mesh_lighting_server_cb_evt_to_btc(
2612 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
2613 }
2614 break;
2615 }
2616 case BLE_MESH_TIME_SINCE_MOTION_SENSED: {
2617 if (length != BLE_MESH_TIME_SINCE_MOTION_SENSED_LEN || length != buf->len) {
2618 BT_WARN("Invalid Motion Sensed Property length %d", length);
2619 return;
2620 }
2621 uint16_t val = net_buf_simple_pull_le16(buf);
2622 if (val <= srv->lc->prop_state.time_occupancy_delay) {
2623 srv->lc->prop_state.set_occupancy_to_1_delay =
2624 srv->lc->prop_state.time_occupancy_delay - val;
2625
2626 change.sensor_status.state.set_occupancy_to_1_delay = srv->lc->prop_state.set_occupancy_to_1_delay;
2627 bt_mesh_lighting_server_cb_evt_to_btc(
2628 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
2629 }
2630 break;
2631 }
2632 case BLE_MESH_PRESENT_AMBIENT_LIGHT_LEVEL: {
2633 /**
2634 * Present Ambient Light Level device property is 4 octets, but ambient
2635 * luxlevel length is 3 octets, and other devices may send Sensor Status
2636 * which only contains 3 octets just for Light LC Server.
2637 * Here we just check if the length is larger than 3.
2638 */
2639 if (buf->len < 3) {
2640 BT_WARN("Invalid Motion Sensed Property length %d", buf->len);
2641 return;
2642 }
2643 uint16_t lsb = net_buf_simple_pull_le16(buf);
2644 uint8_t msb = net_buf_simple_pull_u8(buf);
2645 srv->lc->state.ambient_luxlevel = (msb << 16) | lsb;
2646
2647 change.sensor_status.state.ambient_luxlevel = srv->lc->state.ambient_luxlevel;
2648 bt_mesh_lighting_server_cb_evt_to_btc(
2649 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
2650 break;
2651 }
2652 default:
2653 break;
2654 }
2655 }
2656
get_light_lc_prop_val(struct bt_mesh_model * model,uint16_t prop_id)2657 static uint8_t *get_light_lc_prop_val(struct bt_mesh_model *model, uint16_t prop_id)
2658 {
2659 struct bt_mesh_light_lc_setup_srv *srv = model->user_data;
2660 uint8_t *val = NULL;
2661
2662 switch (prop_id) {
2663 case BLE_MESH_LIGHT_CONTROL_TIME_OCCUPANCY_DELAY:
2664 val = (uint8_t *)&srv->lc->prop_state.time_occupancy_delay;
2665 break;
2666 case BLE_MESH_LIGHT_CONTROL_TIME_FADE_ON:
2667 val = (uint8_t *)&srv->lc->prop_state.time_fade_on;
2668 break;
2669 case BLE_MESH_LIGHT_CONTROL_TIME_RUN_ON:
2670 val = (uint8_t *)&srv->lc->prop_state.time_run_on;
2671 break;
2672 case BLE_MESH_LIGHT_CONTROL_TIME_FADE:
2673 val = (uint8_t *)&srv->lc->prop_state.time_fade;
2674 break;
2675 case BLE_MESH_LIGHT_CONTROL_TIME_PROLONG:
2676 val = (uint8_t *)&srv->lc->prop_state.time_prolong;
2677 break;
2678 case BLE_MESH_LIGHT_CONTROL_TIME_FADE_STANDBY_AUTO:
2679 val = (uint8_t *)&srv->lc->prop_state.time_fade_standby_auto;
2680 break;
2681 case BLE_MESH_LIGHT_CONTROL_TIME_FADE_STANDBY_MANUAL:
2682 val = (uint8_t *)&srv->lc->prop_state.time_fade_standby_manual;
2683 break;
2684 case BLE_MESH_LIGHT_CONTROL_LIGHTNESS_ON:
2685 val = (uint8_t *)&srv->lc->prop_state.lightness_on;
2686 break;
2687 case BLE_MESH_LIGHT_CONTROL_LIGHTNESS_PROLONG:
2688 val = (uint8_t *)&srv->lc->prop_state.lightness_prolong;
2689 break;
2690 case BLE_MESH_LIGHT_CONTROL_LIGHTNESS_STANDBY:
2691 val = (uint8_t *)&srv->lc->prop_state.lightness_standby;
2692 break;
2693 case BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_ON:
2694 val = (uint8_t *)&srv->lc->prop_state.ambient_luxlevel_on;
2695 break;
2696 case BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_PROLONG:
2697 val = (uint8_t *)&srv->lc->prop_state.ambient_luxlevel_prolong;
2698 break;
2699 case BLE_MESH_LIGHT_CONTROL_AMBIENT_LUXLEVEL_STANDBY:
2700 val = (uint8_t *)&srv->lc->prop_state.ambient_luxlevel_standby;
2701 break;
2702 case BLE_MESH_LIGHT_CONTROL_REGULATOR_KIU:
2703 val = (uint8_t *)&srv->lc->prop_state.regulator_kiu;
2704 break;
2705 case BLE_MESH_LIGHT_CONTROL_REGULATOR_KID:
2706 val = (uint8_t *)&srv->lc->prop_state.regulator_kid;
2707 break;
2708 case BLE_MESH_LIGHT_CONTROL_REGULATOR_KPU:
2709 val = (uint8_t *)&srv->lc->prop_state.regulator_kpu;
2710 break;
2711 case BLE_MESH_LIGHT_CONTROL_REGULATOR_KPD:
2712 val = (uint8_t *)&srv->lc->prop_state.regulator_kpd;
2713 break;
2714 case BLE_MESH_LIGHT_CONTROL_REGULATOR_ACCURACY:
2715 val = (uint8_t *)&srv->lc->prop_state.regulator_accuracy;
2716 break;
2717 }
2718
2719 return val;
2720 }
2721
bt_mesh_get_lc_prop_value(struct bt_mesh_model * model,uint16_t prop_id)2722 uint8_t *bt_mesh_get_lc_prop_value(struct bt_mesh_model *model, uint16_t prop_id)
2723 {
2724 if (model == NULL) {
2725 BT_ERR("%s, Invalid parameter", __func__);
2726 return NULL;
2727 }
2728
2729 return get_light_lc_prop_val(model, prop_id);
2730 }
2731
send_light_lc_prop_status(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,uint16_t prop_id,bool publish)2732 static void send_light_lc_prop_status(struct bt_mesh_model *model,
2733 struct bt_mesh_msg_ctx *ctx,
2734 uint16_t prop_id, bool publish)
2735 {
2736 struct net_buf_simple *msg = NULL;
2737 uint8_t length = 1 + 2 + 4;
2738 uint8_t *prop_val = NULL;
2739
2740 prop_val = get_light_lc_prop_val(model, prop_id);
2741 if (prop_val == NULL) {
2742 BT_ERR("Failed to get Light LC Property value");
2743 return;
2744 }
2745
2746 if (publish == false) {
2747 msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
2748 if (msg == NULL) {
2749 BT_ERR("%s, Out of memory", __func__);
2750 return;
2751 }
2752 } else {
2753 msg = bt_mesh_server_get_pub_msg(model, length);
2754 if (msg == NULL) {
2755 return;
2756 }
2757 }
2758
2759 bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_STATUS);
2760 net_buf_simple_add_le16(msg, prop_id);
2761 net_buf_simple_add_mem(msg, prop_val, bt_mesh_get_dev_prop_len(prop_id));
2762
2763 if (publish == false) {
2764 BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
2765 bt_mesh_free_buf(msg);
2766 } else {
2767 BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
2768 }
2769 return;
2770 }
2771
light_lc_prop_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2772 static void light_lc_prop_get(struct bt_mesh_model *model,
2773 struct bt_mesh_msg_ctx *ctx,
2774 struct net_buf_simple *buf)
2775 {
2776 struct bt_mesh_light_lc_setup_srv *srv = model->user_data;
2777 uint16_t prop_id = 0U;
2778
2779 if (srv == NULL || srv->lc == NULL) {
2780 BT_ERR("%s, Invalid model user data", __func__);
2781 return;
2782 }
2783
2784 prop_id = net_buf_simple_pull_le16(buf);
2785 if (prop_id < 0x002B || prop_id > 0x003C) {
2786 BT_ERR("Invalid Light LC Property ID 0x%04x", prop_id);
2787 return;
2788 }
2789
2790 /* Callback the received message to the application layer */
2791 if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
2792 bt_mesh_light_server_recv_get_msg_t get = {
2793 .lc_property_get.id = net_buf_simple_pull_le16(buf),
2794 };
2795 bt_mesh_lighting_server_cb_evt_to_btc(
2796 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_GET_MSG, model, ctx, (const uint8_t *)&get, sizeof(get));
2797 return;
2798 }
2799
2800 send_light_lc_prop_status(model, ctx, prop_id, false);
2801 return;
2802 }
2803
light_lc_prop_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)2804 static void light_lc_prop_set(struct bt_mesh_model *model,
2805 struct bt_mesh_msg_ctx *ctx,
2806 struct net_buf_simple *buf)
2807 {
2808 struct bt_mesh_light_lc_setup_srv *srv = model->user_data;
2809 uint8_t *prop_val = NULL, expect_len = 0U;
2810 uint16_t prop_id = 0U;
2811
2812 if (srv == NULL || srv->lc == NULL) {
2813 BT_ERR("%s, Invalid model user data", __func__);
2814 return;
2815 }
2816
2817 prop_id = net_buf_simple_pull_le16(buf);
2818 if (prop_id < 0x002B || prop_id > 0x003C) {
2819 BT_ERR("Invalid Light LC Property ID 0x%04x", prop_id);
2820 return;
2821 }
2822
2823 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
2824 bt_mesh_light_server_recv_set_msg_t set = {
2825 .lc_property_set.id = net_buf_simple_pull_le16(buf),
2826 .lc_property_set.value = buf,
2827 };
2828 bt_mesh_lighting_server_cb_evt_to_btc(
2829 BTC_BLE_MESH_EVT_LIGHTING_SERVER_RECV_SET_MSG, model, ctx, (const uint8_t *)&set, sizeof(set));
2830 return;
2831 }
2832
2833 expect_len = bt_mesh_get_dev_prop_len(prop_id);
2834 if (buf->len != expect_len) {
2835 BT_ERR("Invalid Light LC Property 0x%04x length, expect %d, actual %d",
2836 prop_id, expect_len, buf->len);
2837 return;
2838 }
2839
2840 prop_val = get_light_lc_prop_val(model, prop_id);
2841 if (prop_val == NULL) {
2842 BT_ERR("Failed to get Light LC Property value");
2843 return;
2844 }
2845
2846 memcpy(prop_val, buf->data, buf->len);
2847
2848 bt_mesh_light_server_state_change_t change = {
2849 .lc_property_set.id = prop_id,
2850 .lc_property_set.value = buf,
2851 };
2852 bt_mesh_lighting_server_cb_evt_to_btc(
2853 BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change));
2854
2855 if (ctx->recv_op == BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET) {
2856 send_light_lc_prop_status(model, ctx, prop_id, false);
2857 }
2858 send_light_lc_prop_status(model, ctx, prop_id, true);
2859
2860 return;
2861 }
2862
2863 /* message handlers (End) */
2864
2865 /* Mapping of message handlers for Light Lightness Server (0x1300) */
2866 const struct bt_mesh_model_op bt_mesh_light_lightness_srv_op[] = {
2867 { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_GET, 0, light_lightness_get },
2868 { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET, 3, light_lightness_set },
2869 { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_SET_UNACK, 3, light_lightness_set },
2870 { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_GET, 0, light_lightness_get },
2871 { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET, 3, light_lightness_linear_set },
2872 { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_SET_UNACK, 3, light_lightness_linear_set },
2873 { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LAST_GET, 0, light_lightness_get },
2874 { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_GET, 0, light_lightness_get },
2875 { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_GET, 0, light_lightness_get },
2876 BLE_MESH_MODEL_OP_END,
2877 };
2878
2879 /* Mapping of message handlers for Light Lightness Setup Server (0x1301) */
2880 const struct bt_mesh_model_op bt_mesh_light_lightness_setup_srv_op[] = {
2881 { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET, 2, light_lightness_default_set },
2882 { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_DEFAULT_SET_UNACK, 2, light_lightness_default_set },
2883 { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET, 4, light_lightness_range_set },
2884 { BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_RANGE_SET_UNACK, 4, light_lightness_range_set },
2885 BLE_MESH_MODEL_OP_END,
2886 };
2887
2888 /* Mapping of message handlers for Light CTL Server (0x1303) */
2889 const struct bt_mesh_model_op bt_mesh_light_ctl_srv_op[] = {
2890 { BLE_MESH_MODEL_OP_LIGHT_CTL_GET, 0, light_ctl_get },
2891 { BLE_MESH_MODEL_OP_LIGHT_CTL_SET, 7, light_ctl_set },
2892 { BLE_MESH_MODEL_OP_LIGHT_CTL_SET_UNACK, 7, light_ctl_set },
2893 { BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_GET, 0, light_ctl_get },
2894 { BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_GET, 0, light_ctl_get },
2895 BLE_MESH_MODEL_OP_END,
2896 };
2897
2898 /* Mapping of message handlers for Light CTL Setup Server (0x1304) */
2899 const struct bt_mesh_model_op bt_mesh_light_ctl_setup_srv_op[] = {
2900 { BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET, 6, light_ctl_default_set },
2901 { BLE_MESH_MODEL_OP_LIGHT_CTL_DEFAULT_SET_UNACK, 6, light_ctl_default_set },
2902 { BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET, 4, light_ctl_temp_range_set },
2903 { BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_RANGE_SET_UNACK, 4, light_ctl_temp_range_set },
2904 BLE_MESH_MODEL_OP_END,
2905 };
2906
2907 /* Mapping of message handlers for Light CTL Temperature Server (0x1306) */
2908 const struct bt_mesh_model_op bt_mesh_light_ctl_temp_srv_op[] = {
2909 { BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_GET, 0, light_ctl_get },
2910 { BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET, 5, light_ctl_temp_set },
2911 { BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_SET_UNACK, 5, light_ctl_temp_set },
2912 BLE_MESH_MODEL_OP_END,
2913 };
2914
2915 /* Mapping of message handlers for Light HSL Server (0x1307) */
2916 const struct bt_mesh_model_op bt_mesh_light_hsl_srv_op[] = {
2917 { BLE_MESH_MODEL_OP_LIGHT_HSL_GET, 0, light_hsl_get },
2918 { BLE_MESH_MODEL_OP_LIGHT_HSL_SET, 7, light_hsl_set },
2919 { BLE_MESH_MODEL_OP_LIGHT_HSL_SET_UNACK, 7, light_hsl_set },
2920 { BLE_MESH_MODEL_OP_LIGHT_HSL_TARGET_GET, 0, light_hsl_get },
2921 { BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_GET, 0, light_hsl_get },
2922 { BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_GET, 0, light_hsl_get },
2923 BLE_MESH_MODEL_OP_END,
2924 };
2925
2926 /* Mapping of message handlers for Light HSL Setup Server (0x1308) */
2927 const struct bt_mesh_model_op bt_mesh_light_hsl_setup_srv_op[] = {
2928 { BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET, 6, light_hsl_default_set },
2929 { BLE_MESH_MODEL_OP_LIGHT_HSL_DEFAULT_SET_UNACK, 6, light_hsl_default_set },
2930 { BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET, 8, light_hsl_range_set },
2931 { BLE_MESH_MODEL_OP_LIGHT_HSL_RANGE_SET_UNACK, 8, light_hsl_range_set },
2932 BLE_MESH_MODEL_OP_END,
2933 };
2934
2935 /* Mapping of message handlers for Light HSL Hue Server (0x130A) */
2936 const struct bt_mesh_model_op bt_mesh_light_hsl_hue_srv_op[] = {
2937 { BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_GET, 0, light_hsl_get },
2938 { BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET, 3, light_hsl_hue_set },
2939 { BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_SET_UNACK, 3, light_hsl_hue_set },
2940 BLE_MESH_MODEL_OP_END,
2941 };
2942
2943 /* Mapping of message handlers for Light HSL Saturation Server (0x130B) */
2944 const struct bt_mesh_model_op bt_mesh_light_hsl_sat_srv_op[] = {
2945 { BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_GET, 0, light_hsl_get },
2946 { BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET, 3, light_hsl_sat_set },
2947 { BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_SET_UNACK, 3, light_hsl_sat_set },
2948 BLE_MESH_MODEL_OP_END,
2949 };
2950
2951 /* Mapping of message handlers for Light xyL Server (0x130C) */
2952 const struct bt_mesh_model_op bt_mesh_light_xyl_srv_op[] = {
2953 { BLE_MESH_MODEL_OP_LIGHT_XYL_GET, 0, light_xyl_get },
2954 { BLE_MESH_MODEL_OP_LIGHT_XYL_SET, 7, light_xyl_set },
2955 { BLE_MESH_MODEL_OP_LIGHT_XYL_SET_UNACK, 7, light_xyl_set },
2956 { BLE_MESH_MODEL_OP_LIGHT_XYL_TARGET_GET, 0, light_xyl_get },
2957 { BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_GET, 0, light_xyl_get },
2958 { BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_GET, 0, light_xyl_get },
2959 BLE_MESH_MODEL_OP_END,
2960 };
2961
2962 /* Mapping of message handlers for Light xyL Setup Server (0x130D) */
2963 const struct bt_mesh_model_op bt_mesh_light_xyl_setup_srv_op[] = {
2964 { BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET, 6, light_xyl_default_set },
2965 { BLE_MESH_MODEL_OP_LIGHT_XYL_DEFAULT_SET_UNACK, 6, light_xyl_default_set },
2966 { BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET, 8, light_xyl_range_set },
2967 { BLE_MESH_MODEL_OP_LIGHT_XYL_RANGE_SET_UNACK, 8, light_xyl_range_set },
2968 BLE_MESH_MODEL_OP_END,
2969 };
2970
2971 /* Mapping of message handlers for Light LC Server (0x130F) */
2972 const struct bt_mesh_model_op bt_mesh_light_lc_srv_op[] = {
2973 { BLE_MESH_MODEL_OP_LIGHT_LC_MODE_GET, 0, light_lc_get },
2974 { BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET, 1, light_lc_mode_set },
2975 { BLE_MESH_MODEL_OP_LIGHT_LC_MODE_SET_UNACK, 1, light_lc_mode_set },
2976 { BLE_MESH_MODEL_OP_LIGHT_LC_OM_GET, 0, light_lc_get },
2977 { BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET, 1, light_lc_om_set },
2978 { BLE_MESH_MODEL_OP_LIGHT_LC_OM_SET_UNACK, 1, light_lc_om_set },
2979 { BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_GET, 0, light_lc_get },
2980 { BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET, 2, light_lc_light_onoff_set },
2981 { BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_SET_UNACK, 2, light_lc_light_onoff_set },
2982 { BLE_MESH_MODEL_OP_SENSOR_STATUS, 3, light_lc_sensor_status },
2983 BLE_MESH_MODEL_OP_END,
2984 };
2985
2986 /* Mapping of message handlers for Light LC Setup Server (0x1310) */
2987 const struct bt_mesh_model_op bt_mesh_light_lc_setup_srv_op[] = {
2988 { BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_GET, 2, light_lc_prop_get },
2989 { BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET, 3, light_lc_prop_set },
2990 { BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET_UNACK, 3, light_lc_prop_set },
2991 BLE_MESH_MODEL_OP_END,
2992 };
2993
light_server_init(struct bt_mesh_model * model)2994 static int light_server_init(struct bt_mesh_model *model)
2995 {
2996 if (model->user_data == NULL) {
2997 BT_ERR("Invalid Lighting Server user data, model id 0x%04x", model->id);
2998 return -EINVAL;
2999 }
3000
3001 switch (model->id) {
3002 case BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV: {
3003 struct bt_mesh_light_lightness_srv *srv = model->user_data;
3004 if (srv->state == NULL) {
3005 BT_ERR("Invalid Light Lightness State");
3006 return -EINVAL;
3007 }
3008 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3009 bt_mesh_server_alloc_ctx(&srv->actual_transition.timer.work);
3010 bt_mesh_server_alloc_ctx(&srv->linear_transition.timer.work);
3011 k_delayed_work_init(&srv->actual_transition.timer, light_lightness_actual_work_handler);
3012 k_delayed_work_init(&srv->linear_transition.timer, light_lightness_linear_work_handler);
3013 }
3014 srv->model = model;
3015 break;
3016 }
3017 case BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV: {
3018 struct bt_mesh_light_lightness_setup_srv *srv = model->user_data;
3019 if (srv->state == NULL) {
3020 BT_ERR("Invalid Light Lightness State");
3021 return -EINVAL;
3022 }
3023 srv->model = model;
3024 break;
3025 }
3026 case BLE_MESH_MODEL_ID_LIGHT_CTL_SRV: {
3027 struct bt_mesh_light_ctl_srv *srv = model->user_data;
3028 if (srv->state == NULL) {
3029 BT_ERR("Invalid Light CTL State");
3030 return -EINVAL;
3031 }
3032 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3033 bt_mesh_server_alloc_ctx(&srv->transition.timer.work);
3034 k_delayed_work_init(&srv->transition.timer, light_ctl_work_handler);
3035 }
3036 srv->model = model;
3037 break;
3038 }
3039 case BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV: {
3040 struct bt_mesh_light_ctl_setup_srv *srv = model->user_data;
3041 if (srv->state == NULL) {
3042 BT_ERR("Invalid Light CTL State");
3043 return -EINVAL;
3044 }
3045 srv->model = model;
3046 break;
3047 }
3048 case BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV: {
3049 struct bt_mesh_light_ctl_temp_srv *srv = model->user_data;
3050 if (srv->state == NULL) {
3051 BT_ERR("Invalid Light CTL State");
3052 return -EINVAL;
3053 }
3054 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3055 bt_mesh_server_alloc_ctx(&srv->transition.timer.work);
3056 k_delayed_work_init(&srv->transition.timer, light_ctl_temp_work_handler);
3057 }
3058 srv->model = model;
3059 break;
3060 }
3061 case BLE_MESH_MODEL_ID_LIGHT_HSL_SRV: {
3062 struct bt_mesh_light_hsl_srv *srv = model->user_data;
3063 if (srv->state == NULL) {
3064 BT_ERR("Invalid Light HSL State");
3065 return -EINVAL;
3066 }
3067 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3068 bt_mesh_server_alloc_ctx(&srv->transition.timer.work);
3069 k_delayed_work_init(&srv->transition.timer, light_hsl_work_handler);
3070 }
3071 srv->model = model;
3072 break;
3073 }
3074 case BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV: {
3075 struct bt_mesh_light_hsl_setup_srv *srv = model->user_data;
3076 if (srv->state == NULL) {
3077 BT_ERR("Invalid Light HSL State");
3078 return -EINVAL;
3079 }
3080 srv->model = model;
3081 break;
3082 }
3083 case BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV: {
3084 struct bt_mesh_light_hsl_hue_srv *srv = model->user_data;
3085 if (srv->state == NULL) {
3086 BT_ERR("Invalid Light HSL State");
3087 return -EINVAL;
3088 }
3089 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3090 bt_mesh_server_alloc_ctx(&srv->transition.timer.work);
3091 k_delayed_work_init(&srv->transition.timer, light_hsl_hue_work_handler);
3092 }
3093 srv->model = model;
3094 break;
3095 }
3096 case BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV: {
3097 struct bt_mesh_light_hsl_sat_srv *srv = model->user_data;
3098 if (srv->state == NULL) {
3099 BT_ERR("Invalid Light HSL State");
3100 return -EINVAL;
3101 }
3102 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3103 bt_mesh_server_alloc_ctx(&srv->transition.timer.work);
3104 k_delayed_work_init(&srv->transition.timer, light_hsl_sat_work_handler);
3105 }
3106 srv->model = model;
3107 break;
3108 }
3109 case BLE_MESH_MODEL_ID_LIGHT_XYL_SRV: {
3110 struct bt_mesh_light_xyl_srv *srv = model->user_data;
3111 if (srv->state == NULL) {
3112 BT_ERR("Invalid Light xyL State");
3113 return -EINVAL;
3114 }
3115 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3116 bt_mesh_server_alloc_ctx(&srv->transition.timer.work);
3117 k_delayed_work_init(&srv->transition.timer, light_xyl_work_handler);
3118 }
3119 srv->model = model;
3120 break;
3121 }
3122 case BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV: {
3123 struct bt_mesh_light_xyl_setup_srv *srv = model->user_data;
3124 if (srv->state == NULL) {
3125 BT_ERR("Invalid Light xyL State");
3126 return -EINVAL;
3127 }
3128 srv->model = model;
3129 break;
3130 }
3131 case BLE_MESH_MODEL_ID_LIGHT_LC_SRV: {
3132 struct bt_mesh_light_lc_srv *srv = model->user_data;
3133 if (srv->lc == NULL) {
3134 BT_ERR("Invalid Light LC State");
3135 return -EINVAL;
3136 }
3137 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3138 bt_mesh_server_alloc_ctx(&srv->transition.timer.work);
3139 k_delayed_work_init(&srv->transition.timer, light_lc_work_handler);
3140 }
3141 srv->model = model;
3142 break;
3143 }
3144 case BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV: {
3145 struct bt_mesh_light_lc_setup_srv *srv = model->user_data;
3146 if (srv->lc == NULL) {
3147 BT_ERR("Invalid Light LC State");
3148 return -EINVAL;
3149 }
3150 srv->model = model;
3151 break;
3152 }
3153 default:
3154 BT_WARN("Unknown Light Server, model id 0x%04x", model->id);
3155 return -EINVAL;
3156 }
3157
3158 bt_mesh_light_server_mutex_new();
3159
3160 return 0;
3161 }
3162
light_lightness_srv_init(struct bt_mesh_model * model)3163 static int light_lightness_srv_init(struct bt_mesh_model *model)
3164 {
3165 if (model->pub == NULL) {
3166 BT_ERR("Light Lightness Server has no publication support");
3167 return -EINVAL;
3168 }
3169
3170 /* When this model is present on an Element, the corresponding Light Lightness
3171 * Setup Server model shall also be present.
3172 */
3173 struct bt_mesh_elem *element = bt_mesh_model_elem(model);
3174 if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV) == NULL) {
3175 BT_WARN("Light Lightness Setup Server not present");
3176 /* Just give a warning here, continue with the initialization */
3177 }
3178 return light_server_init(model);
3179 }
3180
light_lightness_setup_srv_init(struct bt_mesh_model * model)3181 static int light_lightness_setup_srv_init(struct bt_mesh_model *model)
3182 {
3183 return light_server_init(model);
3184 }
3185
light_ctl_srv_init(struct bt_mesh_model * model)3186 static int light_ctl_srv_init(struct bt_mesh_model *model)
3187 {
3188 if (model->pub == NULL) {
3189 BT_ERR("Light CTL Server has no publication support");
3190 return -EINVAL;
3191 }
3192
3193 /**
3194 * When this model is present on an Element, the corresponding Light CTL
3195 * Temperature Server model and the corresponding Light CTL Setup Server
3196 * model shall also be present.
3197 * The model requires two elements: the main element and the Temperature
3198 * element. The Temperature element contains the corresponding Light CTL
3199 * Temperature Server model.
3200 */
3201 struct bt_mesh_elem *element = bt_mesh_model_elem(model);
3202 if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV) == NULL) {
3203 BT_WARN("Light CTL Setup Server not present");
3204 /* Just give a warning here, continue with the initialization */
3205 }
3206 if (bt_mesh_elem_count() < 2) {
3207 BT_WARN("Light CTL Server requires two elements");
3208 /* Just give a warning here, continue with the initialization */
3209 }
3210 return light_server_init(model);
3211 }
3212
light_ctl_setup_srv_init(struct bt_mesh_model * model)3213 static int light_ctl_setup_srv_init(struct bt_mesh_model *model)
3214 {
3215 return light_server_init(model);
3216 }
3217
light_ctl_temp_srv_init(struct bt_mesh_model * model)3218 static int light_ctl_temp_srv_init(struct bt_mesh_model *model)
3219 {
3220 if (model->pub == NULL) {
3221 BT_ERR("Light CTL Temperature Server has no publication support");
3222 return -EINVAL;
3223 }
3224
3225 return light_server_init(model);
3226 }
3227
light_hsl_srv_init(struct bt_mesh_model * model)3228 static int light_hsl_srv_init(struct bt_mesh_model *model)
3229 {
3230 if (model->pub == NULL) {
3231 BT_ERR("Light HSL Server has no publication support");
3232 return -EINVAL;
3233 }
3234
3235 /**
3236 * When this model is present on an Element, the corresponding Light HSL Hue
3237 * Server model and the corresponding Light HSL Saturation Server model and
3238 * the corresponding Light HSL Setup Server model shall also be present.
3239 * The model requires three elements: the main element and the Hue element
3240 * and the Saturation element. The Hue element contains the corresponding
3241 * Light HSL Hue Server model, and the Saturation element contains the corr-
3242 * esponding Light HSL Saturation Server model.
3243 */
3244 struct bt_mesh_elem *element = bt_mesh_model_elem(model);
3245 if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV) == NULL) {
3246 BT_WARN("Light HSL Setup Server not present");
3247 /* Just give a warning here, continue with the initialization */
3248 }
3249 if (bt_mesh_elem_count() < 3) {
3250 BT_WARN("Light HSL Server requires three elements");
3251 /* Just give a warning here, continue with the initialization */
3252 }
3253 return light_server_init(model);
3254 }
3255
light_hsl_setup_srv_init(struct bt_mesh_model * model)3256 static int light_hsl_setup_srv_init(struct bt_mesh_model *model)
3257 {
3258 return light_server_init(model);
3259 }
3260
light_hsl_hue_srv_init(struct bt_mesh_model * model)3261 static int light_hsl_hue_srv_init(struct bt_mesh_model *model)
3262 {
3263 if (model->pub == NULL) {
3264 BT_ERR("Light HSL Hue Server has no publication support");
3265 return -EINVAL;
3266 }
3267
3268 return light_server_init(model);
3269 }
3270
light_hsl_sat_srv_init(struct bt_mesh_model * model)3271 static int light_hsl_sat_srv_init(struct bt_mesh_model *model)
3272 {
3273 if (model->pub == NULL) {
3274 BT_ERR("Light HSL Saturation Server has no publication support");
3275 return -EINVAL;
3276 }
3277
3278 return light_server_init(model);
3279 }
3280
light_xyl_srv_init(struct bt_mesh_model * model)3281 static int light_xyl_srv_init(struct bt_mesh_model *model)
3282 {
3283 if (model->pub == NULL) {
3284 BT_ERR("Light xyL Server has no publication support");
3285 return -EINVAL;
3286 }
3287
3288 /**
3289 * When this model is present on an Element, the corresponding Light xyL
3290 * Setup Server model shall also be present.
3291 */
3292 struct bt_mesh_elem *element = bt_mesh_model_elem(model);
3293 if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV) == NULL) {
3294 BT_WARN("Light xyL Setup Server not present");
3295 /* Just give a warning here, continue with the initialization */
3296 }
3297 return light_server_init(model);
3298 }
3299
light_xyl_setup_srv_init(struct bt_mesh_model * model)3300 static int light_xyl_setup_srv_init(struct bt_mesh_model *model)
3301 {
3302 return light_server_init(model);
3303 }
3304
light_lc_srv_init(struct bt_mesh_model * model)3305 static int light_lc_srv_init(struct bt_mesh_model *model)
3306 {
3307 if (model->pub == NULL) {
3308 BT_ERR("Light LC Server has no publication support");
3309 return -EINVAL;
3310 }
3311
3312 return light_server_init(model);
3313 }
3314
light_lc_setup_srv_init(struct bt_mesh_model * model)3315 static int light_lc_setup_srv_init(struct bt_mesh_model *model)
3316 {
3317 if (model->pub == NULL) {
3318 BT_ERR("Light LC Setup Server has no publication support");
3319 return -EINVAL;
3320 }
3321
3322 /**
3323 * When this model is present on an Element, the corresponding Light LC
3324 * Setup Server model shall also be present.
3325 */
3326 struct bt_mesh_elem *element = bt_mesh_model_elem(model);
3327 if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV) == NULL) {
3328 BT_WARN("Light LC Setup Server not present");
3329 /* Just give a warning here, continue with the initialization */
3330 }
3331 return light_server_init(model);
3332 }
3333
3334 #if CONFIG_BLE_MESH_DEINIT
light_server_deinit(struct bt_mesh_model * model)3335 static int light_server_deinit(struct bt_mesh_model *model)
3336 {
3337 if (model->user_data == NULL) {
3338 BT_ERR("Invalid Lighting Server user data, model id 0x%04x", model->id);
3339 return -EINVAL;
3340 }
3341
3342 switch (model->id) {
3343 case BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV: {
3344 struct bt_mesh_light_lightness_srv *srv = model->user_data;
3345 if (srv->state == NULL) {
3346 BT_ERR("Invalid Light Lightness State");
3347 return -EINVAL;
3348 }
3349 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3350 bt_mesh_server_free_ctx(&srv->actual_transition.timer.work);
3351 bt_mesh_server_free_ctx(&srv->linear_transition.timer.work);
3352 k_delayed_work_free(&srv->actual_transition.timer);
3353 k_delayed_work_free(&srv->linear_transition.timer);
3354 }
3355 break;
3356 }
3357 case BLE_MESH_MODEL_ID_LIGHT_CTL_SRV: {
3358 struct bt_mesh_light_ctl_srv *srv = model->user_data;
3359 if (srv->state == NULL) {
3360 BT_ERR("Invalid Light CTL State");
3361 return -EINVAL;
3362 }
3363 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3364 bt_mesh_server_free_ctx(&srv->transition.timer.work);
3365 k_delayed_work_free(&srv->transition.timer);
3366 }
3367 break;
3368 }
3369 case BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV: {
3370 struct bt_mesh_light_ctl_temp_srv *srv = model->user_data;
3371 if (srv->state == NULL) {
3372 BT_ERR("Invalid Light CTL State");
3373 return -EINVAL;
3374 }
3375 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3376 bt_mesh_server_free_ctx(&srv->transition.timer.work);
3377 k_delayed_work_free(&srv->transition.timer);
3378 }
3379 break;
3380 }
3381 case BLE_MESH_MODEL_ID_LIGHT_HSL_SRV: {
3382 struct bt_mesh_light_hsl_srv *srv = model->user_data;
3383 if (srv->state == NULL) {
3384 BT_ERR("Invalid Light HSL State");
3385 return -EINVAL;
3386 }
3387 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3388 bt_mesh_server_free_ctx(&srv->transition.timer.work);
3389 k_delayed_work_free(&srv->transition.timer);
3390 }
3391 break;
3392 }
3393 case BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV: {
3394 struct bt_mesh_light_hsl_hue_srv *srv = model->user_data;
3395 if (srv->state == NULL) {
3396 BT_ERR("Invalid Light HSL State");
3397 return -EINVAL;
3398 }
3399 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3400 bt_mesh_server_free_ctx(&srv->transition.timer.work);
3401 k_delayed_work_free(&srv->transition.timer);
3402 }
3403 break;
3404 }
3405 case BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV: {
3406 struct bt_mesh_light_hsl_sat_srv *srv = model->user_data;
3407 if (srv->state == NULL) {
3408 BT_ERR("Invalid Light HSL State");
3409 return -EINVAL;
3410 }
3411 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3412 bt_mesh_server_free_ctx(&srv->transition.timer.work);
3413 k_delayed_work_free(&srv->transition.timer);
3414 }
3415 break;
3416 }
3417 case BLE_MESH_MODEL_ID_LIGHT_XYL_SRV: {
3418 struct bt_mesh_light_xyl_srv *srv = model->user_data;
3419 if (srv->state == NULL) {
3420 BT_ERR("Invalid Light xyL State");
3421 return -EINVAL;
3422 }
3423 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3424 bt_mesh_server_free_ctx(&srv->transition.timer.work);
3425 k_delayed_work_free(&srv->transition.timer);
3426 }
3427 break;
3428 }
3429 case BLE_MESH_MODEL_ID_LIGHT_LC_SRV: {
3430 struct bt_mesh_light_lc_srv *srv = model->user_data;
3431 if (srv->lc == NULL) {
3432 BT_ERR("Invalid Light LC State");
3433 return -EINVAL;
3434 }
3435 if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
3436 bt_mesh_server_free_ctx(&srv->transition.timer.work);
3437 k_delayed_work_free(&srv->transition.timer);
3438 }
3439 break;
3440 }
3441 case BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV:
3442 case BLE_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV:
3443 case BLE_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV:
3444 case BLE_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV:
3445 case BLE_MESH_MODEL_ID_LIGHT_LC_SETUP_SRV:
3446 break;
3447 default:
3448 BT_WARN("Unknown Light Server, model id 0x%04x", model->id);
3449 return -EINVAL;
3450 }
3451
3452 bt_mesh_light_server_mutex_free();
3453
3454 return 0;
3455 }
3456
light_lightness_srv_deinit(struct bt_mesh_model * model)3457 static int light_lightness_srv_deinit(struct bt_mesh_model *model)
3458 {
3459 if (model->pub == NULL) {
3460 BT_ERR("Light Lightness Server has no publication support");
3461 return -EINVAL;
3462 }
3463
3464 return light_server_deinit(model);
3465 }
3466
light_lightness_setup_srv_deinit(struct bt_mesh_model * model)3467 static int light_lightness_setup_srv_deinit(struct bt_mesh_model *model)
3468 {
3469 return light_server_deinit(model);
3470 }
3471
light_ctl_srv_deinit(struct bt_mesh_model * model)3472 static int light_ctl_srv_deinit(struct bt_mesh_model *model)
3473 {
3474 if (model->pub == NULL) {
3475 BT_ERR("Light CTL Server has no publication support");
3476 return -EINVAL;
3477 }
3478
3479 return light_server_deinit(model);
3480 }
3481
light_ctl_setup_srv_deinit(struct bt_mesh_model * model)3482 static int light_ctl_setup_srv_deinit(struct bt_mesh_model *model)
3483 {
3484 return light_server_deinit(model);
3485 }
3486
light_ctl_temp_srv_deinit(struct bt_mesh_model * model)3487 static int light_ctl_temp_srv_deinit(struct bt_mesh_model *model)
3488 {
3489 if (model->pub == NULL) {
3490 BT_ERR("Light CTL Temperature Server has no publication support");
3491 return -EINVAL;
3492 }
3493
3494 return light_server_deinit(model);
3495 }
3496
light_hsl_srv_deinit(struct bt_mesh_model * model)3497 static int light_hsl_srv_deinit(struct bt_mesh_model *model)
3498 {
3499 if (model->pub == NULL) {
3500 BT_ERR("Light HSL Server has no publication support");
3501 return -EINVAL;
3502 }
3503
3504 return light_server_deinit(model);
3505 }
3506
light_hsl_setup_srv_deinit(struct bt_mesh_model * model)3507 static int light_hsl_setup_srv_deinit(struct bt_mesh_model *model)
3508 {
3509 return light_server_deinit(model);
3510 }
3511
light_hsl_hue_srv_deinit(struct bt_mesh_model * model)3512 static int light_hsl_hue_srv_deinit(struct bt_mesh_model *model)
3513 {
3514 if (model->pub == NULL) {
3515 BT_ERR("Light HSL Hue Server has no publication support");
3516 return -EINVAL;
3517 }
3518
3519 return light_server_deinit(model);
3520 }
3521
light_hsl_sat_srv_deinit(struct bt_mesh_model * model)3522 static int light_hsl_sat_srv_deinit(struct bt_mesh_model *model)
3523 {
3524 if (model->pub == NULL) {
3525 BT_ERR("Light HSL Saturation Server has no publication support");
3526 return -EINVAL;
3527 }
3528
3529 return light_server_deinit(model);
3530 }
3531
light_xyl_srv_deinit(struct bt_mesh_model * model)3532 static int light_xyl_srv_deinit(struct bt_mesh_model *model)
3533 {
3534 if (model->pub == NULL) {
3535 BT_ERR("Light xyL Server has no publication support");
3536 return -EINVAL;
3537 }
3538
3539 return light_server_deinit(model);
3540 }
3541
light_xyl_setup_srv_deinit(struct bt_mesh_model * model)3542 static int light_xyl_setup_srv_deinit(struct bt_mesh_model *model)
3543 {
3544 return light_server_deinit(model);
3545 }
3546
light_lc_srv_deinit(struct bt_mesh_model * model)3547 static int light_lc_srv_deinit(struct bt_mesh_model *model)
3548 {
3549 if (model->pub == NULL) {
3550 BT_ERR("Light LC Server has no publication support");
3551 return -EINVAL;
3552 }
3553
3554 return light_server_deinit(model);
3555 }
3556
light_lc_setup_srv_deinit(struct bt_mesh_model * model)3557 static int light_lc_setup_srv_deinit(struct bt_mesh_model *model)
3558 {
3559 if (model->pub == NULL) {
3560 BT_ERR("Light LC Setup Server has no publication support");
3561 return -EINVAL;
3562 }
3563
3564 return light_server_deinit(model);
3565 }
3566 #endif /* CONFIG_BLE_MESH_DEINIT */
3567
3568 const struct bt_mesh_model_cb bt_mesh_light_lightness_srv_cb = {
3569 .init = light_lightness_srv_init,
3570 #if CONFIG_BLE_MESH_DEINIT
3571 .deinit = light_lightness_srv_deinit,
3572 #endif /* CONFIG_BLE_MESH_DEINIT */
3573 };
3574
3575 const struct bt_mesh_model_cb bt_mesh_light_lightness_setup_srv_cb = {
3576 .init = light_lightness_setup_srv_init,
3577 #if CONFIG_BLE_MESH_DEINIT
3578 .deinit = light_lightness_setup_srv_deinit,
3579 #endif /* CONFIG_BLE_MESH_DEINIT */
3580 };
3581
3582 const struct bt_mesh_model_cb bt_mesh_light_ctl_srv_cb = {
3583 .init = light_ctl_srv_init,
3584 #if CONFIG_BLE_MESH_DEINIT
3585 .deinit = light_ctl_srv_deinit,
3586 #endif /* CONFIG_BLE_MESH_DEINIT */
3587 };
3588
3589 const struct bt_mesh_model_cb bt_mesh_light_ctl_setup_srv_cb = {
3590 .init = light_ctl_setup_srv_init,
3591 #if CONFIG_BLE_MESH_DEINIT
3592 .deinit = light_ctl_setup_srv_deinit,
3593 #endif /* CONFIG_BLE_MESH_DEINIT */
3594 };
3595
3596 const struct bt_mesh_model_cb bt_mesh_light_ctl_temp_srv_cb = {
3597 .init = light_ctl_temp_srv_init,
3598 #if CONFIG_BLE_MESH_DEINIT
3599 .deinit = light_ctl_temp_srv_deinit,
3600 #endif /* CONFIG_BLE_MESH_DEINIT */
3601 };
3602
3603 const struct bt_mesh_model_cb bt_mesh_light_hsl_srv_cb = {
3604 .init = light_hsl_srv_init,
3605 #if CONFIG_BLE_MESH_DEINIT
3606 .deinit = light_hsl_srv_deinit,
3607 #endif /* CONFIG_BLE_MESH_DEINIT */
3608 };
3609
3610 const struct bt_mesh_model_cb bt_mesh_light_hsl_setup_srv_cb = {
3611 .init = light_hsl_setup_srv_init,
3612 #if CONFIG_BLE_MESH_DEINIT
3613 .deinit = light_hsl_setup_srv_deinit,
3614 #endif /* CONFIG_BLE_MESH_DEINIT */
3615 };
3616
3617 const struct bt_mesh_model_cb bt_mesh_light_hsl_hue_srv_cb = {
3618 .init = light_hsl_hue_srv_init,
3619 #if CONFIG_BLE_MESH_DEINIT
3620 .deinit = light_hsl_hue_srv_deinit,
3621 #endif /* CONFIG_BLE_MESH_DEINIT */
3622 };
3623
3624 const struct bt_mesh_model_cb bt_mesh_light_hsl_sat_srv_cb = {
3625 .init = light_hsl_sat_srv_init,
3626 #if CONFIG_BLE_MESH_DEINIT
3627 .deinit = light_hsl_sat_srv_deinit,
3628 #endif /* CONFIG_BLE_MESH_DEINIT */
3629 };
3630
3631 const struct bt_mesh_model_cb bt_mesh_light_xyl_srv_cb = {
3632 .init = light_xyl_srv_init,
3633 #if CONFIG_BLE_MESH_DEINIT
3634 .deinit = light_xyl_srv_deinit,
3635 #endif /* CONFIG_BLE_MESH_DEINIT */
3636 };
3637
3638 const struct bt_mesh_model_cb bt_mesh_light_xyl_setup_srv_cb = {
3639 .init = light_xyl_setup_srv_init,
3640 #if CONFIG_BLE_MESH_DEINIT
3641 .deinit = light_xyl_setup_srv_deinit,
3642 #endif /* CONFIG_BLE_MESH_DEINIT */
3643 };
3644
3645 const struct bt_mesh_model_cb bt_mesh_light_lc_srv_cb = {
3646 .init = light_lc_srv_init,
3647 #if CONFIG_BLE_MESH_DEINIT
3648 .deinit = light_lc_srv_deinit,
3649 #endif /* CONFIG_BLE_MESH_DEINIT */
3650 };
3651
3652 const struct bt_mesh_model_cb bt_mesh_light_lc_setup_srv_cb = {
3653 .init = light_lc_setup_srv_init,
3654 #if CONFIG_BLE_MESH_DEINIT
3655 .deinit = light_lc_setup_srv_deinit,
3656 #endif /* CONFIG_BLE_MESH_DEINIT */
3657 };
3658
3659 #endif /* CONFIG_BLE_MESH_LIGHTING_SERVER */
3660