blob: 41512d4f525eb9f64274acda26a00f43b1c9f961 [file] [log] [blame]
Andre Eisenbach2e7fa682013-08-08 15:42:48 -07001/*****************************************************************************
2**
3** Name: bta_hh_le.c
4**
5** Description: This file contains the HID host over LE
6** functions.
7**
8** Copyright (c) 2005-2011, Broadcom Corp, All Rights Reserved.
9** Broadcom Bluetooth Core. Proprietary and confidential.
10**
11*****************************************************************************/
12
13#include "bta_api.h"
14#include "bta_hh_int.h"
15
16#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
17
18#include "bta_api.h"
19#include <string.h>
20#include "btm_api.h"
21#include "btm_ble_api.h"
22#include "bta_hh_co.h"
23#include "bta_gatt_api.h"
24#include "srvc_api.h"
25
26#ifndef BTA_HH_LE_RECONN
27#define BTA_HH_LE_RECONN TRUE
28#endif
29
30#define BTA_HH_APP_ID_LE 0xff
31
32#define BTA_HH_LE_RPT_TYPE_VALID(x) ((x) <= BTA_LE_HID_RPT_FEATURE && (x)>=BTA_LE_HID_RPT_INPUT)
33
34#define BTA_HH_LE_RPT_INST_ID_MAP(s,c) (UINT8)(((s)<<4)||(c))
35#define BTA_HH_LE_RPT_GET_SRVC_INST_ID(x) (UINT8)(x >> 4)
36#define BTA_HH_LE_RPT_GET_RPT_INST_ID(x) (UINT8)(x & 0x0f)
37
38
39#define BTA_HH_LE_PROTO_BOOT_MODE 0x00
40#define BTA_HH_LE_PROTO_REPORT_MODE 0x01
41
42#define BTA_HH_SCPP_INST_DEF 0
43
44#define BTA_HH_LE_DISC_CHAR_NUM 8
45static const UINT16 bta_hh_le_disc_char_uuid[BTA_HH_LE_DISC_CHAR_NUM] =
46{
47 GATT_UUID_HID_INFORMATION,
48 GATT_UUID_HID_REPORT_MAP,
49 GATT_UUID_HID_CONTROL_POINT,
50 GATT_UUID_HID_REPORT,
51 GATT_UUID_HID_BT_KB_INPUT,
52 GATT_UUID_HID_BT_KB_OUTPUT,
53 GATT_UUID_HID_BT_MOUSE_INPUT,
54 GATT_UUID_HID_PROTO_MODE /* always make sure this is the last attribute to discover */
55};
56
57#define BTA_LE_HID_RTP_UUID_MAX 5
58static const UINT16 bta_hh_uuid_to_rtp_type[BTA_LE_HID_RTP_UUID_MAX][2] =
59{
60 {GATT_UUID_HID_REPORT, BTA_HH_RPTT_INPUT},
61 {GATT_UUID_HID_BT_KB_INPUT, BTA_HH_RPTT_INPUT},
62 {GATT_UUID_HID_BT_KB_OUTPUT, BTA_HH_RPTT_OUTPUT},
63 {GATT_UUID_HID_BT_MOUSE_INPUT, BTA_HH_RPTT_INPUT},
64 {GATT_UUID_BATTERY_LEVEL, BTA_HH_RPTT_INPUT}
65};
66
67
68static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
69static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB *p_dev_cb);
70static void bta_hh_le_search_hid_included(tBTA_HH_DEV_CB *p_dev_cb);
71static void bta_hh_le_search_scps(tBTA_HH_DEV_CB *p_cb);
72static void bta_hh_le_search_scps_chars(tBTA_HH_DEV_CB *p_cb);
73static void bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status);
74static void bta_hh_le_register_scpp_notif_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status);
75static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond);
76
77#define BTA_HH_LE_SRVC_DEF 0
78
79#if BTA_HH_DEBUG == TRUE
80static const char *bta_hh_le_rpt_name[4] =
81{
82 "UNKNOWN",
83 "INPUT",
84 "OUTPUT",
85 "FEATURE"
86};
87
88/*******************************************************************************
89**
90** Function bta_hh_le_hid_report_dbg
91**
92** Description debug function to print out all HID report available on remote
93** device.
94**
95** Returns void
96**
97*******************************************************************************/
98static void bta_hh_le_hid_report_dbg(tBTA_HH_DEV_CB *p_cb)
99{
100 UINT8 i , j;
101 tBTA_HH_LE_RPT *p_rpt;
102 char * rpt_name;
103
104 APPL_TRACE_DEBUG0("HID Report DB");
105 for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++)
106 {
107 if (p_cb->hid_srvc[i].in_use)
108 {
109 p_rpt = &p_cb->hid_srvc[i].report[0];
110
111 APPL_TRACE_DEBUG1("\t HID serivce inst: %d", i);
112
113 for (j = 0; j < BTA_HH_LE_RPT_MAX; j ++, p_rpt++)
114 {
115 rpt_name = "Unknown";
116 if (p_rpt->in_use)
117 {
118 if (p_rpt->uuid == GATT_UUID_HID_REPORT)
119 rpt_name = "Report";
120 if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT)
121 rpt_name = "Boot KB Input";
122 if (p_rpt->uuid == GATT_UUID_HID_BT_KB_OUTPUT)
123 rpt_name = "Boot KB Output";
124 if (p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT)
125 rpt_name = "Boot MI Input";
126
127
128 APPL_TRACE_DEBUG6("\t\t [%s- 0x%04x] [Type: %s], [ReportID: %d] [inst_id: %d] [Clt_cfg: %d]",
129 rpt_name,
130 p_rpt->uuid ,
131 ((p_rpt->rpt_type < 4) ? bta_hh_le_rpt_name[p_rpt->rpt_type] : "UNKNOWN"),
132 p_rpt->rpt_id,
133 p_rpt->inst_id,
134 p_rpt->client_cfg_value);
135 }
136 else
137 break;
138 }
139 }
140 else
141 break;
142 }
143}
144/*******************************************************************************
145**
146** Function bta_hh_uuid_to_str
147**
148** Description
149**
150** Returns void
151**
152*******************************************************************************/
153static char *bta_hh_uuid_to_str(UINT16 uuid)
154{
155 switch(uuid)
156 {
157 case GATT_UUID_HID_INFORMATION:
158 return "GATT_UUID_HID_INFORMATION";
159 case GATT_UUID_HID_REPORT_MAP:
160 return "GATT_UUID_HID_REPORT_MAP";
161 case GATT_UUID_HID_CONTROL_POINT:
162 return "GATT_UUID_HID_CONTROL_POINT";
163 case GATT_UUID_HID_REPORT:
164 return "GATT_UUID_HID_REPORT";
165 case GATT_UUID_HID_PROTO_MODE:
166 return "GATT_UUID_HID_PROTO_MODE";
167 case GATT_UUID_HID_BT_KB_INPUT:
168 return "GATT_UUID_HID_BT_KB_INPUT";
169 case GATT_UUID_HID_BT_KB_OUTPUT:
170 return "GATT_UUID_HID_BT_KB_OUTPUT";
171 case GATT_UUID_HID_BT_MOUSE_INPUT:
172 return "GATT_UUID_HID_BT_MOUSE_INPUT";
173 case GATT_UUID_CHAR_CLIENT_CONFIG:
174 return "GATT_UUID_CHAR_CLIENT_CONFIG";
175 case GATT_UUID_EXT_RPT_REF_DESCR:
176 return "GATT_UUID_EXT_RPT_REF_DESCR";
177 case GATT_UUID_RPT_REF_DESCR:
178 return "GATT_UUID_RPT_REF_DESCR";
179 default:
180 return "Unknown UUID";
181 }
182}
183#endif
184/*******************************************************************************
185**
186** Function bta_hh_le_enable
187**
188** Description initialize LE HID related functionality
189**
190**
191** Returns void
192**
193*******************************************************************************/
194void bta_hh_le_enable(void)
195{
196 char app_name[LEN_UUID_128 + 1];
197 tBT_UUID app_uuid = {LEN_UUID_128,{0}};
198 UINT8 xx;
199
200 bta_hh_cb.gatt_if = BTA_GATTS_INVALID_IF;
201
202 for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
203 bta_hh_cb.le_cb_index[xx] = BTA_HH_IDX_INVALID;
204
205 memset (app_name, 0, LEN_UUID_128 + 1);
206 strncpy(app_name, "BTA HH OVER LE", LEN_UUID_128);
207
208 memcpy((void *)app_uuid.uu.uuid128, (void *)app_name, LEN_UUID_128);
209
210 BTA_GATTC_AppRegister(&app_uuid, bta_hh_gattc_callback);
211
212 return;
213}
214/*******************************************************************************
215**
216** Function bta_hh_le_register_cmpl
217**
218** Description BTA HH register with BTA GATTC completed
219**
220** Parameters:
221**
222*******************************************************************************/
223void bta_hh_le_register_cmpl(tBTA_GATTC_REG *p_reg)
224{
225 tBTA_HH_STATUS status = BTA_HH_ERR;
226
227 if (p_reg->status == BTA_GATT_OK)
228 {
229 bta_hh_cb.gatt_if = p_reg->client_if;
230 status = BTA_HH_OK;
231 }
232 else
233 bta_hh_cb.gatt_if = BTA_GATTS_INVALID_IF;
234
235 /* signal BTA call back event */
236 (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
237}
238
239/*******************************************************************************
240**
241** Function bta_hh_le_deregister
242**
243** Description De-register BTA HH from BTA GATTC
244**
245**
246** Returns void
247**
248*******************************************************************************/
249void bta_hh_le_deregister(void)
250{
251 BTA_GATTC_AppDeregister(bta_hh_cb.gatt_if);
252}
253
254/*******************************************************************************
255**
256** Function bta_hh_is_le_device
257**
258** Description Check to see if the remote device is a LE only device
259**
260** Parameters:
261**
262*******************************************************************************/
263BOOLEAN bta_hh_is_le_device(tBTA_HH_DEV_CB *p_cb, BD_ADDR remote_bda)
264{
265 p_cb->is_le_device = BTM_UseLeLink (remote_bda);
266
267 return p_cb->is_le_device;
268}
269/*******************************************************************************
270**
271** Function bta_hh_le_hid_srvc_cached
272**
273** Description Check to see if LE HID service has been discovered and cached
274**
275** Parameters: TRUE : has cache; FALSE: none.
276**
277*******************************************************************************/
278BOOLEAN bta_hh_le_hid_srvc_cached(tBTA_HH_DEV_CB *p_dev_cb)
279{
280 if (p_dev_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].in_use)
281 return TRUE;
282 else
283 return FALSE;
284}
285/*******************************************************************************
286**
287** Function bta_hh_le_add_hid_srvc_entry
288**
289** Description Add a HID service entry in the HID device control block
290**
291** Parameters:
292**
293*******************************************************************************/
294BOOLEAN bta_hh_le_add_hid_srvc_entry(tBTA_HH_DEV_CB *p_dev_cb, UINT8 idx)
295{
296 BOOLEAN added = FALSE;
297
298 if (idx < BTA_HH_LE_HID_SRVC_MAX)
299 {
300 p_dev_cb->hid_srvc[idx].in_use = TRUE;
301 added = TRUE;
302 }
303 else
304 {
305 APPL_TRACE_ERROR0("DB full,max HID service entry!");
306 }
307 return added;
308
309}
310/*******************************************************************************
311**
312** Function bta_hh_le_open_conn
313**
314** Description open a GATT connection first.
315**
316** Parameters:
317**
318*******************************************************************************/
319void bta_hh_le_open_conn(tBTA_HH_DEV_CB *p_cb, BD_ADDR remote_bda)
320{
321 /* update cb_index[] map */
322 p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
323 memcpy(p_cb->addr, remote_bda, BD_ADDR_LEN);
324 bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
325 p_cb->in_use = TRUE;
326
327 BTA_GATTC_Open(bta_hh_cb.gatt_if, remote_bda, TRUE);
328}
329/*******************************************************************************
330**
331** Function bta_hh_le_fill_16bits_gatt_id
332**
333** Description Utility function to fill a GATT ID strucure
334**
335*******************************************************************************/
336void bta_hh_le_fill_16bits_gatt_id(UINT8 inst_id, UINT16 uuid, tBTA_GATT_ID *p_output)
337{
338 p_output->inst_id = inst_id;
339 p_output->uuid.len = LEN_UUID_16;
340 p_output->uuid.uu.uuid16 = uuid;
341}
342/*******************************************************************************
343**
344** Function bta_hh_le_fill_16bits_srvc_id
345**
346** Description Utility function to fill a service ID strucure with a 16 bits
347** service UUID.
348**
349*******************************************************************************/
350void bta_hh_le_fill_16bits_srvc_id(BOOLEAN is_pri, UINT8 inst_id, UINT16 srvc_uuid,
351 tBTA_GATT_SRVC_ID *p_output)
352{
353 memset((void *)p_output, 0, sizeof(tBTA_GATT_SRVC_ID));
354 p_output->is_primary = is_pri;
355 bta_hh_le_fill_16bits_gatt_id(inst_id, srvc_uuid, &p_output->id);
356
357}
358/*******************************************************************************
359**
360** Function bta_hh_le_fill_16bits_char_id
361**
362** Description Utility function to fill a char ID strucure with a 16 bits
363** char UUID.
364**
365*******************************************************************************/
366void bta_hh_le_fill_16bits_char_id(UINT8 inst_id, UINT16 char_uuid,
367 tBTA_GATT_ID *p_output)
368{
369 memset((void *)p_output, 0, sizeof(tBTA_GATT_ID));
370 bta_hh_le_fill_16bits_gatt_id(inst_id, char_uuid, p_output);
371}
372/*******************************************************************************
373**
374** Function bta_hh_le_find_dev_cb_by_conn_id
375**
376** Description Utility function find a device control block by connection ID.
377**
378*******************************************************************************/
379tBTA_HH_DEV_CB * bta_hh_le_find_dev_cb_by_conn_id(UINT16 conn_id)
380{
381 UINT8 i;
382 tBTA_HH_DEV_CB *p_dev_cb = &bta_hh_cb.kdev[0];
383
384 for (i = 0; i < BTA_HH_MAX_DEVICE; i ++, p_dev_cb ++)
385 {
386 if (p_dev_cb->in_use && p_dev_cb->conn_id == conn_id)
387 return p_dev_cb;
388 }
389 return NULL;
390}
391/*******************************************************************************
392**
393** Function bta_hh_le_find_dev_cb_by_bda
394**
395** Description Utility function find a device control block by BD address.
396**
397*******************************************************************************/
398tBTA_HH_DEV_CB * bta_hh_le_find_dev_cb_by_bda(BD_ADDR bda)
399{
400 UINT8 i;
401 tBTA_HH_DEV_CB *p_dev_cb = &bta_hh_cb.kdev[0];
402
403 for (i = 0; i < BTA_HH_MAX_DEVICE; i ++, p_dev_cb ++)
404 {
405 if (p_dev_cb->in_use &&
406 memcmp(p_dev_cb->addr, bda, BD_ADDR_LEN) == 0)
407 return p_dev_cb;
408 }
409 return NULL;
410}
411UINT8 bta_hh_le_find_service_inst_by_battery_inst_id(tBTA_HH_DEV_CB *p_cb, UINT8 ba_inst_id)
412{
413 UINT8 i;
414
415 for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++)
416 {
417 if (p_cb->hid_srvc[i].in_use &&
418 p_cb->hid_srvc[i].incl_srvc_inst == ba_inst_id)
419 {
420 return i;
421 }
422 }
423 return BTA_HH_IDX_INVALID;
424}
425/*******************************************************************************
426**
427** Function bta_hh_le_find_report_entry
428**
429** Description find the report entry by service instance and report UUID and
430** instance ID
431**
432*******************************************************************************/
433tBTA_HH_LE_RPT * bta_hh_le_find_report_entry(tBTA_HH_DEV_CB *p_cb,
434 UINT8 srvc_inst_id, /* service instance ID */
435 UINT16 rpt_uuid,
436 UINT8 char_inst_id)
437{
438 UINT8 i;
439 UINT8 hid_inst_id = srvc_inst_id;
440 tBTA_HH_LE_RPT *p_rpt;
441
442 if (rpt_uuid == GATT_UUID_BATTERY_LEVEL)
443 {
444 hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_cb, srvc_inst_id);
445
446 if (hid_inst_id == BTA_HH_IDX_INVALID)
447 return NULL;
448 }
449
450 p_rpt = &p_cb->hid_srvc[hid_inst_id].report[0];
451
452 for (i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++)
453 {
454 if (p_rpt->uuid == rpt_uuid &&
455 p_rpt->inst_id == BTA_HH_LE_RPT_INST_ID_MAP(srvc_inst_id, char_inst_id))
456 {
457
458 return p_rpt;
459 }
460 }
461 return NULL;
462
463}
464/*******************************************************************************
465**
466** Function bta_hh_le_find_rpt_by_idtype
467**
468** Description find a report entry by report ID and protocol mode
469**
470** Returns void
471**
472*******************************************************************************/
473tBTA_HH_LE_RPT * bta_hh_le_find_rpt_by_idtype(tBTA_HH_LE_RPT*p_head, UINT8 mode,
474 tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id)
475{
476 tBTA_HH_LE_RPT *p_rpt = p_head;
477 UINT8 i;
478
479#if BTA_HH_DEBUG == TRUE
480 APPL_TRACE_DEBUG2("bta_hh_le_find_rpt_by_idtype: r_tpye: %d rpt_id: %d", r_type, rpt_id);
481#endif
482
483 for (i = 0 ; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt++)
484 {
485 if (p_rpt->in_use && p_rpt->rpt_id == rpt_id && r_type == p_rpt->rpt_type)
486 {
487 /* return battery report w/o condition */
488 if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
489 return p_rpt;
490
491 if (mode == BTA_HH_PROTO_RPT_MODE && p_rpt->uuid == GATT_UUID_HID_REPORT)
492 return p_rpt;
493
494 if ( mode ==BTA_HH_PROTO_BOOT_MODE &&
495 (p_rpt->uuid >= GATT_UUID_HID_BT_KB_INPUT && p_rpt->uuid <= GATT_UUID_HID_BT_MOUSE_INPUT))
496 return p_rpt;
497 }
498 }
499 return NULL;
500}
501/*******************************************************************************
502**
503** Function bta_hh_le_find_alloc_report_entry
504**
505** Description find or allocate a report entry in the HID service report list.
506**
507*******************************************************************************/
508tBTA_HH_LE_RPT * bta_hh_le_find_alloc_report_entry(tBTA_HH_DEV_CB *p_cb,
509 UINT8 srvc_inst_id,
510 UINT16 rpt_uuid,
511 UINT8 inst_id,
512 UINT8 prop)
513{
514 UINT8 i, hid_inst_id = srvc_inst_id;
515 tBTA_HH_LE_RPT *p_rpt;
516
517 if (rpt_uuid == GATT_UUID_BATTERY_LEVEL)
518 {
519 hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_cb, srvc_inst_id);
520
521 if (hid_inst_id == BTA_HH_IDX_INVALID)
522 return NULL;
523 }
524 p_rpt = &p_cb->hid_srvc[hid_inst_id].report[0];
525
526 for (i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++)
527 {
528 if (!p_rpt->in_use ||
529 (p_rpt->uuid == rpt_uuid &&
530 p_rpt->inst_id == BTA_HH_LE_RPT_INST_ID_MAP(srvc_inst_id, inst_id)))
531 {
532 if (!p_rpt->in_use)
533 {
534 p_rpt->in_use = TRUE;
535 p_rpt->index = i;
536 p_rpt->inst_id = BTA_HH_LE_RPT_INST_ID_MAP(srvc_inst_id, inst_id);
537 p_rpt->prop = prop;
538 p_rpt->uuid = rpt_uuid;
539
540 /* assign report type */
541 for (i = 0; i < BTA_LE_HID_RTP_UUID_MAX; i ++)
542 {
543 if (bta_hh_uuid_to_rtp_type[i][0] == rpt_uuid)
544 {
545 p_rpt->rpt_type = (tBTA_HH_RPT_TYPE)bta_hh_uuid_to_rtp_type[i][1];
546
547 if (rpt_uuid == GATT_UUID_HID_BT_KB_INPUT || rpt_uuid == GATT_UUID_HID_BT_KB_OUTPUT)
548 p_rpt->rpt_id = BTA_HH_KEYBD_RPT_ID;
549
550 if (rpt_uuid == GATT_UUID_HID_BT_MOUSE_INPUT)
551 p_rpt->rpt_id = BTA_HH_MOUSE_RPT_ID;
552
553 break;
554 }
555 }
556 }
557
558 return p_rpt;
559 }
560 }
561 return NULL;
562}
563
564/*******************************************************************************
565**
566** Function bta_hh_le_read_char_dscrpt
567**
568** Description read cahracteristic descriptor
569**
570*******************************************************************************/
571tBTA_HH_STATUS bta_hh_le_read_char_dscrpt(tBTA_HH_DEV_CB *p_cb, UINT16 srvc_uuid, UINT8 srvc_inst_id,
572 UINT16 char_uuid, UINT8 char_inst_id, UINT16 char_descp_uuid)
573{
574 tBTA_GATTC_CHAR_ID char_id;
575 tBT_UUID descr_uuid;
576 tBTA_GATTC_CHAR_DESCR_ID descr_id;
577 tBTA_HH_STATUS status = BTA_HH_ERR;
578
579 bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst_id, srvc_uuid, &char_id.srvc_id);
580 bta_hh_le_fill_16bits_char_id(char_inst_id, char_uuid, &char_id.char_id);
581
582 descr_uuid.len = LEN_UUID_16;
583 descr_uuid.uu.uuid16 = char_descp_uuid;
584
585 /* find the report reference descriptor */
586 if (BTA_GATTC_GetFirstCharDescr(p_cb->conn_id,
587 &char_id,
588 &descr_uuid,
589 &descr_id) == BTA_GATT_OK)
590 {
591 BTA_GATTC_ReadCharDescr(p_cb->conn_id,
592 &descr_id,
593 BTA_GATT_AUTH_REQ_NONE);
594
595 status = BTA_HH_OK;
596 }
597 else
598 {
599#if BTA_HH_DEBUG == TRUE
600 APPL_TRACE_ERROR2("bta_hh_le_read_char_dscrpt: No such descrpt exists: %s(0x%04x)",
601 bta_hh_uuid_to_str(char_descp_uuid), char_descp_uuid);
602#endif
603 }
604 return status;
605}
606/*******************************************************************************
607**
608** Function bta_hh_le_read_rpt_ref_descr
609**
610** Description read report refernece descriptors in service discovery process
611**
612*******************************************************************************/
613void bta_hh_le_read_rpt_ref_descr(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_LE_RPT *p_rpt)
614{
615 BOOLEAN started = FALSE;
616 UINT16 srvc_uuid, char_uuid;
617
618 while (p_rpt != NULL)
619 {
620 if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
621 {
622 /* is battery report */
623 if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
624 {
625#if BTA_HH_DEBUG == TRUE
626 APPL_TRACE_DEBUG0("read battery level report reference descriptor");
627#endif
628 srvc_uuid = UUID_SERVCLASS_BATTERY;
629 char_uuid = GATT_UUID_BATTERY_LEVEL;
630 }
631 else
632 {
633#if BTA_HH_DEBUG == TRUE
634 APPL_TRACE_DEBUG0("read HID report reference descriptor");
635#endif
636 srvc_uuid = UUID_SERVCLASS_LE_HID;
637 char_uuid = GATT_UUID_HID_REPORT;
638 }
639
640 if (bta_hh_le_read_char_dscrpt(p_dev_cb,
641 srvc_uuid,
642 BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt->inst_id),
643 char_uuid,
644 BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt->inst_id),
645 GATT_UUID_RPT_REF_DESCR)
646 == BTA_HH_OK)
647 {
648 started = TRUE;
649 break;
650 }
651 }
652 else
653 break;
654
655 if (p_rpt->index == BTA_HH_LE_RPT_MAX - 1)
656 break;
657
658 p_rpt ++;
659 }
660
661
662 /* if no report reference descriptor */
663 if (!started)
664 {
665 /* explore next char */
666 bta_hh_le_search_hid_chars(p_dev_cb);
667 }
668}
669/*******************************************************************************
670**
671** Function bta_hh_le_save_rpt_ref
672**
673** Description save report reference information and move to next one.
674**
675** Parameters:
676**
677*******************************************************************************/
678void bta_hh_le_save_rpt_ref(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_LE_RPT *p_rpt,
679 tBTA_GATTC_READ *p_data)
680{
681 UINT8 *pp;
682
683 /* if the length of the descriptor value is right, parse it */
684 if (p_data->status == BTA_GATT_OK &&
685 p_data->p_value && p_data->p_value->unformat.len == 2)
686 {
687 pp = p_data->p_value->unformat.p_value;
688
689 STREAM_TO_UINT8(p_rpt->rpt_id, pp);
690 STREAM_TO_UINT8(p_rpt->rpt_type, pp);
691
692 if (p_rpt->rpt_type > BTA_HH_RPTT_FEATURE) /* invalid report type */
693 p_rpt->rpt_type = BTA_HH_RPTT_RESRV;
694
695#if BTA_HH_DEBUG == TRUE
696 APPL_TRACE_DEBUG1("report ID: %d", p_rpt->rpt_id);
697#endif
698 }
699
700 if (p_rpt->index < BTA_HH_LE_RPT_MAX)
701 p_rpt ++;
702
703 /* read next report reference descriptor */
704 bta_hh_le_read_rpt_ref_descr(p_dev_cb, p_rpt);
705
706}
707/*******************************************************************************
708**
709** Function bta_hh_le_save_rpt_ref
710**
711** Description save report reference information and move to next one.
712**
713** Parameters:
714**
715*******************************************************************************/
716void bta_hh_le_save_ext_rpt_ref(tBTA_HH_DEV_CB *p_dev_cb,
717 tBTA_GATTC_READ *p_data)
718{
719 UINT8 *pp;
720
721 /* if the length of the descriptor value is right, parse it
722 assume it's a 16 bits UUID */
723 if (p_data->status == BTA_GATT_OK &&
724 p_data->p_value && p_data->p_value->unformat.len == 2)
725 {
726 pp = p_data->p_value->unformat.p_value;
727 STREAM_TO_UINT16(p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].ext_rpt_ref, pp);
728
729#if BTA_HH_DEBUG == TRUE
730 APPL_TRACE_DEBUG1("External Report Reference UUID 0x%04x",
731 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].ext_rpt_ref);
732#endif
733 }
734 bta_hh_le_search_hid_chars(p_dev_cb);
735
736}
737/*******************************************************************************
738**
739** Function bta_hh_le_register_input_notif
740**
741** Description Register for all notifications for the report applicable
742** for the protocol mode.
743**
744** Parameters:
745**
746*******************************************************************************/
747void bta_hh_le_register_input_notif(tBTA_HH_DEV_CB *p_dev_cb, UINT8 srvc_inst,
748 UINT8 proto_mode, BOOLEAN register_ba)
749{
750 tBTA_HH_LE_RPT *p_rpt = &p_dev_cb->hid_srvc[srvc_inst].report[0];
751 tBTA_GATTC_CHAR_ID char_id;
752 UINT8 i;
753 UINT16 srvc_uuid;
754
755#if BTA_HH_DEBUG == TRUE
756 APPL_TRACE_DEBUG1("bta_hh_le_register_input_notif mode: %d", proto_mode);
757#endif
758
759 for (i = 0; i < BTA_HH_LE_RPT_MAX; i ++, p_rpt ++)
760 {
761 if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
762 {
763 if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
764 srvc_uuid = UUID_SERVCLASS_BATTERY;
765 else
766 srvc_uuid = UUID_SERVCLASS_LE_HID;
767
768 bta_hh_le_fill_16bits_srvc_id(TRUE, BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt->inst_id), srvc_uuid, &char_id.srvc_id);
769 bta_hh_le_fill_16bits_char_id(BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt->inst_id), p_rpt->uuid, &char_id.char_id);
770
771 if (register_ba && p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
772 {
773 BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if,
774 p_dev_cb->addr,
775 &char_id);
776 }
777 /* boot mode, deregister report input notification */
778 else if (proto_mode == BTA_HH_PROTO_BOOT_MODE)
779 {
780 if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
781 p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
782 {
783 APPL_TRACE_DEBUG1("---> Deregister Report ID: %d", p_rpt->rpt_id);
784 BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if,
785 p_dev_cb->addr,
786 &char_id);
787 }
788 /* register boot reports notification */
789 else if (p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
790 p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT)
791 {
792 APPL_TRACE_DEBUG1("<--- Register Boot Report ID: %d", p_rpt->rpt_id);
793 BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if,
794 p_dev_cb->addr,
795 &char_id);
796 }
797 }
798 else if (proto_mode == BTA_HH_PROTO_RPT_MODE)
799 {
800 if ((p_rpt->uuid == GATT_UUID_HID_BT_KB_INPUT ||
801 p_rpt->uuid == GATT_UUID_HID_BT_MOUSE_INPUT) &&
802 p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
803 {
804
805 APPL_TRACE_DEBUG1("---> Deregister Boot Report ID: %d", p_rpt->rpt_id);
806 BTA_GATTC_DeregisterForNotifications(bta_hh_cb.gatt_if,
807 p_dev_cb->addr,
808 &char_id);
809 }
810 else if (p_rpt->uuid == GATT_UUID_HID_REPORT &&
811 p_rpt->client_cfg_value == BTA_GATT_CLT_CONFIG_NOTIFICATION)
812 {
813 APPL_TRACE_DEBUG1("<--- Register Report ID: %d", p_rpt->rpt_id);
814 BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if,
815 p_dev_cb->addr,
816 &char_id);
817 }
818 }
819 /*
820 else unknow protocol mode */
821 }
822 }
823}
824
825/*******************************************************************************
826**
827** Function bta_hh_le_open_cmpl
828**
829** Description HID over GATT connection sucessfully opened
830**
831*******************************************************************************/
832void bta_hh_le_open_cmpl(tBTA_HH_DEV_CB *p_cb)
833{
834 if ( p_cb->disc_active == BTA_HH_LE_DISC_NONE)
835 {
836#if BTA_HH_DEBUG
837 bta_hh_le_hid_report_dbg(p_cb);
838#endif
839 bta_hh_le_register_input_notif(p_cb, 0, p_cb->mode, TRUE);
840 bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
841#if (BTA_HH_LE_RECONN == TRUE)
842 if (p_cb->status == BTA_HH_OK)
843 {
844 bta_hh_le_add_dev_bg_conn(p_cb, TRUE);
845 }
846#endif
847 }
848}
849/*******************************************************************************
850**
851** Function bta_hh_le_write_char_clt_cfg
852**
853** Description Utility function to find and write client configuration of
854** a characteristic
855**
856*******************************************************************************/
857BOOLEAN bta_hh_le_write_char_clt_cfg(tBTA_HH_DEV_CB *p_cb,
858 UINT8 srvc_inst_id, UINT16 srvc_uuid16,
859 UINT8 char_inst_id, UINT16 char_uuid16,
860 UINT16 clt_cfg_value)
861{
862 tBTA_GATTC_CHAR_ID char_id;
863 tBT_UUID descr_cond;
864 tBTA_GATTC_CHAR_DESCR_ID descr_id;
865 tBTA_GATT_UNFMT value;
866 UINT8 buf[2], *pp = buf;
867
868 bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst_id, srvc_uuid16, &char_id.srvc_id);
869 bta_hh_le_fill_16bits_char_id(char_inst_id, char_uuid16, &char_id.char_id);
870
871 descr_cond.len = LEN_UUID_16;
872 descr_cond.uu.uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG;
873
874 value.len = 2;
875 value.p_value = buf;
876
877 UINT16_TO_STREAM(pp, clt_cfg_value);
878
879 if (BTA_GATTC_GetFirstCharDescr(p_cb->conn_id,
880 &char_id,
881 &descr_cond,
882 &descr_id) == BTA_GATT_OK)
883 {
884 BTA_GATTC_WriteCharDescr(p_cb->conn_id,
885 &descr_id,
886 BTA_GATTC_TYPE_WRITE_NO_RSP,
887 &value,
888 BTA_GATT_AUTH_REQ_NONE);
889
890 return TRUE;
891 }
892 return FALSE;
893}
894/*******************************************************************************
895**
896** Function bta_hh_le_write_rpt_clt_cfg
897**
898** Description write client configuration. This is only for input report
899** enable all input notification upon connection open.
900**
901*******************************************************************************/
902BOOLEAN bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst_id)
903{
904 UINT8 i;
905 tBTA_HH_LE_RPT *p_rpt = &p_cb->hid_srvc[srvc_inst_id].report[p_cb->clt_cfg_idx];
906 UINT16 srvc_uuid;
907
908 for (i = p_cb->clt_cfg_idx; i < BTA_HH_LE_RPT_MAX && p_rpt->in_use; i ++, p_rpt ++)
909 {
910 /* enable notification for all input report, regardless mode */
911 if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT)
912
913 {
914 if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
915 srvc_uuid = UUID_SERVCLASS_BATTERY;
916 else
917 srvc_uuid = UUID_SERVCLASS_LE_HID;
918
919 if (bta_hh_le_write_char_clt_cfg(p_cb,
920 BTA_HH_LE_RPT_GET_SRVC_INST_ID(p_rpt->inst_id),
921 srvc_uuid,
922 BTA_HH_LE_RPT_GET_RPT_INST_ID(p_rpt->inst_id),
923 p_rpt->uuid,
924 BTA_GATT_CLT_CONFIG_NOTIFICATION))
925 {
926 p_cb->clt_cfg_idx = i;
927 return TRUE;
928 }
929 }
930
931 }
932 p_cb->clt_cfg_idx = 0;
933
934 /* client configuration is completed, send open callback */
935 if (p_cb->state == BTA_HH_W4_CONN_ST)
936 {
937 p_cb->disc_active &= ~BTA_HH_LE_DISC_HIDS;
938
939 /* discover scan parameter profile is act as report host */
940 bta_hh_le_search_scps(p_cb);
941 }
942 return FALSE;
943}
944
945/*******************************************************************************
946**
947** Function bta_hh_le_set_protocol_mode
948**
949** Description Set remote device protocol mode.
950**
951*******************************************************************************/
952BOOLEAN bta_hh_le_set_protocol_mode(tBTA_HH_DEV_CB *p_cb, tBTA_HH_PROTO_MODE mode)
953{
954 tBTA_GATTC_CHAR_ID char_id;
955 tBTA_HH_CBDATA cback_data ;
956 BOOLEAN exec = TRUE;
957
958 APPL_TRACE_DEBUG1("bta_hh_le_set_protocol_mode attempt mode: %s",
959 (mode == BTA_HH_PROTO_RPT_MODE)? "Report": "Boot");
960
961 cback_data.handle = p_cb->hid_handle;
962 /* boot mode is not supported in the remote device */
963 if ((p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].option_char & BTA_HH_LE_PROTO_MODE_BIT) == 0)
964 {
965 exec = FALSE;
966 p_cb->mode = BTA_HH_PROTO_RPT_MODE;
967
968 if (mode == BTA_HH_PROTO_BOOT_MODE)
969 {
970 APPL_TRACE_ERROR0("Set Boot Mode failed!! No PROTO_MODE Char!");
971 cback_data.status = BTA_HH_ERR;
972 }
973 else
974 {
975 /* if set to report mode, need to de-register all input report notification */
976 bta_hh_le_register_input_notif(p_cb, 0, p_cb->mode, FALSE);
977 cback_data.status = BTA_HH_OK;
978 }
979 if (p_cb->state == BTA_HH_W4_CONN_ST)
980 {
981 p_cb->status = (cback_data.status == BTA_HH_OK)? BTA_HH_OK: BTA_HH_ERR_PROTO;
982 }
983 else
984 (* bta_hh_cb.p_cback)(BTA_HH_SET_PROTO_EVT, (tBTA_HH *)&cback_data);
985 }
986 else
987 {
988 bta_hh_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
989 bta_hh_le_fill_16bits_char_id(0, GATT_UUID_HID_PROTO_MODE, &char_id.char_id);
990
991 p_cb->mode = mode;
992 mode = (mode == BTA_HH_PROTO_BOOT_MODE)? BTA_HH_LE_PROTO_BOOT_MODE : BTA_HH_LE_PROTO_REPORT_MODE;
993
994 BTA_GATTC_WriteCharValue(p_cb->conn_id,
995 &char_id,
996 BTA_GATTC_TYPE_WRITE_NO_RSP,
997 1,
998 &mode,
999 BTA_GATT_AUTH_REQ_NONE);
1000 }
1001 return exec;
1002}
1003
1004/*******************************************************************************
1005**
1006** Function bta_hh_le_get_protocol_mode
1007**
1008** Description Get remote device protocol mode.
1009**
1010*******************************************************************************/
1011void bta_hh_le_get_protocol_mode(tBTA_HH_DEV_CB *p_cb)
1012{
1013 tBTA_GATTC_CHAR_ID char_id;
1014 tBTA_HH_HSDATA hs_data;
1015 UINT8 i;
1016
1017 p_cb->w4_evt = BTA_HH_GET_PROTO_EVT;
1018
1019 for (i = 0; i< BTA_HH_LE_HID_SRVC_MAX; i ++)
1020 {
1021 if (p_cb->hid_srvc[i].in_use &&
1022 p_cb->hid_srvc[i].option_char & BTA_HH_LE_PROTO_MODE_BIT)
1023 {
1024 bta_hh_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
1025 bta_hh_le_fill_16bits_char_id(0, GATT_UUID_HID_PROTO_MODE, &char_id.char_id);
1026
1027 BTA_GATTC_ReadCharacteristic(p_cb->conn_id,
1028 &char_id,
1029 BTA_GATT_AUTH_REQ_NONE);
1030 break;
1031 }
1032 }
1033 /* no service support protocol_mode, by default report mode */
1034 if (i == BTA_HH_LE_HID_SRVC_MAX)
1035 {
1036 hs_data.status = BTA_HH_OK;
1037 hs_data.handle = p_cb->hid_handle;
1038 hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
1039 p_cb->w4_evt = 0;
1040 (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
1041 }
1042
1043}
1044/*******************************************************************************
1045**
1046** Function bta_hh_le_expl_rpt
1047**
1048** Description explore all report characteristic
1049**
1050*******************************************************************************/
1051void bta_hh_le_expl_rpt(tBTA_HH_DEV_CB *p_dev_cb,
1052 tBTA_GATTC_CHAR_ID *p_char_id,
1053 tBT_UUID *p_char_cond,
1054 tBTA_GATT_CHAR_PROP prop)
1055{
1056 tBTA_GATTC_CHAR_ID char_result;
1057
1058 do
1059 {
1060 if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
1061 p_dev_cb->cur_srvc_index,
1062 GATT_UUID_HID_REPORT,
1063 p_char_id->char_id.inst_id,
1064 prop) == NULL)
1065 {
1066 APPL_TRACE_ERROR0("Add report entry failed !!!")
1067 break;
1068 }
1069
1070 APPL_TRACE_DEBUG0("Find more REPORT");
1071
1072 if (BTA_GATTC_GetNextChar(p_dev_cb->conn_id,
1073 p_char_id,
1074 p_char_cond,
1075 &char_result,
1076 &prop) != BTA_GATT_OK)
1077 break;
1078
1079 p_char_id = &char_result;
1080 }
1081 while (1);
1082
1083 APPL_TRACE_ERROR0("all report searched");
1084 bta_hh_le_read_rpt_ref_descr(p_dev_cb,
1085 &p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].report[0]);
1086
1087
1088 return ;
1089}
1090/*******************************************************************************
1091**
1092** Function bta_hh_le_expl_boot_rpt
1093**
1094** Description explore boot report
1095**
1096*******************************************************************************/
1097void bta_hh_le_expl_boot_rpt(tBTA_HH_DEV_CB *p_dev_cb, UINT16 char_uuid,
1098 tBTA_GATT_CHAR_PROP prop)
1099{
1100 if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
1101 p_dev_cb->cur_srvc_index,
1102 char_uuid,
1103 0,
1104 prop) == NULL)
1105
1106 {
1107 APPL_TRACE_ERROR0("Add report entry failed !!!")
1108 }
1109
1110 return;
1111}
1112/*******************************************************************************
1113**
1114** Function bta_hh_le_dis_cback
1115**
1116** Description DIS read complete callback
1117**
1118** Parameters:
1119**
1120*******************************************************************************/
1121void bta_hh_le_dis_cback(BD_ADDR addr, tDIS_VALUE *p_dis_value)
1122{
1123 tBTA_HH_DEV_CB *p_cb = bta_hh_le_find_dev_cb_by_bda(addr);
1124
1125
1126 if (p_cb == NULL || p_dis_value == NULL)
1127 {
1128 APPL_TRACE_ERROR0("received unexpected/error DIS callback");
1129 return;
1130 }
1131
1132 p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
1133 /* plug in the PnP info for this device */
1134 if (p_dis_value->attr_mask & DIS_ATTR_PNP_ID_BIT)
1135 {
1136#if BTA_HH_DEBUG == TRUE
1137 APPL_TRACE_DEBUG3("Plug in PnP info: product_id = %02x, vendor_id = %04x, version = %04x",
1138 p_dis_value->pnp_id.product_id,
1139 p_dis_value->pnp_id.vendor_id,
1140 p_dis_value->pnp_id.product_version);
1141#endif
1142 p_cb->dscp_info.product_id = p_dis_value->pnp_id.product_id;
1143 p_cb->dscp_info.vendor_id = p_dis_value->pnp_id.vendor_id;
1144 p_cb->dscp_info.version = p_dis_value->pnp_id.product_version;
1145 }
1146 bta_hh_le_open_cmpl(p_cb);
1147}
1148/*******************************************************************************
1149**
1150** Function bta_hh_le_pri_service_discovery
1151**
1152** Description Initialize GATT discovery on the remote LE HID device by opening
1153** a GATT connection first.
1154**
1155** Parameters:
1156**
1157*******************************************************************************/
1158void bta_hh_le_pri_service_discovery(tBTA_HH_DEV_CB *p_cb)
1159{
1160 tBT_UUID pri_srvc;
1161
1162 p_cb->disc_active |= (BTA_HH_LE_DISC_HIDS|BTA_HH_LE_DISC_DIS);
1163
1164 /* read DIS info */
1165 if (!DIS_ReadDISInfo(p_cb->addr, bta_hh_le_dis_cback))
1166 {
1167 APPL_TRACE_ERROR0("read DIS failed");
1168 p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
1169 }
1170
1171 /* in parallel */
1172 /* start primary service discovery for HID service */
1173 pri_srvc.len = LEN_UUID_16;
1174 pri_srvc.uu.uuid16 = UUID_SERVCLASS_LE_HID;
1175 BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc);
1176 return;
1177}
1178/*******************************************************************************
1179**
1180** Function bta_hh_le_encrypt_cback
1181**
1182** Description link encryption complete callback for bond verification.
1183**
1184** Returns None
1185**
1186*******************************************************************************/
1187void bta_hh_le_encrypt_cback(BD_ADDR bd_addr, void *p_ref_data, tBTM_STATUS result)
1188{
1189 UINT8 idx = bta_hh_find_cb(bd_addr);
1190 tBTA_HH_DEV_CB *p_dev_cb;
1191
1192 APPL_TRACE_ERROR0("bta_hh_le_encrypt_cback");
1193
1194 if (idx != BTA_HH_IDX_INVALID)
1195 p_dev_cb = &bta_hh_cb.kdev[idx];
1196 else
1197 {
1198 APPL_TRACE_ERROR0("unexpected encryption callback, ignore");
1199 return;
1200 }
1201 p_dev_cb->status = (result == BTM_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR_SEC;
1202
1203 bta_hh_sm_execute(p_dev_cb, BTA_HH_ENC_CMPL_EVT, NULL);
1204}
1205/*******************************************************************************
1206**
1207** Function bta_hh_security_cmpl
1208**
1209** Description Security check completed, start the service discovery
1210** if no cache available, otherwise report connection open completed
1211**
1212** Parameters:
1213**
1214*******************************************************************************/
1215void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1216{
1217 if (p_cb->status == BTA_HH_OK)
1218 {
1219 /* discovery has been done for HID service */
1220 if (p_cb->app_id != 0 && bta_hh_le_hid_srvc_cached(p_cb))
1221 {
1222 /* configure protocol mode */
1223 if (bta_hh_le_set_protocol_mode(p_cb, p_cb->mode) == FALSE)
1224 {
1225 APPL_TRACE_ERROR0("bta_hh_security_cmpl");
1226 bta_hh_le_open_cmpl(p_cb);
1227 }
1228 }
1229 /* start primary service discovery for HID service */
1230 else
1231 {
1232 bta_hh_le_pri_service_discovery(p_cb);
1233 }
1234 }
1235 else
1236 bta_hh_le_api_disc_act(p_cb);
1237
1238}
1239/*******************************************************************************
1240**
1241** Function bta_hh_start_security
1242**
1243** Description start the security check of the established connection
1244**
1245** Parameters:
1246**
1247*******************************************************************************/
1248void bta_hh_start_security(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1249{
1250 UINT8 sec_flag=0;
1251
1252 /* verify bond */
1253 BTM_GetSecurityFlags(p_cb->addr, &sec_flag);
1254
1255 /* if link has been encrypted */
1256 if (sec_flag & BTM_SEC_FLAG_ENCRYPTED)
1257 {
1258 bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
1259 }
1260 /* if bonded and link not encrypted */
1261 else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)
1262 {
1263 sec_flag = BTM_BLE_SEC_ENCRYPT;
1264 p_cb->status = BTA_HH_ERR_AUTH_FAILED;
1265 BTM_SetEncryption(p_cb->addr, bta_hh_le_encrypt_cback, &sec_flag);
1266 }
1267 /* unbonded device, report security error here */
1268 else if (p_cb->sec_mask != BTA_SEC_NONE)
1269 {
1270 sec_flag = BTM_BLE_SEC_ENCRYPT_NO_MITM;
1271 p_cb->status = BTA_HH_ERR_AUTH_FAILED;
1272 BTM_SetEncryption(p_cb->addr, bta_hh_le_encrypt_cback, &sec_flag);
1273 }
1274 /* otherwise let it go through */
1275 else
1276 {
1277 bta_hh_sm_execute(p_cb, BTA_HH_ENC_CMPL_EVT, NULL);
1278 }
1279
1280
1281}
1282/*******************************************************************************
1283**
1284** Function bta_hh_gatt_open
1285**
1286** Description process GATT open event.
1287**
1288** Parameters:
1289**
1290*******************************************************************************/
1291void bta_hh_gatt_open(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf)
1292{
1293 tBTA_GATTC_OPEN *p_data = &p_buf->le_open;
1294 UINT8 *p2;
1295 tHID_STATUS status = BTA_HH_ERR;
1296
1297 /* if received invalid callback data , ignore it */
1298 if (p_cb == NULL || p_data == NULL)
1299 return;
1300
1301 p2 = p_data->remote_bda;
1302
1303 APPL_TRACE_DEBUG3("bta_hh_gatt_open BTA_GATTC_OPEN_EVT bda= [%08x%04x] status =%d",
1304 ((p2[0])<<24)+((p2[1])<<16)+((p2[2])<<8)+(p2[3]),
1305 ((p2[4])<<8)+ p2[5],p_data->status);
1306
1307 if (p_data->status == BTA_GATT_OK)
1308 {
1309
1310 p_cb->in_use = TRUE;
1311 p_cb->conn_id = p_data->conn_id;
1312 p_cb->hid_handle = BTA_HH_GET_LE_DEV_HDL(p_cb->index);
1313
1314 bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index;
1315
1316#if BTA_HH_DEBUG == TRUE
1317 APPL_TRACE_DEBUG3("hid_handle = %2x conn_id = %04x cb_index = %d", p_cb->hid_handle, p_cb->conn_id, p_cb->index);
1318#endif
1319
1320 bta_hh_sm_execute(p_cb, BTA_HH_START_ENC_EVT, NULL);
1321
1322 }
1323 else /* open failure */
1324 {
1325 bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
1326 }
1327
1328}
1329/*******************************************************************************
1330**
1331** Function bta_hh_le_close
1332**
1333** Description This function process the GATT close event and post it as a
1334** BTA HH internal event
1335**
1336** Parameters:
1337**
1338*******************************************************************************/
1339void bta_hh_le_close(tBTA_GATTC_CLOSE * p_data)
1340{
1341 tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->remote_bda);
1342 tBTA_HH_LE_CLOSE *p_buf = NULL;
1343 UINT16 sm_event = BTA_HH_GATT_CLOSE_EVT;
1344
1345 if (p_dev_cb != NULL &&
1346 (p_buf = (tBTA_HH_LE_CLOSE *)GKI_getbuf(sizeof(tBTA_HH_LE_CLOSE))) != NULL)
1347 {
1348 p_buf->hdr.event = sm_event;
1349 p_buf->hdr.layer_specific = (UINT16)p_dev_cb->hid_handle;
1350 p_buf->conn_id = p_data->conn_id;
1351 p_buf->reason = p_data->reason;
1352
1353 p_dev_cb->conn_id = BTA_GATT_INVALID_CONN_ID;
1354
1355 bta_sys_sendmsg(p_buf);
1356 }
1357}
1358
1359/*******************************************************************************
1360**
1361** Function bta_hh_le_search_result
1362**
1363** Description This function process the GATT service search result.
1364**
1365** Parameters:
1366**
1367*******************************************************************************/
1368void bta_hh_le_search_result(tBTA_GATTC_SRVC_RES *p_srvc_result)
1369{
1370 tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_srvc_result->conn_id);
1371
1372 if (p_dev_cb != NULL)
1373 {
1374 switch (p_srvc_result->service_uuid.id.uuid.uu.uuid16)
1375 {
1376 case UUID_SERVCLASS_LE_HID:
1377 if (p_srvc_result->service_uuid.is_primary)
1378 {
1379 /* found HID primamry service */
1380 /* TODO: proceed to find battery and device info */
1381 if (bta_hh_le_add_hid_srvc_entry(p_dev_cb, p_dev_cb->total_srvc))
1382 p_dev_cb->total_srvc ++;
1383 APPL_TRACE_DEBUG1("num of hid service: %d", p_dev_cb->total_srvc);
1384 }
1385 break;
1386
1387 case UUID_SERVCLASS_SCAN_PARAM : /* scan parameter service */
1388 bta_hh_le_search_scps_chars(p_dev_cb);
1389 break;
1390 }
1391
1392 }
1393
1394}
1395
1396
1397/*******************************************************************************
1398**
1399** Function bta_hh_le_gatt_disc_cmpl
1400**
1401** Description Check to see if the remote device is a LE only device
1402**
1403** Parameters:
1404**
1405*******************************************************************************/
1406void bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_STATUS status)
1407{
1408 APPL_TRACE_DEBUG0("bta_hh_le_gatt_disc_cmpl ");
1409
1410 /* if open sucessful or protocol mode not desired, keep the connection open but inform app */
1411 if (status == BTA_HH_OK || status == BTA_HH_ERR_PROTO)
1412 {
1413 /* assign a special APP ID temp, since device type unknown */
1414 p_cb->app_id = BTA_HH_APP_ID_LE;
1415
1416 /* set report notification configuration */
1417 p_cb->clt_cfg_idx = 0;
1418 bta_hh_le_write_rpt_clt_cfg(p_cb, BTA_HH_LE_SRVC_DEF);
1419 }
1420 else /* error, close the GATT connection */
1421 {
1422 /* close GATT connection if it's on */
1423 bta_hh_le_api_disc_act(p_cb);
1424 }
1425}
1426
1427/*******************************************************************************
1428**
1429** Function bta_hh_le_srvc_expl_srvc
1430**
1431** Description This function discover the next avaible HID service.
1432**
1433** Parameters:
1434**
1435*******************************************************************************/
1436void bta_hh_le_srvc_expl_srvc(tBTA_HH_DEV_CB *p_dev_cb)
1437{
1438#if BTA_HH_DEBUG == TRUE
1439 APPL_TRACE_DEBUG2("bta_hh_le_srvc_expl_srvc cur_srvc_index = %d in_use = %d",
1440 p_dev_cb->cur_srvc_index,
1441 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].in_use);
1442#endif
1443
1444 if (p_dev_cb->cur_srvc_index < BTA_HH_LE_HID_SRVC_MAX &&
1445 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].in_use)
1446 {
1447 if (!p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc)
1448 /* explore included service first */
1449 {
1450 bta_hh_le_search_hid_included(p_dev_cb);
1451 }
1452 else
1453 {
1454 /* explore characterisc */
1455 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx = 0;
1456 bta_hh_le_search_hid_chars(p_dev_cb);
1457 }
1458 }
1459 else /* all service discvery finished */
1460 {
1461 bta_hh_le_gatt_disc_cmpl(p_dev_cb, p_dev_cb->status);
1462 }
1463}
1464/*******************************************************************************
1465**
1466** Function bta_hh_le_srvc_search_cmpl
1467**
1468** Description This function process the GATT service search complete.
1469**
1470** Parameters:
1471**
1472*******************************************************************************/
1473void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL *p_data)
1474{
1475 tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
1476
1477 /* service search exception or no HID service is supported on remote */
1478 if (p_dev_cb == NULL)
1479 return;
1480
1481 if(p_data->status != BTA_GATT_OK || p_dev_cb->total_srvc == 0)
1482 {
1483 p_dev_cb->status = BTA_HH_ERR_SDP;
1484 /* close the connection and report service discovery complete with error */
1485 bta_hh_le_api_disc_act(p_dev_cb);
1486 }
1487 /* GATT service discovery sucessfully finished */
1488 else
1489 {
1490 if (p_dev_cb->disc_active & BTA_HH_LE_DISC_SCPS)
1491 {
1492 p_dev_cb->disc_active &= ~BTA_HH_LE_DISC_SCPS;
1493 bta_hh_le_open_cmpl(p_dev_cb);
1494 }
1495 else /* discover HID service */
1496 {
1497 p_dev_cb->cur_srvc_index = 0;
1498 bta_hh_le_srvc_expl_srvc(p_dev_cb);
1499 }
1500}
1501}
1502
1503/*******************************************************************************
1504**
1505** Function bta_hh_le_search_hid_included
1506**
1507** Description This function search the included service within the HID service.
1508**
1509** Parameters:
1510**
1511*******************************************************************************/
1512static void bta_hh_le_search_hid_included(tBTA_HH_DEV_CB *p_dev_cb)
1513{
1514 tBT_UUID srvc_cond, char_cond;
1515 tBTA_GATTC_INCL_SVC_ID inc_srvc_result;
1516 tBTA_GATT_SRVC_ID srvc_id;
1517 tBTA_GATTC_CHAR_ID char_result;
1518 tBTA_GATT_CHAR_PROP prop = 0;
1519
1520 bta_hh_le_fill_16bits_srvc_id(TRUE, p_dev_cb->cur_srvc_index, UUID_SERVCLASS_LE_HID, &srvc_id);
1521
1522 srvc_cond.len = LEN_UUID_16;
1523 srvc_cond.uu.uuid16 = UUID_SERVCLASS_BATTERY;
1524
1525 if (BTA_GATTC_GetFirstIncludedService(p_dev_cb->conn_id,
1526 &srvc_id,
1527 &srvc_cond,
1528 &inc_srvc_result) == BTA_GATT_OK)
1529 {
1530 /* read include service UUID */
1531
1532 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].incl_srvc_inst = inc_srvc_result.incl_svc_id.id.inst_id;
1533
1534 char_cond.len = LEN_UUID_16;
1535 char_cond.uu.uuid16 = GATT_UUID_BATTERY_LEVEL;
1536
1537 /* find the battery characteristic */
1538 if (BTA_GATTC_GetFirstChar( p_dev_cb->conn_id,
1539 &inc_srvc_result.incl_svc_id,
1540 &char_cond,
1541 &char_result,
1542 &prop) == BTA_GATT_OK)
1543 {
1544 if (bta_hh_le_find_alloc_report_entry(p_dev_cb,
1545 char_result.srvc_id.id.inst_id,
1546 GATT_UUID_BATTERY_LEVEL,
1547 char_result.char_id.inst_id,
1548 prop) == NULL)
1549 {
1550 APPL_TRACE_ERROR0("Add battery report entry failed !!!")
1551 }
1552
1553 /* read the battery characteristic */
1554 BTA_GATTC_ReadCharacteristic(p_dev_cb->conn_id,
1555 &char_result,
1556 BTA_GATT_AUTH_REQ_NONE);
1557
1558 return;
1559
1560 }
1561 else
1562 {
1563 APPL_TRACE_ERROR0("Remote device does not have battery level");
1564 }
1565 }
1566
1567 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc = TRUE;
1568
1569 bta_hh_le_srvc_expl_srvc(p_dev_cb);
1570
1571}
1572/*******************************************************************************
1573**
1574** Function bta_hh_read_battery_level_cmpl
1575**
1576** Description This function process the battery level read
1577**
1578** Parameters:
1579**
1580*******************************************************************************/
1581void bta_hh_read_battery_level_cmpl(UINT8 status, tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
1582{
1583 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].expl_incl_srvc = TRUE;
1584 bta_hh_le_srvc_expl_srvc(p_dev_cb);
1585}
1586/*******************************************************************************
1587**
1588** Function bta_hh_le_search_hid_chars
1589**
1590** Description This function discover all characteristics a service and
1591** all descriptors available.
1592**
1593** Parameters:
1594**
1595*******************************************************************************/
1596static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB *p_dev_cb)
1597{
1598 tBT_UUID char_cond;
1599 tBTA_GATTC_CHAR_ID char_result;
1600 tBTA_GATT_CHAR_PROP prop;
1601 BOOLEAN next = TRUE;
1602 UINT16 char_uuid = 0;
1603 tBTA_GATT_SRVC_ID srvc_id;
1604
1605 if (p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx == BTA_HH_LE_DISC_CHAR_NUM ||
1606 (p_dev_cb->status != BTA_HH_OK && p_dev_cb->status != BTA_HH_ERR_PROTO))
1607 {
1608 p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx = 0;
1609 /* explore next service */
1610 p_dev_cb->cur_srvc_index ++;
1611 bta_hh_le_srvc_expl_srvc(p_dev_cb);
1612 return;
1613 }
1614
1615 p_dev_cb->hid_srvc[ p_dev_cb->cur_srvc_index].cur_expl_char_idx ++;
1616 char_uuid = bta_hh_le_disc_char_uuid[p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].cur_expl_char_idx - 1];
1617
1618 char_cond.len = LEN_UUID_16;
1619 char_cond.uu.uuid16 = char_uuid;
1620
1621 bta_hh_le_fill_16bits_srvc_id(TRUE, p_dev_cb->cur_srvc_index, UUID_SERVCLASS_LE_HID, &srvc_id);
1622
1623#if BTA_HH_DEBUG == TRUE
1624 APPL_TRACE_DEBUG2("bta_hh_le_search_hid_chars: looking for %s(0x%04x)",
1625 bta_hh_uuid_to_str(char_uuid), char_uuid);
1626#endif
1627
1628 if (BTA_GATTC_GetFirstChar( p_dev_cb->conn_id,
1629 &srvc_id,
1630 &char_cond,
1631 &char_result,
1632 &prop) == BTA_GATT_OK)
1633 {
1634 switch (char_uuid)
1635 {
1636 case GATT_UUID_HID_CONTROL_POINT:
1637 p_dev_cb->hid_srvc[char_result.srvc_id.id.inst_id].option_char |= BTA_HH_LE_CP_BIT;
1638 next = TRUE;
1639 break;
1640 case GATT_UUID_HID_INFORMATION:
1641 case GATT_UUID_HID_REPORT_MAP:
1642 /* read the char value */
1643 BTA_GATTC_ReadCharacteristic(p_dev_cb->conn_id,
1644 &char_result,
1645 BTA_GATT_AUTH_REQ_NONE);
1646 next = FALSE;
1647 break;
1648
1649 case GATT_UUID_HID_PROTO_MODE:
1650 p_dev_cb->hid_srvc[char_result.srvc_id.id.inst_id].option_char |= BTA_HH_LE_PROTO_MODE_BIT;
1651 next = !bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
1652 break;
1653
1654 case GATT_UUID_HID_REPORT:
1655 bta_hh_le_expl_rpt(p_dev_cb, &char_result, &char_cond, prop);
1656 next = FALSE;
1657 break;
1658
1659 /* found boot mode report types */
1660 case GATT_UUID_HID_BT_KB_OUTPUT:
1661 case GATT_UUID_HID_BT_MOUSE_INPUT:
1662 case GATT_UUID_HID_BT_KB_INPUT:
1663 bta_hh_le_expl_boot_rpt(p_dev_cb, char_uuid, prop);
1664 break;
1665 }
1666 }
1667 else
1668 {
1669 if (char_uuid == GATT_UUID_HID_PROTO_MODE)
1670 next = !bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
1671
1672 }
1673
1674 if (next == TRUE)
1675 {
1676 bta_hh_le_search_hid_chars(p_dev_cb);
1677 }
1678}
1679/*******************************************************************************
1680**
1681** Function bta_hh_le_save_rpt_map
1682**
1683** Description save the report map into the control block.
1684**
1685** Parameters:
1686**
1687*******************************************************************************/
1688void bta_hh_le_save_rpt_map(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
1689{
1690 UINT8 *pp ;
1691 tBTA_HH_LE_HID_SRVC *p_srvc = &p_dev_cb->hid_srvc[p_data->srvc_id.id.inst_id];
1692
1693 pp = p_data->p_value->unformat.p_value;
1694
1695 /* save report descriptor */
1696 if (p_srvc->rpt_map != NULL)
1697 GKI_freebuf((void*)p_srvc->rpt_map);
1698
1699 if (p_data->p_value->unformat.len > 0)
1700 p_srvc->rpt_map = (UINT8 *)GKI_getbuf(p_data->p_value->unformat.len);
1701
1702 if (p_srvc->rpt_map != NULL)
1703 {
1704 STREAM_TO_ARRAY(p_srvc->rpt_map, pp, p_data->p_value->unformat.len);
1705 p_srvc->descriptor.dl_len = p_data->p_value->unformat.len;
1706 p_srvc->descriptor.dsc_list = p_dev_cb->hid_srvc[p_data->srvc_id.id.inst_id].rpt_map;
1707 }
1708
1709 if (bta_hh_le_read_char_dscrpt(p_dev_cb,
1710 UUID_SERVCLASS_LE_HID,
1711 p_data->srvc_id.id.inst_id,
1712 GATT_UUID_HID_REPORT_MAP,
1713 p_data->char_id.inst_id,
1714 GATT_UUID_EXT_RPT_REF_DESCR) != BTA_HH_OK)
1715 {
1716 bta_hh_le_search_hid_chars(p_dev_cb);
1717 }
1718
1719
1720}
1721/*******************************************************************************
1722**
1723** Function bta_hh_le_proc_get_rpt_cmpl
1724**
1725** Description Process the Read report complete, send GET_REPORT_EVT to application
1726** with the report data.
1727**
1728** Parameters:
1729**
1730*******************************************************************************/
1731void bta_hh_le_proc_get_rpt_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
1732{
1733 BT_HDR *p_buf = NULL;
1734 tBTA_HH_LE_RPT *p_rpt;
1735 tBTA_HH_HSDATA hs_data;
1736 UINT8 *pp ;
1737
1738 if (p_dev_cb->w4_evt != BTA_HH_GET_RPT_EVT)
1739 {
1740 APPL_TRACE_ERROR1("Unexpected READ cmpl, w4_evt = %d", p_dev_cb->w4_evt);
1741 return;
1742 }
1743
1744 hs_data.status = BTA_HH_ERR;
1745 hs_data.handle = p_dev_cb->hid_handle;
1746
1747 if (p_data->status == BTA_GATT_OK)
1748 {
1749 p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
1750 p_data->srvc_id.id.inst_id,//BTA_HH_LE_SRVC_DEF,
1751 p_data->char_id.uuid.uu.uuid16,
1752 p_data->char_id.inst_id);
1753
1754 if (p_rpt != NULL &&
1755 p_data->p_value != NULL &&
1756 (p_buf = (BT_HDR *)GKI_getbuf((UINT16)(sizeof(BT_HDR) +p_data->p_value->unformat.len + 1))) != NULL)
1757 {
1758 /* pack data send to app */
1759 hs_data.status = BTA_HH_OK;
1760 p_buf->len = p_data->p_value->unformat.len + 1;
1761 p_buf->layer_specific = 0;
1762
1763 /* attach report ID as the first byte of the report before sending it to USB HID driver */
1764 pp = (UINT8*)(p_buf + 1);
1765 UINT8_TO_STREAM(pp, p_rpt->rpt_id);
1766 memcpy(pp, p_data->p_value->unformat.p_value, p_data->p_value->unformat.len);
1767
1768 hs_data.rsp_data.p_rpt_data =p_buf;
1769 }
1770 }
1771
1772 p_dev_cb->w4_evt = 0;
1773 (* bta_hh_cb.p_cback)(BTA_HH_GET_RPT_EVT, (tBTA_HH *)&hs_data);
1774
1775 utl_freebuf((void **)&p_buf);
1776
1777}
1778/*******************************************************************************
1779**
1780** Function bta_hh_le_proc_read_proto_mode
1781**
1782** Description Process the Read protocol mode, send GET_PROTO_EVT to application
1783** with the protocol mode.
1784**
1785*******************************************************************************/
1786void bta_hh_le_proc_read_proto_mode(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ *p_data)
1787{
1788 tBTA_HH_HSDATA hs_data;
1789
1790 hs_data.status = BTA_HH_ERR;
1791 hs_data.handle = p_dev_cb->hid_handle;
1792 hs_data.rsp_data.proto_mode = p_dev_cb->mode;
1793
1794 if (p_data->status == BTA_GATT_OK && p_data->p_value)
1795 {
1796 hs_data.status = BTA_HH_OK;
1797 /* match up BTE/BTA report/boot mode def*/
1798 hs_data.rsp_data.proto_mode = *(p_data->p_value->unformat.p_value);
1799 /* LE repot mode is the opposite value of BR/EDR report mode, flip it here */
1800 if (hs_data.rsp_data.proto_mode == 0)
1801 hs_data.rsp_data.proto_mode = BTA_HH_PROTO_BOOT_MODE;
1802 else
1803 hs_data.rsp_data.proto_mode = BTA_HH_PROTO_RPT_MODE;
1804
1805 p_dev_cb->mode = hs_data.rsp_data.proto_mode;
1806 }
1807#if BTA_HH_DEBUG
1808 APPL_TRACE_DEBUG1("LE GET_PROTOCOL Mode = [%s]",
1809 (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)? "Report" : "Boot");
1810#endif
1811
1812 p_dev_cb->w4_evt = 0;
1813 (* bta_hh_cb.p_cback)(BTA_HH_GET_PROTO_EVT, (tBTA_HH *)&hs_data);
1814
1815}
1816/*******************************************************************************
1817**
1818** Function bta_hh_w4_le_read_char_cmpl
1819**
1820** Description process the GATT read complete in W4_CONN state.
1821**
1822** Parameters:
1823**
1824*******************************************************************************/
1825void bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
1826{
1827 tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
1828 UINT8 *pp ;
1829
1830 if (p_data->char_id.uuid.uu.uuid16 == GATT_UUID_BATTERY_LEVEL)
1831 {
1832 bta_hh_read_battery_level_cmpl(p_data->status, p_dev_cb, p_data);
1833 }
1834 else
1835 {
1836 if (p_data->status == BTA_GATT_OK && p_data->p_value)
1837 {
1838 pp = p_data->p_value->unformat.p_value;
1839
1840 switch (p_data->char_id.uuid.uu.uuid16)
1841 {
1842 /* save device information */
1843 case GATT_UUID_HID_INFORMATION:
1844 STREAM_TO_UINT16(p_dev_cb->dscp_info.version, pp);
1845 STREAM_TO_UINT8(p_dev_cb->dscp_info.ctry_code, pp);
1846 STREAM_TO_UINT8(p_dev_cb->dscp_info.flag, pp);
1847 break;
1848
1849 case GATT_UUID_HID_REPORT_MAP:
1850 bta_hh_le_save_rpt_map(p_dev_cb, p_data);
1851 return;
1852
1853 default:
1854#if BTA_HH_DEBUG == TRUE
1855 APPL_TRACE_ERROR2("Unexpected read %s(0x%04x)",
1856 bta_hh_uuid_to_str(p_data->char_id.uuid.uu.uuid16),
1857 p_data->char_id.uuid.uu.uuid16);
1858#endif
1859 break;
1860 }
1861 }
1862 else
1863 {
1864#if BTA_HH_DEBUG == TRUE
1865 APPL_TRACE_ERROR3("read uuid %s[0x%04x] error: %d",
1866 bta_hh_uuid_to_str(p_data->char_id.uuid.uu.uuid16),
1867 p_data->char_id.uuid.uu.uuid16,
1868 p_data->status);
1869#else
1870 APPL_TRACE_ERROR2("read uuid [0x%04x] error: %d", p_data->char_id.uuid.uu.uuid16, p_data->status);
1871#endif
1872 }
1873 bta_hh_le_search_hid_chars(p_dev_cb);
1874 }
1875
1876}
1877/*******************************************************************************
1878**
1879** Function bta_hh_le_read_char_cmpl
1880**
1881** Description a characteristic value is received.
1882**
1883** Parameters:
1884**
1885*******************************************************************************/
1886void bta_hh_le_read_char_cmpl (tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
1887{
1888 tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
1889
1890 switch (p_data->char_id.uuid.uu.uuid16)
1891 {
1892 /* GET_REPORT */
1893 case GATT_UUID_HID_REPORT:
1894 case GATT_UUID_HID_BT_KB_INPUT:
1895 case GATT_UUID_HID_BT_KB_OUTPUT:
1896 case GATT_UUID_HID_BT_MOUSE_INPUT:
1897 case GATT_UUID_BATTERY_LEVEL: /* read battery level */
1898 bta_hh_le_proc_get_rpt_cmpl(p_dev_cb, p_data);
1899 break;
1900
1901 case GATT_UUID_HID_PROTO_MODE:
1902 bta_hh_le_proc_read_proto_mode(p_dev_cb, p_data);
1903 break;
1904
1905 default:
1906 APPL_TRACE_ERROR1("Unexpected Read UUID: 0x%04x", p_data->char_id.uuid.uu.uuid16);
1907 break;
1908 }
1909
1910}
1911/*******************************************************************************
1912**
1913** Function bta_hh_le_read_descr_cmpl
1914**
1915** Description read characteristic descriptor is completed in CONN st.
1916**
1917** Parameters:
1918**
1919*******************************************************************************/
1920void bta_hh_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
1921{
1922 tBTA_HH_LE_RPT *p_rpt;
1923 tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
1924 UINT8 *pp;
1925
1926 /* if a report client configuration */
1927 if (p_data->descr_type.uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG)
1928 {
1929 if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
1930 BTA_HH_LE_SRVC_DEF,
1931 p_data->char_id.uuid.uu.uuid16,
1932 p_data->char_id.inst_id)) != NULL)
1933 {
1934 pp = p_data->p_value->unformat.p_value;
1935 STREAM_TO_UINT16(p_rpt->client_cfg_value, pp);
1936
1937 APPL_TRACE_DEBUG1("Read Client Configuration: 0x%04x", p_rpt->client_cfg_value);
1938 }
1939 }
1940}
1941
1942void bta_hh_le_read_battery_level_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATTC_READ * p_data)
1943{
1944 tBTA_HH_LE_RPT *p_rpt;
1945 UINT16 descr_uuid = p_data->descr_type.uuid.uu.uuid16;
1946
1947 /* read report reference descriptor for battery level is completed */
1948 if (descr_uuid == GATT_UUID_RPT_REF_DESCR)
1949 {
1950 if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
1951 p_data->srvc_id.id.inst_id,
1952 GATT_UUID_BATTERY_LEVEL,
1953 p_data->char_id.inst_id)) == NULL)
1954 {
1955 bta_hh_le_search_hid_chars(p_dev_cb);
1956 }
1957 else
1958 bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data);
1959
1960 }
1961}
1962/*******************************************************************************
1963**
1964** Function bta_hh_w4_le_read_descr_cmpl
1965**
1966** Description read characteristic descriptor is completed in W4_CONN st.
1967**
1968** Parameters:
1969**
1970*******************************************************************************/
1971void bta_hh_w4_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
1972{
1973 tBTA_HH_LE_RPT *p_rpt;
1974 tBTA_GATTC_READ * p_data = (tBTA_GATTC_READ *)p_buf;
1975 UINT16 char_uuid16;
1976
1977 if (p_data == NULL)
1978 return;
1979
1980 char_uuid16 = p_data->char_id.uuid.uu.uuid16;
1981
1982#if BTA_HH_DEBUG == TRUE
1983 APPL_TRACE_DEBUG2("bta_hh_w4_le_read_descr_cmpl uuid: %s(0x%04x)",
1984 bta_hh_uuid_to_str(p_data->descr_type.uuid.uu.uuid16),
1985 p_data->descr_type.uuid.uu.uuid16);
1986#endif
1987 switch (char_uuid16)
1988 {
1989 case GATT_UUID_HID_REPORT:
1990 if ((p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
1991 p_data->srvc_id.id.inst_id,
1992 GATT_UUID_HID_REPORT,
1993 p_data->char_id.inst_id)) == NULL)
1994 {
1995 bta_hh_le_search_hid_chars(p_dev_cb);
1996 }
1997 else
1998 bta_hh_le_save_rpt_ref(p_dev_cb, p_rpt, p_data);
1999 break;
2000
2001 case GATT_UUID_HID_REPORT_MAP:
2002 bta_hh_le_save_ext_rpt_ref(p_dev_cb, p_data);
2003 break;
2004
2005 case GATT_UUID_BATTERY_LEVEL:
2006 bta_hh_le_read_battery_level_descr_cmpl(p_dev_cb, p_data);
2007 break;
2008
2009 default:
2010 APPL_TRACE_ERROR1("unknown descriptor read complete for uuid: 0x%04x", char_uuid16);
2011 break;
2012 }
2013}
2014
2015/*******************************************************************************
2016**
2017** Function bta_hh_w4_le_write_cmpl
2018**
2019** Description Write charactersitic complete event at W4_CONN st.
2020**
2021** Parameters:
2022**
2023*******************************************************************************/
2024void bta_hh_w4_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
2025{
2026 tBTA_GATTC_WRITE *p_data = (tBTA_GATTC_WRITE *)p_buf;
2027
2028 if (p_data == NULL)
2029 return;
2030
2031 if (p_data->char_id.uuid.uu.uuid16 == GATT_UUID_HID_PROTO_MODE)
2032 {
2033 p_dev_cb->status = (p_data->status == BTA_GATT_OK) ? BTA_HH_OK : BTA_HH_ERR_PROTO;
2034
2035 if ((p_dev_cb->disc_active & BTA_HH_LE_DISC_HIDS) != 0)
2036 {
2037 bta_hh_le_search_hid_chars(p_dev_cb);
2038 }
2039 else
2040 {
2041 bta_hh_le_open_cmpl(p_dev_cb);
2042 }
2043 }
2044}
2045/*******************************************************************************
2046**
2047** Function bta_hh_le_write_cmpl
2048**
2049** Description Write charactersitic complete event at CONN st.
2050**
2051** Parameters:
2052**
2053*******************************************************************************/
2054void bta_hh_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
2055{
2056 tBTA_GATTC_WRITE *p_data = (tBTA_GATTC_WRITE *)p_buf;
2057 tBTA_HH_CBDATA cback_data ;
2058 UINT16 cb_evt = p_dev_cb->w4_evt;
2059
2060 if (p_data == NULL || cb_evt == 0)
2061 return;
2062
2063#if BTA_HH_DEBUG
2064 APPL_TRACE_DEBUG1("bta_hh_le_write_cmpl w4_evt: %d", p_dev_cb->w4_evt);
2065#endif
2066 switch (p_data->char_id.uuid.uu.uuid16)
2067 {
2068 /* Set protocol finished */
2069 case GATT_UUID_HID_PROTO_MODE:
2070 cback_data.handle = p_dev_cb->hid_handle;
2071 if (p_data->status == BTA_GATT_OK)
2072 {
2073 bta_hh_le_register_input_notif(p_dev_cb, p_data->srvc_id.id.inst_id, p_dev_cb->mode, FALSE);
2074 cback_data.status = BTA_HH_OK;
2075 }
2076 else
2077 cback_data.status = BTA_HH_ERR;
2078 p_dev_cb->w4_evt = 0;
2079 (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
2080 break;
2081
2082 /* Set Report finished */
2083 case GATT_UUID_HID_REPORT:
2084 case GATT_UUID_HID_BT_KB_INPUT:
2085 case GATT_UUID_HID_BT_MOUSE_INPUT:
2086 case GATT_UUID_HID_BT_KB_OUTPUT:
2087 cback_data.handle = p_dev_cb->hid_handle;
2088 cback_data.status = (p_data->status == BTA_GATT_OK)? BTA_HH_OK : BTA_HH_ERR;
2089 p_dev_cb->w4_evt = 0;
2090 (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
2091 break;
2092
2093 case GATT_UUID_SCAN_INT_WINDOW:
2094 bta_hh_le_register_scpp_notif(p_dev_cb, p_data->status);
2095 break;
2096
2097
2098 default:
2099 break;
2100 }
2101
2102}
2103/*******************************************************************************
2104**
2105** Function bta_hh_le_write_char_descr_cmpl
2106**
2107** Description Write charactersitic descriptor complete event
2108**
2109** Parameters:
2110**
2111*******************************************************************************/
2112void bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
2113{
2114 tBTA_GATTC_WRITE *p_data = (tBTA_GATTC_WRITE *)p_buf;
2115 UINT8 srvc_inst_id, hid_inst_id;
2116
2117 /* only write client configuration possible */
2118 if (p_data && p_data->descr_type.uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG)
2119 {
2120 srvc_inst_id = p_data->srvc_id.id.inst_id;
2121 hid_inst_id = srvc_inst_id;
2122 switch (p_data->char_id.uuid.uu.uuid16)
2123 {
2124 case GATT_UUID_BATTERY_LEVEL: /* battery level clt cfg registered */
2125 hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(p_dev_cb, srvc_inst_id);
2126 /* fall through */
2127 case GATT_UUID_HID_BT_KB_INPUT:
2128 case GATT_UUID_HID_BT_MOUSE_INPUT:
2129 case GATT_UUID_HID_REPORT:
2130 if (p_data->status == BTA_GATT_OK)
2131 p_dev_cb->hid_srvc[hid_inst_id].report[p_dev_cb->clt_cfg_idx ++].client_cfg_value =
2132 BTA_GATT_CLT_CONFIG_NOTIFICATION;
2133
2134 bta_hh_le_write_rpt_clt_cfg(p_dev_cb, hid_inst_id);
2135
2136 break;
2137
2138 case GATT_UUID_SCAN_REFRESH:
2139 bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, p_data->status);
2140 break;
2141 default:
2142 APPL_TRACE_ERROR1("Unknown char ID clt cfg: 0x%04x", p_data->char_id.uuid.uu.uuid16);
2143 }
2144 }
2145 else
2146 {
2147#if BTA_HH_DEBUG == TRUE
2148 APPL_TRACE_ERROR2("Unexpected write to %s(0x%04x)",
2149 bta_hh_uuid_to_str(p_data->descr_type.uuid.uu.uuid16),
2150 p_data->descr_type.uuid.uu.uuid16);
2151#else
2152 APPL_TRACE_ERROR1("Unexpected write to (0x%04x)", p_data->descr_type.uuid.uu.uuid16);
2153#endif
2154 }
2155
2156}
2157/*******************************************************************************
2158**
2159** Function bta_hh_le_input_rpt_notify
2160**
2161** Description process the notificaton event, most likely for input report.
2162**
2163** Parameters:
2164**
2165*******************************************************************************/
2166void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY *p_data)
2167{
2168 tBTA_HH_DEV_CB *p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->conn_id);
2169 UINT8 app_id;
2170 UINT8 *p_buf;
2171 tBTA_HH_LE_RPT *p_rpt;
2172
2173 if (p_dev_cb == NULL)
2174 {
2175 APPL_TRACE_ERROR0("notification received from Unknown device");
2176 return;
2177 }
2178
2179 app_id= p_dev_cb->app_id;
2180
2181 p_rpt = bta_hh_le_find_report_entry(p_dev_cb,
2182 BTA_HH_LE_SRVC_DEF,
2183 p_data->char_id.char_id.uuid.uu.uuid16,
2184 p_data->char_id.char_id.inst_id);
2185 if (p_rpt == NULL)
2186 {
2187 APPL_TRACE_ERROR0("notification received for Unknown Report");
2188 return;
2189 }
2190
2191 if (p_data->char_id.char_id.uuid.uu.uuid16 == GATT_UUID_HID_BT_MOUSE_INPUT)
2192 app_id = BTA_HH_APP_ID_MI;
2193 else if (p_data->char_id.char_id.uuid.uu.uuid16 == GATT_UUID_HID_BT_KB_INPUT)
2194 app_id = BTA_HH_APP_ID_KB;
2195
2196 /* need to append report ID to the head of data */
2197 if ((p_buf = (UINT8 *)GKI_getbuf((UINT16)(p_data->len + 1))) == NULL)
2198 {
2199 APPL_TRACE_ERROR0("No resources to send report data");
2200 return;
2201 }
2202
2203 APPL_TRACE_ERROR1("Notification received on report ID: %d", p_rpt->rpt_id);
2204
2205 p_buf[0] = p_rpt->rpt_id;
2206 memcpy(&p_buf[1], p_data->value, p_data->len);
2207 p_data->len ++;
2208
2209 bta_hh_co_data((UINT8)p_dev_cb->hid_handle,
2210 p_buf,
2211 p_data->len,
2212 p_dev_cb->mode,
2213 0 , /* no sub class*/
2214 p_dev_cb->dscp_info.ctry_code,
2215 p_dev_cb->addr,
2216 app_id);
2217
2218 GKI_freebuf(p_buf);
2219}
2220
2221
2222/*******************************************************************************
2223**
2224** Function bta_hh_gatt_open_fail
2225**
2226** Description action function to process the open fail
2227**
2228** Returns void
2229**
2230*******************************************************************************/
2231void bta_hh_le_open_fail(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
2232{
2233 tBTA_HH_CONN conn_dat ;
2234 tBTA_HH_LE_HID_SRVC *p_hid_srvc = &p_cb->hid_srvc[0];
2235 UINT8 i;
2236
2237 p_cb->disc_active = BTA_HH_LE_DISC_NONE;
2238 /* Failure in opening connection or GATT discovery failure */
2239 conn_dat.handle = p_cb->hid_handle;
2240 memcpy(conn_dat.bda, p_cb->addr, BD_ADDR_LEN);
2241 conn_dat.le_hid = TRUE;
2242 conn_dat.scps_supported = p_cb->scps_supported;
2243
2244 if (p_cb->status == BTA_HH_OK)
2245 conn_dat.status = (p_data->le_close.reason == BTA_GATT_CONN_UNKNOWN) ? p_cb->status : BTA_HH_ERR;
2246 else
2247 conn_dat.status = p_cb->status;
2248
2249 for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++, p_hid_srvc ++)
2250 {
2251 utl_freebuf((void **)&p_hid_srvc->rpt_map);
2252 memset(p_hid_srvc, 0, sizeof(tBTA_HH_LE_HID_SRVC));
2253 }
2254
2255 /* Report OPEN fail event */
2256 (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
2257
2258}
2259/*******************************************************************************
2260**
2261** Function bta_hh_gatt_close
2262**
2263** Description action function to process the GATT close int he state machine.
2264**
2265** Returns void
2266**
2267*******************************************************************************/
2268void bta_hh_gatt_close(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
2269{
2270 tBTA_HH_CBDATA disc_dat = {BTA_HH_OK, 0};
2271
2272 /* finaliza device driver */
2273 bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
2274 /* update total conn number */
2275 bta_hh_cb.cnt_num --;
2276
2277 disc_dat.handle = p_cb->hid_handle;
2278 disc_dat.status = p_cb->status;
2279
2280 (*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH *)&disc_dat);
2281
2282 /* if no connection is active and HH disable is signaled, disable service */
2283 if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable)
2284 {
2285 bta_hh_disc_cmpl();
2286 }
2287 else
2288 {
2289#if (BTA_HH_LE_RECONN == TRUE)
2290 if (p_data->le_close.reason == BTA_GATT_CONN_TIMEOUT)
2291 {
2292 bta_hh_le_add_dev_bg_conn(p_cb, FALSE);
2293 }
2294#endif
2295 }
2296
2297 return;
2298
2299}
2300/*******************************************************************************
2301**
2302** Function bta_hh_le_api_disc_act
2303**
2304** Description initaite a Close API to a remote HID device
2305**
2306** Returns void
2307**
2308*******************************************************************************/
2309void bta_hh_le_api_disc_act(tBTA_HH_DEV_CB *p_cb)
2310{
2311 if (p_cb->conn_id != BTA_GATT_INVALID_CONN_ID)
2312 BTA_GATTC_Close(p_cb->conn_id);
2313}
2314
2315/*******************************************************************************
2316**
2317** Function bta_hh_le_get_rpt
2318**
2319** Description GET_REPORT on a LE HID Report
2320**
2321** Returns void
2322**
2323*******************************************************************************/
2324void bta_hh_le_get_rpt(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id)
2325{
2326 tBTA_HH_LE_RPT *p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc[srvc_inst].report, p_cb->mode, r_type, rpt_id);
2327 tBTA_GATTC_CHAR_ID char_id;
2328 UINT16 srvc_uuid = UUID_SERVCLASS_LE_HID;
2329
2330 if (p_rpt == NULL)
2331 {
2332 APPL_TRACE_ERROR0("bta_hh_le_get_rpt: no matching report");
2333 return;
2334 }
2335 if (p_rpt->uuid == GATT_UUID_BATTERY_LEVEL)
2336 srvc_uuid = UUID_SERVCLASS_BATTERY;
2337
2338 p_cb->w4_evt = BTA_HH_GET_RPT_EVT;
2339
2340 bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst, srvc_uuid, &char_id.srvc_id);
2341 bta_hh_le_fill_16bits_char_id(p_rpt->inst_id, p_rpt->uuid, &char_id.char_id);
2342
2343 BTA_GATTC_ReadCharacteristic(p_cb->conn_id,
2344 &char_id,
2345 BTA_GATT_AUTH_REQ_NONE);
2346}
2347
2348/*******************************************************************************
2349**
2350** Function bta_hh_le_write_rpt
2351**
2352** Description SET_REPORT/or DATA output on a LE HID Report
2353**
2354** Returns void
2355**
2356*******************************************************************************/
2357void bta_hh_le_write_rpt(tBTA_HH_DEV_CB *p_cb, UINT8 srvc_inst,
2358 tBTA_GATTC_WRITE_TYPE write_type,
2359 tBTA_HH_RPT_TYPE r_type,
2360 BT_HDR *p_buf, UINT16 w4_evt )
2361{
2362 tBTA_HH_LE_RPT *p_rpt;
2363 tBTA_GATTC_CHAR_ID char_id;
2364 UINT8 *p_value, rpt_id;
2365
2366 if (p_buf == NULL || p_buf->len == 0)
2367 {
2368 APPL_TRACE_ERROR0("bta_hh_le_write_rpt: Illegal data");
2369 return;
2370 }
2371
2372 /* strip report ID from the data */
2373 p_value = (UINT8 *)(p_buf + 1) + p_buf->offset;
2374 STREAM_TO_UINT8(rpt_id, p_value);
2375 p_buf->len -= 1;
2376
2377 p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc[srvc_inst].report, p_cb->mode, r_type, rpt_id);
2378
2379 if (p_rpt == NULL)
2380 {
2381 APPL_TRACE_ERROR0("bta_hh_le_write_rpt: no matching report");
2382 return;
2383 }
2384
2385 APPL_TRACE_ERROR2("bta_hh_le_write_rpt: ReportID: 0x%02x Data Len: %d", rpt_id, p_buf->len);
2386
2387 p_cb->w4_evt = w4_evt;
2388
2389 bta_hh_le_fill_16bits_srvc_id(TRUE, srvc_inst, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
2390 bta_hh_le_fill_16bits_char_id(p_rpt->inst_id, p_rpt->uuid, &char_id.char_id);
2391
2392 BTA_GATTC_WriteCharValue(p_cb->conn_id,
2393 &char_id,
2394 write_type, /* default to use write request */
2395 p_buf->len,
2396 p_value,
2397 BTA_GATT_AUTH_REQ_NONE);
2398
2399}
2400/*******************************************************************************
2401**
2402** Function bta_hh_le_suspend
2403**
2404** Description send LE suspend or exit suspend mode to remote device.
2405**
2406** Returns void
2407**
2408*******************************************************************************/
2409void bta_hh_le_suspend(tBTA_HH_DEV_CB *p_cb, tBTA_HH_TRANS_CTRL_TYPE ctrl_type)
2410{
2411 UINT8 i;
2412 tBTA_GATTC_CHAR_ID char_id;
2413
2414 ctrl_type -= BTA_HH_CTRL_SUSPEND;
2415
2416 for (i = 0; i < BTA_HH_LE_HID_SRVC_MAX; i ++)
2417 {
2418 bta_hh_le_fill_16bits_srvc_id(TRUE, i, UUID_SERVCLASS_LE_HID, &char_id.srvc_id);
2419 bta_hh_le_fill_16bits_char_id(0, GATT_UUID_HID_CONTROL_POINT, &char_id.char_id);
2420
2421 BTA_GATTC_WriteCharValue(p_cb->conn_id,
2422 &char_id,
2423 BTA_GATTC_TYPE_WRITE_NO_RSP, /* default to use write request */
2424 1,
2425 &ctrl_type,
2426 BTA_GATT_AUTH_REQ_NONE);
2427 }
2428}
2429
2430/*******************************************************************************
2431**
2432** Function bta_hh_le_write_dev_act
2433**
2434** Description Write LE device action. can be SET/GET/DATA transaction.
2435**
2436** Returns void
2437**
2438*******************************************************************************/
2439void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
2440{
2441 switch(p_data->api_sndcmd.t_type)
2442 {
2443 case HID_TRANS_SET_PROTOCOL:
2444 p_cb->w4_evt = BTA_HH_SET_PROTO_EVT;
2445 bta_hh_le_set_protocol_mode(p_cb, p_data->api_sndcmd.param);
2446 break;
2447
2448 case HID_TRANS_GET_PROTOCOL:
2449 bta_hh_le_get_protocol_mode(p_cb);
2450 break;
2451
2452 case HID_TRANS_GET_REPORT:
2453 bta_hh_le_get_rpt(p_cb,
2454 BTA_HH_LE_SRVC_DEF,
2455 p_data->api_sndcmd.param,
2456 p_data->api_sndcmd.rpt_id);
2457 break;
2458
2459 case HID_TRANS_SET_REPORT:
2460 bta_hh_le_write_rpt(p_cb,
2461 BTA_HH_LE_SRVC_DEF,
2462 BTA_GATTC_TYPE_WRITE,
2463 p_data->api_sndcmd.param,
2464 p_data->api_sndcmd.p_data,
2465 BTA_HH_SET_RPT_EVT);
2466 break;
2467
2468 case HID_TRANS_DATA: /* output report */
2469
2470 bta_hh_le_write_rpt(p_cb,
2471 BTA_HH_LE_SRVC_DEF,
2472 BTA_GATTC_TYPE_WRITE_NO_RSP,
2473 p_data->api_sndcmd.param,
2474 p_data->api_sndcmd.p_data,
2475 BTA_HH_DATA_EVT);
2476 break;
2477
2478 case HID_TRANS_CONTROL:
2479 /* no handshake event will be generated */
2480 /* if VC_UNPLUG is issued, set flag */
2481 if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND ||
2482 p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND)
2483 {
2484 bta_hh_le_suspend(p_cb, p_data->api_sndcmd.param);
2485 }
2486 break;
2487
2488 default:
2489 APPL_TRACE_ERROR1("unsupported trsanction for LE HID device: %d", p_data->api_sndcmd.t_type);
2490 break;
2491 }
2492
2493}
2494/*******************************************************************************
2495**
2496** Function bta_hh_le_get_dscp_act
2497**
2498** Description Send ReportDescriptor to application for all HID services.
2499**
2500** Returns void
2501**
2502*******************************************************************************/
2503void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB *p_cb)
2504{
2505 UINT8 i;
2506
2507 for (i = 0 ;i < BTA_HH_LE_HID_SRVC_MAX; i ++)
2508 {
2509 if (p_cb->hid_srvc[i].in_use)
2510 {
2511 p_cb->dscp_info.descriptor.dl_len = p_cb->hid_srvc[i].descriptor.dl_len;
2512 p_cb->dscp_info.descriptor.dsc_list = p_cb->hid_srvc[i].descriptor.dsc_list;
2513
2514 (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH *)&p_cb->dscp_info);
2515 }
2516 else
2517 break;
2518 }
2519}
2520
2521/*******************************************************************************
2522**
2523** Function bta_hh_le_add_dev_bg_conn
2524**
2525** Description Remove a LE HID device from back ground connection procedure.
2526**
2527** Returns void
2528**
2529*******************************************************************************/
2530static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond)
2531{
2532 UINT8 sec_flag=0;
2533 BOOLEAN to_add = TRUE;
2534
2535 if (check_bond)
2536 {
2537 /* start reconnection if remote is a bonded device */
2538 /* verify bond */
2539 BTM_GetSecurityFlags(p_cb->addr, &sec_flag);
2540
2541 if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) == 0)
2542 to_add = FALSE;
2543 }
2544
2545 if (/*p_cb->dscp_info.flag & BTA_HH_LE_NORMAL_CONN &&*/
2546 !p_cb->in_bg_conn && to_add)
2547 {
2548 /* add device into BG connection to accept remote initiated connection */
2549 BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, FALSE);
2550 p_cb->in_bg_conn = TRUE;
2551
2552 BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL);
2553 }
2554 return;
2555}
2556
2557/*******************************************************************************
2558**
2559** Function bta_hh_le_add_device
2560**
2561** Description Add a LE HID device as a known device, and also add the address
2562** into back ground connection WL for incoming connection.
2563**
2564** Returns void
2565**
2566*******************************************************************************/
2567UINT8 bta_hh_le_add_device(tBTA_HH_DEV_CB *p_cb, tBTA_HH_MAINT_DEV *p_dev_info)
2568{
2569
2570 /* update DI information */
2571 bta_hh_update_di_info(p_cb,
2572 p_dev_info->dscp_info.vendor_id,
2573 p_dev_info->dscp_info.product_id,
2574 p_dev_info->dscp_info.version,
2575 p_dev_info->dscp_info.flag);
2576
2577 /* add to BTA device list */
2578 bta_hh_add_device_to_list(p_cb, p_cb->hid_handle,
2579 p_dev_info->attr_mask,
2580 &p_dev_info->dscp_info.descriptor,
2581 p_dev_info->sub_class,
2582 p_dev_info->dscp_info.ssr_max_latency,
2583 p_dev_info->dscp_info.ssr_min_tout,
2584 p_dev_info->app_id);
2585
2586 bta_hh_le_add_dev_bg_conn(p_cb, FALSE);
2587
2588 return p_cb->hid_handle;
2589}
2590
2591/*******************************************************************************
2592**
2593** Function bta_hh_le_remove_dev_bg_conn
2594**
2595** Description Remove a LE HID device from back ground connection procedure.
2596**
2597** Returns void
2598**
2599*******************************************************************************/
2600void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB *p_dev_cb)
2601{
2602 if (p_dev_cb->in_bg_conn)
2603 {
2604 p_dev_cb->in_bg_conn = FALSE;
2605
2606 BTA_GATTC_CancelOpen(bta_hh_cb.gatt_if, p_dev_cb->addr, FALSE);
2607 }
2608}
2609/*******************************************************************************
2610**
2611** Function bta_hh_le_update_scpp
2612**
2613** Description action function to update the scan parameters on remote HID
2614** device
2615**
2616** Parameters:
2617**
2618*******************************************************************************/
2619void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
2620{
2621 tBTA_GATTC_CHAR_ID char_id;
2622 UINT8 value[4], *p = value;
2623 tBTA_HH_CBDATA cback_data ;
2624
2625 if (!p_dev_cb->is_le_device ||
2626 p_dev_cb->mode != BTA_HH_PROTO_RPT_MODE ||
2627 p_dev_cb->scps_supported == FALSE)
2628 {
2629 APPL_TRACE_ERROR0("Can not set ScPP scan paramter as boot host, or remote does not support ScPP ");
2630
2631 cback_data.handle = p_dev_cb->hid_handle;
2632 cback_data.status = BTA_HH_ERR;
2633 (* bta_hh_cb.p_cback)(BTA_HH_UPDATE_SCPP_EVT, (tBTA_HH *)&cback_data);
2634
2635 return;
2636 }
2637
2638 p_dev_cb->w4_evt = BTA_HH_UPDATE_SCPP_EVT;
2639
2640 UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_int);
2641 UINT16_TO_STREAM(p, p_buf->le_scpp_update.scan_win);
2642
2643 bta_hh_le_fill_16bits_srvc_id(TRUE, BTA_HH_SCPP_INST_DEF, UUID_SERVCLASS_SCAN_PARAM, &char_id.srvc_id);
2644 bta_hh_le_fill_16bits_char_id(BTA_HH_SCPP_INST_DEF, GATT_UUID_SCAN_INT_WINDOW, &char_id.char_id);
2645
2646 BTA_GATTC_WriteCharValue(p_dev_cb->conn_id,
2647 &char_id,
2648 BTA_GATTC_TYPE_WRITE_NO_RSP,
2649 2,
2650 value,
2651 BTA_GATT_AUTH_REQ_NONE);
2652
2653}
2654/*******************************************************************************
2655**
2656** Function bta_hh_gattc_callback
2657**
2658** Description This is GATT client callback function used in BTA HH.
2659**
2660** Parameters:
2661**
2662*******************************************************************************/
2663static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
2664{
2665 tBTA_HH_DEV_CB *p_dev_cb;
2666 UINT16 evt;
2667#if BTA_HH_DEBUG
2668 APPL_TRACE_DEBUG1("bta_hh_gattc_callback event = %d", event);
2669#endif
2670 if (p_data == NULL)
2671 return;
2672
2673 switch (event)
2674 {
2675 case BTA_GATTC_REG_EVT: /* 0 */
2676 bta_hh_le_register_cmpl(&p_data->reg_oper);
2677 break;
2678
2679 case BTA_GATTC_DEREG_EVT: /* 1 */
2680 bta_hh_cleanup_disable(p_data->reg_oper.status);
2681 break;
2682
2683 case BTA_GATTC_OPEN_EVT: /* 2 */
2684 p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->open.remote_bda);
2685 bta_hh_sm_execute(p_dev_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA *)&p_data->open);
2686 break;
2687
2688 case BTA_GATTC_READ_CHAR_EVT: /* 3 */
2689 case BTA_GATTC_READ_DESCR_EVT: /* 8 */
2690 p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->read.conn_id);
2691 if (event == BTA_GATTC_READ_CHAR_EVT)
2692 evt = BTA_HH_GATT_READ_CHAR_CMPL_EVT;
2693 else
2694 evt = BTA_HH_GATT_READ_DESCR_CMPL_EVT;
2695
2696 bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->read);
2697 break;
2698
2699 case BTA_GATTC_WRITE_DESCR_EVT: /* 9 */
2700 case BTA_GATTC_WRITE_CHAR_EVT: /* 4 */
2701 p_dev_cb = bta_hh_le_find_dev_cb_by_conn_id(p_data->write.conn_id);
2702 if (event == BTA_GATTC_WRITE_CHAR_EVT)
2703 evt = BTA_HH_GATT_WRITE_CHAR_CMPL_EVT;
2704 else
2705 evt = BTA_HH_GATT_WRITE_DESCR_CMPL_EVT;
2706
2707 bta_hh_sm_execute(p_dev_cb, evt, (tBTA_HH_DATA *)&p_data->write);
2708 break;
2709
2710 case BTA_GATTC_CLOSE_EVT: /* 5 */
2711 bta_hh_le_close(&p_data->close);
2712 break;
2713
2714 case BTA_GATTC_SEARCH_CMPL_EVT: /* 6 */
2715 bta_hh_le_srvc_search_cmpl(&p_data->search_cmpl);
2716 break;
2717
2718 case BTA_GATTC_SEARCH_RES_EVT: /* 7 */
2719 bta_hh_le_search_result(&p_data->srvc_res);
2720 break;
2721
2722
2723
2724 case BTA_GATTC_NOTIF_EVT: /* 10 */
2725 bta_hh_le_input_rpt_notify(&p_data->notify);
2726 break;
2727 default:
2728 break;
2729 }
2730}
2731
2732/*******************************************************************************
2733**
2734** Function bta_hh_le_hid_read_rpt_clt_cfg
2735**
2736** Description a test command to read report descriptor client configuration
2737**
2738** Returns void
2739**
2740*******************************************************************************/
2741void bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr, UINT8 rpt_id)
2742{
2743 tBTA_HH_DEV_CB *p_cb = NULL;
2744 tBTA_HH_LE_RPT *p_rpt ;
2745 UINT8 index = BTA_HH_IDX_INVALID;
2746
2747 index = bta_hh_find_cb(bd_addr);
2748 if ((index = bta_hh_find_cb(bd_addr))== BTA_HH_IDX_INVALID)
2749 {
2750 APPL_TRACE_ERROR0("unknown device");
2751 return;
2752 }
2753
2754 p_cb = &bta_hh_cb.kdev[index];
2755
2756 p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc[BTA_HH_LE_SRVC_DEF].report, p_cb->mode, BTA_HH_RPTT_INPUT, rpt_id);
2757
2758 if (p_rpt == NULL)
2759 {
2760 APPL_TRACE_ERROR0("bta_hh_le_write_rpt: no matching report");
2761 return;
2762 }
2763
2764 bta_hh_le_read_char_dscrpt(p_cb,
2765 UUID_SERVCLASS_LE_HID,
2766 BTA_HH_LE_SRVC_DEF,
2767 p_rpt->uuid,
2768 p_rpt->inst_id,
2769 GATT_UUID_CHAR_CLIENT_CONFIG);
2770
2771
2772
2773 return;
2774}
2775/*******************************************************************************
2776**
2777** Function bta_hh_le_search_scps
2778**
2779** Description discovery scan parameter service if act as report host, otherwise
2780** finish LE connection.
2781**
2782** Parameters:
2783**
2784*******************************************************************************/
2785static void bta_hh_le_search_scps(tBTA_HH_DEV_CB *p_cb)
2786{
2787 tBT_UUID pri_srvc;
2788
2789 if ( p_cb->mode == BTA_HH_PROTO_RPT_MODE)
2790 {
2791 p_cb->disc_active |= BTA_HH_LE_DISC_SCPS;
2792 /* start service discovery for Scan Parameter service */
2793 pri_srvc.len = LEN_UUID_16;
2794 pri_srvc.uu.uuid16 = UUID_SERVCLASS_SCAN_PARAM;
2795
2796 BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc);
2797 }
2798 else
2799 bta_hh_le_open_cmpl(p_cb);
2800}
2801/*******************************************************************************
2802**
2803** Function bta_hh_le_search_scps_chars
2804**
2805** Description find ScPS optional characteristics scan refresh
2806**
2807** Parameters:
2808**
2809*******************************************************************************/
2810static void bta_hh_le_search_scps_chars(tBTA_HH_DEV_CB *p_cb)
2811{
2812 tBTA_GATT_SRVC_ID srvc_id;
2813 tBT_UUID char_cond;
2814 tBTA_GATTC_CHAR_ID char_result;
2815 tBTA_GATT_CHAR_PROP prop;
2816
2817 p_cb->scps_supported = TRUE;
2818 bta_hh_le_fill_16bits_srvc_id(TRUE, 0, UUID_SERVCLASS_SCAN_PARAM, &srvc_id);
2819
2820 char_cond.len = LEN_UUID_16;
2821 char_cond.uu.uuid16 = GATT_UUID_SCAN_REFRESH;
2822
2823 /* look for scan refresh */
2824 if (BTA_GATTC_GetFirstChar( p_cb->conn_id,
2825 &srvc_id,
2826 &char_cond,
2827 &char_result,
2828 &prop) == BTA_GATT_OK)
2829 {
2830 if (prop & BTA_GATT_CHAR_PROP_BIT_NOTIFY)
2831 p_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT;
2832 else
2833 p_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE;
2834
2835 }
2836}
2837
2838/*******************************************************************************
2839**
2840** Function bta_hh_le_register_scpp_notif
2841**
2842** Description register scan parameter refresh notitication complete
2843**
2844**
2845** Parameters:
2846**
2847*******************************************************************************/
2848static void bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status)
2849{
2850 UINT8 sec_flag=0;
2851 tBTA_GATTC_CHAR_ID char_id;
2852
2853 /* if write scan parameter sucessful */
2854 /* if bonded and notification is not enabled, configure the client configuration */
2855 if (status == BTA_GATT_OK &&
2856 (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_SPT) != 0 &&
2857 (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_ENB) == 0)
2858 {
2859 BTM_GetSecurityFlags(p_dev_cb->addr, &sec_flag);
2860 if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN))
2861 {
2862 if (bta_hh_le_write_char_clt_cfg (p_dev_cb,
2863 BTA_HH_SCPP_INST_DEF,
2864 UUID_SERVCLASS_SCAN_PARAM,
2865 BTA_HH_SCPP_INST_DEF,
2866 GATT_UUID_SCAN_REFRESH,
2867 BTA_GATT_CLT_CONFIG_NOTIFICATION))
2868 {
2869 bta_hh_le_fill_16bits_srvc_id(TRUE, BTA_HH_SCPP_INST_DEF, UUID_SERVCLASS_SCAN_PARAM, &char_id.srvc_id);
2870 bta_hh_le_fill_16bits_char_id(BTA_HH_SCPP_INST_DEF, GATT_UUID_SCAN_REFRESH, &char_id.char_id);
2871
2872 BTA_GATTC_RegisterForNotifications(bta_hh_cb.gatt_if,
2873 p_dev_cb->addr,
2874 &char_id);
2875 return;
2876 }
2877 }
2878 }
2879 bta_hh_le_register_scpp_notif_cmpl(p_dev_cb, status);
2880}
2881/*******************************************************************************
2882**
2883** Function bta_hh_le_register_scpp_notif_cmpl
2884**
2885** Description action function to register scan parameter refresh notitication
2886**
2887** Parameters:
2888**
2889*******************************************************************************/
2890static void bta_hh_le_register_scpp_notif_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_STATUS status)
2891{
2892 tBTA_HH_CBDATA cback_data ;
2893 UINT16 cb_evt = p_dev_cb->w4_evt;
2894
2895 if (status == BTA_GATT_OK)
2896 p_dev_cb->scps_notify = (BTA_HH_LE_SCPS_NOTIFY_ENB | BTA_HH_LE_SCPS_NOTIFY_SPT);
2897
2898 cback_data.handle = p_dev_cb->hid_handle;
2899 cback_data.status = (status == BTA_GATT_OK)? BTA_HH_OK : BTA_HH_ERR;
2900 p_dev_cb->w4_evt = 0;
2901 (* bta_hh_cb.p_cback)(cb_evt, (tBTA_HH *)&cback_data);
2902
2903
2904}
2905#endif
2906
2907
2908
2909