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