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