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