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