optimize HID Host disconnection procedure

This commit is contained in:
liqigan 2022-11-03 11:29:09 +08:00
parent 39189e7522
commit 54c5e28c80
4 changed files with 57 additions and 56 deletions

View File

@ -131,7 +131,9 @@ esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_id_and_proto(esp_hidh_de
esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_proto_and_data(esp_hidh_dev_t *dev, int protocol_mode, esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_proto_and_data(esp_hidh_dev_t *dev, int protocol_mode,
size_t len, const uint8_t *data, bool *has_report_id); size_t len, const uint8_t *data, bool *has_report_id);
esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_handle(esp_hidh_dev_t *dev, uint16_t handle); //BLE Only esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_handle(esp_hidh_dev_t *dev, uint16_t handle); //BLE Only
void esp_hidh_process_event_data_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void esp_hidh_preprocess_event_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id,
void *event_data);
void esp_hidh_post_process_event_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id,
void *event_data); void *event_data);
void esp_hidh_dev_lock(esp_hidh_dev_t *dev); void esp_hidh_dev_lock(esp_hidh_dev_t *dev);
void esp_hidh_dev_unlock(esp_hidh_dev_t *dev); void esp_hidh_dev_unlock(esp_hidh_dev_t *dev);

View File

@ -59,6 +59,7 @@ static esp_event_loop_handle_t event_loop_handle;
static uint8_t *s_read_data_val = NULL; static uint8_t *s_read_data_val = NULL;
static uint16_t s_read_data_len = 0; static uint16_t s_read_data_len = 0;
static esp_gatt_status_t s_read_status = ESP_GATT_OK; static esp_gatt_status_t s_read_status = ESP_GATT_OK;
static esp_event_handler_t s_event_callback;
static esp_gatt_status_t read_char(esp_gatt_if_t gattc_if, uint16_t conn_id, uint16_t handle, esp_gatt_auth_req_t auth_req, uint8_t **out, uint16_t *out_len) static esp_gatt_status_t read_char(esp_gatt_if_t gattc_if, uint16_t conn_id, uint16_t handle, esp_gatt_auth_req_t auth_req, uint8_t **out, uint16_t *out_len)
{ {
@ -624,6 +625,18 @@ static void esp_ble_hidh_dev_dump(esp_hidh_dev_t *dev, FILE *fp)
} }
static void esp_ble_hidh_event_handler_wrapper(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id,
void *event_data)
{
esp_hidh_preprocess_event_handler(event_handler_arg, event_base, event_id, event_data);
if (s_event_callback) {
s_event_callback(event_handler_arg, event_base, event_id, event_data);
}
esp_hidh_post_process_event_handler(event_handler_arg, event_base, event_id, event_data);
}
esp_err_t esp_ble_hidh_init(const esp_hidh_config_t *config) esp_err_t esp_ble_hidh_init(const esp_hidh_config_t *config)
{ {
esp_err_t ret; esp_err_t ret;
@ -661,10 +674,10 @@ esp_err_t esp_ble_hidh_init(const esp_hidh_config_t *config)
break; break;
} }
WAIT_CB(); WAIT_CB();
s_event_callback = config->callback;
ret = esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, ret = esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID,
esp_hidh_process_event_data_handler, NULL); esp_ble_hidh_event_handler_wrapper, config->callback_arg);
ret |= esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, config->callback,
config->callback_arg);
} while (0); } while (0);
if (ret != ESP_OK) { if (ret != ESP_OK) {
@ -698,6 +711,8 @@ esp_err_t esp_ble_hidh_deinit(void)
} }
vSemaphoreDelete(s_ble_hidh_cb_semaphore); vSemaphoreDelete(s_ble_hidh_cb_semaphore);
s_ble_hidh_cb_semaphore = NULL; s_ble_hidh_cb_semaphore = NULL;
s_event_callback = NULL;
return err; return err;
} }

View File

@ -35,6 +35,7 @@ typedef struct {
typedef struct { typedef struct {
fixed_queue_t *connection_queue; /* Queue of connection */ fixed_queue_t *connection_queue; /* Queue of connection */
esp_event_loop_handle_t event_loop_handle; esp_event_loop_handle_t event_loop_handle;
esp_event_handler_t event_callback;
} hidh_local_param_t; } hidh_local_param_t;
static hidh_local_param_t hidh_local_param; static hidh_local_param_t hidh_local_param;
@ -180,6 +181,8 @@ static void free_local_param(void)
if (hidh_local_param.connection_queue) { if (hidh_local_param.connection_queue) {
fixed_queue_free(hidh_local_param.connection_queue, free); fixed_queue_free(hidh_local_param.connection_queue, free);
} }
hidh_local_param.event_callback = NULL;
} }
static void open_failed_cb(esp_hidh_dev_t *dev, esp_hidh_status_t status, esp_hidh_event_data_t *p, static void open_failed_cb(esp_hidh_dev_t *dev, esp_hidh_status_t status, esp_hidh_event_data_t *p,
@ -1000,6 +1003,18 @@ static void esp_bt_hidh_dev_dump(esp_hidh_dev_t *dev, FILE *fp)
} }
} }
static void esp_bt_hidh_event_handler_wrapper(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id,
void *event_data)
{
esp_hidh_preprocess_event_handler(event_handler_arg, event_base, event_id, event_data);
if (hidh_local_param.event_callback) {
hidh_local_param.event_callback(event_handler_arg, event_base, event_id, event_data);
}
esp_hidh_post_process_event_handler(event_handler_arg, event_base, event_id, event_data);
}
esp_err_t esp_bt_hidh_init(const esp_hidh_config_t *config) esp_err_t esp_bt_hidh_init(const esp_hidh_config_t *config)
{ {
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
@ -1027,10 +1042,10 @@ esp_err_t esp_bt_hidh_init(const esp_hidh_config_t *config)
ret = ESP_FAIL; ret = ESP_FAIL;
break; break;
} }
hidh_local_param.event_callback = config->callback;
ret = esp_event_handler_register_with(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, ret = esp_event_handler_register_with(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID,
esp_hidh_process_event_data_handler, NULL); esp_bt_hidh_event_handler_wrapper, config->callback_arg);
ret |= esp_event_handler_register_with(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID,
config->callback, config->callback_arg);
if (ret != ESP_OK) { if (ret != ESP_OK) {
ESP_LOGE(TAG, "event_loop register failed!"); ESP_LOGE(TAG, "event_loop register failed!");
ret = ESP_FAIL; ret = ESP_FAIL;

View File

@ -18,10 +18,7 @@ ESP_EVENT_DEFINE_BASE(ESP_HIDH_EVENTS);
static const char *TAG = "ESP_HIDH"; static const char *TAG = "ESP_HIDH";
static esp_hidh_dev_head_t s_esp_hidh_devices; static esp_hidh_dev_head_t s_esp_hidh_devices;
static esp_timer_handle_t s_esp_hidh_timer; static SemaphoreHandle_t s_esp_hidh_devices_semaphore = NULL;
static xSemaphoreHandle s_esp_hidh_devices_semaphore = NULL;
static void esp_hidh_dev_delay_free(void *arg);
static inline void lock_devices(void) static inline void lock_devices(void)
{ {
@ -74,17 +71,6 @@ esp_err_t esp_hidh_init(const esp_hidh_config_t *config)
TAILQ_INIT(&s_esp_hidh_devices); TAILQ_INIT(&s_esp_hidh_devices);
esp_timer_create_args_t timer_config = {
.callback = &esp_hidh_dev_delay_free,
.arg = NULL,
.name = "hidh_timer"
};
if ((err = esp_timer_create(&timer_config, &s_esp_hidh_timer)) != ESP_OK) {
ESP_LOGE(TAG, "%s create timer failed!", __func__);
return err;
}
s_esp_hidh_devices_semaphore = xSemaphoreCreateMutex(); s_esp_hidh_devices_semaphore = xSemaphoreCreateMutex();
if (s_esp_hidh_devices_semaphore == NULL) { if (s_esp_hidh_devices_semaphore == NULL) {
ESP_LOGE(TAG, "xSemaphoreCreateMutex failed!"); ESP_LOGE(TAG, "xSemaphoreCreateMutex failed!");
@ -108,8 +94,6 @@ esp_err_t esp_hidh_init(const esp_hidh_config_t *config)
if (err != ESP_OK) { if (err != ESP_OK) {
vSemaphoreDelete(s_esp_hidh_devices_semaphore); vSemaphoreDelete(s_esp_hidh_devices_semaphore);
s_esp_hidh_devices_semaphore = NULL; s_esp_hidh_devices_semaphore = NULL;
esp_timer_delete(s_esp_hidh_timer);
s_esp_hidh_timer = NULL;
} }
return err; return err;
@ -123,11 +107,6 @@ esp_err_t esp_hidh_deinit(void)
return err; return err;
} }
if (esp_timer_is_active(s_esp_hidh_timer)) {
ESP_LOGE(TAG, "Busy, try again later!");
return ESP_ERR_NOT_FINISHED;
}
if (!TAILQ_EMPTY(&s_esp_hidh_devices)) { if (!TAILQ_EMPTY(&s_esp_hidh_devices)) {
ESP_LOGE(TAG, "Please disconnect all devices first!"); ESP_LOGE(TAG, "Please disconnect all devices first!");
return err; return err;
@ -151,8 +130,6 @@ esp_err_t esp_hidh_deinit(void)
TAILQ_INIT(&s_esp_hidh_devices); TAILQ_INIT(&s_esp_hidh_devices);
vSemaphoreDelete(s_esp_hidh_devices_semaphore); vSemaphoreDelete(s_esp_hidh_devices_semaphore);
s_esp_hidh_devices_semaphore = NULL; s_esp_hidh_devices_semaphore = NULL;
esp_timer_delete(s_esp_hidh_timer);
s_esp_hidh_timer = NULL;
} }
return err; return err;
} }
@ -742,20 +719,6 @@ esp_err_t esp_hidh_dev_free_inner(esp_hidh_dev_t *dev)
return ret; return ret;
} }
static void esp_hidh_dev_delay_free(void *arg)
{
esp_hidh_dev_t *d = NULL;
esp_hidh_dev_t *next = NULL;
lock_devices();
TAILQ_FOREACH_SAFE(d, &s_esp_hidh_devices, devices, next) {
if (!d->in_use) {
TAILQ_REMOVE(&s_esp_hidh_devices, d, devices);
esp_hidh_dev_resources_free(d);
}
}
unlock_devices();
}
#if CONFIG_BLUEDROID_ENABLED #if CONFIG_BLUEDROID_ENABLED
esp_hidh_dev_t *esp_hidh_dev_get_by_bda(esp_bd_addr_t bda) esp_hidh_dev_t *esp_hidh_dev_get_by_bda(esp_bd_addr_t bda)
{ {
@ -805,10 +768,10 @@ esp_hidh_dev_t *esp_hidh_dev_get_by_conn_id(uint16_t conn_id)
/** /**
* The deep copy data append the end of the esp_hidh_event_data_t, move the data pointer to the correct address. This is * The deep copy data append the end of the esp_hidh_event_data_t, move the data pointer to the correct address. This is
* a workaround way, it's better to use flexiable array in the interface. * a workaround way, it's better to use flexible array in the interface.
*/ */
void esp_hidh_process_event_data_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void esp_hidh_preprocess_event_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id,
void *event_data) void *event_data)
{ {
esp_hidh_event_t event = (esp_hidh_event_t)event_id; esp_hidh_event_t event = (esp_hidh_event_t)event_id;
esp_hidh_event_data_t *param = (esp_hidh_event_data_t *)event_data; esp_hidh_event_data_t *param = (esp_hidh_event_data_t *)event_data;
@ -824,19 +787,25 @@ void esp_hidh_process_event_data_handler(void *event_handler_arg, esp_event_base
param->feature.data = (uint8_t *)param + sizeof(esp_hidh_event_data_t); param->feature.data = (uint8_t *)param + sizeof(esp_hidh_event_data_t);
} }
break; break;
default:
break;
}
}
void esp_hidh_post_process_event_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id,
void *event_data)
{
esp_hidh_event_t event = (esp_hidh_event_t)event_id;
esp_hidh_event_data_t *param = (esp_hidh_event_data_t *)event_data;
switch (event) {
case ESP_HIDH_OPEN_EVENT: case ESP_HIDH_OPEN_EVENT:
if (param->open.status != ESP_OK) { if (param->open.status != ESP_OK) {
if (s_esp_hidh_timer && !esp_timer_is_active(s_esp_hidh_timer) && esp_hidh_dev_free_inner(param->open.dev);
esp_timer_start_once(s_esp_hidh_timer, ESP_HIDH_DELAY_FREE_TO) != ESP_OK) {
ESP_LOGE(TAG, "%s set hidh timer failed!", __func__);
}
} }
break; break;
case ESP_HIDH_CLOSE_EVENT: case ESP_HIDH_CLOSE_EVENT:
if (s_esp_hidh_timer && !esp_timer_is_active(s_esp_hidh_timer) && esp_hidh_dev_free_inner(param->close.dev);
esp_timer_start_once(s_esp_hidh_timer, ESP_HIDH_DELAY_FREE_TO) != ESP_OK) {
ESP_LOGE(TAG, "%s set hidh timer failed!", __func__);
}
break; break;
default: default:
break; break;