diff --git a/components/esp_hid/private/esp_hidd_private.h b/components/esp_hid/private/esp_hidd_private.h index 544fd9b58a..0b947e3ee9 100644 --- a/components/esp_hid/private/esp_hidd_private.h +++ b/components/esp_hid/private/esp_hidd_private.h @@ -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 diff --git a/components/esp_hid/private/esp_hidh_private.h b/components/esp_hid/private/esp_hidh_private.h index 1cd5e50605..a052d06809 100644 --- a/components/esp_hid/private/esp_hidh_private.h +++ b/components/esp_hid/private/esp_hidh_private.h @@ -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 diff --git a/components/esp_hid/src/ble_hidd.c b/components/esp_hid/src/ble_hidd.c index b62ce623a2..69061ae4dc 100644 --- a/components/esp_hid/src/ble_hidd.c +++ b/components/esp_hid/src/ble_hidd.c @@ -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) { diff --git a/components/esp_hid/src/ble_hidh.c b/components/esp_hid/src/ble_hidh.c index a56eb04c44..731ac75e7a 100644 --- a/components/esp_hid/src/ble_hidh.c +++ b/components/esp_hid/src/ble_hidh.c @@ -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) diff --git a/components/esp_hid/src/bt_hidh.c b/components/esp_hid/src/bt_hidh.c index cfaf23584b..d30ecffbcb 100644 --- a/components/esp_hid/src/bt_hidh.c +++ b/components/esp_hid/src/bt_hidh.c @@ -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; } } } diff --git a/components/esp_hid/src/esp_hidd.c b/components/esp_hid/src/esp_hidd.c index e6e3c57988..972c486407 100644 --- a/components/esp_hid/src/esp_hidd.c +++ b/components/esp_hid/src/esp_hidd.c @@ -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; + } +} diff --git a/components/esp_hid/src/esp_hidh.c b/components/esp_hid/src/esp_hidh.c index 3d318427f4..74b3b95619 100644 --- a/components/esp_hid/src/esp_hidh.c +++ b/components/esp_hid/src/esp_hidh.c @@ -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 */