1 // Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "hidd_le_prf_int.h"
16 #include <string.h>
17 #include "esp_log.h"
18
19 /// characteristic presentation information
20 struct prf_char_pres_fmt
21 {
22 /// Unit (The Unit is a UUID)
23 uint16_t unit;
24 /// Description
25 uint16_t description;
26 /// Format
27 uint8_t format;
28 /// Exponent
29 uint8_t exponent;
30 /// Name space
31 uint8_t name_space;
32 };
33
34 // HID report mapping table
35 static hid_report_map_t hid_rpt_map[HID_NUM_REPORTS];
36
37 // HID Report Map characteristic value
38 // Keyboard report descriptor (using format for Boot interface descriptor)
39 static const uint8_t hidReportMap[] = {
40 0x05, 0x01, // Usage Page (Generic Desktop)
41 0x09, 0x02, // Usage (Mouse)
42 0xA1, 0x01, // Collection (Application)
43 0x85, 0x01, // Report Id (1)
44 0x09, 0x01, // Usage (Pointer)
45 0xA1, 0x00, // Collection (Physical)
46 0x05, 0x09, // Usage Page (Buttons)
47 0x19, 0x01, // Usage Minimum (01) - Button 1
48 0x29, 0x03, // Usage Maximum (03) - Button 3
49 0x15, 0x00, // Logical Minimum (0)
50 0x25, 0x01, // Logical Maximum (1)
51 0x75, 0x01, // Report Size (1)
52 0x95, 0x03, // Report Count (3)
53 0x81, 0x02, // Input (Data, Variable, Absolute) - Button states
54 0x75, 0x05, // Report Size (5)
55 0x95, 0x01, // Report Count (1)
56 0x81, 0x01, // Input (Constant) - Padding or Reserved bits
57 0x05, 0x01, // Usage Page (Generic Desktop)
58 0x09, 0x30, // Usage (X)
59 0x09, 0x31, // Usage (Y)
60 0x09, 0x38, // Usage (Wheel)
61 0x15, 0x81, // Logical Minimum (-127)
62 0x25, 0x7F, // Logical Maximum (127)
63 0x75, 0x08, // Report Size (8)
64 0x95, 0x03, // Report Count (3)
65 0x81, 0x06, // Input (Data, Variable, Relative) - X & Y coordinate
66 0xC0, // End Collection
67 0xC0, // End Collection
68
69 0x05, 0x01, // Usage Pg (Generic Desktop)
70 0x09, 0x06, // Usage (Keyboard)
71 0xA1, 0x01, // Collection: (Application)
72 0x85, 0x02, // Report Id (2)
73 //
74 0x05, 0x07, // Usage Pg (Key Codes)
75 0x19, 0xE0, // Usage Min (224)
76 0x29, 0xE7, // Usage Max (231)
77 0x15, 0x00, // Log Min (0)
78 0x25, 0x01, // Log Max (1)
79 //
80 // Modifier byte
81 0x75, 0x01, // Report Size (1)
82 0x95, 0x08, // Report Count (8)
83 0x81, 0x02, // Input: (Data, Variable, Absolute)
84 //
85 // Reserved byte
86 0x95, 0x01, // Report Count (1)
87 0x75, 0x08, // Report Size (8)
88 0x81, 0x01, // Input: (Constant)
89 //
90 // LED report
91 0x95, 0x05, // Report Count (5)
92 0x75, 0x01, // Report Size (1)
93 0x05, 0x08, // Usage Pg (LEDs)
94 0x19, 0x01, // Usage Min (1)
95 0x29, 0x05, // Usage Max (5)
96 0x91, 0x02, // Output: (Data, Variable, Absolute)
97 //
98 // LED report padding
99 0x95, 0x01, // Report Count (1)
100 0x75, 0x03, // Report Size (3)
101 0x91, 0x01, // Output: (Constant)
102 //
103 // Key arrays (6 bytes)
104 0x95, 0x06, // Report Count (6)
105 0x75, 0x08, // Report Size (8)
106 0x15, 0x00, // Log Min (0)
107 0x25, 0x65, // Log Max (101)
108 0x05, 0x07, // Usage Pg (Key Codes)
109 0x19, 0x00, // Usage Min (0)
110 0x29, 0x65, // Usage Max (101)
111 0x81, 0x00, // Input: (Data, Array)
112 //
113 0xC0, // End Collection
114 //
115 0x05, 0x0C, // Usage Pg (Consumer Devices)
116 0x09, 0x01, // Usage (Consumer Control)
117 0xA1, 0x01, // Collection (Application)
118 0x85, 0x03, // Report Id (3)
119 0x09, 0x02, // Usage (Numeric Key Pad)
120 0xA1, 0x02, // Collection (Logical)
121 0x05, 0x09, // Usage Pg (Button)
122 0x19, 0x01, // Usage Min (Button 1)
123 0x29, 0x0A, // Usage Max (Button 10)
124 0x15, 0x01, // Logical Min (1)
125 0x25, 0x0A, // Logical Max (10)
126 0x75, 0x04, // Report Size (4)
127 0x95, 0x01, // Report Count (1)
128 0x81, 0x00, // Input (Data, Ary, Abs)
129 0xC0, // End Collection
130 0x05, 0x0C, // Usage Pg (Consumer Devices)
131 0x09, 0x86, // Usage (Channel)
132 0x15, 0xFF, // Logical Min (-1)
133 0x25, 0x01, // Logical Max (1)
134 0x75, 0x02, // Report Size (2)
135 0x95, 0x01, // Report Count (1)
136 0x81, 0x46, // Input (Data, Var, Rel, Null)
137 0x09, 0xE9, // Usage (Volume Up)
138 0x09, 0xEA, // Usage (Volume Down)
139 0x15, 0x00, // Logical Min (0)
140 0x75, 0x01, // Report Size (1)
141 0x95, 0x02, // Report Count (2)
142 0x81, 0x02, // Input (Data, Var, Abs)
143 0x09, 0xE2, // Usage (Mute)
144 0x09, 0x30, // Usage (Power)
145 0x09, 0x83, // Usage (Recall Last)
146 0x09, 0x81, // Usage (Assign Selection)
147 0x09, 0xB0, // Usage (Play)
148 0x09, 0xB1, // Usage (Pause)
149 0x09, 0xB2, // Usage (Record)
150 0x09, 0xB3, // Usage (Fast Forward)
151 0x09, 0xB4, // Usage (Rewind)
152 0x09, 0xB5, // Usage (Scan Next)
153 0x09, 0xB6, // Usage (Scan Prev)
154 0x09, 0xB7, // Usage (Stop)
155 0x15, 0x01, // Logical Min (1)
156 0x25, 0x0C, // Logical Max (12)
157 0x75, 0x04, // Report Size (4)
158 0x95, 0x01, // Report Count (1)
159 0x81, 0x00, // Input (Data, Ary, Abs)
160 0x09, 0x80, // Usage (Selection)
161 0xA1, 0x02, // Collection (Logical)
162 0x05, 0x09, // Usage Pg (Button)
163 0x19, 0x01, // Usage Min (Button 1)
164 0x29, 0x03, // Usage Max (Button 3)
165 0x15, 0x01, // Logical Min (1)
166 0x25, 0x03, // Logical Max (3)
167 0x75, 0x02, // Report Size (2)
168 0x81, 0x00, // Input (Data, Ary, Abs)
169 0xC0, // End Collection
170 0x81, 0x03, // Input (Const, Var, Abs)
171 0xC0, // End Collectionq
172
173 #if (SUPPORT_REPORT_VENDOR == true)
174 0x06, 0xFF, 0xFF, // Usage Page(Vendor defined)
175 0x09, 0xA5, // Usage(Vendor Defined)
176 0xA1, 0x01, // Collection(Application)
177 0x85, 0x04, // Report Id (4)
178 0x09, 0xA6, // Usage(Vendor defined)
179 0x09, 0xA9, // Usage(Vendor defined)
180 0x75, 0x08, // Report Size
181 0x95, 0x7F, // Report Count = 127 Btyes
182 0x91, 0x02, // Output(Data, Variable, Absolute)
183 0xC0, // End Collection
184 #endif
185
186 };
187
188 /// Battery Service Attributes Indexes
189 enum
190 {
191 BAS_IDX_SVC,
192
193 BAS_IDX_BATT_LVL_CHAR,
194 BAS_IDX_BATT_LVL_VAL,
195 BAS_IDX_BATT_LVL_NTF_CFG,
196 BAS_IDX_BATT_LVL_PRES_FMT,
197
198 BAS_IDX_NB,
199 };
200
201 #define HI_UINT16(a) (((a) >> 8) & 0xFF)
202 #define LO_UINT16(a) ((a) & 0xFF)
203 #define PROFILE_NUM 1
204 #define PROFILE_APP_IDX 0
205
206 struct gatts_profile_inst {
207 esp_gatts_cb_t gatts_cb;
208 uint16_t gatts_if;
209 uint16_t app_id;
210 uint16_t conn_id;
211 };
212
213 hidd_le_env_t hidd_le_env;
214
215 // HID report map length
216 uint8_t hidReportMapLen = sizeof(hidReportMap);
217 uint8_t hidProtocolMode = HID_PROTOCOL_MODE_REPORT;
218
219 // HID report mapping table
220 //static hidRptMap_t hidRptMap[HID_NUM_REPORTS];
221
222 // HID Information characteristic value
223 static const uint8_t hidInfo[HID_INFORMATION_LEN] = {
224 LO_UINT16(0x0111), HI_UINT16(0x0111), // bcdHID (USB HID version)
225 0x00, // bCountryCode
226 HID_KBD_FLAGS // Flags
227 };
228
229
230 // HID External Report Reference Descriptor
231 static uint16_t hidExtReportRefDesc = ESP_GATT_UUID_BATTERY_LEVEL;
232
233 // HID Report Reference characteristic descriptor, mouse input
234 static uint8_t hidReportRefMouseIn[HID_REPORT_REF_LEN] =
235 { HID_RPT_ID_MOUSE_IN, HID_REPORT_TYPE_INPUT };
236
237
238 // HID Report Reference characteristic descriptor, key input
239 static uint8_t hidReportRefKeyIn[HID_REPORT_REF_LEN] =
240 { HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT };
241
242 // HID Report Reference characteristic descriptor, LED output
243 static uint8_t hidReportRefLedOut[HID_REPORT_REF_LEN] =
244 { HID_RPT_ID_LED_OUT, HID_REPORT_TYPE_OUTPUT };
245
246 #if (SUPPORT_REPORT_VENDOR == true)
247
248 static uint8_t hidReportRefVendorOut[HID_REPORT_REF_LEN] =
249 {HID_RPT_ID_VENDOR_OUT, HID_REPORT_TYPE_OUTPUT};
250 #endif
251
252 // HID Report Reference characteristic descriptor, Feature
253 static uint8_t hidReportRefFeature[HID_REPORT_REF_LEN] =
254 { HID_RPT_ID_FEATURE, HID_REPORT_TYPE_FEATURE };
255
256 // HID Report Reference characteristic descriptor, consumer control input
257 static uint8_t hidReportRefCCIn[HID_REPORT_REF_LEN] =
258 { HID_RPT_ID_CC_IN, HID_REPORT_TYPE_INPUT };
259
260
261 /*
262 * Heart Rate PROFILE ATTRIBUTES
263 ****************************************************************************************
264 */
265
266 /// hid Service uuid
267 static uint16_t hid_le_svc = ATT_SVC_HID;
268 uint16_t hid_count = 0;
269 esp_gatts_incl_svc_desc_t incl_svc = {0};
270
271 #define CHAR_DECLARATION_SIZE (sizeof(uint8_t))
272 ///the uuid definition
273 static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE;
274 static const uint16_t include_service_uuid = ESP_GATT_UUID_INCLUDE_SERVICE;
275 static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE;
276 static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
277 static const uint16_t hid_info_char_uuid = ESP_GATT_UUID_HID_INFORMATION;
278 static const uint16_t hid_report_map_uuid = ESP_GATT_UUID_HID_REPORT_MAP;
279 static const uint16_t hid_control_point_uuid = ESP_GATT_UUID_HID_CONTROL_POINT;
280 static const uint16_t hid_report_uuid = ESP_GATT_UUID_HID_REPORT;
281 static const uint16_t hid_proto_mode_uuid = ESP_GATT_UUID_HID_PROTO_MODE;
282 static const uint16_t hid_kb_input_uuid = ESP_GATT_UUID_HID_BT_KB_INPUT;
283 static const uint16_t hid_kb_output_uuid = ESP_GATT_UUID_HID_BT_KB_OUTPUT;
284 static const uint16_t hid_mouse_input_uuid = ESP_GATT_UUID_HID_BT_MOUSE_INPUT;
285 static const uint16_t hid_repot_map_ext_desc_uuid = ESP_GATT_UUID_EXT_RPT_REF_DESCR;
286 static const uint16_t hid_report_ref_descr_uuid = ESP_GATT_UUID_RPT_REF_DESCR;
287 ///the propoty definition
288 static const uint8_t char_prop_notify = ESP_GATT_CHAR_PROP_BIT_NOTIFY;
289 static const uint8_t char_prop_read = ESP_GATT_CHAR_PROP_BIT_READ;
290 static const uint8_t char_prop_write_nr = ESP_GATT_CHAR_PROP_BIT_WRITE_NR;
291 static const uint8_t char_prop_read_write = ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_READ;
292 static const uint8_t char_prop_read_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_NOTIFY;
293 static const uint8_t char_prop_read_write_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_NOTIFY;
294
295 /// battary Service
296 static const uint16_t battary_svc = ESP_GATT_UUID_BATTERY_SERVICE_SVC;
297
298 static const uint16_t bat_lev_uuid = ESP_GATT_UUID_BATTERY_LEVEL;
299 static const uint8_t bat_lev_ccc[2] ={ 0x00, 0x00};
300 static const uint16_t char_format_uuid = ESP_GATT_UUID_CHAR_PRESENT_FORMAT;
301
302 static uint8_t battary_lev = 50;
303 /// Full HRS Database Description - Used to add attributes into the database
304 static const esp_gatts_attr_db_t bas_att_db[BAS_IDX_NB] =
305 {
306 // Battary Service Declaration
307 [BAS_IDX_SVC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
308 sizeof(uint16_t), sizeof(battary_svc), (uint8_t *)&battary_svc}},
309
310 // Battary level Characteristic Declaration
311 [BAS_IDX_BATT_LVL_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
312 CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
313
314 // Battary level Characteristic Value
315 [BAS_IDX_BATT_LVL_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&bat_lev_uuid, ESP_GATT_PERM_READ,
316 sizeof(uint8_t),sizeof(uint8_t), &battary_lev}},
317
318 // Battary level Characteristic - Client Characteristic Configuration Descriptor
319 [BAS_IDX_BATT_LVL_NTF_CFG] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
320 sizeof(uint16_t),sizeof(bat_lev_ccc), (uint8_t *)bat_lev_ccc}},
321
322 // Battary level report Characteristic Declaration
323 [BAS_IDX_BATT_LVL_PRES_FMT] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&char_format_uuid, ESP_GATT_PERM_READ,
324 sizeof(struct prf_char_pres_fmt), 0, NULL}},
325 };
326
327
328 /// Full Hid device Database Description - Used to add attributes into the database
329 static esp_gatts_attr_db_t hidd_le_gatt_db[HIDD_LE_IDX_NB] =
330 {
331 // HID Service Declaration
332 [HIDD_LE_IDX_SVC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid,
333 ESP_GATT_PERM_READ_ENCRYPTED, sizeof(uint16_t), sizeof(hid_le_svc),
334 (uint8_t *)&hid_le_svc}},
335
336 // HID Service Declaration
337 [HIDD_LE_IDX_INCL_SVC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&include_service_uuid,
338 ESP_GATT_PERM_READ,
339 sizeof(esp_gatts_incl_svc_desc_t), sizeof(esp_gatts_incl_svc_desc_t),
340 (uint8_t *)&incl_svc}},
341
342 // HID Information Characteristic Declaration
343 [HIDD_LE_IDX_HID_INFO_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
344 ESP_GATT_PERM_READ,
345 CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
346 (uint8_t *)&char_prop_read}},
347 // HID Information Characteristic Value
348 [HIDD_LE_IDX_HID_INFO_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_info_char_uuid,
349 ESP_GATT_PERM_READ,
350 sizeof(hids_hid_info_t), sizeof(hidInfo),
351 (uint8_t *)&hidInfo}},
352
353 // HID Control Point Characteristic Declaration
354 [HIDD_LE_IDX_HID_CTNL_PT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
355 ESP_GATT_PERM_READ,
356 CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
357 (uint8_t *)&char_prop_write_nr}},
358 // HID Control Point Characteristic Value
359 [HIDD_LE_IDX_HID_CTNL_PT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_control_point_uuid,
360 ESP_GATT_PERM_WRITE,
361 sizeof(uint8_t), 0,
362 NULL}},
363
364 // Report Map Characteristic Declaration
365 [HIDD_LE_IDX_REPORT_MAP_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
366 ESP_GATT_PERM_READ,
367 CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
368 (uint8_t *)&char_prop_read}},
369 // Report Map Characteristic Value
370 [HIDD_LE_IDX_REPORT_MAP_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_map_uuid,
371 ESP_GATT_PERM_READ,
372 HIDD_LE_REPORT_MAP_MAX_LEN, sizeof(hidReportMap),
373 (uint8_t *)&hidReportMap}},
374
375 // Report Map Characteristic - External Report Reference Descriptor
376 [HIDD_LE_IDX_REPORT_MAP_EXT_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_repot_map_ext_desc_uuid,
377 ESP_GATT_PERM_READ,
378 sizeof(uint16_t), sizeof(uint16_t),
379 (uint8_t *)&hidExtReportRefDesc}},
380
381 // Protocol Mode Characteristic Declaration
382 [HIDD_LE_IDX_PROTO_MODE_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
383 ESP_GATT_PERM_READ,
384 CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
385 (uint8_t *)&char_prop_read_write}},
386 // Protocol Mode Characteristic Value
387 [HIDD_LE_IDX_PROTO_MODE_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_proto_mode_uuid,
388 (ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE),
389 sizeof(uint8_t), sizeof(hidProtocolMode),
390 (uint8_t *)&hidProtocolMode}},
391
392 [HIDD_LE_IDX_REPORT_MOUSE_IN_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
393 ESP_GATT_PERM_READ,
394 CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
395 (uint8_t *)&char_prop_read_notify}},
396
397 [HIDD_LE_IDX_REPORT_MOUSE_IN_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
398 ESP_GATT_PERM_READ,
399 HIDD_LE_REPORT_MAX_LEN, 0,
400 NULL}},
401
402 [HIDD_LE_IDX_REPORT_MOUSE_IN_CCC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
403 (ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
404 sizeof(uint16_t), 0,
405 NULL}},
406
407 [HIDD_LE_IDX_REPORT_MOUSE_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
408 ESP_GATT_PERM_READ,
409 sizeof(hidReportRefMouseIn), sizeof(hidReportRefMouseIn),
410 hidReportRefMouseIn}},
411 // Report Characteristic Declaration
412 [HIDD_LE_IDX_REPORT_KEY_IN_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
413 ESP_GATT_PERM_READ,
414 CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
415 (uint8_t *)&char_prop_read_notify}},
416 // Report Characteristic Value
417 [HIDD_LE_IDX_REPORT_KEY_IN_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
418 ESP_GATT_PERM_READ,
419 HIDD_LE_REPORT_MAX_LEN, 0,
420 NULL}},
421 // Report KEY INPUT Characteristic - Client Characteristic Configuration Descriptor
422 [HIDD_LE_IDX_REPORT_KEY_IN_CCC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
423 (ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
424 sizeof(uint16_t), 0,
425 NULL}},
426 // Report Characteristic - Report Reference Descriptor
427 [HIDD_LE_IDX_REPORT_KEY_IN_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
428 ESP_GATT_PERM_READ,
429 sizeof(hidReportRefKeyIn), sizeof(hidReportRefKeyIn),
430 hidReportRefKeyIn}},
431
432 // Report Characteristic Declaration
433 [HIDD_LE_IDX_REPORT_LED_OUT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
434 ESP_GATT_PERM_READ,
435 CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
436 (uint8_t *)&char_prop_read_write}},
437
438 [HIDD_LE_IDX_REPORT_LED_OUT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
439 ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
440 HIDD_LE_REPORT_MAX_LEN, 0,
441 NULL}},
442 [HIDD_LE_IDX_REPORT_LED_OUT_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
443 ESP_GATT_PERM_READ,
444 sizeof(hidReportRefLedOut), sizeof(hidReportRefLedOut),
445 hidReportRefLedOut}},
446 #if (SUPPORT_REPORT_VENDOR == true)
447 // Report Characteristic Declaration
448 [HIDD_LE_IDX_REPORT_VENDOR_OUT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
449 ESP_GATT_PERM_READ,
450 CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
451 (uint8_t *)&char_prop_read_write_notify}},
452 [HIDD_LE_IDX_REPORT_VENDOR_OUT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
453 ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
454 HIDD_LE_REPORT_MAX_LEN, 0,
455 NULL}},
456 [HIDD_LE_IDX_REPORT_VENDOR_OUT_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
457 ESP_GATT_PERM_READ,
458 sizeof(hidReportRefVendorOut), sizeof(hidReportRefVendorOut),
459 hidReportRefVendorOut}},
460 #endif
461 // Report Characteristic Declaration
462 [HIDD_LE_IDX_REPORT_CC_IN_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
463 ESP_GATT_PERM_READ,
464 CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
465 (uint8_t *)&char_prop_read_notify}},
466 // Report Characteristic Value
467 [HIDD_LE_IDX_REPORT_CC_IN_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
468 ESP_GATT_PERM_READ,
469 HIDD_LE_REPORT_MAX_LEN, 0,
470 NULL}},
471 // Report KEY INPUT Characteristic - Client Characteristic Configuration Descriptor
472 [HIDD_LE_IDX_REPORT_CC_IN_CCC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
473 (ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE_ENCRYPTED),
474 sizeof(uint16_t), 0,
475 NULL}},
476 // Report Characteristic - Report Reference Descriptor
477 [HIDD_LE_IDX_REPORT_CC_IN_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
478 ESP_GATT_PERM_READ,
479 sizeof(hidReportRefCCIn), sizeof(hidReportRefCCIn),
480 hidReportRefCCIn}},
481
482 // Boot Keyboard Input Report Characteristic Declaration
483 [HIDD_LE_IDX_BOOT_KB_IN_REPORT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
484 ESP_GATT_PERM_READ,
485 CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
486 (uint8_t *)&char_prop_read_notify}},
487 // Boot Keyboard Input Report Characteristic Value
488 [HIDD_LE_IDX_BOOT_KB_IN_REPORT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_kb_input_uuid,
489 ESP_GATT_PERM_READ,
490 HIDD_LE_BOOT_REPORT_MAX_LEN, 0,
491 NULL}},
492 // Boot Keyboard Input Report Characteristic - Client Characteristic Configuration Descriptor
493 [HIDD_LE_IDX_BOOT_KB_IN_REPORT_NTF_CFG] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
494 (ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE),
495 sizeof(uint16_t), 0,
496 NULL}},
497
498 // Boot Keyboard Output Report Characteristic Declaration
499 [HIDD_LE_IDX_BOOT_KB_OUT_REPORT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
500 ESP_GATT_PERM_READ,
501 CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
502 (uint8_t *)&char_prop_read_write}},
503 // Boot Keyboard Output Report Characteristic Value
504 [HIDD_LE_IDX_BOOT_KB_OUT_REPORT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_kb_output_uuid,
505 (ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE),
506 HIDD_LE_BOOT_REPORT_MAX_LEN, 0,
507 NULL}},
508
509 // Boot Mouse Input Report Characteristic Declaration
510 [HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
511 ESP_GATT_PERM_READ,
512 CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
513 (uint8_t *)&char_prop_read_notify}},
514 // Boot Mouse Input Report Characteristic Value
515 [HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_mouse_input_uuid,
516 ESP_GATT_PERM_READ,
517 HIDD_LE_BOOT_REPORT_MAX_LEN, 0,
518 NULL}},
519 // Boot Mouse Input Report Characteristic - Client Characteristic Configuration Descriptor
520 [HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_NTF_CFG] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid,
521 (ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
522 sizeof(uint16_t), 0,
523 NULL}},
524
525 // Report Characteristic Declaration
526 [HIDD_LE_IDX_REPORT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid,
527 ESP_GATT_PERM_READ,
528 CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
529 (uint8_t *)&char_prop_read_write}},
530 // Report Characteristic Value
531 [HIDD_LE_IDX_REPORT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid,
532 ESP_GATT_PERM_READ,
533 HIDD_LE_REPORT_MAX_LEN, 0,
534 NULL}},
535 // Report Characteristic - Report Reference Descriptor
536 [HIDD_LE_IDX_REPORT_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid,
537 ESP_GATT_PERM_READ,
538 sizeof(hidReportRefFeature), sizeof(hidReportRefFeature),
539 hidReportRefFeature}},
540 };
541
542 static void hid_add_id_tbl(void);
543
esp_hidd_prf_cb_hdl(esp_gatts_cb_event_t event,esp_gatt_if_t gatts_if,esp_ble_gatts_cb_param_t * param)544 void esp_hidd_prf_cb_hdl(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
545 esp_ble_gatts_cb_param_t *param)
546 {
547 switch(event) {
548 case ESP_GATTS_REG_EVT: {
549 esp_ble_gap_config_local_icon (ESP_BLE_APPEARANCE_GENERIC_HID);
550 esp_hidd_cb_param_t hidd_param;
551 hidd_param.init_finish.state = param->reg.status;
552 if(param->reg.app_id == HIDD_APP_ID) {
553 hidd_le_env.gatt_if = gatts_if;
554 if(hidd_le_env.hidd_cb != NULL) {
555 (hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_REG_FINISH, &hidd_param);
556 hidd_le_create_service(hidd_le_env.gatt_if);
557 }
558 }
559 if(param->reg.app_id == BATTRAY_APP_ID) {
560 hidd_param.init_finish.gatts_if = gatts_if;
561 if(hidd_le_env.hidd_cb != NULL) {
562 (hidd_le_env.hidd_cb)(ESP_BAT_EVENT_REG, &hidd_param);
563 }
564
565 }
566
567 break;
568 }
569 case ESP_GATTS_CONF_EVT: {
570 break;
571 }
572 case ESP_GATTS_CREATE_EVT:
573 break;
574 case ESP_GATTS_CONNECT_EVT: {
575 esp_hidd_cb_param_t cb_param = {0};
576 ESP_LOGI(HID_LE_PRF_TAG, "HID connection establish, conn_id = %x",param->connect.conn_id);
577 memcpy(cb_param.connect.remote_bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
578 cb_param.connect.conn_id = param->connect.conn_id;
579 hidd_clcb_alloc(param->connect.conn_id, param->connect.remote_bda);
580 esp_ble_set_encryption(param->connect.remote_bda, ESP_BLE_SEC_ENCRYPT_NO_MITM);
581 if(hidd_le_env.hidd_cb != NULL) {
582 (hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_BLE_CONNECT, &cb_param);
583 }
584 break;
585 }
586 case ESP_GATTS_DISCONNECT_EVT: {
587 if(hidd_le_env.hidd_cb != NULL) {
588 (hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_BLE_DISCONNECT, NULL);
589 }
590 hidd_clcb_dealloc(param->disconnect.conn_id);
591 break;
592 }
593 case ESP_GATTS_CLOSE_EVT:
594 break;
595 case ESP_GATTS_WRITE_EVT: {
596 #if (SUPPORT_REPORT_VENDOR == true)
597 esp_hidd_cb_param_t cb_param = {0};
598 if (param->write.handle == hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_VENDOR_OUT_VAL] &&
599 hidd_le_env.hidd_cb != NULL) {
600 cb_param.vendor_write.conn_id = param->write.conn_id;
601 cb_param.vendor_write.report_id = HID_RPT_ID_VENDOR_OUT;
602 cb_param.vendor_write.length = param->write.len;
603 cb_param.vendor_write.data = param->write.value;
604 (hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT, &cb_param);
605 }
606 #endif
607 break;
608 }
609 case ESP_GATTS_CREAT_ATTR_TAB_EVT: {
610 if (param->add_attr_tab.num_handle == BAS_IDX_NB &&
611 param->add_attr_tab.svc_uuid.uuid.uuid16 == ESP_GATT_UUID_BATTERY_SERVICE_SVC &&
612 param->add_attr_tab.status == ESP_GATT_OK) {
613 incl_svc.start_hdl = param->add_attr_tab.handles[BAS_IDX_SVC];
614 incl_svc.end_hdl = incl_svc.start_hdl + BAS_IDX_NB -1;
615 ESP_LOGI(HID_LE_PRF_TAG, "%s(), start added the hid service to the stack database. incl_handle = %d",
616 __func__, incl_svc.start_hdl);
617 esp_ble_gatts_create_attr_tab(hidd_le_gatt_db, gatts_if, HIDD_LE_IDX_NB, 0);
618 }
619 if (param->add_attr_tab.num_handle == HIDD_LE_IDX_NB &&
620 param->add_attr_tab.status == ESP_GATT_OK) {
621 memcpy(hidd_le_env.hidd_inst.att_tbl, param->add_attr_tab.handles,
622 HIDD_LE_IDX_NB*sizeof(uint16_t));
623 ESP_LOGI(HID_LE_PRF_TAG, "hid svc handle = %x",hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC]);
624 hid_add_id_tbl();
625 esp_ble_gatts_start_service(hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC]);
626 } else {
627 esp_ble_gatts_start_service(param->add_attr_tab.handles[0]);
628 }
629 break;
630 }
631
632 default:
633 break;
634 }
635 }
636
hidd_le_create_service(esp_gatt_if_t gatts_if)637 void hidd_le_create_service(esp_gatt_if_t gatts_if)
638 {
639 /* Here should added the battery service first, because the hid service should include the battery service.
640 After finish to added the battery service then can added the hid service. */
641 esp_ble_gatts_create_attr_tab(bas_att_db, gatts_if, BAS_IDX_NB, 0);
642
643 }
644
hidd_le_init(void)645 void hidd_le_init(void)
646 {
647
648 // Reset the hid device target environment
649 memset(&hidd_le_env, 0, sizeof(hidd_le_env_t));
650 }
651
hidd_clcb_alloc(uint16_t conn_id,esp_bd_addr_t bda)652 void hidd_clcb_alloc (uint16_t conn_id, esp_bd_addr_t bda)
653 {
654 uint8_t i_clcb = 0;
655 hidd_clcb_t *p_clcb = NULL;
656
657 for (i_clcb = 0, p_clcb= hidd_le_env.hidd_clcb; i_clcb < HID_MAX_APPS; i_clcb++, p_clcb++) {
658 if (!p_clcb->in_use) {
659 p_clcb->in_use = true;
660 p_clcb->conn_id = conn_id;
661 p_clcb->connected = true;
662 memcpy (p_clcb->remote_bda, bda, ESP_BD_ADDR_LEN);
663 break;
664 }
665 }
666 return;
667 }
668
hidd_clcb_dealloc(uint16_t conn_id)669 bool hidd_clcb_dealloc (uint16_t conn_id)
670 {
671 uint8_t i_clcb = 0;
672 hidd_clcb_t *p_clcb = NULL;
673
674 for (i_clcb = 0, p_clcb= hidd_le_env.hidd_clcb; i_clcb < HID_MAX_APPS; i_clcb++, p_clcb++) {
675 memset(p_clcb, 0, sizeof(hidd_clcb_t));
676 return true;
677 }
678
679 return false;
680 }
681
682 static struct gatts_profile_inst heart_rate_profile_tab[PROFILE_NUM] = {
683 [PROFILE_APP_IDX] = {
684 .gatts_cb = esp_hidd_prf_cb_hdl,
685 .gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
686 },
687
688 };
689
gatts_event_handler(esp_gatts_cb_event_t event,esp_gatt_if_t gatts_if,esp_ble_gatts_cb_param_t * param)690 static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
691 esp_ble_gatts_cb_param_t *param)
692 {
693 /* If event is register event, store the gatts_if for each profile */
694 if (event == ESP_GATTS_REG_EVT) {
695 if (param->reg.status == ESP_GATT_OK) {
696 heart_rate_profile_tab[PROFILE_APP_IDX].gatts_if = gatts_if;
697 } else {
698 ESP_LOGI(HID_LE_PRF_TAG, "Reg app failed, app_id %04x, status %d\n",
699 param->reg.app_id,
700 param->reg.status);
701 return;
702 }
703 }
704
705 do {
706 int idx;
707 for (idx = 0; idx < PROFILE_NUM; idx++) {
708 if (gatts_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
709 gatts_if == heart_rate_profile_tab[idx].gatts_if) {
710 if (heart_rate_profile_tab[idx].gatts_cb) {
711 heart_rate_profile_tab[idx].gatts_cb(event, gatts_if, param);
712 }
713 }
714 }
715 } while (0);
716 }
717
718
hidd_register_cb(void)719 esp_err_t hidd_register_cb(void)
720 {
721 esp_err_t status;
722 status = esp_ble_gatts_register_callback(gatts_event_handler);
723 return status;
724 }
725
hidd_set_attr_value(uint16_t handle,uint16_t val_len,const uint8_t * value)726 void hidd_set_attr_value(uint16_t handle, uint16_t val_len, const uint8_t *value)
727 {
728 hidd_inst_t *hidd_inst = &hidd_le_env.hidd_inst;
729 if(hidd_inst->att_tbl[HIDD_LE_IDX_HID_INFO_VAL] <= handle &&
730 hidd_inst->att_tbl[HIDD_LE_IDX_REPORT_REP_REF] >= handle) {
731 esp_ble_gatts_set_attr_value(handle, val_len, value);
732 } else {
733 ESP_LOGE(HID_LE_PRF_TAG, "%s error:Invalid handle value.",__func__);
734 }
735 return;
736 }
737
hidd_get_attr_value(uint16_t handle,uint16_t * length,uint8_t ** value)738 void hidd_get_attr_value(uint16_t handle, uint16_t *length, uint8_t **value)
739 {
740 hidd_inst_t *hidd_inst = &hidd_le_env.hidd_inst;
741 if(hidd_inst->att_tbl[HIDD_LE_IDX_HID_INFO_VAL] <= handle &&
742 hidd_inst->att_tbl[HIDD_LE_IDX_REPORT_REP_REF] >= handle){
743 esp_ble_gatts_get_attr_value(handle, length, (const uint8_t **)value);
744 } else {
745 ESP_LOGE(HID_LE_PRF_TAG, "%s error:Invalid handle value.", __func__);
746 }
747
748 return;
749 }
750
hid_add_id_tbl(void)751 static void hid_add_id_tbl(void)
752 {
753 // Mouse input report
754 hid_rpt_map[0].id = hidReportRefMouseIn[0];
755 hid_rpt_map[0].type = hidReportRefMouseIn[1];
756 hid_rpt_map[0].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_MOUSE_IN_VAL];
757 hid_rpt_map[0].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_MOUSE_IN_VAL];
758 hid_rpt_map[0].mode = HID_PROTOCOL_MODE_REPORT;
759
760 // Key input report
761 hid_rpt_map[1].id = hidReportRefKeyIn[0];
762 hid_rpt_map[1].type = hidReportRefKeyIn[1];
763 hid_rpt_map[1].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_KEY_IN_VAL];
764 hid_rpt_map[1].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_KEY_IN_CCC];
765 hid_rpt_map[1].mode = HID_PROTOCOL_MODE_REPORT;
766
767 // Consumer Control input report
768 hid_rpt_map[2].id = hidReportRefCCIn[0];
769 hid_rpt_map[2].type = hidReportRefCCIn[1];
770 hid_rpt_map[2].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_CC_IN_VAL];
771 hid_rpt_map[2].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_CC_IN_CCC];
772 hid_rpt_map[2].mode = HID_PROTOCOL_MODE_REPORT;
773
774 // LED output report
775 hid_rpt_map[3].id = hidReportRefLedOut[0];
776 hid_rpt_map[3].type = hidReportRefLedOut[1];
777 hid_rpt_map[3].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_LED_OUT_VAL];
778 hid_rpt_map[3].cccdHandle = 0;
779 hid_rpt_map[3].mode = HID_PROTOCOL_MODE_REPORT;
780
781 // Boot keyboard input report
782 // Use same ID and type as key input report
783 hid_rpt_map[4].id = hidReportRefKeyIn[0];
784 hid_rpt_map[4].type = hidReportRefKeyIn[1];
785 hid_rpt_map[4].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_KB_IN_REPORT_VAL];
786 hid_rpt_map[4].cccdHandle = 0;
787 hid_rpt_map[4].mode = HID_PROTOCOL_MODE_BOOT;
788
789 // Boot keyboard output report
790 // Use same ID and type as LED output report
791 hid_rpt_map[5].id = hidReportRefLedOut[0];
792 hid_rpt_map[5].type = hidReportRefLedOut[1];
793 hid_rpt_map[5].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_KB_OUT_REPORT_VAL];
794 hid_rpt_map[5].cccdHandle = 0;
795 hid_rpt_map[5].mode = HID_PROTOCOL_MODE_BOOT;
796
797 // Boot mouse input report
798 // Use same ID and type as mouse input report
799 hid_rpt_map[6].id = hidReportRefMouseIn[0];
800 hid_rpt_map[6].type = hidReportRefMouseIn[1];
801 hid_rpt_map[6].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_VAL];
802 hid_rpt_map[6].cccdHandle = 0;
803 hid_rpt_map[6].mode = HID_PROTOCOL_MODE_BOOT;
804
805 // Feature report
806 hid_rpt_map[7].id = hidReportRefFeature[0];
807 hid_rpt_map[7].type = hidReportRefFeature[1];
808 hid_rpt_map[7].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_VAL];
809 hid_rpt_map[7].cccdHandle = 0;
810 hid_rpt_map[7].mode = HID_PROTOCOL_MODE_REPORT;
811
812
813 // Setup report ID map
814 hid_dev_register_reports(HID_NUM_REPORTS, hid_rpt_map);
815 }
816