blob: 503f095c725d23797891c77f765476cc84a290ae [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 2005-2012 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/******************************************************************************
20 *
21 * This file contains the HID host action functions.
22 *
23 ******************************************************************************/
24
25#include "bt_target.h"
26
Marie Janssene9e58ce2016-06-17 14:12:17 -070027#if (BTA_HH_INCLUDED == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -080028
29#include <string.h>
30
31#include "bta_sys.h"
32#include "btm_api.h"
33#include "l2c_api.h"
34#include "bta_hh_int.h"
35#include "bta_hh_co.h"
Myles Watsond7ffd642016-10-27 10:27:36 -070036#include "osi/include/osi.h"
Mike J. Chen5cd8bff2014-01-31 18:16:59 -080037#include "utl.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080038
39/*****************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -080040 * Constants
41 ****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -080042
43
44/*****************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -080045 * Local Function prototypes
46 ****************************************************************************/
Marie Janssene9e58ce2016-06-17 14:12:17 -070047static void bta_hh_cback (uint8_t dev_handle, BD_ADDR addr, uint8_t event,
48 uint32_t data, BT_HDR *pdata);
49static tBTA_HH_STATUS bta_hh_get_trans_status(uint32_t result);
The Android Open Source Project5738f832012-12-12 16:00:35 -080050
Marie Janssene9e58ce2016-06-17 14:12:17 -070051#if (BTA_HH_DEBUG == TRUE)
52static const char* bta_hh_get_w4_event(uint16_t event);
53static const char * bta_hh_hid_event_name(uint16_t event);
The Android Open Source Project5738f832012-12-12 16:00:35 -080054#endif
55
56/*****************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -080057 * Action Functions
58 ****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -080059/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -080060 *
61 * Function bta_hh_api_enable
62 *
63 * Description Perform necessary operations to enable HID host.
64 *
65 *
66 * Returns void
67 *
68 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -080069void bta_hh_api_enable(tBTA_HH_DATA *p_data)
70{
71 tBTA_HH_STATUS status = BTA_HH_ERR;
Marie Janssene9e58ce2016-06-17 14:12:17 -070072 uint8_t xx;
The Android Open Source Project5738f832012-12-12 16:00:35 -080073
74 /* initialize BTE HID */
75 HID_HostInit();
76
77 memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
78
79 HID_HostSetSecurityLevel("", p_data->api_enable.sec_mask);
80
81 /* Register with L2CAP */
82 if ( HID_HostRegister (bta_hh_cback) == HID_SUCCESS)
83 {
84 /* store parameters */
85 bta_hh_cb.p_cback = p_data->api_enable.p_cback;
86
87 status = BTA_HH_OK;
88 /* initialize device CB */
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -080089 for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
The Android Open Source Project5738f832012-12-12 16:00:35 -080090 {
91 bta_hh_cb.kdev[xx].state = BTA_HH_IDLE_ST;
92 bta_hh_cb.kdev[xx].hid_handle = BTA_HH_INVALID_HANDLE;
93 bta_hh_cb.kdev[xx].index = xx;
The Android Open Source Project5738f832012-12-12 16:00:35 -080094 }
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -080095
96 /* initialize control block map */
97 for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
98 bta_hh_cb.cb_index[xx] = BTA_HH_IDX_INVALID;
The Android Open Source Project5738f832012-12-12 16:00:35 -080099 }
100
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700101#if (BTA_HH_LE_INCLUDED == TRUE)
102 if (status == BTA_HH_OK)
103 {
104 bta_hh_le_enable();
105 }
106 else
107#endif
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800108 /* signal BTA call back event */
109 (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800110}
111/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800112 *
113 * Function bta_hh_api_disable
114 *
115 * Description Perform necessary operations to disable HID host.
116 *
117 *
118 * Returns void
119 *
120 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800121void bta_hh_api_disable(void)
122{
Marie Janssene9e58ce2016-06-17 14:12:17 -0700123 uint8_t xx;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800124
125 /* service is not enabled */
126 if (bta_hh_cb.p_cback == NULL)
127 return;
128
129 /* no live connection, signal DISC_CMPL_EVT directly */
130 if (!bta_hh_cb.cnt_num)
131 {
132 bta_hh_disc_cmpl();
133 }
134 else /* otherwise, disconnect all live connections */
135 {
Marie Janssene9e58ce2016-06-17 14:12:17 -0700136 bta_hh_cb.w4_disable = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800137
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800138 for(xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800139 {
140 /* send API_CLOSE event to every connected device */
141 if ( bta_hh_cb.kdev[xx].state == BTA_HH_CONN_ST )
142 {
143 /* disconnect all connected devices */
144 bta_hh_sm_execute(&bta_hh_cb.kdev[xx],
145 BTA_HH_API_CLOSE_EVT,
146 NULL);
147 }
148 }
149 }
150
151 return;
152}
153
154/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800155 *
156 * Function bta_hh_disc_cmpl
157 *
158 * Description All connections have been closed, disable service.
159 *
160 *
161 * Returns void
162 *
163 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800164void bta_hh_disc_cmpl(void)
165{
Myles Watsond628a062016-10-27 10:02:37 -0700166#if (BTA_HH_LE_INCLUDED == TRUE)
167 HID_HostDeregister();
168 bta_hh_le_deregister();
169#else
The Android Open Source Project5738f832012-12-12 16:00:35 -0800170 tBTA_HH_STATUS status = BTA_HH_OK;
171
172 /* Deregister with lower layer */
VenkatRaghavan VijayaRaghavan4540f592015-02-05 04:40:47 -0800173 if (HID_HostDeregister() != HID_SUCCESS)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800174 status = BTA_HH_ERR;
175
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800176 bta_hh_cleanup_disable(status);
VenkatRaghavan VijayaRaghavan4540f592015-02-05 04:40:47 -0800177#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -0800178}
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800179
The Android Open Source Project5738f832012-12-12 16:00:35 -0800180/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800181 *
182 * Function bta_hh_sdp_cback
183 *
184 * Description SDP callback function.
185 *
186 * Returns void
187 *
188 ******************************************************************************/
Marie Janssene9e58ce2016-06-17 14:12:17 -0700189static void bta_hh_sdp_cback(uint16_t result, uint16_t attr_mask,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800190 tHID_DEV_SDP_INFO *sdp_rec )
191{
192 tBTA_HH_DEV_CB *p_cb = bta_hh_cb.p_cur;
Marie Janssene9e58ce2016-06-17 14:12:17 -0700193 uint8_t hdl = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800194 tBTA_HH_STATUS status = BTA_HH_ERR_SDP;
195
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800196 /* make sure sdp succeeded and hh has not been disabled */
197 if ((result == SDP_SUCCESS) && (p_cb != NULL))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800198 {
199 /* security is required for the connection, add attr_mask bit*/
200 if (p_cb->sec_mask)
201 attr_mask |= HID_SEC_REQUIRED;
202
Marie Janssene9e58ce2016-06-17 14:12:17 -0700203#if (BTA_HH_DEBUG == TRUE)
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700204 APPL_TRACE_EVENT("bta_hh_sdp_cback: p_cb: %d result 0x%02x, \
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700205 attr_mask 0x%02x, handle %x", \
206 p_cb, result, attr_mask,p_cb->hid_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800207#endif
208
209 /* check to see type of device is supported , and should not been added before */
210 if (bta_hh_tod_spt(p_cb, sdp_rec->sub_class))
211 {
212 /* if not added before */
213 if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
214 {
215 /* add device/update attr_mask information */
216 if(HID_HostAddDev (p_cb->addr, attr_mask, &hdl) == HID_SUCCESS)
217 {
218 status = BTA_HH_OK;
219 /* update cb_index[] map */
220 bta_hh_cb.cb_index[hdl] = p_cb->index;
221 }
222 else
223 {
224 p_cb->app_id = 0;
225 }
Zhihai Xu9628abf2013-12-16 14:22:36 -0800226 }
Kim Schulz2a2701c2013-09-16 15:59:33 +0200227 else
228 {
229 hdl = p_cb->hid_handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800230 }
231 /* else : incoming connection after SDP should update the SDP information as well */
232
233 if (p_cb->app_id != 0)
234 {
235 /* update cb information with attr_mask, dscp_info etc. */
236 bta_hh_add_device_to_list(p_cb, hdl, attr_mask,
237 &sdp_rec->dscp_info,
238 sdp_rec->sub_class,
239 sdp_rec->ssr_max_latency,
240 sdp_rec->ssr_min_tout,
241 p_cb->app_id);
242
243 p_cb->dscp_info.ctry_code = sdp_rec->ctry_code;
244
245 status = BTA_HH_OK;
246 }
247
248 }
249 else /* type of device is not supported */
250 status = BTA_HH_ERR_TOD_UNSPT;
251 }
252
253 /* free disc_db when SDP is completed */
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800254 osi_free_and_reset((void **)&bta_hh_cb.p_disc_db);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800255
The Android Open Source Project5738f832012-12-12 16:00:35 -0800256 /* send SDP_CMPL_EVT into state machine */
257 bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
258
259 return;
260}
261/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800262 *
263 * Function bta_hh_di_sdp_cback
264 *
265 * Description SDP DI callback function.
266 *
267 * Returns void
268 *
269 ******************************************************************************/
Marie Janssene9e58ce2016-06-17 14:12:17 -0700270static void bta_hh_di_sdp_cback(uint16_t result)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800271{
272 tBTA_HH_DEV_CB *p_cb = bta_hh_cb.p_cur;
273 tBTA_HH_STATUS status = BTA_HH_ERR_SDP;
274 tSDP_DI_GET_RECORD di_rec;
275 tHID_STATUS ret;
Marie Janssene9e58ce2016-06-17 14:12:17 -0700276#if (BTA_HH_DEBUG == TRUE)
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700277 APPL_TRACE_EVENT("bta_hh_di_sdp_cback: p_cb: %d result 0x%02x", p_cb, result);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800278#endif
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700279
The Android Open Source Project5738f832012-12-12 16:00:35 -0800280 /* if DI record does not exist on remote device, vendor_id in tBTA_HH_DEV_DSCP_INFO will be
281 * set to 0xffff and we will allow the connection to go through. Spec mandates that DI
282 * record be set, but many HID devices do not set this. So for IOP purposes, we allow the
283 * connection to go through and update the DI record to invalid DI entry.*/
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800284 if (((result == SDP_SUCCESS) || (result == SDP_NO_RECS_MATCH)) && (p_cb != NULL))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800285 {
286 if(result == SDP_SUCCESS && SDP_GetNumDiRecords(bta_hh_cb.p_disc_db) != 0)
287 {
288 /* always update information with primary DI record */
289 if (SDP_GetDiRecord(1, &di_rec, bta_hh_cb.p_disc_db) == SDP_SUCCESS)
290 {
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800291 bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product, di_rec.rec.version, 0);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800292 }
293
294 }
295 else /* no DI recrod available */
296 {
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800297 bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0, 0);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800298 }
299
300 if ((ret = HID_HostGetSDPRecord(p_cb->addr,
301 bta_hh_cb.p_disc_db,
302 p_bta_hh_cfg->sdp_db_size,
303 bta_hh_sdp_cback)) == HID_SUCCESS)
304 {
305 status = BTA_HH_OK;
306 }
307 else
308 {
Marie Janssene9e58ce2016-06-17 14:12:17 -0700309#if (BTA_HH_DEBUG == TRUE)
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700310 APPL_TRACE_DEBUG ("bta_hh_di_sdp_cback: HID_HostGetSDPRecord failed: Status 0x%2x",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800311 ret);
312#endif
313 }
314 }
315
316
Pavlin Radoslavov20524d32016-02-02 18:12:08 -0800317 if (status != BTA_HH_OK) {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800318 osi_free_and_reset((void **)&bta_hh_cb.p_disc_db);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800319 /* send SDP_CMPL_EVT into state machine */
320 bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
321 }
322 return;
323
324}
325
326
327/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800328 *
329 * Function bta_hh_start_sdp
330 *
331 * Description Start SDP service search, and obtain necessary SDP records.
332 * Only one SDP service search request is allowed at the same
333 * time. For every BTA_HhOpen API call, do SDP first unless SDP
334 * has been done previously.
335 *
336 * Returns void
337 *
338 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800339void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
340{
341 tBTA_HH_STATUS status = BTA_HH_ERR_SDP;
Marie Janssene9e58ce2016-06-17 14:12:17 -0700342 uint8_t hdl;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800343
344 p_cb->sec_mask = p_data->api_conn.sec_mask;
345 p_cb->mode = p_data->api_conn.mode;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800346 bta_hh_cb.p_cur = p_cb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800347
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700348#if (BTA_HH_LE_INCLUDED == TRUE)
349 if (bta_hh_is_le_device(p_cb, p_data->api_conn.bd_addr))
350 {
351 bta_hh_le_open_conn(p_cb, p_data->api_conn.bd_addr);
352 return;
353 }
354#endif
355
The Android Open Source Project5738f832012-12-12 16:00:35 -0800356 /* if previously virtually cabled device, skip SDP */
357 if (p_cb->app_id)
358 {
359 status = BTA_HH_OK;
Marie Janssene9e58ce2016-06-17 14:12:17 -0700360#if (BTA_HH_DEBUG == TRUE)
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700361 APPL_TRACE_DEBUG("bta_hh_start_sdp:: skip SDP for known devices");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800362#endif
363 if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
364 {
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700365 if (HID_HostAddDev (p_cb->addr, p_cb->attr_mask, &hdl) \
The Android Open Source Project5738f832012-12-12 16:00:35 -0800366 == HID_SUCCESS)
367 {
368 /* update device CB with newly register device handle */
369 bta_hh_add_device_to_list(p_cb, hdl, p_cb->attr_mask, NULL,
370 p_cb->sub_class,
371 p_cb->dscp_info.ssr_max_latency,
372 p_cb->dscp_info.ssr_min_tout,
373 p_cb->app_id);
374 /* update cb_index[] map */
375 bta_hh_cb.cb_index[hdl] = p_cb->index;
376 }
377 else
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800378 status = BTA_HH_ERR_NO_RES;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800379 }
380 bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
381
382 return;
383 }
384 /* GetSDPRecord. at one time only one SDP precedure can be active */
385 else if (!bta_hh_cb.p_disc_db)
386 {
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800387 bta_hh_cb.p_disc_db = (tSDP_DISCOVERY_DB *)osi_malloc(p_bta_hh_cfg->sdp_db_size);
388 bta_hh_cb.p_cur = p_cb;
389 /* do DI discovery first */
390 if (SDP_DiDiscover(p_data->api_conn.bd_addr,
391 bta_hh_cb.p_disc_db,
392 p_bta_hh_cfg->sdp_db_size,
393 bta_hh_di_sdp_cback) != SDP_SUCCESS) {
Marie Janssene9e58ce2016-06-17 14:12:17 -0700394#if (BTA_HH_DEBUG == TRUE)
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800395 APPL_TRACE_DEBUG("bta_hh_start_sdp: SDP_DiDiscover failed: \
The Android Open Source Project5738f832012-12-12 16:00:35 -0800396 Status 0x%2X",status);
397#endif
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800398 status = BTA_HH_ERR_SDP;
399 osi_free_and_reset((void **)&bta_hh_cb.p_disc_db);
400 } else {
401 status = BTA_HH_OK;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800402 }
Hemant Gupta556b78b2015-10-07 12:08:10 +0530403 } else if (bta_hh_cb.p_disc_db) {
404 /* It is possible that there is incoming/outgoing collision case. DUT initiated
405 * HID connection at same time remote has connected L2CAP for HID control,
406 * so SDP would be in progress, when this flow reaches here. Just do nothing
407 * when the code reaches here, and ongoing SDP completion or failure will handle this case.
408 */
409 APPL_TRACE_DEBUG("%s: ignoring as SDP already in progress", __func__);
410 return;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800411 }
412
413 if (status != BTA_HH_OK)
414 bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
415
416 return;
417
418}
419/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800420 *
421 * Function bta_hh_sdp_cmpl
422 *
423 * Description When SDP completed, initiate a connection or report error depend
424 * on SDP result.
425 *
426 *
427 * Returns void
428 *
429 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800430void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
431{
432 tBTA_HH_CONN conn_dat;
433 tBTA_HH_STATUS status = p_data->status;
434
Marie Janssene9e58ce2016-06-17 14:12:17 -0700435#if (BTA_HH_DEBUG == TRUE)
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700436 APPL_TRACE_DEBUG ("bta_hh_sdp_cmpl: status 0x%2X",p_data->status);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800437#endif
438
439 /* initialize call back data */
440 memset((void *)&conn_dat, 0, sizeof(tBTA_HH_CONN));
441 conn_dat.handle = p_cb->hid_handle;
442 bdcpy(conn_dat.bda, p_cb->addr);
443
444 /* if SDP compl success */
445 if ( status == BTA_HH_OK)
446 {
447 /* not incoming connection doing SDP, initiate a HID connection */
448 if (!p_cb->incoming_conn)
449 {
450 tHID_STATUS ret;
451 /* set security level */
452 HID_HostSetSecurityLevel("", p_cb->sec_mask);
453
454 /* open HID connection */
Hemant Gupta891723a2015-12-11 20:09:22 +0530455 ret = HID_HostOpenDev (p_cb->hid_handle);
456 APPL_TRACE_DEBUG ("%s: HID_HostOpenDev returned=%d", __func__, ret);
457 if (ret == HID_SUCCESS || ret == HID_ERR_ALREADY_CONN)
458 {
459 status = BTA_HH_OK;
460 }
461 else if (ret == HID_ERR_CONN_IN_PROCESS)
462 {
463 /* Connection already in progress, return from here, SDP
464 * will be performed after connection is completed.
465 */
466 APPL_TRACE_DEBUG ("%s: connection already in progress", __func__);
467 return;
468 }
469 else
The Android Open Source Project5738f832012-12-12 16:00:35 -0800470 {
Marie Janssene9e58ce2016-06-17 14:12:17 -0700471#if (BTA_HH_DEBUG == TRUE)
Hemant Gupta891723a2015-12-11 20:09:22 +0530472 APPL_TRACE_DEBUG ("%s: HID_HostOpenDev failed: Status 0x%2X", __func__, ret);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800473#endif
474 /* open fail, remove device from management device list */
475 HID_HostRemoveDev( p_cb->hid_handle);
476 status = BTA_HH_ERR;
477 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800478 }
479 else /* incoming connection SDP finish */
480 {
481 bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
482 }
483 }
484
485 if (status != BTA_HH_OK)
486 {
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700487 /* Check if this was incoming connection request from an unknown device
488 **and connection failed due to missing HID Device SDP UUID
489 **In above condition, disconnect the link as well as remove the
490 **device from list of HID devices*/
491 if ((status == BTA_HH_ERR_SDP) &&
492 (p_cb->incoming_conn) &&(p_cb->app_id == 0))
493 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700494 APPL_TRACE_DEBUG ("bta_hh_sdp_cmpl:SDP failed for incoming conn :hndl %d",
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700495 p_cb->incoming_hid_handle);
496 HID_HostRemoveDev( p_cb->incoming_hid_handle);
497 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800498 conn_dat.status = status;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800499 (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
500
501 /* move state machine W4_CONN ->IDLE */
502 bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL);
503
504 /* if this is an outgoing connection to an unknown device, clean up cb */
505 if (p_cb->app_id == 0 && !p_cb->incoming_conn)
506 {
507 /* clean up device control block */
508 bta_hh_clean_up_kdev(p_cb);
509 }
Marie Janssene9e58ce2016-06-17 14:12:17 -0700510#if (BTA_HH_DEBUG == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800511 bta_hh_trace_dev_db();
512#endif
513 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800514 return;
515}
516
517/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800518 *
519 * Function bta_hh_api_disc_act
520 *
521 * Description HID Host initiate a disconnection.
522 *
523 *
524 * Returns void
525 *
526 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800527void bta_hh_api_disc_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
528{
529 tBTA_HH_CBDATA disc_dat;
530 tHID_STATUS status;
531
Marie Janssene9e58ce2016-06-17 14:12:17 -0700532#if (BTA_HH_LE_INCLUDED == TRUE)
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700533 if (p_cb->is_le_device)
534 bta_hh_le_api_disc_act(p_cb);
535 else
536#endif
537 {
538 /* found an active connection */
Marie Janssene9e58ce2016-06-17 14:12:17 -0700539 disc_dat.handle = p_data ?(uint8_t)p_data->hdr.layer_specific :p_cb->hid_handle;
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700540 disc_dat.status = BTA_HH_ERR;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800541
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700542 status = HID_HostCloseDev(disc_dat.handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800543
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700544 if (status)
545 (* bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH *)&disc_dat);
546 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800547
548 return;
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700549
The Android Open Source Project5738f832012-12-12 16:00:35 -0800550}
551/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800552 *
553 * Function bta_hh_open_cmpl_act
554 *
555 * Description HID host connection completed
556 *
557 *
558 * Returns void
559 *
560 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800561void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
562{
563 tBTA_HH_CONN conn ;
Marie Janssene9e58ce2016-06-17 14:12:17 -0700564 uint8_t dev_handle = p_data ? (uint8_t)p_data->hid_cback.hdr.layer_specific : \
The Android Open Source Project5738f832012-12-12 16:00:35 -0800565 p_cb->hid_handle;
566
567 memset((void *)&conn, 0, sizeof (tBTA_HH_CONN));
568 conn.handle = dev_handle;
569 bdcpy(conn.bda, p_cb->addr);
570
571 /* increase connection number */
572 bta_hh_cb.cnt_num ++;
573
574 /* initialize device driver */
575 bta_hh_co_open(p_cb->hid_handle, p_cb->sub_class,
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800576 p_cb->attr_mask, p_cb->app_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800577
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700578#if (BTA_HH_LE_INCLUDED == TRUE)
579 conn.status = p_cb->status;
580 conn.le_hid = p_cb->is_le_device;
581 conn.scps_supported = p_cb->scps_supported;
582
583 if (!p_cb->is_le_device)
584#endif
585 {
586 /* inform role manager */
587 bta_sys_conn_open( BTA_ID_HH ,p_cb->app_id, p_cb->addr);
588 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800589 /* set protocol mode when not default report mode */
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700590 if ( p_cb->mode != BTA_HH_PROTO_RPT_MODE
591#if (BTA_HH_LE_INCLUDED == TRUE)
592 && !p_cb->is_le_device
593#endif
594 )
The Android Open Source Project5738f832012-12-12 16:00:35 -0800595 {
596 if ((HID_HostWriteDev(dev_handle,
597 HID_TRANS_SET_PROTOCOL, HID_PAR_PROTOCOL_BOOT_MODE,
598 0,
599 0, NULL)) != HID_SUCCESS)
600 {
601 /* HID connection is up, while SET_PROTO fail */
602 conn.status = BTA_HH_ERR_PROTO;
603 (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn);
604 }
605 else
606 {
607 conn.status = BTA_HH_OK;
608 p_cb->w4_evt = BTA_HH_OPEN_EVT;
609 }
610 }
611 else
612 (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn);
613
Marie Janssene9e58ce2016-06-17 14:12:17 -0700614 p_cb->incoming_conn = false;
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700615 p_cb->incoming_hid_handle = BTA_HH_INVALID_HANDLE;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800616
617}
618/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800619 *
620 * Function bta_hh_open_act
621 *
622 * Description HID host receive HID_OPEN_EVT .
623 *
624 *
625 * Returns void
626 *
627 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800628void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
629{
630 tBTA_HH_API_CONN conn_data;
631
Marie Janssene9e58ce2016-06-17 14:12:17 -0700632 uint8_t dev_handle = p_data ? (uint8_t)p_data->hid_cback.hdr.layer_specific : \
The Android Open Source Project5738f832012-12-12 16:00:35 -0800633 p_cb->hid_handle;
634
Marie Janssene9e58ce2016-06-17 14:12:17 -0700635#if (BTA_HH_DEBUG == TRUE)
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700636 APPL_TRACE_EVENT ("bta_hh_open_act: Device[%d] connected", dev_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800637#endif
638
639 /* SDP has been done */
640 if (p_cb->app_id != 0)
641 {
642 bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, p_data);
643 }
644 else
645 /* app_id == 0 indicates an incoming conenction request arrives without SDP
646 performed, do it first */
647 {
Marie Janssene9e58ce2016-06-17 14:12:17 -0700648 p_cb->incoming_conn = true;
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700649 /* store the handle here in case sdp fails - need to disconnect */
650 p_cb->incoming_hid_handle = dev_handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800651
652 memset(&conn_data, 0, sizeof(tBTA_HH_API_CONN));
653 bdcpy(conn_data.bd_addr, p_cb->addr);
654 bta_hh_start_sdp(p_cb, (tBTA_HH_DATA *)&conn_data);
655 }
656
657 return;
658}
659
660
661/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800662 *
663 * Function bta_hh_data_act
664 *
665 * Description HID Host process a data report
666 *
667 *
668 * Returns void
669 *
670 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800671void bta_hh_data_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data)
672{
673 BT_HDR *pdata = p_data->hid_cback.p_data;
Marie Janssene9e58ce2016-06-17 14:12:17 -0700674 uint8_t *p_rpt = (uint8_t *)(pdata + 1) + pdata->offset;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800675
Marie Janssene9e58ce2016-06-17 14:12:17 -0700676 bta_hh_co_data((uint8_t)p_data->hid_cback.hdr.layer_specific, p_rpt, pdata->len,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800677 p_cb->mode, p_cb->sub_class, p_cb->dscp_info.ctry_code, p_cb->addr, p_cb->app_id);
678
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800679 osi_free_and_reset((void **)&pdata);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800680}
681
682
683/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800684 *
685 * Function bta_hh_handsk_act
686 *
687 * Description HID Host process a handshake acknoledgement.
688 *
689 *
690 * Returns void
691 *
692 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800693void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data)
694{
695 tBTA_HH_CBDATA cback_data ;
696 tBTA_HH_HSDATA hs_data;
697 tBTA_HH_CONN conn ;
698
Marie Janssene9e58ce2016-06-17 14:12:17 -0700699#if (BTA_HH_DEBUG == TRUE)
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700700 APPL_TRACE_DEBUG("HANDSHAKE received for: event = %s data= %d",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800701 bta_hh_get_w4_event(p_cb->w4_evt), p_data->hid_cback.data);
702#endif
703
704 memset(&hs_data, 0, sizeof(tBTA_HH_HSDATA));
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700705 memset(&cback_data, 0, sizeof(tBTA_HH_CBDATA));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800706
707 switch (p_cb->w4_evt)
708 {
709 /* GET_ transsaction, handshake indicate unsupported request */
710 case BTA_HH_GET_PROTO_EVT:
711 hs_data.rsp_data.proto_mode = BTA_HH_PROTO_UNKNOWN;
712 /* fall through */
713 case BTA_HH_GET_RPT_EVT:
714 case BTA_HH_GET_IDLE_EVT :
715 hs_data.handle = p_cb->hid_handle;
716 /* if handshake gives an OK code for these transaction, fill in UNSUPT */
717 if ((hs_data.status = bta_hh_get_trans_status(p_data->hid_cback.data)) == BTA_HH_OK)
718 hs_data.status = BTA_HH_HS_TRANS_NOT_SPT;
719
720 (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&hs_data);
721 p_cb->w4_evt = 0;
722 break;
723
724 /* acknoledgement from HID device for SET_ transaction */
725 case BTA_HH_SET_RPT_EVT:
726 case BTA_HH_SET_PROTO_EVT:
727 case BTA_HH_SET_IDLE_EVT :
728 cback_data.handle = p_cb->hid_handle;
729 cback_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
730 (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&cback_data);
731 p_cb->w4_evt = 0;
732 break;
733
734 /* SET_PROTOCOL when open connection */
735 case BTA_HH_OPEN_EVT:
736 conn.status =p_data->hid_cback.data ? BTA_HH_ERR_PROTO: BTA_HH_OK;
737 conn.handle = p_cb->hid_handle;
738 bdcpy(conn.bda, p_cb->addr);
739 (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&conn);
Marie Janssene9e58ce2016-06-17 14:12:17 -0700740#if (BTA_HH_DEBUG == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800741 bta_hh_trace_dev_db();
742#endif
743 p_cb->w4_evt = 0;
744 break;
745
746 default:
747 /* unknow transaction handshake response */
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700748 APPL_TRACE_DEBUG("unknown transaction type");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800749 break;
750 }
751
752 /* transaction achknoledgement received, inform PM for mode change */
753 bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
754 return;
755}
756/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800757 *
758 * Function bta_hh_ctrl_dat_act
759 *
760 * Description HID Host process a data report from control channel.
761 *
762 *
763 * Returns void
764 *
765 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800766void bta_hh_ctrl_dat_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data)
767{
768 BT_HDR *pdata = p_data->hid_cback.p_data;
Marie Janssene9e58ce2016-06-17 14:12:17 -0700769 uint8_t *data = (uint8_t *)(pdata + 1) + pdata->offset;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800770 tBTA_HH_HSDATA hs_data;
771
Marie Janssene9e58ce2016-06-17 14:12:17 -0700772#if (BTA_HH_DEBUG == TRUE)
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700773 APPL_TRACE_DEBUG("Ctrl DATA received w4: event[%s]",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800774 bta_hh_get_w4_event(p_cb->w4_evt));
775#endif
776 hs_data.status = BTA_HH_OK;
777 hs_data.handle = p_cb->hid_handle;
778
779 switch (p_cb->w4_evt)
780 {
781 case BTA_HH_GET_IDLE_EVT:
782 hs_data.rsp_data.idle_rate = *data;
783 break;
784 case BTA_HH_GET_RPT_EVT:
785 hs_data.rsp_data.p_rpt_data = pdata;
786 break;
787 case BTA_HH_GET_PROTO_EVT:
788 /* match up BTE/BTA report/boot mode def*/
789 hs_data.rsp_data.proto_mode = ((*data) == HID_PAR_PROTOCOL_REPORT)? \
790 BTA_HH_PROTO_RPT_MODE : BTA_HH_PROTO_BOOT_MODE;
Marie Janssene9e58ce2016-06-17 14:12:17 -0700791#if (BTA_HH_DEBUG == TRUE)
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700792 APPL_TRACE_DEBUG("GET_PROTOCOL Mode = [%s]",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800793 (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)? "Report" : "Boot");
794#endif
795 break;
796 /* should not expect control DATA for SET_ transaction */
797 case BTA_HH_SET_PROTO_EVT:
798 /* fall through */
799 case BTA_HH_SET_RPT_EVT:
800 /* fall through */
801 case BTA_HH_SET_IDLE_EVT :
802 /* fall through */
803 default:
Marie Janssene9e58ce2016-06-17 14:12:17 -0700804#if (BTA_HH_DEBUG == TRUE)
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700805 APPL_TRACE_DEBUG("invalid transaction type for DATA payload: 4_evt[%s]",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800806 bta_hh_get_w4_event(p_cb->w4_evt));
807#endif
808 break;
809 }
810
811 /* inform PM for mode change */
812 bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
813 bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
814
815 (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&hs_data);
816
817 p_cb->w4_evt = 0;
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800818 osi_free_and_reset((void **)&pdata);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800819
820}
821
822/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800823 *
824 * Function bta_hh_open_failure
825 *
826 * Description report HID open failure when at wait for connection state and receive
827 * device close event.
828 *
829 *
830 * Returns void
831 *
832 ******************************************************************************/
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700833void bta_hh_open_failure(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
834{
835 tBTA_HH_CONN conn_dat ;
Marie Janssene9e58ce2016-06-17 14:12:17 -0700836 uint32_t reason = p_data->hid_cback.data; /* Reason for closing (32-bit) */
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700837
838 memset(&conn_dat, 0, sizeof(tBTA_HH_CONN));
839 conn_dat.handle = p_cb->hid_handle;
840 conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ?
841 BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
842 bdcpy(conn_dat.bda, p_cb->addr);
843 HID_HostCloseDev(p_cb->hid_handle);
844
845 /* Report OPEN fail event */
846 (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
847
Marie Janssene9e58ce2016-06-17 14:12:17 -0700848#if (BTA_HH_DEBUG == TRUE)
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700849 bta_hh_trace_dev_db();
850#endif
851 /* clean up control block, but retain SDP info and device handle */
Marie Janssene9e58ce2016-06-17 14:12:17 -0700852 p_cb->vp = false;
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700853 p_cb->w4_evt = 0;
854
855 /* if no connection is active and HH disable is signaled, disable service */
856 if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable)
857 {
858 bta_hh_disc_cmpl();
859 }
860
Hemant Gupta891723a2015-12-11 20:09:22 +0530861 /* Error in opening hid connection, reset flags */
Marie Janssene9e58ce2016-06-17 14:12:17 -0700862 p_cb->incoming_conn = false;
Hemant Gupta891723a2015-12-11 20:09:22 +0530863 p_cb->incoming_hid_handle = BTA_HH_INVALID_HANDLE;
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700864}
865
866/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800867 *
868 * Function bta_hh_close_act
869 *
870 * Description HID Host process a close event
871 *
872 *
873 * Returns void
874 *
875 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800876void bta_hh_close_act (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
877{
878 tBTA_HH_CONN conn_dat ;
879 tBTA_HH_CBDATA disc_dat = {BTA_HH_OK, 0};
Marie Janssene9e58ce2016-06-17 14:12:17 -0700880 uint32_t reason = p_data->hid_cback.data; /* Reason for closing (32-bit) */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800881
882 /* if HID_HDEV_EVT_VC_UNPLUG was received, report BTA_HH_VC_UNPLUG_EVT */
Marie Janssene9e58ce2016-06-17 14:12:17 -0700883 uint16_t event = p_cb->vp ? BTA_HH_VC_UNPLUG_EVT : BTA_HH_CLOSE_EVT;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800884
885 disc_dat.handle = p_cb->hid_handle;
886 disc_dat.status = p_data->hid_cback.data;
887
888 /* Check reason for closing */
889 if ((reason & (HID_L2CAP_CONN_FAIL|HID_L2CAP_REQ_FAIL)) || /* Failure to initialize connection (page timeout or l2cap error) */
890 (reason == HID_ERR_AUTH_FAILED) || /* Authenication error (while initiating) */
891 (reason == HID_ERR_L2CAP_FAILED)) /* Failure creating l2cap connection */
892 {
893 /* Failure in opening connection */
894 conn_dat.handle = p_cb->hid_handle;
895 conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
896 bdcpy(conn_dat.bda, p_cb->addr);
897 HID_HostCloseDev(p_cb->hid_handle);
898
899 /* Report OPEN fail event */
900 (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
901
Marie Janssene9e58ce2016-06-17 14:12:17 -0700902#if (BTA_HH_DEBUG == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800903 bta_hh_trace_dev_db();
904#endif
905 return;
906 }
907 /* otherwise report CLOSE/VC_UNPLUG event */
908 else
909 {
910 /* finaliza device driver */
911 bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
912 /* inform role manager */
913 bta_sys_conn_close( BTA_ID_HH ,p_cb->app_id, p_cb->addr);
914 /* update total conn number */
915 bta_hh_cb.cnt_num --;
916
917 if (disc_dat.status)
918 disc_dat.status = BTA_HH_ERR;
919
920 (*bta_hh_cb.p_cback)(event, (tBTA_HH *)&disc_dat);
921
922 /* if virtually unplug, remove device */
923 if (p_cb->vp )
924 {
925 HID_HostRemoveDev( p_cb->hid_handle);
926 bta_hh_clean_up_kdev(p_cb);
927 }
928
Marie Janssene9e58ce2016-06-17 14:12:17 -0700929#if (BTA_HH_DEBUG == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800930 bta_hh_trace_dev_db();
931#endif
932 }
933
934 /* clean up control block, but retain SDP info and device handle */
Marie Janssene9e58ce2016-06-17 14:12:17 -0700935 p_cb->vp = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800936 p_cb->w4_evt = 0;
937
938 /* if no connection is active and HH disable is signaled, disable service */
939 if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable)
940 {
941 bta_hh_disc_cmpl();
942 }
943
944 return;
945}
946
947/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800948 *
949 * Function bta_hh_get_dscp_act
950 *
951 * Description Get device report descriptor
952 *
953 *
954 * Returns void
955 *
956 ******************************************************************************/
Myles Watsond35a6482016-10-27 08:52:16 -0700957void bta_hh_get_dscp_act(tBTA_HH_DEV_CB *p_cb,
958 UNUSED_ATTR tBTA_HH_DATA *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800959{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800960
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700961#if (BTA_HH_LE_INCLUDED == TRUE)
962 if (p_cb->is_le_device)
963 {
964 bta_hh_le_get_dscp_act(p_cb);
965 }
966 else
967#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -0800968 (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH *)&p_cb->dscp_info);
969}
970
971/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -0800972 *
973 * Function bta_hh_maint_dev_act
974 *
975 * Description HID Host maintain device list.
976 *
977 *
978 * Returns void
979 *
980 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800981void bta_hh_maint_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
982{
983 tBTA_HH_MAINT_DEV *p_dev_info = &p_data->api_maintdev;
984 tBTA_HH_DEV_INFO dev_info ;
Marie Janssene9e58ce2016-06-17 14:12:17 -0700985 uint8_t dev_handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800986
987 dev_info.status = BTA_HH_ERR;
988 dev_info.handle = BTA_HH_INVALID_HANDLE;
989
990 switch (p_dev_info->sub_event)
991 {
992 case BTA_HH_ADD_DEV_EVT: /* add a device */
993 bdcpy(dev_info.bda, p_dev_info->bda);
994 /* initialize callback data */
995 if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
996 {
Andre Eisenbach2e7fa682013-08-08 15:42:48 -0700997#if (BTA_HH_LE_INCLUDED == TRUE)
998 if (bta_hh_is_le_device(p_cb, p_data->api_conn.bd_addr))
999 {
1000 dev_info.handle = bta_hh_le_add_device(p_cb, p_dev_info);
1001 dev_info.status = BTA_HH_OK;
1002 }
1003 else
1004#endif
1005
The Android Open Source Project5738f832012-12-12 16:00:35 -08001006 if (HID_HostAddDev(p_dev_info->bda, p_dev_info->attr_mask, &dev_handle)\
1007 == HID_SUCCESS)
1008 {
1009 dev_info.handle = dev_handle;
1010 dev_info.status = BTA_HH_OK;
1011
Marie Janssene9e58ce2016-06-17 14:12:17 -07001012#if (BTA_HH_LE_INCLUDED == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001013 /* update DI information */
1014 bta_hh_update_di_info(p_cb,
1015 p_dev_info->dscp_info.vendor_id,
1016 p_dev_info->dscp_info.product_id,
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001017 p_dev_info->dscp_info.version,
Andre Eisenbach2e7fa682013-08-08 15:42:48 -07001018 p_dev_info->dscp_info.flag);
1019#else
1020 bta_hh_update_di_info(p_cb,
1021 p_dev_info->dscp_info.vendor_id,
1022 p_dev_info->dscp_info.product_id,
1023 p_dev_info->dscp_info.version,
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001024 0);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001025
Andre Eisenbach2e7fa682013-08-08 15:42:48 -07001026#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -08001027 /* add to BTA device list */
1028 bta_hh_add_device_to_list(p_cb, dev_handle,
1029 p_dev_info->attr_mask,
1030 &p_dev_info->dscp_info.descriptor,
1031 p_dev_info->sub_class,
1032 p_dev_info->dscp_info.ssr_max_latency,
1033 p_dev_info->dscp_info.ssr_min_tout,
1034 p_dev_info->app_id);
1035 /* update cb_index[] map */
1036 bta_hh_cb.cb_index[dev_handle] = p_cb->index;
1037 }
1038 }
1039 else /* device already been added */
1040 {
1041 dev_info.handle = p_cb->hid_handle;
1042 dev_info.status = BTA_HH_OK;
1043 }
Marie Janssene9e58ce2016-06-17 14:12:17 -07001044#if (BTA_HH_DEBUG == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001045 bta_hh_trace_dev_db();
1046#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -08001047
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001048 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001049 case BTA_HH_RMV_DEV_EVT: /* remove device */
Marie Janssene9e58ce2016-06-17 14:12:17 -07001050 dev_info.handle = (uint8_t)p_dev_info->hdr.layer_specific;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001051 bdcpy(dev_info.bda, p_cb->addr);
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001052
Marie Janssene9e58ce2016-06-17 14:12:17 -07001053#if (BTA_HH_LE_INCLUDED == TRUE)
Andre Eisenbach2e7fa682013-08-08 15:42:48 -07001054 if (p_cb->is_le_device)
1055 {
1056 bta_hh_le_remove_dev_bg_conn(p_cb);
1057 bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL);
1058 bta_hh_clean_up_kdev(p_cb);
1059 }
1060 else
1061#endif
The Android Open Source Project5738f832012-12-12 16:00:35 -08001062 {
1063 if(HID_HostRemoveDev( dev_info.handle ) == HID_SUCCESS)
1064 {
1065 dev_info.status = BTA_HH_OK;
1066
1067 /* remove from known device list in BTA */
1068 bta_hh_clean_up_kdev(p_cb);
1069 }
1070 }
1071 break;
1072
1073 default:
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001074 APPL_TRACE_DEBUG("invalid command");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001075 break;
1076 }
1077
1078 (* bta_hh_cb.p_cback)(p_dev_info->sub_event, (tBTA_HH *)&dev_info);
1079}
1080/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -08001081 *
1082 * Function bta_hh_write_dev_act
1083 *
1084 * Description Write device action. can be SET/GET/DATA transaction.
1085 *
1086 * Returns void
1087 *
1088 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -08001089void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
1090{
1091 tBTA_HH_CBDATA cbdata = {BTA_HH_OK, 0};
Marie Janssene9e58ce2016-06-17 14:12:17 -07001092 uint16_t event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
The Android Open Source Project5738f832012-12-12 16:00:35 -08001093 BTA_HH_FST_TRANS_CB_EVT;
1094
Marie Janssene9e58ce2016-06-17 14:12:17 -07001095#if (BTA_HH_LE_INCLUDED == TRUE)
Andre Eisenbach2e7fa682013-08-08 15:42:48 -07001096 if (p_cb->is_le_device)
1097 bta_hh_le_write_dev_act(p_cb, p_data);
1098 else
1099#endif
1100 {
1101
The Android Open Source Project5738f832012-12-12 16:00:35 -08001102 cbdata.handle = p_cb->hid_handle;
1103
1104 /* match up BTE/BTA report/boot mode def */
1105 if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL)
1106 {
1107 p_data->api_sndcmd.param = ( p_data->api_sndcmd.param == BTA_HH_PROTO_RPT_MODE) ?\
1108 HID_PAR_PROTOCOL_REPORT :HID_PAR_PROTOCOL_BOOT_MODE;
1109 }
1110
1111 if (HID_HostWriteDev (p_cb->hid_handle,
1112 p_data->api_sndcmd.t_type,
1113 p_data->api_sndcmd.param,
1114 p_data->api_sndcmd.data,
1115 p_data->api_sndcmd.rpt_id,
1116 p_data->api_sndcmd.p_data) != HID_SUCCESS)
1117 {
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001118 APPL_TRACE_ERROR("HID_HostWriteDev Error ");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001119 cbdata.status = BTA_HH_ERR;
1120
1121 if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL &&
1122 p_data->api_sndcmd.t_type != HID_TRANS_DATA)
1123 (* bta_hh_cb.p_cback)(event, (tBTA_HH *)&cbdata);
1124 else if (p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
1125 (* bta_hh_cb.p_cback)(BTA_HH_VC_UNPLUG_EVT, (tBTA_HH *)&cbdata);
1126 }
1127 else
1128 {
1129
1130 switch(p_data->api_sndcmd.t_type)
1131 {
1132 case HID_TRANS_SET_PROTOCOL:
1133 /* fall through */
1134 case HID_TRANS_GET_REPORT:
1135 /* fall through */
1136 case HID_TRANS_SET_REPORT:
1137 /* fall through */
1138 case HID_TRANS_GET_PROTOCOL:
1139 /* fall through */
1140 case HID_TRANS_GET_IDLE:
1141 /* fall through */
1142 case HID_TRANS_SET_IDLE:/* set w4_handsk event name for callback function use */
1143 p_cb->w4_evt = event;
1144 break;
1145 case HID_TRANS_DATA: /* output report */
1146 /* fall through */
1147 case HID_TRANS_CONTROL:
1148 /* no handshake event will be generated */
1149 /* if VC_UNPLUG is issued, set flag */
1150 if (p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
Marie Janssene9e58ce2016-06-17 14:12:17 -07001151 p_cb->vp = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001152
1153 break;
1154 /* currently not expected */
1155 case HID_TRANS_DATAC:
1156 default:
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001157 APPL_TRACE_DEBUG("bta_hh_write_dev_act:: cmd type = %d",
The Android Open Source Project5738f832012-12-12 16:00:35 -08001158 p_data->api_sndcmd.t_type);
1159 break;
1160 }
1161
1162 /* if not control type transaction, notify PM for energy control */
1163 if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL)
1164 {
1165 /* inform PM for mode change */
1166 bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
1167 bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
1168 }
1169 else if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND)
1170 {
1171 bta_sys_sco_close(BTA_ID_HH, p_cb->app_id, p_cb->addr);
1172 }
1173 else if (p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND)
1174 {
1175 bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
1176 }
1177 }
1178
Andre Eisenbach2e7fa682013-08-08 15:42:48 -07001179 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001180 return;
1181}
1182
1183/*****************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -08001184 * Static Function
1185 ****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -08001186/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -08001187 *
1188 * Function bta_hh_cback
1189 *
1190 * Description BTA HH callback function.
1191 *
1192 *
1193 * Returns void
1194 *
1195 ******************************************************************************/
Marie Janssene9e58ce2016-06-17 14:12:17 -07001196static void bta_hh_cback (uint8_t dev_handle, BD_ADDR addr, uint8_t event,
1197 uint32_t data, BT_HDR *pdata)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001198{
Marie Janssene9e58ce2016-06-17 14:12:17 -07001199 uint16_t sm_event = BTA_HH_INVALID_EVT;
1200 uint8_t xx = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001201
Marie Janssene9e58ce2016-06-17 14:12:17 -07001202#if (BTA_HH_DEBUG == TRUE)
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -07001203 APPL_TRACE_DEBUG("bta_hh_cback::HID_event [%s]", bta_hh_hid_event_name(event));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001204#endif
1205
1206 switch (event)
1207 {
1208 case HID_HDEV_EVT_OPEN:
1209 sm_event = BTA_HH_INT_OPEN_EVT;
1210 break;
1211 case HID_HDEV_EVT_CLOSE:
1212 sm_event = BTA_HH_INT_CLOSE_EVT;
1213 break;
1214 case HID_HDEV_EVT_INTR_DATA:
1215 sm_event = BTA_HH_INT_DATA_EVT;
1216 break;
1217 case HID_HDEV_EVT_HANDSHAKE:
1218 sm_event = BTA_HH_INT_HANDSK_EVT;
1219 break;
1220 case HID_HDEV_EVT_CTRL_DATA:
1221 sm_event = BTA_HH_INT_CTRL_DATA;
1222 break;
1223 case HID_HDEV_EVT_RETRYING:
1224 break;
1225 case HID_HDEV_EVT_INTR_DATC:
1226 case HID_HDEV_EVT_CTRL_DATC:
1227 /* Unhandled events: Free buffer for DATAC */
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001228 osi_free_and_reset((void **)&pdata);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001229 break;
1230 case HID_HDEV_EVT_VC_UNPLUG:
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001231 for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001232 {
1233 if (bta_hh_cb.kdev[xx].hid_handle == dev_handle)
1234 {
Marie Janssene9e58ce2016-06-17 14:12:17 -07001235 bta_hh_cb.kdev[xx].vp = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001236 break;
1237 }
1238 }
1239 break;
1240 }
1241
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001242 if (sm_event != BTA_HH_INVALID_EVT) {
1243 tBTA_HH_CBACK_DATA *p_buf =
1244 (tBTA_HH_CBACK_DATA *)osi_malloc(sizeof(tBTA_HH_CBACK_DATA) +
1245 sizeof(BT_HDR));
1246 p_buf->hdr.event = sm_event;
Marie Janssene9e58ce2016-06-17 14:12:17 -07001247 p_buf->hdr.layer_specific = (uint16_t)dev_handle;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001248 p_buf->data = data;
Andre Eisenbach2e7fa682013-08-08 15:42:48 -07001249 bdcpy(p_buf->addr, addr);
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001250 p_buf->p_data = pdata;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001251
1252 bta_sys_sendmsg(p_buf);
1253 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001254}
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001255
The Android Open Source Project5738f832012-12-12 16:00:35 -08001256/*******************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -08001257 *
1258 * Function bta_hh_get_trans_status
1259 *
1260 * Description translate a handshake result code into BTA HH
1261 * status code
1262 *
1263 ******************************************************************************/
Marie Janssene9e58ce2016-06-17 14:12:17 -07001264static tBTA_HH_STATUS bta_hh_get_trans_status(uint32_t result)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001265{
1266 switch(result)
1267 {
1268 case HID_PAR_HANDSHAKE_RSP_SUCCESS : /* (0) */
1269 return BTA_HH_OK;
1270 case HID_PAR_HANDSHAKE_RSP_NOT_READY : /* (1) */
1271 case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID: /* (2) */
1272 case HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ : /* (3) */
1273 case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM : /* (4) */
1274 return (tBTA_HH_STATUS)result;
1275 case HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN : /* (14) */
1276 case HID_PAR_HANDSHAKE_RSP_ERR_FATAL : /* (15) */
1277 default:
1278 return BTA_HH_HS_ERROR;
1279 break;
1280 }
1281}
1282/*****************************************************************************
Myles Watson8af480e2016-11-09 10:40:23 -08001283 * Debug Functions
1284 ****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -08001285
Marie Janssene9e58ce2016-06-17 14:12:17 -07001286#if (BTA_HH_DEBUG == TRUE)
1287static const char* bta_hh_get_w4_event(uint16_t event)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001288{
1289 switch (event)
1290 {
1291 case BTA_HH_GET_RPT_EVT:
1292 return "BTA_HH_GET_RPT_EVT";
1293 case BTA_HH_SET_RPT_EVT:
1294 return "BTA_HH_SET_RPT_EVT";
1295 case BTA_HH_GET_PROTO_EVT:
1296 return "BTA_HH_GET_PROTO_EVT";
1297 case BTA_HH_SET_PROTO_EVT:
1298 return "BTA_HH_SET_PROTO_EVT";
1299 case BTA_HH_GET_IDLE_EVT:
1300 return "BTA_HH_GET_IDLE_EVT";
1301 case BTA_HH_SET_IDLE_EVT:
1302 return "BTA_HH_SET_IDLE_EVT";
1303 case BTA_HH_OPEN_EVT:
1304 return "BTA_HH_OPEN_EVT";
1305 default:
1306 return "Unknown event";
1307 }
1308
1309}
1310
Marie Janssene9e58ce2016-06-17 14:12:17 -07001311static const char * bta_hh_hid_event_name(uint16_t event)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001312{
1313 switch (event)
1314 {
1315 case HID_HDEV_EVT_OPEN:
1316 return "HID_HDEV_EVT_OPEN";
1317 case HID_HDEV_EVT_CLOSE:
1318 return "HID_HDEV_EVT_CLOSE";
1319 case HID_HDEV_EVT_RETRYING:
1320 return "HID_HDEV_EVT_RETRYING";
1321 case HID_HDEV_EVT_INTR_DATA:
1322 return "HID_HDEV_EVT_INTR_DATA";
1323 case HID_HDEV_EVT_INTR_DATC:
1324 return "HID_HDEV_EVT_INTR_DATC";
1325 case HID_HDEV_EVT_CTRL_DATA:
1326 return "HID_HDEV_EVT_CTRL_DATA";
1327 case HID_HDEV_EVT_CTRL_DATC:
1328 return "HID_HDEV_EVT_CTRL_DATC";
1329 case HID_HDEV_EVT_HANDSHAKE:
1330 return "HID_HDEV_EVT_HANDSHAKE";
1331 case HID_HDEV_EVT_VC_UNPLUG:
1332 return "HID_HDEV_EVT_VC_UNPLUG";
1333 default:
1334 return "Unknown HID event";
1335 }
1336}
1337#endif
1338#endif /* BTA_HH_INCLUDED */
1339