component/ble_mesh: fix ble mesh fast prov demo bug

This commit is contained in:
lly
2019-06-20 10:02:16 +08:00
parent 54ecdca320
commit 1d7d736a2b
25 changed files with 588 additions and 450 deletions

View File

@@ -1335,8 +1335,8 @@ if BLE_MESH
if BLE_MESH_PB_ADV
config BLE_MESH_PBA_SAME_TIME
int "Maximum number of PB-ADV running at the same time by provisioner"
default 10
range 1 30
default 2
range 1 10
help
This option specifies how many devices can be provisioned at the same
time using PB-ADV.
@@ -1345,7 +1345,7 @@ if BLE_MESH
if BLE_MESH_PB_GATT
config BLE_MESH_PBG_SAME_TIME
int "Maximum number of PB-GATT running at the same time by provisioner"
default 4
default 1
range 1 5
help
This option specifies how many devices can be provisioned at the same
@@ -1447,7 +1447,7 @@ if BLE_MESH
config BLE_MESH_STORE_TIMEOUT
int "Delay (in seconds) before storing anything persistently"
range 0 1000000
default 2
default 0
help
This value defines in seconds how soon any pending changes are actually
written into persistent storage (flash) after a change occurs.
@@ -1486,21 +1486,21 @@ if BLE_MESH
config BLE_MESH_SUBNET_COUNT
int "Maximum number of mesh subnets per network"
default 1
default 3
range 1 4096
help
This option specifies how many subnets a Mesh network can have at the same time.
config BLE_MESH_APP_KEY_COUNT
int "Maximum number of application keys per network"
default 1
default 3
range 1 4096
help
This option specifies how many application keys the device can store per network.
config BLE_MESH_MODEL_KEY_COUNT
int "Maximum number of application keys per model"
default 1
default 3
range 1 4096
help
This option specifies the maximum number of application keys to which each model
@@ -1508,7 +1508,7 @@ if BLE_MESH
config BLE_MESH_MODEL_GROUP_COUNT
int "Maximum number of group address subscriptions per model"
default 1
default 3
range 1 4096
help
This option specifies the maximum number of addresses to which each model can
@@ -1516,7 +1516,7 @@ if BLE_MESH
config BLE_MESH_LABEL_COUNT
int "Maximum number of Label UUIDs used for Virtual Addresses"
default 1
default 3
range 0 4096
help
This option specifies how many Label UUIDs can be stored.

View File

@@ -113,18 +113,18 @@ void k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler)
if (!hash_map_has_key(bm_alarm_hash_map, (void *)work)) {
alarm = osi_alarm_new("bt_mesh", bt_mesh_alarm_cb, (void *)work, 0);
if (alarm == NULL) {
LOG_ERROR("%s, Unable to create alarm", __func__);
BT_ERR("%s, Unable to create alarm", __func__);
return;
}
if (!hash_map_set(bm_alarm_hash_map, work, (void *)alarm)) {
LOG_ERROR("%s Unable to add the timer to hash map.", __func__);
BT_ERR("%s Unable to add the timer to hash map.", __func__);
}
}
osi_mutex_unlock(&bm_alarm_lock);
alarm = hash_map_get(bm_alarm_hash_map, work);
if (alarm == NULL) {
LOG_WARN("%s, Unable to find expected alarm in hash map", __func__);
BT_WARN("%s, Unable to find expected alarm in hash map", __func__);
return;
}
@@ -140,7 +140,7 @@ int k_delayed_work_submit(struct k_delayed_work *work,
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
if (alarm == NULL) {
LOG_WARN("%s, Unable to find expected alarm in hash map", __func__);
BT_WARN("%s, Unable to find expected alarm in hash map", __func__);
return -EINVAL;
}
@@ -156,7 +156,7 @@ int k_delayed_work_cancel(struct k_delayed_work *work)
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
if (alarm == NULL) {
LOG_WARN("%s, Unable to find expected alarm in hash map", __func__);
BT_WARN("%s, Unable to find expected alarm in hash map", __func__);
return -EINVAL;
}
@@ -171,7 +171,7 @@ int k_delayed_work_free(struct k_delayed_work *work)
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, work);
if (alarm == NULL) {
LOG_WARN("%s Unable to find expected alarm in hash map", __func__);
BT_WARN("%s Unable to find expected alarm in hash map", __func__);
return -EINVAL;
}
@@ -185,7 +185,7 @@ s32_t k_delayed_work_remaining_get(struct k_delayed_work *work)
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
if (alarm == NULL) {
LOG_WARN("%s Unable to find expected alarm in hash map", __func__);
BT_WARN("%s Unable to find expected alarm in hash map", __func__);
return 0;
}

View File

@@ -1255,6 +1255,15 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf,
transmit = bt_mesh_relay_retransmit_get();
} else {
transmit = bt_mesh_net_transmit_get();
if (rx->net_if == BLE_MESH_NET_IF_PROXY &&
transmit < BLE_MESH_TRANSMIT(5, 20)) {
/**
* Add this in case EspBleMesh APP just send a message once, and
* the Proxy Node will send this message using advertising bearer
* with duration not less than 180ms.
*/
transmit = BLE_MESH_TRANSMIT(5, 20);
}
}
buf = bt_mesh_adv_create(BLE_MESH_ADV_DATA,

View File

@@ -136,6 +136,7 @@ struct prov_link {
#if defined(CONFIG_BLE_MESH_PB_ADV)
u32_t id; /* Link ID */
u8_t tx_pdu_type; /* The previously transmitted Provisioning PDU type */
struct {
u8_t id; /* Transaction ID */
@@ -171,12 +172,14 @@ struct prov_rx {
u8_t gpc;
};
#define RETRANSMIT_TIMEOUT K_MSEC(500)
#define BUF_TIMEOUT K_MSEC(400)
#if defined(CONFIG_BLE_MESH_FAST_PROV)
#define RETRANSMIT_TIMEOUT K_MSEC(360)
#define TRANSACTION_TIMEOUT K_SECONDS(3)
#define PROVISION_TIMEOUT K_SECONDS(6)
#else
#define RETRANSMIT_TIMEOUT K_MSEC(500)
#define TRANSACTION_TIMEOUT K_SECONDS(30)
#define PROVISION_TIMEOUT K_SECONDS(60)
#endif /* CONFIG_BLE_MESH_FAST_PROV */
@@ -412,7 +415,7 @@ static int prov_send_adv(struct net_buf_simple *msg)
struct net_buf *start, *buf;
u8_t seg_len, seg_id;
u8_t xact_id;
u8_t type;
s32_t timeout = PROVISION_TIMEOUT;
BT_DBG("%s, len %u: %s", __func__, msg->len, bt_hex(msg->data, msg->len));
@@ -432,8 +435,8 @@ static int prov_send_adv(struct net_buf_simple *msg)
net_buf_add_u8(start, bt_mesh_fcs_calc(msg->data, msg->len));
link.tx.buf[0] = start;
/* Change by Espressif, get message type */
type = msg->data[0];
/* Changed by Espressif, get message type */
link.tx_pdu_type = msg->data[0];
seg_len = MIN(msg->len, START_PAYLOAD_MAX);
BT_DBG("seg 0 len %u: %s", seg_len, bt_hex(msg->data, seg_len));
@@ -476,10 +479,13 @@ static int prov_send_adv(struct net_buf_simple *msg)
if (bt_mesh_atomic_test_and_clear_bit(link.flags, TIMEOUT_START)) {
k_delayed_work_cancel(&link.timeout);
}
if (type != PROV_COMPLETE && type != PROV_FAILED) {
if (!bt_mesh_atomic_test_and_set_bit(link.flags, TIMEOUT_START)) {
k_delayed_work_submit(&link.timeout, PROVISION_TIMEOUT);
}
#if defined(CONFIG_BLE_MESH_FAST_PROV)
if (link.tx_pdu_type >= PROV_COMPLETE) {
timeout = K_SECONDS(60);
}
#endif
if (!bt_mesh_atomic_test_and_set_bit(link.flags, TIMEOUT_START)) {
k_delayed_work_submit(&link.timeout, timeout);
}
return 0;
@@ -1243,6 +1249,7 @@ static void prov_timeout(struct k_work *work)
#if defined(CONFIG_BLE_MESH_PB_ADV)
static void prov_retransmit(struct k_work *work)
{
s64_t timeout = TRANSACTION_TIMEOUT;
int i;
BT_DBG("%s", __func__);
@@ -1252,8 +1259,14 @@ static void prov_retransmit(struct k_work *work)
return;
}
if (k_uptime_get() - link.tx.start > TRANSACTION_TIMEOUT) {
BT_WARN("Giving up transaction");
#if defined(CONFIG_BLE_MESH_FAST_PROV)
/* When Provisioning Failed PDU is sent, 3s may be used here. */
if (link.tx_pdu_type >= PROV_COMPLETE) {
timeout = K_SECONDS(30);
}
#endif
if (k_uptime_get() - link.tx.start > timeout) {
BT_WARN("Node timeout, giving up transaction");
reset_link();
return;
}
@@ -1290,7 +1303,14 @@ static void link_open(struct prov_rx *rx, struct net_buf_simple *buf)
}
if (bt_mesh_atomic_test_bit(link.flags, LINK_ACTIVE)) {
BT_WARN("Ignoring bearer open: link already active");
/* Send another link ack if the provisioner missed the last */
if (link.id == rx->link_id && link.expect == PROV_INVITE) {
BT_DBG("Resending link ack");
bearer_ctl_send(LINK_ACK, NULL, 0);
} else {
BT_WARN("Ignoring bearer open: link already active");
}
return;
}
@@ -1495,7 +1515,7 @@ static void gen_prov_start(struct prov_rx *rx, struct net_buf_simple *buf)
if (link.rx.buf->len > link.rx.buf->size) {
BT_ERR("%s, Too large provisioning PDU (%u bytes)",
__func__, link.rx.buf->len);
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
// close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
return;
}

View File

@@ -15,9 +15,9 @@
#include <string.h>
#include <errno.h>
#include "stack/bt_types.h"
#include "sdkconfig.h"
#include "osi/allocator.h"
#include "osi/mutex.h"
#include "mesh_main.h"
#include "mesh_trace.h"
@@ -168,10 +168,11 @@ struct prov_link {
#if defined(CONFIG_BLE_MESH_PB_ADV)
bool linking; /* Linking is being establishing */
u16_t link_close; /* Link close been sent flag */
u16_t send_link_close; /* Link close is being sent flag */
u32_t link_id; /* Link ID */
u8_t pending_ack; /* Decide which transaction id ack is pending */
u8_t expect_ack_for; /* Transaction ACK expected for provisioning pdu */
u8_t tx_pdu_type; /* The current transmitted Provisioning PDU type */
struct {
u8_t trans_id; /* Transaction ID */
@@ -197,6 +198,7 @@ struct prov_link {
struct k_delayed_work retransmit;
} tx;
#endif
/** Provision timeout timer. Spec P259 says: The provisioning protocol
* shall have a minimum timeout of 60 seconds that is reset each time
* a provisioning protocol PDU is sent or received.
@@ -204,6 +206,12 @@ struct prov_link {
struct k_delayed_work timeout;
};
/* Number of devices can be provisioned at the same time equals to PB-ADV + PB-GATT */
#define BLE_MESH_PROV_SAME_TIME \
(CONFIG_BLE_MESH_PBA_SAME_TIME + CONFIG_BLE_MESH_PBG_SAME_TIME)
static struct prov_link link[BLE_MESH_PROV_SAME_TIME];
struct prov_rx {
u32_t link_id;
u8_t xact_id;
@@ -255,6 +263,12 @@ struct prov_ctx_t {
/* Indicate when received uuid_match adv_pkts, can provision it at once */
bool prov_after_match;
/* Mutex used to protect the PB-ADV procedure */
osi_mutex_t pb_adv_lock;
/* Mutex used to protect the PB-GATT procedure */
osi_mutex_t pb_gatt_lock;
/** This structure is used to store the information of the device which
* provisioner has successfully sent provisioning data to. In this
* structure, we don't care if the device is currently in the mesh
@@ -268,9 +282,11 @@ struct prov_ctx_t {
} already_prov[BLE_MESH_ALREADY_PROV_NUM];
};
static struct prov_ctx_t prov_ctx;
struct prov_node_info {
bool provisioned; /* device provisioned flag */
bt_mesh_addr_t addr; /* device address */
bt_mesh_addr_t addr; /* device address */
u8_t uuid[16]; /* node uuid */
u16_t oob_info; /* oob info contained in adv pkt */
u8_t element_num; /* element contained in this node */
@@ -280,6 +296,8 @@ struct prov_node_info {
u32_t iv_index; /* IV Index */
};
static struct prov_node_info prov_nodes[CONFIG_BLE_MESH_MAX_PROV_NODES];
struct unprov_dev_queue {
bt_mesh_addr_t addr;
u8_t uuid[16];
@@ -296,12 +314,14 @@ struct unprov_dev_queue {
static unprov_adv_pkt_cb_t notify_unprov_adv_pkt_cb;
#define RETRANSMIT_TIMEOUT K_MSEC(500)
#define BUF_TIMEOUT K_MSEC(400)
#if defined(CONFIG_BLE_MESH_FAST_PROV)
#define RETRANSMIT_TIMEOUT K_MSEC(360)
#define TRANSACTION_TIMEOUT K_SECONDS(3)
#define PROVISION_TIMEOUT K_SECONDS(6)
#else
#define RETRANSMIT_TIMEOUT K_MSEC(500)
#define TRANSACTION_TIMEOUT K_SECONDS(30)
#define PROVISION_TIMEOUT K_SECONDS(60)
#endif /* CONFIG_BLE_MESH_FAST_PROV */
@@ -314,19 +334,10 @@ static unprov_adv_pkt_cb_t notify_unprov_adv_pkt_cb;
#define PROV_BUF(len) NET_BUF_SIMPLE(PROV_BUF_HEADROOM + len)
/* Number of devices can be provisioned at the same time using PB-GATT + PB-ADV */
#define BLE_MESH_PROV_SAME_TIME (CONFIG_BLE_MESH_PBA_SAME_TIME + CONFIG_BLE_MESH_PBG_SAME_TIME)
static struct prov_link link[BLE_MESH_PROV_SAME_TIME];
static const struct bt_mesh_prov *prov;
static struct prov_ctx_t prov_ctx;
static struct prov_node_info prov_nodes[CONFIG_BLE_MESH_MAX_PROV_NODES];
#if defined(CONFIG_BLE_MESH_PB_ADV)
static void send_link_open(void);
static void send_link_open(int i);
#endif
static void prov_gen_dh_key(int i);
@@ -351,15 +362,14 @@ static struct adv_buf_t {
}
/* Fast provisioning uses this structure for provisioning data */
struct bt_mesh_fast_prov {
static struct bt_mesh_fast_prov_info {
u16_t net_idx;
const u8_t *net_key;
u8_t flags;
u32_t iv_index;
u16_t unicast_addr_min;
u16_t unicast_addr_max;
};
static struct bt_mesh_fast_prov fast_prov;
} fast_prov_info;
static bool fast_prov_flag;
#define FAST_PROV_FLAG_GET() fast_prov_flag
@@ -448,7 +458,7 @@ static int provisioner_dev_find(const bt_mesh_addr_t *addr, const u8_t uuid[16],
comp = memcmp(addr->val, zero, BLE_MESH_ADDR_LEN);
}
if ((!uuid && (!addr || (comp == 0) || (addr->type > BLE_ADDR_RANDOM))) || !index) {
if ((!uuid && (!addr || (comp == 0) || (addr->type > BLE_MESH_ADDR_RANDOM))) || !index) {
return -EINVAL;
}
@@ -465,7 +475,7 @@ static int provisioner_dev_find(const bt_mesh_addr_t *addr, const u8_t uuid[16],
}
}
if (addr && comp && (addr->type <= BLE_ADDR_RANDOM)) {
if (addr && comp && (addr->type <= BLE_MESH_ADDR_RANDOM)) {
for (j = 0; j < ARRAY_SIZE(unprov_dev); j++) {
if (!memcmp(unprov_dev[j].addr.val, addr->val, BLE_MESH_ADDR_LEN) &&
unprov_dev[j].addr.type == addr->type) {
@@ -495,24 +505,60 @@ static int provisioner_dev_find(const bt_mesh_addr_t *addr, const u8_t uuid[16],
return 0;
}
static int provisioner_dev_uuid_match(const u8_t uuid[16])
static bool is_unprov_dev_being_provision(const u8_t uuid[16])
{
if (!uuid) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
int i;
if (prov_ctx.match_length && prov_ctx.match_value) {
if (memcmp(uuid + prov_ctx.match_offset,
prov_ctx.match_value, prov_ctx.match_length)) {
return -EAGAIN;
#if defined(CONFIG_BLE_MESH_FAST_PROV)
/**
* During Fast Provisioning test, we found that if a device has already being
* provisioned, there is still a chance that the Provisioner can receive the
* Unprovisioned Device Beacon from the device (because the device will stop
* Unprovisioned Device Beacon when Transaction ACK for Provisioning Complete
* is received). So in Fast Provisioning the Provisioner should ignore this.
*/
for (i = 0; i < ARRAY_SIZE(prov_nodes); i++) {
if (prov_nodes[i].provisioned) {
if (!memcmp(prov_nodes[i].uuid, uuid, 16)) {
BT_WARN("Device has already been provisioned");
return -EALREADY;
}
}
}
#endif
for (i = 0; i < BLE_MESH_PROV_SAME_TIME; i++) {
#if defined(CONFIG_BLE_MESH_PB_ADV) && defined(CONFIG_BLE_MESH_PB_GATT)
if (link[i].linking || link[i].connecting ||
bt_mesh_atomic_test_bit(link[i].flags, LINK_ACTIVE)) {
#elif defined(CONFIG_BLE_MESH_PB_ADV) && !defined(CONFIG_BLE_MESH_PB_GATT)
if (link[i].linking || bt_mesh_atomic_test_bit(link[i].flags, LINK_ACTIVE)) {
#else
if (link[i].connecting || bt_mesh_atomic_test_bit(link[i].flags, LINK_ACTIVE)) {
#endif
if (!memcmp(link[i].uuid, uuid, 16)) {
BT_DBG("%s, Device is being provisioned", __func__);
return true;
}
}
}
return 0;
return false;
}
static int provisioner_check_device_uuid(const u8_t uuid[16])
static bool is_unprov_dev_uuid_match(const u8_t uuid[16])
{
if (prov_ctx.match_length && prov_ctx.match_value) {
if (memcmp(uuid + prov_ctx.match_offset,
prov_ctx.match_value, prov_ctx.match_length)) {
return false;
}
}
return true;
}
static int provisioner_check_unprov_dev_info(const u8_t uuid[16])
{
int i;
@@ -521,29 +567,20 @@ static int provisioner_check_device_uuid(const u8_t uuid[16])
return -EINVAL;
}
/* Check if the device uuid matches configured value */
if (is_unprov_dev_uuid_match(uuid) == false) {
BT_DBG("%s, Device uuid is not matched", __func__);
return -EIO;
}
/* Check if this device is currently being provisioned.
* According to Zephyr's device code, if we connect with
* one device and start to provision it, we may still can
* receive the connectable prov adv pkt from this device.
* Here we check both PB-GATT and PB-ADV link status.
*/
for (i = 0; i < BLE_MESH_PROV_SAME_TIME; i++) {
#if defined(CONFIG_BLE_MESH_PB_GATT)
if (link[i].connecting || bt_mesh_atomic_test_bit(link[i].flags, LINK_ACTIVE)) {
#else
if (link[i].linking || bt_mesh_atomic_test_bit(link[i].flags, LINK_ACTIVE)) {
#endif
if (!memcmp(link[i].uuid, uuid, 16)) {
BT_DBG("%s, Device is being provisioned", __func__);
return -EALREADY;
}
}
}
/* Check if the device uuid matches configured value */
if (provisioner_dev_uuid_match(uuid)) {
BT_DBG("%s, Device uuid failed to match", __func__);
return -EIO;
if (is_unprov_dev_being_provision(uuid)) {
return -EALREADY;
}
/* Check if the device has already been provisioned */
@@ -570,74 +607,95 @@ static int provisioner_check_device_uuid(const u8_t uuid[16])
return 0;
}
static int provisioner_start_prov_device(bt_mesh_prov_bearer_t bearer, const u8_t uuid[16],
#if defined(CONFIG_BLE_MESH_PB_ADV)
static int provisioner_start_prov_pb_adv(const u8_t uuid[16],
const bt_mesh_addr_t *addr, u16_t oob_info)
{
u8_t zero[6] = {0};
int addr_cmp, i;
if ((bearer != BLE_MESH_PROV_ADV && bearer != BLE_MESH_PROV_GATT) || !uuid || !addr) {
if (!uuid || !addr) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
addr_cmp = memcmp(addr->val, zero, BLE_MESH_ADDR_LEN);
osi_mutex_lock(&prov_ctx.pb_adv_lock, OSI_MUTEX_MAX_TIMEOUT);
if (bearer == BLE_MESH_PROV_ADV) {
#if defined(CONFIG_BLE_MESH_PB_ADV)
for (i = 0; i < CONFIG_BLE_MESH_PBA_SAME_TIME; i++) {
if (!bt_mesh_atomic_test_bit(link[i].flags, LINK_ACTIVE) && !link[i].linking) {
memcpy(link[i].uuid, uuid, 16);
link[i].oob_info = oob_info;
if (addr_cmp && (addr->type <= BLE_ADDR_RANDOM)) {
link[i].addr.type = addr->type;
memcpy(link[i].addr.val, addr->val, BLE_MESH_ADDR_LEN);
}
prov_set_pb_index(i);
send_link_open();
/* If Provisioner sets LINK_ACTIVE flag once Link Open is sent, here
* we may not need to use linking flag (like PB-GATT connecting) to
* prevent the stored device info (UUID, oob_info) being replaced by
* other received unprovisioned device beacons.
* But if Provisioner sets LINK_ACTIVE flag after Link ACK is received,
* we need to use linking flag to prevent device info being replaced.
* Currently we set LINK_ACTIVE flag after sending Link Open.
*/
link[i].linking = true;
if (prov->prov_link_open) {
prov->prov_link_open(BLE_MESH_PROV_ADV);
}
return 0;
}
}
#endif
} else {
#if defined(CONFIG_BLE_MESH_PB_GATT)
for (i = CONFIG_BLE_MESH_PBA_SAME_TIME; i < BLE_MESH_PROV_SAME_TIME; i++) {
if (!bt_mesh_atomic_test_bit(link[i].flags, LINK_ACTIVE) && !link[i].connecting) {
memcpy(link[i].uuid, uuid, 16);
link[i].oob_info = oob_info;
if (addr_cmp && (addr->type <= BLE_ADDR_RANDOM)) {
link[i].addr.type = addr->type;
memcpy(link[i].addr.val, addr->val, BLE_MESH_ADDR_LEN);
}
if (bt_mesh_gattc_conn_create(&link[i].addr, BLE_MESH_UUID_MESH_PROV_VAL)) {
memset(link[i].uuid, 0, 16);
link[i].oob_info = 0x0;
memset(&link[i].addr, 0, sizeof(bt_mesh_addr_t));
return -EIO;
}
/* If creating connection successfully, set connecting flag to 1 */
link[i].connecting = true;
return 0;
}
}
#endif
if (is_unprov_dev_being_provision(uuid)) {
osi_mutex_unlock(&prov_ctx.pb_adv_lock);
return -EALREADY;
}
BT_ERR("%s, No link is available", __func__);
addr_cmp = memcmp(addr->val, zero, BLE_MESH_ADDR_LEN);
for (i = 0; i < CONFIG_BLE_MESH_PBA_SAME_TIME; i++) {
if (!bt_mesh_atomic_test_bit(link[i].flags, LINK_ACTIVE) && !link[i].linking) {
memcpy(link[i].uuid, uuid, 16);
link[i].oob_info = oob_info;
if (addr_cmp && (addr->type <= BLE_MESH_ADDR_RANDOM)) {
link[i].addr.type = addr->type;
memcpy(link[i].addr.val, addr->val, BLE_MESH_ADDR_LEN);
}
send_link_open(i);
osi_mutex_unlock(&prov_ctx.pb_adv_lock);
return 0;
}
}
BT_ERR("%s, No PB-ADV link is available", __func__);
osi_mutex_unlock(&prov_ctx.pb_adv_lock);
return -ENOMEM;
}
#endif /* CONFIG_BLE_MESH_PB_ADV */
#if defined(CONFIG_BLE_MESH_PB_GATT)
static int provisioner_start_prov_pb_gatt(const u8_t uuid[16],
const bt_mesh_addr_t *addr, u16_t oob_info)
{
u8_t zero[6] = {0};
int addr_cmp, i;
if (!uuid || !addr) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
osi_mutex_lock(&prov_ctx.pb_gatt_lock, OSI_MUTEX_MAX_TIMEOUT);
if (is_unprov_dev_being_provision(uuid)) {
osi_mutex_unlock(&prov_ctx.pb_gatt_lock);
return -EALREADY;
}
addr_cmp = memcmp(addr->val, zero, BLE_MESH_ADDR_LEN);
for (i = CONFIG_BLE_MESH_PBA_SAME_TIME; i < BLE_MESH_PROV_SAME_TIME; i++) {
if (!link[i].connecting && !bt_mesh_atomic_test_bit(link[i].flags, LINK_ACTIVE)) {
memcpy(link[i].uuid, uuid, 16);
link[i].oob_info = oob_info;
if (addr_cmp && (addr->type <= BLE_MESH_ADDR_RANDOM)) {
link[i].addr.type = addr->type;
memcpy(link[i].addr.val, addr->val, BLE_MESH_ADDR_LEN);
}
if (bt_mesh_gattc_conn_create(&link[i].addr, BLE_MESH_UUID_MESH_PROV_VAL)) {
memset(link[i].uuid, 0, 16);
link[i].oob_info = 0x0;
memset(&link[i].addr, 0, sizeof(bt_mesh_addr_t));
osi_mutex_unlock(&prov_ctx.pb_gatt_lock);
return -EIO;
}
/* If creating connection successfully, set connecting flag to 1 */
link[i].connecting = true;
osi_mutex_unlock(&prov_ctx.pb_gatt_lock);
return 0;
}
}
BT_ERR("%s, No PB-GATT link is available", __func__);
osi_mutex_unlock(&prov_ctx.pb_gatt_lock);
return -ENOMEM;
}
#endif /* CONFIG_BLE_MESH_PB_GATT */
int bt_mesh_provisioner_add_unprov_dev(struct bt_mesh_unprov_dev_add *add_dev, u8_t flags)
{
@@ -655,7 +713,7 @@ int bt_mesh_provisioner_add_unprov_dev(struct bt_mesh_unprov_dev_add *add_dev, u
uuid_cmp = memcmp(add_dev->uuid, zero, 16);
if (add_dev->bearer == 0x0 || ((uuid_cmp == 0) &&
((addr_cmp == 0) || add_dev->addr_type > BLE_ADDR_RANDOM))) {
((addr_cmp == 0) || add_dev->addr_type > BLE_MESH_ADDR_RANDOM))) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
@@ -672,7 +730,7 @@ int bt_mesh_provisioner_add_unprov_dev(struct bt_mesh_unprov_dev_add *add_dev, u
}
if ((add_dev->bearer & BLE_MESH_PROV_GATT) && (flags & START_PROV_NOW) &&
((addr_cmp == 0) || add_dev->addr_type > BLE_ADDR_RANDOM)) {
((addr_cmp == 0) || add_dev->addr_type > BLE_MESH_ADDR_RANDOM)) {
BT_ERR("%s, Invalid device address for PB-GATT", __func__);
return -EINVAL;
}
@@ -712,7 +770,7 @@ int bt_mesh_provisioner_add_unprov_dev(struct bt_mesh_unprov_dev_add *add_dev, u
if (unprov_dev[i].bearer) {
continue;
}
if (addr_cmp && (add_dev->addr_type <= BLE_ADDR_RANDOM)) {
if (addr_cmp && (add_dev->addr_type <= BLE_MESH_ADDR_RANDOM)) {
unprov_dev[i].addr.type = add_dev->addr_type;
memcpy(unprov_dev[i].addr.val, add_dev->addr, BLE_MESH_ADDR_LEN);
}
@@ -728,7 +786,7 @@ int bt_mesh_provisioner_add_unprov_dev(struct bt_mesh_unprov_dev_add *add_dev, u
for (i = 0; i < ARRAY_SIZE(unprov_dev); i++) {
if (unprov_dev[i].flags & FLUSHABLE_DEV) {
memset(&unprov_dev[i], 0, sizeof(struct unprov_dev_queue));
if (addr_cmp && (add_dev->addr_type <= BLE_ADDR_RANDOM)) {
if (addr_cmp && (add_dev->addr_type <= BLE_MESH_ADDR_RANDOM)) {
unprov_dev[i].addr.type = add_dev->addr_type;
memcpy(unprov_dev[i].addr.val, add_dev->addr, BLE_MESH_ADDR_LEN);
}
@@ -756,7 +814,7 @@ start:
return -EIO;
}
if ((err = provisioner_check_device_uuid(add_dev->uuid))) {
if ((err = provisioner_check_unprov_dev_info(add_dev->uuid))) {
return err;
}
@@ -766,7 +824,7 @@ start:
BT_WARN("%s, Current PB-ADV links reach max limit", __func__);
return -EIO;
}
if ((err = provisioner_start_prov_device(BLE_MESH_PROV_ADV,
if ((err = provisioner_start_prov_pb_adv(
add_dev->uuid, &add_addr, add_dev->oob_info))) {
return err;
}
@@ -777,7 +835,7 @@ start:
BT_WARN("%s, Current PB-GATT links reach max limit", __func__);
return -EIO;
}
if ((err = provisioner_start_prov_device(BLE_MESH_PROV_GATT,
if ((err = provisioner_start_prov_pb_gatt(
add_dev->uuid, &add_addr, add_dev->oob_info))) {
return err;
}
@@ -812,7 +870,7 @@ int bt_mesh_provisioner_delete_device(struct bt_mesh_device_delete *del_dev)
addr_cmp = memcmp(del_dev->addr, zero, BLE_MESH_ADDR_LEN);
uuid_cmp = memcmp(del_dev->uuid, zero, 16);
if ((uuid_cmp == 0) && ((addr_cmp == 0) || del_dev->addr_type > BLE_ADDR_RANDOM)) {
if ((uuid_cmp == 0) && ((addr_cmp == 0) || del_dev->addr_type > BLE_MESH_ADDR_RANDOM)) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
@@ -830,7 +888,7 @@ int bt_mesh_provisioner_delete_device(struct bt_mesh_device_delete *del_dev)
/* Second: find if the device is being provisioned */
for (i = 0; i < ARRAY_SIZE(link); i++) {
if (addr_cmp && (del_dev->addr_type <= BLE_ADDR_RANDOM)) {
if (addr_cmp && (del_dev->addr_type <= BLE_MESH_ADDR_RANDOM)) {
if (!memcmp(link[i].addr.val, del_dev->addr, BLE_MESH_ADDR_LEN) &&
link[i].addr.type == del_dev->addr_type) {
addr_match = true;
@@ -849,7 +907,7 @@ int bt_mesh_provisioner_delete_device(struct bt_mesh_device_delete *del_dev)
/* Third: find if the device is been provisioned */
for (i = 0; i < ARRAY_SIZE(prov_nodes); i++) {
if (addr_cmp && (del_dev->addr_type <= BLE_ADDR_RANDOM)) {
if (addr_cmp && (del_dev->addr_type <= BLE_MESH_ADDR_RANDOM)) {
if (!memcmp(prov_nodes[i].addr.val, del_dev->addr, BLE_MESH_ADDR_LEN) &&
prov_nodes[i].addr.type == del_dev->addr_type) {
addr_match = true;
@@ -943,8 +1001,8 @@ void provisioner_set_fast_prov_flag(bool flag)
u8_t provisioner_set_fast_prov_net_idx(const u8_t *net_key, u16_t net_idx)
{
fast_prov.net_idx = net_idx;
fast_prov.net_key = net_key;
fast_prov_info.net_idx = net_idx;
fast_prov_info.net_key = net_key;
if (!net_key) {
BT_WARN("%s, Wait for NetKey for fast provisioning", __func__);
@@ -956,7 +1014,7 @@ u8_t provisioner_set_fast_prov_net_idx(const u8_t *net_key, u16_t net_idx)
u16_t provisioner_get_fast_prov_net_idx(void)
{
return fast_prov.net_idx;
return fast_prov_info.net_idx;
}
u8_t bt_mesh_set_fast_prov_unicast_addr_range(u16_t min, u16_t max)
@@ -971,15 +1029,15 @@ u8_t bt_mesh_set_fast_prov_unicast_addr_range(u16_t min, u16_t max)
return 0x02; /* status: min is bigger than max */
}
if (min <= fast_prov.unicast_addr_max) {
if (min <= fast_prov_info.unicast_addr_max) {
BT_ERR("%s, Address overlap", __func__);
return 0x03; /* status: address overlaps with current value */
}
fast_prov.unicast_addr_min = min;
fast_prov.unicast_addr_max = max;
fast_prov_info.unicast_addr_min = min;
fast_prov_info.unicast_addr_max = max;
prov_ctx.current_addr = fast_prov.unicast_addr_min;
prov_ctx.current_addr = fast_prov_info.unicast_addr_min;
return 0x0; /* status: success */
}
@@ -987,8 +1045,8 @@ u8_t bt_mesh_set_fast_prov_unicast_addr_range(u16_t min, u16_t max)
void bt_mesh_set_fast_prov_flags_iv_index(u8_t flags, u32_t iv_index)
{
/* BIT0: Key Refreash flag, BIT1: IV Update flag */
fast_prov.flags = flags & BIT_MASK(2);
fast_prov.iv_index = iv_index;
fast_prov_info.flags = flags & BIT_MASK(2);
fast_prov_info.iv_index = iv_index;
}
#if defined(CONFIG_BLE_MESH_PB_ADV)
@@ -1207,16 +1265,16 @@ static int bearer_ctl_send(int i, u8_t op, void *data, u8_t data_len)
*/
if (op == LINK_CLOSE) {
u8_t reason = *(u8_t *)data;
link[i].link_close = (reason << 8 | BIT(0));
link[i].send_link_close = ((reason & BIT_MASK(2)) << 1) | BIT(0);
link[i].tx.trans_id = 0;
}
return 0;
}
static void send_link_open(void)
static void send_link_open(int i)
{
int i = prov_get_pb_index(), j;
int j;
/** Generate link ID, and may need to check if this id is
* currently being used, which may will not happen ever.
@@ -1244,9 +1302,23 @@ static void send_link_open(void)
bearer_ctl_send(i, LINK_OPEN, link[i].uuid, 16);
/* Set LINK_ACTIVE just to be in compatibility with current Zephyr code */
/* If Provisioner sets LINK_ACTIVE flag once Link Open is sent, we have
* no need to use linking flag (like PB-GATT connecting) to prevent the
* stored device info (UUID, oob_info) being replaced by other received
* unprovisioned device beacons.
* But if Provisioner sets LINK_ACTIVE flag after Link ACK is received,
* we need to use linking flag to prevent device info being replaced.
* Currently we set LINK_ACTIVE flag after sending Link Open.
*/
link[i].linking = true;
/* Set LINK_ACTIVE just to be in compatibility with current Zephyr code */
bt_mesh_atomic_set_bit(link[i].flags, LINK_ACTIVE);
if (prov->prov_link_open) {
prov->prov_link_open(BLE_MESH_PROV_ADV);
}
prov_ctx.pba_count++;
}
@@ -1265,11 +1337,10 @@ static inline u8_t next_transaction_id(void)
{
int i = prov_get_pb_index();
if (link[i].tx.trans_id < 0x7F) {
return link[i].tx.trans_id++;
if (link[i].tx.trans_id > 0x7F) {
link[i].tx.trans_id = 0x0;
}
return 0x0;
return link[i].tx.trans_id++;
}
static int prov_send_adv(struct net_buf_simple *msg)
@@ -1278,6 +1349,7 @@ static int prov_send_adv(struct net_buf_simple *msg)
u8_t seg_len, seg_id;
u8_t xact_id;
int i = prov_get_pb_index();
s32_t timeout = PROVISION_TIMEOUT;
BT_DBG("%s, len %u: %s", __func__, msg->len, bt_hex(msg->data, msg->len));
@@ -1297,6 +1369,8 @@ static int prov_send_adv(struct net_buf_simple *msg)
net_buf_add_u8(start, bt_mesh_fcs_calc(msg->data, msg->len));
link[i].tx.buf[0] = start;
/* Changed by Espressif, get message type */
link[i].tx_pdu_type = msg->data[0];
seg_len = MIN(msg->len, START_PAYLOAD_MAX);
BT_DBG("seg 0 len %u: %s", seg_len, bt_hex(msg->data, seg_len));
@@ -1333,8 +1407,13 @@ static int prov_send_adv(struct net_buf_simple *msg)
send_reliable(i);
#if defined(CONFIG_BLE_MESH_FAST_PROV)
if (link[i].tx_pdu_type >= PROV_DATA) {
timeout = K_SECONDS(60);
}
#endif
if (!bt_mesh_atomic_test_and_set_bit(link[i].flags, TIMEOUT_START)) {
k_delayed_work_submit(&link[i].timeout, PROVISION_TIMEOUT);
k_delayed_work_submit(&link[i].timeout, timeout);
}
return 0;
@@ -1816,36 +1895,38 @@ int bt_mesh_prov_set_oob_input_data(u8_t *val, u8_t link_idx, bool num_flag)
return 0;
}
// int bt_mesh_prov_set_oob_output_data(u8_t *num, u8_t size, bool num_flag, u8_t link_idx)
// {
// /** This function should be called in the prov_output_num
// * callback, after the data has been output by provisioner.
// * Parameter size is used to indicate the length of data
// * indicated by Pointer num, for example, if provisioner
// * output data is 12345678(decimal), the data in auth value
// * will be 0xBC614E.
// * Parameter num_flag is used to indicate whether the value
// * output by provisioner is number or string.
// */
// if (!link[link_idx].auth) {
// BT_ERR("%s, link auth is NULL", __func__);
// return -EINVAL;
// }
#if 0
int bt_mesh_prov_set_oob_output_data(u8_t *num, u8_t size, bool num_flag, u8_t link_idx)
{
/** This function should be called in the prov_output_num
* callback, after the data has been output by provisioner.
* Parameter size is used to indicate the length of data
* indicated by Pointer num, for example, if provisioner
* output data is 12345678(decimal), the data in auth value
* will be 0xBC614E.
* Parameter num_flag is used to indicate whether the value
* output by provisioner is number or string.
*/
if (!link[link_idx].auth) {
BT_ERR("%s, link auth is NULL", __func__);
return -EINVAL;
}
// if (num_flag) {
// /* Provisioner output number */
// memset(link[link_idx].auth, 0, 16);
// memcpy(link[link_idx].auth + 16 - size, num, size);
// } else {
// /* Provisioner output string */
// memset(link[link_idx].auth, 0, 16);
// memcpy(link[link_idx].auth, num, size);
// }
if (num_flag) {
/* Provisioner output number */
memset(link[link_idx].auth, 0, 16);
memcpy(link[link_idx].auth + 16 - size, num, size);
} else {
/* Provisioner output string */
memset(link[link_idx].auth, 0, 16);
memcpy(link[link_idx].auth, num, size);
}
// link[link_idx].expect = PROV_INPUT_COMPLETE;
link[link_idx].expect = PROV_INPUT_COMPLETE;
// return 0;
// }
return 0;
}
#endif
int bt_mesh_prov_read_oob_pub_key(u8_t link_idx, u8_t pub_key_x[32], u8_t pub_key_y[32])
{
@@ -2106,15 +2187,15 @@ static void send_prov_data(void)
* subnet will the device be provisioned later.
*/
if (FAST_PROV_FLAG_GET()) {
netkey = fast_prov.net_key;
netkey = fast_prov_info.net_key;
if (!netkey) {
BT_ERR("%s, Failed to get NetKey for fast provisioning", __func__);
goto fail;
}
memcpy(pdu, netkey, 16);
sys_put_be16(fast_prov.net_idx, &pdu[16]);
pdu[18] = fast_prov.flags;
sys_put_be32(fast_prov.iv_index, &pdu[19]);
sys_put_be16(fast_prov_info.net_idx, &pdu[16]);
pdu[18] = fast_prov_info.flags;
sys_put_be32(fast_prov_info.iv_index, &pdu[19]);
} else {
netkey = provisioner_net_key_get(prov_ctx.curr_net_idx);
if (!netkey) {
@@ -2161,7 +2242,7 @@ static void send_prov_data(void)
}
}
max_addr = FAST_PROV_FLAG_GET() ? fast_prov.unicast_addr_max : 0x7FFF;
max_addr = FAST_PROV_FLAG_GET() ? fast_prov_info.unicast_addr_max : 0x7FFF;
if (!already_flag) {
/* If this device to be provisioned is a new device */
@@ -2220,8 +2301,8 @@ static void send_prov_data(void)
}
if (FAST_PROV_FLAG_GET()) {
link[i].ki_flags = fast_prov.flags;
link[i].iv_index = fast_prov.iv_index;
link[i].ki_flags = fast_prov_info.flags;
link[i].iv_index = fast_prov_info.iv_index;
} else {
link[i].ki_flags = prov_ctx.curr_flags;
link[i].iv_index = prov_ctx.curr_iv_index;
@@ -2317,7 +2398,7 @@ static void prov_complete(const u8_t *data)
prov_nodes[j].element_num = link[i].element_num;
prov_nodes[j].unicast_addr = link[i].unicast_addr;
if (FAST_PROV_FLAG_GET()) {
prov_nodes[j].net_idx = fast_prov.net_idx;
prov_nodes[j].net_idx = fast_prov_info.net_idx;
} else {
prov_nodes[j].net_idx = prov_ctx.curr_net_idx;
}
@@ -2422,6 +2503,7 @@ static void prov_timeout(struct k_work *work)
#if defined(CONFIG_BLE_MESH_PB_ADV)
static void prov_retransmit(struct k_work *work)
{
s64_t timeout = TRANSACTION_TIMEOUT;
int id = work->index;
BT_DBG("%s", __func__);
@@ -2431,18 +2513,25 @@ static void prov_retransmit(struct k_work *work)
return;
}
if (k_uptime_get() - link[id].tx.start > TRANSACTION_TIMEOUT) {
BT_WARN("%s, Timeout, giving up transaction", __func__);
close_link(id, CLOSE_REASON_TIMEOUT);
#if defined(CONFIG_BLE_MESH_FAST_PROV)
if (link[id].tx_pdu_type >= PROV_DATA) {
timeout = K_SECONDS(30);
}
#endif
if (k_uptime_get() - link[id].tx.start > timeout) {
BT_WARN("Provisioner timeout, giving up transaction");
reset_link(id, CLOSE_REASON_TIMEOUT);
return;
}
if (link[id].link_close & BIT(0)) {
if (link[id].link_close >> 1 & 0x02) {
reset_link(id, link[id].link_close >> 8);
if (link[id].send_link_close & BIT(0)) {
u8_t reason = (link[id].send_link_close >> 1) & BIT_MASK(2);
u16_t count = (link[id].send_link_close >> 3);
if (count >= 2) {
reset_link(id, reason);
return;
}
link[id].link_close += BIT(1);
link[id].send_link_close += BIT(3);
}
for (int i = 0; i < ARRAY_SIZE(link[id].tx.buf); i++) {
@@ -2490,10 +2579,6 @@ static void link_ack(struct prov_rx *rx, struct net_buf_simple *buf)
return;
}
/** After received link_ack, we don't call prov_clear_tx() to
* cancel retransmit timer, because retransmit timer will be
* cancelled after we send the provisioning invite pdu.
*/
send_invite();
}
@@ -2702,7 +2787,7 @@ static void gen_prov_start(struct prov_rx *rx, struct net_buf_simple *buf)
if (link[i].rx.buf->len > link[i].rx.buf->size) {
BT_ERR("%s, Too large provisioning PDU (%u bytes)", __func__, link[i].rx.buf->len);
close_link(i, CLOSE_REASON_FAILED);
// close_link(i, CLOSE_REASON_FAILED);
return;
}
@@ -3024,45 +3109,43 @@ int provisioner_prov_init(const struct bt_mesh_prov *prov_info)
prov_ctx.curr_flags = prov->flags;
prov_ctx.curr_iv_index = prov->iv_index;
osi_mutex_new(&prov_ctx.pb_adv_lock);
osi_mutex_new(&prov_ctx.pb_gatt_lock);
return 0;
}
static int provisioner_notify_unprov_adv_pkt(bt_mesh_prov_bearer_t bearer, const u8_t uuid[16],
const bt_mesh_addr_t *addr, u16_t oob_info)
static bool is_unprov_dev_info_callback_to_app(bt_mesh_prov_bearer_t bearer,
const u8_t uuid[16], const bt_mesh_addr_t *addr, u16_t oob_info)
{
u8_t adv_type;
int index;
if ((bearer != BLE_MESH_PROV_ADV && bearer != BLE_MESH_PROV_GATT) || !uuid || !addr) {
BT_ERR("%s, invalid parameter", __func__);
return -EINVAL;
}
adv_type = (bearer == BLE_MESH_PROV_ADV) ? BLE_MESH_ADV_NONCONN_IND : BLE_MESH_ADV_IND;
if (prov_ctx.prov_after_match == false) {
if (provisioner_dev_find(addr, uuid, &index)) {
BT_DBG("%s, Device is not found, notify to upper layer", __func__);
BT_DBG("%s, Device is not in queue, notify to upper layer", __func__);
u8_t adv_type = (bearer == BLE_MESH_PROV_ADV) ?
BLE_MESH_ADV_NONCONN_IND : BLE_MESH_ADV_IND;
if (notify_unprov_adv_pkt_cb) {
notify_unprov_adv_pkt_cb(addr->val, addr->type, adv_type, uuid, oob_info, bearer);
}
return -EALREADY;
return true;
}
if (!(unprov_dev[index].bearer & bearer)) {
BT_DBG("%s, Not support PB-%s", __func__, (bearer == BLE_MESH_PROV_ADV) ? "ADV" : "GATT");
return -EIO;
BT_WARN("Device in queue not support PB-%s",
(bearer == BLE_MESH_PROV_ADV) ? "ADV" : "GATT");
return true;
}
}
return 0;
return false;
}
void provisioner_unprov_beacon_recv(struct net_buf_simple *buf)
{
#if defined(CONFIG_BLE_MESH_PB_ADV)
const bt_mesh_addr_t *addr = NULL;
u8_t *uuid = NULL;
const u8_t *uuid = NULL;
u16_t oob_info;
if (buf->len != 0x12 && buf->len != 0x16) {
@@ -3081,16 +3164,16 @@ void provisioner_unprov_beacon_recv(struct net_buf_simple *buf)
/* Mesh beacon uses big-endian to send beacon data */
oob_info = net_buf_simple_pull_be16(buf);
if (provisioner_check_device_uuid(uuid)) {
if (provisioner_check_unprov_dev_info(uuid)) {
return;
}
if (provisioner_notify_unprov_adv_pkt(
if (is_unprov_dev_info_callback_to_app(
BLE_MESH_PROV_ADV, uuid, addr, oob_info)) {
return;
}
provisioner_start_prov_device(BLE_MESH_PROV_ADV, uuid, addr, oob_info);
provisioner_start_prov_pb_adv(uuid, addr, oob_info);
#endif /* CONFIG_BLE_MESH_PB_ADV */
}
@@ -3175,7 +3258,7 @@ void provisioner_srv_data_recv(struct net_buf_simple *buf, const bt_mesh_addr_t
static void provisioner_prov_srv_data_recv(struct net_buf_simple *buf, const bt_mesh_addr_t *addr)
{
#if defined(CONFIG_BLE_MESH_PB_GATT)
u8_t *uuid = NULL;
const u8_t *uuid = NULL;
u16_t oob_info;
if (prov_ctx.pbg_count == CONFIG_BLE_MESH_PBG_SAME_TIME) {
@@ -3188,11 +3271,11 @@ static void provisioner_prov_srv_data_recv(struct net_buf_simple *buf, const bt_
/* Mesh beacon uses big-endian to send beacon data */
oob_info = net_buf_simple_pull_be16(buf);
if (provisioner_check_device_uuid(uuid)) {
if (provisioner_check_unprov_dev_info(uuid)) {
return;
}
if (provisioner_notify_unprov_adv_pkt(
if (is_unprov_dev_info_callback_to_app(
BLE_MESH_PROV_GATT, uuid, addr, oob_info)) {
return;
}
@@ -3209,7 +3292,7 @@ static void provisioner_prov_srv_data_recv(struct net_buf_simple *buf, const bt_
* Use connecting flag to prevent if two devices's adv pkts are both received,
* the previous one info will be replaced by the second one.
*/
provisioner_start_prov_device(BLE_MESH_PROV_GATT, uuid, addr, oob_info);
provisioner_start_prov_pb_gatt(uuid, addr, oob_info);
#endif /* CONFIG_BLE_MESH_PB_GATT */
}

View File

@@ -1,11 +1,16 @@
# Override some defaults so BT stack is enabled
# by default in this example
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y
CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY=
CONFIG_BTDM_CONTROLLER_MODE_BTDM=
CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=n
CONFIG_BLE_SCAN_DUPLICATE=y
CONFIG_SCAN_DUPLICATE_TYPE=2
CONFIG_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BLE_MESH_SCAN_DUPLICATE_EN=y
CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BTDM_CONTROLLER_FULL_SCAN_SUPPORTED=y
CONFIG_GATTS_ENABLE=y
CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL=y
CONFIG_BLE_MESH=y

View File

@@ -4,11 +4,16 @@ CONFIG_CONSOLE_UART_BAUDRATE=921600
CONFIG_ESPTOOLPY_BAUD_921600B=y
CONFIG_MONITOR_BAUD_921600B=y
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y
CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY=
CONFIG_BTDM_CONTROLLER_MODE_BTDM=
CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=n
CONFIG_BLE_SCAN_DUPLICATE=y
CONFIG_SCAN_DUPLICATE_TYPE=2
CONFIG_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BLE_MESH_SCAN_DUPLICATE_EN=y
CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BTDM_CONTROLLER_FULL_SCAN_SUPPORTED=y
CONFIG_GATTS_ENABLE=y
CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL=y
CONFIG_BLE_MESH=y

View File

@@ -1,11 +1,16 @@
# Override some defaults so BT stack is enabled
# by default in this example
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y
CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY=
CONFIG_BTDM_CONTROLLER_MODE_BTDM=
CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=n
CONFIG_BLE_SCAN_DUPLICATE=y
CONFIG_SCAN_DUPLICATE_TYPE=2
CONFIG_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BLE_MESH_SCAN_DUPLICATE_EN=y
CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BTDM_CONTROLLER_FULL_SCAN_SUPPORTED=y
CONFIG_BLE_MESH=y
CONFIG_BLE_MESH_USE_DUPLICATE_SCAN=y
CONFIG_BLE_MESH_PROV=y

View File

@@ -1,11 +1,16 @@
# Override some defaults so BT stack is enabled
# by default in this example
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y
CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY=
CONFIG_BTDM_CONTROLLER_MODE_BTDM=
CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=n
CONFIG_BLE_SCAN_DUPLICATE=y
CONFIG_SCAN_DUPLICATE_TYPE=2
CONFIG_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BLE_MESH_SCAN_DUPLICATE_EN=y
CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BTDM_CONTROLLER_FULL_SCAN_SUPPORTED=y
CONFIG_BLE_MESH=y
CONFIG_BLE_MESH_USE_DUPLICATE_SCAN=y
CONFIG_BLE_MESH_PROV=y

View File

@@ -113,10 +113,12 @@ static esp_ble_mesh_model_pub_t onoff_pub = {
};
static esp_ble_mesh_model_op_t fast_prov_srv_op[] = {
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET, 3, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD, 16, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR, 2, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET, 0, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET, 3, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD, 16, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR, 2, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET, 0, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_ADD, 2, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_DELETE, 2, NULL },
ESP_BLE_MESH_MODEL_OP_END,
};
@@ -179,7 +181,6 @@ static void gen_onoff_get_handler(esp_ble_mesh_model_t *model,
}
send_data = led->current;
ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current);
/* Sends Generic OnOff Status as a reponse to Generic OnOff Get */
err = esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
@@ -210,12 +211,7 @@ static void gen_onoff_set_unack_handler(esp_ble_mesh_model_t *model,
}
led->current = data[0];
ESP_LOGI(TAG, "addr 0x%02x onoff 0x%02x", model->element->element_addr, led->current);
if (led_action_task_post(led, portMAX_DELAY) != ESP_OK) {
ESP_LOGE(TAG, "%s: Failed to post led action to queue", __func__);
return;
}
gpio_set_level(led->pin, led->current);
/* When the node receives the first Generic OnOff Get/Set/Set Unack message, it will
* start the timer used to disable fast provisioning functionality.
@@ -268,6 +264,9 @@ static void provisioner_prov_complete(int node_idx, const uint8_t uuid[16], uint
fast_prov_server.prov_node_cnt++;
}
ESP_LOG_BUFFER_HEX("Device uuid", uuid + 2, 6);
ESP_LOGI(TAG, "Unicast address 0x%04x", unicast_addr);
/* Sets node info */
err = example_store_node_info(uuid, unicast_addr, element_num, net_idx,
fast_prov_server.app_idx, LED_OFF);
@@ -295,12 +294,13 @@ static void provisioner_prov_complete(int node_idx, const uint8_t uuid[16], uint
ESP_LOGE(TAG, "%s: Failed to store node address 0x%04x", __func__, unicast_addr);
return;
}
if (fast_prov_server.node_addr_cnt <= fast_prov_server.max_node_num) {
if (bt_mesh_atomic_test_and_clear_bit(fast_prov_server.srv_flags, SEND_ALL_NODE_ADDR_START)) {
k_delayed_work_cancel(&fast_prov_server.send_all_node_addr_timer);
if (fast_prov_server.node_addr_cnt != FAST_PROV_NODE_COUNT_MIN &&
fast_prov_server.node_addr_cnt <= fast_prov_server.max_node_num) {
if (bt_mesh_atomic_test_and_clear_bit(fast_prov_server.srv_flags, GATT_PROXY_ENABLE_START)) {
k_delayed_work_cancel(&fast_prov_server.gatt_proxy_enable_timer);
}
if (!bt_mesh_atomic_test_and_set_bit(fast_prov_server.srv_flags, SEND_ALL_NODE_ADDR_START)) {
k_delayed_work_submit(&fast_prov_server.send_all_node_addr_timer, SEND_ALL_NODE_ADDR_TIMEOUT);
if (!bt_mesh_atomic_test_and_set_bit(fast_prov_server.srv_flags, GATT_PROXY_ENABLE_START)) {
k_delayed_work_submit(&fast_prov_server.gatt_proxy_enable_timer, GATT_PROXY_ENABLE_TIMEOUT);
}
}
} else {
@@ -503,7 +503,9 @@ static void example_ble_mesh_custom_model_cb(esp_ble_mesh_model_cb_event_t event
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET:
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD:
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR:
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET: {
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET:
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_ADD:
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_DELETE: {
ESP_LOGI(TAG, "%s: Fast prov server receives msg, opcode 0x%04x", __func__, opcode);
struct net_buf_simple buf = {
.len = param->model_operation.length,

View File

@@ -14,27 +14,18 @@
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "driver/gpio.h"
#include "board.h"
#include "esp_fast_prov_server_model.h"
#include "esp_fast_prov_common.h"
#define TAG "BOARD"
extern example_fast_prov_server_t fast_prov_server;
struct _led_state led_state[3] = {
{ LED_OFF, LED_OFF, LED_R, "red" },
{ LED_OFF, LED_OFF, LED_G, "green" },
{ LED_OFF, LED_OFF, LED_B, "blue" },
};
static xQueueHandle led_action_queue;
void board_output_number(esp_ble_mesh_output_action_t action, uint32_t number)
{
ESP_LOGI(TAG, "Board output number %d", number);
@@ -74,48 +65,8 @@ static void board_led_init(void)
}
}
static void led_action_thread(void *arg)
{
struct _led_state led = {0};
while (1) {
if (xQueueReceive(led_action_queue, &led, (portTickType)portMAX_DELAY)) {
ESP_LOGI(TAG, "%s: pin 0x%04x onoff 0x%02x", __func__, led.pin, led.current);
/* If the node is controlled by phone, add a delay when turn on/off led */
if (fast_prov_server.primary_role == true) {
vTaskDelay(50 / portTICK_PERIOD_MS);
}
gpio_set_level(led.pin, led.current);
}
}
}
esp_err_t led_action_task_post(struct _led_state *msg, uint32_t timeout)
{
if (xQueueSend(led_action_queue, msg, timeout) != pdTRUE) {
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t board_init(void)
{
BaseType_t ret;
board_led_init();
led_action_queue = xQueueCreate(60, sizeof(struct _led_state));
if (!led_action_queue) {
ESP_LOGE(TAG, "%s: Failed to create led action queue", __func__);
return ESP_FAIL;
}
ret = xTaskCreate(led_action_thread, "led_action_thread", 4096, NULL, 5, NULL);
if (ret == pdFAIL) {
ESP_LOGE(TAG, "%s: Failed to create led_action_thread", __func__);
vQueueDelete(led_action_queue);
return ESP_FAIL;
}
return ESP_OK;
}

View File

@@ -41,8 +41,6 @@ void board_prov_complete(void);
void board_led_operation(uint8_t pin, uint8_t onoff);
esp_err_t led_action_task_post(struct _led_state *msg, uint32_t timeout);
esp_err_t board_init(void);
#endif

View File

@@ -1,11 +1,16 @@
# Override some defaults so BT stack is enabled
# by default in this example
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y
CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY=
CONFIG_BTDM_CONTROLLER_MODE_BTDM=
CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=n
CONFIG_BLE_SCAN_DUPLICATE=y
CONFIG_SCAN_DUPLICATE_TYPE=2
CONFIG_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BLE_MESH_SCAN_DUPLICATE_EN=y
CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BTDM_CONTROLLER_FULL_SCAN_SUPPORTED=y
CONFIG_GATTS_ENABLE=y
CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL=y
CONFIG_BLE_MESH=y
@@ -23,6 +28,10 @@ CONFIG_BLE_MESH_PROVISIONER_SUBNET_COUNT=3
CONFIG_BLE_MESH_PROVISIONER_APP_KEY_COUNT=9
CONFIG_BLE_MESH_PB_ADV=y
CONFIG_BLE_MESH_NET_BUF_POOL_USAGE=y
CONFIG_BLE_MESH_SUBNET_COUNT=2
CONFIG_BLE_MESH_APP_KEY_COUNT=3
CONFIG_BLE_MESH_MODEL_KEY_COUNT=3
CONFIG_BLE_MESH_MODEL_GROUP_COUNT=3
CONFIG_BLE_MESH_PB_GATT=y
CONFIG_BLE_MESH_GATT_PROXY=y
CONFIG_BLE_MESH_RELAY=y

View File

@@ -55,7 +55,7 @@ typedef struct {
uint8_t state; /* Fast prov state -> 0: idle, 1: pend, 2: active */
struct k_delayed_work disable_fast_prov_timer; /* Used to disable fast provisioning */
struct k_delayed_work send_all_node_addr_timer; /* Used to send all node addresses to top provisioner(e.g. phone) */
struct k_delayed_work gatt_proxy_enable_timer; /* Used to Mesh GATT Proxy functionality */
} __attribute__((packed)) example_fast_prov_server_t;
```
@@ -70,7 +70,7 @@ In the struct, there are three variables that are related to roles and states, w
| ---------------------|------------------------- |
| `primary_role` | Provisioner identity |
| `state` | Fast provisioner state (0: idle, 1: pend, 2: active) |
| `srv_flags` | Flags (`DISABLE_FAST_PROV_START`,`SEND_ALL_NODE_ADDR_START`,`RELAY_PROXY_DISABLED`,`SRV_MAX_FLAGS`) |
| `srv_flags` | Flags (`DISABLE_FAST_PROV_START`,`GATT_PROXY_ENABLE_START`,`RELAY_PROXY_DISABLED`,`SRV_MAX_FLAGS`) |
Among which, there are four roles in this demo (`primary_role`):
@@ -120,7 +120,7 @@ The node's cache data, which are described in the following table, is sent by th
There are two timers in this demo, which are:
1. `send_all_node_addr_timer` is used to collect the addresses of all nodes.
1. `gatt_proxy_enable_timer` is used to enable Mesh GATT Proxy functionality.
* The timer starts or resets and starts when a Temporary Provisioner provisions an unprovisioned device.
* The Temporary Provisioner will send a message (Address information) to the Primary Provisioner.
2. `disable_fast_prov_timer` is used to disable the provisioning capabilities.
@@ -131,7 +131,7 @@ The variables that are related to these two timers are described below:
| Variable Name |Description |
| ----------------------|------------------------- |
| `disable_fast_prov_timer` |Used to disable fast provisioning|
| `send_all_node_addr_timer` |Used to send all node addresses to top provisioner|
| `gatt_proxy_enable_timer` |Used to enable Mesh GATT Proxy functionality|
### 2.2 Model Definition

View File

@@ -1,11 +1,16 @@
# Override some defaults so BT stack is enabled
# by default in this example
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y
CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY=
CONFIG_BTDM_CONTROLLER_MODE_BTDM=
CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=n
CONFIG_BLE_SCAN_DUPLICATE=y
CONFIG_SCAN_DUPLICATE_TYPE=2
CONFIG_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BLE_MESH_SCAN_DUPLICATE_EN=y
CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BTDM_CONTROLLER_FULL_SCAN_SUPPORTED=y
CONFIG_GATTS_ENABLE=y
CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL=y
CONFIG_BLE_MESH=y

View File

@@ -1,11 +1,16 @@
# Override some defaults so BT stack is enabled
# by default in this example
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y
CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY=
CONFIG_BTDM_CONTROLLER_MODE_BTDM=
CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=n
CONFIG_BLE_SCAN_DUPLICATE=y
CONFIG_SCAN_DUPLICATE_TYPE=2
CONFIG_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BLE_MESH_SCAN_DUPLICATE_EN=y
CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BTDM_CONTROLLER_FULL_SCAN_SUPPORTED=y
CONFIG_BLE_MESH=y
CONFIG_BLE_MESH_USE_DUPLICATE_SCAN=y
CONFIG_BLE_MESH_PROV=y

View File

@@ -41,6 +41,10 @@
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET ESP_BLE_MESH_MODEL_OP_3(0x06, CID_ESP)
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_STATUS ESP_BLE_MESH_MODEL_OP_3(0x07, CID_ESP)
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_ADD ESP_BLE_MESH_MODEL_OP_3(0x08, CID_ESP)
#define ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_DELETE ESP_BLE_MESH_MODEL_OP_3(0x09, CID_ESP)
typedef struct {
uint16_t net_idx;
uint16_t app_idx;

View File

@@ -289,6 +289,40 @@ esp_err_t example_add_fast_prov_group_address(uint16_t model_id, uint16_t group_
return ESP_OK;
}
esp_err_t example_delete_fast_prov_group_address(uint16_t model_id, uint16_t group_addr)
{
const esp_ble_mesh_comp_t *comp = NULL;
esp_ble_mesh_elem_t *element = NULL;
esp_ble_mesh_model_t *model = NULL;
int i, j;
if (!ESP_BLE_MESH_ADDR_IS_GROUP(group_addr)) {
return ESP_ERR_INVALID_ARG;
}
comp = esp_ble_mesh_get_composition_data();
if (comp == NULL) {
return ESP_FAIL;
}
for (i = 0; i < comp->element_count; i++) {
element = &comp->elements[i];
model = esp_ble_mesh_find_sig_model(element, model_id);
if (model == NULL) {
continue;
}
for (j = 0; j < ARRAY_SIZE(model->groups); j++) {
if (model->groups[j] == group_addr) {
model->groups[j] = ESP_BLE_MESH_ADDR_UNASSIGNED;
break;
}
}
}
return ESP_OK;
}
esp_err_t example_send_config_appkey_add(esp_ble_mesh_model_t *model,
example_msg_common_info_t *info,
esp_ble_mesh_cfg_app_key_add_t *add_key)

View File

@@ -34,6 +34,8 @@ esp_err_t example_handle_config_app_key_add_evt(uint16_t app_idx);
esp_err_t example_add_fast_prov_group_address(uint16_t model_id, uint16_t group_addr);
esp_err_t example_delete_fast_prov_group_address(uint16_t model_id, uint16_t group_addr);
esp_err_t example_send_config_appkey_add(esp_ble_mesh_model_t *model,
example_msg_common_info_t *info,
esp_ble_mesh_cfg_app_key_add_t *add_key);

View File

@@ -28,7 +28,7 @@
#define TAG "FAST_PROV_SERVER"
/* Array used to store all node addresses */
static uint16_t all_node_addr[100];
static uint16_t all_node_addr[120];
static uint16_t all_node_addr_cnt;
esp_err_t example_store_remote_node_address(uint16_t node_addr)
@@ -57,6 +57,20 @@ esp_err_t example_store_remote_node_address(uint16_t node_addr)
return ESP_FAIL;
}
esp_ble_mesh_cfg_srv_t *get_cfg_srv_user_data(void)
{
esp_ble_mesh_model_t *model = NULL;
model = example_find_model(esp_ble_mesh_get_primary_element_address(),
ESP_BLE_MESH_MODEL_ID_CONFIG_SRV, CID_NVAL);
if (!model) {
ESP_LOGE(TAG, "%s: Failed to get config server model", __func__);
return NULL;
}
return (esp_ble_mesh_cfg_srv_t *)(model->user_data);
}
/* Timeout handler for disable_fast_prov_timer */
static void disable_fast_prov_cb(struct k_work *work)
{
@@ -74,41 +88,20 @@ static void disable_fast_prov_cb(struct k_work *work)
}
}
static esp_ble_mesh_cfg_srv_t *get_cfg_srv_user_data(void)
/* Timeout handler for gatt_proxy_enable_timer */
static void enable_gatt_proxy_cb(struct k_work *work)
{
esp_ble_mesh_model_t *model = NULL;
example_fast_prov_server_t *srv = NULL;
model = example_find_model(esp_ble_mesh_get_primary_element_address(),
ESP_BLE_MESH_MODEL_ID_CONFIG_SRV, CID_NVAL);
if (!model) {
ESP_LOGE(TAG, "%s: Failed to get config server model", __func__);
return NULL;
}
return (esp_ble_mesh_cfg_srv_t *)(model->user_data);
}
/* Timeout handler for send_all_node_addr_timer */
static void example_send_all_node_addr(struct k_work *work)
{
example_fast_prov_server_t *fast_prov_srv_data = NULL;
esp_ble_mesh_cfg_srv_t *cfg_srv_data = NULL;
fast_prov_srv_data = CONTAINER_OF(work, example_fast_prov_server_t, send_all_node_addr_timer.work);
if (!fast_prov_srv_data) {
srv = CONTAINER_OF(work, example_fast_prov_server_t, gatt_proxy_enable_timer.work);
if (!srv) {
ESP_LOGE(TAG, "%s: Failed to get fast prov server model user_data", __func__);
return;
}
cfg_srv_data = get_cfg_srv_user_data();
if (!cfg_srv_data) {
ESP_LOGE(TAG, "%s: Failed to get config server model user_data", __func__);
return;
}
if (bt_mesh_atomic_test_and_clear_bit(fast_prov_srv_data->srv_flags, RELAY_PROXY_DISABLED)) {
if (bt_mesh_atomic_test_and_clear_bit(srv->srv_flags, RELAY_PROXY_DISABLED)) {
ESP_LOGI(TAG, "%s: Enable BLE Mesh Relay & GATT Proxy", __func__);
cfg_srv_data->relay = ESP_BLE_MESH_RELAY_ENABLED;
/* For Primary Provisioner, Relay will not be enabled */
esp_ble_mesh_proxy_gatt_enable();
esp_ble_mesh_proxy_identity_enable();
}
@@ -125,22 +118,18 @@ static void example_free_set_info(example_fast_prov_server_t *srv)
}
esp_err_t example_fast_prov_server_recv_msg(esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx,
struct net_buf_simple *buf)
esp_ble_mesh_msg_ctx_t *ctx, struct net_buf_simple *buf)
{
example_fast_prov_server_t *srv = NULL;
struct net_buf_simple *msg = NULL;
uint32_t opcode;
uint32_t opcode = 0;
esp_err_t err;
if (!model || !ctx || !buf) {
if (!model || !model->user_data || !ctx || !buf) {
return ESP_ERR_INVALID_ARG;
}
srv = (example_fast_prov_server_t *)model->user_data;
if (!srv) {
return ESP_FAIL;
}
ESP_LOG_BUFFER_HEX("fast prov server recv", buf->data, buf->len);
@@ -280,6 +269,10 @@ esp_err_t example_fast_prov_server_recv_msg(esp_ble_mesh_model_t *model,
return ESP_FAIL;
}
if (unicast_max < unicast_min + srv->max_node_num - 1) {
srv->max_node_num = unicast_max - unicast_min + 1;
}
srv->set_info->set_succeed = false;
srv->set_info->node_addr_cnt = node_addr_cnt;
srv->set_info->unicast_min = unicast_min;
@@ -294,7 +287,7 @@ esp_err_t example_fast_prov_server_recv_msg(esp_ble_mesh_model_t *model,
esp_ble_mesh_fast_prov_info_t info_set = {
.unicast_min = unicast_min,
.unicast_max = unicast_max,
.unicast_max = unicast_min + srv->max_node_num - 1,
.flags = flags,
.iv_index = iv_index,
.net_idx = net_idx,
@@ -340,14 +333,13 @@ esp_err_t example_fast_prov_server_recv_msg(esp_ble_mesh_model_t *model,
return ESP_FAIL;
}
if (bt_mesh_atomic_test_and_clear_bit(srv->srv_flags, SEND_ALL_NODE_ADDR_START)) {
k_delayed_work_cancel(&srv->send_all_node_addr_timer);
if (bt_mesh_atomic_test_and_clear_bit(srv->srv_flags, GATT_PROXY_ENABLE_START)) {
k_delayed_work_cancel(&srv->gatt_proxy_enable_timer);
}
uint16_t length = buf->len;
for (int i = 0; i < (length >> 1); i++) {
for (; buf->len; ) {
uint16_t node_addr = net_buf_simple_pull_le16(buf);
ESP_LOGI(TAG, "node address %d: 0x%04x", i, node_addr);
ESP_LOGI(TAG, "Node address: 0x%04x", node_addr);
err = example_store_remote_node_address(node_addr);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: Failed to store node address 0x%04x", __func__, node_addr);
@@ -374,6 +366,46 @@ esp_err_t example_fast_prov_server_recv_msg(esp_ble_mesh_model_t *model,
opcode = ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_STATUS;
break;
}
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_ADD: {
uint16_t own_addr = esp_ble_mesh_get_primary_element_address();
uint16_t group_addr = net_buf_simple_pull_le16(buf);
ESP_LOGI(TAG, "%s, group address 0x%04x", __func__, group_addr);
if (!ESP_BLE_MESH_ADDR_IS_GROUP(group_addr)) {
return ESP_FAIL;
}
for (; buf->len; ) {
uint16_t dst = net_buf_simple_pull_le16(buf);
ESP_LOGI(TAG, "%s, dst 0x%04x, own address 0x%04x", __func__, dst, own_addr);
if (dst == own_addr) {
err = example_add_fast_prov_group_address(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, group_addr);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: Failed to add group address 0x%04x", __func__, group_addr);
}
return err;
}
}
return ESP_OK;
}
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_DELETE: {
uint16_t own_addr = esp_ble_mesh_get_primary_element_address();
uint16_t group_addr = net_buf_simple_pull_le16(buf);
ESP_LOGI(TAG, "%s, group address 0x%04x", __func__, group_addr);
if (!ESP_BLE_MESH_ADDR_IS_GROUP(group_addr)) {
return ESP_FAIL;
}
for (; buf->len; ) {
uint16_t dst = net_buf_simple_pull_le16(buf);
ESP_LOGI(TAG, "%s, dst 0x%04x, own address 0x%04x", __func__, dst, own_addr);
if (dst == own_addr) {
err = example_delete_fast_prov_group_address(ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV, group_addr);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: Failed to delete group address 0x%04x", __func__, group_addr);
}
return err;
}
}
return ESP_OK;
}
default:
ESP_LOGW(TAG, "%s: Not a Fast Prov Client message opcode", __func__);
return ESP_FAIL;
@@ -396,12 +428,12 @@ esp_err_t example_handle_fast_prov_info_set_comp_evt(esp_ble_mesh_model_t *model
struct net_buf_simple *msg = NULL;
esp_err_t err;
if (!model) {
if (!model || !model->user_data) {
return ESP_ERR_INVALID_ARG;
}
srv = (example_fast_prov_server_t *)model->user_data;
if (!srv || !srv->set_info) {
if (!srv->set_info) {
return ESP_FAIL;
}
@@ -416,9 +448,6 @@ esp_err_t example_handle_fast_prov_info_set_comp_evt(esp_ble_mesh_model_t *model
}
/* Update Fast Prov Server Model user_data */
if (srv->set_info->unicast_max < srv->set_info->unicast_min + srv->max_node_num - 1) {
srv->max_node_num = srv->set_info->unicast_max - srv->set_info->unicast_min + 1;
}
srv->unicast_min = srv->set_info->unicast_min + srv->max_node_num;
srv->unicast_max = srv->set_info->unicast_max;
srv->unicast_cur = srv->set_info->unicast_min + srv->max_node_num;
@@ -476,29 +505,48 @@ send:
esp_err_t example_handle_fast_prov_action_set_comp_evt(esp_ble_mesh_model_t *model, uint8_t status_action)
{
example_fast_prov_server_t *srv = model->user_data;
example_fast_prov_server_t *srv = NULL;
struct net_buf_simple *msg = NULL;
uint32_t opcode;
esp_err_t err;
if (!model || !model->user_data) {
return ESP_ERR_INVALID_ARG;
}
srv = (example_fast_prov_server_t *)model->user_data;
msg = bt_mesh_alloc_buf(9);
net_buf_simple_init(msg, 0);
switch (srv->state) {
case STATE_IDLE: { /* fast prov info set (enter) */
case STATE_IDLE: { /* fast prov info set (enter) */
const uint8_t zero[6] = {0};
net_buf_simple_add_le16(msg, 0x7f);
net_buf_simple_add_mem(msg, zero, 6);
net_buf_simple_add_u8(msg, status_action);
opcode = ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_STATUS;
/**
* Disable relay should not have a impact on Mesh Proxy PDU, and
* we can also move "disabling relay" in the event of "disabling
* gatt proxy" here.
*/
if (srv->node_addr_cnt == FAST_PROV_NODE_COUNT_MIN) {
if (bt_mesh_atomic_test_and_clear_bit(srv->srv_flags, GATT_PROXY_ENABLE_START)) {
k_delayed_work_cancel(&srv->gatt_proxy_enable_timer);
}
if (!bt_mesh_atomic_test_and_set_bit(srv->srv_flags, GATT_PROXY_ENABLE_START)) {
k_delayed_work_submit(&srv->gatt_proxy_enable_timer, K_SECONDS(3));
}
}
break;
}
case STATE_ACTIVE: /* fast prov info set (suspend/exit) */
/* Currently we only support suspend/exit fast prov after
* Generic OnOff Set/Set Unack is received. So no fast prov
* status message will be sent.
case STATE_ACTIVE: /* fast prov info set (suspend/exit) */
/* Currently we only support suspend/exit fast prov after Generic
* OnOff Set/Set Unack is received. So no fast prov status message
* will be sent.
*/
case STATE_PEND: /* fast prov net_key add */
case STATE_PEND: /* fast prov net_key add */
/* In this case, we should send fast prov net_key status */
default:
bt_mesh_free_buf(msg);
@@ -529,19 +577,18 @@ esp_err_t example_handle_fast_prov_action_set_comp_evt(esp_ble_mesh_model_t *mod
}
esp_err_t example_handle_fast_prov_status_send_comp_evt(int err_code, uint32_t opcode,
esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx)
esp_ble_mesh_model_t *model, esp_ble_mesh_msg_ctx_t *ctx)
{
example_fast_prov_server_t *srv = model->user_data;
esp_ble_mesh_cfg_srv_t *cfg_srv_data = NULL;
example_fast_prov_server_t *srv = NULL;
if (!model || !model->user_data) {
return ESP_ERR_INVALID_ARG;
}
srv = (example_fast_prov_server_t *)model->user_data;
ESP_LOGI(TAG, "%s: opcode 0x%06x", __func__, opcode);
cfg_srv_data = get_cfg_srv_user_data();
if (!cfg_srv_data) {
return ESP_FAIL;
}
switch (opcode) {
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_STATUS:
if (err_code == 0 && srv->set_info && srv->set_info->set_succeed == true) {
@@ -558,11 +605,8 @@ esp_err_t example_handle_fast_prov_status_send_comp_evt(int err_code, uint32_t o
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_STATUS:
break;
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_ACK:
/* Minus 1 which is provisioned by the top device */
if (all_node_addr_cnt < srv->node_addr_cnt - 1) {
if (!bt_mesh_atomic_test_and_set_bit(srv->srv_flags, SEND_ALL_NODE_ADDR_START)) {
k_delayed_work_submit(&srv->send_all_node_addr_timer, SEND_ALL_NODE_ADDR_TIMEOUT);
}
if (!bt_mesh_atomic_test_and_set_bit(srv->srv_flags, GATT_PROXY_ENABLE_START)) {
k_delayed_work_submit(&srv->gatt_proxy_enable_timer, GATT_PROXY_ENABLE_TIMEOUT);
}
break;
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_STATUS:
@@ -578,19 +622,15 @@ esp_err_t example_fast_prov_server_init(esp_ble_mesh_model_t *model)
{
example_fast_prov_server_t *srv = NULL;
if (!model) {
if (!model || !model->user_data) {
return ESP_ERR_INVALID_ARG;
}
srv = (example_fast_prov_server_t *)model->user_data;
if (!srv) {
return ESP_FAIL;
}
srv->model = model;
k_delayed_work_init(&srv->disable_fast_prov_timer, disable_fast_prov_cb);
k_delayed_work_init(&srv->send_all_node_addr_timer, example_send_all_node_addr);
k_delayed_work_init(&srv->gatt_proxy_enable_timer, enable_gatt_proxy_cb);
return ESP_OK;
}

View File

@@ -18,11 +18,13 @@
#include "esp_fast_prov_common.h"
#define DISABLE_FAST_PROV_TIMEOUT K_SECONDS(10)
#define SEND_ALL_NODE_ADDR_TIMEOUT K_SECONDS(10)
#define GATT_PROXY_ENABLE_TIMEOUT K_SECONDS(10)
#define FAST_PROV_NODE_COUNT_MIN 0x01
enum {
DISABLE_FAST_PROV_START, /* Flag indicates the timer used to disable fast provisioning has been started */
SEND_ALL_NODE_ADDR_START, /* Flag indicates the timer used to send all node address has been started */
GATT_PROXY_ENABLE_START, /* Flag indicates the timer used to enable Mesh GATT Proxy has been started */
RELAY_PROXY_DISABLED, /* Flag indicates if relay & proxy_adv are enabled or disabled */
SRV_MAX_FLAGS,
};
@@ -79,14 +81,13 @@ typedef struct {
uint8_t state; /* Fast prov state -> 0: idle, 1: pend, 2: active */
struct k_delayed_work disable_fast_prov_timer; /* Used to disable fast provisioning */
struct k_delayed_work send_all_node_addr_timer; /* Used to send all node addresses to top provisioner(e.g. phone) */
struct k_delayed_work gatt_proxy_enable_timer; /* Used to enable Mesh GATT Proxy functionality */
} __attribute__((packed)) example_fast_prov_server_t;
esp_err_t example_store_remote_node_address(uint16_t node_addr);
esp_err_t example_fast_prov_server_recv_msg(esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx,
struct net_buf_simple *buf);
esp_ble_mesh_msg_ctx_t *ctx, struct net_buf_simple *buf);
esp_err_t example_handle_fast_prov_info_set_comp_evt(esp_ble_mesh_model_t *model, uint8_t status_unicast,
uint8_t status_net_idx, uint8_t status_match);
@@ -94,8 +95,7 @@ esp_err_t example_handle_fast_prov_info_set_comp_evt(esp_ble_mesh_model_t *model
esp_err_t example_handle_fast_prov_action_set_comp_evt(esp_ble_mesh_model_t *model, uint8_t status_action);
esp_err_t example_handle_fast_prov_status_send_comp_evt(int err_code, uint32_t opcode,
esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx);
esp_ble_mesh_model_t *model, esp_ble_mesh_msg_ctx_t *ctx);
esp_err_t example_fast_prov_server_init(esp_ble_mesh_model_t *model);

View File

@@ -125,10 +125,12 @@ static esp_ble_mesh_model_pub_t onoff_pub = {
};
static esp_ble_mesh_model_op_t fast_prov_srv_op[] = {
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET, 3, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD, 16, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR, 2, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET, 0, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET, 3, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD, 16, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR, 2, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET, 0, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_ADD, 2, NULL },
{ ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_DELETE, 2, NULL },
ESP_BLE_MESH_MODEL_OP_END,
};
@@ -191,7 +193,6 @@ static void gen_onoff_get_handler(esp_ble_mesh_model_t *model,
}
send_data = led->current;
ESP_LOGI(TAG, "%s, addr 0x%04x onoff 0x%02x", __func__, model->element->element_addr, led->current);
/* Sends Generic OnOff Status as a reponse to Generic OnOff Get */
err = esp_ble_mesh_server_model_send_msg(model, ctx, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
@@ -222,12 +223,7 @@ static void gen_onoff_set_unack_handler(esp_ble_mesh_model_t *model,
}
led->current = data[0];
ESP_LOGI(TAG, "addr 0x%02x onoff 0x%02x", model->element->element_addr, led->current);
if (led_action_task_post(led, portMAX_DELAY) != ESP_OK) {
ESP_LOGE(TAG, "%s: Failed to post led action to queue", __func__);
return;
}
gpio_set_level(led->pin, led->current);
/* When the node receives the first Generic OnOff Get/Set/Set Unack message, it will
* start the timer used to disable fast provisioning functionality.
@@ -280,6 +276,9 @@ static void provisioner_prov_complete(int node_idx, const uint8_t uuid[16], uint
fast_prov_server.prov_node_cnt++;
}
ESP_LOG_BUFFER_HEX("Device uuid", uuid + 2, 6);
ESP_LOGI(TAG, "Unicast address 0x%04x", unicast_addr);
/* Sets node info */
err = example_store_node_info(uuid, unicast_addr, element_num, net_idx,
fast_prov_server.app_idx, LED_OFF);
@@ -307,12 +306,13 @@ static void provisioner_prov_complete(int node_idx, const uint8_t uuid[16], uint
ESP_LOGE(TAG, "%s: Failed to store node address 0x%04x", __func__, unicast_addr);
return;
}
if (fast_prov_server.node_addr_cnt <= fast_prov_server.max_node_num) {
if (bt_mesh_atomic_test_and_clear_bit(fast_prov_server.srv_flags, SEND_ALL_NODE_ADDR_START)) {
k_delayed_work_cancel(&fast_prov_server.send_all_node_addr_timer);
if (fast_prov_server.node_addr_cnt != FAST_PROV_NODE_COUNT_MIN &&
fast_prov_server.node_addr_cnt <= fast_prov_server.max_node_num) {
if (bt_mesh_atomic_test_and_clear_bit(fast_prov_server.srv_flags, GATT_PROXY_ENABLE_START)) {
k_delayed_work_cancel(&fast_prov_server.gatt_proxy_enable_timer);
}
if (!bt_mesh_atomic_test_and_set_bit(fast_prov_server.srv_flags, SEND_ALL_NODE_ADDR_START)) {
k_delayed_work_submit(&fast_prov_server.send_all_node_addr_timer, SEND_ALL_NODE_ADDR_TIMEOUT);
if (!bt_mesh_atomic_test_and_set_bit(fast_prov_server.srv_flags, GATT_PROXY_ENABLE_START)) {
k_delayed_work_submit(&fast_prov_server.gatt_proxy_enable_timer, GATT_PROXY_ENABLE_TIMEOUT);
}
}
} else {
@@ -515,7 +515,9 @@ static void example_ble_mesh_custom_model_cb(esp_ble_mesh_model_cb_event_t event
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET:
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_ADD:
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR:
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET: {
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET:
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_ADD:
case ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_GROUP_DELETE: {
ESP_LOGI(TAG, "%s: Fast prov server receives msg, opcode 0x%04x", __func__, opcode);
struct net_buf_simple buf = {
.len = param->model_operation.length,

View File

@@ -14,27 +14,18 @@
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "driver/gpio.h"
#include "board.h"
#include "esp_fast_prov_server_model.h"
#include "esp_fast_prov_common.h"
#define TAG "BOARD"
extern example_fast_prov_server_t fast_prov_server;
struct _led_state led_state[3] = {
{ LED_OFF, LED_OFF, LED_R, "red" },
{ LED_OFF, LED_OFF, LED_G, "green" },
{ LED_OFF, LED_OFF, LED_B, "blue" },
};
static xQueueHandle led_action_queue;
void board_output_number(esp_ble_mesh_output_action_t action, uint32_t number)
{
ESP_LOGI(TAG, "Board output number %d", number);
@@ -74,48 +65,8 @@ static void board_led_init(void)
}
}
static void led_action_thread(void *arg)
{
struct _led_state led = {0};
while (1) {
if (xQueueReceive(led_action_queue, &led, (portTickType)portMAX_DELAY)) {
ESP_LOGI(TAG, "%s: pin 0x%04x onoff 0x%02x", __func__, led.pin, led.current);
/* If the node is controlled by phone, add a delay when turn on/off led */
if (fast_prov_server.primary_role == true) {
vTaskDelay(50 / portTICK_PERIOD_MS);
}
gpio_set_level(led.pin, led.current);
}
}
}
esp_err_t led_action_task_post(struct _led_state *msg, uint32_t timeout)
{
if (xQueueSend(led_action_queue, msg, timeout) != pdTRUE) {
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t board_init(void)
{
BaseType_t ret;
board_led_init();
led_action_queue = xQueueCreate(60, sizeof(struct _led_state));
if (!led_action_queue) {
ESP_LOGE(TAG, "%s: Failed to create led action queue", __func__);
return ESP_FAIL;
}
ret = xTaskCreate(led_action_thread, "led_action_thread", 4096, NULL, 5, NULL);
if (ret == pdFAIL) {
ESP_LOGE(TAG, "%s: Failed to create led_action_thread", __func__);
vQueueDelete(led_action_queue);
return ESP_FAIL;
}
return ESP_OK;
}

View File

@@ -41,8 +41,6 @@ void board_prov_complete(void);
void board_led_operation(uint8_t pin, uint8_t onoff);
esp_err_t led_action_task_post(struct _led_state *msg, uint32_t timeout);
esp_err_t board_init(void);
#endif

View File

@@ -5,11 +5,16 @@ CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
CONFIG_MEMMAP_SMP=y
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y
CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY=
CONFIG_BTDM_CONTROLLER_MODE_BTDM=
CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=n
CONFIG_BLE_SCAN_DUPLICATE=y
CONFIG_SCAN_DUPLICATE_TYPE=2
CONFIG_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BLE_MESH_SCAN_DUPLICATE_EN=y
CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE=200
CONFIG_BTDM_CONTROLLER_FULL_SCAN_SUPPORTED=y
CONFIG_GATTS_ENABLE=y
CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL=y
CONFIG_BLE_MESH=y