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