1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
25
26
32
33
34
35
40
41
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
64
65
66
67
68
69
70
71
72
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
152
153
159
160
161
162
163
164
165
166
167
170
171
172
173
174
175
176
177
178
182
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
210
211
212
216
217
218
219
220
221
222
227
228
229
230
232
233
234
235
236
237
238
239
240
241
242
245
246
247
248
249
250
251
252
253
254
255
256
260
261
262
263
264
265
266
267
268
269
/* ... */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_bt.h"12 includes
#if CONFIG_BT_NIMBLE_ENABLED
#include "host/ble_hs.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"/* ... */
#else
#include "esp_bt_defs.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_gatt_defs.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"/* ... */
#endif
#if CONFIG_BT_NIMBLE_ENABLED
#include "host/ble_hs.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#define ESP_BD_ADDR_STR "%02x:%02x:%02x:%02x:%02x:%02x"
#define ESP_BD_ADDR_HEX(addr) addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]/* ... */
#else
#include "esp_bt_defs.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_gatt_defs.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"/* ... */
#endif
#include "esp_hidh.h"
#include "esp_hid_gap.h"
static const char *TAG = "ESP_HIDH_DEMO";
#if CONFIG_BT_HID_HOST_ENABLED
static const char * remote_device_name = CONFIG_EXAMPLE_PEER_DEVICE_NAME;
#endif
#if !CONFIG_BT_NIMBLE_ENABLED
static char *bda2str(uint8_t *bda, char *str, size_t size)
{
if (bda == NULL || str == NULL || size < 18) {
return NULL;
}{...}
uint8_t *p = bda;
sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
p[0], p[1], p[2], p[3], p[4], p[5]);
return str;
}{...}
/* ... */#endif
void hidh_callback(void *handler_args, esp_event_base_t base, int32_t id, void *event_data)
{
esp_hidh_event_t event = (esp_hidh_event_t)id;
esp_hidh_event_data_t *param = (esp_hidh_event_data_t *)event_data;
switch (event) {
case ESP_HIDH_OPEN_EVENT: {
if (param->open.status == ESP_OK) {
const uint8_t *bda = esp_hidh_dev_bda_get(param->open.dev);
if (bda) {
ESP_LOGI(TAG, ESP_BD_ADDR_STR " OPEN: %s", ESP_BD_ADDR_HEX(bda), esp_hidh_dev_name_get(param->open.dev));
esp_hidh_dev_dump(param->open.dev, stdout);
}{...}
}{...} else {
ESP_LOGE(TAG, " OPEN failed!");
}{...}
break;
}{...}
... case ESP_HIDH_BATTERY_EVENT: {
const uint8_t *bda = esp_hidh_dev_bda_get(param->battery.dev);
if (bda) {
ESP_LOGI(TAG, ESP_BD_ADDR_STR " BATTERY: %d%%", ESP_BD_ADDR_HEX(bda), param->battery.level);
}{...}
break;
}{...}
... case ESP_HIDH_INPUT_EVENT: {
const uint8_t *bda = esp_hidh_dev_bda_get(param->input.dev);
if (bda) {
ESP_LOGI(TAG, ESP_BD_ADDR_STR " INPUT: %8s, MAP: %2u, ID: %3u, Len: %d, Data:", ESP_BD_ADDR_HEX(bda), esp_hid_usage_str(param->input.usage), param->input.map_index, param->input.report_id, param->input.length);
ESP_LOG_BUFFER_HEX(TAG, param->input.data, param->input.length);
}{...}
break;
}{...}
... case ESP_HIDH_FEATURE_EVENT: {
const uint8_t *bda = esp_hidh_dev_bda_get(param->feature.dev);
if (bda) {
ESP_LOGI(TAG, ESP_BD_ADDR_STR " FEATURE: %8s, MAP: %2u, ID: %3u, Len: %d", ESP_BD_ADDR_HEX(bda),
esp_hid_usage_str(param->feature.usage), param->feature.map_index, param->feature.report_id,
param->feature.length);
ESP_LOG_BUFFER_HEX(TAG, param->feature.data, param->feature.length);
}{...}
break;
}{...}
... case ESP_HIDH_CLOSE_EVENT: {
const uint8_t *bda = esp_hidh_dev_bda_get(param->close.dev);
if (bda) {
ESP_LOGI(TAG, ESP_BD_ADDR_STR " CLOSE: %s", ESP_BD_ADDR_HEX(bda), esp_hidh_dev_name_get(param->close.dev));
}{...}
break;
}{...}
... default:
ESP_LOGI(TAG, "EVENT: %d", event);
break;...
}{...}
}{...}
#define SCAN_DURATION_SECONDS 5
void hid_demo_task(void *pvParameters)
{
size_t results_len = 0;
esp_hid_scan_result_t *results = NULL;
ESP_LOGI(TAG, "SCAN...");
esp_hid_scan(SCAN_DURATION_SECONDS, &results_len, &results);
ESP_LOGI(TAG, "SCAN: %u results", results_len);
if (results_len) {
esp_hid_scan_result_t *r = results;
esp_hid_scan_result_t *cr = NULL;
while (r) {
printf(" %s: " ESP_BD_ADDR_STR ", ", (r->transport == ESP_HID_TRANSPORT_BLE) ? "BLE" : "BT ", ESP_BD_ADDR_HEX(r->bda));
printf("RSSI: %d, ", r->rssi);
printf("USAGE: %s, ", esp_hid_usage_str(r->usage));
#if CONFIG_BT_BLE_ENABLED
if (r->transport == ESP_HID_TRANSPORT_BLE) {
cr = r;
printf("APPEARANCE: 0x%04x, ", r->ble.appearance);
printf("ADDR_TYPE: '%s', ", ble_addr_type_str(r->ble.addr_type));
}{...}
/* ... */#endif
#if CONFIG_BT_NIMBLE_ENABLED
if (r->transport == ESP_HID_TRANSPORT_BLE) {
cr = r;
printf("APPEARANCE: 0x%04x, ", r->ble.appearance);
printf("ADDR_TYPE: '%d', ", r->ble.addr_type);
}{...}
/* ... */#endif
#if CONFIG_BT_HID_HOST_ENABLED
if (r->transport == ESP_HID_TRANSPORT_BT) {
cr = r;
printf("COD: %s[", esp_hid_cod_major_str(r->bt.cod.major));
esp_hid_cod_minor_print(r->bt.cod.minor, stdout);
printf("] srv 0x%03x, ", r->bt.cod.service);
print_uuid(&r->bt.uuid);
printf(", ");
if (strncmp(r->name, remote_device_name, strlen(remote_device_name)) == 0) {
break;
}{...}
}{...}
/* ... */#endif
printf("NAME: %s ", r->name ? r->name : "");
printf("\n");
r = r->next;
}{...}
#if CONFIG_BT_HID_HOST_ENABLED
if (cr && strncmp(cr->name, remote_device_name, strlen(remote_device_name)) == 0) {
esp_hidh_dev_open(cr->bda, cr->transport, cr->ble.addr_type);
}{...}
/* ... */#else
if (cr) {
esp_hidh_dev_open(cr->bda, cr->transport, cr->ble.addr_type);
}{...}
/* ... */#endif
esp_hid_scan_results_free(results);
}{...}
vTaskDelete(NULL);
}{...}
#if CONFIG_BT_NIMBLE_ENABLED
void ble_hid_host_task(void *param)
{
ESP_LOGI(TAG, "BLE Host Task Started");
nimble_port_run();
nimble_port_freertos_deinit();
}{...}
void ble_store_config_init(void);/* ... */
#endif
void app_main(void)
{
esp_err_t ret;
#if HID_HOST_MODE == HIDH_IDLE_MODE
ESP_LOGE(TAG, "Please turn on BT HID host or BLE!");
return;/* ... */
#endif
ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}{...}
ESP_ERROR_CHECK( ret );
ESP_LOGI(TAG, "setting hid gap, mode:%d", HID_HOST_MODE);
ESP_ERROR_CHECK( esp_hid_gap_init(HID_HOST_MODE) );
#if CONFIG_BT_BLE_ENABLED
ESP_ERROR_CHECK( esp_ble_gattc_register_callback(esp_hidh_gattc_event_handler) );
#endif
esp_hidh_config_t config = {
.callback = hidh_callback,
.event_stack_size = 4096,
.callback_arg = NULL,
}{...};
ESP_ERROR_CHECK( esp_hidh_init(&config) );
#if !CONFIG_BT_NIMBLE_ENABLED
char bda_str[18] = {0};
ESP_LOGI(TAG, "Own address:[%s]", bda2str((uint8_t *)esp_bt_dev_get_address(), bda_str, sizeof(bda_str)));/* ... */
#endif
#if CONFIG_BT_NIMBLE_ENABLED
ble_store_config_init();
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
ret = esp_nimble_enable(ble_hid_host_task);
if (ret) {
ESP_LOGE(TAG, "esp_nimble_enable failed: %d", ret);
}{...}
vTaskDelay(200);
uint8_t own_addr_type = 0;
int rc;
uint8_t addr_val[6] = {0};
rc = ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, NULL, NULL);
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
ESP_LOGI(TAG, "error determining address type; rc=%d\n", rc);
return;
}{...}
rc = ble_hs_id_copy_addr(own_addr_type, addr_val, NULL);
ESP_LOGI(TAG, "Device Address: ");
ESP_LOGI(TAG, "%02x:%02x:%02x:%02x:%02x:%02x \n", addr_val[5], addr_val[4], addr_val[3],
addr_val[2], addr_val[1], addr_val[0]);
/* ... */
#endif
xTaskCreate(&hid_demo_task, "hid_task", 6 * 1024, NULL, 2, NULL);
}{...}