1. Add an API to set Provisioner static oob value 2. Add an API to deinit BLE Mesh stack 3. Add an API to set Provisioner unicast address 4. Add an API to provision devices with fixed address 5. Add an API to store node composition data 6. Add an API to get node with device uuid 7. Add an API to get node with unicast address 8. Add an API to delete node with device uuid 9. Add an API to delete node with unicast address 10. Add an API for Provisioner to update local AppKey 11. Add an API for Provisioner to update local NetKey 12. Support Provisioner persistent functionality 13. Fix Provisioner entering IV Update procedure 14. Fix an issue which may cause client failing to send msg 15. Use bt_mesh.flags to indicate device role 16. Remove several useless macros 17. Callback RSSI of received mesh provisioning packets 18. Modify the Provisioner disable function 19. Change some log level from debug to info 20. Add parameters to Provisioner bind AppKey completion event 21. Fix node ignoring relay messages issue 22. Support using a specific partition for BLE Mesh 23. Fix compile warning when proxy related macros are disabled 24. Clean up BLE Mesh stack included header files 25. NULL can be input if client message needs no parameters 26. Fix compile warning when BT log is disabled 27. Initilize BLE Mesh stack local variables 28. Support using PSRAM for BLE Mesh mutex, queue and task 29. Add a menuconfig option to enable using memory from PSRAM 30. Clean up sdkconfig.defaults of BLE Mesh examples
2795 lines
No EOL
96 KiB
C
2795 lines
No EOL
96 KiB
C
/* Bluetooth: Mesh Generic Server Models
|
|
*
|
|
* Copyright (c) 2018 Vikrant More
|
|
* Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <errno.h>
|
|
|
|
#include "access.h"
|
|
#include "transport.h"
|
|
#include "model_opcode.h"
|
|
#include "state_transition.h"
|
|
#include "device_property.h"
|
|
|
|
#include "btc_ble_mesh_generic_model.h"
|
|
|
|
static bt_mesh_mutex_t generic_server_lock;
|
|
|
|
static void bt_mesh_generic_server_mutex_new(void)
|
|
{
|
|
if (!generic_server_lock.mutex) {
|
|
bt_mesh_mutex_create(&generic_server_lock);
|
|
}
|
|
}
|
|
|
|
static void bt_mesh_generic_server_mutex_free(void)
|
|
{
|
|
bt_mesh_mutex_free(&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;
|
|
u8_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, Failed to allocate 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));
|
|
}
|
|
return;
|
|
}
|
|
|
|
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);
|
|
return;
|
|
}
|
|
|
|
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);
|
|
return;
|
|
}
|
|
|
|
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;
|
|
u8_t tid = 0U, onoff = 0U, trans_time = 0U, delay = 0U;
|
|
bool optional = false;
|
|
s64_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("%s, Invalid OnOff value 0x%02x", __func__, 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 u8_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 u8_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._reserved) {
|
|
memcpy(srv->transition.timer.work._reserved, 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);
|
|
return;
|
|
}
|
|
|
|
/* 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;
|
|
u8_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, Failed to allocate 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));
|
|
}
|
|
return;
|
|
}
|
|
|
|
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);
|
|
return;
|
|
}
|
|
|
|
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);
|
|
return;
|
|
}
|
|
|
|
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;
|
|
u8_t tid = 0U, trans_time = 0U, delay = 0U;
|
|
bool optional = false;
|
|
s16_t level = 0;
|
|
s64_t now = 0;
|
|
|
|
if (srv == NULL) {
|
|
BT_ERR("%s, Invalid model user_data", __func__);
|
|
return;
|
|
}
|
|
|
|
level = (s16_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 u8_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 u8_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._reserved) {
|
|
memcpy(srv->transition.timer.work._reserved, 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);
|
|
return;
|
|
}
|
|
|
|
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;
|
|
u8_t tid = 0U, trans_time = 0U, delay = 0U;
|
|
s32_t tmp32 = 0, delta = 0;
|
|
bool optional = false;
|
|
s64_t now = 0;
|
|
|
|
if (srv == NULL) {
|
|
BT_ERR("%s, Invalid model user_data", __func__);
|
|
return;
|
|
}
|
|
|
|
delta = (s32_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 u8_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 u8_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._reserved) {
|
|
memcpy(srv->transition.timer.work._reserved, 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);
|
|
return;
|
|
}
|
|
|
|
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;
|
|
u8_t tid = 0U, trans_time = 0U, delay = 0U;
|
|
bool optional = false;
|
|
s16_t delta = 0;
|
|
s32_t tmp32 = 0;
|
|
s64_t now = 0;
|
|
|
|
if (srv == NULL) {
|
|
BT_ERR("%s, Invalid model user_data", __func__);
|
|
return;
|
|
}
|
|
|
|
delta = (s16_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 u8_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 u8_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._reserved) {
|
|
memcpy(srv->transition.timer.work._reserved, 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 u8_t *)&change, sizeof(change));
|
|
return;
|
|
}
|
|
|
|
bt_mesh_server_start_transition(&srv->transition);
|
|
return;
|
|
}
|
|
|
|
/* 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;
|
|
u8_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, Failed to allocate 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));
|
|
}
|
|
return;
|
|
}
|
|
|
|
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);
|
|
return;
|
|
}
|
|
|
|
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;
|
|
u8_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("%s, Invalid Transaction Number of Steps 0x3F", __func__);
|
|
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 u8_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 u8_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);
|
|
|
|
return;
|
|
}
|
|
|
|
/* 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;
|
|
u8_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, Failed to allocate 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("%s, Invalid Generic Power OnOff Server 0x%04x", __func__, 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));
|
|
}
|
|
return;
|
|
}
|
|
|
|
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);
|
|
return;
|
|
}
|
|
|
|
/* 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("%s, Invalid Generic Power OnOff Server state", __func__);
|
|
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("%s, Invalid Generic Power OnOff Setup Server state", __func__);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
BT_ERR("%s, Invalid Generic Power OnOff Server 0x%04x", __func__, model->id);
|
|
return;
|
|
}
|
|
|
|
send_gen_onpowerup_status(model, NULL, true);
|
|
return;
|
|
}
|
|
|
|
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;
|
|
u8_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("%s, Invalid OnPowerUp value 0x%02x", __func__, 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 u8_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 u8_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);
|
|
|
|
return;
|
|
}
|
|
|
|
/* 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, u16_t opcode)
|
|
{
|
|
struct net_buf_simple *msg = NULL;
|
|
u8_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, Failed to allocate 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("%s, Unknown Generic Power status opcode 0x%04x", __func__, 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));
|
|
}
|
|
return;
|
|
}
|
|
|
|
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;
|
|
u16_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("%s, Unknown Generic Power Get opcode 0x%04x", __func__, ctx->recv_op);
|
|
return;
|
|
}
|
|
|
|
send_gen_power_level_status(model, ctx, false, opcode);
|
|
return;
|
|
}
|
|
|
|
void gen_power_level_publish(struct bt_mesh_model *model, u16_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("%s, Invalid Generic Power Level Server state", __func__);
|
|
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("%s, Invalid Generic Power Level Setup Server state", __func__);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
BT_ERR("%s, Invalid Generic Power Level Server 0x%04x", __func__, model->id);
|
|
return;
|
|
}
|
|
|
|
send_gen_power_level_status(model, NULL, true, opcode);
|
|
return;
|
|
}
|
|
|
|
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;
|
|
u8_t tid = 0U, trans_time = 0U, delay = 0U;
|
|
bool optional = false;
|
|
u16_t power = 0U;
|
|
s64_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 u8_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 u8_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._reserved) {
|
|
memcpy(srv->transition.timer.work._reserved, 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);
|
|
return;
|
|
}
|
|
|
|
/* 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;
|
|
u16_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 recived value */
|
|
};
|
|
bt_mesh_generic_server_cb_evt_to_btc(
|
|
BTC_BLE_MESH_EVT_GENERIC_SERVER_RECV_SET_MSG, model, ctx, (const u8_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 u8_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);
|
|
|
|
return;
|
|
}
|
|
|
|
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;
|
|
u16_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("%s, Range Min 0x%04x is greater than Range Max 0x%04x",
|
|
__func__, 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 u8_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 u8_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);
|
|
|
|
return;
|
|
}
|
|
|
|
/* 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));
|
|
return;
|
|
}
|
|
|
|
/* Generic Location Server message handlers */
|
|
static void send_gen_location_status(struct bt_mesh_model *model,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
bool publish, u16_t opcode)
|
|
{
|
|
struct net_buf_simple *msg = NULL;
|
|
u8_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, Failed to allocate 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("%s, Unknown Generic Location status opcode 0x%04x", __func__, 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));
|
|
}
|
|
return;
|
|
}
|
|
|
|
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;
|
|
u16_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("%s, Unknown Generic Location Get opcode 0x%04x", __func__, ctx->recv_op);
|
|
return;
|
|
}
|
|
|
|
send_gen_location_status(model, ctx, false, opcode);
|
|
return;
|
|
}
|
|
|
|
/* 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;
|
|
u16_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;
|
|
s32_t latitude = net_buf_simple_pull_le32(buf);
|
|
s32_t longitude = net_buf_simple_pull_le32(buf);
|
|
s16_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 u8_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 u8_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;
|
|
u16_t north = net_buf_simple_pull_le16(buf);
|
|
u16_t east = net_buf_simple_pull_le16(buf);
|
|
u16_t altitude = net_buf_simple_pull_le16(buf);
|
|
u8_t floor = net_buf_simple_pull_u8(buf);
|
|
u16_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 u8_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 u8_t *)&change, sizeof(change));
|
|
break;
|
|
}
|
|
default:
|
|
BT_WARN("%s, Unknown Generic Location Set opcode 0x%04x", __func__, 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);
|
|
|
|
return;
|
|
}
|
|
|
|
/* Generic User Property Server message handlers */
|
|
struct bt_mesh_generic_property *gen_get_user_property(struct bt_mesh_model *model,
|
|
u16_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,
|
|
u16_t property_id, bool publish)
|
|
{
|
|
struct bt_mesh_generic_property *property = NULL;
|
|
struct net_buf_simple *msg = NULL;
|
|
u16_t length = 0U;
|
|
|
|
if (property_id == BLE_MESH_INVALID_DEVICE_PROPERTY_ID) {
|
|
BT_ERR("%s, Invalid User Property ID 0x%04x", __func__, property_id);
|
|
return;
|
|
}
|
|
|
|
property = gen_get_user_property(model, property_id);
|
|
if (property == NULL) {
|
|
BT_WARN("%s, User property 0x%04x not exist", __func__, 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, Failed to allocate 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));
|
|
}
|
|
return;
|
|
}
|
|
|
|
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 __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 u8_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 u8_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;
|
|
u8_t i;
|
|
msg = bt_mesh_alloc_buf(1 + srv->property_count * 2 + BLE_MESH_SERVER_TRANS_MIC_SIZE);
|
|
if (msg == NULL) {
|
|
BT_ERR("%s, Failed to allocate 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: {
|
|
u16_t property_id = net_buf_simple_pull_le16(buf);
|
|
send_gen_user_prop_status(model, ctx, property_id, false);
|
|
return;
|
|
}
|
|
default:
|
|
BT_WARN("%s, Unknown Generic User Property Get opcode 0x%04x", __func__, 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;
|
|
u16_t property_id = 0U;
|
|
u8_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 u8_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("%s, Invalid User Property length, ID 0x%04x, expect %d, actual %d",
|
|
__func__, 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 u8_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);
|
|
|
|
return;
|
|
}
|
|
|
|
/* Generic Admin Property Server message handlers */
|
|
struct bt_mesh_generic_property *gen_get_admin_property(struct bt_mesh_model *model,
|
|
u16_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,
|
|
u16_t property_id, bool publish)
|
|
{
|
|
struct bt_mesh_generic_property *property = NULL;
|
|
struct net_buf_simple *msg = NULL;
|
|
u16_t length = 0U;
|
|
|
|
if (property_id == BLE_MESH_INVALID_DEVICE_PROPERTY_ID) {
|
|
BT_ERR("%s, Invalid User Property ID 0x%04x", __func__, property_id);
|
|
return;
|
|
}
|
|
|
|
property = gen_get_admin_property(model, property_id);
|
|
if (property == NULL) {
|
|
BT_WARN("%s, Admin property 0x%04x not exist", __func__, 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, Failed to allocate 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));
|
|
}
|
|
return;
|
|
}
|
|
|
|
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 u8_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 u8_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;
|
|
u8_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, Failed to allocate 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: {
|
|
u16_t property_id = net_buf_simple_pull_le16(buf);
|
|
send_gen_admin_prop_status(model, ctx, property_id, false);
|
|
return;
|
|
}
|
|
default:
|
|
BT_WARN("%s, Unknown Generic Admin Property Get opcode 0x%04x", __func__, 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;
|
|
u16_t property_id = 0U;
|
|
u8_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("%s, Invalid Admin Access 0x%02x", __func__, 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 u8_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 u8_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);
|
|
|
|
return;
|
|
}
|
|
|
|
/* Generic Manufacturer Property Server message handlers */
|
|
struct bt_mesh_generic_property *gen_get_manu_property(struct bt_mesh_model *model,
|
|
u16_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,
|
|
u16_t property_id, bool publish)
|
|
{
|
|
struct bt_mesh_generic_property *property = NULL;
|
|
struct net_buf_simple *msg = NULL;
|
|
u16_t length = 0U;
|
|
|
|
if (property_id == BLE_MESH_INVALID_DEVICE_PROPERTY_ID) {
|
|
BT_ERR("%s, Invalid User Property ID 0x%04x", __func__, property_id);
|
|
return;
|
|
}
|
|
|
|
property = gen_get_manu_property(model, property_id);
|
|
if (property == NULL) {
|
|
BT_WARN("%s, Manufacturer property 0x%04x not exist", __func__, 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, Failed to allocate 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));
|
|
}
|
|
return;
|
|
}
|
|
|
|
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 u8_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 u8_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;
|
|
u8_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, Failed to allocate 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: {
|
|
u16_t property_id = net_buf_simple_pull_le16(buf);
|
|
send_gen_manu_prop_status(model, ctx, property_id, false);
|
|
return;
|
|
}
|
|
default:
|
|
BT_WARN("%s, Unknown Generic Manufacturer Property Get opcode 0x%04x", __func__, 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;
|
|
u16_t property_id = 0U;
|
|
u8_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("%s, Invalid Manufacturer Access 0x%02x", __func__, 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 u8_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 u8_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);
|
|
|
|
return;
|
|
}
|
|
|
|
/* Generic Client Property Server message handlers */
|
|
static int search_prop_id_index(const u16_t *array, u8_t array_idx, u16_t id)
|
|
{
|
|
static const u16_t *start = NULL;
|
|
u8_t index = 0U;
|
|
u16_t temp = 0U;
|
|
|
|
if (start == NULL) {
|
|
start = array;
|
|
}
|
|
|
|
if (array_idx == 0U) {
|
|
if (*array >= id) {
|
|
return array - start;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
index = array_idx / 2;
|
|
temp = array[index];
|
|
|
|
if (temp == id) {
|
|
return array + index - start;
|
|
} else if (temp > id) {
|
|
return search_prop_id_index(array, index, id);
|
|
} else {
|
|
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;
|
|
u16_t total_len = 5U;
|
|
u16_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 u8_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 Properities 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, Failed to allocate 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(u16_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 */
|
|
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);
|
|
return;
|
|
}
|
|
|
|
/* message handlers (End) */
|
|
|
|
/* Mapping of message handlers for Generic OnOff Server (0x1000) */
|
|
const struct bt_mesh_model_op 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 Levl Server (0x1002) */
|
|
const struct bt_mesh_model_op 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 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 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 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 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 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 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 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 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 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 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 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 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 (*(u16_t *)p1 < * (u16_t *)p2) {
|
|
return -1;
|
|
}
|
|
if (*(u16_t *)p1 > *(u16_t *)p2) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int generic_server_init(struct bt_mesh_model *model)
|
|
{
|
|
if (model->user_data == NULL) {
|
|
BT_ERR("%s, No Generic Server context provided, model_id 0x%04x", __func__, 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("%s, NULL Generic OnPowerUp State", __func__);
|
|
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("%s, NULL Generic OnPowerUp State", __func__);
|
|
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("%s, NULL Generic Power Level State", __func__);
|
|
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("%s, NULL Generic Power Level State", __func__);
|
|
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("%s, NULL Generic Location State", __func__);
|
|
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("%s, NULL Generic Location State", __func__);
|
|
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("%s, NULL Generic User Property State", __func__);
|
|
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("%s, NULL Generic Admin Property State", __func__);
|
|
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("%s, NULL Generic Manufacturer Property State", __func__);
|
|
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("%s, NULL Generic Client Property State", __func__);
|
|
return -EINVAL;
|
|
}
|
|
/* Quick sort the Client Property IDs in ascending order */
|
|
qsort(srv->property_ids, srv->id_count, sizeof(u16_t), property_id_compare);
|
|
srv->model = model;
|
|
break;
|
|
}
|
|
default:
|
|
BT_WARN("%s, Unknown Generic Server Model, model_id 0x%04x", __func__, model->id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
bt_mesh_generic_server_mutex_new();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int bt_mesh_gen_onoff_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic OnOff Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_gen_level_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Level Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_gen_def_trans_time_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Default Trans Time Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_gen_power_onoff_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Power OnOff Server has no publication support", __func__);
|
|
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("%s, Generic Power OnOff Setup Server is not present", __func__);
|
|
/* Just give a warning here, continue with the initialization */
|
|
}
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_gen_power_onoff_setup_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_gen_power_level_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Power Level Server has no publication support", __func__);
|
|
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("%s, Generic Power Level Setup Server is not present", __func__);
|
|
/* Just give a warning here, continue with the initialization */
|
|
}
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_gen_power_level_setup_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_gen_battery_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Battery Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_gen_location_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Location Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_gen_location_setup_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
/* 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("%s, Generic Location Setup Server is not present", __func__);
|
|
/* Just give a warning here, continue with the initialization */
|
|
}
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_gen_user_prop_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic User Property has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_gen_admin_prop_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Admin Property has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_gen_manu_prop_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Manufacturer Property has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
int bt_mesh_gen_client_prop_srv_init(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Client Property has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_init(model);
|
|
}
|
|
|
|
static int generic_server_deinit(struct bt_mesh_model *model)
|
|
{
|
|
if (model->user_data == NULL) {
|
|
BT_ERR("%s, No Generic Server context provided, model_id 0x%04x", __func__, 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("%s, NULL Generic Power Level State", __func__);
|
|
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;
|
|
}
|
|
default:
|
|
BT_WARN("%s, Unknown Generic Server Model, model_id 0x%04x", __func__, model->id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
bt_mesh_generic_server_mutex_free();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int bt_mesh_gen_onoff_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic OnOff Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_gen_level_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Level Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_gen_def_trans_time_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Default Trans Time Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_gen_power_onoff_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Power OnOff Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_gen_power_onoff_setup_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
return generic_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_gen_power_level_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Power Level Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_gen_power_level_setup_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
return generic_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_gen_battery_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Battery Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_gen_location_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Location Server has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_gen_location_setup_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
return generic_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_gen_user_prop_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic User Property has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_gen_admin_prop_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Admin Property has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_gen_manu_prop_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Manufacturer Property has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_deinit(model);
|
|
}
|
|
|
|
int bt_mesh_gen_client_prop_srv_deinit(struct bt_mesh_model *model, bool primary)
|
|
{
|
|
if (model->pub == NULL) {
|
|
BT_ERR("%s, Generic Client Property has no publication support", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return generic_server_deinit(model);
|
|
} |