diff --git a/components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c index 202f90b0a43..d280f8f7ebc 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c +++ b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c @@ -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, ¶m); } @@ -405,30 +418,46 @@ 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 (!is_hidd_app_register()) { - BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__); - ret = ESP_HIDD_NEED_REG; + if (ret != ESP_HIDD_SUCCESS) { 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; + if (!is_hidd_app_register()) { + BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__); + ret = ESP_HIDD_NEED_REG; 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,30 +478,47 @@ 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 (!is_hidd_app_register()) { - BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__); - ret = ESP_HIDD_NEED_REG; + if (ret != ESP_HIDD_SUCCESS) { break; } - if (btc_hd_cb.status != BTC_HD_CONNECTED) { - BTC_TRACE_ERROR("%s: already disconnected!", __func__); - ret = ESP_HIDD_NO_CONNECTION; + if (!is_hidd_app_register()) { + BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__); + ret = ESP_HIDD_NEED_REG; 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, ¶m); @@ -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, ¶m); @@ -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, ¶m); } } @@ -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, ¶m); diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h index 7fe7460c10d..c290dd7c0a9 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h @@ -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 { diff --git a/components/bt/host/bluedroid/stack/hid/hidd_conn.c b/components/bt/host/bluedroid/stack/hid/hidd_conn.c index 7cfed65a39c..3b44402eed1 100644 --- a/components/bt/host/bluedroid/stack/hid/hidd_conn.c +++ b/components/bt/host/bluedroid/stack/hid/hidd_conn.c @@ -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; }