Bluetooth: tester: Add BTP Mesh Model Send command implementation
This command will be used to test if model can properly send segmented and unsegmented messages to a given destination address. Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This commit is contained in:
parent
6f642a19fd
commit
0d71cef1f2
7 changed files with 180 additions and 1 deletions
|
@ -30,6 +30,10 @@ extern "C" {
|
||||||
struct bt_test_cb {
|
struct bt_test_cb {
|
||||||
void (*mesh_net_recv)(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
|
void (*mesh_net_recv)(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
|
||||||
const void *payload, size_t payload_len);
|
const void *payload, size_t payload_len);
|
||||||
|
void (*mesh_model_bound)(u16_t addr, struct bt_mesh_model *model,
|
||||||
|
u16_t key_idx);
|
||||||
|
void (*mesh_model_unbound)(u16_t addr, struct bt_mesh_model *model,
|
||||||
|
u16_t key_idx);
|
||||||
|
|
||||||
sys_snode_t node;
|
sys_snode_t node;
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)
|
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
|
|
||||||
|
#include "../testing.h"
|
||||||
|
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "adv.h"
|
#include "adv.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
@ -2305,6 +2307,10 @@ static void mod_app_bind(struct bt_mesh_model *model,
|
||||||
|
|
||||||
status = mod_bind(mod, key_app_idx);
|
status = mod_bind(mod, key_app_idx);
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_BT_TESTING) && status == STATUS_SUCCESS) {
|
||||||
|
bt_test_mesh_model_bound(ctx->addr, mod, key_app_idx);
|
||||||
|
}
|
||||||
|
|
||||||
send_status:
|
send_status:
|
||||||
BT_DBG("status 0x%02x", status);
|
BT_DBG("status 0x%02x", status);
|
||||||
create_mod_app_status(msg, mod, vnd, elem_addr, key_app_idx, status,
|
create_mod_app_status(msg, mod, vnd, elem_addr, key_app_idx, status,
|
||||||
|
@ -2346,6 +2352,10 @@ static void mod_app_unbind(struct bt_mesh_model *model,
|
||||||
|
|
||||||
status = mod_unbind(mod, key_app_idx);
|
status = mod_unbind(mod, key_app_idx);
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_BT_TESTING) && status == STATUS_SUCCESS) {
|
||||||
|
bt_test_mesh_model_unbound(ctx->addr, mod, key_app_idx);
|
||||||
|
}
|
||||||
|
|
||||||
send_status:
|
send_status:
|
||||||
BT_DBG("status 0x%02x", status);
|
BT_DBG("status 0x%02x", status);
|
||||||
create_mod_app_status(msg, mod, vnd, elem_addr, key_app_idx, status,
|
create_mod_app_status(msg, mod, vnd, elem_addr, key_app_idx, status,
|
||||||
|
|
|
@ -7,8 +7,11 @@
|
||||||
#include <zephyr.h>
|
#include <zephyr.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <bluetooth/mesh.h>
|
||||||
#include <bluetooth/testing.h>
|
#include <bluetooth/testing.h>
|
||||||
|
|
||||||
|
#include "testing.h"
|
||||||
|
|
||||||
static sys_slist_t cb_slist;
|
static sys_slist_t cb_slist;
|
||||||
|
|
||||||
void bt_test_cb_register(struct bt_test_cb *cb)
|
void bt_test_cb_register(struct bt_test_cb *cb)
|
||||||
|
@ -33,3 +36,27 @@ void bt_test_mesh_net_recv(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bt_test_mesh_model_bound(u16_t addr, struct bt_mesh_model *model,
|
||||||
|
u16_t key_idx)
|
||||||
|
{
|
||||||
|
struct bt_test_cb *cb;
|
||||||
|
|
||||||
|
SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) {
|
||||||
|
if (cb->mesh_model_bound) {
|
||||||
|
cb->mesh_model_bound(addr, model, key_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_test_mesh_model_unbound(u16_t addr, struct bt_mesh_model *model,
|
||||||
|
u16_t key_idx)
|
||||||
|
{
|
||||||
|
struct bt_test_cb *cb;
|
||||||
|
|
||||||
|
SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) {
|
||||||
|
if (cb->mesh_model_unbound) {
|
||||||
|
cb->mesh_model_unbound(addr, model, key_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
15
subsys/bluetooth/host/testing.h
Normal file
15
subsys/bluetooth/host/testing.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/**
|
||||||
|
* @file testing.h
|
||||||
|
* @brief Internal API for Bluetooth testing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
void bt_test_mesh_model_bound(u16_t addr, struct bt_mesh_model *model,
|
||||||
|
u16_t key_idx);
|
||||||
|
void bt_test_mesh_model_unbound(u16_t addr, struct bt_mesh_model *model,
|
||||||
|
u16_t key_idx);
|
|
@ -1507,6 +1507,17 @@ Commands and responses:
|
||||||
|
|
||||||
In case of an error, the error response will be returned.
|
In case of an error, the error response will be returned.
|
||||||
|
|
||||||
|
Opcode 0x0f - Model Send
|
||||||
|
Controller Index: <controller id>
|
||||||
|
Command parameters: SRC (2 octets)
|
||||||
|
DST (2 octets)
|
||||||
|
Payload_Len (1 octet)
|
||||||
|
Payload (variable)
|
||||||
|
|
||||||
|
This command is used to send Mesh model message.
|
||||||
|
|
||||||
|
In case of an error, the error response will be returned.
|
||||||
|
|
||||||
Events:
|
Events:
|
||||||
Opcode 0x80 - Output number action Event
|
Opcode 0x80 - Output number action Event
|
||||||
|
|
||||||
|
|
|
@ -747,6 +747,14 @@ struct mesh_lpn_set_cmd {
|
||||||
|
|
||||||
#define MESH_LPN_POLL 0x0e
|
#define MESH_LPN_POLL 0x0e
|
||||||
|
|
||||||
|
#define MESH_MODEL_SEND 0x0f
|
||||||
|
struct mesh_model_send_cmd {
|
||||||
|
u16_t src;
|
||||||
|
u16_t dst;
|
||||||
|
u8_t payload_len;
|
||||||
|
u8_t payload[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
/* events */
|
/* events */
|
||||||
#define MESH_EV_OUT_NUMBER_ACTION 0x80
|
#define MESH_EV_OUT_NUMBER_ACTION 0x80
|
||||||
struct mesh_out_number_action_ev {
|
struct mesh_out_number_action_ev {
|
||||||
|
|
|
@ -41,6 +41,15 @@ static u8_t static_auth[16];
|
||||||
/* Vendor Model data */
|
/* Vendor Model data */
|
||||||
#define VND_MODEL_ID_1 0x1234
|
#define VND_MODEL_ID_1 0x1234
|
||||||
|
|
||||||
|
/* Model send data */
|
||||||
|
#define MODEL_BOUNDS_MAX 2
|
||||||
|
|
||||||
|
static struct model_data {
|
||||||
|
struct bt_mesh_model *model;
|
||||||
|
u16_t addr;
|
||||||
|
u16_t appkey_idx;
|
||||||
|
} model_bound[MODEL_BOUNDS_MAX];
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
u16_t local;
|
u16_t local;
|
||||||
u16_t dst;
|
u16_t dst;
|
||||||
|
@ -66,7 +75,6 @@ static void supported_commands(u8_t *data, u16_t len)
|
||||||
tester_set_bit(buf->data, MESH_INPUT_NUMBER);
|
tester_set_bit(buf->data, MESH_INPUT_NUMBER);
|
||||||
tester_set_bit(buf->data, MESH_INPUT_STRING);
|
tester_set_bit(buf->data, MESH_INPUT_STRING);
|
||||||
/* 2nd octet */
|
/* 2nd octet */
|
||||||
memset(net_buf_simple_add(buf, 1), 0, 1);
|
|
||||||
tester_set_bit(buf->data, MESH_IVU_TEST_MODE);
|
tester_set_bit(buf->data, MESH_IVU_TEST_MODE);
|
||||||
tester_set_bit(buf->data, MESH_IVU_TOGGLE_STATE);
|
tester_set_bit(buf->data, MESH_IVU_TOGGLE_STATE);
|
||||||
tester_set_bit(buf->data, MESH_NET_SEND);
|
tester_set_bit(buf->data, MESH_NET_SEND);
|
||||||
|
@ -74,6 +82,7 @@ static void supported_commands(u8_t *data, u16_t len)
|
||||||
tester_set_bit(buf->data, MESH_HEALTH_CLEAR_FAULTS);
|
tester_set_bit(buf->data, MESH_HEALTH_CLEAR_FAULTS);
|
||||||
tester_set_bit(buf->data, MESH_LPN);
|
tester_set_bit(buf->data, MESH_LPN);
|
||||||
tester_set_bit(buf->data, MESH_LPN_POLL);
|
tester_set_bit(buf->data, MESH_LPN_POLL);
|
||||||
|
tester_set_bit(buf->data, MESH_MODEL_SEND);
|
||||||
|
|
||||||
tester_send(BTP_SERVICE_ID_MESH, MESH_READ_SUPPORTED_COMMANDS,
|
tester_send(BTP_SERVICE_ID_MESH, MESH_READ_SUPPORTED_COMMANDS,
|
||||||
CONTROLLER_INDEX, buf->data, buf->len);
|
CONTROLLER_INDEX, buf->data, buf->len);
|
||||||
|
@ -602,6 +611,54 @@ static void health_clear_faults(u8_t *data, u16_t len)
|
||||||
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
|
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void model_send(u8_t *data, u16_t len)
|
||||||
|
{
|
||||||
|
struct mesh_model_send_cmd *cmd = (void *) data;
|
||||||
|
struct net_buf_simple *msg = NET_BUF_SIMPLE(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;
|
||||||
|
u16_t src = sys_le16_to_cpu(cmd->src);
|
||||||
|
|
||||||
|
/* Lookup source address */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(model_bound); i++) {
|
||||||
|
if (model_bound[i].model->elem->addr == src) {
|
||||||
|
model = model_bound[i].model;
|
||||||
|
ctx.app_idx = model_bound[i].appkey_idx;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!model) {
|
||||||
|
SYS_LOG_ERR("Model not found");
|
||||||
|
err = -EINVAL;
|
||||||
|
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_LOG_DBG("src 0x%04x dst 0x%04x model %p payload_len %d", src,
|
||||||
|
ctx.addr, model, cmd->payload_len);
|
||||||
|
|
||||||
|
net_buf_simple_init(msg, 0);
|
||||||
|
|
||||||
|
net_buf_simple_add_mem(msg, cmd->payload, cmd->payload_len);
|
||||||
|
|
||||||
|
err = bt_mesh_model_send(model, &ctx, msg, NULL, NULL);
|
||||||
|
if (err) {
|
||||||
|
SYS_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);
|
||||||
|
}
|
||||||
|
|
||||||
void tester_handle_mesh(u8_t opcode, u8_t index, u8_t *data, u16_t len)
|
void tester_handle_mesh(u8_t opcode, u8_t index, u8_t *data, u16_t len)
|
||||||
{
|
{
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
|
@ -647,6 +704,9 @@ void tester_handle_mesh(u8_t opcode, u8_t index, u8_t *data, u16_t len)
|
||||||
case MESH_HEALTH_CLEAR_FAULTS:
|
case MESH_HEALTH_CLEAR_FAULTS:
|
||||||
health_clear_faults(data, len);
|
health_clear_faults(data, len);
|
||||||
break;
|
break;
|
||||||
|
case MESH_MODEL_SEND:
|
||||||
|
model_send(data, len);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
tester_rsp(BTP_SERVICE_ID_MESH, opcode, index,
|
tester_rsp(BTP_SERVICE_ID_MESH, opcode, index,
|
||||||
BTP_STATUS_UNKNOWN_CMD);
|
BTP_STATUS_UNKNOWN_CMD);
|
||||||
|
@ -683,8 +743,52 @@ void net_recv_ev(u8_t ttl, u8_t ctl, u16_t src, u16_t dst, const void *payload,
|
||||||
buf->data, buf->len);
|
buf->data, buf->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void model_bound_cb(u16_t addr, struct bt_mesh_model *model,
|
||||||
|
u16_t key_idx)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
SYS_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_LOG_ERR("model_bound is full");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void model_unbound_cb(u16_t addr, struct bt_mesh_model *model,
|
||||||
|
u16_t key_idx)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
SYS_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_LOG_INF("model not found");
|
||||||
|
}
|
||||||
|
|
||||||
static struct bt_test_cb bt_test_cb = {
|
static struct bt_test_cb bt_test_cb = {
|
||||||
.mesh_net_recv = net_recv_ev,
|
.mesh_net_recv = net_recv_ev,
|
||||||
|
.mesh_model_bound = model_bound_cb,
|
||||||
|
.mesh_model_unbound = model_unbound_cb,
|
||||||
};
|
};
|
||||||
|
|
||||||
u8_t tester_init_mesh(void)
|
u8_t tester_init_mesh(void)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue