1/******************************************************************************
2 *
3 *  Copyright (C) 2009-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 *  Filename:      btif_hh.c
22 *
23 *  Description:   HID Host Profile Bluetooth Interface
24 *
25 *
26 ***********************************************************************************/
27
28#define LOG_TAG "bt_btif_hh"
29
30#include "btif_hh.h"
31
32#include <assert.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <errno.h>
36#include <string.h>
37#include <unistd.h>
38
39#include "bta_api.h"
40#include "btif_common.h"
41#include "btif_storage.h"
42#include "btif_util.h"
43#include "bt_common.h"
44#include "l2c_api.h"
45#include "osi/include/log.h"
46
47#define BTIF_HH_APP_ID_MI       0x01
48#define BTIF_HH_APP_ID_KB       0x02
49
50#define COD_HID_KEYBOARD        0x0540
51#define COD_HID_POINTING        0x0580
52#define COD_HID_COMBO           0x05C0
53
54#define KEYSTATE_FILEPATH "/data/misc/bluedroid/bt_hh_ks" //keep this in sync with HID host jni
55
56#define HID_REPORT_CAPSLOCK   0x39
57#define HID_REPORT_NUMLOCK    0x53
58#define HID_REPORT_SCROLLLOCK 0x47
59
60//For Apple Magic Mouse
61#define MAGICMOUSE_VENDOR_ID 0x05ac
62#define MAGICMOUSE_PRODUCT_ID 0x030d
63
64#define LOGITECH_KB_MX5500_VENDOR_ID  0x046D
65#define LOGITECH_KB_MX5500_PRODUCT_ID 0xB30B
66
67extern fixed_queue_t *btu_general_alarm_queue;
68extern const int BT_UID;
69extern const int BT_GID;
70static int btif_hh_keylockstates=0; //The current key state of each key
71
72#define BTIF_HH_ID_1        0
73#define BTIF_HH_DEV_DISCONNECTED 3
74
75#define BTIF_TIMEOUT_VUP_MS   (3 * 1000)
76
77#ifndef BTUI_HH_SECURITY
78#define BTUI_HH_SECURITY (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)
79#endif
80
81#ifndef BTUI_HH_MOUSE_SECURITY
82#define BTUI_HH_MOUSE_SECURITY (BTA_SEC_NONE)
83#endif
84
85/* HH request events */
86typedef enum
87{
88    BTIF_HH_CONNECT_REQ_EVT = 0,
89    BTIF_HH_DISCONNECT_REQ_EVT,
90    BTIF_HH_VUP_REQ_EVT
91} btif_hh_req_evt_t;
92
93/************************************************************************************
94**  Constants & Macros
95************************************************************************************/
96#define BTIF_HH_SERVICES    (BTA_HID_SERVICE_MASK)
97
98/************************************************************************************
99**  Local type definitions
100************************************************************************************/
101
102typedef struct hid_kb_list
103{
104    UINT16 product_id;
105    UINT16 version_id;
106    char*  kb_name;
107} tHID_KB_LIST;
108
109/************************************************************************************
110**  Static variables
111************************************************************************************/
112btif_hh_cb_t btif_hh_cb;
113
114static bthh_callbacks_t *bt_hh_callbacks = NULL;
115
116/* List of HID keyboards for which the NUMLOCK state needs to be
117 * turned ON by default. Add devices to this list to apply the
118 * NUMLOCK state toggle on fpr first connect.*/
119static tHID_KB_LIST hid_kb_numlock_on_list[] =
120{
121    {LOGITECH_KB_MX5500_PRODUCT_ID,
122    LOGITECH_KB_MX5500_VENDOR_ID,
123    "Logitech MX5500 Keyboard"}
124};
125
126#define CHECK_BTHH_INIT() if (bt_hh_callbacks == NULL)\
127    {\
128        BTIF_TRACE_WARNING("BTHH: %s: BTHH not initialized", __FUNCTION__);\
129        return BT_STATUS_NOT_READY;\
130    }\
131    else\
132    {\
133        BTIF_TRACE_EVENT("BTHH: %s", __FUNCTION__);\
134    }
135
136/************************************************************************************
137**  Static functions
138************************************************************************************/
139
140/************************************************************************************
141**  Externs
142************************************************************************************/
143extern void bta_hh_co_destroy(int fd);
144extern void bta_hh_co_write(int fd, UINT8* rpt, UINT16 len);
145extern bt_status_t btif_dm_remove_bond(const bt_bdaddr_t *bd_addr);
146extern void bta_hh_co_send_hid_info(btif_hh_device_t *p_dev, char *dev_name, UINT16 vendor_id,
147                                    UINT16 product_id, UINT16 version, UINT8 ctry_code,
148                                    int dscp_len, UINT8 *p_dscp);
149extern BOOLEAN check_cod(const bt_bdaddr_t *remote_bdaddr, uint32_t cod);
150extern void btif_dm_cb_remove_bond(bt_bdaddr_t *bd_addr);
151extern BOOLEAN check_cod_hid(const bt_bdaddr_t *remote_bdaddr);
152extern int  scru_ascii_2_hex(char *p_ascii, int len, UINT8 *p_hex);
153extern void btif_dm_hh_open_failed(bt_bdaddr_t *bdaddr);
154
155/*****************************************************************************
156**  Local Function prototypes
157*****************************************************************************/
158static void set_keylockstate(int keymask, BOOLEAN isSet);
159static void toggle_os_keylockstates(int fd, int changedkeystates);
160static void sync_lockstate_on_connect(btif_hh_device_t *p_dev);
161//static void hh_update_keyboard_lockstates(btif_hh_device_t *p_dev);
162void btif_hh_timer_timeout(void *data);
163
164/************************************************************************************
165**  Functions
166************************************************************************************/
167
168static int get_keylockstates()
169{
170    return btif_hh_keylockstates;
171}
172
173static void set_keylockstate(int keymask, BOOLEAN isSet)
174{
175    if(isSet)
176        btif_hh_keylockstates |= keymask;
177}
178
179/*******************************************************************************
180**
181** Function         toggle_os_keylockstates
182**
183** Description      Function to toggle the keyboard lock states managed by the linux.
184**                  This function is used in by two call paths
185**                  (1) if the lock state change occurred from an onscreen keyboard,
186**                  this function is called to update the lock state maintained
187                    for the HID keyboard(s)
188**                  (2) if a HID keyboard is disconnected and reconnected,
189**                  this function is called to update the lock state maintained
190                    for the HID keyboard(s)
191** Returns          void
192*******************************************************************************/
193
194static void toggle_os_keylockstates(int fd, int changedlockstates)
195{
196    BTIF_TRACE_EVENT("%s: fd = %d, changedlockstates = 0x%x",
197        __FUNCTION__, fd, changedlockstates);
198    UINT8 hidreport[9];
199    int reportIndex;
200    memset(hidreport,0,9);
201    hidreport[0]=1;
202    reportIndex=4;
203
204    if (changedlockstates & BTIF_HH_KEYSTATE_MASK_CAPSLOCK) {
205        BTIF_TRACE_DEBUG("%s Setting CAPSLOCK", __FUNCTION__);
206        hidreport[reportIndex++] = (UINT8)HID_REPORT_CAPSLOCK;
207    }
208
209    if (changedlockstates & BTIF_HH_KEYSTATE_MASK_NUMLOCK)  {
210        BTIF_TRACE_DEBUG("%s Setting NUMLOCK", __FUNCTION__);
211        hidreport[reportIndex++] = (UINT8)HID_REPORT_NUMLOCK;
212    }
213
214    if (changedlockstates & BTIF_HH_KEYSTATE_MASK_SCROLLLOCK) {
215        BTIF_TRACE_DEBUG("%s Setting SCROLLLOCK", __FUNCTION__);
216        hidreport[reportIndex++] = (UINT8) HID_REPORT_SCROLLLOCK;
217    }
218
219     BTIF_TRACE_DEBUG("Writing hidreport #1 to os: "\
220        "%s:  %x %x %x", __FUNCTION__,
221         hidreport[0], hidreport[1], hidreport[2]);
222    BTIF_TRACE_DEBUG("%s:  %x %x %x", __FUNCTION__,
223         hidreport[3], hidreport[4], hidreport[5]);
224    BTIF_TRACE_DEBUG("%s:  %x %x %x", __FUNCTION__,
225         hidreport[6], hidreport[7], hidreport[8]);
226    bta_hh_co_write(fd , hidreport, sizeof(hidreport));
227    usleep(200000);
228    memset(hidreport,0,9);
229    hidreport[0]=1;
230    BTIF_TRACE_DEBUG("Writing hidreport #2 to os: "\
231       "%s:  %x %x %x", __FUNCTION__,
232         hidreport[0], hidreport[1], hidreport[2]);
233    BTIF_TRACE_DEBUG("%s:  %x %x %x", __FUNCTION__,
234         hidreport[3], hidreport[4], hidreport[5]);
235    BTIF_TRACE_DEBUG("%s:  %x %x %x ", __FUNCTION__,
236         hidreport[6], hidreport[7], hidreport[8]);
237    bta_hh_co_write(fd , hidreport, sizeof(hidreport));
238}
239
240/*******************************************************************************
241**
242** Function         create_pbuf
243**
244** Description      Helper function to create p_buf for send_data or set_report
245**
246*******************************************************************************/
247static BT_HDR *create_pbuf(UINT16 len, UINT8 *data)
248{
249    BT_HDR* p_buf = osi_malloc(len + BTA_HH_MIN_OFFSET + sizeof(BT_HDR));
250    UINT8* pbuf_data;
251
252    p_buf->len = len;
253    p_buf->offset = BTA_HH_MIN_OFFSET;
254
255    pbuf_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
256    memcpy(pbuf_data, data, len);
257
258    return p_buf;
259}
260
261/*******************************************************************************
262**
263** Function         update_keyboard_lockstates
264**
265** Description      Sends a report to the keyboard to set the lock states of keys
266**
267*******************************************************************************/
268static void update_keyboard_lockstates(btif_hh_device_t *p_dev)
269{
270    UINT8 len = 2;  /* reportid + 1 byte report*/
271    BD_ADDR* bda;
272    BT_HDR* p_buf;
273    UINT8 data[] = {0x01, /* report id */
274                    btif_hh_keylockstates}; /* keystate */
275
276    /* Set report for other keyboards */
277    BTIF_TRACE_EVENT("%s: setting report on dev_handle %d to 0x%x",
278         __FUNCTION__, p_dev->dev_handle, btif_hh_keylockstates);
279
280    /* Get SetReport buffer */
281    p_buf = create_pbuf(len, data);
282    if (p_buf != NULL) {
283        p_buf->layer_specific = BTA_HH_RPTT_OUTPUT;
284        bda = (BD_ADDR*) (&p_dev->bd_addr);
285        BTA_HhSendData(p_dev->dev_handle, *bda, p_buf);
286    }
287}
288
289/*******************************************************************************
290**
291** Function         sync_lockstate_on_connect
292**
293** Description      Function to update the keyboard lock states managed by the OS
294**                  when a HID keyboard is connected or disconnected and reconnected
295** Returns          void
296*******************************************************************************/
297static void sync_lockstate_on_connect(btif_hh_device_t *p_dev)
298{
299    int keylockstates;
300
301    BTIF_TRACE_EVENT("%s: Syncing keyboard lock states after "\
302        "reconnect...",__FUNCTION__);
303    /*If the device is connected, update keyboard state */
304    update_keyboard_lockstates(p_dev);
305
306    /*Check if the lockstate of caps,scroll,num is set.
307     If so, send a report to the kernel
308    so the lockstate is in sync */
309    keylockstates = get_keylockstates();
310    if (keylockstates)
311    {
312        BTIF_TRACE_DEBUG("%s: Sending hid report to kernel "\
313            "indicating lock key state 0x%x",__FUNCTION__,
314            keylockstates);
315        usleep(200000);
316        toggle_os_keylockstates(p_dev->fd, keylockstates);
317    }
318    else
319    {
320        BTIF_TRACE_DEBUG("%s: NOT sending hid report to kernel "\
321            "indicating lock key state 0x%x",__FUNCTION__,
322            keylockstates);
323    }
324}
325
326/*******************************************************************************
327**
328** Function         btif_hh_find_connected_dev_by_handle
329**
330** Description      Return the connected device pointer of the specified device handle
331**
332** Returns          Device entry pointer in the device table
333*******************************************************************************/
334btif_hh_device_t *btif_hh_find_connected_dev_by_handle(UINT8 handle)
335{
336    UINT32 i;
337    for (i = 0; i < BTIF_HH_MAX_HID; i++) {
338        if (btif_hh_cb.devices[i].dev_status == BTHH_CONN_STATE_CONNECTED &&
339            btif_hh_cb.devices[i].dev_handle == handle)
340        {
341            return &btif_hh_cb.devices[i];
342        }
343    }
344    return NULL;
345}
346
347/*******************************************************************************
348**
349** Function         btif_hh_find_dev_by_bda
350**
351** Description      Return the device pointer of the specified bt_bdaddr_t.
352**
353** Returns          Device entry pointer in the device table
354*******************************************************************************/
355static btif_hh_device_t *btif_hh_find_dev_by_bda(bt_bdaddr_t *bd_addr)
356{
357    UINT32 i;
358    for (i = 0; i < BTIF_HH_MAX_HID; i++) {
359        if (btif_hh_cb.devices[i].dev_status != BTHH_CONN_STATE_UNKNOWN &&
360            memcmp(&(btif_hh_cb.devices[i].bd_addr), bd_addr, BD_ADDR_LEN) == 0)
361        {
362            return &btif_hh_cb.devices[i];
363        }
364    }
365    return NULL;
366}
367
368/*******************************************************************************
369**
370** Function         btif_hh_find_connected_dev_by_bda
371**
372** Description      Return the connected device pointer of the specified bt_bdaddr_t.
373**
374** Returns          Device entry pointer in the device table
375*******************************************************************************/
376static btif_hh_device_t *btif_hh_find_connected_dev_by_bda(bt_bdaddr_t *bd_addr)
377{
378    UINT32 i;
379    for (i = 0; i < BTIF_HH_MAX_HID; i++) {
380        if (btif_hh_cb.devices[i].dev_status == BTHH_CONN_STATE_CONNECTED &&
381            memcmp(&(btif_hh_cb.devices[i].bd_addr), bd_addr, BD_ADDR_LEN) == 0)
382        {
383            return &btif_hh_cb.devices[i];
384        }
385    }
386    return NULL;
387}
388
389/*******************************************************************************
390**
391** Function      btif_hh_stop_vup_timer
392**
393** Description  stop vitual unplug timer
394**
395** Returns      void
396*******************************************************************************/
397void btif_hh_stop_vup_timer(bt_bdaddr_t *bd_addr)
398{
399    btif_hh_device_t *p_dev = btif_hh_find_connected_dev_by_bda(bd_addr);
400
401    if (p_dev != NULL) {
402        BTIF_TRACE_DEBUG("stop VUP timer");
403        alarm_free(p_dev->vup_timer);
404        p_dev->vup_timer = NULL;
405    }
406}
407/*******************************************************************************
408**
409** Function      btif_hh_start_vup_timer
410**
411** Description  start virtual unplug timer
412**
413** Returns      void
414*******************************************************************************/
415void btif_hh_start_vup_timer(bt_bdaddr_t *bd_addr)
416{
417    BTIF_TRACE_DEBUG("%s", __func__);
418
419    btif_hh_device_t *p_dev  = btif_hh_find_connected_dev_by_bda(bd_addr);
420    assert(p_dev != NULL);
421
422    alarm_free(p_dev->vup_timer);
423    p_dev->vup_timer = alarm_new("btif_hh.vup_timer");
424    alarm_set_on_queue(p_dev->vup_timer, BTIF_TIMEOUT_VUP_MS,
425                       btif_hh_timer_timeout, p_dev,
426                       btu_general_alarm_queue);
427}
428
429/*******************************************************************************
430**
431** Function         btif_hh_add_added_dev
432**
433** Description      Add a new device to the added device list.
434**
435** Returns          TRUE if add successfully, otherwise FALSE.
436*******************************************************************************/
437BOOLEAN btif_hh_add_added_dev(bt_bdaddr_t bda, tBTA_HH_ATTR_MASK attr_mask)
438{
439    int i;
440    for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
441        if (memcmp(&(btif_hh_cb.added_devices[i].bd_addr), &bda, BD_ADDR_LEN) == 0) {
442            BTIF_TRACE_WARNING(" Device %02X:%02X:%02X:%02X:%02X:%02X already added",
443                  bda.address[0], bda.address[1], bda.address[2], bda.address[3], bda.address[4], bda.address[5]);
444            return FALSE;
445        }
446    }
447    for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
448        if (btif_hh_cb.added_devices[i].bd_addr.address[0] == 0 &&
449            btif_hh_cb.added_devices[i].bd_addr.address[1] == 0 &&
450            btif_hh_cb.added_devices[i].bd_addr.address[2] == 0 &&
451            btif_hh_cb.added_devices[i].bd_addr.address[3] == 0 &&
452            btif_hh_cb.added_devices[i].bd_addr.address[4] == 0 &&
453            btif_hh_cb.added_devices[i].bd_addr.address[5] == 0)
454        {
455            BTIF_TRACE_WARNING(" Added device %02X:%02X:%02X:%02X:%02X:%02X",
456                  bda.address[0], bda.address[1], bda.address[2], bda.address[3], bda.address[4], bda.address[5]);
457            memcpy(&(btif_hh_cb.added_devices[i].bd_addr), &bda, BD_ADDR_LEN);
458            btif_hh_cb.added_devices[i].dev_handle = BTA_HH_INVALID_HANDLE;
459            btif_hh_cb.added_devices[i].attr_mask  = attr_mask;
460            return TRUE;
461        }
462    }
463
464    BTIF_TRACE_WARNING("%s: Error, out of space to add device",__FUNCTION__);
465    return FALSE;
466}
467
468/*******************************************************************************
469 **
470 ** Function         btif_hh_remove_device
471 **
472 ** Description      Remove an added device from the stack.
473 **
474 ** Returns          void
475 *******************************************************************************/
476void btif_hh_remove_device(bt_bdaddr_t bd_addr)
477{
478    int                    i;
479    btif_hh_device_t       *p_dev;
480    btif_hh_added_device_t *p_added_dev;
481
482    LOG_INFO(LOG_TAG, "%s: bda = %02x:%02x:%02x:%02x:%02x:%02x", __FUNCTION__,
483         bd_addr.address[0], bd_addr.address[1], bd_addr.address[2], bd_addr.address[3], bd_addr.address[4], bd_addr.address[5]);
484
485    for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
486        p_added_dev = &btif_hh_cb.added_devices[i];
487        if (memcmp(&(p_added_dev->bd_addr),&bd_addr, 6) == 0) {
488            BTA_HhRemoveDev(p_added_dev->dev_handle);
489            btif_storage_remove_hid_info(&(p_added_dev->bd_addr));
490            memset(&(p_added_dev->bd_addr), 0, 6);
491            p_added_dev->dev_handle = BTA_HH_INVALID_HANDLE;
492            break;
493        }
494    }
495
496    p_dev = btif_hh_find_dev_by_bda(&bd_addr);
497    if (p_dev == NULL) {
498        BTIF_TRACE_WARNING(" Oops, can't find device [%02x:%02x:%02x:%02x:%02x:%02x]",
499             bd_addr.address[0], bd_addr.address[1], bd_addr.address[2], bd_addr.address[3], bd_addr.address[4], bd_addr.address[5]);
500        return;
501    }
502
503    /* need to notify up-layer device is disconnected to avoid state out of sync with up-layer */
504    HAL_CBACK(bt_hh_callbacks, connection_state_cb, &(p_dev->bd_addr), BTHH_CONN_STATE_DISCONNECTED);
505
506    p_dev->dev_status = BTHH_CONN_STATE_UNKNOWN;
507    p_dev->dev_handle = BTA_HH_INVALID_HANDLE;
508    p_dev->ready_for_data = FALSE;
509
510    if (btif_hh_cb.device_num > 0) {
511        btif_hh_cb.device_num--;
512    }
513    else {
514        BTIF_TRACE_WARNING("%s: device_num = 0", __FUNCTION__);
515    }
516
517    p_dev->hh_keep_polling = 0;
518    p_dev->hh_poll_thread_id = -1;
519    BTIF_TRACE_DEBUG("%s: uhid fd = %d", __FUNCTION__, p_dev->fd);
520    if (p_dev->fd >= 0) {
521        bta_hh_co_destroy(p_dev->fd);
522        p_dev->fd = -1;
523    }
524}
525
526BOOLEAN btif_hh_copy_hid_info(tBTA_HH_DEV_DSCP_INFO* dest , tBTA_HH_DEV_DSCP_INFO* src)
527{
528    dest->descriptor.dl_len = 0;
529    if (src->descriptor.dl_len > 0) {
530        dest->descriptor.dsc_list = (UINT8 *)osi_malloc(src->descriptor.dl_len);
531    }
532    memcpy(dest->descriptor.dsc_list, src->descriptor.dsc_list, src->descriptor.dl_len);
533    dest->descriptor.dl_len = src->descriptor.dl_len;
534    dest->vendor_id  = src->vendor_id;
535    dest->product_id = src->product_id;
536    dest->version    = src->version;
537    dest->ctry_code  = src->ctry_code;
538    dest->ssr_max_latency = src->ssr_max_latency;
539    dest->ssr_min_tout = src->ssr_min_tout;
540    return TRUE;
541}
542
543/*******************************************************************************
544**
545** Function         btif_hh_virtual_unplug
546**
547** Description      Virtual unplug initiated from the BTIF thread context
548**                  Special handling for HID mouse-
549**
550** Returns          void
551**
552*******************************************************************************/
553
554bt_status_t btif_hh_virtual_unplug(bt_bdaddr_t *bd_addr)
555{
556    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
557    btif_hh_device_t *p_dev;
558    char bd_str[18];
559    sprintf(bd_str, "%02X:%02X:%02X:%02X:%02X:%02X",
560            bd_addr->address[0],  bd_addr->address[1],  bd_addr->address[2],  bd_addr->address[3],
561            bd_addr->address[4], bd_addr->address[5]);
562    p_dev = btif_hh_find_dev_by_bda(bd_addr);
563    if ((p_dev != NULL) && (p_dev->dev_status == BTHH_CONN_STATE_CONNECTED)
564        && (p_dev->attr_mask & HID_VIRTUAL_CABLE))
565    {
566        BTIF_TRACE_DEBUG("%s Sending BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG", __FUNCTION__);
567        /* start the timer */
568        btif_hh_start_vup_timer(bd_addr);
569        p_dev->local_vup = TRUE;
570        BTA_HhSendCtrl(p_dev->dev_handle, BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG);
571        return BT_STATUS_SUCCESS;
572    }
573    else
574    {
575        BTIF_TRACE_ERROR("%s: Error, device %s not opened.", __FUNCTION__, bd_str);
576        return BT_STATUS_FAIL;
577    }
578}
579
580/*******************************************************************************
581**
582** Function         btif_hh_connect
583**
584** Description      connection initiated from the BTIF thread context
585**
586** Returns          int status
587**
588*******************************************************************************/
589
590bt_status_t btif_hh_connect(bt_bdaddr_t *bd_addr)
591{
592    btif_hh_device_t *dev;
593    btif_hh_added_device_t *added_dev = NULL;
594    char bda_str[20];
595    int i;
596    BD_ADDR *bda = (BD_ADDR*)bd_addr;
597    CHECK_BTHH_INIT();
598    dev = btif_hh_find_dev_by_bda(bd_addr);
599    BTIF_TRACE_DEBUG("Connect _hh");
600    sprintf(bda_str, "%02X:%02X:%02X:%02X:%02X:%02X",
601            (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
602    if (dev == NULL && btif_hh_cb.device_num >= BTIF_HH_MAX_HID) {
603        // No space for more HID device now.
604         BTIF_TRACE_WARNING("%s: Error, exceeded the maximum supported HID device number %d",
605             __FUNCTION__, BTIF_HH_MAX_HID);
606        return BT_STATUS_FAIL;
607    }
608
609    for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
610        if (memcmp(&(btif_hh_cb.added_devices[i].bd_addr), bd_addr, BD_ADDR_LEN) == 0) {
611            added_dev = &btif_hh_cb.added_devices[i];
612             BTIF_TRACE_WARNING("%s: Device %s already added, attr_mask = 0x%x",
613                 __FUNCTION__, bda_str, added_dev->attr_mask);
614        }
615    }
616
617    if (added_dev != NULL) {
618        if (added_dev->dev_handle == BTA_HH_INVALID_HANDLE) {
619            // No space for more HID device now.
620            BTIF_TRACE_ERROR("%s: Error, device %s added but addition failed", __FUNCTION__, bda_str);
621            memset(&(added_dev->bd_addr), 0, 6);
622            added_dev->dev_handle = BTA_HH_INVALID_HANDLE;
623            return BT_STATUS_FAIL;
624        }
625    }
626
627    /* Not checking the NORMALLY_Connectible flags from sdp record, and anyways sending this
628     request from host, for subsequent user initiated connection. If the remote is not in
629     pagescan mode, we will do 2 retries to connect before giving up */
630    tBTA_SEC sec_mask = BTUI_HH_SECURITY;
631    btif_hh_cb.status = BTIF_HH_DEV_CONNECTING;
632    BTA_HhOpen(*bda, BTA_HH_PROTO_RPT_MODE, sec_mask);
633
634    HAL_CBACK(bt_hh_callbacks, connection_state_cb, bd_addr, BTHH_CONN_STATE_CONNECTING);
635    return BT_STATUS_SUCCESS;
636}
637
638/*******************************************************************************
639**
640** Function         btif_hh_disconnect
641**
642** Description      disconnection initiated from the BTIF thread context
643**
644** Returns          void
645**
646*******************************************************************************/
647
648void btif_hh_disconnect(bt_bdaddr_t *bd_addr)
649{
650    btif_hh_device_t *p_dev;
651    p_dev = btif_hh_find_connected_dev_by_bda(bd_addr);
652    if (p_dev != NULL)
653    {
654        BTA_HhClose(p_dev->dev_handle);
655    }
656    else
657        BTIF_TRACE_DEBUG("%s-- Error: device not connected:",__FUNCTION__);
658}
659
660/*******************************************************************************
661**
662** Function         btif_btif_hh_setreport
663**
664** Description      setreport initiated from the BTIF thread context
665**
666** Returns          void
667**
668*******************************************************************************/
669void btif_hh_setreport(btif_hh_device_t *p_dev, bthh_report_type_t r_type, UINT16 size,
670                            UINT8* report)
671{
672    BT_HDR* p_buf = create_pbuf(size, report);
673    if (p_buf == NULL) {
674        APPL_TRACE_ERROR("%s: Error, failed to allocate RPT buffer, size = %d", __FUNCTION__, size);
675        return;
676    }
677    BTA_HhSetReport(p_dev->dev_handle, r_type, p_buf);
678}
679
680/*****************************************************************************
681**   Section name (Group of functions)
682*****************************************************************************/
683
684/*****************************************************************************
685**
686**   btif hh api functions (no context switch)
687**
688*****************************************************************************/
689
690/*******************************************************************************
691**
692** Function         btif_hh_upstreams_evt
693**
694** Description      Executes HH UPSTREAMS events in btif context
695**
696** Returns          void
697**
698*******************************************************************************/
699static void btif_hh_upstreams_evt(UINT16 event, char* p_param)
700{
701    tBTA_HH *p_data = (tBTA_HH *)p_param;
702    btif_hh_device_t *p_dev = NULL;
703    int i;
704    int len, tmplen;
705
706    BTIF_TRACE_DEBUG("%s: event=%s", __FUNCTION__, dump_hh_event(event));
707
708    switch (event)
709    {
710        case BTA_HH_ENABLE_EVT:
711            BTIF_TRACE_DEBUG("%s: BTA_HH_ENABLE_EVT: status =%d",__FUNCTION__, p_data->status);
712            if (p_data->status == BTA_HH_OK) {
713                btif_hh_cb.status = BTIF_HH_ENABLED;
714                BTIF_TRACE_DEBUG("%s--Loading added devices",__FUNCTION__);
715                /* Add hid descriptors for already bonded hid devices*/
716                btif_storage_load_bonded_hid_info();
717            }
718            else {
719                btif_hh_cb.status = BTIF_HH_DISABLED;
720                BTIF_TRACE_WARNING("BTA_HH_ENABLE_EVT: Error, HH enabling failed, status = %d", p_data->status);
721            }
722            break;
723
724        case BTA_HH_DISABLE_EVT:
725            btif_hh_cb.status = BTIF_HH_DISABLED;
726            if (p_data->status == BTA_HH_OK) {
727                int i;
728                // Clear the control block
729                for (i = 0; i < BTIF_HH_MAX_HID; i++) {
730                    alarm_free(btif_hh_cb.devices[i].vup_timer);
731                }
732                memset(&btif_hh_cb, 0, sizeof(btif_hh_cb));
733                for (i = 0; i < BTIF_HH_MAX_HID; i++) {
734                    btif_hh_cb.devices[i].dev_status = BTHH_CONN_STATE_UNKNOWN;
735                }
736            }
737            else
738                BTIF_TRACE_WARNING("BTA_HH_DISABLE_EVT: Error, HH disabling failed, status = %d", p_data->status);
739            break;
740
741        case BTA_HH_OPEN_EVT:
742            BTIF_TRACE_WARNING("%s: BTA_HH_OPN_EVT: handle=%d, status =%d",__FUNCTION__, p_data->conn.handle, p_data->conn.status);
743            if (p_data->conn.status == BTA_HH_OK) {
744                p_dev = btif_hh_find_connected_dev_by_handle(p_data->conn.handle);
745                if (p_dev == NULL) {
746                    BTIF_TRACE_WARNING("BTA_HH_OPEN_EVT: Error, cannot find device with handle %d", p_data->conn.handle);
747                    btif_hh_cb.status = BTIF_HH_DEV_DISCONNECTED;
748                    // The connect request must come from device side and exceeded the connected
749                                   // HID device number.
750                    BTA_HhClose(p_data->conn.handle);
751                    HAL_CBACK(bt_hh_callbacks, connection_state_cb, (bt_bdaddr_t*) &p_data->conn.bda,BTHH_CONN_STATE_DISCONNECTED);
752                }
753                else if (p_dev->fd < 0) {
754                    BTIF_TRACE_WARNING("BTA_HH_OPEN_EVT: Error, failed to find the uhid driver...");
755                    memcpy(&(p_dev->bd_addr), p_data->conn.bda, BD_ADDR_LEN);
756                    //remove the connection  and then try again to reconnect from the mouse side to recover
757                    btif_hh_cb.status = BTIF_HH_DEV_DISCONNECTED;
758                    BTA_HhClose(p_data->conn.handle);
759                }
760                else {
761                    BTIF_TRACE_WARNING("BTA_HH_OPEN_EVT: Found device...Getting dscp info for handle ... %d",p_data->conn.handle);
762                    memcpy(&(p_dev->bd_addr), p_data->conn.bda, BD_ADDR_LEN);
763                    btif_hh_cb.status = BTIF_HH_DEV_CONNECTED;
764                    // Send set_idle if the peer_device is a keyboard
765                    if (check_cod((bt_bdaddr_t*)p_data->conn.bda, COD_HID_KEYBOARD )||
766                                check_cod((bt_bdaddr_t*)p_data->conn.bda, COD_HID_COMBO))
767                        BTA_HhSetIdle(p_data->conn.handle, 0);
768                    btif_hh_cb.p_curr_dev = btif_hh_find_connected_dev_by_handle(p_data->conn.handle);
769                    BTA_HhGetDscpInfo(p_data->conn.handle);
770                    p_dev->dev_status = BTHH_CONN_STATE_CONNECTED;
771                    HAL_CBACK(bt_hh_callbacks, connection_state_cb,&(p_dev->bd_addr), p_dev->dev_status);
772                }
773            }
774            else {
775                bt_bdaddr_t *bdaddr = (bt_bdaddr_t*)p_data->conn.bda;
776                btif_dm_hh_open_failed(bdaddr);
777                p_dev = btif_hh_find_dev_by_bda(bdaddr);
778                if (p_dev != NULL) {
779                    btif_hh_stop_vup_timer(&(p_dev->bd_addr));
780                    if (p_dev->fd >= 0) {
781                        bta_hh_co_destroy(p_dev->fd);
782                        p_dev->fd = -1;
783                    }
784                    p_dev->dev_status = BTHH_CONN_STATE_DISCONNECTED;
785                }
786                HAL_CBACK(bt_hh_callbacks, connection_state_cb, (bt_bdaddr_t*) &p_data->conn.bda,BTHH_CONN_STATE_DISCONNECTED);
787                btif_hh_cb.status = BTIF_HH_DEV_DISCONNECTED;
788            }
789            break;
790
791        case BTA_HH_CLOSE_EVT:
792            BTIF_TRACE_DEBUG("BTA_HH_CLOSE_EVT: status = %d, handle = %d",
793            p_data->dev_status.status, p_data->dev_status.handle);
794            p_dev = btif_hh_find_connected_dev_by_handle(p_data->dev_status.handle);
795            if (p_dev != NULL) {
796                BTIF_TRACE_DEBUG("%s: uhid fd=%d local_vup=%d", __func__, p_dev->fd, p_dev->local_vup);
797                btif_hh_stop_vup_timer(&(p_dev->bd_addr));
798                /* If this is a locally initiated VUP, remove the bond as ACL got
799                 *  disconnected while VUP being processed.
800                 */
801                if (p_dev->local_vup)
802                {
803                    p_dev->local_vup = FALSE;
804                    BTA_DmRemoveDevice((UINT8 *)p_dev->bd_addr.address);
805                }
806
807                btif_hh_cb.status = BTIF_HH_DEV_DISCONNECTED;
808                p_dev->dev_status = BTHH_CONN_STATE_DISCONNECTED;
809
810                if (p_dev->fd >= 0) {
811                    bta_hh_co_destroy(p_dev->fd);
812                    p_dev->fd = -1;
813                }
814                HAL_CBACK(bt_hh_callbacks, connection_state_cb,&(p_dev->bd_addr), p_dev->dev_status);
815            }
816            else {
817                BTIF_TRACE_WARNING("Error: cannot find device with handle %d", p_data->dev_status.handle);
818            }
819            break;
820
821        case BTA_HH_GET_RPT_EVT: {
822            BT_HDR *hdr = p_data->hs_data.rsp_data.p_rpt_data;
823            UINT8 *data = NULL;
824            UINT16 len = 0;
825
826            BTIF_TRACE_DEBUG("BTA_HH_GET_RPT_EVT: status = %d, handle = %d",
827                 p_data->hs_data.status, p_data->hs_data.handle);
828            p_dev = btif_hh_find_connected_dev_by_handle(p_data->hs_data.handle);
829            if (p_dev) {
830                /* p_rpt_data is NULL in HANDSHAKE response case */
831                if (hdr) {
832                    data = (UINT8 *)(hdr + 1) + hdr->offset;
833                    len = hdr->len;
834                    HAL_CBACK(bt_hh_callbacks, get_report_cb,
835                              (bt_bdaddr_t*) &(p_dev->bd_addr),
836                              (bthh_status_t) p_data->hs_data.status, data, len);
837                } else {
838                    HAL_CBACK(bt_hh_callbacks, handshake_cb,
839                              (bt_bdaddr_t*) &(p_dev->bd_addr),
840                              (bthh_status_t) p_data->hs_data.status);
841                }
842            } else {
843                BTIF_TRACE_WARNING("Error: cannot find device with handle %d", p_data->hs_data.handle);
844            }
845            break;
846        }
847
848        case BTA_HH_SET_RPT_EVT:
849            BTIF_TRACE_DEBUG("BTA_HH_SET_RPT_EVT: status = %d, handle = %d",
850            p_data->dev_status.status, p_data->dev_status.handle);
851            p_dev = btif_hh_find_connected_dev_by_handle(p_data->dev_status.handle);
852            if (p_dev != NULL) {
853                HAL_CBACK(bt_hh_callbacks, handshake_cb,
854                          (bt_bdaddr_t*) &(p_dev->bd_addr),
855                          (bthh_status_t) p_data->hs_data.status);
856            }
857            break;
858
859        case BTA_HH_GET_PROTO_EVT:
860            p_dev = btif_hh_find_connected_dev_by_handle(p_data->dev_status.handle);
861            BTIF_TRACE_WARNING("BTA_HH_GET_PROTO_EVT: status = %d, handle = %d, proto = [%d], %s",
862                 p_data->hs_data.status, p_data->hs_data.handle,
863                 p_data->hs_data.rsp_data.proto_mode,
864                 (p_data->hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE) ? "Report Mode" :
865                 (p_data->hs_data.rsp_data.proto_mode == BTA_HH_PROTO_BOOT_MODE) ? "Boot Mode" : "Unsupported");
866            if (p_data->hs_data.rsp_data.proto_mode != BTA_HH_PROTO_UNKNOWN) {
867                HAL_CBACK(bt_hh_callbacks, protocol_mode_cb,
868                          (bt_bdaddr_t*) &(p_dev->bd_addr),
869                          (bthh_status_t)p_data->hs_data.status,
870                          (bthh_protocol_mode_t) p_data->hs_data.rsp_data.proto_mode);
871            } else {
872                HAL_CBACK(bt_hh_callbacks, handshake_cb,
873                          (bt_bdaddr_t*) &(p_dev->bd_addr),
874                          (bthh_status_t)p_data->hs_data.status);
875            }
876            break;
877
878        case BTA_HH_SET_PROTO_EVT:
879            BTIF_TRACE_DEBUG("BTA_HH_SET_PROTO_EVT: status = %d, handle = %d",
880                 p_data->dev_status.status, p_data->dev_status.handle);
881            p_dev = btif_hh_find_connected_dev_by_handle(p_data->dev_status.handle);
882            if (p_dev) {
883                HAL_CBACK(bt_hh_callbacks, handshake_cb,
884                          (bt_bdaddr_t*)&(p_dev->bd_addr),
885                          (bthh_status_t)p_data->hs_data.status);
886            }
887            break;
888
889        case BTA_HH_GET_IDLE_EVT:
890            BTIF_TRACE_DEBUG("BTA_HH_GET_IDLE_EVT: handle = %d, status = %d, rate = %d",
891                 p_data->hs_data.handle, p_data->hs_data.status,
892                 p_data->hs_data.rsp_data.idle_rate);
893            break;
894
895        case BTA_HH_SET_IDLE_EVT:
896            BTIF_TRACE_DEBUG("BTA_HH_SET_IDLE_EVT: status = %d, handle = %d",
897            p_data->dev_status.status, p_data->dev_status.handle);
898            break;
899
900        case BTA_HH_GET_DSCP_EVT:
901            len = p_data->dscp_info.descriptor.dl_len;
902            BTIF_TRACE_DEBUG("BTA_HH_GET_DSCP_EVT: len = %d", len);
903            p_dev = btif_hh_cb.p_curr_dev;
904            if (p_dev == NULL) {
905                BTIF_TRACE_ERROR("BTA_HH_GET_DSCP_EVT: No HID device is currently connected");
906                return;
907            }
908            if (p_dev->fd < 0) {
909                LOG_ERROR(LOG_TAG, "BTA_HH_GET_DSCP_EVT: Error, failed to find the uhid driver...");
910                return;
911            }
912            {
913                char *cached_name = NULL;
914                bt_bdname_t bdname;
915                bt_property_t prop_name;
916                BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME,
917                                           sizeof(bt_bdname_t), &bdname);
918                if (btif_storage_get_remote_device_property(
919                    &p_dev->bd_addr, &prop_name) == BT_STATUS_SUCCESS)
920                {
921                    cached_name = (char *)bdname.name;
922                }
923                else
924                {
925                    cached_name = "Bluetooth HID";
926                }
927
928                BTIF_TRACE_WARNING("%s: name = %s", __FUNCTION__, cached_name);
929                bta_hh_co_send_hid_info(p_dev, cached_name,
930                    p_data->dscp_info.vendor_id, p_data->dscp_info.product_id,
931                    p_data->dscp_info.version,   p_data->dscp_info.ctry_code,
932                    len, p_data->dscp_info.descriptor.dsc_list);
933                if (btif_hh_add_added_dev(p_dev->bd_addr, p_dev->attr_mask)) {
934                    BD_ADDR bda;
935                    bdcpy(bda, p_dev->bd_addr.address);
936                    tBTA_HH_DEV_DSCP_INFO dscp_info;
937                    bt_status_t ret;
938                    bdcpy(bda, p_dev->bd_addr.address);
939                    btif_hh_copy_hid_info(&dscp_info, &p_data->dscp_info);
940                    BTIF_TRACE_DEBUG("BTA_HH_GET_DSCP_EVT:bda = %02x:%02x:%02x:%02x:%02x:%02x",
941                              p_dev->bd_addr.address[0], p_dev->bd_addr.address[1],
942                              p_dev->bd_addr.address[2],p_dev->bd_addr.address[3],
943                              p_dev->bd_addr.address[4], p_dev->bd_addr.address[5]);
944                    BTA_HhAddDev(bda, p_dev->attr_mask,p_dev->sub_class,p_dev->app_id, dscp_info);
945                    // write hid info to nvram
946                    ret = btif_storage_add_hid_device_info(&(p_dev->bd_addr), p_dev->attr_mask,p_dev->sub_class,p_dev->app_id,
947                                                        p_data->dscp_info.vendor_id, p_data->dscp_info.product_id,
948                                                        p_data->dscp_info.version,   p_data->dscp_info.ctry_code,
949                                                        p_data->dscp_info.ssr_max_latency, p_data->dscp_info.ssr_min_tout,
950                                                        len, p_data->dscp_info.descriptor.dsc_list);
951
952                    ASSERTC(ret == BT_STATUS_SUCCESS, "storing hid info failed", ret);
953                    BTIF_TRACE_WARNING("BTA_HH_GET_DSCP_EVT: Called add device");
954
955                    //Free buffer created for dscp_info;
956                    if (dscp_info.descriptor.dl_len >0 && dscp_info.descriptor.dsc_list != NULL)
957                    {
958                        osi_free_and_reset((void **)&dscp_info.descriptor.dsc_list);
959                        dscp_info.descriptor.dl_len = 0;
960                    }
961                }
962                else {
963                    //Device already added.
964                    BTIF_TRACE_WARNING("%s: Device already added ",__FUNCTION__);
965                }
966                /*Sync HID Keyboard lockstates */
967                tmplen = sizeof(hid_kb_numlock_on_list)
968                            / sizeof(tHID_KB_LIST);
969                for(i = 0; i< tmplen; i++)
970                {
971                    if(p_data->dscp_info.vendor_id
972                        == hid_kb_numlock_on_list[i].version_id &&
973                        p_data->dscp_info.product_id
974                        == hid_kb_numlock_on_list[i].product_id)
975                    {
976                        BTIF_TRACE_DEBUG("%s() idx[%d] Enabling "\
977                            "NUMLOCK for device :: %s", __FUNCTION__,
978                            i, hid_kb_numlock_on_list[i].kb_name);
979                        /* Enable NUMLOCK by default so that numeric
980                            keys work from first keyboard connect */
981                        set_keylockstate(BTIF_HH_KEYSTATE_MASK_NUMLOCK,
982                                        TRUE);
983                        sync_lockstate_on_connect(p_dev);
984                        /* End Sync HID Keyboard lockstates */
985                        break;
986                    }
987                }
988            }
989            break;
990
991        case BTA_HH_ADD_DEV_EVT:
992            BTIF_TRACE_WARNING("BTA_HH_ADD_DEV_EVT: status = %d, handle = %d",p_data->dev_info.status, p_data->dev_info.handle);
993            int i;
994            for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
995                if (memcmp(btif_hh_cb.added_devices[i].bd_addr.address, p_data->dev_info.bda, 6) == 0) {
996                    if (p_data->dev_info.status == BTA_HH_OK) {
997                        btif_hh_cb.added_devices[i].dev_handle = p_data->dev_info.handle;
998                    }
999                    else {
1000                        memset(btif_hh_cb.added_devices[i].bd_addr.address, 0, 6);
1001                        btif_hh_cb.added_devices[i].dev_handle = BTA_HH_INVALID_HANDLE;
1002                    }
1003                    break;
1004                }
1005            }
1006            break;
1007        case BTA_HH_RMV_DEV_EVT:
1008                BTIF_TRACE_DEBUG("BTA_HH_RMV_DEV_EVT: status = %d, handle = %d",
1009                     p_data->dev_info.status, p_data->dev_info.handle);
1010                BTIF_TRACE_DEBUG("BTA_HH_RMV_DEV_EVT:bda = %02x:%02x:%02x:%02x:%02x:%02x",
1011                     p_data->dev_info.bda[0], p_data->dev_info.bda[1], p_data->dev_info.bda[2],
1012                     p_data->dev_info.bda[3], p_data->dev_info.bda[4], p_data->dev_info.bda[5]);
1013                break;
1014
1015        case BTA_HH_VC_UNPLUG_EVT:
1016                BTIF_TRACE_DEBUG("BTA_HH_VC_UNPLUG_EVT: status = %d, handle = %d",
1017                     p_data->dev_status.status, p_data->dev_status.handle);
1018                p_dev = btif_hh_find_connected_dev_by_handle(p_data->dev_status.handle);
1019                btif_hh_cb.status = BTIF_HH_DEV_DISCONNECTED;
1020                if (p_dev != NULL) {
1021                    BTIF_TRACE_DEBUG("BTA_HH_VC_UNPLUG_EVT:bda = %02x:%02x:%02x:%02x:%02x:%02x",
1022                         p_dev->bd_addr.address[0], p_dev->bd_addr.address[1],
1023                         p_dev->bd_addr.address[2],p_dev->bd_addr.address[3],
1024                         p_dev->bd_addr.address[4], p_dev->bd_addr.address[5]);
1025                    /* Stop the VUP timer */
1026                    btif_hh_stop_vup_timer(&(p_dev->bd_addr));
1027                    p_dev->dev_status = BTHH_CONN_STATE_DISCONNECTED;
1028                    BTIF_TRACE_DEBUG("%s---Sending connection state change", __FUNCTION__);
1029                    HAL_CBACK(bt_hh_callbacks, connection_state_cb,&(p_dev->bd_addr), p_dev->dev_status);
1030                    BTIF_TRACE_DEBUG("%s---Removing HID bond", __FUNCTION__);
1031                    /* If it is locally initiated VUP or remote device has its major COD as
1032                    Peripheral removed the bond.*/
1033                    if (p_dev->local_vup  || check_cod_hid(&(p_dev->bd_addr)))
1034                    {
1035                        p_dev->local_vup = FALSE;
1036                        BTA_DmRemoveDevice((UINT8 *)p_dev->bd_addr.address);
1037                    }
1038                    else
1039                        btif_hh_remove_device(p_dev->bd_addr);
1040                    HAL_CBACK(bt_hh_callbacks, virtual_unplug_cb,&(p_dev->bd_addr),
1041                                    p_data->dev_status.status);
1042                }
1043                break;
1044
1045        case BTA_HH_API_ERR_EVT  :
1046                LOG_INFO(LOG_TAG, "BTA_HH API_ERR");
1047                break;
1048
1049            default:
1050                BTIF_TRACE_WARNING("%s: Unhandled event: %d", __FUNCTION__, event);
1051                break;
1052        }
1053}
1054
1055/*******************************************************************************
1056**
1057** Function         bte_hh_evt
1058**
1059** Description      Switches context from BTE to BTIF for all HH events
1060**
1061** Returns          void
1062**
1063*******************************************************************************/
1064
1065static void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH *p_data)
1066{
1067    bt_status_t status;
1068    int param_len = 0;
1069
1070    if (BTA_HH_ENABLE_EVT == event)
1071        param_len = sizeof(tBTA_HH_STATUS);
1072    else if (BTA_HH_OPEN_EVT == event)
1073        param_len = sizeof(tBTA_HH_CONN);
1074    else if (BTA_HH_DISABLE_EVT == event)
1075        param_len = sizeof(tBTA_HH_STATUS);
1076    else if (BTA_HH_CLOSE_EVT == event)
1077        param_len = sizeof(tBTA_HH_CBDATA);
1078    else if (BTA_HH_GET_DSCP_EVT == event)
1079        param_len = sizeof(tBTA_HH_DEV_DSCP_INFO);
1080    else if ((BTA_HH_GET_PROTO_EVT == event) || (BTA_HH_GET_RPT_EVT == event)|| (BTA_HH_GET_IDLE_EVT == event))
1081        param_len = sizeof(tBTA_HH_HSDATA);
1082    else if ((BTA_HH_SET_PROTO_EVT == event) || (BTA_HH_SET_RPT_EVT == event) || (BTA_HH_VC_UNPLUG_EVT == event) || (BTA_HH_SET_IDLE_EVT == event))
1083        param_len = sizeof(tBTA_HH_CBDATA);
1084    else if ((BTA_HH_ADD_DEV_EVT == event) || (BTA_HH_RMV_DEV_EVT == event) )
1085        param_len = sizeof(tBTA_HH_DEV_INFO);
1086    else if (BTA_HH_API_ERR_EVT == event)
1087        param_len = 0;
1088    /* switch context to btif task context (copy full union size for convenience) */
1089    status = btif_transfer_context(btif_hh_upstreams_evt, (uint16_t)event, (void*)p_data, param_len, NULL);
1090
1091    /* catch any failed context transfers */
1092    ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
1093}
1094
1095/*******************************************************************************
1096**
1097** Function         btif_hh_handle_evt
1098**
1099** Description      Switches context for immediate callback
1100**
1101** Returns          void
1102**
1103*******************************************************************************/
1104
1105static void btif_hh_handle_evt(UINT16 event, char *p_param)
1106{
1107    bt_bdaddr_t *bd_addr = (bt_bdaddr_t*)p_param;
1108    BTIF_TRACE_EVENT("%s: event=%d", __FUNCTION__, event);
1109    int ret;
1110    switch(event)
1111    {
1112        case BTIF_HH_CONNECT_REQ_EVT:
1113        {
1114            ret = btif_hh_connect(bd_addr);
1115            if(ret == BT_STATUS_SUCCESS)
1116            {
1117                HAL_CBACK(bt_hh_callbacks, connection_state_cb,bd_addr,BTHH_CONN_STATE_CONNECTING);
1118            }
1119            else
1120                HAL_CBACK(bt_hh_callbacks, connection_state_cb,bd_addr,BTHH_CONN_STATE_DISCONNECTED);
1121        }
1122        break;
1123
1124        case BTIF_HH_DISCONNECT_REQ_EVT:
1125        {
1126            BTIF_TRACE_EVENT("%s: event=%d", __FUNCTION__, event);
1127            btif_hh_disconnect(bd_addr);
1128            HAL_CBACK(bt_hh_callbacks, connection_state_cb,bd_addr,BTHH_CONN_STATE_DISCONNECTING);
1129        }
1130        break;
1131
1132        case BTIF_HH_VUP_REQ_EVT:
1133        {
1134            BTIF_TRACE_EVENT("%s: event=%d", __FUNCTION__, event);
1135            ret = btif_hh_virtual_unplug(bd_addr);
1136        }
1137        break;
1138
1139        default:
1140        {
1141            BTIF_TRACE_WARNING("%s : Unknown event 0x%x", __FUNCTION__, event);
1142        }
1143        break;
1144    }
1145}
1146
1147/*******************************************************************************
1148**
1149** Function      btif_hh_timer_timeout
1150**
1151** Description   Process timer timeout
1152**
1153** Returns      void
1154*******************************************************************************/
1155void btif_hh_timer_timeout(void *data)
1156{
1157    btif_hh_device_t *p_dev = (btif_hh_device_t *)data;
1158    tBTA_HH_EVT event = BTA_HH_VC_UNPLUG_EVT;
1159    tBTA_HH p_data;
1160    int param_len = sizeof(tBTA_HH_CBDATA);
1161
1162    BTIF_TRACE_DEBUG("%s",  __func__);
1163    if (p_dev->dev_status != BTHH_CONN_STATE_CONNECTED)
1164        return;
1165
1166    memset(&p_data, 0, sizeof(tBTA_HH));
1167    p_data.dev_status.status = BTHH_ERR;
1168    p_data.dev_status.handle = p_dev->dev_handle;
1169
1170    /* switch context to btif task context */
1171    btif_transfer_context(btif_hh_upstreams_evt, (uint16_t)event,
1172                          (char *)&p_data, param_len, NULL);
1173}
1174
1175/*******************************************************************************
1176**
1177** Function         btif_hh_init
1178**
1179** Description     initializes the hh interface
1180**
1181** Returns         bt_status_t
1182**
1183*******************************************************************************/
1184static bt_status_t init( bthh_callbacks_t* callbacks )
1185{
1186    UINT32 i;
1187    BTIF_TRACE_EVENT("%s", __FUNCTION__);
1188
1189    bt_hh_callbacks = callbacks;
1190    memset(&btif_hh_cb, 0, sizeof(btif_hh_cb));
1191    for (i = 0; i < BTIF_HH_MAX_HID; i++){
1192        btif_hh_cb.devices[i].dev_status = BTHH_CONN_STATE_UNKNOWN;
1193    }
1194    /* Invoke the enable service API to the core to set the appropriate service_id */
1195    btif_enable_service(BTA_HID_SERVICE_ID);
1196    return BT_STATUS_SUCCESS;
1197}
1198
1199/*******************************************************************************
1200**
1201** Function        connect
1202**
1203** Description     connect to hid device
1204**
1205** Returns         bt_status_t
1206**
1207*******************************************************************************/
1208static bt_status_t connect( bt_bdaddr_t *bd_addr)
1209{
1210    if(btif_hh_cb.status != BTIF_HH_DEV_CONNECTING)
1211    {
1212        btif_transfer_context(btif_hh_handle_evt, BTIF_HH_CONNECT_REQ_EVT,
1213                                 (char*)bd_addr, sizeof(bt_bdaddr_t), NULL);
1214        return BT_STATUS_SUCCESS;
1215    }
1216    else
1217        return BT_STATUS_BUSY;
1218}
1219
1220/*******************************************************************************
1221**
1222** Function         disconnect
1223**
1224** Description      disconnect from hid device
1225**
1226** Returns         bt_status_t
1227**
1228*******************************************************************************/
1229static bt_status_t disconnect( bt_bdaddr_t *bd_addr )
1230{
1231    CHECK_BTHH_INIT();
1232    btif_hh_device_t *p_dev;
1233
1234    if (btif_hh_cb.status == BTIF_HH_DISABLED)
1235    {
1236        BTIF_TRACE_WARNING("%s: Error, HH status = %d", __FUNCTION__, btif_hh_cb.status);
1237        return BT_STATUS_FAIL;
1238    }
1239    p_dev = btif_hh_find_connected_dev_by_bda(bd_addr);
1240    if (p_dev != NULL)
1241    {
1242        return btif_transfer_context(btif_hh_handle_evt, BTIF_HH_DISCONNECT_REQ_EVT,
1243                     (char*)bd_addr, sizeof(bt_bdaddr_t), NULL);
1244    }
1245    else
1246    {
1247        BTIF_TRACE_WARNING("%s: Error, device  not opened.", __FUNCTION__);
1248        return BT_STATUS_FAIL;
1249    }
1250}
1251
1252/*******************************************************************************
1253**
1254** Function         virtual_unplug
1255**
1256** Description      Virtual UnPlug (VUP) the specified HID device.
1257**
1258** Returns         bt_status_t
1259**
1260*******************************************************************************/
1261static bt_status_t virtual_unplug (bt_bdaddr_t *bd_addr)
1262{
1263    CHECK_BTHH_INIT();
1264    btif_hh_device_t *p_dev;
1265    char bd_str[18];
1266    sprintf(bd_str, "%02X:%02X:%02X:%02X:%02X:%02X",
1267            bd_addr->address[0],  bd_addr->address[1],  bd_addr->address[2],  bd_addr->address[3],
1268            bd_addr->address[4], bd_addr->address[5]);
1269    if (btif_hh_cb.status == BTIF_HH_DISABLED)
1270    {
1271        BTIF_TRACE_ERROR("%s: Error, HH status = %d", __FUNCTION__, btif_hh_cb.status);
1272        return BT_STATUS_FAIL;
1273    }
1274    p_dev = btif_hh_find_dev_by_bda(bd_addr);
1275    if (!p_dev)
1276    {
1277        BTIF_TRACE_ERROR("%s: Error, device %s not opened.", __FUNCTION__, bd_str);
1278        return BT_STATUS_FAIL;
1279    }
1280    btif_transfer_context(btif_hh_handle_evt, BTIF_HH_VUP_REQ_EVT,
1281                                 (char*)bd_addr, sizeof(bt_bdaddr_t), NULL);
1282    return BT_STATUS_SUCCESS;
1283}
1284
1285/*******************************************************************************
1286**
1287** Function         set_info
1288**
1289** Description      Set the HID device descriptor for the specified HID device.
1290**
1291** Returns         bt_status_t
1292**
1293*******************************************************************************/
1294static bt_status_t set_info (bt_bdaddr_t *bd_addr, bthh_hid_info_t hid_info )
1295{
1296    CHECK_BTHH_INIT();
1297    tBTA_HH_DEV_DSCP_INFO dscp_info;
1298    BD_ADDR* bda = (BD_ADDR*) bd_addr;
1299
1300    BTIF_TRACE_DEBUG("addr = %02X:%02X:%02X:%02X:%02X:%02X",
1301         (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
1302    BTIF_TRACE_DEBUG("%s: sub_class = 0x%02x, app_id = %d, vendor_id = 0x%04x, "
1303         "product_id = 0x%04x, version= 0x%04x",
1304         __FUNCTION__, hid_info.sub_class,
1305         hid_info.app_id, hid_info.vendor_id, hid_info.product_id,
1306         hid_info.version);
1307
1308    if (btif_hh_cb.status == BTIF_HH_DISABLED)
1309    {
1310        BTIF_TRACE_ERROR("%s: Error, HH status = %d", __FUNCTION__, btif_hh_cb.status);
1311        return BT_STATUS_FAIL;
1312    }
1313
1314    dscp_info.vendor_id  = hid_info.vendor_id;
1315    dscp_info.product_id = hid_info.product_id;
1316    dscp_info.version    = hid_info.version;
1317    dscp_info.ctry_code  = hid_info.ctry_code;
1318
1319    dscp_info.descriptor.dl_len = hid_info.dl_len;
1320    dscp_info.descriptor.dsc_list = (UINT8 *)osi_malloc(dscp_info.descriptor.dl_len);
1321    memcpy(dscp_info.descriptor.dsc_list, &(hid_info.dsc_list), hid_info.dl_len);
1322
1323    if (btif_hh_add_added_dev(*bd_addr, hid_info.attr_mask))
1324    {
1325        BTA_HhAddDev(*bda, hid_info.attr_mask, hid_info.sub_class,
1326                     hid_info.app_id, dscp_info);
1327    }
1328
1329    osi_free_and_reset((void **)&dscp_info.descriptor.dsc_list);
1330
1331    return BT_STATUS_SUCCESS;
1332}
1333
1334/*******************************************************************************
1335**
1336** Function         get_protocol
1337**
1338** Description      Get the HID proto mode.
1339**
1340** Returns         bt_status_t
1341**
1342*******************************************************************************/
1343static bt_status_t get_protocol (bt_bdaddr_t *bd_addr, bthh_protocol_mode_t protocolMode)
1344{
1345    CHECK_BTHH_INIT();
1346    btif_hh_device_t *p_dev;
1347    BD_ADDR* bda = (BD_ADDR*) bd_addr;
1348    UNUSED(protocolMode);
1349
1350    BTIF_TRACE_DEBUG(" addr = %02X:%02X:%02X:%02X:%02X:%02X",
1351         (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
1352
1353    if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1354        BTIF_TRACE_ERROR("%s: Error, HH status = %d", __FUNCTION__, btif_hh_cb.status);
1355        return BT_STATUS_FAIL;
1356    }
1357
1358    p_dev = btif_hh_find_connected_dev_by_bda(bd_addr);
1359    if (p_dev != NULL) {
1360
1361        BTA_HhGetProtoMode(p_dev->dev_handle);
1362    }
1363    else {
1364        return BT_STATUS_FAIL;
1365    }
1366    return BT_STATUS_SUCCESS;
1367}
1368
1369/*******************************************************************************
1370**
1371** Function         set_protocol
1372**
1373** Description      Set the HID proto mode.
1374**
1375** Returns         bt_status_t
1376**
1377*******************************************************************************/
1378static bt_status_t set_protocol (bt_bdaddr_t *bd_addr, bthh_protocol_mode_t protocolMode)
1379{
1380    CHECK_BTHH_INIT();
1381    btif_hh_device_t *p_dev;
1382    UINT8 proto_mode = protocolMode;
1383    BD_ADDR* bda = (BD_ADDR*) bd_addr;
1384
1385    BTIF_TRACE_DEBUG("%s:proto_mode = %d", __FUNCTION__,protocolMode);
1386
1387    BTIF_TRACE_DEBUG("addr = %02X:%02X:%02X:%02X:%02X:%02X",
1388         (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
1389
1390    if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1391        BTIF_TRACE_ERROR("%s: Error, HH status = %d", __FUNCTION__, btif_hh_cb.status);
1392        return BT_STATUS_FAIL;
1393    }
1394
1395    p_dev = btif_hh_find_connected_dev_by_bda(bd_addr);
1396    if (p_dev == NULL) {
1397        BTIF_TRACE_WARNING(" Error, device %02X:%02X:%02X:%02X:%02X:%02X not opened.",
1398             (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
1399        return BT_STATUS_FAIL;
1400    }
1401    else if (protocolMode != BTA_HH_PROTO_RPT_MODE && protocolMode != BTA_HH_PROTO_BOOT_MODE) {
1402        BTIF_TRACE_WARNING("%s: Error, device proto_mode = %d.", __func__, proto_mode);
1403        return BT_STATUS_FAIL;
1404    }
1405    else {
1406        BTA_HhSetProtoMode(p_dev->dev_handle, protocolMode);
1407    }
1408
1409    return BT_STATUS_SUCCESS;
1410}
1411
1412/*******************************************************************************
1413**
1414** Function         get_report
1415**
1416** Description      Send a GET_REPORT to HID device.
1417**
1418** Returns         bt_status_t
1419**
1420*******************************************************************************/
1421static bt_status_t get_report (bt_bdaddr_t *bd_addr, bthh_report_type_t reportType, uint8_t reportId, int bufferSize)
1422{
1423    CHECK_BTHH_INIT();
1424    btif_hh_device_t *p_dev;
1425    BD_ADDR* bda = (BD_ADDR*) bd_addr;
1426
1427    BTIF_TRACE_DEBUG("%s: r_type = %d, rpt_id = %d, buf_size = %d", __func__,
1428          reportType, reportId, bufferSize);
1429
1430    BTIF_TRACE_DEBUG("addr = %02X:%02X:%02X:%02X:%02X:%02X",
1431         (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
1432
1433    if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1434        BTIF_TRACE_ERROR("%s: Error, HH status = %d", __FUNCTION__, btif_hh_cb.status);
1435        return BT_STATUS_FAIL;
1436    }
1437
1438    p_dev = btif_hh_find_connected_dev_by_bda(bd_addr);
1439    if (p_dev == NULL) {
1440        BTIF_TRACE_ERROR("%s: Error, device %02X:%02X:%02X:%02X:%02X:%02X not opened.", __func__,
1441             (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
1442        return BT_STATUS_FAIL;
1443    }
1444    else if ( ((int) reportType) <= BTA_HH_RPTT_RESRV || ((int) reportType) > BTA_HH_RPTT_FEATURE) {
1445        BTIF_TRACE_ERROR(" Error, device %02X:%02X:%02X:%02X:%02X:%02X not opened.",
1446             (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
1447        return BT_STATUS_FAIL;
1448    }
1449    else {
1450        BTA_HhGetReport(p_dev->dev_handle, reportType,
1451                        reportId, bufferSize);
1452    }
1453
1454    return BT_STATUS_SUCCESS;
1455}
1456
1457/*******************************************************************************
1458**
1459** Function         set_report
1460**
1461** Description      Send a SET_REPORT to HID device.
1462**
1463** Returns         bt_status_t
1464**
1465*******************************************************************************/
1466static bt_status_t set_report (bt_bdaddr_t *bd_addr, bthh_report_type_t reportType, char* report)
1467{
1468    CHECK_BTHH_INIT();
1469    btif_hh_device_t *p_dev;
1470    BD_ADDR* bda = (BD_ADDR*) bd_addr;
1471
1472    BTIF_TRACE_DEBUG("%s:reportType = %d", __FUNCTION__,reportType);
1473
1474    BTIF_TRACE_DEBUG("addr = %02X:%02X:%02X:%02X:%02X:%02X",
1475         (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
1476
1477    if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1478        BTIF_TRACE_ERROR("%s: Error, HH status = %d", __FUNCTION__, btif_hh_cb.status);
1479        return BT_STATUS_FAIL;
1480    }
1481
1482    p_dev = btif_hh_find_connected_dev_by_bda(bd_addr);
1483    if (p_dev == NULL) {
1484        BTIF_TRACE_ERROR("%s: Error, device %02X:%02X:%02X:%02X:%02X:%02X not opened.", __func__,
1485             (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
1486        return BT_STATUS_FAIL;
1487    }
1488    else if ( ( (int) reportType) <= BTA_HH_RPTT_RESRV || ( (int) reportType) > BTA_HH_RPTT_FEATURE) {
1489        BTIF_TRACE_ERROR(" Error, device %02X:%02X:%02X:%02X:%02X:%02X not opened.",
1490             (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
1491        return BT_STATUS_FAIL;
1492    }
1493    else {
1494        int    hex_bytes_filled;
1495        size_t len = (strlen(report) + 1) / 2;
1496        UINT8  *hexbuf = osi_calloc(len);
1497
1498        /* Build a SetReport data buffer */
1499        //TODO
1500        hex_bytes_filled = ascii_2_hex(report, len, hexbuf);
1501        LOG_INFO(LOG_TAG, "Hex bytes filled, hex value: %d", hex_bytes_filled);
1502        if (hex_bytes_filled) {
1503            BT_HDR* p_buf = create_pbuf(hex_bytes_filled, hexbuf);
1504            if (p_buf == NULL) {
1505                BTIF_TRACE_ERROR("%s: Error, failed to allocate RPT buffer, len = %d",
1506                                  __FUNCTION__, hex_bytes_filled);
1507                osi_free(hexbuf);
1508                return BT_STATUS_FAIL;
1509            }
1510            BTA_HhSetReport(p_dev->dev_handle, reportType, p_buf);
1511            osi_free(hexbuf);
1512            return BT_STATUS_SUCCESS;
1513        }
1514        osi_free(hexbuf);
1515        return BT_STATUS_FAIL;
1516    }
1517}
1518
1519/*******************************************************************************
1520**
1521** Function         send_data
1522**
1523** Description      Send a SEND_DATA to HID device.
1524**
1525** Returns         bt_status_t
1526**
1527*******************************************************************************/
1528static bt_status_t send_data (bt_bdaddr_t *bd_addr, char* data)
1529{
1530    CHECK_BTHH_INIT();
1531    btif_hh_device_t *p_dev;
1532    BD_ADDR* bda = (BD_ADDR*) bd_addr;
1533
1534    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
1535
1536    BTIF_TRACE_DEBUG("addr = %02X:%02X:%02X:%02X:%02X:%02X",
1537         (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
1538
1539    if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1540        BTIF_TRACE_ERROR("%s: Error, HH status = %d", __FUNCTION__, btif_hh_cb.status);
1541        return BT_STATUS_FAIL;
1542    }
1543
1544    p_dev = btif_hh_find_connected_dev_by_bda(bd_addr);
1545    if (p_dev == NULL) {
1546        BTIF_TRACE_ERROR("%s: Error, device %02X:%02X:%02X:%02X:%02X:%02X not opened.", __func__,
1547             (*bda)[0], (*bda)[1], (*bda)[2], (*bda)[3], (*bda)[4], (*bda)[5]);
1548        return BT_STATUS_FAIL;
1549    }
1550
1551    else {
1552        int    hex_bytes_filled;
1553        size_t len = (strlen(data) + 1) / 2;
1554        UINT8 *hexbuf = osi_calloc(len);
1555
1556        /* Build a SendData data buffer */
1557        hex_bytes_filled = ascii_2_hex(data, len, hexbuf);
1558        BTIF_TRACE_ERROR("Hex bytes filled, hex value: %d, %d", hex_bytes_filled, len);
1559
1560        if (hex_bytes_filled) {
1561            BT_HDR* p_buf = create_pbuf(hex_bytes_filled, hexbuf);
1562            if (p_buf == NULL) {
1563                BTIF_TRACE_ERROR("%s: Error, failed to allocate RPT buffer, len = %d",
1564                                  __FUNCTION__, hex_bytes_filled);
1565                osi_free(hexbuf);
1566                return BT_STATUS_FAIL;
1567            }
1568            p_buf->layer_specific = BTA_HH_RPTT_OUTPUT;
1569            BTA_HhSendData(p_dev->dev_handle, *bda, p_buf);
1570            osi_free(hexbuf);
1571            return BT_STATUS_SUCCESS;
1572        }
1573        osi_free(hexbuf);
1574        return BT_STATUS_FAIL;
1575    }
1576}
1577
1578/*******************************************************************************
1579**
1580** Function         cleanup
1581**
1582** Description      Closes the HH interface
1583**
1584** Returns          bt_status_t
1585**
1586*******************************************************************************/
1587static void  cleanup( void )
1588{
1589    BTIF_TRACE_EVENT("%s", __FUNCTION__);
1590    btif_hh_device_t *p_dev;
1591    int i;
1592    if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1593        BTIF_TRACE_WARNING("%s: HH disabling or disabled already, status = %d", __FUNCTION__, btif_hh_cb.status);
1594        return;
1595    }
1596    btif_hh_cb.status = BTIF_HH_DISABLING;
1597    for (i = 0; i < BTIF_HH_MAX_HID; i++) {
1598         p_dev = &btif_hh_cb.devices[i];
1599         if (p_dev->dev_status != BTHH_CONN_STATE_UNKNOWN && p_dev->fd >= 0) {
1600             BTIF_TRACE_DEBUG("%s: Closing uhid fd = %d", __FUNCTION__, p_dev->fd);
1601             if (p_dev->fd >= 0) {
1602                 bta_hh_co_destroy(p_dev->fd);
1603                 p_dev->fd = -1;
1604             }
1605             p_dev->hh_keep_polling = 0;
1606             p_dev->hh_poll_thread_id = -1;
1607         }
1608     }
1609
1610    if (bt_hh_callbacks)
1611    {
1612        btif_disable_service(BTA_HID_SERVICE_ID);
1613        bt_hh_callbacks = NULL;
1614    }
1615
1616}
1617
1618static const bthh_interface_t bthhInterface = {
1619    sizeof(bthhInterface),
1620    init,
1621    connect,
1622    disconnect,
1623    virtual_unplug,
1624    set_info,
1625    get_protocol,
1626    set_protocol,
1627//    get_idle_time,
1628//    set_idle_time,
1629    get_report,
1630    set_report,
1631    send_data,
1632    cleanup,
1633};
1634
1635/*******************************************************************************
1636**
1637** Function         btif_hh_execute_service
1638**
1639** Description      Initializes/Shuts down the service
1640**
1641** Returns          BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
1642**
1643*******************************************************************************/
1644bt_status_t btif_hh_execute_service(BOOLEAN b_enable)
1645{
1646     if (b_enable)
1647     {
1648          /* Enable and register with BTA-HH */
1649          BTA_HhEnable(BTUI_HH_SECURITY, bte_hh_evt);
1650     }
1651     else {
1652         /* Disable HH */
1653         BTA_HhDisable();
1654     }
1655     return BT_STATUS_SUCCESS;
1656}
1657
1658/*******************************************************************************
1659**
1660** Function         btif_hh_get_interface
1661**
1662** Description      Get the hh callback interface
1663**
1664** Returns          bthh_interface_t
1665**
1666*******************************************************************************/
1667const bthh_interface_t *btif_hh_get_interface()
1668{
1669    BTIF_TRACE_EVENT("%s", __FUNCTION__);
1670    return &bthhInterface;
1671}
1672