• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright 2002-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  This file contains the HID HOST API entry points
22  *
23  ******************************************************************************/
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "bt_common.h"
30 #include "bt_types.h"
31 #include "btm_api.h"
32 #include "btm_int.h"
33 #include "btu.h"
34 #include "hiddefs.h"
35 #include "hidh_api.h"
36 #include "hidh_int.h"
37 
38 using bluetooth::Uuid;
39 
40 tHID_HOST_CTB hh_cb;
41 
42 static void hidh_search_callback(uint16_t sdp_result);
43 
44 /*******************************************************************************
45  *
46  * Function         HID_HostGetSDPRecord
47  *
48  * Description      This function reads the device SDP record
49  *
50  * Returns          tHID_STATUS
51  *
52  ******************************************************************************/
HID_HostGetSDPRecord(const RawAddress & addr,tSDP_DISCOVERY_DB * p_db,uint32_t db_len,tHID_HOST_SDP_CALLBACK * sdp_cback)53 tHID_STATUS HID_HostGetSDPRecord(const RawAddress& addr,
54                                  tSDP_DISCOVERY_DB* p_db, uint32_t db_len,
55                                  tHID_HOST_SDP_CALLBACK* sdp_cback) {
56 
57   if (hh_cb.sdp_busy) return HID_ERR_SDP_BUSY;
58 
59   hh_cb.p_sdp_db = p_db;
60   Uuid uuid_list = Uuid::From16Bit(UUID_SERVCLASS_HUMAN_INTERFACE);
61   SDP_InitDiscoveryDb(p_db, db_len, 1, &uuid_list, 0, NULL);
62 
63   if (SDP_ServiceSearchRequest(addr, p_db, hidh_search_callback)) {
64     hh_cb.sdp_cback = sdp_cback;
65     hh_cb.sdp_busy = true;
66     return HID_SUCCESS;
67   } else
68     return HID_ERR_NO_RESOURCES;
69 }
70 
hidh_get_str_attr(tSDP_DISC_REC * p_rec,uint16_t attr_id,uint16_t max_len,char * str)71 void hidh_get_str_attr(tSDP_DISC_REC* p_rec, uint16_t attr_id, uint16_t max_len,
72                        char* str) {
73   tSDP_DISC_ATTR* p_attr;
74   uint16_t name_len;
75 
76   p_attr = SDP_FindAttributeInRec(p_rec, attr_id);
77   if (p_attr != NULL) {
78     name_len = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
79     if (name_len < max_len) {
80       memcpy(str, (char*)p_attr->attr_value.v.array, name_len);
81       str[name_len] = '\0';
82     } else {
83       memcpy(str, (char*)p_attr->attr_value.v.array, max_len - 1);
84       str[max_len - 1] = '\0';
85     }
86   } else
87     str[0] = '\0';
88 }
89 
hidh_search_callback(uint16_t sdp_result)90 static void hidh_search_callback(uint16_t sdp_result) {
91   tSDP_DISCOVERY_DB* p_db = hh_cb.p_sdp_db;
92   tSDP_DISC_REC* p_rec;
93   tSDP_DISC_ATTR *p_attr, *p_subattr1, *p_subattr2, *p_repdesc;
94   tHID_DEV_SDP_INFO* p_nvi = &hh_cb.sdp_rec;
95   uint16_t attr_mask = 0;
96 
97 
98   hh_cb.sdp_busy = false;
99 
100   if (sdp_result != SDP_SUCCESS) {
101     hh_cb.sdp_cback(sdp_result, 0, NULL);
102     return;
103   }
104 
105   Uuid hid_uuid = Uuid::From16Bit(UUID_SERVCLASS_HUMAN_INTERFACE);
106   p_rec = SDP_FindServiceUUIDInDb(p_db, hid_uuid, NULL);
107   if (p_rec == NULL) {
108     hh_cb.sdp_cback(HID_SDP_NO_SERV_UUID, 0, NULL);
109     return;
110   }
111 
112   memset(&hh_cb.sdp_rec, 0, sizeof(tHID_DEV_SDP_INFO));
113 
114   /* First, verify the mandatory fields we care about */
115   if (((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HID_DESCRIPTOR_LIST)) ==
116        NULL) ||
117       (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE) ||
118       ((p_subattr1 = p_attr->attr_value.v.p_sub_attr) == NULL) ||
119       (SDP_DISC_ATTR_TYPE(p_subattr1->attr_len_type) !=
120        DATA_ELE_SEQ_DESC_TYPE) ||
121       ((p_subattr2 = p_subattr1->attr_value.v.p_sub_attr) == NULL) ||
122       ((p_repdesc = p_subattr2->p_next_attr) == NULL) ||
123       (SDP_DISC_ATTR_TYPE(p_repdesc->attr_len_type) != TEXT_STR_DESC_TYPE)) {
124     hh_cb.sdp_cback(HID_SDP_MANDATORY_MISSING, 0, NULL);
125     return;
126   }
127 
128   p_nvi->dscp_info.dl_len = SDP_DISC_ATTR_LEN(p_repdesc->attr_len_type);
129   if (p_nvi->dscp_info.dl_len != 0)
130     p_nvi->dscp_info.dsc_list = (uint8_t*)&p_repdesc->attr_value;
131 
132   if (((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HID_VIRTUAL_CABLE)) !=
133        NULL) &&
134       (p_attr->attr_value.v.u8)) {
135     attr_mask |= HID_VIRTUAL_CABLE;
136   }
137 
138   if (((p_attr = SDP_FindAttributeInRec(
139             p_rec, ATTR_ID_HID_RECONNECT_INITIATE)) != NULL) &&
140       (p_attr->attr_value.v.u8)) {
141     attr_mask |= HID_RECONN_INIT;
142   }
143 
144   if (((p_attr = SDP_FindAttributeInRec(
145             p_rec, ATTR_ID_HID_NORMALLY_CONNECTABLE)) != NULL) &&
146       (p_attr->attr_value.v.u8)) {
147     attr_mask |= HID_NORMALLY_CONNECTABLE;
148   }
149 
150   if (((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HID_SDP_DISABLE)) !=
151        NULL) &&
152       (p_attr->attr_value.v.u8)) {
153     attr_mask |= HID_SDP_DISABLE;
154   }
155 
156   if (((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HID_BATTERY_POWER)) !=
157        NULL) &&
158       (p_attr->attr_value.v.u8)) {
159     attr_mask |= HID_BATTERY_POWER;
160   }
161 
162   if (((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HID_REMOTE_WAKE)) !=
163        NULL) &&
164       (p_attr->attr_value.v.u8)) {
165     attr_mask |= HID_REMOTE_WAKE;
166   }
167 
168   hidh_get_str_attr(p_rec, ATTR_ID_SERVICE_NAME, HID_MAX_SVC_NAME_LEN,
169                     p_nvi->svc_name);
170   hidh_get_str_attr(p_rec, ATTR_ID_SERVICE_DESCRIPTION, HID_MAX_SVC_DESCR_LEN,
171                     p_nvi->svc_descr);
172   hidh_get_str_attr(p_rec, ATTR_ID_PROVIDER_NAME, HID_MAX_PROV_NAME_LEN,
173                     p_nvi->prov_name);
174 
175   if (((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HID_DEVICE_RELNUM)) !=
176        NULL)) {
177     p_nvi->rel_num = p_attr->attr_value.v.u16;
178   }
179 
180   if (((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HID_COUNTRY_CODE)) !=
181        NULL)) {
182     p_nvi->ctry_code = p_attr->attr_value.v.u8;
183   }
184 
185   if (((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HID_DEVICE_SUBCLASS)) !=
186        NULL)) {
187     p_nvi->sub_class = p_attr->attr_value.v.u8;
188   }
189 
190   if (((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HID_PARSER_VERSION)) !=
191        NULL)) {
192     p_nvi->hpars_ver = p_attr->attr_value.v.u16;
193   }
194 
195   if (((p_attr = SDP_FindAttributeInRec(
196             p_rec, ATTR_ID_HID_LINK_SUPERVISION_TO)) != NULL)) {
197     attr_mask |= HID_SUP_TOUT_AVLBL;
198     p_nvi->sup_timeout = p_attr->attr_value.v.u16;
199   }
200 
201   if (((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HID_SSR_HOST_MAX_LAT)) !=
202        NULL)) {
203     attr_mask |= HID_SSR_MAX_LATENCY;
204     p_nvi->ssr_max_latency = p_attr->attr_value.v.u16;
205   } else
206     p_nvi->ssr_max_latency = HID_SSR_PARAM_INVALID;
207 
208   if (((p_attr = SDP_FindAttributeInRec(
209             p_rec, ATTR_ID_HID_SSR_HOST_MIN_TOUT)) != NULL)) {
210     attr_mask |= HID_SSR_MIN_TOUT;
211     p_nvi->ssr_min_tout = p_attr->attr_value.v.u16;
212   } else
213     p_nvi->ssr_min_tout = HID_SSR_PARAM_INVALID;
214 
215   hh_cb.sdp_rec.p_sdp_layer_rec = p_rec;
216   hh_cb.sdp_cback(SDP_SUCCESS, attr_mask, &hh_cb.sdp_rec);
217 }
218 
219 /*******************************************************************************
220  *
221  * Function         HID_HostInit
222  *
223  * Description      This function initializes the control block and trace
224  *                  variable
225  *
226  * Returns          void
227  *
228  ******************************************************************************/
HID_HostInit(void)229 void HID_HostInit(void) {
230   uint8_t log_level = hh_cb.trace_level;
231   memset(&hh_cb, 0, sizeof(tHID_HOST_CTB));
232   hh_cb.trace_level = log_level;
233 }
234 
235 /*******************************************************************************
236  *
237  * Function         HID_HostSetTraceLevel
238  *
239  * Description      This function sets the trace level for HID Host. If called
240  *                  with 0xFF, it simply reads the current trace level.
241  *
242  * Returns          the new (current) trace level
243  *
244  ******************************************************************************/
HID_HostSetTraceLevel(uint8_t new_level)245 uint8_t HID_HostSetTraceLevel(uint8_t new_level) {
246   if (new_level != 0xFF) hh_cb.trace_level = new_level;
247 
248   return (hh_cb.trace_level);
249 }
250 
251 /*******************************************************************************
252  *
253  * Function         HID_HostRegister
254  *
255  * Description      This function registers HID-Host with lower layers
256  *
257  * Returns          tHID_STATUS
258  *
259  ******************************************************************************/
HID_HostRegister(tHID_HOST_DEV_CALLBACK * dev_cback)260 tHID_STATUS HID_HostRegister(tHID_HOST_DEV_CALLBACK* dev_cback) {
261   tHID_STATUS st;
262 
263   if (hh_cb.reg_flag) return HID_ERR_ALREADY_REGISTERED;
264 
265   if (dev_cback == NULL) return HID_ERR_INVALID_PARAM;
266 
267   /* Register with L2CAP */
268   st = hidh_conn_reg();
269   if (st != HID_SUCCESS) {
270     return st;
271   }
272 
273   hh_cb.callback = dev_cback;
274   hh_cb.reg_flag = true;
275 
276   for (size_t i = 0; i < HID_HOST_MAX_DEVICES; i++) {
277     hh_cb.devices[i].conn.process_repage_timer =
278         alarm_new("hid_devices_conn.process_repage_timer");
279   }
280   return (HID_SUCCESS);
281 }
282 
283 /*******************************************************************************
284  *
285  * Function         HID_HostDeregister
286  *
287  * Description      This function is called when the host is about power down.
288  *
289  * Returns          tHID_STATUS
290  *
291  ******************************************************************************/
HID_HostDeregister(void)292 tHID_STATUS HID_HostDeregister(void) {
293   uint8_t i;
294 
295   if (!hh_cb.reg_flag) return (HID_ERR_NOT_REGISTERED);
296 
297   for (i = 0; i < HID_HOST_MAX_DEVICES; i++) {
298     HID_HostRemoveDev(i);
299     alarm_free(hh_cb.devices[i].conn.process_repage_timer);
300   }
301 
302   hidh_conn_dereg();
303   hh_cb.reg_flag = false;
304 
305   return (HID_SUCCESS);
306 }
307 
308 /*******************************************************************************
309  *
310  * Function         HID_HostAddDev
311  *
312  * Description      This is called so HID-host may manage this device.
313  *
314  * Returns          tHID_STATUS
315  *
316  ******************************************************************************/
HID_HostAddDev(const RawAddress & addr,uint16_t attr_mask,uint8_t * handle)317 tHID_STATUS HID_HostAddDev(const RawAddress& addr, uint16_t attr_mask,
318                            uint8_t* handle) {
319   int i;
320   /* Find an entry for this device in hh_cb.devices array */
321   if (!hh_cb.reg_flag) return (HID_ERR_NOT_REGISTERED);
322 
323   for (i = 0; i < HID_HOST_MAX_DEVICES; i++) {
324     if ((hh_cb.devices[i].in_use) && addr == hh_cb.devices[i].addr) break;
325   }
326 
327   if (i == HID_HOST_MAX_DEVICES) {
328     for (i = 0; i < HID_HOST_MAX_DEVICES; i++) {
329       if (!hh_cb.devices[i].in_use) break;
330     }
331   }
332 
333   if (i == HID_HOST_MAX_DEVICES) return HID_ERR_NO_RESOURCES;
334 
335   if (!hh_cb.devices[i].in_use) {
336     hh_cb.devices[i].in_use = true;
337     hh_cb.devices[i].addr = addr;
338     hh_cb.devices[i].state = HID_DEV_NO_CONN;
339     hh_cb.devices[i].conn_tries = 0;
340   }
341 
342   if (attr_mask != HID_ATTR_MASK_IGNORE) hh_cb.devices[i].attr_mask = attr_mask;
343 
344   *handle = i;
345 
346   return (HID_SUCCESS);
347 }
348 
349 /*******************************************************************************
350  *
351  * Function         HID_HostRemoveDev
352  *
353  * Description      This removes the device from the list of devices that the
354  *                  host has to manage.
355  *
356  * Returns          tHID_STATUS
357  *
358  ******************************************************************************/
HID_HostRemoveDev(uint8_t dev_handle)359 tHID_STATUS HID_HostRemoveDev(uint8_t dev_handle) {
360   if (!hh_cb.reg_flag) return (HID_ERR_NOT_REGISTERED);
361 
362   if ((dev_handle >= HID_HOST_MAX_DEVICES) ||
363       (!hh_cb.devices[dev_handle].in_use))
364     return HID_ERR_INVALID_PARAM;
365 
366   HID_HostCloseDev(dev_handle);
367   hh_cb.devices[dev_handle].in_use = false;
368   hh_cb.devices[dev_handle].conn.conn_state = HID_CONN_STATE_UNUSED;
369   hh_cb.devices[dev_handle].conn.ctrl_cid =
370       hh_cb.devices[dev_handle].conn.intr_cid = 0;
371   hh_cb.devices[dev_handle].attr_mask = 0;
372   return HID_SUCCESS;
373 }
374 
375 /*******************************************************************************
376  *
377  * Function         HID_HostOpenDev
378  *
379  * Description      This function is called when the user wants to initiate a
380  *                  connection attempt to a device.
381  *
382  * Returns          void
383  *
384  ******************************************************************************/
HID_HostOpenDev(uint8_t dev_handle)385 tHID_STATUS HID_HostOpenDev(uint8_t dev_handle) {
386   if (!hh_cb.reg_flag) return (HID_ERR_NOT_REGISTERED);
387 
388   if ((dev_handle >= HID_HOST_MAX_DEVICES) ||
389       (!hh_cb.devices[dev_handle].in_use))
390     return HID_ERR_INVALID_PARAM;
391 
392   if (hh_cb.devices[dev_handle].state != HID_DEV_NO_CONN)
393     return HID_ERR_ALREADY_CONN;
394 
395   hh_cb.devices[dev_handle].conn_tries = 1;
396   return hidh_conn_initiate(dev_handle);
397 }
398 
399 /*******************************************************************************
400  *
401  * Function         HID_HostWriteDev
402  *
403  * Description      This function is called when the host has a report to send.
404  *
405  *                  report_id: is only used on GET_REPORT transaction if is
406  *                              specified. only valid when it is non-zero.
407  *
408  * Returns          void
409  *
410  ******************************************************************************/
HID_HostWriteDev(uint8_t dev_handle,uint8_t t_type,uint8_t param,uint16_t data,uint8_t report_id,BT_HDR * pbuf)411 tHID_STATUS HID_HostWriteDev(uint8_t dev_handle, uint8_t t_type, uint8_t param,
412                              uint16_t data, uint8_t report_id, BT_HDR* pbuf) {
413   tHID_STATUS status = HID_SUCCESS;
414 
415   if (!hh_cb.reg_flag) {
416     HIDH_TRACE_ERROR("HID_ERR_NOT_REGISTERED");
417     status = HID_ERR_NOT_REGISTERED;
418   }
419 
420   if ((dev_handle >= HID_HOST_MAX_DEVICES) ||
421       (!hh_cb.devices[dev_handle].in_use)) {
422     HIDH_TRACE_ERROR("HID_ERR_INVALID_PARAM");
423     status = HID_ERR_INVALID_PARAM;
424   }
425 
426   else if (hh_cb.devices[dev_handle].state != HID_DEV_CONNECTED) {
427     HIDH_TRACE_ERROR("HID_ERR_NO_CONNECTION dev_handle %d", dev_handle);
428     status = HID_ERR_NO_CONNECTION;
429   }
430 
431   if (status != HID_SUCCESS)
432     osi_free(pbuf);
433   else
434     status =
435         hidh_conn_snd_data(dev_handle, t_type, param, data, report_id, pbuf);
436 
437   return status;
438 }
439 
440 /*******************************************************************************
441  *
442  * Function         HID_HostCloseDev
443  *
444  * Description      This function disconnects the device.
445  *
446  * Returns          void
447  *
448  ******************************************************************************/
HID_HostCloseDev(uint8_t dev_handle)449 tHID_STATUS HID_HostCloseDev(uint8_t dev_handle) {
450   if (!hh_cb.reg_flag) return (HID_ERR_NOT_REGISTERED);
451 
452   if ((dev_handle >= HID_HOST_MAX_DEVICES) ||
453       (!hh_cb.devices[dev_handle].in_use))
454     return HID_ERR_INVALID_PARAM;
455 
456   if (hh_cb.devices[dev_handle].state != HID_DEV_CONNECTED)
457     return HID_ERR_NO_CONNECTION;
458 
459   alarm_cancel(hh_cb.devices[dev_handle].conn.process_repage_timer);
460   hh_cb.devices[dev_handle].conn_tries = HID_HOST_MAX_CONN_RETRY + 1;
461   return hidh_conn_disconnect(dev_handle);
462 }
463 
HID_HostSetSecurityLevel(const char serv_name[],uint8_t sec_lvl)464 tHID_STATUS HID_HostSetSecurityLevel(const char serv_name[], uint8_t sec_lvl) {
465   if (!BTM_SetSecurityLevel(false, serv_name, BTM_SEC_SERVICE_HIDH_SEC_CTRL,
466                             sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID,
467                             HID_SEC_CHN)) {
468     HIDH_TRACE_ERROR("Security Registration 1 failed");
469     return (HID_ERR_NO_RESOURCES);
470   }
471 
472   if (!BTM_SetSecurityLevel(true, serv_name, BTM_SEC_SERVICE_HIDH_SEC_CTRL,
473                             sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID,
474                             HID_SEC_CHN)) {
475     HIDH_TRACE_ERROR("Security Registration 2 failed");
476     return (HID_ERR_NO_RESOURCES);
477   }
478 
479   if (!BTM_SetSecurityLevel(false, serv_name, BTM_SEC_SERVICE_HIDH_NOSEC_CTRL,
480                             BTM_SEC_NONE, HID_PSM_CONTROL, BTM_SEC_PROTO_HID,
481                             HID_NOSEC_CHN)) {
482     HIDH_TRACE_ERROR("Security Registration 3 failed");
483     return (HID_ERR_NO_RESOURCES);
484   }
485 
486   if (!BTM_SetSecurityLevel(true, serv_name, BTM_SEC_SERVICE_HIDH_NOSEC_CTRL,
487                             BTM_SEC_NONE, HID_PSM_CONTROL, BTM_SEC_PROTO_HID,
488                             HID_NOSEC_CHN)) {
489     HIDH_TRACE_ERROR("Security Registration 4 failed");
490     return (HID_ERR_NO_RESOURCES);
491   }
492 
493   if (!BTM_SetSecurityLevel(true, serv_name, BTM_SEC_SERVICE_HIDH_INTR,
494                             BTM_SEC_NONE, HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID,
495                             0)) {
496     HIDH_TRACE_ERROR("Security Registration 5 failed");
497     return (HID_ERR_NO_RESOURCES);
498   }
499 
500   if (!BTM_SetSecurityLevel(false, serv_name, BTM_SEC_SERVICE_HIDH_INTR,
501                             BTM_SEC_NONE, HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID,
502                             0)) {
503     HIDH_TRACE_ERROR("Security Registration 6 failed");
504     return (HID_ERR_NO_RESOURCES);
505   }
506 
507   return (HID_SUCCESS);
508 }
509 
510 /******************************************************************************
511  *
512  * Function         hid_known_hid_device
513  *
514  * Description      check if this device is  of type HID Device
515  *
516  * Returns          true if device is HID Device else false
517  *
518  ******************************************************************************/
hid_known_hid_device(const RawAddress & bd_addr)519 bool hid_known_hid_device(const RawAddress& bd_addr) {
520   uint8_t i;
521   tBTM_INQ_INFO* p_inq_info = BTM_InqDbRead(bd_addr);
522 
523   if (!hh_cb.reg_flag) return false;
524 
525   /* First  check for class of device , if Inq DB has information about this
526    * device*/
527   if (p_inq_info != NULL) {
528     /* Check if remote major device class is of type BTM_COD_MAJOR_PERIPHERAL */
529     if ((p_inq_info->results.dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) ==
530         BTM_COD_MAJOR_PERIPHERAL) {
531       HIDH_TRACE_DEBUG(
532           "hid_known_hid_device:dev found in InqDB & COD matches HID dev");
533       return true;
534     }
535   } else {
536     /* Look for this device in security device DB */
537     tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr);
538     if ((p_dev_rec != NULL) &&
539         ((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) ==
540          BTM_COD_MAJOR_PERIPHERAL)) {
541       HIDH_TRACE_DEBUG(
542           "hid_known_hid_device:dev found in SecDevDB & COD matches HID dev");
543       return true;
544     }
545   }
546 
547   /* Find an entry for this device in hh_cb.devices array */
548   for (i = 0; i < HID_HOST_MAX_DEVICES; i++) {
549     if ((hh_cb.devices[i].in_use) && bd_addr == hh_cb.devices[i].addr)
550       return true;
551   }
552   /* Check if this device is marked as HID Device in IOP Dev */
553   HIDH_TRACE_DEBUG("hid_known_hid_device:remote is not HID device");
554   return false;
555 }
556