mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 13:09:38 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			2865 lines
		
	
	
		
			99 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2865 lines
		
	
	
		
			99 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Bluetooth: Mesh Generic Server Models
 | |
|  *
 | |
|  * SPDX-FileCopyrightText: 2018 Vikrant More
 | |
|  * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
 | |
|  *
 | |
|  * SPDX-License-Identifier: Apache-2.0
 | |
|  */
 | |
| 
 | |
| #include <errno.h>
 | |
| 
 | |
| #include "btc_ble_mesh_generic_model.h"
 | |
| 
 | |
| #include "mesh/config.h"
 | |
| #include "access.h"
 | |
| #include "transport.h"
 | |
| #include "mesh/model_opcode.h"
 | |
| #include "mesh/state_transition.h"
 | |
| #include "mesh/device_property.h"
 | |
| 
 | |
| #if CONFIG_BLE_MESH_GENERIC_SERVER
 | |
| 
 | |
| static bt_mesh_mutex_t generic_server_lock;
 | |
| 
 | |
| void bt_mesh_generic_server_lock(void)
 | |
| {
 | |
|     bt_mesh_mutex_lock(&generic_server_lock);
 | |
| }
 | |
| 
 | |
| void bt_mesh_generic_server_unlock(void)
 | |
| {
 | |
|     bt_mesh_mutex_unlock(&generic_server_lock);
 | |
| }
 | |
| 
 | |
| /* message handlers (Start) */
 | |
| 
 | |
| /* Generic OnOff Server message handlers */
 | |
| static void send_gen_onoff_status(struct bt_mesh_model *model,
 | |
|                                   struct bt_mesh_msg_ctx *ctx,
 | |
|                                   bool publish)
 | |
| {
 | |
|     struct bt_mesh_gen_onoff_srv *srv = model->user_data;
 | |
|     struct net_buf_simple *msg = NULL;
 | |
|     uint8_t length = 2 + 3;
 | |
| 
 | |
|     if (ctx == NULL && publish == false) {
 | |
|         BT_ERR("%s, Invalid parameter", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
|         if (msg == NULL) {
 | |
|             BT_ERR("%s, Out of memory", __func__);
 | |
|             return;
 | |
|         }
 | |
|     } else {
 | |
|         msg = bt_mesh_server_get_pub_msg(model, length);
 | |
|         if (msg == NULL) {
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS);
 | |
|     net_buf_simple_add_u8(msg, srv->state.onoff);
 | |
|     if (srv->transition.counter) {
 | |
|         bt_mesh_server_calc_remain_time(&srv->transition);
 | |
|         net_buf_simple_add_u8(msg, srv->state.target_onoff);
 | |
|         net_buf_simple_add_u8(msg, srv->transition.remain_time);
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
 | |
|         bt_mesh_free_buf(msg);
 | |
|     } else {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void gen_onoff_get(struct bt_mesh_model *model,
 | |
|                           struct bt_mesh_msg_ctx *ctx,
 | |
|                           struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_onoff_srv *srv = model->user_data;
 | |
| 
 | |
|     if (srv == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG,
 | |
|                                              model, ctx, NULL, 0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     send_gen_onoff_status(model, ctx, false);
 | |
| }
 | |
| 
 | |
| void gen_onoff_publish(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->user_data == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     send_gen_onoff_status(model, NULL, true);
 | |
| }
 | |
| 
 | |
| static void gen_onoff_set(struct bt_mesh_model *model,
 | |
|                           struct bt_mesh_msg_ctx *ctx,
 | |
|                           struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_onoff_srv *srv = model->user_data;
 | |
|     uint8_t tid = 0U, onoff = 0U, trans_time = 0U, delay = 0U;
 | |
|     bool optional = false;
 | |
|     int64_t now = 0;
 | |
| 
 | |
|     if (srv == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     onoff = net_buf_simple_pull_u8(buf);
 | |
|     if (onoff > BLE_MESH_STATE_ON) {
 | |
|         BT_ERR("Invalid OnOff value 0x%02x", onoff);
 | |
|         return;
 | |
|     }
 | |
|     tid = net_buf_simple_pull_u8(buf);
 | |
| 
 | |
|     if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|             .onoff_set.op_en = optional,
 | |
|             .onoff_set.onoff = onoff,
 | |
|             .onoff_set.tid = tid,
 | |
|             .onoff_set.trans_time = trans_time,
 | |
|             .onoff_set.delay = delay,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                              model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ONOFF_SET) {
 | |
|             send_gen_onoff_status(model, ctx, false);
 | |
|         }
 | |
|         send_gen_onoff_status(model, NULL, true);
 | |
|         /* In this condition, no event will be callback to application layer */
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_generic_server_lock();
 | |
| 
 | |
|     bt_mesh_server_stop_transition(&srv->transition);
 | |
|     bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
 | |
| 
 | |
|     srv->state.target_onoff = onoff;
 | |
| 
 | |
|     if (srv->state.target_onoff != srv->state.onoff) {
 | |
|         generic_onoff_tt_values(srv, trans_time, delay);
 | |
|     } else {
 | |
|         bt_mesh_gen_server_state_change_t change = {
 | |
|             .gen_onoff_set.onoff = srv->state.onoff,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                              model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
| 
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ONOFF_SET) {
 | |
|             send_gen_onoff_status(model, ctx, false);
 | |
|         }
 | |
|         send_gen_onoff_status(model, NULL, true);
 | |
| 
 | |
|         bt_mesh_generic_server_unlock();
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Copy the ctx of the received message */
 | |
|     if (srv->transition.timer.work.user_data) {
 | |
|         memcpy(srv->transition.timer.work.user_data, ctx, sizeof(struct bt_mesh_msg_ctx));
 | |
|     }
 | |
| 
 | |
|     /* For Instantaneous Transition */
 | |
|     if (srv->transition.counter == 0U) {
 | |
|         srv->state.onoff = srv->state.target_onoff;
 | |
|     }
 | |
| 
 | |
|     srv->transition.just_started = true;
 | |
|     if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ONOFF_SET) {
 | |
|         send_gen_onoff_status(model, ctx, false);
 | |
|     }
 | |
|     send_gen_onoff_status(model, NULL, true);
 | |
| 
 | |
|     bt_mesh_generic_server_unlock();
 | |
| 
 | |
|     bt_mesh_server_start_transition(&srv->transition);
 | |
| }
 | |
| 
 | |
| /* Generic Level Server message handlers */
 | |
| static void send_gen_level_status(struct bt_mesh_model *model,
 | |
|                                   struct bt_mesh_msg_ctx *ctx,
 | |
|                                   bool publish)
 | |
| {
 | |
|     struct bt_mesh_gen_level_srv *srv = model->user_data;
 | |
|     struct net_buf_simple *msg = NULL;
 | |
|     uint8_t length = 2 + 5;
 | |
| 
 | |
|     if (ctx == NULL && publish == false) {
 | |
|         BT_ERR("%s, Invalid parameter", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
|         if (msg == NULL) {
 | |
|             BT_ERR("%s, Out of memory", __func__);
 | |
|             return;
 | |
|         }
 | |
|     } else {
 | |
|         msg = bt_mesh_server_get_pub_msg(model, length);
 | |
|         if (msg == NULL) {
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_LEVEL_STATUS);
 | |
|     net_buf_simple_add_le16(msg, srv->state.level);
 | |
|     if (srv->transition.counter) {
 | |
|         if (srv->state.move_start) {
 | |
|             if (srv->state.positive) {
 | |
|                 net_buf_simple_add_le16(msg, INT16_MAX);
 | |
|             } else { /* 0 should not be possible */
 | |
|                 net_buf_simple_add_le16(msg, INT16_MIN);
 | |
|             }
 | |
|             net_buf_simple_add_u8(msg, BLE_MESH_UNKNOWN_REMAIN_TIME);
 | |
|         } else {
 | |
|             bt_mesh_server_calc_remain_time(&srv->transition);
 | |
|             net_buf_simple_add_le16(msg, srv->state.target_level);
 | |
|             net_buf_simple_add_u8(msg, srv->transition.remain_time);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
 | |
|         bt_mesh_free_buf(msg);
 | |
|     } else {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void gen_level_get(struct bt_mesh_model *model,
 | |
|                           struct bt_mesh_msg_ctx *ctx,
 | |
|                           struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_level_srv *srv = model->user_data;
 | |
| 
 | |
|     if (srv == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG,
 | |
|                                              model, ctx, NULL, 0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     send_gen_level_status(model, ctx, false);
 | |
| }
 | |
| 
 | |
| void gen_level_publish(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->user_data == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     send_gen_level_status(model, NULL, true);
 | |
| }
 | |
| 
 | |
| static void gen_level_set(struct bt_mesh_model *model,
 | |
|                           struct bt_mesh_msg_ctx *ctx,
 | |
|                           struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_level_srv *srv = model->user_data;
 | |
|     uint8_t tid = 0U, trans_time = 0U, delay = 0U;
 | |
|     bool optional = false;
 | |
|     int16_t level = 0;
 | |
|     int64_t now = 0;
 | |
| 
 | |
|     if (srv == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     level = (int16_t) net_buf_simple_pull_le16(buf);
 | |
|     tid = net_buf_simple_pull_u8(buf);
 | |
| 
 | |
|     if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|             .level_set.op_en = optional,
 | |
|             .level_set.level = level,
 | |
|             .level_set.tid = tid,
 | |
|             .level_set.trans_time = trans_time,
 | |
|             .level_set.delay = delay,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                              model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_LEVEL_SET) {
 | |
|             send_gen_level_status(model, ctx, false);
 | |
|         }
 | |
|         send_gen_level_status(model, NULL, true);
 | |
|         /* In this condition, no event will be callback to application layer */
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_generic_server_lock();
 | |
| 
 | |
|     bt_mesh_server_stop_transition(&srv->transition);
 | |
|     bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
 | |
| 
 | |
|     srv->state.target_level = level;
 | |
| 
 | |
|     /**
 | |
|      * If the target state is equal to the current state, the transition
 | |
|      * shall not be started and is considered complete.
 | |
|      */
 | |
|     if (srv->state.target_level != srv->state.level) {
 | |
|         generic_level_tt_values(srv, trans_time, delay);
 | |
|     } else {
 | |
|         bt_mesh_gen_server_state_change_t change = {
 | |
|             .gen_level_set.level = srv->state.level,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                              model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
| 
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_LEVEL_SET) {
 | |
|             send_gen_level_status(model, ctx, false);
 | |
|         }
 | |
|         send_gen_level_status(model, NULL, true);
 | |
| 
 | |
|         bt_mesh_generic_server_unlock();
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Copy the ctx of the received message */
 | |
|     if (srv->transition.timer.work.user_data) {
 | |
|         memcpy(srv->transition.timer.work.user_data, ctx, sizeof(struct bt_mesh_msg_ctx));
 | |
|     }
 | |
| 
 | |
|     /* For Instantaneous Transition */
 | |
|     if (srv->transition.counter == 0U) {
 | |
|         srv->state.level = srv->state.target_level;
 | |
|     }
 | |
| 
 | |
|     srv->transition.just_started = true;
 | |
|     if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_LEVEL_SET) {
 | |
|         send_gen_level_status(model, ctx, false);
 | |
|     }
 | |
|     send_gen_level_status(model, NULL, true);
 | |
| 
 | |
|     bt_mesh_generic_server_unlock();
 | |
| 
 | |
|     bt_mesh_server_start_transition(&srv->transition);
 | |
| }
 | |
| 
 | |
| static void gen_delta_set(struct bt_mesh_model *model,
 | |
|                           struct bt_mesh_msg_ctx *ctx,
 | |
|                           struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_level_srv *srv = model->user_data;
 | |
|     uint8_t tid = 0U, trans_time = 0U, delay = 0U;
 | |
|     int32_t tmp32 = 0, delta = 0;
 | |
|     bool optional = false;
 | |
|     int64_t now = 0;
 | |
| 
 | |
|     if (srv == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     delta = (int32_t)net_buf_simple_pull_le32(buf);
 | |
|     tid = net_buf_simple_pull_u8(buf);
 | |
| 
 | |
|     if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|             .delta_set.op_en = optional,
 | |
|             .delta_set.delta_level = delta,
 | |
|             .delta_set.tid = tid,
 | |
|             .delta_set.trans_time = trans_time,
 | |
|             .delta_set.delay = delay,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                              model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * A number of Generic Delta Set and Generic Delta Set Unacknowledged
 | |
|      * messages with the same transaction identifier set in the TID field
 | |
|      * may be sent.
 | |
|      *
 | |
|      * A new transaction starts when the TID field value in the received
 | |
|      * message is different from the TID field value in the previously
 | |
|      * received message that was using the same source and destination
 | |
|      * addresses or from the most recently received message with the same
 | |
|      * TID field value that was received 6 or more seconds earlier.
 | |
|      */
 | |
|     if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
 | |
|         if (srv->state.last_delta == delta) {
 | |
|             if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_DELTA_SET) {
 | |
|                 send_gen_level_status(model, ctx, false);
 | |
|             }
 | |
|             send_gen_level_status(model, NULL, true);
 | |
|             /* In this condition, no event will be callback to application layer */
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         tmp32 = srv->state.last_level + delta;
 | |
|     } else {
 | |
|         /* Starts a new transaction */
 | |
|         srv->state.last_level = srv->state.level;
 | |
|         tmp32 = srv->state.level + delta;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_generic_server_lock();
 | |
| 
 | |
|     bt_mesh_server_stop_transition(&srv->transition);
 | |
|     bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
 | |
| 
 | |
|     srv->state.last_delta = delta;
 | |
|     if (tmp32 < INT16_MIN) {
 | |
|         tmp32 = INT16_MIN;
 | |
|     } else if (tmp32 > INT16_MAX) {
 | |
|         tmp32 = INT16_MAX;
 | |
|     }
 | |
|     srv->state.target_level = tmp32;
 | |
| 
 | |
|     /**
 | |
|      * If the target state is equal to the current state, the transition
 | |
|      * shall not be started and is considered complete.
 | |
|      */
 | |
|     if (srv->state.target_level != srv->state.level) {
 | |
|         generic_level_tt_values(srv, trans_time, delay);
 | |
|     } else {
 | |
|         bt_mesh_gen_server_state_change_t change = {
 | |
|             .gen_delta_set.level = srv->state.level,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                              model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
| 
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_DELTA_SET) {
 | |
|             send_gen_level_status(model, ctx, false);
 | |
|         }
 | |
|         send_gen_level_status(model, NULL, true);
 | |
| 
 | |
|         bt_mesh_generic_server_unlock();
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Copy the ctx of the received message */
 | |
|     if (srv->transition.timer.work.user_data) {
 | |
|         memcpy(srv->transition.timer.work.user_data, ctx, sizeof(struct bt_mesh_msg_ctx));
 | |
|     }
 | |
| 
 | |
|     /* For Instantaneous Transition */
 | |
|     if (srv->transition.counter == 0U) {
 | |
|         srv->state.level = srv->state.target_level;
 | |
|     }
 | |
| 
 | |
|     srv->transition.just_started = true;
 | |
|     if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_DELTA_SET) {
 | |
|         send_gen_level_status(model, ctx, false);
 | |
|     }
 | |
|     send_gen_level_status(model, NULL, true);
 | |
| 
 | |
|     bt_mesh_generic_server_unlock();
 | |
| 
 | |
|     bt_mesh_server_start_transition(&srv->transition);
 | |
| }
 | |
| 
 | |
| static void gen_move_set(struct bt_mesh_model *model,
 | |
|                          struct bt_mesh_msg_ctx *ctx,
 | |
|                          struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_level_srv *srv = model->user_data;
 | |
|     uint8_t tid = 0U, trans_time = 0U, delay = 0U;
 | |
|     bool optional = false;
 | |
|     int16_t delta = 0;
 | |
|     int32_t tmp32 = 0;
 | |
|     int64_t now = 0;
 | |
| 
 | |
|     if (srv == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     delta = (int16_t) net_buf_simple_pull_le16(buf);
 | |
|     tid = net_buf_simple_pull_u8(buf);
 | |
| 
 | |
|     if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|             .move_set.op_en = optional,
 | |
|             .move_set.delta_level = delta,
 | |
|             .move_set.tid = tid,
 | |
|             .move_set.trans_time = trans_time,
 | |
|             .move_set.delay = delay,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                              model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_MOVE_SET) {
 | |
|             send_gen_level_status(model, ctx, false);
 | |
|         }
 | |
|         send_gen_level_status(model, NULL, true);
 | |
|         /* In this condition, no event will be callback to application layer */
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_generic_server_lock();
 | |
| 
 | |
|     bt_mesh_server_stop_transition(&srv->transition);
 | |
|     bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
 | |
| 
 | |
|     srv->state.last_delta = delta;
 | |
| 
 | |
|     tmp32 = srv->state.level + delta;
 | |
|     if (tmp32 < INT16_MIN) {
 | |
|         tmp32 = INT16_MIN;
 | |
|     } else if (tmp32 > INT16_MAX) {
 | |
|         tmp32 = INT16_MAX;
 | |
|     }
 | |
|     srv->state.target_level = tmp32;
 | |
| 
 | |
|     /**
 | |
|      * If the target state is equal to the current state, the transition
 | |
|      * shall not be started and is considered complete.
 | |
|      */
 | |
|     if (srv->state.target_level != srv->state.level) {
 | |
|         generic_level_tt_values(srv, trans_time, delay);
 | |
|     } else {
 | |
|         bt_mesh_gen_server_state_change_t change = {
 | |
|             .gen_move_set.level = srv->state.level,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                              model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
| 
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_MOVE_SET) {
 | |
|             send_gen_level_status(model, ctx, false);
 | |
|         }
 | |
|         send_gen_level_status(model, NULL, true);
 | |
|         srv->state.move_start = false;
 | |
| 
 | |
|         bt_mesh_generic_server_unlock();
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Copy the ctx of the received message */
 | |
|     if (srv->transition.timer.work.user_data) {
 | |
|         memcpy(srv->transition.timer.work.user_data, ctx, sizeof(struct bt_mesh_msg_ctx));
 | |
|     }
 | |
| 
 | |
|     if (delta) {
 | |
|         srv->state.move_start = true;
 | |
|         srv->state.positive = (delta > 0) ? true : false;
 | |
|     }
 | |
| 
 | |
|     srv->transition.just_started = true;
 | |
|     if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_MOVE_SET) {
 | |
|         send_gen_level_status(model, ctx, false);
 | |
|     }
 | |
|     send_gen_level_status(model, NULL, true);
 | |
| 
 | |
|     bt_mesh_generic_server_unlock();
 | |
| 
 | |
|     /**
 | |
|      * If (trans_time == 0) OR (delta == 0)
 | |
|      * 1. If the resulting Transition Time is equal to 0 or is undefined,
 | |
|      *    the Generic Move Set command will not initiate any Generic Level
 | |
|      *    state change.
 | |
|      * 2. When a Generic Level Server receives the message with a value of
 | |
|      *    the Delta Level field equal to 0, it shall stop changing the
 | |
|      *    Generic Level state. (if delta == 0, srv->state.target_level will
 | |
|      *    equal to srv->state.level)
 | |
|      */
 | |
|     if (srv->transition.counter == 0U) {
 | |
|         srv->state.move_start = false;
 | |
|         bt_mesh_gen_server_state_change_t change = {
 | |
|             .gen_move_set.level = srv->state.level,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                              model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_server_start_transition(&srv->transition);
 | |
| }
 | |
| 
 | |
| /* Generic Default Transition Time Server message handlers */
 | |
| static void send_gen_def_trans_time_status(struct bt_mesh_model *model,
 | |
|         struct bt_mesh_msg_ctx *ctx,
 | |
|         bool publish)
 | |
| {
 | |
|     struct bt_mesh_gen_def_trans_time_srv *srv = model->user_data;
 | |
|     struct net_buf_simple *msg = NULL;
 | |
|     uint8_t length = 2 + 1;
 | |
| 
 | |
|     if (ctx == NULL && publish == false) {
 | |
|         BT_ERR("%s, Invalid parameter", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
|         if (msg == NULL) {
 | |
|             BT_ERR("%s, Out of memory", __func__);
 | |
|             return;
 | |
|         }
 | |
|     } else {
 | |
|         msg = bt_mesh_server_get_pub_msg(model, length);
 | |
|         if (msg == NULL) {
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_STATUS);
 | |
|     net_buf_simple_add_u8(msg, srv->state.trans_time);
 | |
| 
 | |
|     if (publish == false) {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
 | |
|         bt_mesh_free_buf(msg);
 | |
|     } else {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void gen_def_trans_time_get(struct bt_mesh_model *model,
 | |
|                                    struct bt_mesh_msg_ctx *ctx,
 | |
|                                    struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_def_trans_time_srv *srv = model->user_data;
 | |
| 
 | |
|     if (srv == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG,
 | |
|                                              model, ctx, NULL, 0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     send_gen_def_trans_time_status(model, ctx, false);
 | |
| }
 | |
| 
 | |
| static void gen_def_trans_time_set(struct bt_mesh_model *model,
 | |
|                                    struct bt_mesh_msg_ctx *ctx,
 | |
|                                    struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_def_trans_time_srv *srv = model->user_data;
 | |
|     uint8_t trans_time = 0U;
 | |
| 
 | |
|     if (srv == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     trans_time = net_buf_simple_pull_u8(buf);
 | |
|     if ((trans_time & 0x3F) == 0x3F) {
 | |
|         BT_WARN("Invalid Transaction Number of Steps 0x3f");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|             .def_trans_time_set.trans_time = trans_time,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                              model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (srv->state.trans_time != trans_time) {
 | |
|         srv->state.trans_time = trans_time;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_gen_server_state_change_t change = {
 | |
|         .gen_def_trans_time_set.trans_time = trans_time,
 | |
|     };
 | |
|     bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                          model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
| 
 | |
|     if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET) {
 | |
|         send_gen_def_trans_time_status(model, ctx, false);
 | |
|     }
 | |
|     send_gen_def_trans_time_status(model, NULL, true);
 | |
| }
 | |
| 
 | |
| /* Generic Power OnOff Server message handlers */
 | |
| static void send_gen_onpowerup_status(struct bt_mesh_model *model,
 | |
|                                       struct bt_mesh_msg_ctx *ctx,
 | |
|                                       bool publish)
 | |
| {
 | |
|     struct net_buf_simple *msg = NULL;
 | |
|     uint8_t length = 2 + 1;
 | |
| 
 | |
|     if (ctx == NULL && publish == false) {
 | |
|         BT_ERR("%s, Invalid parameter", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
|         if (msg == NULL) {
 | |
|             BT_ERR("%s, Out of memory", __func__);
 | |
|             return;
 | |
|         }
 | |
|     } else {
 | |
|         msg = bt_mesh_server_get_pub_msg(model, length);
 | |
|         if (msg == NULL) {
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_ONPOWERUP_STATUS);
 | |
|     switch (model->id) {
 | |
|     case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV: {
 | |
|         struct bt_mesh_gen_power_onoff_srv *srv = model->user_data;
 | |
|         net_buf_simple_add_u8(msg, srv->state->onpowerup);
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV: {
 | |
|         struct bt_mesh_gen_power_onoff_setup_srv *srv = model->user_data;
 | |
|         net_buf_simple_add_u8(msg, srv->state->onpowerup);
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         BT_ERR("Invalid Generic Power OnOff Server 0x%04x", model->id);
 | |
|         if (publish == false) {
 | |
|             bt_mesh_free_buf(msg);
 | |
|         }
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
 | |
|         bt_mesh_free_buf(msg);
 | |
|     } else {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void gen_onpowerup_get(struct bt_mesh_model *model,
 | |
|                               struct bt_mesh_msg_ctx *ctx,
 | |
|                               struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_power_onoff_srv *srv = model->user_data;
 | |
| 
 | |
|     if (srv == NULL || srv->state == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG,
 | |
|                                              model, ctx, NULL, 0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     send_gen_onpowerup_status(model, ctx, false);
 | |
| }
 | |
| 
 | |
| /* Generic Power OnOff Setup Server message handlers */
 | |
| void gen_onpowerup_publish(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->user_data == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch (model->id) {
 | |
|     case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV: {
 | |
|         struct bt_mesh_gen_power_onoff_srv *srv = model->user_data;
 | |
|         if (srv->state == NULL) {
 | |
|             BT_ERR("Invalid Generic Power OnOff Server state");
 | |
|             return;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV: {
 | |
|         struct bt_mesh_gen_power_onoff_setup_srv *srv = model->user_data;
 | |
|         if (srv->state == NULL) {
 | |
|             BT_ERR("Invalid Generic Power OnOff Setup Server state");
 | |
|             return;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         BT_ERR("Invalid Generic Power OnOff Server 0x%04x", model->id);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     send_gen_onpowerup_status(model, NULL, true);
 | |
| }
 | |
| 
 | |
| static void gen_onpowerup_set(struct bt_mesh_model *model,
 | |
|                               struct bt_mesh_msg_ctx *ctx,
 | |
|                               struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_power_onoff_setup_srv *srv = model->user_data;
 | |
|     uint8_t onpowerup = 0U;
 | |
| 
 | |
|     if (srv == NULL || srv->state == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     onpowerup = net_buf_simple_pull_u8(buf);
 | |
|     if (onpowerup > BLE_MESH_STATE_RESTORE) {
 | |
|         BT_WARN("Invalid OnPowerUp value 0x%02x", onpowerup);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|             .onpowerup_set.onpowerup = onpowerup,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                              model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (srv->state->onpowerup != onpowerup) {
 | |
|         srv->state->onpowerup = onpowerup;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_gen_server_state_change_t change = {
 | |
|         .gen_onpowerup_set.onpowerup = onpowerup,
 | |
|     };
 | |
|     bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                          model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
| 
 | |
|     if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET) {
 | |
|         send_gen_onpowerup_status(model, ctx, false);
 | |
|     }
 | |
|     send_gen_onpowerup_status(model, NULL, true);
 | |
| }
 | |
| 
 | |
| /* Generic Power Level Server message handlers */
 | |
| static void send_gen_power_level_status(struct bt_mesh_model *model,
 | |
|                                         struct bt_mesh_msg_ctx *ctx,
 | |
|                                         bool publish, uint16_t opcode)
 | |
| {
 | |
|     struct net_buf_simple *msg = NULL;
 | |
|     uint8_t length = 2 + 5;
 | |
| 
 | |
|     if (ctx == NULL && publish == false) {
 | |
|         BT_ERR("%s, Invalid parameter", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
|         if (msg == NULL) {
 | |
|             BT_ERR("%s, Out of memory", __func__);
 | |
|             return;
 | |
|         }
 | |
|     } else {
 | |
|         msg = bt_mesh_server_get_pub_msg(model, length);
 | |
|         if (msg == NULL) {
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     bt_mesh_model_msg_init(msg, opcode);
 | |
|     switch (opcode) {
 | |
|     case BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS:
 | |
|     case BLE_MESH_MODEL_OP_GEN_POWER_LAST_STATUS: {
 | |
|         struct bt_mesh_gen_power_level_srv *srv = model->user_data;
 | |
|         if (opcode == BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS) {
 | |
|             net_buf_simple_add_le16(msg, srv->state->power_actual);
 | |
|             if (srv->transition.counter) {
 | |
|                 bt_mesh_server_calc_remain_time(&srv->transition);
 | |
|                 net_buf_simple_add_le16(msg, srv->state->target_power_actual);
 | |
|                 net_buf_simple_add_u8(msg, srv->transition.remain_time);
 | |
|             }
 | |
|         } else if (opcode == BLE_MESH_MODEL_OP_GEN_POWER_LAST_STATUS) {
 | |
|             net_buf_simple_add_le16(msg, srv->state->power_last);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_STATUS:
 | |
|         if (model->id == BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV) {
 | |
|             struct bt_mesh_gen_power_level_srv *srv = model->user_data;
 | |
|             net_buf_simple_add_le16(msg, srv->state->power_default);
 | |
|         } else if (model->id == BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV) {
 | |
|             struct bt_mesh_gen_power_level_setup_srv *srv = model->user_data;
 | |
|             net_buf_simple_add_le16(msg, srv->state->power_default);
 | |
|         }
 | |
|         break;
 | |
|     case BLE_MESH_MODEL_OP_GEN_POWER_RANGE_STATUS:
 | |
|         if (model->id == BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV) {
 | |
|             struct bt_mesh_gen_power_level_srv *srv = model->user_data;
 | |
|             net_buf_simple_add_u8(msg, srv->state->status_code);
 | |
|             net_buf_simple_add_le16(msg, srv->state->power_range_min);
 | |
|             net_buf_simple_add_le16(msg, srv->state->power_range_max);
 | |
|         } else if (model->id == BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV) {
 | |
|             struct bt_mesh_gen_power_level_setup_srv *srv = model->user_data;
 | |
|             net_buf_simple_add_u8(msg, srv->state->status_code);
 | |
|             net_buf_simple_add_le16(msg, srv->state->power_range_min);
 | |
|             net_buf_simple_add_le16(msg, srv->state->power_range_max);
 | |
|         }
 | |
|         break;
 | |
|     default:
 | |
|         BT_WARN("Unknown Generic Power status opcode 0x%04x", opcode);
 | |
|         if (publish == false) {
 | |
|             bt_mesh_free_buf(msg);
 | |
|         }
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
 | |
|         bt_mesh_free_buf(msg);
 | |
|     } else {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void gen_power_level_get(struct bt_mesh_model *model,
 | |
|                                 struct bt_mesh_msg_ctx *ctx,
 | |
|                                 struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_power_level_srv *srv = model->user_data;
 | |
|     uint16_t opcode = 0U;
 | |
| 
 | |
|     if (srv == NULL || srv->state == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG,
 | |
|                                              model, ctx, NULL, 0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch (ctx->recv_op) {
 | |
|     case BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_GET:
 | |
|         opcode = BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS;
 | |
|         break;
 | |
|     case BLE_MESH_MODEL_OP_GEN_POWER_LAST_GET:
 | |
|         opcode = BLE_MESH_MODEL_OP_GEN_POWER_LAST_STATUS;
 | |
|         break;
 | |
|     case BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_GET:
 | |
|         opcode = BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_STATUS;
 | |
|         break;
 | |
|     case BLE_MESH_MODEL_OP_GEN_POWER_RANGE_GET:
 | |
|         opcode = BLE_MESH_MODEL_OP_GEN_POWER_RANGE_STATUS;
 | |
|         break;
 | |
|     default:
 | |
|         BT_WARN("Unknown Generic Power Get opcode 0x%04x", ctx->recv_op);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     send_gen_power_level_status(model, ctx, false, opcode);
 | |
| }
 | |
| 
 | |
| void gen_power_level_publish(struct bt_mesh_model *model, uint16_t opcode)
 | |
| {
 | |
|     if (model->user_data == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch (model->id) {
 | |
|     case BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV: {
 | |
|         struct bt_mesh_gen_power_level_srv *srv = model->user_data;
 | |
|         if (srv->state == NULL) {
 | |
|             BT_ERR("Invalid Generic Power Level Server state");
 | |
|             return;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case ESP_BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV: {
 | |
|         struct bt_mesh_gen_power_level_setup_srv *srv = model->user_data;
 | |
|         if (srv->state == NULL) {
 | |
|             BT_ERR("Invalid Generic Power Level Setup Server state");
 | |
|             return;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         BT_ERR("Invalid Generic Power Level Server 0x%04x", model->id);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     send_gen_power_level_status(model, NULL, true, opcode);
 | |
| }
 | |
| 
 | |
| static void gen_power_level_set(struct bt_mesh_model *model,
 | |
|                                 struct bt_mesh_msg_ctx *ctx,
 | |
|                                 struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_power_level_srv *srv = model->user_data;
 | |
|     uint8_t tid = 0U, trans_time = 0U, delay = 0U;
 | |
|     bool optional = false;
 | |
|     uint16_t power = 0U;
 | |
|     int64_t now = 0;
 | |
| 
 | |
|     if (srv == NULL || srv->state == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     power = net_buf_simple_pull_le16(buf);
 | |
|     tid = net_buf_simple_pull_u8(buf);
 | |
| 
 | |
|     if (bt_mesh_server_get_optional(model, ctx, buf, &trans_time, &delay, &optional)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|             .power_level_set.op_en = optional,
 | |
|             .power_level_set.power = power,
 | |
|             .power_level_set.tid = tid,
 | |
|             .power_level_set.trans_time = trans_time,
 | |
|             .power_level_set.delay = delay,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                              model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (bt_mesh_is_server_recv_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now)) {
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET) {
 | |
|             send_gen_power_level_status(model, ctx, false, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS);
 | |
|         }
 | |
|         send_gen_power_level_status(model, NULL, true, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS);
 | |
|         /* In this condition, no event will be callback to application layer */
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_generic_server_lock();
 | |
| 
 | |
|     bt_mesh_server_stop_transition(&srv->transition);
 | |
|     bt_mesh_server_update_last_msg(&srv->last, tid, ctx->addr, ctx->recv_dst, &now);
 | |
| 
 | |
|     if (power) {
 | |
|         if (srv->state->power_range_min && power < srv->state->power_range_min) {
 | |
|             power = srv->state->power_range_min;
 | |
|         } else if (srv->state->power_range_max && power > srv->state->power_range_max) {
 | |
|             power = srv->state->power_range_max;
 | |
|         }
 | |
|     }
 | |
|     srv->state->target_power_actual = power;
 | |
| 
 | |
|     /* If the target state is equal to the current state, the transition
 | |
|      * shall not be started and is considered complete.
 | |
|      */
 | |
|     if (srv->state->target_power_actual != srv->state->power_actual) {
 | |
|         generic_power_level_tt_values(srv, trans_time, delay);
 | |
|     } else {
 | |
|         bt_mesh_gen_server_state_change_t change = {
 | |
|             .gen_power_level_set.power = srv->state->power_actual,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                              model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
| 
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET) {
 | |
|             send_gen_power_level_status(model, ctx, false, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS);
 | |
|         }
 | |
|         send_gen_power_level_status(model, NULL, true, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS);
 | |
| 
 | |
|         bt_mesh_generic_server_unlock();
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Copy the ctx of the received message */
 | |
|     if (srv->transition.timer.work.user_data) {
 | |
|         memcpy(srv->transition.timer.work.user_data, ctx, sizeof(struct bt_mesh_msg_ctx));
 | |
|     }
 | |
| 
 | |
|     /* For Instantaneous Transition */
 | |
|     if (srv->transition.counter == 0U) {
 | |
|         srv->state->power_actual = srv->state->target_power_actual;
 | |
|         /* Whenever the Generic Power Actual state is changed to a non-zero value
 | |
|          * as a result of a non-transactional message or a completed sequence of
 | |
|          * transactional messages, the value of the Generic Power Last state shall
 | |
|          * be set to the value of the Generic Power Actual state.
 | |
|          */
 | |
|         if (srv->state->power_actual) {
 | |
|             srv->state->power_last = srv->state->power_actual;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     srv->transition.just_started = true;
 | |
|     if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET) {
 | |
|         send_gen_power_level_status(model, ctx, false, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS);
 | |
|     }
 | |
|     send_gen_power_level_status(model, NULL, true, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS);
 | |
| 
 | |
|     bt_mesh_generic_server_unlock();
 | |
| 
 | |
|     bt_mesh_server_start_transition(&srv->transition);
 | |
| }
 | |
| 
 | |
| /* Generic Power Level Setup Server message handlers */
 | |
| static void gen_power_default_set(struct bt_mesh_model *model,
 | |
|                                   struct bt_mesh_msg_ctx *ctx,
 | |
|                                   struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_power_level_setup_srv *srv = model->user_data;
 | |
|     uint16_t power = 0U;
 | |
| 
 | |
|     if (srv == NULL || srv->state == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     power = net_buf_simple_pull_le16(buf);
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|             .power_default_set.power = power, /* Just callback the actual received value */
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                              model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Value 0x0000 has a special meaning defined: use the value of the
 | |
|      * Generic Power Last state as the default value.
 | |
|      */
 | |
|     if (power == 0x0000) {
 | |
|         power = srv->state->power_last;
 | |
|     }
 | |
| 
 | |
|     if (srv->state->power_default != power) {
 | |
|         srv->state->power_default = power;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_gen_server_state_change_t change = {
 | |
|         .gen_power_default_set.power = power,
 | |
|     };
 | |
|     bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                          model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
| 
 | |
|     if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET) {
 | |
|         send_gen_power_level_status(model, ctx, false, BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_STATUS);
 | |
|     }
 | |
|     send_gen_power_level_status(model, NULL, true, BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_STATUS);
 | |
| }
 | |
| 
 | |
| static void gen_power_range_set(struct bt_mesh_model *model,
 | |
|                                 struct bt_mesh_msg_ctx *ctx,
 | |
|                                 struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_power_level_setup_srv *srv = model->user_data;
 | |
|     uint16_t range_min = 0U, range_max = 0U;
 | |
| 
 | |
|     if (srv == NULL || srv->state == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     range_min = net_buf_simple_pull_le16(buf);
 | |
|     range_max = net_buf_simple_pull_le16(buf);
 | |
| 
 | |
|     if (range_min > range_max) {
 | |
|         BT_ERR("Range min 0x%04x is greater than range max 0x%04x",
 | |
|                 range_min, range_max);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|             .power_range_set.range_min = range_min,
 | |
|             .power_range_set.range_max = range_max,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                              model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (range_min == 0x0000) {
 | |
|         srv->state->status_code = BLE_MESH_CANNOT_SET_RANGE_MIN;
 | |
|     } else if (range_max == 0x0000) {
 | |
|         srv->state->status_code = BLE_MESH_CANNOT_SET_RANGE_MAX;
 | |
|     } else {
 | |
|         srv->state->status_code = BLE_MESH_RANGE_UPDATE_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     if (range_min && srv->state->power_range_min != range_min) {
 | |
|         srv->state->power_range_min = range_min;
 | |
|     }
 | |
| 
 | |
|     if (range_max && srv->state->power_range_max != range_max) {
 | |
|         srv->state->power_range_max = range_max;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_gen_server_state_change_t change = {
 | |
|         .gen_power_range_set.range_min = srv->state->power_range_min,
 | |
|         .gen_power_range_set.range_max = srv->state->power_range_max,
 | |
|     };
 | |
|     bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                          model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
| 
 | |
|     if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET) {
 | |
|         send_gen_power_level_status(model, ctx, false, BLE_MESH_MODEL_OP_GEN_POWER_RANGE_STATUS);
 | |
|     }
 | |
|     send_gen_power_level_status(model, NULL, true, BLE_MESH_MODEL_OP_GEN_POWER_RANGE_STATUS);
 | |
| }
 | |
| 
 | |
| /* Generic Battery Server message handlers */
 | |
| static void gen_battery_get(struct bt_mesh_model *model,
 | |
|                             struct bt_mesh_msg_ctx *ctx,
 | |
|                             struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_battery_srv *srv = model->user_data;
 | |
|     NET_BUF_SIMPLE_DEFINE(msg, 2 + 8 + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
| 
 | |
|     if (srv == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG,
 | |
|                                              model, ctx, NULL, 0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_model_msg_init(&msg, BLE_MESH_MODEL_OP_GEN_BATTERY_STATUS);
 | |
|     net_buf_simple_add_le32(&msg, srv->state.time_to_discharge << 8 | srv->state.battery_level);
 | |
|     net_buf_simple_add_le32(&msg, srv->state.battery_flags << 24 | srv->state.time_to_charge);
 | |
| 
 | |
|     BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, &msg, NULL, NULL));
 | |
| }
 | |
| 
 | |
| /* Generic Location Server message handlers */
 | |
| static void send_gen_location_status(struct bt_mesh_model *model,
 | |
|                                      struct bt_mesh_msg_ctx *ctx,
 | |
|                                      bool publish, uint16_t opcode)
 | |
| {
 | |
|     struct net_buf_simple *msg = NULL;
 | |
|     uint8_t length = 1 + 10;
 | |
| 
 | |
|     if (ctx == NULL && publish == false) {
 | |
|         BT_ERR("%s, Invalid parameter", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         msg = bt_mesh_alloc_buf(length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
|         if (msg == NULL) {
 | |
|             BT_ERR("%s, Out of memory", __func__);
 | |
|             return;
 | |
|         }
 | |
|     } else {
 | |
|         msg = bt_mesh_server_get_pub_msg(model, length);
 | |
|         if (msg == NULL) {
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     bt_mesh_model_msg_init(msg, opcode);
 | |
|     switch (opcode) {
 | |
|     case BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_STATUS:
 | |
|         if (model->id == BLE_MESH_MODEL_ID_GEN_LOCATION_SRV) {
 | |
|             struct bt_mesh_gen_location_srv *srv = model->user_data;
 | |
|             net_buf_simple_add_le32(msg, srv->state->global_latitude);
 | |
|             net_buf_simple_add_le32(msg, srv->state->global_longitude);
 | |
|             net_buf_simple_add_le16(msg, srv->state->global_altitude);
 | |
|         } else if (model->id == BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV) {
 | |
|             struct bt_mesh_gen_location_setup_srv *srv = model->user_data;
 | |
|             net_buf_simple_add_le32(msg, srv->state->global_latitude);
 | |
|             net_buf_simple_add_le32(msg, srv->state->global_longitude);
 | |
|             net_buf_simple_add_le16(msg, srv->state->global_altitude);
 | |
|         }
 | |
|         break;
 | |
|     case BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_STATUS:
 | |
|         if (model->id == BLE_MESH_MODEL_ID_GEN_LOCATION_SRV) {
 | |
|             struct bt_mesh_gen_location_srv *srv = model->user_data;
 | |
|             net_buf_simple_add_le16(msg, srv->state->local_north);
 | |
|             net_buf_simple_add_le16(msg, srv->state->local_east);
 | |
|             net_buf_simple_add_le16(msg, srv->state->local_altitude);
 | |
|             net_buf_simple_add_u8(msg, srv->state->floor_number);
 | |
|             net_buf_simple_add_le16(msg, srv->state->uncertainty);
 | |
|         } else if (model->id == BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV) {
 | |
|             struct bt_mesh_gen_location_setup_srv *srv = model->user_data;
 | |
|             net_buf_simple_add_le16(msg, srv->state->local_north);
 | |
|             net_buf_simple_add_le16(msg, srv->state->local_east);
 | |
|             net_buf_simple_add_le16(msg, srv->state->local_altitude);
 | |
|             net_buf_simple_add_u8(msg, srv->state->floor_number);
 | |
|             net_buf_simple_add_le16(msg, srv->state->uncertainty);
 | |
|         }
 | |
|         break;
 | |
|     default:
 | |
|         BT_WARN("Unknown Generic Location status opcode 0x%04x", opcode);
 | |
|         if (publish == false) {
 | |
|             bt_mesh_free_buf(msg);
 | |
|         }
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
 | |
|         bt_mesh_free_buf(msg);
 | |
|     } else {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void gen_location_get(struct bt_mesh_model *model,
 | |
|                              struct bt_mesh_msg_ctx *ctx,
 | |
|                              struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_location_srv *srv = model->user_data;
 | |
|     uint16_t opcode = 0U;
 | |
| 
 | |
|     if (srv == NULL || srv->state == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG,
 | |
|                                              model, ctx, NULL, 0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch (ctx->recv_op) {
 | |
|     case BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_GET:
 | |
|         opcode = BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_STATUS;
 | |
|         break;
 | |
|     case BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_GET:
 | |
|         opcode = BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_STATUS;
 | |
|         break;
 | |
|     default:
 | |
|         BT_WARN("Unknown Generic Location Get opcode 0x%04x", ctx->recv_op);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     send_gen_location_status(model, ctx, false, opcode);
 | |
| }
 | |
| 
 | |
| /* Generic Location Setup Server message handlers */
 | |
| static void gen_location_set(struct bt_mesh_model *model,
 | |
|                              struct bt_mesh_msg_ctx *ctx,
 | |
|                              struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_location_setup_srv *srv = model->user_data;
 | |
|     uint16_t opcode = 0U;
 | |
| 
 | |
|     if (srv == NULL || srv->state == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch (ctx->recv_op) {
 | |
|     case BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET:
 | |
|     case BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET_UNACK: {
 | |
|         opcode = BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_STATUS;
 | |
|         int32_t latitude = net_buf_simple_pull_le32(buf);
 | |
|         int32_t longitude = net_buf_simple_pull_le32(buf);
 | |
|         int16_t altitude = net_buf_simple_pull_le16(buf);
 | |
| 
 | |
|         /* Callback the received message to the application layer */
 | |
|         if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|             bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|                 .loc_global_set.latitude = latitude,
 | |
|                 .loc_global_set.longitude = longitude,
 | |
|                 .loc_global_set.altitude = altitude,
 | |
|             };
 | |
|             bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                                  model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         if (latitude != 0x80000000) {
 | |
|             srv->state->global_latitude = latitude;
 | |
|         }
 | |
|         if (longitude != 0x80000000) {
 | |
|             srv->state->global_longitude = longitude;
 | |
|         }
 | |
|         if (altitude != 0x7FFF) {
 | |
|             srv->state->global_altitude = altitude;
 | |
|         }
 | |
| 
 | |
|         bt_mesh_gen_server_state_change_t change = {
 | |
|             .gen_loc_global_set.latitude = srv->state->global_latitude,
 | |
|             .gen_loc_global_set.longitude = srv->state->global_longitude,
 | |
|             .gen_loc_global_set.altitude = srv->state->global_altitude,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                              model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET:
 | |
|     case BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET_UNACK: {
 | |
|         opcode = BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_STATUS;
 | |
|         uint16_t north = net_buf_simple_pull_le16(buf);
 | |
|         uint16_t east = net_buf_simple_pull_le16(buf);
 | |
|         uint16_t altitude = net_buf_simple_pull_le16(buf);
 | |
|         uint8_t floor = net_buf_simple_pull_u8(buf);
 | |
|         uint16_t uncertainty = net_buf_simple_pull_le16(buf);
 | |
| 
 | |
|         /* Callback the received message to the application layer */
 | |
|         if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|             bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|                 .loc_local_set.north = north,
 | |
|                 .loc_local_set.east = east,
 | |
|                 .loc_local_set.altitude = altitude,
 | |
|                 .loc_local_set.floor_number = floor,
 | |
|                 .loc_local_set.uncertainty = uncertainty,
 | |
|             };
 | |
|             bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                                  model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         if (north != 0x8000) {
 | |
|             srv->state->local_north = north;
 | |
|         }
 | |
|         if (east != 0x8000) {
 | |
|             srv->state->local_east = east;
 | |
|         }
 | |
|         if (altitude != 0x7FFF) {
 | |
|             srv->state->local_altitude = altitude;
 | |
|         }
 | |
|         if (floor != 0xFF) {
 | |
|             srv->state->floor_number = floor;
 | |
|         }
 | |
|         srv->state->uncertainty = uncertainty;
 | |
| 
 | |
|         bt_mesh_gen_server_state_change_t change = {
 | |
|             .gen_loc_local_set.north = srv->state->local_north,
 | |
|             .gen_loc_local_set.east = srv->state->local_east,
 | |
|             .gen_loc_local_set.altitude = srv->state->local_altitude,
 | |
|             .gen_loc_local_set.floor_number = srv->state->floor_number,
 | |
|             .gen_loc_local_set.uncertainty = srv->state->uncertainty,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                              model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         BT_WARN("Unknown Generic Location Set opcode 0x%04x", ctx->recv_op);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET ||
 | |
|             ctx->recv_op == BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET) {
 | |
|         send_gen_location_status(model, ctx, false, opcode);
 | |
|     }
 | |
|     send_gen_location_status(model, NULL, true, opcode);
 | |
| }
 | |
| 
 | |
| /* Generic User Property Server message handlers */
 | |
| static struct bt_mesh_generic_property *gen_get_user_property(struct bt_mesh_model *model,
 | |
|                                                               uint16_t property_id)
 | |
| {
 | |
|     struct bt_mesh_gen_user_prop_srv *srv = model->user_data;
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < srv->property_count; i++) {
 | |
|         if (srv->properties[i].id == property_id) {
 | |
|             return &srv->properties[i];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| static void send_gen_user_prop_status(struct bt_mesh_model *model,
 | |
|                                       struct bt_mesh_msg_ctx *ctx,
 | |
|                                       uint16_t property_id, bool publish)
 | |
| {
 | |
|     struct bt_mesh_generic_property *property = NULL;
 | |
|     struct net_buf_simple *msg = NULL;
 | |
|     uint16_t length = 0U;
 | |
| 
 | |
|     if (property_id == BLE_MESH_INVALID_DEVICE_PROPERTY_ID) {
 | |
|         BT_ERR("Invalid User Property ID 0x%04x", property_id);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     property = gen_get_user_property(model, property_id);
 | |
|     if (property == NULL) {
 | |
|         BT_WARN("User property 0x%04x not exists", property_id);
 | |
|         length = sizeof(property_id);
 | |
|     } else {
 | |
|         length = sizeof(property->id) + sizeof(property->user_access) + property->val->len;
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         msg = bt_mesh_alloc_buf(1 + length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
|         if (msg == NULL) {
 | |
|             BT_ERR("%s, Out of memory", __func__);
 | |
|             return;
 | |
|         }
 | |
|     } else {
 | |
|         msg = bt_mesh_server_get_pub_msg(model, 1 + length);
 | |
|         if (msg == NULL) {
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_STATUS);
 | |
|     if (property == NULL) {
 | |
|         net_buf_simple_add_le16(msg, property_id);
 | |
|     } else {
 | |
|         net_buf_simple_add_le16(msg, property->id);
 | |
|         net_buf_simple_add_u8(msg, property->user_access);
 | |
|         if ((ctx->recv_op == BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_GET &&
 | |
|                 property->user_access != USER_ACCESS_PROHIBIT &&
 | |
|                 property->user_access != USER_ACCESS_WRITE) ||
 | |
|                 ((ctx->recv_op == BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET ||
 | |
|                   ctx->recv_op == BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET_UNACK) &&
 | |
|                  property->user_access != USER_ACCESS_PROHIBIT &&
 | |
|                  property->user_access != USER_ACCESS_READ)) {
 | |
|             net_buf_simple_add_mem(msg, property->val->data, property->val->len);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
 | |
|         bt_mesh_free_buf(msg);
 | |
|     } else {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void gen_user_prop_get(struct bt_mesh_model *model,
 | |
|                               struct bt_mesh_msg_ctx *ctx,
 | |
|                               struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_user_prop_srv *srv = model->user_data;
 | |
| 
 | |
|     if (srv == NULL || srv->property_count == 0U || srv->properties == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         /**
 | |
|          * Also we can use __attribute__((packed)) for esp_ble_mesh_gen_user_property_get_t,
 | |
|          * and directly callback with buf->data & buf->len.
 | |
|          */
 | |
|         bt_mesh_gen_server_recv_get_msg_t get = {0};
 | |
|         const uint8_t *param = NULL;
 | |
|         size_t len = 0;
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_GET) {
 | |
|             get.user_property_get.id = net_buf_simple_pull_le16(buf);
 | |
|             param = (const uint8_t *)&get;
 | |
|             len = sizeof(get);
 | |
|         }
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG,
 | |
|                                              model, ctx, param, len);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch (ctx->recv_op) {
 | |
|     case BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_GET: {
 | |
|         struct net_buf_simple *msg = NULL;
 | |
|         uint8_t i;
 | |
|         msg = bt_mesh_alloc_buf(1 + srv->property_count * 2 + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
|         if (msg == NULL) {
 | |
|             BT_ERR("%s, Out of memory", __func__);
 | |
|             return;
 | |
|         }
 | |
|         bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_STATUS);
 | |
|         for (i = 0U; i < srv->property_count; i++) {
 | |
|             if (srv->properties[i].admin_access != ADMIN_NOT_USER_PROP &&
 | |
|                 srv->properties[i].manu_access != MANU_NOT_USER_PROP) {
 | |
|                 net_buf_simple_add_le16(msg, srv->properties[i].id);
 | |
|             }
 | |
|         }
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
 | |
|         bt_mesh_free_buf(msg);
 | |
|         return;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_GET: {
 | |
|         uint16_t property_id = net_buf_simple_pull_le16(buf);
 | |
|         send_gen_user_prop_status(model, ctx, property_id, false);
 | |
|         return;
 | |
|     }
 | |
|     default:
 | |
|         BT_WARN("Unknown Generic User Property Get opcode 0x%04x", ctx->recv_op);
 | |
|         return;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void gen_user_prop_set(struct bt_mesh_model *model,
 | |
|                               struct bt_mesh_msg_ctx *ctx,
 | |
|                               struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_user_prop_srv *srv = model->user_data;
 | |
|     struct bt_mesh_generic_property *property = NULL;
 | |
|     uint16_t property_id = 0U;
 | |
|     uint8_t expect_len = 0U;
 | |
| 
 | |
|     if (srv == NULL || srv->property_count == 0U || srv->properties == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     property_id = net_buf_simple_pull_le16(buf);
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|             .user_property_set.id = property_id,
 | |
|             .user_property_set.value = buf,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                              model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     property = gen_get_user_property(model, property_id);
 | |
|     if (property == NULL || property->user_access == USER_ACCESS_PROHIBIT ||
 | |
|         property->user_access == USER_ACCESS_READ) {
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET) {
 | |
|             send_gen_user_prop_status(model, ctx, property_id, false);
 | |
|         }
 | |
|         send_gen_user_prop_status(model, ctx, property_id, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* For BLE Mesh Model BQB test:
 | |
|      * PTS will send Generic User Property Set/Set Unack messages with
 | |
|      * invalid device property value length, these messages need to be
 | |
|      * ignored, otherwise the test case will fail.
 | |
|      */
 | |
|     expect_len = bt_mesh_get_dev_prop_len(property_id);
 | |
|     if (buf->len != expect_len) {
 | |
|         BT_ERR("Invalid User Property 0x%04x length, expect %d, actual %d",
 | |
|                 property_id, expect_len, buf->len);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     net_buf_simple_reset(property->val);
 | |
|     net_buf_simple_add_mem(property->val, buf->data, MIN(buf->len, property->val->size));
 | |
| 
 | |
|     bt_mesh_gen_server_state_change_t change = {
 | |
|         .gen_user_prop_set.id = property_id,
 | |
|         .gen_user_prop_set.value = property->val,
 | |
|     };
 | |
|     bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                          model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
| 
 | |
|     if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET) {
 | |
|         send_gen_user_prop_status(model, ctx, property_id, false);
 | |
|     }
 | |
|     send_gen_user_prop_status(model, ctx, property_id, true);
 | |
| }
 | |
| 
 | |
| /* Generic Admin Property Server message handlers */
 | |
| static struct bt_mesh_generic_property *gen_get_admin_property(struct bt_mesh_model *model,
 | |
|                                                                uint16_t property_id)
 | |
| {
 | |
|     struct bt_mesh_gen_admin_prop_srv *srv = model->user_data;
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < srv->property_count; i++) {
 | |
|         if (srv->properties[i].id == property_id) {
 | |
|             return &srv->properties[i];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| static void send_gen_admin_prop_status(struct bt_mesh_model *model,
 | |
|                                        struct bt_mesh_msg_ctx *ctx,
 | |
|                                        uint16_t property_id, bool publish)
 | |
| {
 | |
|     struct bt_mesh_generic_property *property = NULL;
 | |
|     struct net_buf_simple *msg = NULL;
 | |
|     uint16_t length = 0U;
 | |
| 
 | |
|     if (property_id == BLE_MESH_INVALID_DEVICE_PROPERTY_ID) {
 | |
|         BT_ERR("Invalid Admin Property ID 0x%04x", property_id);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     property = gen_get_admin_property(model, property_id);
 | |
|     if (property == NULL) {
 | |
|         BT_WARN("Admin property 0x%04x not exists", property_id);
 | |
|         length = sizeof(property_id);
 | |
|     } else {
 | |
|         length = sizeof(property->id) + sizeof(property->admin_access) + property->val->len;
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         msg = bt_mesh_alloc_buf(1 + length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
|         if (msg == NULL) {
 | |
|             BT_ERR("%s, Out of memory", __func__);
 | |
|             return;
 | |
|         }
 | |
|     } else {
 | |
|         msg = bt_mesh_server_get_pub_msg(model, 1 + length);
 | |
|         if (msg == NULL) {
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_STATUS);
 | |
|     if (property == NULL) {
 | |
|         net_buf_simple_add_le16(msg, property_id);
 | |
|     } else {
 | |
|         net_buf_simple_add_le16(msg, property->id);
 | |
|         net_buf_simple_add_u8(msg, property->admin_access);
 | |
|         if (ctx->recv_op != BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_GET ||
 | |
|                 property->admin_access != ADMIN_ACCESS_WRITE) {
 | |
|             net_buf_simple_add_mem(msg, property->val->data, property->val->len);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
 | |
|         bt_mesh_free_buf(msg);
 | |
|     } else {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void gen_admin_prop_get(struct bt_mesh_model *model,
 | |
|                                struct bt_mesh_msg_ctx *ctx,
 | |
|                                struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_admin_prop_srv *srv = model->user_data;
 | |
| 
 | |
|     if (srv == NULL || srv->property_count == 0U || srv->properties == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_get_msg_t get = {0};
 | |
|         const uint8_t *param = NULL;
 | |
|         size_t len = 0U;
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_GET) {
 | |
|             get.admin_property_get.id = net_buf_simple_pull_le16(buf);
 | |
|             param = (const uint8_t *)&get;
 | |
|             len = sizeof(get);
 | |
|         }
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG,
 | |
|                                              model, ctx, param, len);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch (ctx->recv_op) {
 | |
|     case BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_GET: {
 | |
|         struct net_buf_simple *msg = NULL;
 | |
|         uint8_t i = 0U;
 | |
|         msg = bt_mesh_alloc_buf(1 + srv->property_count * 2 + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
|         if (msg == NULL) {
 | |
|             BT_ERR("%s, Out of memory", __func__);
 | |
|             return;
 | |
|         }
 | |
|         bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_STATUS);
 | |
|         for (i = 0U; i < srv->property_count; i++) {
 | |
|             net_buf_simple_add_le16(msg, srv->properties[i].id);
 | |
|         }
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
 | |
|         bt_mesh_free_buf(msg);
 | |
|         return;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_GET: {
 | |
|         uint16_t property_id = net_buf_simple_pull_le16(buf);
 | |
|         send_gen_admin_prop_status(model, ctx, property_id, false);
 | |
|         return;
 | |
|     }
 | |
|     default:
 | |
|         BT_WARN("Unknown Generic Admin Property Get opcode 0x%04x", ctx->recv_op);
 | |
|         return;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void gen_admin_prop_set(struct bt_mesh_model *model,
 | |
|                                struct bt_mesh_msg_ctx *ctx,
 | |
|                                struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_admin_prop_srv *srv = model->user_data;
 | |
|     struct bt_mesh_generic_property *property = NULL;
 | |
|     uint16_t property_id = 0U;
 | |
|     uint8_t access = 0U;
 | |
| 
 | |
|     if (srv == NULL || srv->property_count == 0U || srv->properties == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     property_id = net_buf_simple_pull_le16(buf);
 | |
|     access = net_buf_simple_pull_u8(buf);
 | |
|     if (access > ADMIN_ACCESS_READ_WRITE) {
 | |
|         BT_ERR("Invalid Admin Access 0x%02x", access);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|             .admin_property_set.id = property_id,
 | |
|             .admin_property_set.access = access,
 | |
|             .admin_property_set.value = buf,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                              model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     property = gen_get_admin_property(model, property_id);
 | |
|     if (property == NULL) {
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET) {
 | |
|             send_gen_admin_prop_status(model, ctx, property_id, false);
 | |
|         }
 | |
|         send_gen_admin_prop_status(model, ctx, property_id, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     property->admin_access = access;
 | |
| 
 | |
|     net_buf_simple_reset(property->val);
 | |
|     net_buf_simple_add_mem(property->val, buf->data, MIN(buf->len, property->val->size));
 | |
| 
 | |
|     bt_mesh_gen_server_state_change_t change = {
 | |
|         .gen_admin_prop_set.id = property_id,
 | |
|         .gen_admin_prop_set.access = property->admin_access,
 | |
|         .gen_admin_prop_set.value = property->val,
 | |
|     };
 | |
|     bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                          model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
| 
 | |
|     if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET) {
 | |
|         send_gen_admin_prop_status(model, ctx, property_id, false);
 | |
|     }
 | |
|     send_gen_admin_prop_status(model, ctx, property_id, true);
 | |
| }
 | |
| 
 | |
| /* Generic Manufacturer Property Server message handlers */
 | |
| static struct bt_mesh_generic_property *gen_get_manu_property(struct bt_mesh_model *model,
 | |
|                                                               uint16_t property_id)
 | |
| {
 | |
|     struct bt_mesh_gen_manu_prop_srv *srv = model->user_data;
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < srv->property_count; i++) {
 | |
|         if (srv->properties[i].id == property_id) {
 | |
|             return &srv->properties[i];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| static void send_gen_manu_prop_status(struct bt_mesh_model *model,
 | |
|                                       struct bt_mesh_msg_ctx *ctx,
 | |
|                                       uint16_t property_id, bool publish)
 | |
| {
 | |
|     struct bt_mesh_generic_property *property = NULL;
 | |
|     struct net_buf_simple *msg = NULL;
 | |
|     uint16_t length = 0U;
 | |
| 
 | |
|     if (property_id == BLE_MESH_INVALID_DEVICE_PROPERTY_ID) {
 | |
|         BT_ERR("Invalid Manu Property ID 0x%04x", property_id);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     property = gen_get_manu_property(model, property_id);
 | |
|     if (property == NULL) {
 | |
|         BT_WARN("Manu property 0x%04x not exists", property_id);
 | |
|         length = sizeof(property_id);
 | |
|     } else {
 | |
|         length = sizeof(property->id) + sizeof(property->manu_access) + property->val->len;
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         msg = bt_mesh_alloc_buf(1 + length + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
|         if (msg == NULL) {
 | |
|             BT_ERR("%s, Out of memory", __func__);
 | |
|             return;
 | |
|         }
 | |
|     } else {
 | |
|         msg = bt_mesh_server_get_pub_msg(model, 1 + length);
 | |
|         if (msg == NULL) {
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_STATUS);
 | |
|     if (property == NULL) {
 | |
|         net_buf_simple_add_le16(msg, property_id);
 | |
|     } else {
 | |
|         net_buf_simple_add_le16(msg, property->id);
 | |
|         net_buf_simple_add_u8(msg, property->manu_access);
 | |
|         net_buf_simple_add_mem(msg, property->val->data, property->val->len);
 | |
|     }
 | |
| 
 | |
|     if (publish == false) {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
 | |
|         bt_mesh_free_buf(msg);
 | |
|     } else {
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_publish(model));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void gen_manu_prop_get(struct bt_mesh_model *model,
 | |
|                               struct bt_mesh_msg_ctx *ctx,
 | |
|                               struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_manu_prop_srv *srv = model->user_data;
 | |
| 
 | |
|     if (srv == NULL || srv->property_count == 0U || srv->properties == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_get_msg_t get = {0};
 | |
|         const uint8_t *param = NULL;
 | |
|         size_t len = 0U;
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_GET) {
 | |
|             get.manu_property_get.id = net_buf_simple_pull_le16(buf);
 | |
|             param = (const uint8_t *)&get;
 | |
|             len = sizeof(get);
 | |
|         }
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG,
 | |
|                                              model, ctx, param, len);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch (ctx->recv_op) {
 | |
|     case BLE_MESH_MODEL_OP_GEN_MANU_PROPERTIES_GET: {
 | |
|         struct net_buf_simple *msg = NULL;
 | |
|         uint8_t i = 0U;
 | |
|         msg = bt_mesh_alloc_buf(1 + srv->property_count * 2 + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
|         if (msg == NULL) {
 | |
|             BT_ERR("%s, Out of memory", __func__);
 | |
|             return;
 | |
|         }
 | |
|         bt_mesh_model_msg_init(msg, BLE_MESH_MODEL_OP_GEN_MANU_PROPERTIES_STATUS);
 | |
|         for (i = 0U; i < srv->property_count; i++) {
 | |
|             net_buf_simple_add_le16(msg, srv->properties[i].id);
 | |
|         }
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, msg, NULL, NULL));
 | |
|         bt_mesh_free_buf(msg);
 | |
|         return;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_GET: {
 | |
|         uint16_t property_id = net_buf_simple_pull_le16(buf);
 | |
|         send_gen_manu_prop_status(model, ctx, property_id, false);
 | |
|         return;
 | |
|     }
 | |
|     default:
 | |
|         BT_WARN("Unknown Generic Manu Property Get opcode 0x%04x", ctx->recv_op);
 | |
|         return;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void gen_manu_prop_set(struct bt_mesh_model *model,
 | |
|                               struct bt_mesh_msg_ctx *ctx,
 | |
|                               struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_manu_prop_srv *srv = model->user_data;
 | |
|     struct bt_mesh_generic_property *property = NULL;
 | |
|     uint16_t property_id = 0U;
 | |
|     uint8_t access = 0U;
 | |
| 
 | |
|     if (srv == NULL || srv->property_count == 0U || srv->properties == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     property_id = net_buf_simple_pull_le16(buf);
 | |
|     access = net_buf_simple_pull_u8(buf);
 | |
|     if (access > MANU_ACCESS_READ) {
 | |
|         BT_ERR("Invalid Manu Access 0x%02x", access);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_set_msg_t set = {
 | |
|             .manu_property_set.id = property_id,
 | |
|             .manu_property_set.access = access,
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG,
 | |
|                                              model, ctx, (const uint8_t *)&set, sizeof(set));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     property = gen_get_manu_property(model, property_id);
 | |
|     if (property == NULL) {
 | |
|         if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_SET) {
 | |
|             send_gen_manu_prop_status(model, ctx, property_id, false);
 | |
|         }
 | |
|         send_gen_manu_prop_status(model, ctx, property_id, true);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     property->manu_access = access;
 | |
| 
 | |
|     bt_mesh_gen_server_state_change_t change = {
 | |
|         .gen_manu_prop_set.id = property_id,
 | |
|         .gen_manu_prop_set.access = property->manu_access,
 | |
|     };
 | |
|     bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE,
 | |
|                                          model, ctx, (const uint8_t *)&change, sizeof(change));
 | |
| 
 | |
|     if (ctx->recv_op == BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_SET) {
 | |
|         send_gen_manu_prop_status(model, ctx, property_id, false);
 | |
|     }
 | |
|     send_gen_manu_prop_status(model, ctx, property_id, true);
 | |
| }
 | |
| 
 | |
| /* Generic Client Property Server message handlers */
 | |
| static int search_prop_id_index(const uint16_t *array, uint8_t array_idx, uint16_t id)
 | |
| {
 | |
|     static const uint16_t *start = NULL;
 | |
|     uint8_t index = 0U;
 | |
|     uint16_t temp = 0U;
 | |
| 
 | |
|     if (start == NULL) {
 | |
|         start = array;
 | |
|     }
 | |
| 
 | |
|     if (array_idx == 0U) {
 | |
|         if (*array >= id) {
 | |
|             return array - start;
 | |
|         }
 | |
| 
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     index = array_idx / 2;
 | |
|     temp = array[index];
 | |
| 
 | |
|     if (temp == id) {
 | |
|         return array + index - start;
 | |
|     }
 | |
| 
 | |
|     if (temp > id) {
 | |
|         return search_prop_id_index(array, index, id);
 | |
|     }
 | |
| 
 | |
|     return search_prop_id_index(array + index + 1, array_idx - 1 - index, id);
 | |
| }
 | |
| 
 | |
| static void gen_client_prop_get(struct bt_mesh_model *model,
 | |
|                                 struct bt_mesh_msg_ctx *ctx,
 | |
|                                 struct net_buf_simple *buf)
 | |
| {
 | |
|     struct bt_mesh_gen_client_prop_srv *srv = model->user_data;
 | |
|     struct net_buf_simple *sdu = NULL;
 | |
|     uint16_t total_len = 5U;
 | |
|     uint16_t property_id = 0U;
 | |
|     int i, index = 0;
 | |
| 
 | |
|     if (srv == NULL || srv->id_count == 0U || srv->property_ids == NULL) {
 | |
|         BT_ERR("%s, Invalid model user data", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Callback the received message to the application layer */
 | |
|     if (srv->rsp_ctrl.get_auto_rsp == BLE_MESH_SERVER_RSP_BY_APP) {
 | |
|         bt_mesh_gen_server_recv_get_msg_t get = {
 | |
|             .client_properties_get.id = net_buf_simple_pull_le16(buf),
 | |
|         };
 | |
|         bt_mesh_generic_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_GET_MSG,
 | |
|                                              model, ctx, (const uint8_t *)&get, sizeof(get));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* The sequence shall be in an ascending order of Property ID values and shall
 | |
|      * start with a smallest Property ID that is greater than or equal to the value
 | |
|      * of the Generic Client Property field of the Generic Client Properties Get
 | |
|      * message that it is responding to.
 | |
|      */
 | |
| 
 | |
|     property_id = net_buf_simple_pull_le16(buf);
 | |
|     index = search_prop_id_index(srv->property_ids, srv->id_count - 1, property_id);
 | |
|     if (index < 0) {
 | |
|         NET_BUF_SIMPLE_DEFINE(msg, 1 + BLE_MESH_SERVER_TRANS_MIC_SIZE);
 | |
|         bt_mesh_model_msg_init(&msg, BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_STATUS);
 | |
|         BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, &msg, NULL, NULL));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     sdu = bt_mesh_alloc_buf(MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN));
 | |
|     if (sdu == NULL) {
 | |
|         BT_ERR("%s, Out of memory", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_model_msg_init(sdu, BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_STATUS);
 | |
|     for (i = index; i < srv->id_count; i++) {
 | |
|         total_len += sizeof(uint16_t);
 | |
|         if (total_len > MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SERVER_RSP_MAX_LEN)) {
 | |
|             /* Add this in case the message is too long */
 | |
|             BT_WARN("Too large generic client properties status");
 | |
|             break;
 | |
|         }
 | |
|         net_buf_simple_add_le16(sdu, srv->property_ids[i]);
 | |
|     }
 | |
| 
 | |
|     BLE_MESH_CHECK_SEND_STATUS(bt_mesh_model_send(model, ctx, sdu, NULL, NULL));
 | |
| 
 | |
|     bt_mesh_free_buf(sdu);
 | |
| }
 | |
| 
 | |
| /* message handlers (End) */
 | |
| 
 | |
| /* Mapping of message handlers for Generic OnOff Server (0x1000) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_onoff_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_ONOFF_GET,       0, gen_onoff_get },
 | |
|     { BLE_MESH_MODEL_OP_GEN_ONOFF_SET,       2, gen_onoff_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2, gen_onoff_set },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| /* Mapping of message handlers for Generic Level Server (0x1002) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_level_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_LEVEL_GET,       0, gen_level_get },
 | |
|     { BLE_MESH_MODEL_OP_GEN_LEVEL_SET,       3, gen_level_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK, 3, gen_level_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_DELTA_SET,       5, gen_delta_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_DELTA_SET_UNACK, 5, gen_delta_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_MOVE_SET,        3, gen_move_set  },
 | |
|     { BLE_MESH_MODEL_OP_GEN_MOVE_SET_UNACK,  3, gen_move_set  },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| /* Mapping of message handlers for Generic Default TT Server (0x1004) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_def_trans_time_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_GET,       0, gen_def_trans_time_get },
 | |
|     { BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET,       1, gen_def_trans_time_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_DEF_TRANS_TIME_SET_UNACK, 1, gen_def_trans_time_set },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| /* Mapping of message handlers for Generic Power OnOff Server (0x1006) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_power_onoff_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_ONPOWERUP_GET, 0, gen_onpowerup_get },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| /* Mapping of message handlers for Generic Power OnOff Setup Server (0x1007) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_power_onoff_setup_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET,       1, gen_onpowerup_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_ONPOWERUP_SET_UNACK, 1, gen_onpowerup_set },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| /* Mapping of message handlers for Generic Power Level Server (0x1009) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_power_level_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_GET,       0, gen_power_level_get },
 | |
|     { BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET,       3, gen_power_level_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_SET_UNACK, 3, gen_power_level_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_POWER_LAST_GET,        0, gen_power_level_get },
 | |
|     { BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_GET,     0, gen_power_level_get },
 | |
|     { BLE_MESH_MODEL_OP_GEN_POWER_RANGE_GET,       0, gen_power_level_get },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| /* Mapping of message handlers for Generic Power Level Setup Server (0x100A) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_power_level_setup_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET,       2, gen_power_default_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_POWER_DEFAULT_SET_UNACK, 2, gen_power_default_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET,         4, gen_power_range_set   },
 | |
|     { BLE_MESH_MODEL_OP_GEN_POWER_RANGE_SET_UNACK,   4, gen_power_range_set   },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| /* Mapping of message handlers for Generic Battery Server (0x100C) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_battery_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_BATTERY_GET, 0, gen_battery_get },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| /* Mapping of message handlers for Generic Location Server (0x100E) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_location_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_GET, 0, gen_location_get },
 | |
|     { BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_GET,  0, gen_location_get },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| /* Mapping of message handlers for Generic Location Setup Server (0x100F) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_location_setup_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET,       10, gen_location_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_LOC_GLOBAL_SET_UNACK, 10, gen_location_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET,         9, gen_location_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_LOC_LOCAL_SET_UNACK,   9, gen_location_set },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| /* Mapping of message handlers for Generic User Property Server (0x1013) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_user_prop_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_GET,     0, gen_user_prop_get },
 | |
|     { BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_GET,       2, gen_user_prop_get },
 | |
|     { BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET,       3, gen_user_prop_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_SET_UNACK, 3, gen_user_prop_set },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| /* Mapping of message handlers for Generic Admin Property Server (0x1011) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_admin_prop_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTIES_GET,     0, gen_admin_prop_get },
 | |
|     { BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_GET,       2, gen_admin_prop_get },
 | |
|     { BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET,       4, gen_admin_prop_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_SET_UNACK, 4, gen_admin_prop_set },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| /* Mapping of message handlers for Generic Manufacturer Property Server (0x1012) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_manu_prop_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_MANU_PROPERTIES_GET,     0, gen_manu_prop_get },
 | |
|     { BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_GET,       2, gen_manu_prop_get },
 | |
|     { BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_SET,       3, gen_manu_prop_set },
 | |
|     { BLE_MESH_MODEL_OP_GEN_MANU_PROPERTY_SET_UNACK, 3, gen_manu_prop_set },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| /* Mapping of message handlers for Generic Client Property Server (0x1014) */
 | |
| const struct bt_mesh_model_op bt_mesh_gen_client_prop_srv_op[] = {
 | |
|     { BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_GET, 2, gen_client_prop_get },
 | |
|     BLE_MESH_MODEL_OP_END,
 | |
| };
 | |
| 
 | |
| static inline int property_id_compare(const void *p1, const void *p2)
 | |
| {
 | |
|     if (*(uint16_t *)p1 < * (uint16_t *)p2) {
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     if (*(uint16_t *)p1 > *(uint16_t *)p2) {
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static int generic_server_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->user_data == NULL) {
 | |
|         BT_ERR("Invalid Generic Server user data, model id 0x%04x", model->id);
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     switch (model->id) {
 | |
|     case BLE_MESH_MODEL_ID_GEN_ONOFF_SRV: {
 | |
|         struct bt_mesh_gen_onoff_srv *srv = model->user_data;
 | |
|         if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
 | |
|             bt_mesh_server_alloc_ctx(&srv->transition.timer.work);
 | |
|             k_delayed_work_init(&srv->transition.timer, generic_onoff_work_handler);
 | |
|         }
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_LEVEL_SRV: {
 | |
|         struct bt_mesh_gen_level_srv *srv = model->user_data;
 | |
|         if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
 | |
|             bt_mesh_server_alloc_ctx(&srv->transition.timer.work);
 | |
|             k_delayed_work_init(&srv->transition.timer, generic_level_work_handler);
 | |
|         }
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV: {
 | |
|         struct bt_mesh_gen_def_trans_time_srv *srv = model->user_data;
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV: {
 | |
|         struct bt_mesh_gen_power_onoff_srv *srv = model->user_data;
 | |
|         if (srv->state == NULL) {
 | |
|             BT_ERR("Invalid Generic OnPowerUp State");
 | |
|             return -EINVAL;
 | |
|         }
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV: {
 | |
|         struct bt_mesh_gen_power_onoff_setup_srv *srv = model->user_data;
 | |
|         if (srv->state == NULL) {
 | |
|             BT_ERR("Invalid Generic OnPowerUp State");
 | |
|             return -EINVAL;
 | |
|         }
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV: {
 | |
|         struct bt_mesh_gen_power_level_srv *srv = model->user_data;
 | |
|         if (srv->state == NULL) {
 | |
|             BT_ERR("Invalid Generic Power Level State");
 | |
|             return -EINVAL;
 | |
|         }
 | |
|         if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
 | |
|             bt_mesh_server_alloc_ctx(&srv->transition.timer.work);
 | |
|             k_delayed_work_init(&srv->transition.timer, generic_power_level_work_handler);
 | |
|         }
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV: {
 | |
|         struct bt_mesh_gen_power_level_setup_srv *srv = model->user_data;
 | |
|         if (srv->state == NULL) {
 | |
|             BT_ERR("Invalid Generic Power Level State");
 | |
|             return -EINVAL;
 | |
|         }
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_BATTERY_SRV: {
 | |
|         struct bt_mesh_gen_battery_srv *srv = model->user_data;
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_LOCATION_SRV: {
 | |
|         struct bt_mesh_gen_location_srv *srv = model->user_data;
 | |
|         if (srv->state == NULL) {
 | |
|             BT_ERR("Invalid Generic Location State");
 | |
|             return -EINVAL;
 | |
|         }
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV: {
 | |
|         struct bt_mesh_gen_location_setup_srv *srv = model->user_data;
 | |
|         if (srv->state == NULL) {
 | |
|             BT_ERR("Invalid Generic Location State");
 | |
|             return -EINVAL;
 | |
|         }
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_USER_PROP_SRV: {
 | |
|         struct bt_mesh_gen_user_prop_srv *srv = model->user_data;
 | |
|         if (srv->property_count == 0U || srv->properties == NULL) {
 | |
|             BT_ERR("Invalid Generic User Property State");
 | |
|             return -EINVAL;
 | |
|         }
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV: {
 | |
|         struct bt_mesh_gen_admin_prop_srv *srv = model->user_data;
 | |
|         if (srv->property_count == 0U || srv->properties == NULL) {
 | |
|             BT_ERR("Invalid Generic Admin Property State");
 | |
|             return -EINVAL;
 | |
|         }
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV: {
 | |
|         struct bt_mesh_gen_manu_prop_srv *srv = model->user_data;
 | |
|         if (srv->property_count == 0U || srv->properties == NULL) {
 | |
|             BT_ERR("Invalid Generic Manufacturer Property State");
 | |
|             return -EINVAL;
 | |
|         }
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV: {
 | |
|         struct bt_mesh_gen_client_prop_srv *srv = model->user_data;
 | |
|         if (srv->id_count == 0U || srv->property_ids == NULL) {
 | |
|             BT_ERR("Invalid Generic Client Property State");
 | |
|             return -EINVAL;
 | |
|         }
 | |
|         /* Quick sort the Client Property IDs in ascending order */
 | |
|         qsort(srv->property_ids, srv->id_count, sizeof(uint16_t), property_id_compare);
 | |
|         srv->model = model;
 | |
|         break;
 | |
|     }
 | |
|     default:
 | |
|         BT_WARN("Unknown Generic Server, model id 0x%04x", model->id);
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_mutex_create(&generic_server_lock);
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static int gen_onoff_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic OnOff Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| static int gen_level_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Level Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| static int gen_def_trans_time_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Default Trans Time Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| static int gen_power_onoff_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Power OnOff Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     /* When this model is present on an element, the corresponding Generic
 | |
|      * Power OnOff Setup Server model shall also be present.
 | |
|      */
 | |
|     struct bt_mesh_elem *element = bt_mesh_model_elem(model);
 | |
|     if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV) == NULL) {
 | |
|         BT_WARN("Generic Power OnOff Setup Server not present");
 | |
|         /* Just give a warning here, continue with the initialization */
 | |
|     }
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| static int gen_power_onoff_setup_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| static int gen_power_level_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Power Level Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     /* When this model is present on an Element, the corresponding Generic
 | |
|      * Power Level Setup Server model shall also be present.
 | |
|      */
 | |
|     struct bt_mesh_elem *element = bt_mesh_model_elem(model);
 | |
|     if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV) == NULL) {
 | |
|         BT_WARN("Generic Power Level Setup Server not present");
 | |
|         /* Just give a warning here, continue with the initialization */
 | |
|     }
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| static int gen_power_level_setup_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| static int gen_battery_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Battery Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| static int gen_location_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Location Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| static int gen_location_setup_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     /* When this model is present on an Element, the corresponding Generic
 | |
|      * Location Setup Server model shall also be present.
 | |
|      */
 | |
|     struct bt_mesh_elem *element = bt_mesh_model_elem(model);
 | |
|     if (bt_mesh_model_find(element, BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV) == NULL) {
 | |
|         BT_WARN("Generic Location Setup Server not present");
 | |
|         /* Just give a warning here, continue with the initialization */
 | |
|     }
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| static int gen_user_prop_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic User Property Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| static int gen_admin_prop_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Admin Property Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| static int gen_manu_prop_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Manufacturer Property Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| static int gen_client_prop_srv_init(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Client Property Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_init(model);
 | |
| }
 | |
| 
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
| static int generic_server_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->user_data == NULL) {
 | |
|         BT_ERR("Invalid Generic Server user data, model id 0x%04x", model->id);
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     switch (model->id) {
 | |
|     case BLE_MESH_MODEL_ID_GEN_ONOFF_SRV: {
 | |
|         struct bt_mesh_gen_onoff_srv *srv = model->user_data;
 | |
|         if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
 | |
|             bt_mesh_server_free_ctx(&srv->transition.timer.work);
 | |
|             k_delayed_work_free(&srv->transition.timer);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_LEVEL_SRV: {
 | |
|         struct bt_mesh_gen_level_srv *srv = model->user_data;
 | |
|         if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
 | |
|             bt_mesh_server_free_ctx(&srv->transition.timer.work);
 | |
|             k_delayed_work_free(&srv->transition.timer);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV: {
 | |
|         struct bt_mesh_gen_power_level_srv *srv = model->user_data;
 | |
|         if (srv->state == NULL) {
 | |
|             BT_ERR("Invalid Generic Power Level State");
 | |
|             return -EINVAL;
 | |
|         }
 | |
|         if (srv->rsp_ctrl.set_auto_rsp == BLE_MESH_SERVER_AUTO_RSP) {
 | |
|             bt_mesh_server_free_ctx(&srv->transition.timer.work);
 | |
|             k_delayed_work_free(&srv->transition.timer);
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     case BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV:
 | |
|     case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV:
 | |
|     case BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV:
 | |
|     case BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV:
 | |
|     case BLE_MESH_MODEL_ID_GEN_BATTERY_SRV:
 | |
|     case BLE_MESH_MODEL_ID_GEN_LOCATION_SRV:
 | |
|     case BLE_MESH_MODEL_ID_GEN_LOCATION_SETUP_SRV:
 | |
|     case BLE_MESH_MODEL_ID_GEN_USER_PROP_SRV:
 | |
|     case BLE_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV:
 | |
|     case BLE_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV:
 | |
|     case BLE_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV:
 | |
|         break;
 | |
|     default:
 | |
|         BT_WARN("Unknown Generic Server, model id 0x%04x", model->id);
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     bt_mesh_mutex_free(&generic_server_lock);
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static int gen_onoff_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic OnOff Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| 
 | |
| static int gen_level_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Level Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| 
 | |
| static int gen_def_trans_time_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Default Trans Time Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| 
 | |
| static int gen_power_onoff_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Power OnOff Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| 
 | |
| static int gen_power_onoff_setup_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| 
 | |
| static int gen_power_level_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Power Level Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| 
 | |
| static int gen_power_level_setup_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| 
 | |
| static int gen_battery_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Battery Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| 
 | |
| static int gen_location_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Location Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| 
 | |
| static int gen_location_setup_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| 
 | |
| static int gen_user_prop_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic User Property Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| 
 | |
| static int gen_admin_prop_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Admin Property Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| 
 | |
| static int gen_manu_prop_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Manufacturer Property Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| 
 | |
| static int gen_client_prop_srv_deinit(struct bt_mesh_model *model)
 | |
| {
 | |
|     if (model->pub == NULL) {
 | |
|         BT_ERR("Generic Client Property Server has no publication support");
 | |
|         return -EINVAL;
 | |
|     }
 | |
| 
 | |
|     return generic_server_deinit(model);
 | |
| }
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_onoff_srv_cb = {
 | |
|     .init = gen_onoff_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_onoff_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_level_srv_cb = {
 | |
|     .init = gen_level_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_level_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_def_trans_time_srv_cb = {
 | |
|     .init = gen_def_trans_time_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_def_trans_time_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_power_onoff_srv_cb = {
 | |
|     .init = gen_power_onoff_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_power_onoff_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_power_onoff_setup_srv_cb = {
 | |
|     .init = gen_power_onoff_setup_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_power_onoff_setup_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_power_level_srv_cb = {
 | |
|     .init = gen_power_level_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_power_level_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_power_level_setup_srv_cb = {
 | |
|     .init = gen_power_level_setup_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_power_level_setup_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_battery_srv_cb = {
 | |
|     .init = gen_battery_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_battery_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_location_srv_cb = {
 | |
|     .init = gen_location_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_location_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_location_setup_srv_cb = {
 | |
|     .init = gen_location_setup_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_location_setup_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_user_prop_srv_cb = {
 | |
|     .init = gen_user_prop_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_user_prop_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_admin_prop_srv_cb = {
 | |
|     .init = gen_admin_prop_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_admin_prop_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_manu_prop_srv_cb = {
 | |
|     .init = gen_manu_prop_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_manu_prop_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| const struct bt_mesh_model_cb bt_mesh_gen_client_prop_srv_cb = {
 | |
|     .init = gen_client_prop_srv_init,
 | |
| #if CONFIG_BLE_MESH_DEINIT
 | |
|     .deinit = gen_client_prop_srv_deinit,
 | |
| #endif /* CONFIG_BLE_MESH_DEINIT */
 | |
| };
 | |
| 
 | |
| #endif /* CONFIG_BLE_MESH_GENERIC_SERVER */
 | 
