fix deep copy bugs for esp_hid component

Closes https://github.com/espressif/esp-idf/issues/6217
Closes https://github.com/espressif/esp-idf/issues/7169
This commit is contained in:
liqigan
2021-09-07 16:49:49 +08:00
parent 1e0219f16f
commit 9049974d6b
7 changed files with 195 additions and 54 deletions

View File

@@ -37,6 +37,9 @@ struct esp_hidd_dev_s {
typedef struct esp_hidd_dev_s esp_hidd_dev_t;
void esp_hidd_process_event_data_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id,
void *event_data);
#ifdef __cplusplus
}
#endif

View File

@@ -114,6 +114,8 @@ 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_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 *event_data);
#ifdef __cplusplus
}
#endif

View File

@@ -559,23 +559,43 @@ static void hid_event_handler(esp_ble_hidd_dev_t *dev, int device_index, esp_gat
} else {
ESP_LOGV(TAG, "HID WRITE %8s %7s %6s id: %d, len: %d", esp_hid_usage_str(map->usage), esp_hid_report_type_str(map->report_type), esp_hid_protocol_mode_str(map->protocol_mode), map->report_id, param->write.len);
esp_hidd_event_data_t cb_param = {0};
esp_hidd_event_data_t *p_cb_param = NULL;
size_t event_data_size = sizeof(esp_hidd_event_data_t);
if (param->write.len > 0 && param->write.value) {
event_data_size += param->write.len;
}
if ((p_cb_param = (esp_hidd_event_data_t *)malloc(event_data_size)) == NULL) {
ESP_LOGE(TAG, "%s malloc event data failed!", __func__);
break;
}
memset(p_cb_param, 0, event_data_size);
if (param->write.len > 0 && param->write.value) {
memcpy(((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t), param->write.value,
param->write.len);
}
if (map->report_type == ESP_HID_REPORT_TYPE_OUTPUT) {
cb_param.output.dev = dev->dev;
cb_param.output.report_id = map->report_id;
cb_param.output.usage = map->usage;
cb_param.output.length = param->write.len;
cb_param.output.data = param->write.value;
cb_param.output.map_index = device_index;
esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_OUTPUT_EVENT, &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY);
p_cb_param->output.dev = dev->dev;
p_cb_param->output.report_id = map->report_id;
p_cb_param->output.usage = map->usage;
p_cb_param->output.length = param->write.len;
p_cb_param->output.data = param->write.value; /* move the data pointer in the wrapper loop handler */
p_cb_param->output.map_index = device_index;
esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_OUTPUT_EVENT, p_cb_param, event_data_size, portMAX_DELAY);
} else {
cb_param.feature.dev = dev->dev;
cb_param.feature.report_id = map->report_id;
cb_param.feature.usage = map->usage;
cb_param.feature.length = param->write.len;
cb_param.feature.data = param->write.value;
cb_param.feature.map_index = device_index;
esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_FEATURE_EVENT, &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY);
p_cb_param->feature.dev = dev->dev;
p_cb_param->feature.report_id = map->report_id;
p_cb_param->feature.usage = map->usage;
p_cb_param->feature.length = param->write.len;
p_cb_param->feature.data = param->write.value; /* move the data pointer in the wrapper loop handler */
p_cb_param->feature.map_index = device_index;
esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_FEATURE_EVENT, p_cb_param, event_data_size, portMAX_DELAY);
}
if (p_cb_param) {
free(p_cb_param);
p_cb_param = NULL;
}
}
}
@@ -985,6 +1005,12 @@ esp_err_t esp_ble_hidd_dev_init(esp_hidd_dev_t *dev_p, const esp_hid_device_conf
dev_p->event_handler_register = esp_ble_hidd_dev_event_handler_register;
dev_p->event_handler_unregister = esp_ble_hidd_dev_event_handler_unregister;
ret = esp_ble_hidd_dev_event_handler_register(s_dev, esp_hidd_process_event_data_handler, ESP_EVENT_ANY_ID);
if (ret != ESP_OK) {
ble_hidd_dev_free();
return ret;
}
if (callback != NULL) {
ret = esp_ble_hidd_dev_event_handler_register(s_dev, callback, ESP_EVENT_ANY_ID);
if (ret != ESP_OK) {

View File

@@ -475,22 +475,44 @@ void esp_hidh_gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gatt
} else {
report = esp_hidh_dev_get_report_by_handle(dev, p_data->notify.handle);
if (report) {
esp_hidh_event_data_t *p_param = NULL;
size_t event_data_size = sizeof(esp_hidh_event_data_t);
if (p_data->notify.value_len && p_data->notify.value) {
event_data_size += p_data->notify.value_len;
}
if ((p_param = (esp_hidh_event_data_t *)malloc(event_data_size)) == NULL) {
ESP_LOGE(TAG, "%s malloc event data failed!", __func__);
break;
}
memset(p_param, 0, event_data_size);
if (p_data->notify.value_len && p_data->notify.value) {
memcpy(((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t), p_data->notify.value,
p_data->notify.value_len);
}
if (report->report_type == ESP_HID_REPORT_TYPE_FEATURE) {
p.feature.dev = dev;
p.feature.map_index = report->map_index;
p.feature.report_id = report->report_id;
p.feature.usage = report->usage;
p.feature.data = p_data->notify.value;
p.feature.length = p_data->notify.value_len;
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY);
p_param->feature.dev = dev;
p_param->feature.map_index = report->map_index;
p_param->feature.report_id = report->report_id;
p_param->feature.usage = report->usage;
p_param->feature.length = p_data->notify.value_len;
p_param->feature.data = p_data->notify.value;
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, p_param, event_data_size, portMAX_DELAY);
} else {
p.input.dev = dev;
p.input.map_index = report->map_index;
p.input.report_id = report->report_id;
p.input.usage = report->usage;
p.input.data = p_data->notify.value;
p.input.length = p_data->notify.value_len;
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY);
p_param->input.dev = dev;
p_param->input.map_index = report->map_index;
p_param->input.report_id = report->report_id;
p_param->input.usage = report->usage;
p_param->input.length = p_data->notify.value_len;
p_param->input.data = p_data->notify.value;
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, p_param, event_data_size, portMAX_DELAY);
}
if (p_param) {
free(p_param);
p_param = NULL;
}
}
}
@@ -620,22 +642,37 @@ esp_err_t esp_ble_hidh_init(const esp_hidh_config_t *config)
.task_stack_size = config->event_stack_size > 0 ? config->event_stack_size : 2048,
.task_core_id = tskNO_AFFINITY
};
ret = esp_event_loop_create(&event_task_args, &event_loop_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "esp_event_loop_create failed!");
return ESP_FAIL;
}
do {
ret = esp_event_loop_create(&event_task_args, &event_loop_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "%s esp_event_loop_create failed!", __func__);
break;
}
ret = esp_ble_gattc_app_register(0);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "esp_ble_gattc_app_register failed!");
break;
}
WAIT_CB();
ret = esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID,
esp_hidh_process_event_data_handler, NULL);
ret |= esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, config->callback,
NULL);
} while (0);
ret = esp_ble_gattc_app_register(0);
if (ret != ESP_OK) {
vSemaphoreDelete(s_ble_hidh_cb_semaphore);
s_ble_hidh_cb_semaphore = NULL;
return ret;
if (event_loop_handle) {
esp_event_loop_delete(event_loop_handle);
}
if (s_ble_hidh_cb_semaphore) {
vSemaphoreDelete(s_ble_hidh_cb_semaphore);
s_ble_hidh_cb_semaphore = NULL;
}
}
WAIT_CB();
esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, config->callback, NULL);
return ESP_OK;
return ret;
}
esp_err_t esp_ble_hidh_deinit(void)

View File

@@ -333,6 +333,8 @@ esp_err_t esp_bt_hidh_init(const esp_hidh_config_t *config)
ESP_LOGE(TAG, "esp_event_loop_create failed!");
return ret;
}
esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID,
esp_hidh_process_event_data_handler, NULL);
esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, config->callback, NULL);
BTA_HhEnable(0, bta_hh_cb);
return ESP_OK;
@@ -401,21 +403,40 @@ void bta_hh_co_data(uint8_t handle, uint8_t *p_rpt, uint16_t len, tBTA_HH_PROTO_
}
if (event_loop_handle) {
esp_hidh_event_data_t p = {0};
esp_hidh_event_data_t *p_param = NULL;
size_t event_data_size = sizeof(esp_hidh_event_data_t);
if (len > 1 && p_rpt) {
event_data_size += (len - 1);
}
if ((p_param = (esp_hidh_event_data_t *)malloc(event_data_size)) == NULL) {
ESP_LOGE(TAG, "%s malloc event data failed!", __func__);
return;
}
memset(p_param, 0, event_data_size);
if (len > 1 && p_rpt) {
memcpy(((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t), p_rpt + 1, len - 1);
}
if (report->report_type == ESP_HID_REPORT_TYPE_FEATURE) {
p.feature.dev = dev;
p.feature.report_id = report->report_id;
p.feature.usage = report->usage;
p.feature.data = p_rpt + 1;
p.feature.length = len - 1;
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY);
p_param->feature.dev = dev;
p_param->feature.report_id = report->report_id;
p_param->feature.usage = report->usage;
p_param->feature.data = p_rpt + 1;
p_param->feature.length = len - 1;
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, p_param, event_data_size, portMAX_DELAY);
} else {
p.input.dev = dev;
p.input.report_id = report->report_id;
p.input.usage = report->usage;
p.input.data = p_rpt + 1;
p.input.length = len - 1;
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY);
p_param->input.dev = dev;
p_param->input.report_id = report->report_id;
p_param->input.usage = report->usage;
p_param->input.data = p_rpt + 1;
p_param->input.length = len - 1;
esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, p_param, event_data_size, portMAX_DELAY);
}
if (p_param) {
free(p_param);
p_param = NULL;
}
}
}

View File

@@ -119,3 +119,29 @@ esp_err_t esp_hidd_dev_event_handler_unregister(esp_hidd_dev_t *dev, esp_event_h
}
return dev->event_handler_unregister(dev->dev, callback, event);
}
/**
* The deep copy data append the end of the esp_hidd_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.
*/
void esp_hidd_process_event_data_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id,
void *event_data)
{
esp_hidd_event_t event = (esp_hidd_event_t)event_id;
esp_hidd_event_data_t *param = (esp_hidd_event_data_t *)event_data;
switch (event) {
case ESP_HIDD_OUTPUT_EVENT:
if (param->output.length && param->output.data) {
param->output.data = (uint8_t *)param + sizeof(esp_hidd_event_data_t);
}
break;
case ESP_HIDD_FEATURE_EVENT:
if (param->feature.length && param->feature.data) {
param->feature.data = (uint8_t *)param + sizeof(esp_hidd_event_data_t);
}
break;
default:
break;
}
}

View File

@@ -486,4 +486,30 @@ esp_hidh_dev_t *esp_hidh_dev_get_by_conn_id(uint16_t conn_id)
#endif /* CONFIG_GATTC_ENABLE */
return NULL;
}
/**
* 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.
*/
void esp_hidh_process_event_data_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_INPUT_EVENT:
if (param->input.length && param->input.data) {
param->input.data = (uint8_t *)param + sizeof(esp_hidh_event_data_t);
}
break;
case ESP_HIDH_FEATURE_EVENT:
if (param->feature.length && param->feature.data) {
param->feature.data = (uint8_t *)param + sizeof(esp_hidh_event_data_t);
}
break;
default:
break;
}
}
#endif /* CONFIG_BLUEDROID_ENABLED */