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 {
|
||||
void (*mesh_net_recv)(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)
|
||||
#include "common/log.h"
|
||||
|
||||
#include "../testing.h"
|
||||
|
||||
#include "mesh.h"
|
||||
#include "adv.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);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_TESTING) && status == STATUS_SUCCESS) {
|
||||
bt_test_mesh_model_bound(ctx->addr, mod, key_app_idx);
|
||||
}
|
||||
|
||||
send_status:
|
||||
BT_DBG("status 0x%02x", 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);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_TESTING) && status == STATUS_SUCCESS) {
|
||||
bt_test_mesh_model_unbound(ctx->addr, mod, key_app_idx);
|
||||
}
|
||||
|
||||
send_status:
|
||||
BT_DBG("status 0x%02x", status);
|
||||
create_mod_app_status(msg, mod, vnd, elem_addr, key_app_idx, status,
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
#include <zephyr.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <bluetooth/mesh.h>
|
||||
#include <bluetooth/testing.h>
|
||||
|
||||
#include "testing.h"
|
||||
|
||||
static sys_slist_t cb_slist;
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
Opcode 0x80 - Output number action Event
|
||||
|
||||
|
|
|
@ -747,6 +747,14 @@ struct mesh_lpn_set_cmd {
|
|||
|
||||
#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 */
|
||||
#define MESH_EV_OUT_NUMBER_ACTION 0x80
|
||||
struct mesh_out_number_action_ev {
|
||||
|
|
|
@ -41,6 +41,15 @@ static u8_t static_auth[16];
|
|||
/* Vendor Model data */
|
||||
#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 {
|
||||
u16_t local;
|
||||
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_STRING);
|
||||
/* 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_TOGGLE_STATE);
|
||||
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_LPN);
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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:
|
||||
health_clear_faults(data, len);
|
||||
break;
|
||||
case MESH_MODEL_SEND:
|
||||
model_send(data, len);
|
||||
break;
|
||||
default:
|
||||
tester_rsp(BTP_SERVICE_ID_MESH, opcode, index,
|
||||
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);
|
||||
}
|
||||
|
||||
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 = {
|
||||
.mesh_net_recv = net_recv_ev,
|
||||
.mesh_model_bound = model_bound_cb,
|
||||
.mesh_model_unbound = model_unbound_cb,
|
||||
};
|
||||
|
||||
u8_t tester_init_mesh(void)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue