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:
Mariusz Skamra 2017-12-27 20:26:50 +01:00 committed by Johan Hedberg
commit 0d71cef1f2
7 changed files with 180 additions and 1 deletions

View file

@ -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;
};

View file

@ -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,

View file

@ -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);
}
}
}

View 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);

View file

@ -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

View file

@ -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 {

View file

@ -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)