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