Merge branch 'bugfix/fix_hidd_send_rpt_without_connection' into 'master'

Change(bt/bluedroid): Optimize HIDD sending interrupt report behavior

Closes BTQABR2023-92

See merge request espressif/esp-idf!25739
This commit is contained in:
Jiang Jiang Jian 2023-09-11 14:13:15 +08:00
commit 1bcd94a167
3 changed files with 161 additions and 47 deletions

View File

@ -52,7 +52,7 @@ typedef enum { BTC_HD_DUMMY_REQ_EVT = 0 } btc_hd_req_evt_t;
/*******************************************************************************
* Static variables
******************************************************************************/
btc_hd_cb_t btc_hd_cb;
btc_hd_cb_t btc_hd_cb = {0};
// static tBTA_HD_APP_INFO app_info;
// static tBTA_HD_QOS_INFO in_qos;
@ -242,7 +242,7 @@ static void btc_hd_init(void)
* Returns void
*
******************************************************************************/
static void btc_hd_unregister_app(void);
static void btc_hd_unregister_app(bool need_deinit);
static void btc_hd_deinit(void)
{
BTC_TRACE_API("%s", __func__);
@ -261,12 +261,12 @@ static void btc_hd_deinit(void)
}
btc_hd_cb.service_dereg_active = FALSE;
btc_hd_cb.status = BTC_HD_DISABLING;
// unresgister app will also relase the connection
// and disable after receiving unregister event from lower layer
if (is_hidd_app_register()) {
btc_hd_unregister_app();
btc_hd_unregister_app(true);
} else {
btc_hd_cb.status = BTC_HD_DISABLING;
BTC_TRACE_WARNING("%s disabling hid device service now", __func__);
BTA_HdDisable();
}
@ -298,6 +298,10 @@ static void btc_hd_register_app(esp_hidd_app_param_t *p_app_param, esp_hidd_qos_
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
ret = ESP_HIDD_NEED_INIT;
break;
} else if (btc_hd_cb.status == BTC_HD_DISABLING) {
BTC_TRACE_ERROR("%s: deinit is in progress!", __func__);
ret = ESP_HIDD_BUSY;
break;
}
if (is_hidd_app_register()) {
@ -359,7 +363,7 @@ static void btc_hd_register_app(esp_hidd_app_param_t *p_app_param, esp_hidd_qos_
* Returns void
*
******************************************************************************/
static void btc_hd_unregister_app(void)
static void btc_hd_unregister_app(bool need_deinit)
{
BTC_TRACE_API("%s", __func__);
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
@ -368,6 +372,10 @@ static void btc_hd_unregister_app(void)
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
ret = ESP_HIDD_NEED_INIT;
break;
} else if (btc_hd_cb.status == BTC_HD_DISABLING) {
BTC_TRACE_ERROR("%s: deinit is in progress!", __func__);
ret = ESP_HIDD_BUSY;
break;
}
if (!is_hidd_app_register()) {
@ -382,11 +390,16 @@ static void btc_hd_unregister_app(void)
break;
}
btc_hd_cb.service_dereg_active = TRUE;
if (need_deinit) {
btc_hd_cb.status = BTC_HD_DISABLING;
}
BTA_HdUnregisterApp();
} while(0);
if (ret != ESP_HIDD_SUCCESS) {
esp_hidd_cb_param_t param;
esp_hidd_cb_param_t param = {0};
param.unregister_app.status = ret;
btc_hd_cb_to_app(ESP_HIDD_UNREGISTER_APP_EVT, &param);
}
@ -405,11 +418,32 @@ static void btc_hd_connect(BD_ADDR bd_addr)
{
BTC_TRACE_API("%s", __func__);
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
do {
if (!is_hidd_init()) {
switch (btc_hd_cb.status) {
case BTC_HD_DISABLED:
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
ret = ESP_HIDD_NEED_INIT;
break;
case BTC_HD_DISABLING:
BTC_TRACE_ERROR("%s: deinit is in progress!", __func__);
ret = ESP_HIDD_BUSY;
break;
case BTC_HD_CONNECTING:
case BTC_HD_DISCONNECTING:
BTC_TRACE_ERROR("%s: busy now, status:%d, try later!", __func__, btc_hd_cb.status);
ret = ESP_HIDD_BUSY;
break;
case BTC_HD_CONNECTED:
BTC_TRACE_ERROR("%s: already connect to the other HID host!", __func__);
ret = ESP_HIDD_NO_RES;
break;
default:
break;
}
if (ret != ESP_HIDD_SUCCESS) {
break;
}
if (!is_hidd_app_register()) {
@ -418,17 +452,12 @@ static void btc_hd_connect(BD_ADDR bd_addr)
break;
}
if (btc_hd_cb.status == BTC_HD_CONNECTED) {
BTC_TRACE_ERROR("%s: already connect to the other HID host!", __func__);
ret = ESP_HIDD_NO_RES;
break;
}
BTA_HdConnect(bd_addr);
btc_hd_cb.status = BTC_HD_CONNECTING;
} while (0);
if (ret != ESP_HIDD_SUCCESS) {
esp_hidd_cb_param_t param;
esp_hidd_cb_param_t param = {0};
param.open.status = ret;
param.open.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED;
memcpy(param.open.bd_addr, bd_addr, BD_ADDR_LEN);
@ -449,11 +478,33 @@ static void btc_hd_disconnect(void)
{
BTC_TRACE_API("%s", __func__);
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
do {
if (!is_hidd_init()) {
switch (btc_hd_cb.status) {
case BTC_HD_DISABLED:
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
ret = ESP_HIDD_NEED_INIT;
break;
case BTC_HD_DISABLING:
BTC_TRACE_ERROR("%s: deinit is in progress!", __func__);
ret = ESP_HIDD_BUSY;
break;
case BTC_HD_CONNECTING:
case BTC_HD_DISCONNECTING:
BTC_TRACE_ERROR("%s: busy now, status:%d, try later!", __func__, btc_hd_cb.status);
ret = ESP_HIDD_BUSY;
break;
case BTC_HD_ENABLED:
case BTC_HD_DISCONNECTED:
BTC_TRACE_ERROR("%s: no connection!", __func__);
ret = ESP_HIDD_NO_CONNECTION;
break;
default:
break;
}
if (ret != ESP_HIDD_SUCCESS) {
break;
}
if (!is_hidd_app_register()) {
@ -462,17 +513,12 @@ static void btc_hd_disconnect(void)
break;
}
if (btc_hd_cb.status != BTC_HD_CONNECTED) {
BTC_TRACE_ERROR("%s: already disconnected!", __func__);
ret = ESP_HIDD_NO_CONNECTION;
break;
}
BTA_HdDisconnect();
btc_hd_cb.status = BTC_HD_DISCONNECTING;
} while (0);
if (ret != ESP_HIDD_SUCCESS) {
esp_hidd_cb_param_t param;
esp_hidd_cb_param_t param = {0};
param.close.status = ret;
param.close.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED;
btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, &param);
@ -490,15 +536,41 @@ static void btc_hd_disconnect(void)
******************************************************************************/
static void btc_hd_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t len, uint8_t *p_data)
{
tBTA_HD_REPORT report;
BTC_TRACE_API("%s: type=%d id=%d len=%d", __func__, type, id, len);
tBTA_HD_REPORT report = {0};
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
do {
if (!is_hidd_init()) {
switch (btc_hd_cb.status) {
case BTC_HD_DISABLED:
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
ret = ESP_HIDD_NEED_INIT;
break;
case BTC_HD_DISABLING:
BTC_TRACE_ERROR("%s: deinit is in progress!", __func__);
ret = ESP_HIDD_BUSY;
break;
case BTC_HD_CONNECTING:
case BTC_HD_DISCONNECTING:
BTC_TRACE_ERROR("%s: busy now, status:%d, try later!", __func__, btc_hd_cb.status);
ret = ESP_HIDD_BUSY;
break;
case BTC_HD_ENABLED:
case BTC_HD_DISCONNECTED:
if (type == ESP_HIDD_REPORT_TYPE_INTRDATA) {
BTC_TRACE_WARNING("%s: no connection, try to reconnect!", __func__);
btc_hd_cb.status = BTC_HD_CONNECTING;
} else {
BTC_TRACE_ERROR("%s: no connection!", __func__);
ret = ESP_HIDD_NO_CONNECTION;
}
break;
default:
break;
}
if (ret != ESP_HIDD_SUCCESS) {
break;
}
if (!is_hidd_app_register()) {
@ -506,6 +578,7 @@ static void btc_hd_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t
ret = ESP_HIDD_NEED_REG;
break;
}
if (type == ESP_HIDD_REPORT_TYPE_INTRDATA) {
report.type = ESP_HIDD_REPORT_TYPE_INPUT;
report.use_intr = TRUE;
@ -522,7 +595,7 @@ static void btc_hd_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t
} while (0);
if (ret != ESP_HIDD_SUCCESS) {
esp_hidd_cb_param_t param;
esp_hidd_cb_param_t param = {0};
param.send_report.status = ret;
param.send_report.reason = 0;
param.send_report.report_type = report.type;
@ -556,11 +629,18 @@ static void btc_hd_report_error(uint8_t error)
ret = ESP_HIDD_NEED_REG;
break;
}
if (btc_hd_cb.status != BTC_HD_CONNECTED) {
BTC_TRACE_ERROR("%s: no connection!", __func__);
ret = ESP_HIDD_NO_CONNECTION;
break;
}
BTA_HdReportError(error);
} while (0);
if (ret != ESP_HIDD_SUCCESS) {
esp_hidd_cb_param_t param;
esp_hidd_cb_param_t param = {0};
param.report_err.status = ret;
param.report_err.reason = 0;
btc_hd_cb_to_app(ESP_HIDD_REPORT_ERR_EVT, &param);
@ -580,11 +660,28 @@ static void btc_hd_virtual_cable_unplug(void)
{
BTC_TRACE_API("%s", __func__);
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
do {
if (!is_hidd_init()) {
switch (btc_hd_cb.status) {
case BTC_HD_DISABLED:
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
ret = ESP_HIDD_NEED_INIT;
break;
case BTC_HD_DISABLING:
BTC_TRACE_ERROR("%s: deinit is in progress!", __func__);
ret = ESP_HIDD_BUSY;
break;
case BTC_HD_CONNECTING:
case BTC_HD_DISCONNECTING:
BTC_TRACE_ERROR("%s: busy now, status:%d, try later!", __func__, btc_hd_cb.status);
ret = ESP_HIDD_BUSY;
break;
default:
break;
}
if (ret != ESP_HIDD_SUCCESS) {
break;
}
if (!is_hidd_app_register()) {
@ -592,13 +689,18 @@ static void btc_hd_virtual_cable_unplug(void)
ret = ESP_HIDD_NEED_REG;
break;
}
BTA_HdVirtualCableUnplug();
if (btc_hd_cb.status == BTC_HD_CONNECTED) {
btc_hd_cb.status = BTC_HD_DISCONNECTING;
}
} while (0);
if (ret != ESP_HIDD_SUCCESS) {
esp_hidd_cb_param_t param;
param.report_err.status = ret;
param.report_err.reason = 0;
esp_hidd_cb_param_t param = {0};
param.vc_unplug.status = ret;
param.vc_unplug.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED;
btc_hd_cb_to_app(ESP_HIDD_VC_UNPLUG_EVT, &param);
}
}
@ -630,7 +732,7 @@ void btc_hd_call_handler(btc_msg_t *msg)
btc_hd_register_app(arg->register_app.app_param, arg->register_app.in_qos, arg->register_app.out_qos);
break;
case BTC_HD_UNREGISTER_APP_EVT:
btc_hd_unregister_app();
btc_hd_unregister_app(false);
break;
case BTC_HD_CONNECT_EVT:
btc_hd_connect(arg->connect.bd_addr);
@ -750,16 +852,15 @@ void btc_hd_cb_handler(btc_msg_t *msg)
break;
}
case BTA_HD_CLOSE_EVT:
if (btc_hd_cb.forced_disc && p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) {
bt_bdaddr_t *addr = (bt_bdaddr_t *)&p_data->conn.bda;
BTC_TRACE_WARNING("remote device was forcefully disconnected");
btc_hd_remove_device(*addr);
btc_hd_cb.forced_disc = FALSE;
break;
}
if (btc_hd_cb.status == BTC_HD_CONNECTED) {
btc_hd_cb.status = BTC_HD_ENABLED;
if (p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) {
btc_hd_cb.status = BTC_HD_DISCONNECTED;
if (btc_hd_cb.forced_disc) {
bt_bdaddr_t *addr = (bt_bdaddr_t *)&p_data->conn.bda;
BTC_TRACE_WARNING("remote device was forcefully disconnected");
btc_hd_remove_device(*addr);
btc_hd_cb.forced_disc = FALSE;
break;
}
}
param.close.status = p_data->conn.status;
@ -809,8 +910,9 @@ void btc_hd_cb_handler(btc_msg_t *msg)
btc_hd_remove_device(*bd_addr);
}
if (btc_hd_cb.status == BTC_HD_CONNECTED) {
btc_hd_cb.status = BTC_HD_ENABLED;
if (btc_hd_cb.status == BTC_HD_DISCONNECTING || btc_hd_cb.status == BTC_HD_CONNECTING ||
btc_hd_cb.status == BTC_HD_CONNECTED) {
btc_hd_cb.status = BTC_HD_DISCONNECTED;
param.close.status = p_data->conn.status;
param.close.conn_status = p_data->conn.conn_status;
btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, &param);

View File

@ -39,7 +39,15 @@ typedef enum {
BTC_HD_UNPLUG_EVT,
} BTC_HD_EVT;
typedef enum { BTC_HD_DISABLED = 0, BTC_HD_ENABLED, BTC_HD_CONNECTED, BTC_HD_DISABLING } BTC_HD_STATUS;
typedef enum {
BTC_HD_DISABLED = 0,
BTC_HD_ENABLED,
BTC_HD_DISABLING,
BTC_HD_CONNECTING,
BTC_HD_CONNECTED,
BTC_HD_DISCONNECTING,
BTC_HD_DISCONNECTED,
} BTC_HD_STATUS;
/* BTIF-HD control block */
typedef struct {

View File

@ -709,11 +709,14 @@ tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param
uint8_t *p_out;
uint16_t cid;
uint16_t buf_size;
HIDD_TRACE_VERBOSE("%s: channel(%d), msg_type(%d), len(%d)", __func__, channel, msg_type, len);
p_hcon = &hd_cb.device.conn;
if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) {
return HID_ERR_CONGESTED;
}
switch (msg_type) {
case HID_TRANS_HANDSHAKE:
case HID_TRANS_CONTROL:
@ -760,7 +763,8 @@ tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param
}
hd_cb.pending_data = p_buf;
if (hd_cb.device.conn.conn_state == HID_CONN_STATE_UNUSED) {
hidd_conn_initiate();
HIDD_TRACE_WARNING("%s: try to reconnect!", __func__);
return hidd_conn_initiate();
}
return HID_SUCCESS;
}
@ -772,7 +776,7 @@ tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param
}
#endif
HIDD_TRACE_VERBOSE("%s: report sent", __func__);
if (!L2CA_DataWrite(cid, p_buf))
if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED || !L2CA_DataWrite(cid, p_buf))
return (HID_ERR_CONGESTED);
return (HID_SUCCESS);
}