1 /* This example code is in the Public Domain (or CC0 licensed, at your option.)
2 Unless required by applicable law or agreed to in writing, this software is
3 distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
4 CONDITIONS OF ANY KIND, either express or implied.
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "freertos/FreeRTOS.h"
11 #include "freertos/task.h"
12 #include "freertos/event_groups.h"
13 #include "esp_system.h"
14 #include "esp_wifi.h"
15 #include "esp_event.h"
16 #include "esp_log.h"
17 #include "nvs_flash.h"
18 #include "esp_bt.h"
19
20 #include "esp_hidd_prf_api.h"
21 #include "esp_bt_defs.h"
22 #include "esp_gap_ble_api.h"
23 #include "esp_gatts_api.h"
24 #include "esp_gatt_defs.h"
25 #include "esp_bt_main.h"
26 #include "esp_bt_device.h"
27 #include "driver/gpio.h"
28 #include "hid_dev.h"
29
30 /**
31 * Brief:
32 * This example Implemented BLE HID device profile related functions, in which the HID device
33 * has 4 Reports (1 is mouse, 2 is keyboard and LED, 3 is Consumer Devices, 4 is Vendor devices).
34 * Users can choose different reports according to their own application scenarios.
35 * BLE HID profile inheritance and USB HID class.
36 */
37
38 /**
39 * Note:
40 * 1. Win10 does not support vendor report , So SUPPORT_REPORT_VENDOR is always set to FALSE, it defines in hidd_le_prf_int.h
41 * 2. Update connection parameters are not allowed during iPhone HID encryption, slave turns
42 * off the ability to automatically update connection parameters during encryption.
43 * 3. After our HID device is connected, the iPhones write 1 to the Report Characteristic Configuration Descriptor,
44 * even if the HID encryption is not completed. This should actually be written 1 after the HID encryption is completed.
45 * we modify the permissions of the Report Characteristic Configuration Descriptor to `ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE_ENCRYPTED`.
46 * if you got `GATT_INSUF_ENCRYPTION` error, please ignore.
47 */
48
49 #define HID_DEMO_TAG "HID_DEMO"
50
51
52 static uint16_t hid_conn_id = 0;
53 static bool sec_conn = false;
54 static bool send_volum_up = false;
55 #define CHAR_DECLARATION_SIZE (sizeof(uint8_t))
56
57 static void hidd_event_callback(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param);
58
59 #define HIDD_DEVICE_NAME "HID"
60 static uint8_t hidd_service_uuid128[] = {
61 /* LSB <--------------------------------------------------------------------------------> MSB */
62 //first uuid, 16bit, [12],[13] is the value
63 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x12, 0x18, 0x00, 0x00,
64 };
65
66 static esp_ble_adv_data_t hidd_adv_data = {
67 .set_scan_rsp = false,
68 .include_name = true,
69 .include_txpower = true,
70 .min_interval = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec
71 .max_interval = 0x0010, //slave connection max interval, Time = max_interval * 1.25 msec
72 .appearance = 0x03c0, //HID Generic,
73 .manufacturer_len = 0,
74 .p_manufacturer_data = NULL,
75 .service_data_len = 0,
76 .p_service_data = NULL,
77 .service_uuid_len = sizeof(hidd_service_uuid128),
78 .p_service_uuid = hidd_service_uuid128,
79 .flag = 0x6,
80 };
81
82 static esp_ble_adv_params_t hidd_adv_params = {
83 .adv_int_min = 0x20,
84 .adv_int_max = 0x30,
85 .adv_type = ADV_TYPE_IND,
86 .own_addr_type = BLE_ADDR_TYPE_PUBLIC,
87 //.peer_addr =
88 //.peer_addr_type =
89 .channel_map = ADV_CHNL_ALL,
90 .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
91 };
92
93
hidd_event_callback(esp_hidd_cb_event_t event,esp_hidd_cb_param_t * param)94 static void hidd_event_callback(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param)
95 {
96 switch(event) {
97 case ESP_HIDD_EVENT_REG_FINISH: {
98 if (param->init_finish.state == ESP_HIDD_INIT_OK) {
99 //esp_bd_addr_t rand_addr = {0x04,0x11,0x11,0x11,0x11,0x05};
100 esp_ble_gap_set_device_name(HIDD_DEVICE_NAME);
101 esp_ble_gap_config_adv_data(&hidd_adv_data);
102
103 }
104 break;
105 }
106 case ESP_BAT_EVENT_REG: {
107 break;
108 }
109 case ESP_HIDD_EVENT_DEINIT_FINISH:
110 break;
111 case ESP_HIDD_EVENT_BLE_CONNECT: {
112 ESP_LOGI(HID_DEMO_TAG, "ESP_HIDD_EVENT_BLE_CONNECT");
113 hid_conn_id = param->connect.conn_id;
114 break;
115 }
116 case ESP_HIDD_EVENT_BLE_DISCONNECT: {
117 sec_conn = false;
118 ESP_LOGI(HID_DEMO_TAG, "ESP_HIDD_EVENT_BLE_DISCONNECT");
119 esp_ble_gap_start_advertising(&hidd_adv_params);
120 break;
121 }
122 case ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT: {
123 ESP_LOGI(HID_DEMO_TAG, "%s, ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT", __func__);
124 ESP_LOG_BUFFER_HEX(HID_DEMO_TAG, param->vendor_write.data, param->vendor_write.length);
125 }
126 default:
127 break;
128 }
129 return;
130 }
131
gap_event_handler(esp_gap_ble_cb_event_t event,esp_ble_gap_cb_param_t * param)132 static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
133 {
134 switch (event) {
135 case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
136 esp_ble_gap_start_advertising(&hidd_adv_params);
137 break;
138 case ESP_GAP_BLE_SEC_REQ_EVT:
139 for(int i = 0; i < ESP_BD_ADDR_LEN; i++) {
140 ESP_LOGD(HID_DEMO_TAG, "%x:",param->ble_security.ble_req.bd_addr[i]);
141 }
142 esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true);
143 break;
144 case ESP_GAP_BLE_AUTH_CMPL_EVT:
145 sec_conn = true;
146 esp_bd_addr_t bd_addr;
147 memcpy(bd_addr, param->ble_security.auth_cmpl.bd_addr, sizeof(esp_bd_addr_t));
148 ESP_LOGI(HID_DEMO_TAG, "remote BD_ADDR: %08x%04x",\
149 (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3],
150 (bd_addr[4] << 8) + bd_addr[5]);
151 ESP_LOGI(HID_DEMO_TAG, "address type = %d", param->ble_security.auth_cmpl.addr_type);
152 ESP_LOGI(HID_DEMO_TAG, "pair status = %s",param->ble_security.auth_cmpl.success ? "success" : "fail");
153 if(!param->ble_security.auth_cmpl.success) {
154 ESP_LOGE(HID_DEMO_TAG, "fail reason = 0x%x",param->ble_security.auth_cmpl.fail_reason);
155 }
156 break;
157 default:
158 break;
159 }
160 }
161
hid_demo_task(void * pvParameters)162 void hid_demo_task(void *pvParameters)
163 {
164 vTaskDelay(1000 / portTICK_PERIOD_MS);
165 while(1) {
166 vTaskDelay(2000 / portTICK_PERIOD_MS);
167 if (sec_conn) {
168 ESP_LOGI(HID_DEMO_TAG, "Send the volume");
169 send_volum_up = true;
170 //uint8_t key_vaule = {HID_KEY_A};
171 //esp_hidd_send_keyboard_value(hid_conn_id, 0, &key_vaule, 1);
172 esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_UP, true);
173 vTaskDelay(3000 / portTICK_PERIOD_MS);
174 if (send_volum_up) {
175 send_volum_up = false;
176 esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_UP, false);
177 esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_DOWN, true);
178 vTaskDelay(3000 / portTICK_PERIOD_MS);
179 esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_DOWN, false);
180 }
181 }
182 }
183 }
184
185
app_main(void)186 void app_main(void)
187 {
188 esp_err_t ret;
189
190 // Initialize NVS.
191 ret = nvs_flash_init();
192 if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
193 ESP_ERROR_CHECK(nvs_flash_erase());
194 ret = nvs_flash_init();
195 }
196 ESP_ERROR_CHECK( ret );
197
198 ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));
199
200 esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
201 ret = esp_bt_controller_init(&bt_cfg);
202 if (ret) {
203 ESP_LOGE(HID_DEMO_TAG, "%s initialize controller failed\n", __func__);
204 return;
205 }
206
207 ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
208 if (ret) {
209 ESP_LOGE(HID_DEMO_TAG, "%s enable controller failed\n", __func__);
210 return;
211 }
212
213 ret = esp_bluedroid_init();
214 if (ret) {
215 ESP_LOGE(HID_DEMO_TAG, "%s init bluedroid failed\n", __func__);
216 return;
217 }
218
219 ret = esp_bluedroid_enable();
220 if (ret) {
221 ESP_LOGE(HID_DEMO_TAG, "%s init bluedroid failed\n", __func__);
222 return;
223 }
224
225 if((ret = esp_hidd_profile_init()) != ESP_OK) {
226 ESP_LOGE(HID_DEMO_TAG, "%s init bluedroid failed\n", __func__);
227 }
228
229 ///register the callback function to the gap module
230 esp_ble_gap_register_callback(gap_event_handler);
231 esp_hidd_register_callbacks(hidd_event_callback);
232
233 /* set the security iocap & auth_req & key size & init key response key parameters to the stack*/
234 esp_ble_auth_req_t auth_req = ESP_LE_AUTH_BOND; //bonding with peer device after authentication
235 esp_ble_io_cap_t iocap = ESP_IO_CAP_NONE; //set the IO capability to No output No input
236 uint8_t key_size = 16; //the key size should be 7~16 bytes
237 uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
238 uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
239 esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t));
240 esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t));
241 esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t));
242 /* If your BLE device act as a Slave, the init_key means you hope which types of key of the master should distribute to you,
243 and the response key means which key you can distribute to the Master;
244 If your BLE device act as a master, the response key means you hope which types of key of the slave should distribute to you,
245 and the init key means which key you can distribute to the slave. */
246 esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t));
247 esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t));
248
249 xTaskCreate(&hid_demo_task, "hid_task", 2048, NULL, 5, NULL);
250 }
251