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