1/******************************************************************************
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
27#if (BTA_HH_INCLUDED == TRUE)
28
29#include <string.h>
30
31#include "bta_hh_co.h"
32#include "bta_hh_int.h"
33#include "bta_sys.h"
34#include "btm_api.h"
35#include "l2c_api.h"
36#include "osi/include/osi.h"
37#include "utl.h"
38
39/*****************************************************************************
40 *  Constants
41 ****************************************************************************/
42
43/*****************************************************************************
44 *  Local Function prototypes
45 ****************************************************************************/
46static void bta_hh_cback(uint8_t dev_handle, const RawAddress& addr,
47                         uint8_t event, uint32_t data, BT_HDR* pdata);
48static tBTA_HH_STATUS bta_hh_get_trans_status(uint32_t result);
49
50#if (BTA_HH_DEBUG == TRUE)
51static const char* bta_hh_get_w4_event(uint16_t event);
52static const char* bta_hh_hid_event_name(uint16_t event);
53#endif
54
55/*****************************************************************************
56 *  Action Functions
57 ****************************************************************************/
58/*******************************************************************************
59 *
60 * Function         bta_hh_api_enable
61 *
62 * Description      Perform necessary operations to enable HID host.
63 *
64 *
65 * Returns          void
66 *
67 ******************************************************************************/
68void bta_hh_api_enable(tBTA_HH_DATA* p_data) {
69  tBTA_HH_STATUS status = BTA_HH_ERR;
70  uint8_t xx;
71
72  /* initialize BTE HID */
73  HID_HostInit();
74
75  memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
76
77  HID_HostSetSecurityLevel("", p_data->api_enable.sec_mask);
78
79  /* Register with L2CAP */
80  if (HID_HostRegister(bta_hh_cback) == HID_SUCCESS) {
81    /* store parameters */
82    bta_hh_cb.p_cback = p_data->api_enable.p_cback;
83
84    status = BTA_HH_OK;
85    /* initialize device CB */
86    for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
87      bta_hh_cb.kdev[xx].state = BTA_HH_IDLE_ST;
88      bta_hh_cb.kdev[xx].hid_handle = BTA_HH_INVALID_HANDLE;
89      bta_hh_cb.kdev[xx].index = xx;
90    }
91
92    /* initialize control block map */
93    for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
94      bta_hh_cb.cb_index[xx] = BTA_HH_IDX_INVALID;
95  }
96
97#if (BTA_HH_LE_INCLUDED == TRUE)
98  if (status == BTA_HH_OK) {
99    bta_hh_le_enable();
100  } else
101#endif
102    /* signal BTA call back event */
103    (*bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH*)&status);
104}
105/*******************************************************************************
106 *
107 * Function         bta_hh_api_disable
108 *
109 * Description      Perform necessary operations to disable HID host.
110 *
111 *
112 * Returns          void
113 *
114 ******************************************************************************/
115void bta_hh_api_disable(void) {
116  uint8_t xx;
117
118  /* service is not enabled */
119  if (bta_hh_cb.p_cback == NULL) return;
120
121  /* no live connection, signal DISC_CMPL_EVT directly */
122  if (!bta_hh_cb.cnt_num) {
123    bta_hh_disc_cmpl();
124  } else /* otherwise, disconnect all live connections */
125  {
126    bta_hh_cb.w4_disable = true;
127
128    for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
129      /* send API_CLOSE event to every connected device */
130      if (bta_hh_cb.kdev[xx].state == BTA_HH_CONN_ST) {
131        /* disconnect all connected devices */
132        bta_hh_sm_execute(&bta_hh_cb.kdev[xx], BTA_HH_API_CLOSE_EVT, NULL);
133      }
134    }
135  }
136
137  return;
138}
139
140/*******************************************************************************
141 *
142 * Function         bta_hh_disc_cmpl
143 *
144 * Description      All connections have been closed, disable service.
145 *
146 *
147 * Returns          void
148 *
149 ******************************************************************************/
150void bta_hh_disc_cmpl(void) {
151#if (BTA_HH_LE_INCLUDED == TRUE)
152  HID_HostDeregister();
153  bta_hh_le_deregister();
154#else
155  tBTA_HH_STATUS status = BTA_HH_OK;
156
157  /* Deregister with lower layer */
158  if (HID_HostDeregister() != HID_SUCCESS) status = BTA_HH_ERR;
159
160  bta_hh_cleanup_disable(status);
161#endif
162}
163
164/*******************************************************************************
165 *
166 * Function         bta_hh_sdp_cback
167 *
168 * Description      SDP callback function.
169 *
170 * Returns          void
171 *
172 ******************************************************************************/
173static void bta_hh_sdp_cback(uint16_t result, uint16_t attr_mask,
174                             tHID_DEV_SDP_INFO* sdp_rec) {
175  tBTA_HH_DEV_CB* p_cb = bta_hh_cb.p_cur;
176  uint8_t hdl = 0;
177  tBTA_HH_STATUS status = BTA_HH_ERR_SDP;
178
179  /* make sure sdp succeeded and hh has not been disabled */
180  if ((result == SDP_SUCCESS) && (p_cb != NULL)) {
181    /* security is required for the connection, add attr_mask bit*/
182    if (p_cb->sec_mask) attr_mask |= HID_SEC_REQUIRED;
183
184#if (BTA_HH_DEBUG == TRUE)
185    APPL_TRACE_EVENT("%s: p_cb: %d result 0x%02x, attr_mask 0x%02x, handle %x",
186                     __func__, p_cb, result, attr_mask, p_cb->hid_handle);
187#endif
188
189    /* check to see type of device is supported , and should not been added
190     * before */
191    if (bta_hh_tod_spt(p_cb, sdp_rec->sub_class)) {
192      /* if not added before */
193      if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE) {
194        /*  add device/update attr_mask information */
195        if (HID_HostAddDev(p_cb->addr, attr_mask, &hdl) == HID_SUCCESS) {
196          status = BTA_HH_OK;
197          /* update cb_index[] map */
198          bta_hh_cb.cb_index[hdl] = p_cb->index;
199        } else {
200          p_cb->app_id = 0;
201        }
202      } else {
203        hdl = p_cb->hid_handle;
204      }
205      /* else : incoming connection after SDP should update the SDP information
206       * as well */
207
208      if (p_cb->app_id != 0) {
209        /* update cb information with attr_mask, dscp_info etc. */
210        bta_hh_add_device_to_list(p_cb, hdl, attr_mask, &sdp_rec->dscp_info,
211                                  sdp_rec->sub_class, sdp_rec->ssr_max_latency,
212                                  sdp_rec->ssr_min_tout, p_cb->app_id);
213
214        p_cb->dscp_info.ctry_code = sdp_rec->ctry_code;
215
216        status = BTA_HH_OK;
217      }
218
219    } else /* type of device is not supported */
220      status = BTA_HH_ERR_TOD_UNSPT;
221  }
222
223  /* free disc_db when SDP is completed */
224  osi_free_and_reset((void**)&bta_hh_cb.p_disc_db);
225
226  /* send SDP_CMPL_EVT into state machine */
227  bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA*)&status);
228
229  return;
230}
231/*******************************************************************************
232 *
233 * Function         bta_hh_di_sdp_cback
234 *
235 * Description      SDP DI callback function.
236 *
237 * Returns          void
238 *
239 ******************************************************************************/
240static void bta_hh_di_sdp_cback(uint16_t result) {
241  tBTA_HH_DEV_CB* p_cb = bta_hh_cb.p_cur;
242  tBTA_HH_STATUS status = BTA_HH_ERR_SDP;
243  tSDP_DI_GET_RECORD di_rec;
244  tHID_STATUS ret;
245#if (BTA_HH_DEBUG == TRUE)
246  APPL_TRACE_EVENT("%s: p_cb: %d result 0x%02x", __func__, p_cb, result);
247#endif
248
249  /* if DI record does not exist on remote device, vendor_id in
250   * tBTA_HH_DEV_DSCP_INFO will be set to 0xffff and we will allow the
251   * connection to go through. Spec mandates that DI record be set, but many
252   * HID devices do not set this. So for IOP purposes, we allow the connection
253   * to go through and update the DI record to invalid DI entry.
254   */
255  if (((result == SDP_SUCCESS) || (result == SDP_NO_RECS_MATCH)) &&
256      (p_cb != NULL)) {
257    if (result == SDP_SUCCESS &&
258        SDP_GetNumDiRecords(bta_hh_cb.p_disc_db) != 0) {
259      /* always update information with primary DI record */
260      if (SDP_GetDiRecord(1, &di_rec, bta_hh_cb.p_disc_db) == SDP_SUCCESS) {
261        bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product,
262                              di_rec.rec.version, 0);
263      }
264
265    } else /* no DI recrod available */
266    {
267      bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0, 0);
268    }
269
270    ret = HID_HostGetSDPRecord(p_cb->addr, bta_hh_cb.p_disc_db,
271                               p_bta_hh_cfg->sdp_db_size, bta_hh_sdp_cback);
272    if (ret == HID_SUCCESS) {
273      status = BTA_HH_OK;
274    } else {
275#if (BTA_HH_DEBUG == TRUE)
276      APPL_TRACE_DEBUG("%s:  HID_HostGetSDPRecord failed: Status 0x%2x",
277                       __func__, ret);
278#endif
279    }
280  }
281
282  if (status != BTA_HH_OK) {
283    osi_free_and_reset((void**)&bta_hh_cb.p_disc_db);
284    /* send SDP_CMPL_EVT into state machine */
285    bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA*)&status);
286  }
287  return;
288}
289
290/*******************************************************************************
291 *
292 * Function         bta_hh_start_sdp
293 *
294 * Description      Start SDP service search, and obtain necessary SDP records.
295 *                  Only one SDP service search request is allowed at the same
296 *                  time. For every BTA_HhOpen API call, do SDP first unless SDP
297 *                  has been done previously.
298 *
299 * Returns          void
300 *
301 ******************************************************************************/
302void bta_hh_start_sdp(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
303  tBTA_HH_STATUS status = BTA_HH_ERR_SDP;
304  uint8_t hdl;
305
306  p_cb->sec_mask = p_data->api_conn.sec_mask;
307  p_cb->mode = p_data->api_conn.mode;
308  bta_hh_cb.p_cur = p_cb;
309
310#if (BTA_HH_LE_INCLUDED == TRUE)
311  if (bta_hh_is_le_device(p_cb, p_data->api_conn.bd_addr)) {
312    bta_hh_le_open_conn(p_cb, p_data->api_conn.bd_addr);
313    return;
314  }
315#endif
316
317  /* if previously virtually cabled device, skip SDP */
318  if (p_cb->app_id) {
319    status = BTA_HH_OK;
320#if (BTA_HH_DEBUG == TRUE)
321    APPL_TRACE_DEBUG("%s: skip SDP for known devices", __func__);
322#endif
323    if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE) {
324      if (HID_HostAddDev(p_cb->addr, p_cb->attr_mask, &hdl) == HID_SUCCESS) {
325        /* update device CB with newly register device handle */
326        bta_hh_add_device_to_list(p_cb, hdl, p_cb->attr_mask, NULL,
327                                  p_cb->sub_class,
328                                  p_cb->dscp_info.ssr_max_latency,
329                                  p_cb->dscp_info.ssr_min_tout, p_cb->app_id);
330        /* update cb_index[] map */
331        bta_hh_cb.cb_index[hdl] = p_cb->index;
332      } else
333        status = BTA_HH_ERR_NO_RES;
334    }
335    bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA*)&status);
336
337    return;
338  }
339  /* GetSDPRecord. at one time only one SDP precedure can be active */
340  else if (!bta_hh_cb.p_disc_db) {
341    bta_hh_cb.p_disc_db =
342        (tSDP_DISCOVERY_DB*)osi_malloc(p_bta_hh_cfg->sdp_db_size);
343    bta_hh_cb.p_cur = p_cb;
344    /* do DI discovery first */
345    if (SDP_DiDiscover(p_data->api_conn.bd_addr, bta_hh_cb.p_disc_db,
346                       p_bta_hh_cfg->sdp_db_size,
347                       bta_hh_di_sdp_cback) != SDP_SUCCESS) {
348#if (BTA_HH_DEBUG == TRUE)
349      APPL_TRACE_DEBUG("%s:  SDP_DiDiscover failed: Status 0x%2X", __func__,
350                       status);
351#endif
352      status = BTA_HH_ERR_SDP;
353      osi_free_and_reset((void**)&bta_hh_cb.p_disc_db);
354    } else {
355      status = BTA_HH_OK;
356    }
357  } else if (bta_hh_cb.p_disc_db) {
358    /* It is possible that there is incoming/outgoing collision case. DUT
359     * initiated
360     * HID connection at same time remote has connected L2CAP for HID control,
361     * so SDP would be in progress, when this flow reaches here. Just do nothing
362     * when the code reaches here, and ongoing SDP completion or failure will
363     * handle this case.
364     */
365    APPL_TRACE_DEBUG("%s: ignoring as SDP already in progress", __func__);
366    return;
367  }
368
369  if (status != BTA_HH_OK)
370    bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA*)&status);
371
372  return;
373}
374/*******************************************************************************
375 *
376 * Function         bta_hh_sdp_cmpl
377 *
378 * Description      When SDP completes, initiate a connection or report an error
379 *                  depending on the SDP result.
380 *
381 *
382 * Returns          void
383 *
384 ******************************************************************************/
385void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
386  tBTA_HH_CONN conn_dat;
387  tBTA_HH_STATUS status = p_data->status;
388
389#if (BTA_HH_DEBUG == TRUE)
390  APPL_TRACE_DEBUG("%s:  status 0x%2X", __func__, p_data->status);
391#endif
392
393  /* initialize call back data */
394  memset((void*)&conn_dat, 0, sizeof(tBTA_HH_CONN));
395  conn_dat.handle = p_cb->hid_handle;
396  conn_dat.bda = p_cb->addr;
397
398  /* if SDP compl success */
399  if (status == BTA_HH_OK) {
400    /* not incoming connection doing SDP, initiate a HID connection */
401    if (!p_cb->incoming_conn) {
402      tHID_STATUS ret;
403      /* set security level */
404      HID_HostSetSecurityLevel("", p_cb->sec_mask);
405
406      /* open HID connection */
407      ret = HID_HostOpenDev(p_cb->hid_handle);
408      APPL_TRACE_DEBUG("%s: HID_HostOpenDev returned=%d", __func__, ret);
409      if (ret == HID_SUCCESS || ret == HID_ERR_ALREADY_CONN) {
410        status = BTA_HH_OK;
411      } else if (ret == HID_ERR_CONN_IN_PROCESS) {
412        /* Connection already in progress, return from here, SDP
413         * will be performed after connection is completed.
414         */
415        APPL_TRACE_DEBUG("%s: connection already in progress", __func__);
416        return;
417      } else {
418#if (BTA_HH_DEBUG == TRUE)
419        APPL_TRACE_DEBUG("%s: HID_HostOpenDev failed: Status 0x%2X", __func__,
420                         ret);
421#endif
422        /* open fail, remove device from management device list */
423        HID_HostRemoveDev(p_cb->hid_handle);
424        status = BTA_HH_ERR;
425      }
426    } else /* incoming connection SDP finish */
427    {
428      bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
429    }
430  }
431
432  if (status != BTA_HH_OK) {
433    /* Check if this was incoming connection request  from an unknown device
434     * and connection failed due to missing HID Device SDP UUID
435     * In above condition, disconnect the link as well as remove the
436     * device from list of HID devices
437     */
438    if ((status == BTA_HH_ERR_SDP) && (p_cb->incoming_conn) &&
439        (p_cb->app_id == 0)) {
440      APPL_TRACE_DEBUG("%s: SDP failed for  incoming conn :hndl %d", __func__,
441                       p_cb->incoming_hid_handle);
442      HID_HostRemoveDev(p_cb->incoming_hid_handle);
443    }
444    conn_dat.status = status;
445    (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH*)&conn_dat);
446
447    /* move state machine W4_CONN ->IDLE */
448    bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL);
449
450    /* if this is an outgoing connection to an unknown device, clean up cb */
451    if (p_cb->app_id == 0 && !p_cb->incoming_conn) {
452      /* clean up device control block */
453      bta_hh_clean_up_kdev(p_cb);
454    }
455#if (BTA_HH_DEBUG == TRUE)
456    bta_hh_trace_dev_db();
457#endif
458  }
459  return;
460}
461
462/*******************************************************************************
463 *
464 * Function         bta_hh_api_disc_act
465 *
466 * Description      HID Host initiate a disconnection.
467 *
468 *
469 * Returns          void
470 *
471 ******************************************************************************/
472void bta_hh_api_disc_act(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
473  tBTA_HH_CBDATA disc_dat;
474  tHID_STATUS status;
475
476#if (BTA_HH_LE_INCLUDED == TRUE)
477  if (p_cb->is_le_device)
478    bta_hh_le_api_disc_act(p_cb);
479  else
480#endif
481  {
482    /* found an active connection */
483    disc_dat.handle =
484        p_data ? (uint8_t)p_data->hdr.layer_specific : p_cb->hid_handle;
485    disc_dat.status = BTA_HH_ERR;
486
487    status = HID_HostCloseDev(disc_dat.handle);
488
489    if (status) (*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH*)&disc_dat);
490  }
491
492  return;
493}
494/*******************************************************************************
495 *
496 * Function         bta_hh_open_cmpl_act
497 *
498 * Description      HID host connection completed
499 *
500 *
501 * Returns          void
502 *
503 ******************************************************************************/
504void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
505  tBTA_HH_CONN conn;
506  uint8_t dev_handle =
507      p_data ? (uint8_t)p_data->hid_cback.hdr.layer_specific : p_cb->hid_handle;
508
509  memset((void*)&conn, 0, sizeof(tBTA_HH_CONN));
510  conn.handle = dev_handle;
511  conn.bda = p_cb->addr;
512
513  /* increase connection number */
514  bta_hh_cb.cnt_num++;
515
516  /* initialize device driver */
517  bta_hh_co_open(p_cb->hid_handle, p_cb->sub_class, p_cb->attr_mask,
518                 p_cb->app_id);
519
520#if (BTA_HH_LE_INCLUDED == TRUE)
521  conn.status = p_cb->status;
522  conn.le_hid = p_cb->is_le_device;
523  conn.scps_supported = p_cb->scps_supported;
524
525  if (!p_cb->is_le_device)
526#endif
527  {
528    /* inform role manager */
529    bta_sys_conn_open(BTA_ID_HH, p_cb->app_id, p_cb->addr);
530  }
531  /* set protocol mode when not default report mode */
532  if (p_cb->mode != BTA_HH_PROTO_RPT_MODE
533#if (BTA_HH_LE_INCLUDED == TRUE)
534      && !p_cb->is_le_device
535#endif
536      ) {
537    if ((HID_HostWriteDev(dev_handle, HID_TRANS_SET_PROTOCOL,
538                          HID_PAR_PROTOCOL_BOOT_MODE, 0, 0, NULL)) !=
539        HID_SUCCESS) {
540      /* HID connection is up, while SET_PROTO fail */
541      conn.status = BTA_HH_ERR_PROTO;
542      (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH*)&conn);
543    } else {
544      conn.status = BTA_HH_OK;
545      p_cb->w4_evt = BTA_HH_OPEN_EVT;
546    }
547  } else
548    (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH*)&conn);
549
550  p_cb->incoming_conn = false;
551  p_cb->incoming_hid_handle = BTA_HH_INVALID_HANDLE;
552}
553/*******************************************************************************
554 *
555 * Function         bta_hh_open_act
556 *
557 * Description      HID host receive HID_OPEN_EVT .
558 *
559 *
560 * Returns          void
561 *
562 ******************************************************************************/
563void bta_hh_open_act(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
564  tBTA_HH_API_CONN conn_data;
565
566  uint8_t dev_handle =
567      p_data ? (uint8_t)p_data->hid_cback.hdr.layer_specific : p_cb->hid_handle;
568
569#if (BTA_HH_DEBUG == TRUE)
570  APPL_TRACE_EVENT("%s:  Device[%d] connected", __func__, dev_handle);
571#endif
572
573  /* SDP has been done */
574  if (p_cb->app_id != 0) {
575    bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, p_data);
576  } else
577  /*  app_id == 0 indicates an incoming conenction request arrives without SDP
578   *  performed, do it first
579   */
580  {
581    p_cb->incoming_conn = true;
582    /* store the handle here in case sdp fails - need to disconnect */
583    p_cb->incoming_hid_handle = dev_handle;
584
585    memset(&conn_data, 0, sizeof(tBTA_HH_API_CONN));
586    conn_data.bd_addr = p_cb->addr;
587    bta_hh_start_sdp(p_cb, (tBTA_HH_DATA*)&conn_data);
588  }
589
590  return;
591}
592
593/*******************************************************************************
594 *
595 * Function         bta_hh_data_act
596 *
597 * Description      HID Host process a data report
598 *
599 *
600 * Returns          void
601 *
602 ******************************************************************************/
603void bta_hh_data_act(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
604  BT_HDR* pdata = p_data->hid_cback.p_data;
605  uint8_t* p_rpt = (uint8_t*)(pdata + 1) + pdata->offset;
606
607  bta_hh_co_data((uint8_t)p_data->hid_cback.hdr.layer_specific, p_rpt,
608                 pdata->len, p_cb->mode, p_cb->sub_class,
609                 p_cb->dscp_info.ctry_code, p_cb->addr, p_cb->app_id);
610
611  osi_free_and_reset((void**)&pdata);
612}
613
614/*******************************************************************************
615 *
616 * Function         bta_hh_handsk_act
617 *
618 * Description      HID Host process a handshake acknoledgement.
619 *
620 *
621 * Returns          void
622 *
623 ******************************************************************************/
624void bta_hh_handsk_act(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
625  tBTA_HH_CBDATA cback_data;
626  tBTA_HH_HSDATA hs_data;
627  tBTA_HH_CONN conn;
628
629#if (BTA_HH_DEBUG == TRUE)
630  APPL_TRACE_DEBUG("HANDSHAKE received for: event = %s data= %d",
631                   bta_hh_get_w4_event(p_cb->w4_evt), p_data->hid_cback.data);
632#endif
633
634  memset(&hs_data, 0, sizeof(tBTA_HH_HSDATA));
635  memset(&cback_data, 0, sizeof(tBTA_HH_CBDATA));
636
637  switch (p_cb->w4_evt) {
638    /* GET_ transsaction, handshake indicate unsupported request */
639    case BTA_HH_GET_PROTO_EVT:
640      hs_data.rsp_data.proto_mode = BTA_HH_PROTO_UNKNOWN;
641    /* fall through */
642    case BTA_HH_GET_RPT_EVT:
643    case BTA_HH_GET_IDLE_EVT:
644      hs_data.handle = p_cb->hid_handle;
645      /* if handshake gives an OK code for these transaction, fill in UNSUPT */
646      hs_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
647      if (hs_data.status == BTA_HH_OK) hs_data.status = BTA_HH_HS_TRANS_NOT_SPT;
648
649      (*bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH*)&hs_data);
650      p_cb->w4_evt = 0;
651      break;
652
653    /* acknoledgement from HID device for SET_ transaction */
654    case BTA_HH_SET_RPT_EVT:
655    case BTA_HH_SET_PROTO_EVT:
656    case BTA_HH_SET_IDLE_EVT:
657      cback_data.handle = p_cb->hid_handle;
658      cback_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
659      (*bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH*)&cback_data);
660      p_cb->w4_evt = 0;
661      break;
662
663    /* SET_PROTOCOL when open connection */
664    case BTA_HH_OPEN_EVT:
665      conn.status = p_data->hid_cback.data ? BTA_HH_ERR_PROTO : BTA_HH_OK;
666      conn.handle = p_cb->hid_handle;
667      conn.bda = p_cb->addr;
668      (*bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH*)&conn);
669#if (BTA_HH_DEBUG == TRUE)
670      bta_hh_trace_dev_db();
671#endif
672      p_cb->w4_evt = 0;
673      break;
674
675    default:
676      /* unknow transaction handshake response */
677      APPL_TRACE_DEBUG("unknown transaction type");
678      break;
679  }
680
681  /* transaction achknoledgement received, inform PM for mode change */
682  bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
683  return;
684}
685/*******************************************************************************
686 *
687 * Function         bta_hh_ctrl_dat_act
688 *
689 * Description      HID Host process a data report from control channel.
690 *
691 *
692 * Returns          void
693 *
694 ******************************************************************************/
695void bta_hh_ctrl_dat_act(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
696  BT_HDR* pdata = p_data->hid_cback.p_data;
697  uint8_t* data = (uint8_t*)(pdata + 1) + pdata->offset;
698  tBTA_HH_HSDATA hs_data;
699
700#if (BTA_HH_DEBUG == TRUE)
701  APPL_TRACE_DEBUG("Ctrl DATA received w4: event[%s]",
702                   bta_hh_get_w4_event(p_cb->w4_evt));
703#endif
704  hs_data.status = BTA_HH_OK;
705  hs_data.handle = p_cb->hid_handle;
706
707  switch (p_cb->w4_evt) {
708    case BTA_HH_GET_IDLE_EVT:
709      hs_data.rsp_data.idle_rate = *data;
710      break;
711    case BTA_HH_GET_RPT_EVT:
712      hs_data.rsp_data.p_rpt_data = pdata;
713      break;
714    case BTA_HH_GET_PROTO_EVT:
715      /* match up BTE/BTA report/boot mode def*/
716      hs_data.rsp_data.proto_mode = ((*data) == HID_PAR_PROTOCOL_REPORT)
717                                        ? BTA_HH_PROTO_RPT_MODE
718                                        : BTA_HH_PROTO_BOOT_MODE;
719#if (BTA_HH_DEBUG == TRUE)
720      APPL_TRACE_DEBUG("GET_PROTOCOL Mode = [%s]",
721                       (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)
722                           ? "Report"
723                           : "Boot");
724#endif
725      break;
726    /* should not expect control DATA for SET_ transaction */
727    case BTA_HH_SET_PROTO_EVT:
728    /* fall through */
729    case BTA_HH_SET_RPT_EVT:
730    /* fall through */
731    case BTA_HH_SET_IDLE_EVT:
732    /* fall through */
733    default:
734#if (BTA_HH_DEBUG == TRUE)
735      APPL_TRACE_DEBUG("invalid  transaction type for DATA payload: 4_evt[%s]",
736                       bta_hh_get_w4_event(p_cb->w4_evt));
737#endif
738      break;
739  }
740
741  /* inform PM for mode change */
742  bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
743  bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
744
745  (*bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH*)&hs_data);
746
747  p_cb->w4_evt = 0;
748  osi_free_and_reset((void**)&pdata);
749}
750
751/*******************************************************************************
752 *
753 * Function         bta_hh_open_failure
754 *
755 * Description      report HID open failure when at wait for connection state
756 *                  and receive device close event.
757 *
758 *
759 * Returns          void
760 *
761 ******************************************************************************/
762void bta_hh_open_failure(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
763  tBTA_HH_CONN conn_dat;
764  uint32_t reason = p_data->hid_cback.data; /* Reason for closing (32-bit) */
765
766  memset(&conn_dat, 0, sizeof(tBTA_HH_CONN));
767  conn_dat.handle = p_cb->hid_handle;
768  conn_dat.status =
769      (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
770  conn_dat.bda = p_cb->addr;
771  HID_HostCloseDev(p_cb->hid_handle);
772
773  /* Report OPEN fail event */
774  (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH*)&conn_dat);
775
776#if (BTA_HH_DEBUG == TRUE)
777  bta_hh_trace_dev_db();
778#endif
779  /* clean up control block, but retain SDP info and device handle */
780  p_cb->vp = false;
781  p_cb->w4_evt = 0;
782
783  /* if no connection is active and HH disable is signaled, disable service */
784  if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable) {
785    bta_hh_disc_cmpl();
786  }
787
788  /* Error in opening hid connection, reset flags */
789  p_cb->incoming_conn = false;
790  p_cb->incoming_hid_handle = BTA_HH_INVALID_HANDLE;
791}
792
793/*******************************************************************************
794 *
795 * Function         bta_hh_close_act
796 *
797 * Description      HID Host process a close event
798 *
799 *
800 * Returns          void
801 *
802 ******************************************************************************/
803void bta_hh_close_act(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
804  tBTA_HH_CONN conn_dat;
805  tBTA_HH_CBDATA disc_dat = {BTA_HH_OK, 0};
806  uint32_t reason = p_data->hid_cback.data; /* Reason for closing (32-bit) */
807
808  /* if HID_HDEV_EVT_VC_UNPLUG was received, report BTA_HH_VC_UNPLUG_EVT */
809  uint16_t event = p_cb->vp ? BTA_HH_VC_UNPLUG_EVT : BTA_HH_CLOSE_EVT;
810
811  disc_dat.handle = p_cb->hid_handle;
812  disc_dat.status = p_data->hid_cback.data;
813
814  /* Check reason for closing */
815  if ((reason & (HID_L2CAP_CONN_FAIL |
816                 HID_L2CAP_REQ_FAIL)) || /* Failure to initialize connection
817                                            (page timeout or l2cap error) */
818      (reason ==
819       HID_ERR_AUTH_FAILED) || /* Authenication error (while initiating) */
820      (reason == HID_ERR_L2CAP_FAILED)) /* Failure creating l2cap connection */
821  {
822    /* Failure in opening connection */
823    conn_dat.handle = p_cb->hid_handle;
824    conn_dat.status =
825        (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
826    conn_dat.bda = p_cb->addr;
827    HID_HostCloseDev(p_cb->hid_handle);
828
829    /* Report OPEN fail event */
830    (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH*)&conn_dat);
831
832#if (BTA_HH_DEBUG == TRUE)
833    bta_hh_trace_dev_db();
834#endif
835    return;
836  }
837  /* otherwise report CLOSE/VC_UNPLUG event */
838  else {
839    /* finaliza device driver */
840    bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
841    /* inform role manager */
842    bta_sys_conn_close(BTA_ID_HH, p_cb->app_id, p_cb->addr);
843    /* update total conn number */
844    bta_hh_cb.cnt_num--;
845
846    if (disc_dat.status) disc_dat.status = BTA_HH_ERR;
847
848    (*bta_hh_cb.p_cback)(event, (tBTA_HH*)&disc_dat);
849
850    /* if virtually unplug, remove device */
851    if (p_cb->vp) {
852      HID_HostRemoveDev(p_cb->hid_handle);
853      bta_hh_clean_up_kdev(p_cb);
854    }
855
856#if (BTA_HH_DEBUG == TRUE)
857    bta_hh_trace_dev_db();
858#endif
859  }
860
861  /* clean up control block, but retain SDP info and device handle */
862  p_cb->vp = false;
863  p_cb->w4_evt = 0;
864
865  /* if no connection is active and HH disable is signaled, disable service */
866  if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable) {
867    bta_hh_disc_cmpl();
868  }
869
870  return;
871}
872
873/*******************************************************************************
874 *
875 * Function         bta_hh_get_dscp_act
876 *
877 * Description      Get device report descriptor
878 *
879 *
880 * Returns          void
881 *
882 ******************************************************************************/
883void bta_hh_get_dscp_act(tBTA_HH_DEV_CB* p_cb,
884                         UNUSED_ATTR tBTA_HH_DATA* p_data) {
885#if (BTA_HH_LE_INCLUDED == TRUE)
886  if (p_cb->is_le_device) {
887    bta_hh_le_get_dscp_act(p_cb);
888  } else
889#endif
890    (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH*)&p_cb->dscp_info);
891}
892
893/*******************************************************************************
894 *
895 * Function         bta_hh_maint_dev_act
896 *
897 * Description      HID Host maintain device list.
898 *
899 *
900 * Returns          void
901 *
902 ******************************************************************************/
903void bta_hh_maint_dev_act(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
904  tBTA_HH_MAINT_DEV* p_dev_info = &p_data->api_maintdev;
905  tBTA_HH_DEV_INFO dev_info;
906  uint8_t dev_handle;
907
908  dev_info.status = BTA_HH_ERR;
909  dev_info.handle = BTA_HH_INVALID_HANDLE;
910
911  switch (p_dev_info->sub_event) {
912    case BTA_HH_ADD_DEV_EVT: /* add a device */
913      dev_info.bda = p_dev_info->bda;
914      /* initialize callback data */
915      if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE) {
916#if (BTA_HH_LE_INCLUDED == TRUE)
917        if (bta_hh_is_le_device(p_cb, p_data->api_conn.bd_addr)) {
918          dev_info.handle = bta_hh_le_add_device(p_cb, p_dev_info);
919          dev_info.status = BTA_HH_OK;
920        } else
921#endif
922
923            if (HID_HostAddDev(p_dev_info->bda, p_dev_info->attr_mask,
924                               &dev_handle) == HID_SUCCESS) {
925          dev_info.handle = dev_handle;
926          dev_info.status = BTA_HH_OK;
927
928#if (BTA_HH_LE_INCLUDED == TRUE)
929          /* update DI information */
930          bta_hh_update_di_info(p_cb, p_dev_info->dscp_info.vendor_id,
931                                p_dev_info->dscp_info.product_id,
932                                p_dev_info->dscp_info.version,
933                                p_dev_info->dscp_info.flag);
934#else
935          bta_hh_update_di_info(p_cb, p_dev_info->dscp_info.vendor_id,
936                                p_dev_info->dscp_info.product_id,
937                                p_dev_info->dscp_info.version, 0);
938
939#endif
940          /* add to BTA device list */
941          bta_hh_add_device_to_list(
942              p_cb, dev_handle, p_dev_info->attr_mask,
943              &p_dev_info->dscp_info.descriptor, p_dev_info->sub_class,
944              p_dev_info->dscp_info.ssr_max_latency,
945              p_dev_info->dscp_info.ssr_min_tout, p_dev_info->app_id);
946          /* update cb_index[] map */
947          bta_hh_cb.cb_index[dev_handle] = p_cb->index;
948        }
949      } else /* device already been added */
950      {
951        dev_info.handle = p_cb->hid_handle;
952        dev_info.status = BTA_HH_OK;
953      }
954#if (BTA_HH_DEBUG == TRUE)
955      bta_hh_trace_dev_db();
956#endif
957
958      break;
959    case BTA_HH_RMV_DEV_EVT: /* remove device */
960      dev_info.handle = (uint8_t)p_dev_info->hdr.layer_specific;
961      dev_info.bda = p_cb->addr;
962
963#if (BTA_HH_LE_INCLUDED == TRUE)
964      if (p_cb->is_le_device) {
965        bta_hh_le_remove_dev_bg_conn(p_cb);
966        bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL);
967        bta_hh_clean_up_kdev(p_cb);
968      } else
969#endif
970      {
971        if (HID_HostRemoveDev(dev_info.handle) == HID_SUCCESS) {
972          dev_info.status = BTA_HH_OK;
973
974          /* remove from known device list in BTA */
975          bta_hh_clean_up_kdev(p_cb);
976        }
977      }
978      break;
979
980    default:
981      APPL_TRACE_DEBUG("invalid command");
982      break;
983  }
984
985  (*bta_hh_cb.p_cback)(p_dev_info->sub_event, (tBTA_HH*)&dev_info);
986}
987/*******************************************************************************
988 *
989 * Function         bta_hh_write_dev_act
990 *
991 * Description      Write device action. can be SET/GET/DATA transaction.
992 *
993 * Returns          void
994 *
995 ******************************************************************************/
996void bta_hh_write_dev_act(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
997  tBTA_HH_CBDATA cbdata = {BTA_HH_OK, 0};
998  uint16_t event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
999                   BTA_HH_FST_TRANS_CB_EVT;
1000
1001#if (BTA_HH_LE_INCLUDED == TRUE)
1002  if (p_cb->is_le_device)
1003    bta_hh_le_write_dev_act(p_cb, p_data);
1004  else
1005#endif
1006  {
1007
1008    cbdata.handle = p_cb->hid_handle;
1009
1010    /* match up BTE/BTA report/boot mode def */
1011    if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL) {
1012      p_data->api_sndcmd.param =
1013          (p_data->api_sndcmd.param == BTA_HH_PROTO_RPT_MODE)
1014              ? HID_PAR_PROTOCOL_REPORT
1015              : HID_PAR_PROTOCOL_BOOT_MODE;
1016    }
1017
1018    if (HID_HostWriteDev(p_cb->hid_handle, p_data->api_sndcmd.t_type,
1019                         p_data->api_sndcmd.param, p_data->api_sndcmd.data,
1020                         p_data->api_sndcmd.rpt_id,
1021                         p_data->api_sndcmd.p_data) != HID_SUCCESS) {
1022      APPL_TRACE_ERROR("HID_HostWriteDev Error ");
1023      cbdata.status = BTA_HH_ERR;
1024
1025      if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL &&
1026          p_data->api_sndcmd.t_type != HID_TRANS_DATA)
1027        (*bta_hh_cb.p_cback)(event, (tBTA_HH*)&cbdata);
1028      else if (p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
1029        (*bta_hh_cb.p_cback)(BTA_HH_VC_UNPLUG_EVT, (tBTA_HH*)&cbdata);
1030    } else {
1031      switch (p_data->api_sndcmd.t_type) {
1032        case HID_TRANS_SET_PROTOCOL:
1033        /* fall through */
1034        case HID_TRANS_GET_REPORT:
1035        /* fall through */
1036        case HID_TRANS_SET_REPORT:
1037        /* fall through */
1038        case HID_TRANS_GET_PROTOCOL:
1039        /* fall through */
1040        case HID_TRANS_GET_IDLE:
1041        /* fall through */
1042        case HID_TRANS_SET_IDLE: /* set w4_handsk event name for callback
1043                                    function use */
1044          p_cb->w4_evt = event;
1045          break;
1046        case HID_TRANS_DATA: /* output report */
1047                             /* fall through */
1048        case HID_TRANS_CONTROL:
1049          /* no handshake event will be generated */
1050          /* if VC_UNPLUG is issued, set flag */
1051          if (p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
1052            p_cb->vp = true;
1053
1054          break;
1055        /* currently not expected */
1056        case HID_TRANS_DATAC:
1057        default:
1058          APPL_TRACE_DEBUG("%s: cmd type = %d", __func__,
1059                           p_data->api_sndcmd.t_type);
1060          break;
1061      }
1062
1063      /* if not control type transaction, notify PM for energy control */
1064      if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL) {
1065        /* inform PM for mode change */
1066        bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
1067        bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
1068      } else if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND) {
1069        bta_sys_sco_close(BTA_ID_HH, p_cb->app_id, p_cb->addr);
1070      } else if (p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND) {
1071        bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
1072      }
1073    }
1074  }
1075  return;
1076}
1077
1078/*****************************************************************************
1079 *  Static Function
1080 ****************************************************************************/
1081/*******************************************************************************
1082 *
1083 * Function         bta_hh_cback
1084 *
1085 * Description      BTA HH callback function.
1086 *
1087 *
1088 * Returns          void
1089 *
1090 ******************************************************************************/
1091static void bta_hh_cback(uint8_t dev_handle, const RawAddress& addr,
1092                         uint8_t event, uint32_t data, BT_HDR* pdata) {
1093  uint16_t sm_event = BTA_HH_INVALID_EVT;
1094  uint8_t xx = 0;
1095
1096#if (BTA_HH_DEBUG == TRUE)
1097  APPL_TRACE_DEBUG("%s::HID_event [%s]", __func__,
1098                   bta_hh_hid_event_name(event));
1099#endif
1100
1101  switch (event) {
1102    case HID_HDEV_EVT_OPEN:
1103      sm_event = BTA_HH_INT_OPEN_EVT;
1104      break;
1105    case HID_HDEV_EVT_CLOSE:
1106      sm_event = BTA_HH_INT_CLOSE_EVT;
1107      break;
1108    case HID_HDEV_EVT_INTR_DATA:
1109      sm_event = BTA_HH_INT_DATA_EVT;
1110      break;
1111    case HID_HDEV_EVT_HANDSHAKE:
1112      sm_event = BTA_HH_INT_HANDSK_EVT;
1113      break;
1114    case HID_HDEV_EVT_CTRL_DATA:
1115      sm_event = BTA_HH_INT_CTRL_DATA;
1116      break;
1117    case HID_HDEV_EVT_RETRYING:
1118      break;
1119    case HID_HDEV_EVT_INTR_DATC:
1120    case HID_HDEV_EVT_CTRL_DATC:
1121      /* Unhandled events: Free buffer for DATAC */
1122      osi_free_and_reset((void**)&pdata);
1123      break;
1124    case HID_HDEV_EVT_VC_UNPLUG:
1125      for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
1126        if (bta_hh_cb.kdev[xx].hid_handle == dev_handle) {
1127          bta_hh_cb.kdev[xx].vp = true;
1128          break;
1129        }
1130      }
1131      break;
1132  }
1133
1134  if (sm_event != BTA_HH_INVALID_EVT) {
1135    tBTA_HH_CBACK_DATA* p_buf = (tBTA_HH_CBACK_DATA*)osi_malloc(
1136        sizeof(tBTA_HH_CBACK_DATA) + sizeof(BT_HDR));
1137    p_buf->hdr.event = sm_event;
1138    p_buf->hdr.layer_specific = (uint16_t)dev_handle;
1139    p_buf->data = data;
1140    p_buf->addr = addr;
1141    p_buf->p_data = pdata;
1142
1143    bta_sys_sendmsg(p_buf);
1144  }
1145}
1146
1147/*******************************************************************************
1148 *
1149 * Function         bta_hh_get_trans_status
1150 *
1151 * Description      translate a handshake result code into BTA HH
1152 *                  status code
1153 *
1154 ******************************************************************************/
1155static tBTA_HH_STATUS bta_hh_get_trans_status(uint32_t result) {
1156  switch (result) {
1157    case HID_PAR_HANDSHAKE_RSP_SUCCESS: /*   (0) */
1158      return BTA_HH_OK;
1159    case HID_PAR_HANDSHAKE_RSP_NOT_READY:           /*   (1) */
1160    case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID:  /*   (2) */
1161    case HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ: /*   (3) */
1162    case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM:   /*   (4) */
1163      return (tBTA_HH_STATUS)result;
1164    case HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN: /*   (14) */
1165    case HID_PAR_HANDSHAKE_RSP_ERR_FATAL:   /*   (15) */
1166    default:
1167      return BTA_HH_HS_ERROR;
1168      break;
1169  }
1170}
1171/*****************************************************************************
1172 *  Debug Functions
1173 ****************************************************************************/
1174
1175#if (BTA_HH_DEBUG == TRUE)
1176static const char* bta_hh_get_w4_event(uint16_t event) {
1177  switch (event) {
1178    case BTA_HH_GET_RPT_EVT:
1179      return "BTA_HH_GET_RPT_EVT";
1180    case BTA_HH_SET_RPT_EVT:
1181      return "BTA_HH_SET_RPT_EVT";
1182    case BTA_HH_GET_PROTO_EVT:
1183      return "BTA_HH_GET_PROTO_EVT";
1184    case BTA_HH_SET_PROTO_EVT:
1185      return "BTA_HH_SET_PROTO_EVT";
1186    case BTA_HH_GET_IDLE_EVT:
1187      return "BTA_HH_GET_IDLE_EVT";
1188    case BTA_HH_SET_IDLE_EVT:
1189      return "BTA_HH_SET_IDLE_EVT";
1190    case BTA_HH_OPEN_EVT:
1191      return "BTA_HH_OPEN_EVT";
1192    default:
1193      return "Unknown event";
1194  }
1195}
1196
1197static const char* bta_hh_hid_event_name(uint16_t event) {
1198  switch (event) {
1199    case HID_HDEV_EVT_OPEN:
1200      return "HID_HDEV_EVT_OPEN";
1201    case HID_HDEV_EVT_CLOSE:
1202      return "HID_HDEV_EVT_CLOSE";
1203    case HID_HDEV_EVT_RETRYING:
1204      return "HID_HDEV_EVT_RETRYING";
1205    case HID_HDEV_EVT_INTR_DATA:
1206      return "HID_HDEV_EVT_INTR_DATA";
1207    case HID_HDEV_EVT_INTR_DATC:
1208      return "HID_HDEV_EVT_INTR_DATC";
1209    case HID_HDEV_EVT_CTRL_DATA:
1210      return "HID_HDEV_EVT_CTRL_DATA";
1211    case HID_HDEV_EVT_CTRL_DATC:
1212      return "HID_HDEV_EVT_CTRL_DATC";
1213    case HID_HDEV_EVT_HANDSHAKE:
1214      return "HID_HDEV_EVT_HANDSHAKE";
1215    case HID_HDEV_EVT_VC_UNPLUG:
1216      return "HID_HDEV_EVT_VC_UNPLUG";
1217    default:
1218      return "Unknown HID event";
1219  }
1220}
1221#endif
1222#endif /* BTA_HH_INCLUDED */
1223