Merge branch 'feat/ble_mesh_ble_adv_simultaneously_v4.0' into 'release/v4.0'

ble_mesh: Support BLE advertising simultaneously (v4.0)

See merge request espressif/esp-idf!8316
This commit is contained in:
Jiang Jiang Jian 2020-04-10 21:07:42 +08:00
commit acdba0eb46
12 changed files with 729 additions and 26 deletions

View file

@ -310,7 +310,8 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/api/models/include"
"esp_ble_mesh/api")
list(APPEND srcs "esp_ble_mesh/api/core/esp_ble_mesh_common_api.c"
list(APPEND srcs "esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c"
"esp_ble_mesh/api/core/esp_ble_mesh_common_api.c"
"esp_ble_mesh/api/core/esp_ble_mesh_local_data_operation_api.c"
"esp_ble_mesh/api/core/esp_ble_mesh_low_power_api.c"
"esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c"

View file

@ -372,6 +372,24 @@ if BLE_MESH
SDU size is 60 bytes, which leaves 56 bytes for application layer data
using a 4-byte MIC, or 52 bytes using an 8-byte MIC.
config BLE_MESH_SUPPORT_BLE_ADV
bool "Support sending normal BLE advertising packets"
default n
help
When selected, users can send normal BLE advertising packets
with specific API.
if BLE_MESH_SUPPORT_BLE_ADV
config BLE_MESH_BLE_ADV_BUF_COUNT
int "Number of advertising buffers for BLE advertising packets"
default 3
range 1 255
help
Number of advertising buffers for BLE packets available.
endif # BLE_MESH_SUPPORT_BLE_ADV
config BLE_MESH_IVU_DIVIDER
int "Divider for IV Update state refresh timer"
default 4

View file

@ -0,0 +1,73 @@
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include <string.h>
#include "btc/btc_manage.h"
#include "esp_err.h"
#include "btc_ble_mesh_prov.h"
#include "esp_ble_mesh_defs.h"
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
esp_err_t esp_ble_mesh_start_ble_advertising(const esp_ble_mesh_ble_adv_param_t *param,
const esp_ble_mesh_ble_adv_data_t *data)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (param == NULL) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_START_BLE_ADVERTISING;
memcpy(&arg.start_ble_advertising.param, param, sizeof(esp_ble_mesh_ble_adv_param_t));
if (data) {
memcpy(&arg.start_ble_advertising.data, data, sizeof(esp_ble_mesh_ble_adv_data_t));
}
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_stop_ble_advertising(uint8_t index)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (index >= CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_STOP_BLE_ADVERTISING;
arg.stop_ble_advertising.index = index;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */

View file

@ -0,0 +1,57 @@
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ESP_BLE_MESH_BLE_API_H_
#define _ESP_BLE_MESH_BLE_API_H_
#include "esp_ble_mesh_defs.h"
/**
* @brief This function is called to start BLE advertising with the corresponding data
* and parameters while BLE Mesh is working at the same time.
*
* @note 1. When this function is called, the BLE advertising packet will be posted to
* the BLE mesh adv queue in the mesh stack and waited to be sent.
* 2. In the BLE advertising parameters, the "duration" means the time used for
* sending the BLE advertising packet each time, it shall not be smaller than the
* advertising interval. When the packet is sent successfully, it will be posted
* to the adv queue again after the "period" time if the "count" is bigger than 0.
* The "count" means how many durations the packet will be sent after it is sent
* successfully for the first time. And if the "count" is set to 0xFFFF, which
* means the packet will be sent infinitely.
* 3. The "priority" means the priority of BLE advertising packet compared with
* BLE Mesh packets. Currently two options (i.e. low/high) are provided. If the
* "priority" is high, the BLE advertising packet will be posted to the front of
* adv queue. Otherwise it will be posted to the back of adv queue.
*
* @param[in] param: Pointer to the BLE advertising parameters
* @param[in] data: Pointer to the BLE advertising data and scan response data
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_start_ble_advertising(const esp_ble_mesh_ble_adv_param_t *param,
const esp_ble_mesh_ble_adv_data_t *data);
/**
* @brief This function is called to stop BLE advertising with the corresponding index.
*
* @param[in] index: Index of BLE advertising
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_stop_ble_advertising(uint8_t index);
#endif /* _ESP_BLE_MESH_BLE_API_H_ */

View file

@ -725,6 +725,36 @@ typedef enum {
PROXY_FILTER_BLACKLIST,
} esp_ble_mesh_proxy_filter_type_t;
/** Count for sending BLE advertising packet infinitely */
#define ESP_BLE_MESH_BLE_ADV_INFINITE 0xFFFF
/*!< This enum value is the priority of BLE advertising packet */
typedef enum {
ESP_BLE_MESH_BLE_ADV_PRIO_LOW,
ESP_BLE_MESH_BLE_ADV_PRIO_HIGH,
} esp_ble_mesh_ble_adv_priority_t;
/** Context of BLE advertising parameters. */
typedef struct {
uint16_t interval; /*!< BLE advertising interval */
uint8_t adv_type; /*!< BLE advertising type */
uint8_t own_addr_type; /*!< Own address type */
uint8_t peer_addr_type; /*!< Peer address type */
uint8_t peer_addr[BD_ADDR_LEN]; /*!< Peer address */
uint16_t duration; /*!< Duration is milliseconds */
uint16_t period; /*!< Period in milliseconds */
uint16_t count; /*!< Number of advertising duration */
uint8_t priority:2; /*!< Priority of BLE advertising packet */
} esp_ble_mesh_ble_adv_param_t;
/** Context of BLE advertising data. */
typedef struct {
uint8_t adv_data_len; /*!< Advertising data length */
uint8_t adv_data[31]; /*!< Advertising data */
uint8_t scan_rsp_data_len; /*!< Scan response data length */
uint8_t scan_rsp_data[31]; /*!< Scan response data */
} esp_ble_mesh_ble_adv_data_t;
/*!< This enum value is the event of node/provisioner/fast provisioning */
typedef enum {
ESP_BLE_MESH_PROV_REGISTER_COMP_EVT, /*!< Initialize BLE Mesh provisioning capabilities and internal data information completion event */
@ -792,6 +822,8 @@ typedef enum {
ESP_BLE_MESH_PROXY_CLIENT_SET_FILTER_TYPE_COMP_EVT, /*!< Proxy Client set filter type completion event */
ESP_BLE_MESH_PROXY_CLIENT_ADD_FILTER_ADDR_COMP_EVT, /*!< Proxy Client add filter address completion event */
ESP_BLE_MESH_PROXY_CLIENT_REMOVE_FILTER_ADDR_COMP_EVT, /*!< Proxy Client remove filter address completion event */
ESP_BLE_MESH_START_BLE_ADVERTISING_COMP_EVT, /*!< Start BLE advertising completion event */
ESP_BLE_MESH_STOP_BLE_ADVERTISING_COMP_EVT, /*!< Stop BLE advertising completion event */
ESP_BLE_MESH_DEINIT_MESH_COMP_EVT, /*!< De-initialize BLE Mesh stack completion event */
ESP_BLE_MESH_PROV_EVT_MAX,
} esp_ble_mesh_prov_cb_event_t;
@ -1260,6 +1292,20 @@ typedef union {
uint8_t conn_handle; /*!< Proxy connection handle */
uint16_t net_idx; /*!< Corresponding NetKey Index */
} proxy_client_remove_filter_addr_comp; /*!< Event parameter of ESP_BLE_MESH_PROXY_CLIENT_REMOVE_FILTER_ADDR_COMP_EVT */
/**
* @brief ESP_BLE_MESH_START_BLE_ADVERTISING_COMP_EVT
*/
struct ble_mesh_start_ble_advertising_comp_param {
int err_code; /*!< Indicate the result of starting BLE advertising */
uint8_t index; /*!< Index of the BLE advertising */
} start_ble_advertising_comp; /*!< Event parameter of ESP_BLE_MESH_START_BLE_ADVERTISING_COMP_EVT */
/**
* @brief ESP_BLE_MESH_STOP_BLE_ADVERTISING_COMP_EVT
*/
struct ble_mesh_stop_ble_advertising_comp_param {
int err_code; /*!< Indicate the result of stopping BLE advertising */
uint8_t index; /*!< Index of the BLE advertising */
} stop_ble_advertising_comp; /*!< Event parameter of ESP_BLE_MESH_STOP_BLE_ADVERTISING_COMP_EVT */
/**
* @brief ESP_BLE_MESH_DEINIT_MESH_COMP_EVT
*/

View file

@ -18,6 +18,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "adv.h"
#include "mesh_proxy.h"
#include "mesh.h"
#include "access.h"
@ -1879,6 +1880,26 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
break;
}
#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
case BTC_BLE_MESH_ACT_START_BLE_ADVERTISING: {
struct bt_mesh_ble_adv_param *set = (struct bt_mesh_ble_adv_param *)&arg->start_ble_advertising.param;
struct bt_mesh_ble_adv_data *data = NULL;
if (arg->start_ble_advertising.data.adv_data_len ||
arg->start_ble_advertising.data.scan_rsp_data_len) {
data = (struct bt_mesh_ble_adv_data *)&arg->start_ble_advertising.data;
}
act = ESP_BLE_MESH_START_BLE_ADVERTISING_COMP_EVT;
param.start_ble_advertising_comp.err_code =
bt_mesh_start_ble_advertising(set, data, &param.start_ble_advertising_comp.index);
break;
}
case BTC_BLE_MESH_ACT_STOP_BLE_ADVERTISING:
act = ESP_BLE_MESH_STOP_BLE_ADVERTISING_COMP_EVT;
param.stop_ble_advertising_comp.index = arg->stop_ble_advertising.index;
param.stop_ble_advertising_comp.err_code =
bt_mesh_stop_ble_advertising(arg->stop_ble_advertising.index);
break;
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
case BTC_BLE_MESH_ACT_DEINIT_MESH:
act = ESP_BLE_MESH_DEINIT_MESH_COMP_EVT;
param.deinit_mesh_comp.err_code = bt_mesh_deinit((struct bt_mesh_deinit_param *)&arg->mesh_deinit.param);

View file

@ -63,6 +63,8 @@ typedef enum {
BTC_BLE_MESH_ACT_PROXY_CLIENT_SET_FILTER_TYPE,
BTC_BLE_MESH_ACT_PROXY_CLIENT_ADD_FILTER_ADDR,
BTC_BLE_MESH_ACT_PROXY_CLIENT_REMOVE_FILTER_ADDR,
BTC_BLE_MESH_ACT_START_BLE_ADVERTISING,
BTC_BLE_MESH_ACT_STOP_BLE_ADVERTISING,
BTC_BLE_MESH_ACT_DEINIT_MESH,
} btc_ble_mesh_prov_act_t;
@ -235,6 +237,13 @@ typedef union {
uint16_t addr_num;
uint16_t *addr;
} proxy_client_remove_filter_addr;
struct ble_mesh_start_ble_advertising_args {
esp_ble_mesh_ble_adv_param_t param;
esp_ble_mesh_ble_adv_data_t data;
} start_ble_advertising;
struct ble_mesh_stop_ble_advertising_args {
uint8_t index;
} stop_ble_advertising;
struct ble_mesh_deinit_args {
esp_ble_mesh_deinit_param_t param;
} mesh_deinit;

View file

@ -21,6 +21,7 @@
#include "mesh.h"
#include "mesh_hci.h"
#include "mesh_common.h"
#include "adv.h"
#include "beacon.h"
#include "prov.h"
@ -32,6 +33,8 @@
/* Convert from ms to 0.625ms units */
#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5)
/* Convert from 0.625ms units to interval(ms) */
#define ADV_SCAN_INT(val) ((val) * 5 / 8)
/* Window and Interval are equal for continuous scanning */
#define MESH_SCAN_INTERVAL 0x20
@ -73,7 +76,11 @@ struct bt_mesh_queue {
static struct bt_mesh_queue xBleMeshQueue;
/* We reserve one queue for bt_mesh_adv_update() */
#define BLE_MESH_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + 1)
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
#define BLE_MESH_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT + 1)
#else
#define BLE_MESH_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + 1)
#endif
#if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF)
NET_BUF_POOL_DEFINE(relay_adv_buf_pool, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT,
@ -93,6 +100,30 @@ static QueueSetHandle_t xBleMeshQueueSet;
static bool ignore_relay_packet(u32_t timestamp);
#endif /* defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
/* length + advertising data + length + scan response data */
NET_BUF_POOL_DEFINE(ble_adv_buf_pool, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT,
((BLE_MESH_ADV_DATA_SIZE + 3) << 1), BLE_MESH_ADV_USER_DATA_SIZE, NULL);
static struct bt_mesh_adv ble_adv_pool[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT];
enum {
TIMER_INIT, /* Resend timer is initialized */
NUM_FLAGS,
};
static struct ble_adv_tx {
struct bt_mesh_ble_adv_param param;
struct net_buf *buf;
struct k_delayed_work resend;
BLE_MESH_ATOMIC_DEFINE(flags, NUM_FLAGS);
} ble_adv_tx[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT];
#define SEND_BLE_ADV_INFINITE 0xFFFF
static void bt_mesh_ble_adv_deinit(void);
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
struct bt_mesh_adv_task {
TaskHandle_t handle;
#if CONFIG_SPIRAM_USE_MALLOC
@ -136,28 +167,63 @@ static inline int adv_send(struct net_buf *buf)
struct bt_mesh_adv_data ad = {0};
int err = 0;
adv_int = MAX(adv_int_min,
BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit));
duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) *
(adv_int + 10);
BT_DBG("type %u len %u: %s", BLE_MESH_ADV(buf)->type,
buf->len, bt_hex(buf->data, buf->len));
BT_DBG("count %u interval %ums duration %ums",
BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1, adv_int,
duration);
buf->len, bt_hex(buf->data, buf->len));
ad.type = adv_type[BLE_MESH_ADV(buf)->type];
ad.data_len = buf->len;
ad.data = buf->data;
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
if (BLE_MESH_ADV(buf)->type != BLE_MESH_ADV_BLE) {
#endif
adv_int = MAX(adv_int_min,
BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit));
duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) *
(adv_int + 10);
param.options = 0U;
param.interval_min = ADV_SCAN_UNIT(adv_int);
param.interval_max = param.interval_min;
BT_DBG("count %u interval %ums duration %ums",
BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1, adv_int,
duration);
bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL);
ad.type = adv_type[BLE_MESH_ADV(buf)->type];
ad.data_len = buf->len;
ad.data = buf->data;
param.options = 0U;
param.interval_min = ADV_SCAN_UNIT(adv_int);
param.interval_max = param.interval_min;
bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL);
err = bt_le_adv_start(&param, &ad, 1, NULL, 0);
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
} else {
struct bt_mesh_ble_adv_data data = {0};
struct ble_adv_tx *tx = cb_data;
if (tx == NULL) {
BT_ERR("%s, Invalid adv user data", __func__);
net_buf_unref(buf);
return -EINVAL;
}
BT_DBG("interval %dms, duration %dms, period %dms, count %d",
ADV_SCAN_INT(tx->param.interval), tx->param.duration,
tx->param.period, tx->param.count);
data.adv_data_len = tx->buf->data[0];
if (data.adv_data_len) {
memcpy(data.adv_data, tx->buf->data + 1, data.adv_data_len);
}
data.scan_rsp_data_len = tx->buf->data[data.adv_data_len + 1];
if (data.scan_rsp_data_len) {
memcpy(data.scan_rsp_data, tx->buf->data + data.adv_data_len + 2, data.scan_rsp_data_len);
}
duration = tx->param.duration;
bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
err = bt_mesh_ble_adv_start(&tx->param, &data);
}
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
err = bt_le_adv_start(&param, &ad, 1, NULL, 0);
net_buf_unref(buf);
adv_send_start(duration, err, cb, cb_data);
if (err) {
@ -381,7 +447,7 @@ static void bt_mesh_unref_buf(bt_mesh_msg_t *msg)
return;
}
static void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout)
static void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front)
{
BT_DBG("%s", __func__);
@ -390,9 +456,16 @@ static void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout)
return;
}
if (xQueueSend(xBleMeshQueue.queue, msg, timeout) != pdTRUE) {
BT_ERR("%s, Failed to send item to queue", __func__);
bt_mesh_unref_buf(msg);
if (front) {
if (xQueueSendToFront(xBleMeshQueue.queue, msg, timeout) != pdTRUE) {
BT_ERR("%s, Failed to send item to queue front", __func__);
bt_mesh_unref_buf(msg);
}
} else {
if (xQueueSend(xBleMeshQueue.queue, msg, timeout) != pdTRUE) {
BT_ERR("%s, Failed to send item to queue back", __func__);
bt_mesh_unref_buf(msg);
}
}
}
@ -413,7 +486,7 @@ void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
msg.arg = (void *)net_buf_ref(buf);
bt_mesh_task_post(&msg, portMAX_DELAY);
bt_mesh_task_post(&msg, portMAX_DELAY, false);
}
void bt_mesh_adv_update(void)
@ -425,7 +498,7 @@ void bt_mesh_adv_update(void)
BT_DBG("%s", __func__);
bt_mesh_task_post(&msg, K_NO_WAIT);
bt_mesh_task_post(&msg, K_NO_WAIT, false);
}
#if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF)
@ -823,6 +896,10 @@ void bt_mesh_adv_deinit(void)
bt_mesh_unref_buf_from_pool(&adv_buf_pool);
memset(adv_pool, 0, sizeof(adv_pool));
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
bt_mesh_ble_adv_deinit();
#endif
}
int bt_mesh_scan_enable(void)
@ -895,3 +972,248 @@ int bt_mesh_scan_with_wl_enable(void)
return 0;
}
#endif /* CONFIG_BLE_MESH_TEST_USE_WHITE_LIST */
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
static struct bt_mesh_adv *ble_adv_alloc(int id)
{
return &ble_adv_pool[id];
}
static struct net_buf *bt_mesh_ble_adv_create(enum bt_mesh_adv_type type, u8_t xmit, s32_t timeout)
{
return bt_mesh_adv_create_from_pool(&ble_adv_buf_pool, ble_adv_alloc, type,
xmit, timeout);
}
static void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
void *cb_data, bool front)
{
bt_mesh_msg_t msg = {
.relay = false,
};
BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len,
bt_hex(buf->data, buf->len));
BLE_MESH_ADV(buf)->cb = cb;
BLE_MESH_ADV(buf)->cb_data = cb_data;
BLE_MESH_ADV(buf)->busy = 1U;
bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
msg.arg = (void *)net_buf_ref(buf);
bt_mesh_task_post(&msg, portMAX_DELAY, front);
}
static void ble_adv_tx_reset(struct ble_adv_tx *tx, bool unref)
{
if (tx->buf == NULL) {
return;
}
if (bt_mesh_atomic_test_bit(tx->flags, TIMER_INIT)) {
k_delayed_work_free(&tx->resend);
}
bt_mesh_atomic_set(tx->flags, 0);
memset(&tx->param, 0, sizeof(tx->param));
BLE_MESH_ADV(tx->buf)->busy = 0U;
if (unref) {
net_buf_unref(tx->buf);
}
tx->buf = NULL;
}
static void ble_adv_send_start(u16_t duration, int err, void *cb_data)
{
struct ble_adv_tx *tx = cb_data;
BT_DBG("%s, duration %d, err %d", __func__, duration, err);
/* If failed to send BLE adv packet, and param->count is not 0
* which means the timer has been initialized, here we need to
* free the timer.
*/
if (err) {
ble_adv_tx_reset(tx, true);
}
}
static void ble_adv_send_end(int err, void *cb_data)
{
struct ble_adv_tx *tx = cb_data;
BT_DBG("%s, err %d", __func__, err);
if (err) {
ble_adv_tx_reset(tx, true);
return;
}
if (tx->param.count) {
if (tx->param.period) {
k_delayed_work_submit(&tx->resend, tx->param.period);
} else {
k_work_submit(&tx->resend.work);
}
} else {
ble_adv_tx_reset(tx, true);
}
}
static struct bt_mesh_send_cb ble_adv_send_cb = {
.start = ble_adv_send_start,
.end = ble_adv_send_end,
};
static void ble_adv_resend(struct k_work *work)
{
struct ble_adv_tx *tx = CONTAINER_OF(work, struct ble_adv_tx, resend.work);
bool front = false;
if (tx->buf == NULL) {
/* The advertising has been cancelled */
return;
}
front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false;
bt_mesh_ble_adv_send(tx->buf, &ble_adv_send_cb, tx, front);
if (tx->param.count == SEND_BLE_ADV_INFINITE) {
/* Send the BLE advertising packet infinitely */
return;
}
if (tx->param.count > 0U) {
tx->param.count--;
}
}
int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param,
const struct bt_mesh_ble_adv_data *data, u8_t *index)
{
struct ble_adv_tx *tx = NULL;
struct net_buf *buf = NULL;
bool front = false;
if (param == NULL || index == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return -EINVAL;
}
if (param->adv_type != BLE_MESH_ADV_DIRECT_IND &&
(param->interval < 0x20 || param->interval > 0x4000)) {
BT_ERR("%s, Invalid adv interval 0x%04x", __func__, param->interval);
return -EINVAL;
}
if (param->adv_type > BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) {
BT_ERR("%s, Invalid adv type 0x%02x", __func__, param->adv_type);
return -EINVAL;
}
if (param->own_addr_type > BLE_MESH_ADDR_RANDOM_ID) {
BT_ERR("%s, Invalid own addr type 0x%02x", __func__, param->own_addr_type);
return -EINVAL;
}
if ((param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID ||
param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID ||
param->adv_type == BLE_MESH_ADV_DIRECT_IND ||
param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) &&
param->peer_addr_type > BLE_MESH_ADDR_RANDOM) {
BT_ERR("%s, Invalid peer addr type 0x%02x", __func__, param->peer_addr_type);
return -EINVAL;
}
if (data && (data->adv_data_len > 31 || data->scan_rsp_data_len > 31)) {
BT_ERR("%s, Invalid adv data length, %d %d", __func__,
data->adv_data_len, data->scan_rsp_data_len);
return -EINVAL;
}
if (param->priority > BLE_MESH_BLE_ADV_PRIO_HIGH) {
BT_ERR("%s, Invalid adv priority %d", __func__, param->priority);
return -EINVAL;
}
if (param->duration < ADV_SCAN_INT(param->interval)) {
BT_ERR("%s, Too small duration %dms", __func__, param->duration);
return -EINVAL;
}
buf = bt_mesh_ble_adv_create(BLE_MESH_ADV_BLE, 0U, K_NO_WAIT);
if (!buf) {
BT_ERR("%s, Unable to allocate buffer", __func__);
return -ENOBUFS;
}
/* Set advertising data and scan response data */
memset(buf->data, 0, buf->size);
if (data) {
net_buf_add_u8(buf, data->adv_data_len);
if (data->adv_data_len) {
net_buf_add_mem(buf, data->adv_data, data->adv_data_len);
}
net_buf_add_u8(buf, data->scan_rsp_data_len);
if (data->scan_rsp_data_len) {
net_buf_add_mem(buf, data->scan_rsp_data, data->scan_rsp_data_len);
}
}
*index = net_buf_id(buf);
tx = &ble_adv_tx[*index];
tx->buf = buf;
memcpy(&tx->param, param, sizeof(tx->param));
front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false;
bt_mesh_ble_adv_send(buf, &ble_adv_send_cb, tx, front);
if (param->count) {
k_delayed_work_init(&tx->resend, ble_adv_resend);
bt_mesh_atomic_set_bit(tx->flags, TIMER_INIT);
} else {
/* Send the BLE advertising packet only once */
net_buf_unref(buf);
}
return 0;
}
int bt_mesh_stop_ble_advertising(u8_t index)
{
struct ble_adv_tx *tx = NULL;
bool unref = true;
if (index >= ARRAY_SIZE(ble_adv_tx)) {
BT_ERR("%s, Invalid index %d", __func__, index);
return -EINVAL;
}
tx = &ble_adv_tx[index];
if (tx->buf == NULL) {
BT_WARN("%s, Already stopped, index %d", __func__, index);
return 0;
}
/* busy 1, ref 1; busy 1, ref 2;
* busy 0, ref 0; busy 0, ref 1;
*/
if (BLE_MESH_ADV(tx->buf)->busy == 1U &&
tx->buf->ref == 1U) {
unref = false;
}
ble_adv_tx_reset(tx, unref);
return 0;
}
static void bt_mesh_ble_adv_deinit(void)
{
for (int i = 0; i < ARRAY_SIZE(ble_adv_tx); i++) {
struct ble_adv_tx *tx = &ble_adv_tx[i];
ble_adv_tx_reset(tx, false);
}
bt_mesh_unref_buf_from_pool(&ble_adv_buf_pool);
memset(ble_adv_pool, 0, sizeof(ble_adv_pool));
}
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */

View file

@ -34,6 +34,7 @@ enum bt_mesh_adv_type {
BLE_MESH_ADV_DATA,
BLE_MESH_ADV_BEACON,
BLE_MESH_ADV_URI,
BLE_MESH_ADV_BLE,
};
typedef void (*bt_mesh_adv_func_t)(struct net_buf *buf, u16_t duration,
@ -43,7 +44,7 @@ struct bt_mesh_adv {
const struct bt_mesh_send_cb *cb;
void *cb_data;
u8_t type: 2,
u8_t type: 3,
busy: 1;
u8_t xmit;
@ -99,4 +100,11 @@ int bt_mesh_scan_disable(void);
int bt_mesh_scan_with_wl_enable(void);
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param,
const struct bt_mesh_ble_adv_data *data, u8_t *index);
int bt_mesh_stop_ble_advertising(u8_t index);
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
#endif /* _ADV_H_ */

View file

@ -400,6 +400,50 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
return 0;
}
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param,
const struct bt_mesh_ble_adv_data *data)
{
struct bt_mesh_hci_cp_set_adv_data set = {0};
tBTM_BLE_ADV_CHNL_MAP channel_map = 0U;
tBTM_BLE_AFP adv_fil_pol = 0U;
tBLE_BD_ADDR p_dir_bda = {0};
if (data && param->adv_type != BLE_MESH_ADV_DIRECT_IND &&
param->adv_type != BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) {
if (data->adv_data_len) {
set.len = data->adv_data_len;
memcpy(set.data, data->adv_data, data->adv_data_len);
BLE_MESH_BTM_CHECK_STATUS(BTM_BleWriteAdvDataRaw(set.data, set.len));
}
if (data->scan_rsp_data_len && param->adv_type != BLE_MESH_ADV_NONCONN_IND) {
set.len = data->scan_rsp_data_len;
memcpy(set.data, data->scan_rsp_data, data->scan_rsp_data_len);
BLE_MESH_BTM_CHECK_STATUS(BTM_BleWriteScanRspRaw(set.data, set.len));
}
}
channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39;
adv_fil_pol = BLE_MESH_AP_SCAN_CONN_ALL;
if (param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID ||
param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID ||
param->adv_type == BLE_MESH_ADV_DIRECT_IND ||
param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) {
p_dir_bda.type = param->peer_addr_type;
memcpy(p_dir_bda.bda, param->peer_addr, BLE_MESH_ADDR_LEN);
}
/* Check if we can start adv using BTM_BleSetAdvParamsStartAdvCheck */
BLE_MESH_BTM_CHECK_STATUS(
BTM_BleSetAdvParamsAll(param->interval, param->interval, param->adv_type,
param->own_addr_type, &p_dir_bda,
channel_map, adv_fil_pol, NULL));
BLE_MESH_BTM_CHECK_STATUS(BTM_BleStartAdv());
return 0;
}
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
int bt_le_adv_stop(void)
{
#if BLE_MESH_DEV

View file

@ -394,6 +394,32 @@ struct bt_mesh_adv_param {
u16_t interval_max;
};
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
enum bt_mesh_ble_adv_priority {
BLE_MESH_BLE_ADV_PRIO_LOW,
BLE_MESH_BLE_ADV_PRIO_HIGH,
};
struct bt_mesh_ble_adv_param {
u16_t interval; /* Advertising interval */
u8_t adv_type; /* Advertising type */
u8_t own_addr_type; /* Own address type */
u8_t peer_addr_type; /* Peer address type */
u8_t peer_addr[6]; /* Peer address */
u16_t duration; /* Duration is milliseconds */
u16_t period; /* Period in milliseconds */
u16_t count; /* Number of advertising duration */
u8_t priority:2; /* Priority of BLE advertising packet */
};
struct bt_mesh_ble_adv_data {
u8_t adv_data_len; /* Advertising data length */
u8_t adv_data[31]; /* Advertising data */
u8_t scan_rsp_data_len; /* Scan response data length */
u8_t scan_rsp_data[31]; /* Scan response data */
};
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
/* BLE Mesh scan parameters */
struct bt_mesh_scan_param {
/** Scan type (BLE_MESH_SCAN_ACTIVE or BLE_MESH_SCAN_PASSIVE) */
@ -652,6 +678,11 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
const struct bt_mesh_adv_data *ad, size_t ad_len,
const struct bt_mesh_adv_data *sd, size_t sd_len);
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param,
const struct bt_mesh_ble_adv_data *data);
#endif
int bt_le_adv_stop(void);
int bt_le_scan_start(const struct bt_mesh_scan_param *param, bt_mesh_scan_cb_t cb);

View file

@ -846,6 +846,79 @@ again:
return 0;
}
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param,
const struct bt_mesh_ble_adv_data *data)
{
struct ble_gap_adv_params adv_params = {0};
ble_addr_t p_dir_bda = {0};
int err = 0;
if (data && param->adv_type != BLE_MESH_ADV_DIRECT_IND &&
param->adv_type != BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) {
if (data->adv_data_len) {
err = ble_gap_adv_set_data(data->adv_data, data->adv_data_len);
if (err) {
BT_ERR("Failed to set advertising data, err %d", err);
return err;
}
}
if (data->scan_rsp_data_len && param->adv_type != BLE_MESH_ADV_NONCONN_IND) {
err = ble_gap_adv_rsp_set_data(data->scan_rsp_data, data->scan_rsp_data_len);
if (err) {
BT_ERR("Failed to set scan rsp data, err %d", err);
return err;
}
}
}
switch (param->adv_type) {
case BLE_MESH_ADV_IND:
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
break;
case BLE_MESH_ADV_DIRECT_IND:
adv_params.conn_mode = BLE_GAP_CONN_MODE_DIR;
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
break;
case BLE_MESH_ADV_SCAN_IND:
adv_params.conn_mode = BLE_GAP_CONN_MODE_NON;
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
break;
case BLE_MESH_ADV_NONCONN_IND:
adv_params.conn_mode = BLE_GAP_CONN_MODE_NON;
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
break;
case BLE_MESH_ADV_DIRECT_IND_LOW_DUTY:
adv_params.conn_mode = BLE_GAP_CONN_MODE_DIR;
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
break;
}
adv_params.itvl_min = param->interval;
adv_params.itvl_max = param->interval;
adv_params.channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39;
adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL;
adv_params.high_duty_cycle = (param->adv_type == BLE_MESH_ADV_DIRECT_IND) ? true : false;
if (param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID ||
param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID ||
param->adv_type == BLE_MESH_ADV_DIRECT_IND ||
param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) {
p_dir_bda.type = param->peer_addr_type;
memcpy(p_dir_bda.val, param->peer_addr, BLE_MESH_ADDR_LEN);
}
err = ble_gap_adv_start(param->own_addr_type, &p_dir_bda, BLE_HS_FOREVER, &adv_params,
gap_event_cb, NULL);
if (err) {
BT_ERR("Failed to start advertising, err %d", err);
return err;
}
return 0;
}
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
int bt_le_adv_stop(void)
{
#if BLE_MESH_DEV