1 /**
2 *****************************************************************************************
3 *
4 * @file hids.c
5 *
6 * @brief THe Implementation of Human Input Device Service.
7 *
8 *****************************************************************************************
9 * @attention
10 #####Copyright (c) 2019 GOODIX
11 All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions are met:
15 * Redistributions of source code must retain the above copyright
16 notice, this list of conditions and the following disclaimer.
17 * Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in the
19 documentation and/or other materials provided with the distribution.
20 * Neither the name of GOODIX nor the names of its contributors may be used
21 to endorse or promote products derived from this software without
22 specific prior written permission.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 POSSIBILITY OF SUCH DAMAGE.
35 *****************************************************************************************
36 */
37
38 /*
39 * INCLUDE FILES
40 *****************************************************************************************
41 */
42 #include "hids.h"
43 #include "ble_prf_types.h"
44 #include "ble_prf_utils.h"
45 #include "utility.h"
46 #define INDEX_0 0
47 #define INDEX_1 1
48 #define INDEX_2 2
49 #define INDEX_3 3
50 #define INDEX_4 4
51 /*
52 * DEFINES
53 *******************************************************************************
54 */
55 #define IN_REPORT_MAX_COUNT 3 /**< Maximum support input report count. */
56 /**< Maximum size of a Boot Keyboard Input Report (as per Appendix B in Device Class Definition
57 * for Human Interface Devices (HID), Version 1.11). */
58 #define HIDS_BOOT_KB_IN_REPORT_MAX_SIZE 8
59 /**< Maximum size of a Boot Keyboard Output Report (as per Appendix B in Device Class Definition
60 * for Human Interface Devices (HID), Version 1.11). */
61 #define HIDS_BOOT_KB_OUT_REPORT_MAX_SIZE 1
62 /**< Minimum size of a Boot Mouse Input Report (as per Appendix B in Device Class Definition
63 * for Human Interface Devices (HID), Version 1.11). */
64 #define HIDS_BOOT_MOUSE_IN_REPORT_MIN_SIZE 3
65 /**< Maximum size of a Boot Mouse Input Report (as per Appendix B in Device Class Definition
66 * for Human Interface Devices (HID), Version 1.11). */
67 #define HIDS_BOOT_MOUSE_IN_REPORT_MAX_SIZE 8
68
69
70 // Protocol Mode values
71 #define PROTOCOL_MODE_BOOT 0x00 /**< Boot Protocol Mode. */
72 #define PROTOCOL_MODE_REPORT 0x01 /**< Report Protocol Mode. */
73
74 // HID Control Point values
75 #define HIDS_CONTROL_POINT_SUSPEND 0x00 /**< Suspend command. */
76 #define HIDS_CONTROL_POINT_EXIT_SUSPEND 0x01 /**< Exit Suspend command. */
77 /**< Default value for the Protocol Mode characteristic. */
78 #define DEFAULT_PROTOCOL_MODE PROTOCOL_MODE_REPORT
79 /**< Initial value for the HID Control Point characteristic. */
80 #define INITIAL_VALUE_HID_CONTROL_POINT HIDS_CONTROL_POINT_SUSPEND
81 #define REPORT_CNT_0 0
82 #define REPORT_CNT_1 1
83 #define REPORT_CNT_2 2
84 /*
85 * ENUMERATIONS
86 *****************************************************************************************
87 */
88 /**@brief HIDS Attributes database index list. */
89 enum hids_attr_idx_tag {
90 // Service
91 HIDS_IDX_SVC,
92
93 // Protocol Mode characteristic
94 HIDS_IDX_PROTOCOL_MODE_CHAR,
95 HIDS_IDX_PROTOCOL_MODE_VAL,
96
97 // Input Report1 characteristics
98 HIDS_IDX_INPUT1_REPORT_CHAR,
99 HIDS_IDX_INPUT1_REPORT_VAL,
100 HIDS_IDX_INPUT1_REPORT_CCCD,
101 HIDS_IDX_INPUT1_REPORT_REF,
102
103 // Input Report2 characteristics
104 HIDS_IDX_INPUT2_REPORT_CHAR,
105 HIDS_IDX_INPUT2_REPORT_VAL,
106 HIDS_IDX_INPUT2_REPORT_CCCD,
107 HIDS_IDX_INPUT2_REPORT_REF,
108
109 // Input Report3 characteristics
110 HIDS_IDX_INPUT3_REPORT_CHAR,
111 HIDS_IDX_INPUT3_REPORT_VAL,
112 HIDS_IDX_INPUT3_REPORT_CCCD,
113 HIDS_IDX_INPUT3_REPORT_REF,
114
115 // Output Report characteristics
116 HIDS_IDX_OUTPUT_REPORT_CHAR,
117 HIDS_IDX_OUTPUT_REPORT_VAL,
118 HIDS_IDX_OUTPUT_REPORT_REF,
119
120 // Feature Report characteristic
121 HIDS_IDX_FEATURE_REPORT_CHAR,
122 HIDS_IDX_FEATURE_REPORT_VAL,
123 HIDS_IDX_FEATURE_REPORT_REF,
124
125 // Report Map characteristic
126 HIDS_IDX_REPORT_MAP_CHAR,
127 HIDS_IDX_REPORT_MAP_VAL,
128
129 // Boot Keyboard Input Report characteristic
130 HIDS_IDX_BOOT_KB_IN_RPT_CHAR,
131 HIDS_IDX_BOOT_KB_IN_RPT_VAL,
132 HIDS_IDX_BOOT_KB_IN_RPT_CCCD,
133
134 // Boot Keyboard Output Report characteristic
135 HIDS_IDX_BOOT_KB_OUT_RPT_CHAR,
136 HIDS_IDX_BOOT_KB_OUT_RPT_VAL,
137
138 // Boot Mouse Input Report characteristic.
139 HIDS_IDX_BOOT_MS_IN_RPT_CHAR,
140 HIDS_IDX_BOOT_MS_IN_RPT_VAL,
141 HIDS_IDX_BOOT_MS_IN_RPT_CCCD,
142
143 // HID Information characteristic
144 HIDS_IDX_HID_INFO_CHAR,
145 HIDS_IDX_HID_INFO_VAL,
146
147 // HID Control Point characteristic
148 HIDS_IDX_CTRL_POINT_CHAR,
149 HIDS_IDX_CTRL_POINT_VAL,
150
151 HIDS_IDX_NB,
152 };
153
154 /*
155 * STRUCT DEFINE
156 *******************************************************************************
157 */
158 /**@brief Heart Rate Service environment variable. */
159 struct hids_env_t {
160 hids_init_t hids_init; /**< HID Service Init Value. */
161 uint16_t start_hdl; /**< HID Service start handle. */
162 uint8_t
163 char_mask[5]; /**< Mask of Supported characteristics*/
164 uint16_t
165 input_cccd[IN_REPORT_MAX_COUNT][HIDS_CONNECTION_MAX]; /**< Input report characteristics cccd value*/
166 uint16_t
167 kb_input_cccd[HIDS_CONNECTION_MAX]; /**< Boot keyboard input report characteristics cccd value*/
168 uint16_t
169 mouse_input_cccd[HIDS_CONNECTION_MAX]; /**< Boot mouse input report characteristics cccd value*/
170 uint8_t protocol_mode; /**< Protocol mode. */
171 uint8_t ctrl_pt; /**< HID Control Point. */
172 uint8_t
173 input_report_val[IN_REPORT_MAX_COUNT][HIDS_REPORT_MAX_SIZE]; /**< Input report characteristics value*/
174 uint8_t
175 output_report_val[HIDS_REPORT_MAX_SIZE]; /**< Output report characteristic value*/
176 uint8_t
177 feature_report_val[HIDS_REPORT_MAX_SIZE]; /**< Feature report characteristic value*/
178 uint8_t
179 kb_input_report_val[HIDS_BOOT_KB_IN_REPORT_MAX_SIZE]; /**< Boot keyboard input report characteristics value*/
180 uint8_t
181 kb_output_report_val[HIDS_BOOT_KB_OUT_REPORT_MAX_SIZE]; /**< Boot keyboard output report characteristics value*/
182 uint8_t
183 mouse_input_report_val[HIDS_BOOT_MOUSE_IN_REPORT_MAX_SIZE]; /**< Boot mouse input report characteristics value*/
184 };
185
186
187 /*
188 * LOCAL FUNCTION DECLARATIONS
189 *****************************************************************************************
190 */
191 static sdk_err_t hids_init(void);
192 static void hids_write_att_cb(uint8_t conn_idx, const gatts_write_req_cb_t *p_param);
193 static void hids_read_att_cb(uint8_t conn_idx, const gatts_read_req_cb_t *p_param);
194 static void hids_cccd_set_cb(uint8_t conn_idx, uint16_t handle, uint16_t cccd_value);
195
196 /*
197 * LOCAL VARIABLE DEFINITIONS
198 *******************************************************************************
199 */
200 static struct hids_env_t s_hids_env;
201
202
203 /**@brief Full HID Service Database Description - Used to add attributes into the database. */
204 static const attm_desc_t hids_attr_tab[HIDS_IDX_NB] = {
205 // HID Service Declaration
206 [HIDS_IDX_SVC] = {BLE_ATT_DECL_PRIMARY_SERVICE, READ_PERM_UNSEC, 0, 0},
207
208 // Protocol Mode Characteristic - Declaration
209 [HIDS_IDX_PROTOCOL_MODE_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
210 // Protocol Mode Characteristic - Value
211 [HIDS_IDX_PROTOCOL_MODE_VAL] = {
212 BLE_ATT_CHAR_PROTOCOL_MODE, READ_PERM(UNAUTH) | WRITE_CMD_PERM(UNAUTH),
213 ATT_VAL_LOC_USER, sizeof(uint8_t)
214 },
215
216 // Input Report1 Characteristic - Declaration
217 [HIDS_IDX_INPUT1_REPORT_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
218 // Input Report1 Characteristic - Value
219 [HIDS_IDX_INPUT1_REPORT_VAL] = {
220 BLE_ATT_CHAR_REPORT, READ_PERM(UNAUTH) | NOTIFY_PERM(UNAUTH) | WRITE_REQ_PERM(UNAUTH),
221 ATT_VAL_LOC_USER, HIDS_REPORT_MAX_SIZE
222 },
223 // Input Report1 Characteristic - Descriptor: CCCD
224 [HIDS_IDX_INPUT1_REPORT_CCCD] = {BLE_ATT_DESC_CLIENT_CHAR_CFG, READ_PERM(UNAUTH) | WRITE_REQ_PERM(UNAUTH), 0, 0},
225 // Input Report1 Characteristic - Descriptor: Report Reference
226 [HIDS_IDX_INPUT1_REPORT_REF] = {
227 BLE_ATT_DESC_REPORT_REF, READ_PERM(UNAUTH),
228 ATT_VAL_LOC_USER, sizeof(hids_report_ref_t)
229 },
230
231 // Input Report2 Characteristic - Declaration
232 [HIDS_IDX_INPUT2_REPORT_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
233 // Input Report2 Characteristic - Value
234 [HIDS_IDX_INPUT2_REPORT_VAL] = {
235 BLE_ATT_CHAR_REPORT, READ_PERM(UNAUTH) | NOTIFY_PERM(UNAUTH) | WRITE_REQ_PERM(UNAUTH),
236 ATT_VAL_LOC_USER, HIDS_REPORT_MAX_SIZE
237 },
238 // Input Report2 Characteristic - Descriptor: CCCD
239 [HIDS_IDX_INPUT2_REPORT_CCCD] = {BLE_ATT_DESC_CLIENT_CHAR_CFG, READ_PERM(UNAUTH) | WRITE_REQ_PERM(UNAUTH), 0, 0},
240 // Input Report2 Characteristic - Descriptor: Report Reference
241 [HIDS_IDX_INPUT2_REPORT_REF] = {
242 BLE_ATT_DESC_REPORT_REF, READ_PERM(UNAUTH),
243 ATT_VAL_LOC_USER, sizeof(hids_report_ref_t)
244 },
245
246 // Input Report3 Characteristic - Declaration
247 [HIDS_IDX_INPUT3_REPORT_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
248 // Input Report3 Characteristic - Value
249 [HIDS_IDX_INPUT3_REPORT_VAL] = {
250 BLE_ATT_CHAR_REPORT, READ_PERM(UNAUTH) | NOTIFY_PERM(UNAUTH) | WRITE_REQ_PERM(UNAUTH),
251 ATT_VAL_LOC_USER, HIDS_REPORT_MAX_SIZE
252 },
253 // Input Report3 Characteristic - Descriptor: CCCD
254 [HIDS_IDX_INPUT3_REPORT_CCCD] = {BLE_ATT_DESC_CLIENT_CHAR_CFG, READ_PERM(UNAUTH) | WRITE_REQ_PERM(UNAUTH), 0, 0},
255 // Input Report3 Characteristic - Descriptor: Report Reference
256 [HIDS_IDX_INPUT3_REPORT_REF] = {
257 BLE_ATT_DESC_REPORT_REF, READ_PERM(UNAUTH),
258 ATT_VAL_LOC_USER, sizeof(hids_report_ref_t)
259 },
260
261 // Output Report Characteristic - Declaration
262 [HIDS_IDX_OUTPUT_REPORT_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
263 // Output Report Characteristic - Value
264 [HIDS_IDX_OUTPUT_REPORT_VAL] = {
265 BLE_ATT_CHAR_REPORT, READ_PERM(UNAUTH) | WRITE_REQ_PERM(UNAUTH) | WRITE_CMD_PERM(UNAUTH),
266 ATT_VAL_LOC_USER, HIDS_REPORT_MAX_SIZE
267 },
268 // Output Report Characteristic - Descriptor: Report Reference
269 [HIDS_IDX_OUTPUT_REPORT_REF] = {
270 BLE_ATT_DESC_REPORT_REF, READ_PERM(UNAUTH),
271 ATT_VAL_LOC_USER, sizeof(hids_report_ref_t)
272 },
273
274 // Feature Report Characteristic - Declaration
275 [HIDS_IDX_FEATURE_REPORT_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
276 // Feature Report Characteristic - Value
277 [HIDS_IDX_FEATURE_REPORT_VAL] = {
278 BLE_ATT_CHAR_REPORT, READ_PERM(UNAUTH) | WRITE_REQ_PERM(UNAUTH),
279 ATT_VAL_LOC_USER, HIDS_REPORT_MAX_SIZE
280 },
281 // Feature Report Characteristic - Descriptor: Report Reference
282 [HIDS_IDX_FEATURE_REPORT_REF] = {
283 BLE_ATT_DESC_REPORT_REF, READ_PERM(UNAUTH),
284 ATT_VAL_LOC_USER, sizeof(hids_report_ref_t)
285 },
286
287 // Report Map Characteristic - Declaration
288 [HIDS_IDX_REPORT_MAP_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
289 // Report Map Characteristic - Value
290 [HIDS_IDX_REPORT_MAP_VAL] = {
291 BLE_ATT_CHAR_REPORT_MAP, READ_PERM(UNAUTH),
292 ATT_VAL_LOC_USER, HIDS_REPORT_MAP_MAX_SIZE
293 },
294
295 // Boot Keyboard Input Report Characteristic - Declaration
296 [HIDS_IDX_BOOT_KB_IN_RPT_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
297 // Boot Keyboard Input Report Characteristic - Value
298 [HIDS_IDX_BOOT_KB_IN_RPT_VAL] = {
299 BLE_ATT_CHAR_BOOT_KB_IN_REPORT,
300 READ_PERM(UNAUTH) | NOTIFY_PERM(UNAUTH) | WRITE_REQ_PERM(UNAUTH),
301 ATT_VAL_LOC_USER, HIDS_BOOT_KB_IN_REPORT_MAX_SIZE
302 },
303 // Boot Keyboard Input Report Characteristic - Descriptor: CCCD
304 [HIDS_IDX_BOOT_KB_IN_RPT_CCCD] = {BLE_ATT_DESC_CLIENT_CHAR_CFG, READ_PERM(UNAUTH) | WRITE_REQ_PERM(UNAUTH), 0, 0},
305
306 // Boot Keyboard Output Report Characteristic - Declaration
307 [HIDS_IDX_BOOT_KB_OUT_RPT_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
308 // Boot Keyboard Output Report Characteristic - Value
309 [HIDS_IDX_BOOT_KB_OUT_RPT_VAL] = {
310 BLE_ATT_CHAR_BOOT_KB_OUT_REPORT,
311 READ_PERM(UNAUTH) | WRITE_REQ_PERM(UNAUTH) | WRITE_CMD_PERM(UNAUTH),
312 ATT_VAL_LOC_USER, HIDS_BOOT_KB_OUT_REPORT_MAX_SIZE
313 },
314
315 // Boot Mouse Input Report Characteristic - Declaration
316 [HIDS_IDX_BOOT_MS_IN_RPT_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
317 // Boot Mouse Input Report Characteristic - Value
318 [HIDS_IDX_BOOT_MS_IN_RPT_VAL] = {
319 BLE_ATT_CHAR_BOOT_MOUSE_IN_REPORT,
320 READ_PERM(UNAUTH) | NOTIFY_PERM(UNAUTH) | WRITE_REQ_PERM(UNAUTH),
321 ATT_VAL_LOC_USER, HIDS_BOOT_MOUSE_IN_REPORT_MAX_SIZE
322 },
323 // Boot Mouse Input Report Characteristic - Descriptor: CCCD
324 [HIDS_IDX_BOOT_MS_IN_RPT_CCCD] = {BLE_ATT_DESC_CLIENT_CHAR_CFG, READ_PERM(UNAUTH) | WRITE_REQ_PERM(UNAUTH), 0, 0},
325
326 // HID Information Characteristic - Declaration
327 [HIDS_IDX_HID_INFO_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
328 // HID Information Characteristic - Value
329 [HIDS_IDX_HID_INFO_VAL] = {
330 BLE_ATT_CHAR_HID_INFO, READ_PERM(UNAUTH),
331 ATT_VAL_LOC_USER, sizeof(hids_hid_info_t)
332 },
333
334 // HID Control Point Characteristic - Declaration
335 [HIDS_IDX_CTRL_POINT_CHAR] = {
336 BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC,
337 0, 0
338 },
339 // HID Control Point Characteristic - Value
340 [HIDS_IDX_CTRL_POINT_VAL] = {
341 BLE_ATT_CHAR_HID_CTNL_PT, WRITE_CMD_PERM(UNAUTH),
342 ATT_VAL_LOC_USER, sizeof(uint8_t)
343 },
344 };
345
346 /**@brief HIDS interface required by profile manager. */
347 static ble_prf_manager_cbs_t hids_mgr_cbs = {
348 (prf_init_func_t)hids_init,
349 NULL,
350 NULL
351 };
352
353 /**@brief HIDS GATT server Callbacks. */
354 static gatts_prf_cbs_t hids_gatts_cbs = {
355 hids_read_att_cb,
356 hids_write_att_cb,
357 NULL,
358 NULL,
359 hids_cccd_set_cb
360 };
361
362 /**@brief HIDS Information. */
363 static const prf_server_info_t hids_prf_info = {
364 .max_connection_nb = HIDS_CONNECTION_MAX,
365 .manager_cbs = &hids_mgr_cbs,
366 .gatts_prf_cbs = &hids_gatts_cbs
367 };
368
369 /*
370 * LOCAL FUNCTION DEFINITIONS
371 *******************************************************************************
372 */
373
374 /**
375 *****************************************************************************************
376 * @brief Initialize HID service and create db in att.
377 *
378 * @return BLE_ATT_ERR_NO_ERROR on success, otherwise error code.
379 *****************************************************************************************
380 */
hids_init(void)381 static sdk_err_t hids_init(void)
382 {
383 const uint8_t hids_svc_uuid[] = BLE_ATT_16_TO_16_ARRAY(BLE_ATT_SVC_HID);
384 gatts_create_db_t gatts_db;
385 uint16_t start_hdl = PRF_INVALID_HANDLE; /* The start hanlde is an in/out
386 * parameter of ble_gatts_srvc_db_create().
387 * It must be set with PRF_INVALID_HANDLE
388 * to be allocated automatically by BLE Stack. */
389 sdk_err_t ret;
390 ret = memset_s(&gatts_db, sizeof(gatts_db), 0, sizeof(gatts_db));
391 if (ret < 0) {
392 return ret;
393 }
394
395 gatts_db.shdl = &start_hdl;
396 gatts_db.uuid = (uint8_t*)hids_svc_uuid;
397 gatts_db.attr_tab_cfg = (uint8_t*)&s_hids_env.char_mask;
398 gatts_db.max_nb_attr = HIDS_IDX_NB;
399 gatts_db.srvc_perm = 0;
400 gatts_db.attr_tab_type = SERVICE_TABLE_TYPE_16;
401 gatts_db.attr_tab.attr_tab_16 = hids_attr_tab;
402
403 sdk_err_t status = ble_gatts_srvc_db_create(&gatts_db);
404 if (SDK_SUCCESS == status) {
405 s_hids_env.start_hdl = *gatts_db.shdl;
406 }
407 return status;
408 }
409
410 /**
411 *****************************************************************************************
412 * @brief Handles reception of the read request.
413 *
414 * @param[in] conn_idx: Connection index.
415 * @param[in] p_param: Pointer to the parameters of the read request.
416 *****************************************************************************************
417 */
hids_read_att_cb(uint8_t conn_idx,const gatts_read_req_cb_t * p_param)418 static void hids_read_att_cb(uint8_t conn_idx, const gatts_read_req_cb_t *p_param)
419 {
420 uint8_t handle = p_param->handle;
421 uint8_t tab_index = prf_find_idx_by_handle(handle, s_hids_env.start_hdl,
422 HIDS_IDX_NB,
423 (uint8_t *)&s_hids_env.char_mask);
424 gatts_read_cfm_t cfm;
425
426 cfm.handle = handle;
427 cfm.status = BLE_SUCCESS;
428
429 switch (tab_index) {
430 case HIDS_IDX_PROTOCOL_MODE_VAL:
431 cfm.length = sizeof(uint8_t);
432 cfm.value = (uint8_t *)(&s_hids_env.protocol_mode);
433 break;
434 /*----------------------------------------------------------------------------------*/
435 case HIDS_IDX_INPUT1_REPORT_VAL:
436 cfm.length = s_hids_env.hids_init.input_report_array[INDEX_0].value_len;
437 cfm.value = (uint8_t *)(&s_hids_env.input_report_val[INDEX_0]);
438 break;
439
440 case HIDS_IDX_INPUT1_REPORT_CCCD:
441 cfm.length = sizeof(uint16_t);
442 cfm.value = (uint8_t *)(&s_hids_env.input_cccd[INDEX_0][conn_idx]);
443 break;
444
445 case HIDS_IDX_INPUT1_REPORT_REF:
446 cfm.length = sizeof(hids_report_ref_t);
447 cfm.value = (uint8_t *)(&s_hids_env.hids_init.input_report_array[INDEX_0].ref);
448 break;
449 /*----------------------------------------------------------------------------------*/
450 case HIDS_IDX_INPUT2_REPORT_VAL:
451 cfm.length = s_hids_env.hids_init.input_report_array[INDEX_1].value_len;
452 cfm.value = (uint8_t *)(&s_hids_env.input_report_val[INDEX_1]);
453 break;
454
455 case HIDS_IDX_INPUT2_REPORT_CCCD:
456 cfm.length = sizeof(uint16_t);
457 cfm.value = (uint8_t *)(&s_hids_env.input_cccd[INDEX_1][conn_idx]);
458 break;
459
460 case HIDS_IDX_INPUT2_REPORT_REF:
461 cfm.length = sizeof(hids_report_ref_t);
462 cfm.value = (uint8_t *)(&s_hids_env.hids_init.input_report_array[INDEX_1].ref);
463 break;
464 /*----------------------------------------------------------------------------------*/
465 case HIDS_IDX_INPUT3_REPORT_VAL:
466 cfm.length = s_hids_env.hids_init.input_report_array[INDEX_2].value_len;
467 cfm.value = (uint8_t *)(&s_hids_env.input_report_val[INDEX_2]);
468 break;
469
470 case HIDS_IDX_INPUT3_REPORT_CCCD:
471 cfm.length = sizeof(uint16_t);
472 cfm.value = (uint8_t *)(&s_hids_env.input_cccd[INDEX_2][conn_idx]);
473 break;
474
475 case HIDS_IDX_INPUT3_REPORT_REF:
476 cfm.length = sizeof(hids_report_ref_t);
477 cfm.value = (uint8_t *)(&s_hids_env.hids_init.input_report_array[INDEX_2].ref);
478 break;
479 /*----------------------------------------------------------------------------------*/
480 case HIDS_IDX_OUTPUT_REPORT_VAL:
481 cfm.length = s_hids_env.hids_init.output_report.value_len;
482 cfm.value = (uint8_t *)(&s_hids_env.output_report_val);
483 break;
484
485 case HIDS_IDX_OUTPUT_REPORT_REF:
486 cfm.length = sizeof(hids_report_ref_t);
487 cfm.value = (uint8_t *)(&s_hids_env.hids_init.output_report.ref);
488 break;
489 /*----------------------------------------------------------------------------------*/
490 case HIDS_IDX_FEATURE_REPORT_VAL:
491 cfm.length = s_hids_env.hids_init.feature_report.value_len;
492 cfm.value = (uint8_t *)(&s_hids_env.feature_report_val);
493 break;
494
495 case HIDS_IDX_FEATURE_REPORT_REF:
496 cfm.length = sizeof(hids_report_ref_t);
497 cfm.value = (uint8_t *)(&s_hids_env.hids_init.feature_report.ref);
498 break;
499 /*----------------------------------------------------------------------------------*/
500 case HIDS_IDX_REPORT_MAP_VAL:
501 cfm.length = s_hids_env.hids_init.report_map.len;
502 cfm.value = (uint8_t *)(s_hids_env.hids_init.report_map.p_map);
503 break;
504 /*----------------------------------------------------------------------------------*/
505 case HIDS_IDX_BOOT_KB_IN_RPT_VAL:
506 cfm.length = HIDS_BOOT_KB_IN_REPORT_MAX_SIZE;
507 cfm.value = (uint8_t *)(&s_hids_env.kb_input_report_val);
508 break;
509
510 case HIDS_IDX_BOOT_KB_IN_RPT_CCCD:
511 cfm.length = sizeof(uint16_t);
512 cfm.value = (uint8_t *)(&s_hids_env.kb_input_cccd[conn_idx]);
513 break;
514 /*----------------------------------------------------------------------------------*/
515 case HIDS_IDX_BOOT_KB_OUT_RPT_VAL:
516 cfm.length = HIDS_IDX_BOOT_KB_IN_RPT_VAL;
517 cfm.value = (uint8_t *)(&s_hids_env.kb_output_report_val);
518 break;
519 /*----------------------------------------------------------------------------------*/
520 case HIDS_IDX_BOOT_MS_IN_RPT_VAL:
521 cfm.length = HIDS_BOOT_MOUSE_IN_REPORT_MAX_SIZE;
522 cfm.value = (uint8_t *)(&s_hids_env.mouse_input_report_val);
523 break;
524 /*----------------------------------------------------------------------------------*/
525 case HIDS_IDX_BOOT_MS_IN_RPT_CCCD:
526 cfm.length = sizeof(uint16_t);
527 cfm.value = (uint8_t *)&s_hids_env.mouse_input_cccd[conn_idx];
528 break;
529 /*----------------------------------------------------------------------------------*/
530
531 case HIDS_IDX_HID_INFO_VAL:
532 cfm.length = sizeof(hids_hid_info_t);
533 cfm.value = (uint8_t *)(&s_hids_env.hids_init.hid_info);
534 break;
535 /*----------------------------------------------------------------------------------*/
536 case HIDS_IDX_CTRL_POINT_VAL:
537 cfm.length = sizeof(uint16_t);
538 cfm.value = (uint8_t *)(&s_hids_env.ctrl_pt);
539 break;
540 /*----------------------------------------------------------------------------------*/
541 default:
542 cfm.length = 0;
543 cfm.status = BLE_ATT_ERR_INVALID_HANDLE;
544 break;
545 }
546 ble_gatts_read_cfm(conn_idx, &cfm);
547 }
548
549 /**
550 *****************************************************************************************
551 * @brief Check Input Report Characteristic cccd value.
552 *
553 * @param[in] p_evt: Pointer of HID Service event.
554 * @param[in] cccd_value: Cccd value.
555 *****************************************************************************************
556 */
hids_cccd_check(hids_evt_t * p_evt,uint16_t cccd_value)557 static void hids_cccd_check(hids_evt_t *p_evt, uint16_t cccd_value)
558 {
559 p_evt->evt_type = ((cccd_value == PRF_CLI_START_NTF) ?
560 HIDS_EVT_IN_REP_NOTIFY_ENABLED :
561 HIDS_EVT_IN_REP_NOTIFY_DISABLED);
562 }
563
564 /**
565 *****************************************************************************************
566 * @brief Function for handling write events to a cccd value.
567 *
568 * @param[in] tab_index CCCD index in DB.
569 * @param[in] conn_idx Connect index.
570 * @param[in] p_evt Pointer of HID Service event.
571 * @param[in] cccd_value CCCD Value.
572 *****************************************************************************************
573 */
hids_on_cccd_write(uint8_t tab_index,uint8_t conn_idx,hids_evt_t * p_evt,uint16_t cccd_value)574 static void hids_on_cccd_write(uint8_t tab_index, uint8_t conn_idx, hids_evt_t *p_evt, uint16_t cccd_value)
575 {
576 switch (tab_index) {
577 case HIDS_IDX_INPUT1_REPORT_CCCD:
578 s_hids_env.input_cccd[INDEX_0][conn_idx] = cccd_value;
579 p_evt->report_type = HIDS_REPORT_TYPE_IN1;
580 hids_cccd_check(p_evt, cccd_value);
581 break;
582
583 case HIDS_IDX_INPUT2_REPORT_CCCD:
584 s_hids_env.input_cccd[INDEX_1][conn_idx] = cccd_value;
585 p_evt->report_type = HIDS_REPORT_TYPE_IN2;
586 hids_cccd_check(p_evt, cccd_value);
587 break;
588
589 case HIDS_IDX_INPUT3_REPORT_CCCD:
590 s_hids_env.input_cccd[INDEX_2][conn_idx] = cccd_value;
591 p_evt->report_type = HIDS_REPORT_TYPE_IN3;
592 hids_cccd_check(p_evt, cccd_value);
593 break;
594
595 case HIDS_IDX_BOOT_KB_IN_RPT_CCCD:
596 s_hids_env.kb_input_cccd[conn_idx] = cccd_value;
597 p_evt->report_type = HIDS_REPORT_TYPE_KB_IN;
598 hids_cccd_check(p_evt, cccd_value);
599 break;
600
601 case HIDS_IDX_BOOT_MS_IN_RPT_CCCD:
602 s_hids_env.mouse_input_cccd[conn_idx] = cccd_value;
603 p_evt->report_type = HIDS_REPORT_TYPE_MOUSE_IN;
604 hids_cccd_check(p_evt, cccd_value);
605 break;
606
607 default:
608 break;
609 }
610 }
611
612 /**
613 *****************************************************************************************
614 * @brief Function for handling write events to the Protocol Mode value.
615 *
616 * @param[in] p_evt Pointer of HID Service event.
617 * @param[in] p_param Pointer to the parameters of the write request.
618 *****************************************************************************************
619 */
hids_on_protocol_mode_write(hids_evt_t * p_evt,const gatts_write_req_cb_t * p_param)620 static void hids_on_protocol_mode_write(hids_evt_t *p_evt, const gatts_write_req_cb_t *p_param)
621 {
622 if (p_param->length == 1) {
623 switch (p_param->value[INDEX_0]) {
624 case PROTOCOL_MODE_BOOT:
625 p_evt->evt_type = HIDS_EVT_BOOT_MODE_ENTERED;
626 break;
627
628 case PROTOCOL_MODE_REPORT:
629 p_evt->evt_type = HIDS_EVT_REPORT_MODE_ENTERED;
630 break;
631
632 default:
633 break;
634 }
635 s_hids_env.protocol_mode = p_param->value[INDEX_0];
636 }
637 }
638
639 /**
640 *****************************************************************************************
641 * @brief Function for handling write events to the HID Control Point value..
642 *
643 * @param[in] p_evt Pointer of HID Service event.
644 * @param[in] p_param Pointer to the parameters of the write request.
645 *****************************************************************************************
646 */
hids_on_control_point_write(hids_evt_t * p_evt,const gatts_write_req_cb_t * p_param)647 static void hids_on_control_point_write(hids_evt_t *p_evt, const gatts_write_req_cb_t *p_param)
648 {
649 if (p_param->length == 1) {
650 switch (p_param->value[INDEX_0]) {
651 case HIDS_CONTROL_POINT_SUSPEND:
652 p_evt->evt_type = HIDS_EVT_HOST_SUSP;
653 break;
654
655 case HIDS_CONTROL_POINT_EXIT_SUSPEND:
656 p_evt->evt_type = HIDS_EVT_HOST_EXIT_SUSP;
657 break;
658
659 default:
660 break;
661 }
662 s_hids_env.ctrl_pt = p_param->value[INDEX_0];
663 }
664 }
665
666
667 /**
668 *****************************************************************************************
669 * @brief Handles reception of the write request.
670 *
671 * @param[in] conn_idx: Connection index.
672 * @param[in] p_param: Pointer to the parameters of the write request.
673 *****************************************************************************************
674 */
hids_write_att_cb(uint8_t conn_idx,const gatts_write_req_cb_t * p_param)675 static void hids_write_att_cb(uint8_t conn_idx,
676 const gatts_write_req_cb_t *p_param)
677 {
678 uint16_t handle = p_param->handle;
679 uint8_t tab_index = prf_find_idx_by_handle(handle,
680 s_hids_env.start_hdl,
681 HIDS_IDX_NB,
682 (uint8_t *)&s_hids_env.char_mask);
683 uint16_t cccd_value;
684 gatts_write_cfm_t cfm;
685 hids_evt_t evt;
686 uint8_t ret;
687
688 evt.evt_type = HIDS_EVT_INVALID;
689 evt.offset = p_param->offset;
690 evt.len = p_param->length;
691 evt.data = p_param->value;
692 cfm.handle = handle;
693 cfm.status = BLE_SUCCESS;
694
695 switch (tab_index) {
696 case HIDS_IDX_PROTOCOL_MODE_VAL:
697 hids_on_protocol_mode_write(&evt, p_param);
698 break;
699
700 case HIDS_IDX_INPUT1_REPORT_CCCD:
701 case HIDS_IDX_INPUT2_REPORT_CCCD:
702 case HIDS_IDX_INPUT3_REPORT_CCCD:
703 case HIDS_IDX_BOOT_KB_IN_RPT_CCCD:
704 case HIDS_IDX_BOOT_MS_IN_RPT_CCCD:
705 cccd_value = le16toh(&p_param->value[INDEX_0]);
706 hids_on_cccd_write(tab_index, conn_idx, &evt, cccd_value);
707 break;
708
709 case HIDS_IDX_INPUT1_REPORT_VAL:
710 if ((p_param->offset + p_param->length) <= s_hids_env.hids_init.input_report_array[INDEX_0].value_len) {
711 ret = memcp_s(&s_hids_env.input_report_val[INDEX_0][p_param->offset], p_param->length,
712 p_param->value, p_param->length);
713 if (ret < 0) {
714 return ret;
715 }
716 evt.evt_type = HIDS_EVT_REP_CHAR_WRITE;
717 evt.report_type = HIDS_REPORT_TYPE_IN1;
718 }
719 break;
720
721 case HIDS_IDX_INPUT2_REPORT_VAL:
722 if ((p_param->offset + p_param->length) <= s_hids_env.hids_init.input_report_array[INDEX_1].value_len) {
723 ret = memcpy_s(&s_hids_env.input_report_val[INDEX_1][p_param->offset], p_param->length,
724 p_param->value, p_param->length);
725 if (ret < 0) {
726 return ret;
727 }
728 evt.evt_type = HIDS_EVT_REP_CHAR_WRITE;
729 evt.report_type = HIDS_REPORT_TYPE_IN2;
730 }
731 break;
732
733 case HIDS_IDX_INPUT3_REPORT_VAL:
734 if ((p_param->offset + p_param->length) <= s_hids_env.hids_init.input_report_array[INDEX_2].value_len) {
735 ret = memcpy_s(&s_hids_env.input_report_val[INDEX_2][p_param->offset], p_param->length,
736 p_param->value, p_param->length);
737 if (ret < 0) {
738 return ret;
739 }
740 evt.evt_type = HIDS_EVT_REP_CHAR_WRITE;
741 evt.report_type = HIDS_REPORT_TYPE_IN3;
742 }
743 break;
744
745 case HIDS_IDX_OUTPUT_REPORT_VAL:
746 if ((p_param->offset + p_param->length) <= s_hids_env.hids_init.output_report.value_len) {
747 ret = memcpy_s(&s_hids_env.output_report_val[p_param->offset], p_param->length,
748 p_param->value, p_param->length);
749 if (ret < 0) {
750 return ret;
751 }
752 evt.evt_type = HIDS_EVT_REP_CHAR_WRITE;
753 evt.report_type = HIDS_REPORT_TYPE_OUT;
754 }
755 break;
756
757 case HIDS_IDX_FEATURE_REPORT_VAL:
758 if ((p_param->offset + p_param->length) <= s_hids_env.hids_init.feature_report.value_len) {
759 ret = memcpy_s(&s_hids_env.feature_report_val[p_param->offset], p_param->length,
760 p_param->value, p_param->length);
761 if (ret < 0) {
762 return ret;
763 }
764 evt.evt_type = HIDS_EVT_REP_CHAR_WRITE;
765 evt.report_type = HIDS_REPORT_TYPE_FEATURE;
766 }
767 break;
768
769 case HIDS_IDX_BOOT_KB_IN_RPT_VAL:
770 if ((p_param->offset + p_param->length) <= HIDS_BOOT_KB_IN_REPORT_MAX_SIZE) {
771 ret = memcpy_s(&s_hids_env.kb_input_report_val[p_param->offset], p_param->length,
772 p_param->value, p_param->length);
773 if (ret < 0) {
774 return ret;
775 }
776 evt.evt_type = HIDS_EVT_REP_CHAR_WRITE;
777 evt.report_type = HIDS_REPORT_TYPE_KB_IN;
778 }
779 break;
780 case HIDS_IDX_BOOT_KB_OUT_RPT_VAL:
781 if ((p_param->offset + p_param->length) <= HIDS_BOOT_KB_OUT_REPORT_MAX_SIZE) {
782 ret = memcpy_s(&s_hids_env.kb_output_report_val[p_param->offset], p_param->length,
783 p_param->value, p_param->length);
784 if (ret < 0) {
785 return ret;
786 }
787 evt.evt_type = HIDS_EVT_REP_CHAR_WRITE;
788 evt.report_type = HIDS_REPORT_TYPE_KB_OUT;
789 }
790 break;
791 case HIDS_IDX_BOOT_MS_IN_RPT_VAL:
792 if ((p_param->offset + p_param->length) <= HIDS_BOOT_MOUSE_IN_REPORT_MAX_SIZE) {
793 ret = memcpy_s(&s_hids_env.mouse_input_report_val[p_param->offset], p_param->length,
794 p_param->value, p_param->length);
795 if (ret < 0) {
796 return ret;
797 }
798 evt.evt_type = HIDS_EVT_REP_CHAR_WRITE;
799 evt.report_type = HIDS_REPORT_TYPE_MOUSE_IN;
800 }
801 break;
802
803 case HIDS_IDX_CTRL_POINT_VAL:
804 hids_on_control_point_write(&evt, p_param);
805 break;
806
807 default:
808 cfm.status = BLE_ATT_ERR_INVALID_HANDLE;
809 break;
810 }
811
812 if (BLE_ATT_ERR_INVALID_HANDLE != cfm.status && \
813 HIDS_EVT_INVALID != evt.evt_type && \
814 s_hids_env.hids_init.evt_handler) {
815 evt.conn_idx = conn_idx;
816 s_hids_env.hids_init.evt_handler(&evt);
817 }
818
819 ble_gatts_write_cfm(conn_idx, &cfm);
820 }
821
822
823 /**
824 *****************************************************************************************
825 * @brief Handles reception of the cccd recover request.
826 *
827 * @param[in]: conn_idx: Connection index
828 * @param[in]: handle: The handle of cccd attribute.
829 * @param[in]: cccd_value: The value of cccd attribute.
830 *****************************************************************************************
831 */
hids_cccd_set_cb(uint8_t conn_idx,uint16_t handle,uint16_t cccd_value)832 static void hids_cccd_set_cb(uint8_t conn_idx, uint16_t handle, uint16_t cccd_value)
833 {
834 hids_evt_t evt;
835 evt.evt_type = HIDS_EVT_INVALID;
836 if (!prf_is_cccd_value_valid(cccd_value)) {
837 return;
838 }
839
840 uint8_t tab_index = prf_find_idx_by_handle(handle,
841 s_hids_env.start_hdl,
842 HIDS_IDX_NB,
843 (uint8_t *)&s_hids_env.char_mask);
844 hids_on_cccd_write(tab_index, conn_idx, &evt, cccd_value);
845 if (HIDS_EVT_INVALID != evt.evt_type && \
846 s_hids_env.hids_init.evt_handler) {
847 evt.conn_idx = conn_idx;
848 s_hids_env.hids_init.evt_handler(&evt);
849 }
850 }
851
852 /**
853 *****************************************************************************************
854 * @brief HIDS Characteristic mask init.
855 *
856 * @param[in]: p_hids_init: Pointer to the hids init.
857 *****************************************************************************************
858 */
hids_char_mask_init(hids_init_t * p_hids_init)859 static void hids_char_mask_init(hids_init_t *p_hids_init)
860 {
861 s_hids_env.char_mask[INDEX_0] = 0x01;
862 s_hids_env.char_mask[INDEX_1] = 0x00;
863 s_hids_env.char_mask[INDEX_2] = 0x60;
864 s_hids_env.char_mask[INDEX_3] = 0x80;
865 s_hids_env.char_mask[INDEX_4] = 0x07;
866 if (p_hids_init->is_kb || p_hids_init->is_mouse) {
867 s_hids_env.char_mask[INDEX_0] |= 0x06;
868 if (p_hids_init->is_kb) {
869 s_hids_env.char_mask[INDEX_2] |= 0x80;
870 s_hids_env.char_mask[INDEX_3] |= 0x0f;
871 }
872 if (p_hids_init->is_mouse) {
873 s_hids_env.char_mask[INDEX_3] |= 0x70;
874 }
875 }
876 switch (p_hids_init->input_report_count) {
877 case REPORT_CNT_0: // do noting
878 break;
879 case REPORT_CNT_1:
880 s_hids_env.char_mask[INDEX_0] |= 0x78;
881 break;
882 case REPORT_CNT_2:
883 s_hids_env.char_mask[INDEX_0] |= 0xf8;
884 s_hids_env.char_mask[INDEX_1] |= 0x07;
885 break;
886 default: // max count is 3
887 s_hids_env.char_mask[INDEX_0] |= 0xf8;
888 s_hids_env.char_mask[INDEX_1] |= 0x7f;
889 break;
890 }
891
892 if (p_hids_init->out_report_sup) {
893 s_hids_env.char_mask[INDEX_1] |= 0x80;
894 s_hids_env.char_mask[INDEX_2] |= 0x03;
895 }
896
897 if (p_hids_init->feature_report_sup) {
898 s_hids_env.char_mask[INDEX_2] |= 0x1c;
899 }
900 }
901
902 /**
903 *****************************************************************************************
904 * @brief Send an input report.
905 *
906 * @param[in] conn_idx: Connection index.
907 * @param[in] char_idx: Input report Characteristic inedx.
908 * @param[in] p_data: Pointer to data to be sent.
909 * @param[in] length: Length of data to be sent.
910 *
911 * @return BLE_SDK_SUCCESS on success, otherwise an error code.
912 *****************************************************************************************
913 */
hids_in_rep_notify(uint8_t conn_idx,uint8_t char_idx,uint8_t * p_data,uint16_t length)914 static sdk_err_t hids_in_rep_notify(uint8_t conn_idx, uint8_t char_idx, uint8_t *p_data, uint16_t length)
915 {
916 sdk_err_t error_code;
917 gatts_noti_ind_t hids_noti;
918 hids_noti.type = BLE_GATT_NOTIFICATION;
919 hids_noti.handle = prf_find_handle_by_idx(char_idx,
920 s_hids_env.start_hdl,
921 (uint8_t *)&s_hids_env.char_mask);
922 hids_noti.length = length;
923 hids_noti.value = p_data;
924
925 error_code = ble_gatts_noti_ind(conn_idx, &hids_noti);
926 return error_code;
927 }
928
929 /*
930 * GLOBAL FUNCTION DEFINITIONS
931 *******************************************************************************
932 */
hids_service_init(hids_init_t * p_hids_init)933 sdk_err_t hids_service_init(hids_init_t *p_hids_init)
934 {
935 sdk_err_t ret;
936 if (p_hids_init == NULL) {
937 return SDK_ERR_POINTER_NULL;
938 }
939 ret = memcpy_s(&s_hids_env.hids_init, sizeof(hids_init_t), p_hids_init, sizeof(hids_init_t));
940 if (ret < 0) {
941 return ret;
942 }
943 hids_char_mask_init(p_hids_init);
944 s_hids_env.protocol_mode = DEFAULT_PROTOCOL_MODE;
945 s_hids_env.ctrl_pt = INITIAL_VALUE_HID_CONTROL_POINT;
946 return ble_server_prf_add(&hids_prf_info);
947 }
948
949
hids_input_rep_send(uint8_t conn_idx,uint8_t rep_idx,uint8_t * p_data,uint16_t uint16_t length)950 sdk_err_t hids_input_rep_send(uint8_t conn_idx, uint8_t rep_idx, uint8_t *p_data, uint16_t uint16_t length)
951 {
952 uint16_t len = length;
953 sdk_err_t ret;
954 static const uint8_t char_idx[] = {HIDS_IDX_INPUT1_REPORT_VAL,
955 HIDS_IDX_INPUT2_REPORT_VAL, HIDS_IDX_INPUT3_REPORT_VAL};
956 sdk_err_t error_code = SDK_ERR_NTF_DISABLED;
957 if (rep_idx >= IN_REPORT_MAX_COUNT || p_data == NULL || len == 0) {
958 return SDK_ERR_INVALID_PARAM;
959 }
960 len = ((length > HIDS_REPORT_MAX_SIZE) ? HIDS_REPORT_MAX_SIZE : len);
961 ret = memcpy_s(&s_hids_env.input_report_val[rep_idx], len, p_data, len);
962 if (ret < 0) {
963 return ret;
964 }
965 if (s_hids_env.input_cccd[rep_idx][conn_idx] == PRF_CLI_START_NTF) {
966 error_code = hids_in_rep_notify(conn_idx, char_idx[rep_idx], p_data, len);
967 }
968 return error_code;
969 }
970
hids_boot_kb_in_rep_send(uint8_t conn_idx,uint8_t * p_data,uint16_t length)971 sdk_err_t hids_boot_kb_in_rep_send(uint8_t conn_idx, uint8_t *p_data, uint16_t length)
972 {
973 sdk_err_t error_code = SDK_ERR_NTF_DISABLED;
974 uint16_t len = length;
975 if (p_data == NULL || len == 0) {
976 return SDK_ERR_INVALID_PARAM;
977 }
978 len = ((len > HIDS_BOOT_KB_IN_REPORT_MAX_SIZE) ? HIDS_BOOT_KB_IN_REPORT_MAX_SIZE : len);
979 error_code = memcpy_s(&s_hids_env.kb_input_report_val, len, p_data, len);
980 if (error_code < 0) {
981 return error_code;
982 }
983 if (s_hids_env.kb_input_cccd[conn_idx] == PRF_CLI_START_NTF) {
984 error_code = hids_in_rep_notify(conn_idx, HIDS_IDX_BOOT_KB_IN_RPT_VAL, p_data, len);
985 }
986 return error_code;
987 }
988
989 sdk_err_t hids_boot_mouse_in_rep_send(uint8_t conn_idx, uint8_t *p_data, uint16_t length)
990 {
991 sdk_err_t error_code = SDK_ERR_NTF_DISABLED;
992 uint16_t len = length;
993 if (p_data == NULL || length < HIDS_BOOT_MOUSE_IN_REPORT_MIN_SIZE) {
994 return SDK_ERR_INVALID_PARAM;
995 }
996 len = ((len > HIDS_BOOT_MOUSE_IN_REPORT_MAX_SIZE) ? HIDS_BOOT_MOUSE_IN_REPORT_MAX_SIZE : len);
997 error_code = memcpy_s(&s_hids_env.mouse_input_report_val, len, p_data, len);
998 if (error_code < 0) {
999 return error_code;
1000 }
1001 if (s_hids_env.mouse_input_cccd[conn_idx] == PRF_CLI_START_NTF) {
1002 error_code = hids_in_rep_notify(conn_idx, HIDS_IDX_BOOT_MS_IN_RPT_VAL, p_data, len);
1003 }
1004 return error_code;
1005 }
1006