Merge branch 'backport/fix_ble_bugs_v4.3' into 'release/v4.3'

Backport/fix ble bugs v4.3(backport v4.3)

See merge request espressif/esp-idf!26766
This commit is contained in:
Island
2023-11-03 09:12:59 +08:00
11 changed files with 127 additions and 83 deletions

View File

@ -222,6 +222,14 @@ config BT_GATTC_MAX_CACHE_CHAR
help
Maximum GATTC cache characteristic count
config BT_GATTC_NOTIF_REG_MAX
int "Max gattc notify(indication) register number"
depends on BT_GATTC_ENABLE
range 1 64
default 5
help
Maximum GATTC notify(indication) register number
config BT_GATTC_CACHE_NVS_FLASH
bool "Save gattc cache data to nvs flash"
depends on BT_GATTC_ENABLE

View File

@ -361,7 +361,7 @@ void bta_dm_co_ble_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap,
*p_resp_key = bte_appl_cfg.ble_resp_key;
}
if (bte_appl_cfg.ble_max_key_size > 7 && bte_appl_cfg.ble_max_key_size <= 16) {
if (bte_appl_cfg.ble_max_key_size >= 7 && bte_appl_cfg.ble_max_key_size <= 16) {
*p_max_key_size = bte_appl_cfg.ble_max_key_size;
}
#endif ///SMP_INCLUDED == TRUE

View File

@ -932,7 +932,7 @@ tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
}
if (i == BTA_GATTC_NOTIF_REG_MAX) {
status = BTA_GATT_NO_RESOURCES;
APPL_TRACE_ERROR("Max Notification Reached, registration failed.");
APPL_TRACE_ERROR("Max Notification Reached, registration failed,see CONFIG_BT_GATTC_NOTIF_REG_MAX in menuconfig");
}
}
} else {

View File

@ -319,10 +319,6 @@ typedef struct {
bool update_incl_srvc;
} tBTA_GATTC_SERV;
#ifndef BTA_GATTC_NOTIF_REG_MAX
#define BTA_GATTC_NOTIF_REG_MAX BTA_GATTC_CONN_MAX
#endif
typedef struct {
BOOLEAN in_use;
BD_ADDR remote_bda;

View File

@ -150,6 +150,13 @@
#define UC_BT_GATTC_MAX_CACHE_CHAR 40
#endif
//GATTC NOTIF
#ifdef CONFIG_BT_GATTC_NOTIF_REG_MAX
#define UC_BT_GATTC_NOTIF_REG_MAX CONFIG_BT_GATTC_NOTIF_REG_MAX
#else
#define UC_BT_GATTC_NOTIF_REG_MAX 5
#endif
#ifdef CONFIG_BT_GATTC_CACHE_NVS_FLASH
#define UC_BT_GATTC_CACHE_NVS_FLASH_ENABLED CONFIG_BT_GATTC_CACHE_NVS_FLASH
#else

View File

@ -226,6 +226,12 @@
#define GATTC_CONNECT_RETRY_EN FALSE
#endif
#ifdef UC_BT_GATTC_NOTIF_REG_MAX
#define BTA_GATTC_NOTIF_REG_MAX UC_BT_GATTC_NOTIF_REG_MAX
#else
#define BTA_GATTC_NOTIF_REG_MAX 5
#endif
#if (UC_BT_SMP_ENABLE)
#define SMP_INCLUDED TRUE
#if (BLE_INCLUDED == TRUE)

View File

@ -1173,39 +1173,39 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code,
if ((op_code == GATT_SIGN_CMD_WRITE) && !(perm & GATT_WRITE_SIGNED_PERM)) {
status = GATT_WRITE_NOT_PERMIT;
GATT_TRACE_DEBUG( "gatts_write_attr_perm_check - sign cmd write not allowed");
GATT_TRACE_DEBUG( "gatts_write_attr_perm_check - sign cmd write not allowed,handle:0x%04x",handle);
}
if ((op_code == GATT_SIGN_CMD_WRITE) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED)) {
status = GATT_INVALID_PDU;
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - Error!! sign cmd write sent on a encypted link");
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - Error!! sign cmd write sent on a encypted link,handle:0x%04x",handle);
} else if (!(perm & GATT_WRITE_ALLOWED)) {
status = GATT_WRITE_NOT_PERMIT;
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_WRITE_NOT_PERMIT");
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_WRITE_NOT_PERMIT,handle:0x%04x",handle);
}
/* require authentication, but not been authenticated */
else if ((perm & GATT_WRITE_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED)) {
status = GATT_INSUF_AUTHENTICATION;
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION");
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION,handle:0x%04x",handle);
} else if ((perm & GATT_WRITE_MITM_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED)) {
status = GATT_INSUF_AUTHENTICATION;
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: MITM required");
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: MITM required,handle:0x%04x",handle);
} else if ((perm & GATT_WRITE_ENCRYPTED_PERM ) && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)) {
status = GATT_INSUF_ENCRYPTION;
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_ENCRYPTION");
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_ENCRYPTION,handle:0x%04x",handle);
} else if ((perm & GATT_WRITE_ENCRYPTED_PERM ) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (key_size < min_key_size)) {
status = GATT_INSUF_KEY_SIZE;
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_KEY_SIZE");
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_KEY_SIZE,handle:0x%04x",handle);
}
/* LE Authorization check*/
else if ((perm & GATT_WRITE_AUTHORIZATION) && (!(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED) || !(sec_flag & GATT_SEC_FLAG_AUTHORIZATION))){
status = GATT_INSUF_AUTHORIZATION;
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHORIZATION");
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHORIZATION,handle:0x%04x",handle);
}
/* LE security mode 2 attribute */
else if (perm & GATT_WRITE_SIGNED_PERM && op_code != GATT_SIGN_CMD_WRITE && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)
&& (perm & GATT_WRITE_ALLOWED) == 0) {
status = GATT_INSUF_AUTHENTICATION;
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: LE security mode 2 required");
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: LE security mode 2 required,handle:0x%04x",handle);
} else { /* writable: must be char value declaration or char descritpors */
if (p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16) {
switch (p_attr->uuid) {
@ -1246,10 +1246,10 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code,
{
if (op_code == GATT_REQ_PREPARE_WRITE && offset != 0) { /* does not allow write blob */
status = GATT_NOT_LONG;
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_NOT_LONG");
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_NOT_LONG,handle:0x%04x",handle);
} else if (len != max_size) { /* data does not match the required format */
status = GATT_INVALID_ATTR_LEN;
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INVALID_PDU");
GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INVALID_PDU,handle:0x%04x",handle);
} else {
status = GATT_SUCCESS;
}

View File

@ -304,7 +304,7 @@ static esp_err_t create_hid_db(esp_ble_hidd_dev_t *dev, int device_index)
add_db_record(_last_db, HIDD_LE_IDX_HID_INFO_VAL, (uint8_t *)&s_hid_info_char_uuid, ESP_GATT_PERM_READ, 4, 4, (uint8_t *)hidInfo);
add_db_record(_last_db, HIDD_LE_IDX_HID_CTNL_PT_CHAR, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_write_nr);
add_db_record(_last_db, HIDD_LE_IDX_HID_CTNL_PT_VAL, (uint8_t *)&s_hid_control_point_uuid, ESP_GATT_PERM_READ, 1, 0, NULL);
add_db_record(_last_db, HIDD_LE_IDX_HID_CTNL_PT_VAL, (uint8_t *)&s_hid_control_point_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, 1, 0, NULL);
add_db_record(_last_db, HIDD_LE_IDX_PROTO_MODE_CHAR, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read_write_nr);
add_db_record(_last_db, HIDD_LE_IDX_PROTO_MODE_VAL, (uint8_t *)&s_hid_proto_mode_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, 1, 1, (uint8_t *)&dev->protocol);
@ -323,7 +323,7 @@ static esp_err_t create_hid_db(esp_ble_hidd_dev_t *dev, int device_index)
add_db_record(_last_db, index++, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read_notify);
report->index = index;
add_db_record(_last_db, index++, (uint8_t *)&s_hid_report_uuid, ESP_GATT_PERM_READ, report->value_len, 0, NULL);
add_db_record(_last_db, index++, (uint8_t *)&s_character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, 2, 0, NULL);
add_db_record(_last_db, index++, (uint8_t *)&s_character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE_ENCRYPTED, 2, 0, NULL);
} else if (report->report_type == ESP_HID_REPORT_TYPE_OUTPUT) {
//Output Report
add_db_record(_last_db, index++, (uint8_t *)&s_character_declaration_uuid, ESP_GATT_PERM_READ, 1, 1, (uint8_t *)&s_char_prop_read_write_write_nr);
@ -485,7 +485,7 @@ static void hid_event_handler(esp_ble_hidd_dev_t *dev, int device_index, esp_gat
link_report_handles(&dev->devices[device_index], param->add_attr_tab.handles);
esp_ble_gatts_start_service(dev->devices[device_index].hid_svc.handle);
if ((device_index + 1) < dev->devices_len) {
create_hid_db(dev, device_index + 1);//add next device
create_hid_db(dev, device_index + 1);//add next device if support
}
break;
}

View File

@ -1,7 +1,7 @@
/* This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this software is
distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
@ -28,28 +28,17 @@
#include "esp_hid_gap.h"
static const char *TAG = "HID_DEV_DEMO";
#define HIDD_BLE_MODE 0x01
const unsigned char hidapiReportMap[] = { //8 bytes input, 8 bytes feature
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
0x0A, 0x00, 0x01, // Usage (0x0100)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID (1)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x08, // Report Count (8)
0x09, 0x01, // Usage (0x01)
0x82, 0x02, 0x01, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Buffered Bytes)
0x95, 0x08, // Report Count (8)
0x09, 0x02, // Usage (0x02)
0xB2, 0x02, 0x01, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile,Buffered Bytes)
0x95, 0x08, // Report Count (8)
0x09, 0x03, // Usage (0x03)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
typedef struct
{
TaskHandle_t task_hdl;
esp_hidd_dev_t *hid_dev;
uint8_t protocol_mode;
uint8_t *buffer;
} local_param_t;
// 38 bytes
};
static local_param_t s_ble_hid_param = {0};
const unsigned char mediaReportMap[] = {
0x05, 0x0C, // Usage Page (Consumer)
@ -111,30 +100,24 @@ const unsigned char mediaReportMap[] = {
0xC0, // End Collection
};
static esp_hid_raw_report_map_t report_maps[] = {
{
.data = hidapiReportMap,
.len = sizeof(hidapiReportMap)
},
static esp_hid_raw_report_map_t ble_report_maps[] = {
{
.data = mediaReportMap,
.len = sizeof(mediaReportMap)
}
};
static esp_hid_device_config_t hid_config = {
static esp_hid_device_config_t ble_hid_config = {
.vendor_id = 0x16C0,
.product_id = 0x05DF,
.version = 0x0100,
.device_name = "ESP BLE HID2",
.manufacturer_name = "Espressif",
.serial_number = "1234567890",
.report_maps = report_maps,
.report_maps_len = 2
.report_maps = ble_report_maps,
.report_maps_len = 1
};
static esp_hidd_dev_t *hid_dev = NULL;
static bool dev_connected = false;
#define HID_CC_RPT_MUTE 1
#define HID_CC_RPT_POWER 2
@ -283,14 +266,52 @@ void esp_hidd_send_consumer_value(uint8_t key_cmd, bool key_pressed)
break;
}
}
esp_hidd_dev_input_set(hid_dev, 1, HID_RPT_ID_CC_IN, buffer, HID_CC_IN_RPT_LEN);
esp_hidd_dev_input_set(s_ble_hid_param.hid_dev, 0, HID_RPT_ID_CC_IN, buffer, HID_CC_IN_RPT_LEN);
return;
}
static void hidd_event_callback(void *handler_args, esp_event_base_t base, int32_t id, void *event_data)
void ble_hid_demo_task(void *pvParameters)
{
static bool send_volum_up = false;
while (1) {
ESP_LOGI(TAG, "Send the volume");
if (send_volum_up) {
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_UP, true);
vTaskDelay(100 / portTICK_PERIOD_MS);
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_UP, false);
} else {
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_DOWN, true);
vTaskDelay(100 / portTICK_PERIOD_MS);
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_DOWN, false);
}
send_volum_up = !send_volum_up;
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
void ble_hid_task_start_up(void)
{
if (s_ble_hid_param.task_hdl) {
// Task already exists
return;
}
xTaskCreate(ble_hid_demo_task, "ble_hid_demo_task", 2 * 1024, NULL, configMAX_PRIORITIES - 3,
&s_ble_hid_param.task_hdl);
}
void ble_hid_task_shut_down(void)
{
if (s_ble_hid_param.task_hdl) {
vTaskDelete(s_ble_hid_param.task_hdl);
s_ble_hid_param.task_hdl = NULL;
}
}
static void ble_hidd_event_callback(void *handler_args, esp_event_base_t base, int32_t id, void *event_data)
{
esp_hidd_event_t event = (esp_hidd_event_t)id;
esp_hidd_event_data_t *param = (esp_hidd_event_data_t *)event_data;
static const char *TAG = "HID_DEV_BLE";
switch (event) {
case ESP_HIDD_START_EVENT: {
@ -300,7 +321,6 @@ static void hidd_event_callback(void *handler_args, esp_event_base_t base, int32
}
case ESP_HIDD_CONNECT_EVENT: {
ESP_LOGI(TAG, "CONNECT");
dev_connected = true;//todo: this should be on auth_complete (in GAP)
break;
}
case ESP_HIDD_PROTOCOL_MODE_EVENT: {
@ -309,6 +329,14 @@ static void hidd_event_callback(void *handler_args, esp_event_base_t base, int32
}
case ESP_HIDD_CONTROL_EVENT: {
ESP_LOGI(TAG, "CONTROL[%u]: %sSUSPEND", param->control.map_index, param->control.control ? "EXIT_" : "");
if (param->control.control)
{
// exit suspend
ble_hid_task_start_up();
} else {
// suspend
ble_hid_task_shut_down();
}
break;
}
case ESP_HIDD_OUTPUT_EVENT: {
@ -323,7 +351,7 @@ static void hidd_event_callback(void *handler_args, esp_event_base_t base, int32
}
case ESP_HIDD_DISCONNECT_EVENT: {
ESP_LOGI(TAG, "DISCONNECT: %s", esp_hid_disconnect_reason_str(esp_hidd_dev_transport_get(param->disconnect.dev), param->disconnect.reason));
dev_connected = false;
ble_hid_task_shut_down();
esp_hid_ble_gap_adv_start();
break;
}
@ -341,7 +369,6 @@ void hid_demo_task(void *pvParameters)
{
static bool send_volum_up = false;
while (1) {
if (dev_connected) {
ESP_LOGI(TAG, "Send the volume");
if (send_volum_up) {
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_UP, true);
@ -353,7 +380,6 @@ void hid_demo_task(void *pvParameters)
esp_hidd_send_consumer_value(HID_CONSUMER_VOLUME_DOWN, false);
}
send_volum_up = !send_volum_up;
}
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
@ -367,24 +393,22 @@ void app_main(void)
ret = nvs_flash_init();
}
ESP_ERROR_CHECK( ret );
#if CONFIG_BT_CLASSIC_ENABLED
ret = esp_hid_gap_init(ESP_BT_MODE_BTDM);
#else
ret = esp_hid_gap_init(ESP_BT_MODE_BLE);
#endif
#if CONFIG_BT_BLE_ENABLED
// only BLE mode is supported in this version.
ESP_LOGI(TAG, "setting hid gap, mode:%d", HIDD_BLE_MODE);
ret = esp_hid_gap_init(HIDD_BLE_MODE);
ESP_ERROR_CHECK( ret );
ret = esp_hid_ble_gap_adv_init(ESP_HID_APPEARANCE_GENERIC, hid_config.device_name);
ret = esp_hid_ble_gap_adv_init(ESP_HID_APPEARANCE_GENERIC, ble_hid_config.device_name);
ESP_ERROR_CHECK( ret );
if ((ret = esp_ble_gatts_register_callback(esp_hidd_gatts_event_handler)) != ESP_OK) {
ESP_LOGE(TAG, "GATTS register callback failed: %d", ret);
return;
}
ESP_ERROR_CHECK( esp_hidd_dev_init(&hid_config, ESP_HID_TRANSPORT_BLE, hidd_event_callback, &hid_dev) );
xTaskCreate(&hid_demo_task, "hid_task", 2048, NULL, 2, NULL);
ESP_LOGI(TAG, "setting ble device");
ESP_ERROR_CHECK(
esp_hidd_dev_init(&ble_hid_config, ESP_HID_TRANSPORT_BLE, ble_hidd_event_callback, &s_ble_hid_param.hid_dev));
#endif
}

View File

@ -452,7 +452,7 @@ static esp_err_t start_bt_scan(uint32_t seconds)
/*
* BLE GAP
* */
extern void ble_hid_task_start_up(void);
static void ble_gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
switch (event) {
@ -501,10 +501,12 @@ static void ble_gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_p
* */
case ESP_GAP_BLE_AUTH_CMPL_EVT:
if (!param->ble_security.auth_cmpl.success) {
// if AUTH ERROR,hid maybe don't work.
ESP_LOGE(TAG, "BLE GAP AUTH ERROR: 0x%x", param->ble_security.auth_cmpl.fail_reason);
} else {
ESP_LOGI(TAG, "BLE GAP AUTH SUCCESS");
}
ble_hid_task_start_up();
break;
case ESP_GAP_BLE_KEY_EVT: //shows the ble key info share with peer device to the user.

View File

@ -4,3 +4,4 @@ CONFIG_BTDM_CTRL_HCI_MODE_VHCI=y
CONFIG_BT_BLUEDROID_ENABLED=y
CONFIG_BT_CLASSIC_ENABLED=y
CONFIG_BT_HID_HOST_ENABLED=y
CONFIG_BT_GATTC_NOTIF_REG_MAX=16