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