Unacknowledged API is now separate from Ack. Signed-off-by: Michał Narajowski <michal.narajowski@codecoup.pl>
2773 lines
65 KiB
C
2773 lines
65 KiB
C
/*
|
|
* Copyright (c) 2017 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <bluetooth/bluetooth.h>
|
|
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <bluetooth/mesh.h>
|
|
#include <bluetooth/testing.h>
|
|
#include <bluetooth/mesh/cfg.h>
|
|
#include <sys/byteorder.h>
|
|
#include <app_keys.h>
|
|
|
|
#include <logging/log.h>
|
|
#define LOG_MODULE_NAME bttester_mesh
|
|
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
|
|
|
#include "bttester.h"
|
|
|
|
#define CONTROLLER_INDEX 0
|
|
#define CID_LOCAL 0x05F1
|
|
|
|
/* Health server data */
|
|
#define CUR_FAULTS_MAX 4
|
|
#define HEALTH_TEST_ID 0x00
|
|
|
|
static uint8_t cur_faults[CUR_FAULTS_MAX];
|
|
static uint8_t reg_faults[CUR_FAULTS_MAX * 2];
|
|
|
|
/* Provision node data */
|
|
static uint8_t net_key[16];
|
|
static uint16_t net_key_idx;
|
|
static uint8_t flags;
|
|
static uint32_t iv_index;
|
|
static uint16_t addr;
|
|
static uint8_t dev_key[16];
|
|
static uint8_t input_size;
|
|
static uint8_t pub_key[64];
|
|
static uint8_t priv_key[32];
|
|
|
|
/* Configured provisioning data */
|
|
static uint8_t dev_uuid[16];
|
|
static uint8_t static_auth[16];
|
|
|
|
/* Vendor Model data */
|
|
#define VND_MODEL_ID_1 0x1234
|
|
static uint8_t vnd_app_key[16];
|
|
static uint16_t vnd_app_key_idx = 0x000f;
|
|
|
|
/* Model send data */
|
|
#define MODEL_BOUNDS_MAX 2
|
|
|
|
/* Model Authentication Method */
|
|
#define AUTH_METHOD_STATIC 0x01
|
|
#define AUTH_METHOD_OUTPUT 0x02
|
|
#define AUTH_METHOD_INPUT 0x03
|
|
|
|
static struct model_data {
|
|
struct bt_mesh_model *model;
|
|
uint16_t addr;
|
|
uint16_t appkey_idx;
|
|
} model_bound[MODEL_BOUNDS_MAX];
|
|
|
|
static struct {
|
|
uint16_t local;
|
|
uint16_t dst;
|
|
uint16_t net_idx;
|
|
} net = {
|
|
.local = BT_MESH_ADDR_UNASSIGNED,
|
|
.dst = BT_MESH_ADDR_UNASSIGNED,
|
|
};
|
|
|
|
static void supported_commands(uint8_t *data, uint16_t len)
|
|
{
|
|
struct net_buf_simple *buf = NET_BUF_SIMPLE(BTP_DATA_MAX_SIZE);
|
|
|
|
net_buf_simple_init(buf, 0);
|
|
net_buf_simple_add_u8(buf, MESH_READ_SUPPORTED_COMMANDS);
|
|
net_buf_simple_add_u8(buf, MESH_CONFIG_PROVISIONING);
|
|
net_buf_simple_add_u8(buf, MESH_PROVISION_NODE);
|
|
net_buf_simple_add_u8(buf, MESH_INIT);
|
|
net_buf_simple_add_u8(buf, MESH_RESET);
|
|
net_buf_simple_add_u8(buf, MESH_INPUT_NUMBER);
|
|
net_buf_simple_add_u8(buf, MESH_INPUT_STRING);
|
|
net_buf_simple_add_u8(buf, MESH_IVU_TEST_MODE);
|
|
net_buf_simple_add_u8(buf, MESH_IVU_TOGGLE_STATE);
|
|
net_buf_simple_add_u8(buf, MESH_NET_SEND);
|
|
net_buf_simple_add_u8(buf, MESH_HEALTH_GENERATE_FAULTS);
|
|
net_buf_simple_add_u8(buf, MESH_HEALTH_CLEAR_FAULTS);
|
|
net_buf_simple_add_u8(buf, MESH_LPN);
|
|
net_buf_simple_add_u8(buf, MESH_LPN_POLL);
|
|
net_buf_simple_add_u8(buf, MESH_MODEL_SEND);
|
|
#if defined(CONFIG_BT_TESTING)
|
|
net_buf_simple_add_u8(buf, MESH_LPN_SUBSCRIBE);
|
|
net_buf_simple_add_u8(buf, MESH_LPN_UNSUBSCRIBE);
|
|
net_buf_simple_add_u8(buf, MESH_RPL_CLEAR);
|
|
#endif /* CONFIG_BT_TESTING */
|
|
net_buf_simple_add_u8(buf, MESH_PROXY_IDENTITY);
|
|
net_buf_simple_add_u8(buf, MESH_COMP_DATA_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_BEACON_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_BEACON_SET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_DEFAULT_TTL_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_DEFAULT_TTL_SET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_GATT_PROXY_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_GATT_PROXY_SET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_FRIEND_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_FRIEND_SET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_RELAY_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_RELAY_SET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_PUB_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_PUB_SET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_SUB_ADD);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_SUB_DEL);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_NETKEY_ADD);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_NETKEY_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_NETKEY_DEL);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_APPKEY_ADD);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_APPKEY_DEL);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_APPKEY_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_APP_BIND);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_APP_UNBIND);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_APP_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_APP_VND_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_HEARTBEAT_PUB_SET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_HEARTBEAT_PUB_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_HEARTBEAT_SUB_SET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_HEARTBEAT_SUB_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_NET_TRANS_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_NET_TRANS_SET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_SUB_OVW);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_SUB_DEL_ALL);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_SUB_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_SUB_GET_VND);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_SUB_VA_ADD);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_SUB_VA_DEL);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_SUB_VA_OVW);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_NETKEY_UPDATE);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_APPKEY_UPDATE);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_NODE_IDT_SET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_NODE_IDT_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_NODE_RESET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_LPN_TIMEOUT_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_MODEL_APP_BIND_VND);
|
|
net_buf_simple_add_u8(buf, MESH_HEALTH_FAULT_GET);
|
|
net_buf_simple_add_u8(buf, MESH_HEALTH_FAULT_CLEAR);
|
|
net_buf_simple_add_u8(buf, MESH_HEALTH_PERIOD_GET);
|
|
net_buf_simple_add_u8(buf, MESH_HEALTH_PERIOD_SET);
|
|
net_buf_simple_add_u8(buf, MESH_HEALTH_ATTENTION_GET);
|
|
net_buf_simple_add_u8(buf, MESH_HEALTH_ATTENTION_SET);
|
|
net_buf_simple_add_u8(buf, MESH_PROVISION_ADV);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_KRP_GET);
|
|
net_buf_simple_add_u8(buf, MESH_CFG_KRP_SET);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_READ_SUPPORTED_COMMANDS,
|
|
CONTROLLER_INDEX, buf->data, buf->len);
|
|
}
|
|
|
|
static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8_t *count)
|
|
{
|
|
uint8_t i, limit = *count;
|
|
|
|
for (i = 0U, *count = 0U; i < faults_size && *count < limit; i++) {
|
|
if (faults[i]) {
|
|
*dst++ = faults[i];
|
|
(*count)++;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id,
|
|
uint16_t *company_id, uint8_t *faults, uint8_t *fault_count)
|
|
{
|
|
LOG_DBG("");
|
|
|
|
*test_id = HEALTH_TEST_ID;
|
|
*company_id = CID_LOCAL;
|
|
|
|
get_faults(cur_faults, sizeof(cur_faults), faults, fault_count);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int fault_get_reg(struct bt_mesh_model *model, uint16_t company_id,
|
|
uint8_t *test_id, uint8_t *faults, uint8_t *fault_count)
|
|
{
|
|
LOG_DBG("company_id 0x%04x", company_id);
|
|
|
|
if (company_id != CID_LOCAL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
*test_id = HEALTH_TEST_ID;
|
|
|
|
get_faults(reg_faults, sizeof(reg_faults), faults, fault_count);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int fault_clear(struct bt_mesh_model *model, uint16_t company_id)
|
|
{
|
|
LOG_DBG("company_id 0x%04x", company_id);
|
|
|
|
if (company_id != CID_LOCAL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
(void)memset(reg_faults, 0, sizeof(reg_faults));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int fault_test(struct bt_mesh_model *model, uint8_t test_id,
|
|
uint16_t company_id)
|
|
{
|
|
LOG_DBG("test_id 0x%02x company_id 0x%04x", test_id, company_id);
|
|
|
|
if (company_id != CID_LOCAL || test_id != HEALTH_TEST_ID) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct bt_mesh_health_srv_cb health_srv_cb = {
|
|
.fault_get_cur = fault_get_cur,
|
|
.fault_get_reg = fault_get_reg,
|
|
.fault_clear = fault_clear,
|
|
.fault_test = fault_test,
|
|
};
|
|
|
|
static struct bt_mesh_health_srv health_srv = {
|
|
.cb = &health_srv_cb,
|
|
};
|
|
|
|
BT_MESH_HEALTH_PUB_DEFINE(health_pub, CUR_FAULTS_MAX);
|
|
|
|
static struct bt_mesh_cfg_cli cfg_cli = {
|
|
};
|
|
|
|
static void show_faults(uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count)
|
|
{
|
|
size_t i;
|
|
|
|
if (!fault_count) {
|
|
LOG_DBG("Health Test ID 0x%02x Company ID 0x%04x: no faults",
|
|
test_id, cid);
|
|
return;
|
|
}
|
|
|
|
LOG_DBG("Health Test ID 0x%02x Company ID 0x%04x Fault Count %zu: ",
|
|
test_id, cid, fault_count);
|
|
|
|
for (i = 0; i < fault_count; i++) {
|
|
LOG_DBG("0x%02x", faults[i]);
|
|
}
|
|
}
|
|
|
|
static void health_current_status(struct bt_mesh_health_cli *cli, uint16_t addr,
|
|
uint8_t test_id, uint16_t cid, uint8_t *faults,
|
|
size_t fault_count)
|
|
{
|
|
LOG_DBG("Health Current Status from 0x%04x", addr);
|
|
show_faults(test_id, cid, faults, fault_count);
|
|
}
|
|
|
|
static struct bt_mesh_health_cli health_cli = {
|
|
.current_status = health_current_status,
|
|
};
|
|
|
|
static struct bt_mesh_model root_models[] = {
|
|
BT_MESH_MODEL_CFG_SRV,
|
|
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
|
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
|
|
BT_MESH_MODEL_HEALTH_CLI(&health_cli),
|
|
};
|
|
|
|
static struct bt_mesh_model vnd_models[] = {
|
|
BT_MESH_MODEL_VND(CID_LOCAL, VND_MODEL_ID_1, BT_MESH_MODEL_NO_OPS, NULL,
|
|
NULL),
|
|
};
|
|
|
|
static struct bt_mesh_elem elements[] = {
|
|
BT_MESH_ELEM(0, root_models, vnd_models),
|
|
};
|
|
|
|
static void link_open(bt_mesh_prov_bearer_t bearer)
|
|
{
|
|
struct mesh_prov_link_open_ev ev;
|
|
|
|
LOG_DBG("bearer 0x%02x", bearer);
|
|
|
|
switch (bearer) {
|
|
case BT_MESH_PROV_ADV:
|
|
ev.bearer = MESH_PROV_BEARER_PB_ADV;
|
|
break;
|
|
case BT_MESH_PROV_GATT:
|
|
ev.bearer = MESH_PROV_BEARER_PB_GATT;
|
|
break;
|
|
default:
|
|
LOG_ERR("Invalid bearer");
|
|
|
|
return;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_PROV_LINK_OPEN,
|
|
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
|
|
}
|
|
|
|
static void link_close(bt_mesh_prov_bearer_t bearer)
|
|
{
|
|
struct mesh_prov_link_closed_ev ev;
|
|
|
|
LOG_DBG("bearer 0x%02x", bearer);
|
|
|
|
switch (bearer) {
|
|
case BT_MESH_PROV_ADV:
|
|
ev.bearer = MESH_PROV_BEARER_PB_ADV;
|
|
break;
|
|
case BT_MESH_PROV_GATT:
|
|
ev.bearer = MESH_PROV_BEARER_PB_GATT;
|
|
break;
|
|
default:
|
|
LOG_ERR("Invalid bearer");
|
|
|
|
return;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_PROV_LINK_CLOSED,
|
|
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
|
|
}
|
|
|
|
static int output_number(bt_mesh_output_action_t action, uint32_t number)
|
|
{
|
|
struct mesh_out_number_action_ev ev;
|
|
|
|
LOG_DBG("action 0x%04x number 0x%08x", action, number);
|
|
|
|
ev.action = sys_cpu_to_le16(action);
|
|
ev.number = sys_cpu_to_le32(number);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_OUT_NUMBER_ACTION,
|
|
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int output_string(const char *str)
|
|
{
|
|
struct mesh_out_string_action_ev *ev;
|
|
struct net_buf_simple *buf = NET_BUF_SIMPLE(BTP_DATA_MAX_SIZE);
|
|
|
|
LOG_DBG("str %s", log_strdup(str));
|
|
|
|
net_buf_simple_init(buf, 0);
|
|
|
|
ev = net_buf_simple_add(buf, sizeof(*ev));
|
|
ev->string_len = strlen(str);
|
|
|
|
net_buf_simple_add_mem(buf, str, ev->string_len);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_OUT_STRING_ACTION,
|
|
CONTROLLER_INDEX, buf->data, buf->len);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int input(bt_mesh_input_action_t action, uint8_t size)
|
|
{
|
|
struct mesh_in_action_ev ev;
|
|
|
|
LOG_DBG("action 0x%04x number 0x%02x", action, size);
|
|
|
|
input_size = size;
|
|
|
|
ev.action = sys_cpu_to_le16(action);
|
|
ev.size = size;
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_IN_ACTION, CONTROLLER_INDEX,
|
|
(uint8_t *) &ev, sizeof(ev));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void prov_complete(uint16_t net_idx, uint16_t addr)
|
|
{
|
|
LOG_DBG("net_idx 0x%04x addr 0x%04x", net_idx, addr);
|
|
|
|
net.net_idx = net_idx,
|
|
net.local = addr;
|
|
net.dst = addr;
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_PROVISIONED, CONTROLLER_INDEX,
|
|
NULL, 0);
|
|
}
|
|
|
|
static void prov_node_added(uint16_t net_idx, uint8_t uuid[16], uint16_t addr,
|
|
uint8_t num_elem)
|
|
{
|
|
struct mesh_prov_node_added_ev ev;
|
|
|
|
LOG_DBG("net_idx 0x%04x addr 0x%04x num_elem %d", net_idx, addr,
|
|
num_elem);
|
|
|
|
ev.net_idx = net_idx;
|
|
ev.addr = addr;
|
|
ev.num_elems = num_elem;
|
|
memcpy(&ev.uuid, uuid, sizeof(ev.uuid));
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_PROV_NODE_ADDED,
|
|
CONTROLLER_INDEX, (void *)&ev, sizeof(ev));
|
|
}
|
|
|
|
static void prov_reset(void)
|
|
{
|
|
LOG_DBG("");
|
|
|
|
bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
|
|
}
|
|
|
|
static const struct bt_mesh_comp comp = {
|
|
.cid = CID_LOCAL,
|
|
.elem = elements,
|
|
.elem_count = ARRAY_SIZE(elements),
|
|
};
|
|
|
|
static struct bt_mesh_prov prov = {
|
|
.uuid = dev_uuid,
|
|
.static_val = static_auth,
|
|
.static_val_len = sizeof(static_auth),
|
|
.output_number = output_number,
|
|
.output_string = output_string,
|
|
.input = input,
|
|
.link_open = link_open,
|
|
.link_close = link_close,
|
|
.complete = prov_complete,
|
|
.node_added = prov_node_added,
|
|
.reset = prov_reset,
|
|
};
|
|
|
|
static void config_prov(uint8_t *data, uint16_t len)
|
|
{
|
|
const struct mesh_config_provisioning_cmd *cmd = (void *) data;
|
|
int err = 0;
|
|
|
|
LOG_DBG("");
|
|
|
|
memcpy(dev_uuid, cmd->uuid, sizeof(dev_uuid));
|
|
memcpy(static_auth, cmd->static_auth, sizeof(static_auth));
|
|
|
|
prov.output_size = cmd->out_size;
|
|
prov.output_actions = sys_le16_to_cpu(cmd->out_actions);
|
|
prov.input_size = cmd->in_size;
|
|
prov.input_actions = sys_le16_to_cpu(cmd->in_actions);
|
|
|
|
if (cmd->auth_method == AUTH_METHOD_OUTPUT) {
|
|
err = bt_mesh_auth_method_set_output(prov.output_actions, prov.output_size);
|
|
} else if (cmd->auth_method == AUTH_METHOD_INPUT) {
|
|
err = bt_mesh_auth_method_set_input(prov.input_actions, prov.input_size);
|
|
} else if (cmd->auth_method == AUTH_METHOD_STATIC) {
|
|
err = bt_mesh_auth_method_set_static(static_auth, sizeof(static_auth));
|
|
}
|
|
|
|
if (len > sizeof(*cmd)) {
|
|
memcpy(pub_key, cmd->set_keys->pub_key, sizeof(cmd->set_keys->pub_key));
|
|
memcpy(priv_key, cmd->set_keys->priv_key, sizeof(cmd->set_keys->priv_key));
|
|
prov.public_key_be = pub_key;
|
|
prov.private_key_be = priv_key;
|
|
}
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
}
|
|
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CONFIG_PROVISIONING, CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void provision_node(uint8_t *data, uint16_t len)
|
|
{
|
|
const struct mesh_provision_node_cmd *cmd = (void *)data;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
memcpy(dev_key, cmd->dev_key, sizeof(dev_key));
|
|
memcpy(net_key, cmd->net_key, sizeof(net_key));
|
|
|
|
addr = sys_le16_to_cpu(cmd->addr);
|
|
flags = cmd->flags;
|
|
iv_index = sys_le32_to_cpu(cmd->iv_index);
|
|
net_key_idx = sys_le16_to_cpu(cmd->net_key_idx);
|
|
|
|
if (len > sizeof(*cmd)) {
|
|
memcpy(pub_key, cmd->pub_key, sizeof(pub_key));
|
|
|
|
err = bt_mesh_prov_remote_pub_key_set(pub_key);
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
}
|
|
#if defined(CONFIG_BT_MESH_PROVISIONER)
|
|
err = bt_mesh_cdb_create(net_key);
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
#endif
|
|
err = bt_mesh_provision(net_key, net_key_idx, flags, iv_index, addr,
|
|
dev_key);
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_PROVISION_NODE, CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void provision_adv(uint8_t *data, uint16_t len)
|
|
{
|
|
const struct mesh_provision_adv_cmd *cmd = (void *)data;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_provision_adv(cmd->uuid, cmd->net_idx, cmd->address,
|
|
cmd->attention_duration);
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_PROVISION_ADV, CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void init(uint8_t *data, uint16_t len)
|
|
{
|
|
uint8_t status = BTP_STATUS_SUCCESS;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_init(&prov, &comp);
|
|
if (err) {
|
|
status = BTP_STATUS_FAILED;
|
|
|
|
goto rsp;
|
|
}
|
|
|
|
if (addr) {
|
|
err = bt_mesh_provision(net_key, net_key_idx, flags, iv_index,
|
|
addr, dev_key);
|
|
if (err) {
|
|
status = BTP_STATUS_FAILED;
|
|
}
|
|
} else {
|
|
err = bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
|
|
if (err) {
|
|
status = BTP_STATUS_FAILED;
|
|
}
|
|
}
|
|
|
|
rsp:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_INIT, CONTROLLER_INDEX,
|
|
status);
|
|
}
|
|
|
|
static void reset(uint8_t *data, uint16_t len)
|
|
{
|
|
LOG_DBG("");
|
|
|
|
bt_mesh_reset();
|
|
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_RESET, CONTROLLER_INDEX,
|
|
BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void input_number(uint8_t *data, uint16_t len)
|
|
{
|
|
const struct mesh_input_number_cmd *cmd = (void *) data;
|
|
uint8_t status = BTP_STATUS_SUCCESS;
|
|
uint32_t number;
|
|
int err;
|
|
|
|
number = sys_le32_to_cpu(cmd->number);
|
|
|
|
LOG_DBG("number 0x%04x", number);
|
|
|
|
err = bt_mesh_input_number(number);
|
|
if (err) {
|
|
status = BTP_STATUS_FAILED;
|
|
}
|
|
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_INPUT_NUMBER, CONTROLLER_INDEX,
|
|
status);
|
|
}
|
|
|
|
static void input_string(uint8_t *data, uint16_t len)
|
|
{
|
|
const struct mesh_input_string_cmd *cmd = (void *) data;
|
|
uint8_t status = BTP_STATUS_SUCCESS;
|
|
uint8_t str_auth[16];
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
if (cmd->string_len > sizeof(str_auth)) {
|
|
LOG_ERR("Too long input (%u chars required)", input_size);
|
|
status = BTP_STATUS_FAILED;
|
|
goto rsp;
|
|
} else if (cmd->string_len < input_size) {
|
|
LOG_ERR("Too short input (%u chars required)", input_size);
|
|
status = BTP_STATUS_FAILED;
|
|
goto rsp;
|
|
}
|
|
|
|
strncpy(str_auth, cmd->string, cmd->string_len);
|
|
|
|
err = bt_mesh_input_string(str_auth);
|
|
if (err) {
|
|
status = BTP_STATUS_FAILED;
|
|
}
|
|
|
|
rsp:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_INPUT_STRING, CONTROLLER_INDEX,
|
|
status);
|
|
}
|
|
|
|
static void ivu_test_mode(uint8_t *data, uint16_t len)
|
|
{
|
|
const struct mesh_ivu_test_mode_cmd *cmd = (void *) data;
|
|
|
|
LOG_DBG("enable 0x%02x", cmd->enable);
|
|
|
|
bt_mesh_iv_update_test(cmd->enable ? true : false);
|
|
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_IVU_TEST_MODE, CONTROLLER_INDEX,
|
|
BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void ivu_toggle_state(uint8_t *data, uint16_t len)
|
|
{
|
|
bool result;
|
|
|
|
LOG_DBG("");
|
|
|
|
result = bt_mesh_iv_update();
|
|
if (!result) {
|
|
LOG_ERR("Failed to toggle the IV Update state");
|
|
}
|
|
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_IVU_TOGGLE_STATE, CONTROLLER_INDEX,
|
|
result ? BTP_STATUS_SUCCESS : BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void lpn(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_lpn_set_cmd *cmd = (void *) data;
|
|
bool enable;
|
|
int err;
|
|
|
|
LOG_DBG("enable 0x%02x", cmd->enable);
|
|
|
|
enable = cmd->enable ? true : false;
|
|
err = bt_mesh_lpn_set(enable);
|
|
if (err) {
|
|
LOG_ERR("Failed to toggle LPN (err %d)", err);
|
|
}
|
|
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_LPN, CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void lpn_poll(uint8_t *data, uint16_t len)
|
|
{
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_lpn_poll();
|
|
if (err) {
|
|
LOG_ERR("Failed to send poll msg (err %d)", err);
|
|
}
|
|
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_LPN_POLL, CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void net_send(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_net_send_cmd *cmd = (void *) data;
|
|
NET_BUF_SIMPLE_DEFINE(msg, UINT8_MAX);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net.net_idx,
|
|
.app_idx = vnd_app_key_idx,
|
|
.addr = sys_le16_to_cpu(cmd->dst),
|
|
.send_ttl = cmd->ttl,
|
|
};
|
|
int err;
|
|
|
|
LOG_DBG("ttl 0x%02x dst 0x%04x payload_len %d", ctx.send_ttl,
|
|
ctx.addr, cmd->payload_len);
|
|
|
|
if (!bt_mesh_app_key_exists(vnd_app_key_idx)) {
|
|
(void)bt_mesh_app_key_add(vnd_app_key_idx, net.net_idx,
|
|
vnd_app_key);
|
|
vnd_models[0].keys[0] = vnd_app_key_idx;
|
|
}
|
|
|
|
net_buf_simple_add_mem(&msg, cmd->payload, cmd->payload_len);
|
|
|
|
err = bt_mesh_model_send(&vnd_models[0], &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
LOG_ERR("Failed to send (err %d)", err);
|
|
}
|
|
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_NET_SEND, CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void health_generate_faults(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_health_generate_faults_rp *rp;
|
|
NET_BUF_SIMPLE_DEFINE(buf, sizeof(*rp) + sizeof(cur_faults) +
|
|
sizeof(reg_faults));
|
|
uint8_t some_faults[] = { 0x01, 0x02, 0x03, 0xff, 0x06 };
|
|
uint8_t cur_faults_count, reg_faults_count;
|
|
|
|
rp = net_buf_simple_add(&buf, sizeof(*rp));
|
|
|
|
cur_faults_count = MIN(sizeof(cur_faults), sizeof(some_faults));
|
|
memcpy(cur_faults, some_faults, cur_faults_count);
|
|
net_buf_simple_add_mem(&buf, cur_faults, cur_faults_count);
|
|
rp->cur_faults_count = cur_faults_count;
|
|
|
|
reg_faults_count = MIN(sizeof(reg_faults), sizeof(some_faults));
|
|
memcpy(reg_faults, some_faults, reg_faults_count);
|
|
net_buf_simple_add_mem(&buf, reg_faults, reg_faults_count);
|
|
rp->reg_faults_count = reg_faults_count;
|
|
|
|
bt_mesh_fault_update(&elements[0]);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_HEALTH_GENERATE_FAULTS,
|
|
CONTROLLER_INDEX, buf.data, buf.len);
|
|
}
|
|
|
|
static void health_clear_faults(uint8_t *data, uint16_t len)
|
|
{
|
|
LOG_DBG("");
|
|
|
|
(void)memset(cur_faults, 0, sizeof(cur_faults));
|
|
(void)memset(reg_faults, 0, sizeof(reg_faults));
|
|
|
|
bt_mesh_fault_update(&elements[0]);
|
|
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_HEALTH_CLEAR_FAULTS,
|
|
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void model_send(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_model_send_cmd *cmd = (void *) data;
|
|
NET_BUF_SIMPLE_DEFINE(msg, UINT8_MAX);
|
|
struct bt_mesh_msg_ctx ctx = {
|
|
.net_idx = net.net_idx,
|
|
.app_idx = BT_MESH_KEY_DEV,
|
|
.addr = sys_le16_to_cpu(cmd->dst),
|
|
.send_ttl = BT_MESH_TTL_DEFAULT,
|
|
};
|
|
struct bt_mesh_model *model = NULL;
|
|
int err, i;
|
|
uint16_t src = sys_le16_to_cpu(cmd->src);
|
|
|
|
/* Lookup source address */
|
|
for (i = 0; i < ARRAY_SIZE(model_bound); i++) {
|
|
if (bt_mesh_model_elem(model_bound[i].model)->addr == src) {
|
|
model = model_bound[i].model;
|
|
ctx.app_idx = model_bound[i].appkey_idx;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!model) {
|
|
LOG_ERR("Model not found");
|
|
err = -EINVAL;
|
|
|
|
goto fail;
|
|
}
|
|
|
|
LOG_DBG("src 0x%04x dst 0x%04x model %p payload_len %d", src,
|
|
ctx.addr, model, cmd->payload_len);
|
|
|
|
net_buf_simple_add_mem(&msg, cmd->payload, cmd->payload_len);
|
|
|
|
err = bt_mesh_model_send(model, &ctx, &msg, NULL, NULL);
|
|
if (err) {
|
|
LOG_ERR("Failed to send (err %d)", err);
|
|
}
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_MODEL_SEND, CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
#if defined(CONFIG_BT_TESTING)
|
|
static void lpn_subscribe(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_lpn_subscribe_cmd *cmd = (void *) data;
|
|
uint16_t address = sys_le16_to_cpu(cmd->address);
|
|
int err;
|
|
|
|
LOG_DBG("address 0x%04x", address);
|
|
|
|
err = bt_test_mesh_lpn_group_add(address);
|
|
if (err) {
|
|
LOG_ERR("Failed to subscribe (err %d)", err);
|
|
}
|
|
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_LPN_SUBSCRIBE, CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void lpn_unsubscribe(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_lpn_unsubscribe_cmd *cmd = (void *) data;
|
|
uint16_t address = sys_le16_to_cpu(cmd->address);
|
|
int err;
|
|
|
|
LOG_DBG("address 0x%04x", address);
|
|
|
|
err = bt_test_mesh_lpn_group_remove(&address, 1);
|
|
if (err) {
|
|
LOG_ERR("Failed to unsubscribe (err %d)", err);
|
|
}
|
|
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_LPN_UNSUBSCRIBE, CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void rpl_clear(uint8_t *data, uint16_t len)
|
|
{
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_test_mesh_rpl_clear();
|
|
if (err) {
|
|
LOG_ERR("Failed to clear RPL (err %d)", err);
|
|
}
|
|
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_RPL_CLEAR, CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
#endif /* CONFIG_BT_TESTING */
|
|
|
|
static void proxy_identity_enable(uint8_t *data, uint16_t len)
|
|
{
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_proxy_identity_enable();
|
|
if (err) {
|
|
LOG_ERR("Failed to enable proxy identity (err %d)", err);
|
|
}
|
|
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_PROXY_IDENTITY, CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void composition_data_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_comp_data_get_cmd *cmd = (void *)data;
|
|
uint8_t page;
|
|
struct net_buf_simple *comp = NET_BUF_SIMPLE(128);
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
bt_mesh_cfg_cli_timeout_set(10 * MSEC_PER_SEC);
|
|
|
|
net_buf_simple_init(comp, 0);
|
|
|
|
err = bt_mesh_cfg_comp_data_get(cmd->net_idx, cmd->address, cmd->page,
|
|
&page, comp);
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_COMP_DATA_GET, CONTROLLER_INDEX,
|
|
comp->data, comp->len);
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_COMP_DATA_GET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_krp_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_krp_get_cmd *cmd = (void *)data;
|
|
struct net_buf_simple *buf = NET_BUF_SIMPLE(2);
|
|
uint8_t status;
|
|
uint8_t phase;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_krp_get(cmd->net_idx, cmd->address, cmd->key_net_idx, &status, &phase);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
net_buf_simple_init(buf, 0);
|
|
net_buf_simple_add_u8(buf, status);
|
|
net_buf_simple_add_u8(buf, phase);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_KRP_GET, CONTROLLER_INDEX, buf->data, buf->len);
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_KRP_GET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_krp_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_krp_set_cmd *cmd = (void *)data;
|
|
struct net_buf_simple *buf = NET_BUF_SIMPLE(2);
|
|
uint8_t status;
|
|
uint8_t phase;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_krp_set(cmd->net_idx, cmd->address, cmd->key_net_idx, cmd->transition,
|
|
&status, &phase);
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
net_buf_simple_init(buf, 0);
|
|
net_buf_simple_add_u8(buf, status);
|
|
net_buf_simple_add_u8(buf, phase);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_KRP_SET, CONTROLLER_INDEX, buf->data, buf->len);
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_KRP_SET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_beacon_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_val_get_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_beacon_get(cmd->net_idx, cmd->address, &status);
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_BEACON_GET, CONTROLLER_INDEX,
|
|
&status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_BEACON_GET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_beacon_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_beacon_set_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_beacon_set(cmd->net_idx, cmd->address, cmd->val,
|
|
&status);
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_BEACON_SET, CONTROLLER_INDEX,
|
|
&status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_BEACON_SET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_default_ttl_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_val_get_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
err = bt_mesh_cfg_ttl_get(cmd->net_idx, cmd->address, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_DEFAULT_TTL_GET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_DEFAULT_TTL_GET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_default_ttl_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_default_ttl_set_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
err = bt_mesh_cfg_ttl_set(cmd->net_idx, cmd->address, cmd->val,
|
|
&status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_DEFAULT_TTL_SET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_DEFAULT_TTL_SET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_gatt_proxy_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_val_get_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
err = bt_mesh_cfg_gatt_proxy_get(cmd->net_idx, cmd->address, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_GATT_PROXY_GET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_GATT_PROXY_GET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_gatt_proxy_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_gatt_proxy_set_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
err = bt_mesh_cfg_gatt_proxy_set(cmd->net_idx, cmd->address, cmd->val,
|
|
&status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_GATT_PROXY_SET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_GATT_PROXY_SET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_friend_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_val_get_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
err = bt_mesh_cfg_friend_get(cmd->net_idx, cmd->address, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_FRIEND_GET, CONTROLLER_INDEX,
|
|
&status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_FRIEND_GET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_friend_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_friend_set_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
err = bt_mesh_cfg_friend_set(cmd->net_idx, cmd->address, cmd->val,
|
|
&status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_FRIEND_SET, CONTROLLER_INDEX,
|
|
&status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_FRIEND_SET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_relay_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_val_get_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
uint8_t transmit;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
err = bt_mesh_cfg_relay_get(cmd->net_idx, cmd->address, &status,
|
|
&transmit);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_RELAY_GET, CONTROLLER_INDEX,
|
|
&status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_RELAY_GET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_relay_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_relay_set_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
uint8_t transmit;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
err = bt_mesh_cfg_relay_set(cmd->net_idx, cmd->address, cmd->new_relay,
|
|
cmd->new_transmit, &status, &transmit);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_RELAY_SET, CONTROLLER_INDEX,
|
|
&status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_RELAY_SET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_mod_pub_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_pub_get_cmd *cmd = (void *)data;
|
|
struct bt_mesh_cfg_mod_pub pub;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
err = bt_mesh_cfg_mod_pub_get(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->model_id, &pub,
|
|
&status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_PUB_GET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_PUB_GET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_mod_pub_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_pub_set_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
struct bt_mesh_cfg_mod_pub pub;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
pub.addr = cmd->pub_addr;
|
|
pub.uuid = NULL;
|
|
pub.app_idx = cmd->app_idx;
|
|
pub.cred_flag = cmd->cred_flag;
|
|
pub.ttl = cmd->ttl;
|
|
pub.period = cmd->period;
|
|
pub.transmit = cmd->transmit;
|
|
|
|
err = bt_mesh_cfg_mod_pub_set(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->model_id, &pub,
|
|
&status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_PUB_SET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_PUB_SET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_mod_pub_va_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_pub_va_set_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
struct bt_mesh_cfg_mod_pub pub;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
pub.uuid = cmd->uuid;
|
|
pub.app_idx = cmd->app_idx;
|
|
pub.cred_flag = cmd->cred_flag;
|
|
pub.ttl = cmd->ttl;
|
|
pub.period = cmd->period;
|
|
pub.transmit = cmd->transmit;
|
|
|
|
err = bt_mesh_cfg_mod_pub_set(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->model_id,
|
|
&pub, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_PUB_VA_SET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_PUB_VA_SET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_mod_sub_add(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_sub_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_sub_add(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->sub_addr,
|
|
cmd->model_id, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_ADD,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_ADD, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_mod_sub_ovw(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_sub_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_sub_overwrite(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->sub_addr,
|
|
cmd->model_id, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_OVW,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_OVW, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_mod_sub_del(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_sub_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_sub_del(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->sub_addr,
|
|
cmd->model_id, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_DEL,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_DEL, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_mod_sub_del_all(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_sub_del_all_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_sub_del_all(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->model_id,
|
|
&status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_DEL_ALL,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_DEL_ALL, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_mod_sub_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_sub_get_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int16_t subs;
|
|
size_t sub_cn;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_sub_get(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->model_id, &status,
|
|
&subs, &sub_cn);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_GET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_GET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_mod_sub_get_vnd(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_sub_get_vnd_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
uint16_t subs;
|
|
size_t sub_cn;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_sub_get_vnd(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->model_id,
|
|
cmd->cid, &status, &subs, &sub_cn);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_GET_VND,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_GET_VND, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_mod_sub_va_add(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_sub_va_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
uint16_t virt_addr_rcv;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_sub_va_add(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->uuid,
|
|
cmd->model_id, &virt_addr_rcv,
|
|
&status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_VA_ADD,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_VA_ADD, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_mod_sub_va_del(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_sub_va_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
uint16_t virt_addr_rcv;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_sub_va_del(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->uuid,
|
|
cmd->model_id, &virt_addr_rcv,
|
|
&status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_VA_DEL,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_VA_DEL, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_mod_sub_va_ovw(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_sub_va_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
uint16_t virt_addr_rcv;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_sub_va_overwrite(cmd->net_idx, cmd->address,
|
|
cmd->elem_address,
|
|
cmd->uuid, cmd->model_id,
|
|
&virt_addr_rcv, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_VA_OVW,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_SUB_VA_OVW, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_netkey_add(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_netkey_add_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_net_key_add(cmd->net_idx, cmd->address,
|
|
cmd->net_key_idx, cmd->net_key, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_NETKEY_ADD, CONTROLLER_INDEX,
|
|
&status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_NETKEY_ADD, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_netkey_update(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_netkey_add_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_net_key_update(cmd->net_idx, cmd->address,
|
|
cmd->net_key_idx, cmd->net_key,
|
|
&status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_NETKEY_UPDATE,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_NETKEY_UPDATE, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_netkey_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_val_get_cmd *cmd = (void *)data;
|
|
uint16_t keys;
|
|
size_t key_cnt;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_net_key_get(cmd->net_idx, cmd->address, &keys,
|
|
&key_cnt);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_NETKEY_GET, CONTROLLER_INDEX,
|
|
(uint8_t *)&keys, key_cnt);
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_NETKEY_GET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_netkey_del(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_netkey_del_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_net_key_del(cmd->net_idx, cmd->address,
|
|
cmd->net_key_idx, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_NETKEY_DEL, CONTROLLER_INDEX,
|
|
&status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_NETKEY_DEL, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_appkey_add(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_appkey_add_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_app_key_add(cmd->net_idx, cmd->address,
|
|
cmd->net_key_idx, cmd->app_key_idx,
|
|
cmd->app_key, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_APPKEY_ADD, CONTROLLER_INDEX,
|
|
&status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_APPKEY_ADD, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_appkey_update(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_appkey_add_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_app_key_update(cmd->net_idx, cmd->address,
|
|
cmd->net_key_idx, cmd->app_key_idx,
|
|
cmd->app_key, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_APPKEY_UPDATE,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_APPKEY_UPDATE, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_appkey_del(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_appkey_del_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_app_key_del(cmd->net_idx, cmd->address,
|
|
cmd->net_key_idx, cmd->app_key_idx,
|
|
&status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_APPKEY_DEL, CONTROLLER_INDEX,
|
|
&status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_APPKEY_DEL, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_appkey_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_appkey_get_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
uint16_t keys;
|
|
size_t key_cnt;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_app_key_get(cmd->net_idx, cmd->address,
|
|
cmd->net_key_idx, &status, &keys,
|
|
&key_cnt);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_APPKEY_GET, CONTROLLER_INDEX,
|
|
&status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_APPKEY_GET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_model_app_bind(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_app_bind_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_app_bind(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->app_key_idx,
|
|
cmd->mod_id, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_APP_BIND,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_APP_BIND, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_model_app_bind_vnd(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_app_bind_vnd_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_app_bind_vnd(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->app_key_idx,
|
|
cmd->mod_id, cmd->cid, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_APP_BIND_VND,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_APP_BIND_VND, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_model_app_unbind(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_app_bind_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_app_unbind(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->app_key_idx,
|
|
cmd->mod_id, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_APP_UNBIND,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_APP_UNBIND, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_model_app_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_app_get_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
uint16_t apps;
|
|
size_t app_cnt;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_app_get(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->mod_id, &status,
|
|
&apps, &app_cnt);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_APP_GET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_APP_GET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_model_app_vnd_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_model_app_get_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
uint16_t apps;
|
|
size_t app_cnt;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_mod_app_get_vnd(cmd->net_idx, cmd->address,
|
|
cmd->elem_address, cmd->mod_id,
|
|
cmd->cid, &status, &apps, &app_cnt);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_APP_VND_GET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_MODEL_APP_VND_GET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_hb_pub_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_heartbeat_pub_set_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
struct bt_mesh_cfg_hb_pub pub;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
pub.net_idx = cmd->net_key_idx;
|
|
pub.dst = cmd->destination;
|
|
pub.count = cmd->count_log;
|
|
pub.period = cmd->period_log;
|
|
pub.ttl = cmd->ttl;
|
|
pub.feat = cmd->features;
|
|
|
|
err = bt_mesh_cfg_hb_pub_set(cmd->net_idx, cmd->address, &pub, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_HEARTBEAT_PUB_SET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_HEARTBEAT_PUB_SET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_hb_pub_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_val_get_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
struct bt_mesh_cfg_hb_pub pub;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_hb_pub_get(cmd->net_idx, cmd->address, &pub, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_HEARTBEAT_PUB_GET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_HEARTBEAT_PUB_GET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_hb_sub_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_heartbeat_sub_set_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
struct bt_mesh_cfg_hb_sub sub;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
sub.src = cmd->source;
|
|
sub.dst = cmd->destination;
|
|
sub.period = cmd->period_log;
|
|
|
|
err = bt_mesh_cfg_hb_sub_set(cmd->net_idx, cmd->address, &sub, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_HEARTBEAT_SUB_SET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_HEARTBEAT_SUB_SET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_hb_sub_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_val_get_cmd *cmd = (void *)data;
|
|
uint8_t status;
|
|
struct bt_mesh_cfg_hb_sub sub;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_hb_sub_get(cmd->net_idx, cmd->address, &sub, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_HEARTBEAT_SUB_GET,
|
|
CONTROLLER_INDEX, &status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_HEARTBEAT_SUB_GET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_net_trans_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_val_get_cmd *cmd = (void *)data;
|
|
uint8_t transmit;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_net_transmit_get(cmd->net_idx, cmd->address,
|
|
&transmit);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_NET_TRANS_GET,
|
|
CONTROLLER_INDEX, &transmit, sizeof(transmit));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_NET_TRANS_GET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_net_trans_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_net_trans_set_cmd *cmd = (void *)data;
|
|
uint8_t transmit;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_net_transmit_set(cmd->net_idx, cmd->address,
|
|
cmd->transmit, &transmit);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_NET_TRANS_SET,
|
|
CONTROLLER_INDEX, &transmit, sizeof(transmit));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_NET_TRANS_SET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_node_identity_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_node_idt_set_cmd *cmd = (void *)data;
|
|
struct net_buf_simple *buf = NET_BUF_SIMPLE(2);
|
|
uint8_t identity;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_node_identity_set(cmd->net_idx, cmd->address,
|
|
cmd->net_key_idx, cmd->new_identity,
|
|
&status, &identity);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
net_buf_simple_init(buf, 0);
|
|
net_buf_simple_add_u8(buf, status);
|
|
net_buf_simple_add_u8(buf, identity);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_NODE_IDT_SET,
|
|
CONTROLLER_INDEX, buf->data, buf->len);
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_NODE_IDT_SET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_node_identity_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_node_idt_get_cmd *cmd = (void *)data;
|
|
struct net_buf_simple *buf = NET_BUF_SIMPLE(2);
|
|
uint8_t identity;
|
|
uint8_t status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_node_identity_get(cmd->net_idx, cmd->address,
|
|
cmd->net_key_idx, &status,
|
|
&identity);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
net_buf_simple_init(buf, 0);
|
|
net_buf_simple_add_u8(buf, status);
|
|
net_buf_simple_add_u8(buf, identity);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_NODE_IDT_GET,
|
|
CONTROLLER_INDEX, buf->data, buf->len);
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_NODE_IDT_GET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_node_reset(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_node_reset_cmd *cmd = (void *)data;
|
|
bool status;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_node_reset(cmd->net_idx, cmd->address, &status);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_NODE_RESET, CONTROLLER_INDEX,
|
|
(uint8_t *)&status, sizeof(status));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_NODE_RESET, CONTROLLER_INDEX, BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void config_lpn_timeout_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_cfg_lpn_timeout_cmd *cmd = (void *)data;
|
|
int32_t polltimeout;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_cfg_lpn_timeout_get(cmd->net_idx, cmd->address,
|
|
cmd->unicast_addr, &polltimeout);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_CFG_LPN_TIMEOUT_GET,
|
|
CONTROLLER_INDEX, (uint8_t *)&polltimeout,
|
|
sizeof(polltimeout));
|
|
return;
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_CFG_LPN_TIMEOUT_GET, CONTROLLER_INDEX,
|
|
BTP_STATUS_FAILED);
|
|
}
|
|
|
|
static void health_fault_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_health_fault_get_cmd *cmd = (void *)data;
|
|
uint8_t test_id;
|
|
size_t fault_count = 16;
|
|
uint8_t faults[fault_count];
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_health_fault_get(cmd->address, cmd->app_idx, cmd->cid,
|
|
&test_id, faults, &fault_count);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_HEALTH_FAULT_GET, CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void health_fault_clear(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_health_fault_clear_cmd *cmd = (void *)data;
|
|
uint8_t test_id;
|
|
size_t fault_count = 16;
|
|
uint8_t faults[fault_count];
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
if (cmd->ack) {
|
|
err = bt_mesh_health_fault_clear(cmd->address, cmd->app_idx,
|
|
cmd->cid, &test_id, faults,
|
|
&fault_count);
|
|
} else {
|
|
err = bt_mesh_health_fault_clear_unack(cmd->address, cmd->app_idx, cmd->cid);
|
|
}
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
if (cmd->ack) {
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_HEALTH_FAULT_CLEAR,
|
|
CONTROLLER_INDEX, &test_id, sizeof(test_id));
|
|
return;
|
|
}
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_HEALTH_FAULT_CLEAR,
|
|
CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void health_fault_test(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_health_fault_test_cmd *cmd = (void *)data;
|
|
struct net_buf_simple *buf = NET_BUF_SIMPLE(6);
|
|
size_t fault_count = 16;
|
|
uint8_t faults[fault_count];
|
|
uint8_t test_id;
|
|
uint16_t cid;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
test_id = cmd->test_id;
|
|
cid = cmd->cid;
|
|
|
|
if (cmd->ack) {
|
|
err = bt_mesh_health_fault_test(cmd->address, cmd->app_idx,
|
|
cid, test_id, faults,
|
|
&fault_count);
|
|
} else {
|
|
err = bt_mesh_health_fault_test_unack(cmd->address, cmd->app_idx,
|
|
cid, test_id);
|
|
}
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
if (cmd->ack) {
|
|
net_buf_simple_init(buf, 0);
|
|
net_buf_simple_add_u8(buf, test_id);
|
|
net_buf_simple_add_le16(buf, cid);
|
|
net_buf_simple_add_mem(buf, faults, fault_count);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_HEALTH_FAULT_TEST,
|
|
CONTROLLER_INDEX, buf->data, buf->len);
|
|
return;
|
|
}
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_HEALTH_FAULT_TEST,
|
|
CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void health_period_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_health_period_get_cmd *cmd = (void *)data;
|
|
uint8_t divisor;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_health_period_get(cmd->address, cmd->app_idx, &divisor);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_HEALTH_PERIOD_GET,
|
|
CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void health_period_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_health_period_set_cmd *cmd = (void *)data;
|
|
uint8_t updated_divisor;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
if (cmd->ack) {
|
|
err = bt_mesh_health_period_set(cmd->address, cmd->app_idx,
|
|
cmd->divisor, &updated_divisor);
|
|
} else {
|
|
err = bt_mesh_health_period_set_unack(cmd->address, cmd->app_idx, cmd->divisor);
|
|
}
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
if (cmd->ack) {
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_HEALTH_PERIOD_SET,
|
|
CONTROLLER_INDEX, &updated_divisor,
|
|
sizeof(updated_divisor));
|
|
return;
|
|
}
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_HEALTH_PERIOD_SET,
|
|
CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void health_attention_get(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_health_attention_get_cmd *cmd = (void *)data;
|
|
uint8_t attention;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
err = bt_mesh_health_attention_get(cmd->address, cmd->app_idx,
|
|
&attention);
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_HEALTH_ATTENTION_GET,
|
|
CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void health_attention_set(uint8_t *data, uint16_t len)
|
|
{
|
|
struct mesh_health_attention_set_cmd *cmd = (void *)data;
|
|
uint8_t updated_attention;
|
|
int err;
|
|
|
|
LOG_DBG("");
|
|
|
|
if (cmd->ack) {
|
|
err = bt_mesh_health_attention_set(cmd->address, cmd->app_idx,
|
|
cmd->attention,
|
|
&updated_attention);
|
|
} else {
|
|
err = bt_mesh_health_attention_set_unack(cmd->address, cmd->app_idx,
|
|
cmd->attention);
|
|
}
|
|
|
|
if (err) {
|
|
LOG_ERR("err %d", err);
|
|
goto fail;
|
|
}
|
|
|
|
if (cmd->ack) {
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_HEALTH_ATTENTION_SET,
|
|
CONTROLLER_INDEX, &updated_attention,
|
|
sizeof(updated_attention));
|
|
return;
|
|
}
|
|
|
|
fail:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, MESH_HEALTH_ATTENTION_SET,
|
|
CONTROLLER_INDEX,
|
|
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
|
|
}
|
|
|
|
void tester_handle_mesh(uint8_t opcode, uint8_t index, uint8_t *data, uint16_t len)
|
|
{
|
|
switch (opcode) {
|
|
case MESH_READ_SUPPORTED_COMMANDS:
|
|
supported_commands(data, len);
|
|
break;
|
|
case MESH_CONFIG_PROVISIONING:
|
|
config_prov(data, len);
|
|
break;
|
|
case MESH_PROVISION_NODE:
|
|
provision_node(data, len);
|
|
break;
|
|
case MESH_INIT:
|
|
init(data, len);
|
|
break;
|
|
case MESH_RESET:
|
|
reset(data, len);
|
|
break;
|
|
case MESH_INPUT_NUMBER:
|
|
input_number(data, len);
|
|
break;
|
|
case MESH_INPUT_STRING:
|
|
input_string(data, len);
|
|
break;
|
|
case MESH_IVU_TEST_MODE:
|
|
ivu_test_mode(data, len);
|
|
break;
|
|
case MESH_IVU_TOGGLE_STATE:
|
|
ivu_toggle_state(data, len);
|
|
break;
|
|
case MESH_LPN:
|
|
lpn(data, len);
|
|
break;
|
|
case MESH_LPN_POLL:
|
|
lpn_poll(data, len);
|
|
break;
|
|
case MESH_NET_SEND:
|
|
net_send(data, len);
|
|
break;
|
|
case MESH_HEALTH_GENERATE_FAULTS:
|
|
health_generate_faults(data, len);
|
|
break;
|
|
case MESH_HEALTH_CLEAR_FAULTS:
|
|
health_clear_faults(data, len);
|
|
break;
|
|
case MESH_MODEL_SEND:
|
|
model_send(data, len);
|
|
break;
|
|
case MESH_COMP_DATA_GET:
|
|
composition_data_get(data, len);
|
|
break;
|
|
case MESH_CFG_BEACON_GET:
|
|
config_beacon_get(data, len);
|
|
break;
|
|
case MESH_CFG_BEACON_SET:
|
|
config_beacon_set(data, len);
|
|
break;
|
|
case MESH_CFG_DEFAULT_TTL_GET:
|
|
config_default_ttl_get(data, len);
|
|
break;
|
|
case MESH_CFG_DEFAULT_TTL_SET:
|
|
config_default_ttl_set(data, len);
|
|
break;
|
|
case MESH_CFG_GATT_PROXY_GET:
|
|
config_gatt_proxy_get(data, len);
|
|
break;
|
|
case MESH_CFG_GATT_PROXY_SET:
|
|
config_gatt_proxy_set(data, len);
|
|
break;
|
|
case MESH_CFG_FRIEND_GET:
|
|
config_friend_get(data, len);
|
|
break;
|
|
case MESH_CFG_FRIEND_SET:
|
|
config_friend_set(data, len);
|
|
break;
|
|
case MESH_CFG_RELAY_GET:
|
|
config_relay_get(data, len);
|
|
break;
|
|
case MESH_CFG_RELAY_SET:
|
|
config_relay_set(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_PUB_GET:
|
|
config_mod_pub_get(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_PUB_SET:
|
|
config_mod_pub_set(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_SUB_ADD:
|
|
config_mod_sub_add(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_SUB_DEL:
|
|
config_mod_sub_del(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_SUB_OVW:
|
|
config_mod_sub_ovw(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_SUB_DEL_ALL:
|
|
config_mod_sub_del_all(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_SUB_GET:
|
|
config_mod_sub_get(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_SUB_GET_VND:
|
|
config_mod_sub_get_vnd(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_SUB_VA_ADD:
|
|
config_mod_sub_va_add(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_SUB_VA_DEL:
|
|
config_mod_sub_va_del(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_SUB_VA_OVW:
|
|
config_mod_sub_va_ovw(data, len);
|
|
break;
|
|
case MESH_CFG_NETKEY_ADD:
|
|
config_netkey_add(data, len);
|
|
break;
|
|
case MESH_CFG_NETKEY_GET:
|
|
config_netkey_get(data, len);
|
|
break;
|
|
case MESH_CFG_NETKEY_DEL:
|
|
config_netkey_del(data, len);
|
|
break;
|
|
case MESH_CFG_NETKEY_UPDATE:
|
|
config_netkey_update(data, len);
|
|
break;
|
|
case MESH_CFG_APPKEY_ADD:
|
|
config_appkey_add(data, len);
|
|
break;
|
|
case MESH_CFG_APPKEY_DEL:
|
|
config_appkey_del(data, len);
|
|
break;
|
|
case MESH_CFG_APPKEY_GET:
|
|
config_appkey_get(data, len);
|
|
break;
|
|
case MESH_CFG_APPKEY_UPDATE:
|
|
config_appkey_update(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_APP_BIND:
|
|
config_model_app_bind(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_APP_UNBIND:
|
|
config_model_app_unbind(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_APP_GET:
|
|
config_model_app_get(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_APP_VND_GET:
|
|
config_model_app_vnd_get(data, len);
|
|
break;
|
|
case MESH_CFG_HEARTBEAT_PUB_SET:
|
|
config_hb_pub_set(data, len);
|
|
break;
|
|
case MESH_CFG_HEARTBEAT_PUB_GET:
|
|
config_hb_pub_get(data, len);
|
|
break;
|
|
case MESH_CFG_HEARTBEAT_SUB_SET:
|
|
config_hb_sub_set(data, len);
|
|
break;
|
|
case MESH_CFG_HEARTBEAT_SUB_GET:
|
|
config_hb_sub_get(data, len);
|
|
break;
|
|
case MESH_CFG_NET_TRANS_GET:
|
|
config_net_trans_get(data, len);
|
|
break;
|
|
case MESH_CFG_NET_TRANS_SET:
|
|
config_net_trans_set(data, len);
|
|
break;
|
|
case MESH_CFG_NODE_IDT_SET:
|
|
config_node_identity_set(data, len);
|
|
break;
|
|
case MESH_CFG_NODE_IDT_GET:
|
|
config_node_identity_get(data, len);
|
|
break;
|
|
case MESH_CFG_NODE_RESET:
|
|
config_node_reset(data, len);
|
|
break;
|
|
case MESH_CFG_LPN_TIMEOUT_GET:
|
|
config_lpn_timeout_get(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_PUB_VA_SET:
|
|
config_mod_pub_va_set(data, len);
|
|
break;
|
|
case MESH_CFG_MODEL_APP_BIND_VND:
|
|
config_model_app_bind_vnd(data, len);
|
|
break;
|
|
case MESH_HEALTH_FAULT_GET:
|
|
health_fault_get(data, len);
|
|
break;
|
|
case MESH_HEALTH_FAULT_CLEAR:
|
|
health_fault_clear(data, len);
|
|
break;
|
|
case MESH_HEALTH_FAULT_TEST:
|
|
health_fault_test(data, len);
|
|
break;
|
|
case MESH_HEALTH_PERIOD_GET:
|
|
health_period_get(data, len);
|
|
break;
|
|
case MESH_HEALTH_PERIOD_SET:
|
|
health_period_set(data, len);
|
|
break;
|
|
case MESH_HEALTH_ATTENTION_GET:
|
|
health_attention_get(data, len);
|
|
break;
|
|
case MESH_HEALTH_ATTENTION_SET:
|
|
health_attention_set(data, len);
|
|
break;
|
|
case MESH_PROVISION_ADV:
|
|
provision_adv(data, len);
|
|
break;
|
|
case MESH_CFG_KRP_GET:
|
|
config_krp_get(data, len);
|
|
break;
|
|
case MESH_CFG_KRP_SET:
|
|
config_krp_set(data, len);
|
|
break;
|
|
#if defined(CONFIG_BT_TESTING)
|
|
case MESH_LPN_SUBSCRIBE:
|
|
lpn_subscribe(data, len);
|
|
break;
|
|
case MESH_LPN_UNSUBSCRIBE:
|
|
lpn_unsubscribe(data, len);
|
|
break;
|
|
case MESH_RPL_CLEAR:
|
|
rpl_clear(data, len);
|
|
break;
|
|
#endif /* CONFIG_BT_TESTING */
|
|
case MESH_PROXY_IDENTITY:
|
|
proxy_identity_enable(data, len);
|
|
break;
|
|
default:
|
|
tester_rsp(BTP_SERVICE_ID_MESH, opcode, index,
|
|
BTP_STATUS_UNKNOWN_CMD);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void net_recv_ev(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, const void *payload,
|
|
size_t payload_len)
|
|
{
|
|
NET_BUF_SIMPLE_DEFINE(buf, UINT8_MAX);
|
|
struct mesh_net_recv_ev *ev;
|
|
|
|
LOG_DBG("ttl 0x%02x ctl 0x%02x src 0x%04x dst 0x%04x payload_len %zu",
|
|
ttl, ctl, src, dst, payload_len);
|
|
|
|
if (payload_len > net_buf_simple_tailroom(&buf)) {
|
|
LOG_ERR("Payload size exceeds buffer size");
|
|
return;
|
|
}
|
|
|
|
ev = net_buf_simple_add(&buf, sizeof(*ev));
|
|
ev->ttl = ttl;
|
|
ev->ctl = ctl;
|
|
ev->src = sys_cpu_to_le16(src);
|
|
ev->dst = sys_cpu_to_le16(dst);
|
|
ev->payload_len = payload_len;
|
|
net_buf_simple_add_mem(&buf, payload, payload_len);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_NET_RECV, CONTROLLER_INDEX,
|
|
buf.data, buf.len);
|
|
}
|
|
|
|
static void model_bound_cb(uint16_t addr, struct bt_mesh_model *model,
|
|
uint16_t key_idx)
|
|
{
|
|
int i;
|
|
|
|
LOG_DBG("remote addr 0x%04x key_idx 0x%04x model %p",
|
|
addr, key_idx, model);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(model_bound); i++) {
|
|
if (!model_bound[i].model) {
|
|
model_bound[i].model = model;
|
|
model_bound[i].addr = addr;
|
|
model_bound[i].appkey_idx = key_idx;
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
LOG_ERR("model_bound is full");
|
|
}
|
|
|
|
static void model_unbound_cb(uint16_t addr, struct bt_mesh_model *model,
|
|
uint16_t key_idx)
|
|
{
|
|
int i;
|
|
|
|
LOG_DBG("remote addr 0x%04x key_idx 0x%04x model %p",
|
|
addr, key_idx, model);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(model_bound); i++) {
|
|
if (model_bound[i].model == model) {
|
|
model_bound[i].model = NULL;
|
|
model_bound[i].addr = 0x0000;
|
|
model_bound[i].appkey_idx = BT_MESH_KEY_UNUSED;
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
LOG_INF("model not found");
|
|
}
|
|
|
|
static void invalid_bearer_cb(uint8_t opcode)
|
|
{
|
|
struct mesh_invalid_bearer_ev ev = {
|
|
.opcode = opcode,
|
|
};
|
|
|
|
LOG_DBG("opcode 0x%02x", opcode);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_INVALID_BEARER,
|
|
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
|
|
}
|
|
|
|
static void incomp_timer_exp_cb(void)
|
|
{
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_INCOMP_TIMER_EXP,
|
|
CONTROLLER_INDEX, NULL, 0);
|
|
}
|
|
|
|
static struct bt_test_cb bt_test_cb = {
|
|
.mesh_net_recv = net_recv_ev,
|
|
.mesh_model_bound = model_bound_cb,
|
|
.mesh_model_unbound = model_unbound_cb,
|
|
.mesh_prov_invalid_bearer = invalid_bearer_cb,
|
|
.mesh_trans_incomp_timer_exp = incomp_timer_exp_cb,
|
|
};
|
|
|
|
static void friend_established(uint16_t net_idx, uint16_t lpn_addr,
|
|
uint8_t recv_delay, uint32_t polltimeout)
|
|
{
|
|
struct mesh_frnd_established_ev ev = { net_idx, lpn_addr, recv_delay,
|
|
polltimeout };
|
|
|
|
LOG_DBG("Friendship (as Friend) established with "
|
|
"LPN 0x%04x Receive Delay %u Poll Timeout %u",
|
|
lpn_addr, recv_delay, polltimeout);
|
|
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_FRND_ESTABLISHED,
|
|
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
|
|
}
|
|
|
|
static void friend_terminated(uint16_t net_idx, uint16_t lpn_addr)
|
|
{
|
|
struct mesh_frnd_terminated_ev ev = { net_idx, lpn_addr };
|
|
|
|
LOG_DBG("Friendship (as Friend) lost with LPN "
|
|
"0x%04x", lpn_addr);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_FRND_TERMINATED,
|
|
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
|
|
}
|
|
|
|
BT_MESH_FRIEND_CB_DEFINE(friend_cb) = {
|
|
.established = friend_established,
|
|
.terminated = friend_terminated,
|
|
};
|
|
|
|
static void lpn_established(uint16_t net_idx, uint16_t friend_addr,
|
|
uint8_t queue_size, uint8_t recv_win)
|
|
{
|
|
struct mesh_lpn_established_ev ev = { net_idx, friend_addr, queue_size,
|
|
recv_win };
|
|
|
|
LOG_DBG("Friendship (as LPN) established with "
|
|
"Friend 0x%04x Queue Size %d Receive Window %d",
|
|
friend_addr, queue_size, recv_win);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_LPN_ESTABLISHED,
|
|
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
|
|
}
|
|
|
|
static void lpn_terminated(uint16_t net_idx, uint16_t friend_addr)
|
|
{
|
|
struct mesh_lpn_polled_ev ev = { net_idx, friend_addr };
|
|
|
|
LOG_DBG("Friendship (as LPN) lost with Friend "
|
|
"0x%04x", friend_addr);
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_LPN_TERMINATED,
|
|
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
|
|
}
|
|
|
|
static void lpn_polled(uint16_t net_idx, uint16_t friend_addr, bool retry)
|
|
{
|
|
struct mesh_lpn_polled_ev ev = { net_idx, friend_addr, (uint8_t)retry };
|
|
|
|
LOG_DBG("LPN polled 0x%04x %s", friend_addr, retry ? "(retry)" : "");
|
|
|
|
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_LPN_POLLED,
|
|
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
|
|
}
|
|
|
|
BT_MESH_LPN_CB_DEFINE(lpn_cb) = {
|
|
.established = lpn_established,
|
|
.terminated = lpn_terminated,
|
|
.polled = lpn_polled,
|
|
};
|
|
|
|
uint8_t tester_init_mesh(void)
|
|
{
|
|
if (IS_ENABLED(CONFIG_BT_TESTING)) {
|
|
bt_test_cb_register(&bt_test_cb);
|
|
}
|
|
|
|
return BTP_STATUS_SUCCESS;
|
|
}
|
|
|
|
uint8_t tester_unregister_mesh(void)
|
|
{
|
|
return BTP_STATUS_SUCCESS;
|
|
}
|