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 * 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_APP_INFO app_info;
// static tBTA_HD_QOS_INFO in_qos; // static tBTA_HD_QOS_INFO in_qos;
@ -242,7 +242,7 @@ static void btc_hd_init(void)
* Returns 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) static void btc_hd_deinit(void)
{ {
BTC_TRACE_API("%s", __func__); 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.service_dereg_active = FALSE;
btc_hd_cb.status = BTC_HD_DISABLING;
// unresgister app will also relase the connection // unresgister app will also relase the connection
// and disable after receiving unregister event from lower layer // and disable after receiving unregister event from lower layer
if (is_hidd_app_register()) { if (is_hidd_app_register()) {
btc_hd_unregister_app(); btc_hd_unregister_app(true);
} else { } else {
btc_hd_cb.status = BTC_HD_DISABLING;
BTC_TRACE_WARNING("%s disabling hid device service now", __func__); BTC_TRACE_WARNING("%s disabling hid device service now", __func__);
BTA_HdDisable(); 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__); BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
ret = ESP_HIDD_NEED_INIT; ret = ESP_HIDD_NEED_INIT;
break; 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()) { 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 * Returns void
* *
******************************************************************************/ ******************************************************************************/
static void btc_hd_unregister_app(void) static void btc_hd_unregister_app(bool need_deinit)
{ {
BTC_TRACE_API("%s", __func__); BTC_TRACE_API("%s", __func__);
esp_hidd_status_t ret = ESP_HIDD_SUCCESS; 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__); BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
ret = ESP_HIDD_NEED_INIT; ret = ESP_HIDD_NEED_INIT;
break; 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()) { if (!is_hidd_app_register()) {
@ -382,11 +390,16 @@ static void btc_hd_unregister_app(void)
break; break;
} }
btc_hd_cb.service_dereg_active = TRUE; btc_hd_cb.service_dereg_active = TRUE;
if (need_deinit) {
btc_hd_cb.status = BTC_HD_DISABLING;
}
BTA_HdUnregisterApp(); BTA_HdUnregisterApp();
} while(0); } while(0);
if (ret != ESP_HIDD_SUCCESS) { if (ret != ESP_HIDD_SUCCESS) {
esp_hidd_cb_param_t param; esp_hidd_cb_param_t param = {0};
param.unregister_app.status = ret; param.unregister_app.status = ret;
btc_hd_cb_to_app(ESP_HIDD_UNREGISTER_APP_EVT, &param); 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__); BTC_TRACE_API("%s", __func__);
esp_hidd_status_t ret = ESP_HIDD_SUCCESS; esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
do { 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__); BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
ret = ESP_HIDD_NEED_INIT; ret = ESP_HIDD_NEED_INIT;
break; 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()) { if (!is_hidd_app_register()) {
@ -418,17 +452,12 @@ static void btc_hd_connect(BD_ADDR bd_addr)
break; 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); BTA_HdConnect(bd_addr);
btc_hd_cb.status = BTC_HD_CONNECTING;
} while (0); } while (0);
if (ret != ESP_HIDD_SUCCESS) { if (ret != ESP_HIDD_SUCCESS) {
esp_hidd_cb_param_t param; esp_hidd_cb_param_t param = {0};
param.open.status = ret; param.open.status = ret;
param.open.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED; param.open.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED;
memcpy(param.open.bd_addr, bd_addr, BD_ADDR_LEN); 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__); BTC_TRACE_API("%s", __func__);
esp_hidd_status_t ret = ESP_HIDD_SUCCESS; esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
do { 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__); BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
ret = ESP_HIDD_NEED_INIT; ret = ESP_HIDD_NEED_INIT;
break; 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()) { if (!is_hidd_app_register()) {
@ -462,17 +513,12 @@ static void btc_hd_disconnect(void)
break; break;
} }
if (btc_hd_cb.status != BTC_HD_CONNECTED) {
BTC_TRACE_ERROR("%s: already disconnected!", __func__);
ret = ESP_HIDD_NO_CONNECTION;
break;
}
BTA_HdDisconnect(); BTA_HdDisconnect();
btc_hd_cb.status = BTC_HD_DISCONNECTING;
} while (0); } while (0);
if (ret != ESP_HIDD_SUCCESS) { if (ret != ESP_HIDD_SUCCESS) {
esp_hidd_cb_param_t param; esp_hidd_cb_param_t param = {0};
param.close.status = ret; param.close.status = ret;
param.close.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED; param.close.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED;
btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, &param); 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) 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); 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; esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
do { 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__); BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
ret = ESP_HIDD_NEED_INIT; ret = ESP_HIDD_NEED_INIT;
break; 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()) { 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; ret = ESP_HIDD_NEED_REG;
break; break;
} }
if (type == ESP_HIDD_REPORT_TYPE_INTRDATA) { if (type == ESP_HIDD_REPORT_TYPE_INTRDATA) {
report.type = ESP_HIDD_REPORT_TYPE_INPUT; report.type = ESP_HIDD_REPORT_TYPE_INPUT;
report.use_intr = TRUE; 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); } while (0);
if (ret != ESP_HIDD_SUCCESS) { 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.status = ret;
param.send_report.reason = 0; param.send_report.reason = 0;
param.send_report.report_type = report.type; 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; ret = ESP_HIDD_NEED_REG;
break; 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); BTA_HdReportError(error);
} while (0); } while (0);
if (ret != ESP_HIDD_SUCCESS) { 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.status = ret;
param.report_err.reason = 0; param.report_err.reason = 0;
btc_hd_cb_to_app(ESP_HIDD_REPORT_ERR_EVT, &param); 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__); BTC_TRACE_API("%s", __func__);
esp_hidd_status_t ret = ESP_HIDD_SUCCESS; esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
do { 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__); BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
ret = ESP_HIDD_NEED_INIT; ret = ESP_HIDD_NEED_INIT;
break; 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()) { if (!is_hidd_app_register()) {
@ -592,13 +689,18 @@ static void btc_hd_virtual_cable_unplug(void)
ret = ESP_HIDD_NEED_REG; ret = ESP_HIDD_NEED_REG;
break; break;
} }
BTA_HdVirtualCableUnplug(); BTA_HdVirtualCableUnplug();
if (btc_hd_cb.status == BTC_HD_CONNECTED) {
btc_hd_cb.status = BTC_HD_DISCONNECTING;
}
} while (0); } while (0);
if (ret != ESP_HIDD_SUCCESS) { if (ret != ESP_HIDD_SUCCESS) {
esp_hidd_cb_param_t param; esp_hidd_cb_param_t param = {0};
param.report_err.status = ret; param.vc_unplug.status = ret;
param.report_err.reason = 0; param.vc_unplug.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED;
btc_hd_cb_to_app(ESP_HIDD_VC_UNPLUG_EVT, &param); 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); btc_hd_register_app(arg->register_app.app_param, arg->register_app.in_qos, arg->register_app.out_qos);
break; break;
case BTC_HD_UNREGISTER_APP_EVT: case BTC_HD_UNREGISTER_APP_EVT:
btc_hd_unregister_app(); btc_hd_unregister_app(false);
break; break;
case BTC_HD_CONNECT_EVT: case BTC_HD_CONNECT_EVT:
btc_hd_connect(arg->connect.bd_addr); btc_hd_connect(arg->connect.bd_addr);
@ -750,16 +852,15 @@ void btc_hd_cb_handler(btc_msg_t *msg)
break; break;
} }
case BTA_HD_CLOSE_EVT: case BTA_HD_CLOSE_EVT:
if (btc_hd_cb.forced_disc && p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) { 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; bt_bdaddr_t *addr = (bt_bdaddr_t *)&p_data->conn.bda;
BTC_TRACE_WARNING("remote device was forcefully disconnected"); BTC_TRACE_WARNING("remote device was forcefully disconnected");
btc_hd_remove_device(*addr); btc_hd_remove_device(*addr);
btc_hd_cb.forced_disc = FALSE; btc_hd_cb.forced_disc = FALSE;
break; break;
} }
if (btc_hd_cb.status == BTC_HD_CONNECTED) {
btc_hd_cb.status = BTC_HD_ENABLED;
} }
param.close.status = p_data->conn.status; 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); btc_hd_remove_device(*bd_addr);
} }
if (btc_hd_cb.status == BTC_HD_CONNECTED) { if (btc_hd_cb.status == BTC_HD_DISCONNECTING || btc_hd_cb.status == BTC_HD_CONNECTING ||
btc_hd_cb.status = BTC_HD_ENABLED; btc_hd_cb.status == BTC_HD_CONNECTED) {
btc_hd_cb.status = BTC_HD_DISCONNECTED;
param.close.status = p_data->conn.status; param.close.status = p_data->conn.status;
param.close.conn_status = p_data->conn.conn_status; param.close.conn_status = p_data->conn.conn_status;
btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, &param); btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, &param);

View File

@ -39,7 +39,15 @@ typedef enum {
BTC_HD_UNPLUG_EVT, BTC_HD_UNPLUG_EVT,
} BTC_HD_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 */ /* BTIF-HD control block */
typedef struct { 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; uint8_t *p_out;
uint16_t cid; uint16_t cid;
uint16_t buf_size; uint16_t buf_size;
HIDD_TRACE_VERBOSE("%s: channel(%d), msg_type(%d), len(%d)", __func__, channel, msg_type, len); HIDD_TRACE_VERBOSE("%s: channel(%d), msg_type(%d), len(%d)", __func__, channel, msg_type, len);
p_hcon = &hd_cb.device.conn; p_hcon = &hd_cb.device.conn;
if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) { if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) {
return HID_ERR_CONGESTED; return HID_ERR_CONGESTED;
} }
switch (msg_type) { switch (msg_type) {
case HID_TRANS_HANDSHAKE: case HID_TRANS_HANDSHAKE:
case HID_TRANS_CONTROL: 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; hd_cb.pending_data = p_buf;
if (hd_cb.device.conn.conn_state == HID_CONN_STATE_UNUSED) { 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; return HID_SUCCESS;
} }
@ -772,7 +776,7 @@ tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param
} }
#endif #endif
HIDD_TRACE_VERBOSE("%s: report sent", __func__); 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_ERR_CONGESTED);
return (HID_SUCCESS); return (HID_SUCCESS);
} }