mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Provisioning BLE: Add API to set manufacturer data in scan response
- Add `wifi_prov_scheme_ble_set_mfg_data` API to set custom manufacturer data in BLE advertisements. - Run format.sh script on modified files. - Fix few typos in `protocomm_nimble.c`. - Incorporate suggestion to remove extra check on protocomm_ble_mfg_data_len - Remove few unnecessary comments.
This commit is contained in:
parent
44c175649a
commit
c8f4153d4f
@ -26,6 +26,14 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define MAX_BLE_DEVNAME_LEN 29
|
#define MAX_BLE_DEVNAME_LEN 29
|
||||||
#define BLE_UUID128_VAL_LENGTH 16
|
#define BLE_UUID128_VAL_LENGTH 16
|
||||||
|
/**
|
||||||
|
* Theoretically, the limit for max manufacturer length remains same as BLE
|
||||||
|
* device name i.e. 31 bytes (max scan response size) - 1 byte (length) - 1
|
||||||
|
* byte (type) = 29 bytes
|
||||||
|
* However, manufacturer data goes along with BLE device name in scan response.
|
||||||
|
* So, it is important to understand the actual length should be smaller than
|
||||||
|
* (29 - (BLE device name length) - 2). */
|
||||||
|
#define MAX_BLE_MANUFACTURER_DATA_LEN 29
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This structure maps handler required by protocomm layer to
|
* @brief This structure maps handler required by protocomm layer to
|
||||||
@ -59,6 +67,16 @@ typedef struct protocomm_ble_config {
|
|||||||
*/
|
*/
|
||||||
uint8_t service_uuid[BLE_UUID128_VAL_LENGTH];
|
uint8_t service_uuid[BLE_UUID128_VAL_LENGTH];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BLE device manufacturer data pointer in advertisement
|
||||||
|
*/
|
||||||
|
uint8_t *manufacturer_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BLE device manufacturer data length in advertisement
|
||||||
|
*/
|
||||||
|
ssize_t manufacturer_data_len;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of entries in the Name-UUID lookup table
|
* Number of entries in the Name-UUID lookup table
|
||||||
*/
|
*/
|
||||||
|
@ -78,6 +78,8 @@ static esp_ble_adv_params_t adv_params = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static char *protocomm_ble_device_name = NULL;
|
static char *protocomm_ble_device_name = NULL;
|
||||||
|
static uint8_t *protocomm_ble_mfg_data = NULL;
|
||||||
|
static size_t protocomm_ble_mfg_data_len;
|
||||||
|
|
||||||
static void hexdump(const char *msg, uint8_t *buf, int len)
|
static void hexdump(const char *msg, uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
@ -433,6 +435,11 @@ static void protocomm_ble_cleanup(void)
|
|||||||
free(protocomm_ble_device_name);
|
free(protocomm_ble_device_name);
|
||||||
protocomm_ble_device_name = NULL;
|
protocomm_ble_device_name = NULL;
|
||||||
}
|
}
|
||||||
|
if (protocomm_ble_mfg_data) {
|
||||||
|
free(protocomm_ble_mfg_data);
|
||||||
|
protocomm_ble_mfg_data = NULL;
|
||||||
|
protocomm_ble_mfg_data_len = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t protocomm_ble_start(protocomm_t *pc, const protocomm_ble_config_t *config)
|
esp_err_t protocomm_ble_start(protocomm_t *pc, const protocomm_ble_config_t *config)
|
||||||
@ -454,6 +461,12 @@ esp_err_t protocomm_ble_start(protocomm_t *pc, const protocomm_ble_config_t *con
|
|||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store BLE manufacturer data pointer */
|
||||||
|
if (config->manufacturer_data != NULL) {
|
||||||
|
protocomm_ble_mfg_data = config->manufacturer_data;
|
||||||
|
protocomm_ble_mfg_data_len = config->manufacturer_data_len;
|
||||||
|
}
|
||||||
|
|
||||||
protoble_internal = (_protocomm_ble_internal_t *) calloc(1, sizeof(_protocomm_ble_internal_t));
|
protoble_internal = (_protocomm_ble_internal_t *) calloc(1, sizeof(_protocomm_ble_internal_t));
|
||||||
if (protoble_internal == NULL) {
|
if (protoble_internal == NULL) {
|
||||||
ESP_LOGE(TAG, "Error allocating internal protocomm structure");
|
ESP_LOGE(TAG, "Error allocating internal protocomm structure");
|
||||||
@ -557,7 +570,12 @@ esp_err_t protocomm_ble_start(protocomm_t *pc, const protocomm_ble_config_t *con
|
|||||||
*
|
*
|
||||||
* Any remaining space may be used for accommodating
|
* Any remaining space may be used for accommodating
|
||||||
* other fields in the future
|
* other fields in the future
|
||||||
|
*
|
||||||
|
* 2) Manufacturer Data (To be truncated depending upon available size)
|
||||||
|
* Size : The maximum supported manufacturer data size
|
||||||
|
* will be 31 - 2 (length + type) - ble_devname_len - 2 (length + type)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
raw_data_info_t scan_resp_data[] = {
|
raw_data_info_t scan_resp_data[] = {
|
||||||
{ /* If full device name can fit in the scan response then indicate
|
{ /* If full device name can fit in the scan response then indicate
|
||||||
* that by setting type to "Complete Name", else set it to "Short Name"
|
* that by setting type to "Complete Name", else set it to "Short Name"
|
||||||
@ -568,8 +586,17 @@ esp_err_t protocomm_ble_start(protocomm_t *pc, const protocomm_ble_config_t *con
|
|||||||
.length = MIN(ble_devname_len, (ESP_BLE_SCAN_RSP_DATA_LEN_MAX - 2)),
|
.length = MIN(ble_devname_len, (ESP_BLE_SCAN_RSP_DATA_LEN_MAX - 2)),
|
||||||
.data_p = (uint8_t *) protocomm_ble_device_name
|
.data_p = (uint8_t *) protocomm_ble_device_name
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
0,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (protocomm_ble_mfg_data_len > 0) {
|
||||||
|
scan_resp_data[1].type = ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE;
|
||||||
|
scan_resp_data[1].length = protocomm_ble_mfg_data_len;
|
||||||
|
scan_resp_data[1].data_p = (uint8_t *) protocomm_ble_mfg_data;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the total raw scan response data length required for above entries */
|
/* Get the total raw scan response data length required for above entries */
|
||||||
uint8_t scan_resp_data_len = 0;
|
uint8_t scan_resp_data_len = 0;
|
||||||
for (int i = 0; i < (sizeof(scan_resp_data) / sizeof(scan_resp_data[0])); i++) {
|
for (int i = 0; i < (sizeof(scan_resp_data) / sizeof(scan_resp_data[0])); i++) {
|
||||||
|
@ -81,6 +81,9 @@ static struct ble_gap_adv_params adv_params;
|
|||||||
static char *protocomm_ble_device_name;
|
static char *protocomm_ble_device_name;
|
||||||
static struct ble_hs_adv_fields adv_data, resp_data;
|
static struct ble_hs_adv_fields adv_data, resp_data;
|
||||||
|
|
||||||
|
static uint8_t *protocomm_ble_mfg_data;
|
||||||
|
static size_t protocomm_ble_mfg_data_len;
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Maintain database of uuid_name addresses to free memory afterwards *
|
* Maintain database of uuid_name addresses to free memory afterwards *
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
@ -308,7 +311,7 @@ gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle,
|
|||||||
|
|
||||||
switch (ctxt->op) {
|
switch (ctxt->op) {
|
||||||
case BLE_GATT_ACCESS_OP_READ_CHR:
|
case BLE_GATT_ACCESS_OP_READ_CHR:
|
||||||
ESP_LOGD(TAG, "Read attempeted for Characterstic UUID = %s, attr_handle = %d",
|
ESP_LOGD(TAG, "Read attempted for characteristic UUID = %s, attr_handle = %d",
|
||||||
ble_uuid_to_str(ctxt->chr->uuid, buf), attr_handle);
|
ble_uuid_to_str(ctxt->chr->uuid, buf), attr_handle);
|
||||||
|
|
||||||
rc = simple_ble_gatts_get_attr_value(attr_handle, &temp_outlen,
|
rc = simple_ble_gatts_get_attr_value(attr_handle, &temp_outlen,
|
||||||
@ -474,7 +477,7 @@ static int simple_ble_start(const simple_ble_cfg_t *cfg)
|
|||||||
{
|
{
|
||||||
ble_cfg_p = (void *)cfg;
|
ble_cfg_p = (void *)cfg;
|
||||||
int rc;
|
int rc;
|
||||||
ESP_LOGD(TAG, "Free mem at start of simple_ble_init %d", esp_get_free_heap_size());
|
ESP_LOGD(TAG, "Free memory at start of simple_ble_init %d", esp_get_free_heap_size());
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init());
|
ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init());
|
||||||
nimble_port_init();
|
nimble_port_init();
|
||||||
@ -513,6 +516,13 @@ static int simple_ble_start(const simple_ble_cfg_t *cfg)
|
|||||||
resp_data.name_is_complete = 1;
|
resp_data.name_is_complete = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set manufacturer data if protocomm_ble_mfg_data points to valid data */
|
||||||
|
if (protocomm_ble_mfg_data != NULL) {
|
||||||
|
resp_data.mfg_data = protocomm_ble_mfg_data;
|
||||||
|
resp_data.mfg_data_len = protocomm_ble_mfg_data_len;
|
||||||
|
ESP_LOGD(TAG, "Custom manufacturer data length = %d", protocomm_ble_mfg_data_len);
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX Need to have template for store */
|
/* XXX Need to have template for store */
|
||||||
ble_store_config_init();
|
ble_store_config_init();
|
||||||
nimble_port_freertos_init(nimble_host_task);
|
nimble_port_freertos_init(nimble_host_task);
|
||||||
@ -733,10 +743,17 @@ static void protocomm_ble_cleanup(void)
|
|||||||
free(protoble_internal);
|
free(protoble_internal);
|
||||||
protoble_internal = NULL;
|
protoble_internal = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (protocomm_ble_device_name) {
|
if (protocomm_ble_device_name) {
|
||||||
free(protocomm_ble_device_name);
|
free(protocomm_ble_device_name);
|
||||||
protocomm_ble_device_name = NULL;
|
protocomm_ble_device_name = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (protocomm_ble_mfg_data) {
|
||||||
|
free(protocomm_ble_mfg_data);
|
||||||
|
protocomm_ble_mfg_data = NULL;
|
||||||
|
protocomm_ble_mfg_data_len = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_gatt_ble_misc_memory(simple_ble_cfg_t *ble_config)
|
static void free_gatt_ble_misc_memory(simple_ble_cfg_t *ble_config)
|
||||||
@ -788,7 +805,9 @@ esp_err_t protocomm_ble_start(protocomm_t *pc, const protocomm_ble_config_t *con
|
|||||||
{
|
{
|
||||||
/* copy the 128 bit service UUID into local buffer to use as base 128 bit
|
/* copy the 128 bit service UUID into local buffer to use as base 128 bit
|
||||||
* UUID. */
|
* UUID. */
|
||||||
|
if (config->service_uuid != NULL) {
|
||||||
memcpy(ble_uuid_base, config->service_uuid, BLE_UUID128_VAL_LENGTH);
|
memcpy(ble_uuid_base, config->service_uuid, BLE_UUID128_VAL_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
if (!pc || !config || !config->device_name || !config->nu_lookup) {
|
if (!pc || !config || !config->device_name || !config->nu_lookup) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
@ -829,13 +848,18 @@ esp_err_t protocomm_ble_start(protocomm_t *pc, const protocomm_ble_config_t *con
|
|||||||
|
|
||||||
/* Store BLE device name internally */
|
/* Store BLE device name internally */
|
||||||
protocomm_ble_device_name = strdup(config->device_name);
|
protocomm_ble_device_name = strdup(config->device_name);
|
||||||
|
|
||||||
if (protocomm_ble_device_name == NULL) {
|
if (protocomm_ble_device_name == NULL) {
|
||||||
ESP_LOGE(TAG, "Error allocating memory for storing BLE device name");
|
ESP_LOGE(TAG, "Error allocating memory for storing BLE device name");
|
||||||
protocomm_ble_cleanup();
|
protocomm_ble_cleanup();
|
||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store BLE manufacturer data pointer */
|
||||||
|
if (config->manufacturer_data != NULL) {
|
||||||
|
protocomm_ble_mfg_data = config->manufacturer_data;
|
||||||
|
protocomm_ble_mfg_data_len = config->manufacturer_data_len;
|
||||||
|
}
|
||||||
|
|
||||||
protoble_internal = (_protocomm_ble_internal_t *) calloc(1, sizeof(_protocomm_ble_internal_t));
|
protoble_internal = (_protocomm_ble_internal_t *) calloc(1, sizeof(_protocomm_ble_internal_t));
|
||||||
if (protoble_internal == NULL) {
|
if (protoble_internal == NULL) {
|
||||||
ESP_LOGE(TAG, "Error allocating internal protocomm structure");
|
ESP_LOGE(TAG, "Error allocating internal protocomm structure");
|
||||||
|
@ -77,6 +77,29 @@ void wifi_prov_scheme_ble_event_cb_free_bt (void *user_data, wifi_prov_cb_event
|
|||||||
*/
|
*/
|
||||||
esp_err_t wifi_prov_scheme_ble_set_service_uuid(uint8_t *uuid128);
|
esp_err_t wifi_prov_scheme_ble_set_service_uuid(uint8_t *uuid128);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set manufacturer specific data in scan response
|
||||||
|
*
|
||||||
|
* This must be called before starting provisioning, i.e. before
|
||||||
|
* making a call to wifi_prov_mgr_start_provisioning().
|
||||||
|
*
|
||||||
|
* @note It is important to understand that length of custom manufacturer
|
||||||
|
* data should be within limits. The manufacturer data goes into scan
|
||||||
|
* response along with BLE device name. By default, BLE device name
|
||||||
|
* length is of 11 Bytes, however it can vary as per application use
|
||||||
|
* case. So, one has to honour the scan response data size limits i.e.
|
||||||
|
* (mfg_data_len + 2) < 31 - (device_name_length + 2 ). If the
|
||||||
|
* mfg_data length exceeds this limit, the length will be truncated.
|
||||||
|
*
|
||||||
|
* @param[in] mfg_data Custom manufacturer data
|
||||||
|
* @param[in] mfg_data_len Manufacturer data length
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK : Success
|
||||||
|
* - ESP_ERR_INVALID_ARG : Null argument
|
||||||
|
*/
|
||||||
|
esp_err_t wifi_prov_scheme_ble_set_mfg_data(uint8_t *mfg_data, ssize_t mfg_data_len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,6 +29,9 @@ extern const wifi_prov_scheme_t wifi_prov_scheme_ble;
|
|||||||
|
|
||||||
static uint8_t *custom_service_uuid;
|
static uint8_t *custom_service_uuid;
|
||||||
|
|
||||||
|
static uint8_t *custom_manufacturer_data;
|
||||||
|
static size_t custom_manufacturer_data_len;
|
||||||
|
|
||||||
static esp_err_t prov_start(protocomm_t *pc, void *config)
|
static esp_err_t prov_start(protocomm_t *pc, void *config)
|
||||||
{
|
{
|
||||||
if (!pc) {
|
if (!pc) {
|
||||||
@ -60,6 +63,23 @@ esp_err_t wifi_prov_scheme_ble_set_service_uuid(uint8_t *uuid128)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t wifi_prov_scheme_ble_set_mfg_data(uint8_t *mfg_data, ssize_t mfg_data_len)
|
||||||
|
{
|
||||||
|
if (!mfg_data || !mfg_data_len) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
custom_manufacturer_data = (uint8_t *) malloc(mfg_data_len);
|
||||||
|
if (custom_manufacturer_data == NULL) {
|
||||||
|
ESP_LOGE(TAG, "Error allocating memory for mfg_data");
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
custom_manufacturer_data_len = mfg_data_len;
|
||||||
|
memcpy(custom_manufacturer_data, mfg_data, mfg_data_len);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static void *new_config(void)
|
static void *new_config(void)
|
||||||
{
|
{
|
||||||
protocomm_ble_config_t *ble_config = calloc(1, sizeof(protocomm_ble_config_t));
|
protocomm_ble_config_t *ble_config = calloc(1, sizeof(protocomm_ble_config_t));
|
||||||
@ -114,6 +134,26 @@ static esp_err_t set_config_service(void *config, const char *service_name, cons
|
|||||||
if (custom_service_uuid) {
|
if (custom_service_uuid) {
|
||||||
memcpy(ble_config->service_uuid, custom_service_uuid, sizeof(ble_config->service_uuid));
|
memcpy(ble_config->service_uuid, custom_service_uuid, sizeof(ble_config->service_uuid));
|
||||||
}
|
}
|
||||||
|
/* Set manufacturer data if it is provided by app */
|
||||||
|
if (custom_manufacturer_data) {
|
||||||
|
size_t mfg_data_len = custom_manufacturer_data_len;
|
||||||
|
/* Manufacturer Data Length + 2 Byte header + BLE Device name + 2 Byte
|
||||||
|
* header <= 31 Bytes */
|
||||||
|
if (mfg_data_len > (MAX_BLE_MANUFACTURER_DATA_LEN - sizeof(ble_config->device_name) - 2)) {
|
||||||
|
ESP_LOGE(TAG, "Manufacturer data length is more than the max allowed size; expect truncated mfg_data ");
|
||||||
|
/* XXX Does it even make any sense to set truncated mfg_data ? The
|
||||||
|
* only reason to not return failure from here is provisioning
|
||||||
|
* should continue as it is with error prints for mfg_data length */
|
||||||
|
mfg_data_len = MAX_BLE_MANUFACTURER_DATA_LEN - sizeof(ble_config->device_name) - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ble_config->manufacturer_data = custom_manufacturer_data;
|
||||||
|
ble_config->manufacturer_data_len = mfg_data_len;
|
||||||
|
} else {
|
||||||
|
ble_config->manufacturer_data = NULL;
|
||||||
|
ble_config->manufacturer_data_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user