blob: 5ce9bb2e3cb24d0e184f8c9566c47a13cc2e0af1 [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
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
Myles Watsonee96a3c2016-11-23 14:49:54 -080019/*******************************************************************************
The Android Open Source Project5738f832012-12-12 16:00:35 -080020 *
21 * Filename: btif_hh.c
22 *
23 * Description: HID Host Profile Bluetooth Interface
24 *
25 *
Myles Watsonee96a3c2016-11-23 14:49:54 -080026 ******************************************************************************/
Marie Janssendb554582015-06-26 14:53:46 -070027
Marie Janssen49120dc2015-07-07 16:47:20 -070028#define LOG_TAG "bt_btif_hh"
29
Marie Janssen49a86702015-07-08 11:48:57 -070030#include "btif_hh.h"
31
Jack Hef2af1c42016-12-13 01:59:12 -080032#include <base/logging.h>
Myles Watson6bd442f2016-10-19 09:50:22 -070033#include <errno.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080034#include <stdio.h>
35#include <stdlib.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080036#include <string.h>
Arman Ugurayd30195c2015-05-29 15:27:58 -070037#include <unistd.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080038
Myles Watson6bd442f2016-10-19 09:50:22 -070039#include "bt_common.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080040#include "bta_api.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080041#include "btif_common.h"
Marie Janssendb554582015-06-26 14:53:46 -070042#include "btif_storage.h"
43#include "btif_util.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080044#include "l2c_api.h"
Sharvil Nanavati44802762014-12-23 23:08:58 -080045#include "osi/include/log.h"
Myles Watsond7ffd642016-10-27 10:27:36 -070046#include "osi/include/osi.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080047
Myles Watson6bd442f2016-10-19 09:50:22 -070048#define BTIF_HH_APP_ID_MI 0x01
49#define BTIF_HH_APP_ID_KB 0x02
The Android Open Source Project5738f832012-12-12 16:00:35 -080050
Myles Watson6bd442f2016-10-19 09:50:22 -070051#define COD_HID_KEYBOARD 0x0540
52#define COD_HID_POINTING 0x0580
53#define COD_HID_COMBO 0x05C0
The Android Open Source Project5738f832012-12-12 16:00:35 -080054
Myles Watson6bd442f2016-10-19 09:50:22 -070055#define KEYSTATE_FILEPATH \
56 "/data/misc/bluedroid/bt_hh_ks" // keep this in sync with HID host jni
The Android Open Source Project5738f832012-12-12 16:00:35 -080057
Myles Watson6bd442f2016-10-19 09:50:22 -070058#define HID_REPORT_CAPSLOCK 0x39
59#define HID_REPORT_NUMLOCK 0x53
The Android Open Source Project5738f832012-12-12 16:00:35 -080060#define HID_REPORT_SCROLLLOCK 0x47
61
Myles Watson6bd442f2016-10-19 09:50:22 -070062// For Apple Magic Mouse
The Android Open Source Project5738f832012-12-12 16:00:35 -080063#define MAGICMOUSE_VENDOR_ID 0x05ac
64#define MAGICMOUSE_PRODUCT_ID 0x030d
65
Myles Watson6bd442f2016-10-19 09:50:22 -070066#define LOGITECH_KB_MX5500_VENDOR_ID 0x046D
The Android Open Source Project5738f832012-12-12 16:00:35 -080067#define LOGITECH_KB_MX5500_PRODUCT_ID 0xB30B
68
Myles Watson6bd442f2016-10-19 09:50:22 -070069extern fixed_queue_t* btu_general_alarm_queue;
The Android Open Source Project5738f832012-12-12 16:00:35 -080070extern const int BT_UID;
71extern const int BT_GID;
Myles Watson6bd442f2016-10-19 09:50:22 -070072static int btif_hh_keylockstates = 0; // The current key state of each key
The Android Open Source Project5738f832012-12-12 16:00:35 -080073
Myles Watson6bd442f2016-10-19 09:50:22 -070074#define BTIF_HH_ID_1 0
The Android Open Source Project5738f832012-12-12 16:00:35 -080075#define BTIF_HH_DEV_DISCONNECTED 3
76
Myles Watson6bd442f2016-10-19 09:50:22 -070077#define BTIF_TIMEOUT_VUP_MS (3 * 1000)
Ganesh Ganapathi Batta33af35c2013-04-09 16:33:31 -070078
The Android Open Source Project5738f832012-12-12 16:00:35 -080079#ifndef BTUI_HH_SECURITY
80#define BTUI_HH_SECURITY (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)
81#endif
82
83#ifndef BTUI_HH_MOUSE_SECURITY
84#define BTUI_HH_MOUSE_SECURITY (BTA_SEC_NONE)
85#endif
86
87/* HH request events */
Myles Watson6bd442f2016-10-19 09:50:22 -070088typedef enum {
89 BTIF_HH_CONNECT_REQ_EVT = 0,
90 BTIF_HH_DISCONNECT_REQ_EVT,
91 BTIF_HH_VUP_REQ_EVT
The Android Open Source Project5738f832012-12-12 16:00:35 -080092} btif_hh_req_evt_t;
93
Myles Watsonee96a3c2016-11-23 14:49:54 -080094/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -070095 * Constants & Macros
Myles Watsonee96a3c2016-11-23 14:49:54 -080096 ******************************************************************************/
Myles Watson6bd442f2016-10-19 09:50:22 -070097#define BTIF_HH_SERVICES (BTA_HID_SERVICE_MASK)
The Android Open Source Project5738f832012-12-12 16:00:35 -080098
Myles Watsonee96a3c2016-11-23 14:49:54 -080099/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700100 * Local type definitions
Myles Watsonee96a3c2016-11-23 14:49:54 -0800101 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800102
Myles Watson6bd442f2016-10-19 09:50:22 -0700103typedef struct hid_kb_list {
104 uint16_t product_id;
105 uint16_t version_id;
106 const char* kb_name;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800107} tHID_KB_LIST;
108
Myles Watsonee96a3c2016-11-23 14:49:54 -0800109/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700110 * Static variables
Myles Watsonee96a3c2016-11-23 14:49:54 -0800111 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800112btif_hh_cb_t btif_hh_cb;
113
Myles Watson6bd442f2016-10-19 09:50:22 -0700114static bthh_callbacks_t* bt_hh_callbacks = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800115
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.*/
Myles Watson6bd442f2016-10-19 09:50:22 -0700119static tHID_KB_LIST hid_kb_numlock_on_list[] = {{LOGITECH_KB_MX5500_PRODUCT_ID,
120 LOGITECH_KB_MX5500_VENDOR_ID,
121 "Logitech MX5500 Keyboard"}};
The Android Open Source Project5738f832012-12-12 16:00:35 -0800122
Myles Watson40cde562016-10-21 09:39:13 -0700123#define CHECK_BTHH_INIT() \
124 do { \
125 if (bt_hh_callbacks == NULL) { \
126 BTIF_TRACE_WARNING("BTHH: %s: BTHH not initialized", __func__); \
127 return BT_STATUS_NOT_READY; \
Myles Watson40cde562016-10-21 09:39:13 -0700128 } \
129 } while (0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800130
Myles Watsonee96a3c2016-11-23 14:49:54 -0800131/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700132 * Static functions
Myles Watsonee96a3c2016-11-23 14:49:54 -0800133 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800134
Myles Watsonee96a3c2016-11-23 14:49:54 -0800135/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700136 * Externs
Myles Watsonee96a3c2016-11-23 14:49:54 -0800137 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800138extern void bta_hh_co_destroy(int fd);
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700139extern void bta_hh_co_write(int fd, uint8_t* rpt, uint16_t len);
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700140extern bt_status_t btif_dm_remove_bond(const RawAddress* bd_addr);
Myles Watson6bd442f2016-10-19 09:50:22 -0700141extern void bta_hh_co_send_hid_info(btif_hh_device_t* p_dev,
142 const char* dev_name, uint16_t vendor_id,
143 uint16_t product_id, uint16_t version,
144 uint8_t ctry_code, int dscp_len,
145 uint8_t* p_dscp);
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700146extern bool check_cod(const RawAddress* remote_bdaddr, uint32_t cod);
147extern void btif_dm_cb_remove_bond(const RawAddress* bd_addr);
148extern bool check_cod_hid(const RawAddress* remote_bdaddr);
Myles Watson6bd442f2016-10-19 09:50:22 -0700149extern int scru_ascii_2_hex(char* p_ascii, int len, uint8_t* p_hex);
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700150extern void btif_dm_hh_open_failed(RawAddress* bdaddr);
Hemant Gupta8843cc82014-04-18 12:34:55 +0530151extern void btif_hd_service_registration();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800152
153/*****************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700154 * Local Function prototypes
155 ****************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700156static void set_keylockstate(int keymask, bool isSet);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800157static void toggle_os_keylockstates(int fd, int changedkeystates);
Myles Watson6bd442f2016-10-19 09:50:22 -0700158static void sync_lockstate_on_connect(btif_hh_device_t* p_dev);
159// static void hh_update_keyboard_lockstates(btif_hh_device_t *p_dev);
160void btif_hh_timer_timeout(void* data);
Hemant Gupta8843cc82014-04-18 12:34:55 +0530161void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800162
Myles Watsonee96a3c2016-11-23 14:49:54 -0800163/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700164 * Functions
Myles Watsonee96a3c2016-11-23 14:49:54 -0800165 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800166
Myles Watson6bd442f2016-10-19 09:50:22 -0700167static int get_keylockstates() { return btif_hh_keylockstates; }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800168
Myles Watson6bd442f2016-10-19 09:50:22 -0700169static void set_keylockstate(int keymask, bool isSet) {
170 if (isSet) btif_hh_keylockstates |= keymask;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800171}
172
173/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700174 *
175 * Function toggle_os_keylockstates
176 *
177 * Description Function to toggle the keyboard lock states managed by the
178 linux.
179 * This function is used in by two call paths
180 * (1) if the lock state change occurred from an onscreen
181 keyboard,
182 * this function is called to update the lock state maintained
The Android Open Source Project5738f832012-12-12 16:00:35 -0800183 for the HID keyboard(s)
Myles Watson6bd442f2016-10-19 09:50:22 -0700184 * (2) if a HID keyboard is disconnected and reconnected,
185 * this function is called to update the lock state maintained
The Android Open Source Project5738f832012-12-12 16:00:35 -0800186 for the HID keyboard(s)
Myles Watson6bd442f2016-10-19 09:50:22 -0700187 * Returns void
188 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800189
Myles Watson6bd442f2016-10-19 09:50:22 -0700190static void toggle_os_keylockstates(int fd, int changedlockstates) {
191 BTIF_TRACE_EVENT("%s: fd = %d, changedlockstates = 0x%x", __func__, fd,
192 changedlockstates);
193 uint8_t hidreport[9];
194 int reportIndex;
195 memset(hidreport, 0, 9);
196 hidreport[0] = 1;
197 reportIndex = 4;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800198
Myles Watson6bd442f2016-10-19 09:50:22 -0700199 if (changedlockstates & BTIF_HH_KEYSTATE_MASK_CAPSLOCK) {
200 BTIF_TRACE_DEBUG("%s Setting CAPSLOCK", __func__);
201 hidreport[reportIndex++] = (uint8_t)HID_REPORT_CAPSLOCK;
202 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800203
Myles Watson6bd442f2016-10-19 09:50:22 -0700204 if (changedlockstates & BTIF_HH_KEYSTATE_MASK_NUMLOCK) {
205 BTIF_TRACE_DEBUG("%s Setting NUMLOCK", __func__);
206 hidreport[reportIndex++] = (uint8_t)HID_REPORT_NUMLOCK;
207 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800208
Myles Watson6bd442f2016-10-19 09:50:22 -0700209 if (changedlockstates & BTIF_HH_KEYSTATE_MASK_SCROLLLOCK) {
210 BTIF_TRACE_DEBUG("%s Setting SCROLLLOCK", __func__);
211 hidreport[reportIndex++] = (uint8_t)HID_REPORT_SCROLLLOCK;
212 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800213
Myles Watson6bd442f2016-10-19 09:50:22 -0700214 BTIF_TRACE_DEBUG(
215 "Writing hidreport #1 to os: "
216 "%s: %x %x %x",
217 __func__, hidreport[0], hidreport[1], hidreport[2]);
218 BTIF_TRACE_DEBUG("%s: %x %x %x", __func__, hidreport[3], hidreport[4],
219 hidreport[5]);
220 BTIF_TRACE_DEBUG("%s: %x %x %x", __func__, hidreport[6], hidreport[7],
221 hidreport[8]);
222 bta_hh_co_write(fd, hidreport, sizeof(hidreport));
223 usleep(200000);
224 memset(hidreport, 0, 9);
225 hidreport[0] = 1;
226 BTIF_TRACE_DEBUG(
227 "Writing hidreport #2 to os: "
228 "%s: %x %x %x",
229 __func__, hidreport[0], hidreport[1], hidreport[2]);
230 BTIF_TRACE_DEBUG("%s: %x %x %x", __func__, hidreport[3], hidreport[4],
231 hidreport[5]);
232 BTIF_TRACE_DEBUG("%s: %x %x %x ", __func__, hidreport[6], hidreport[7],
233 hidreport[8]);
234 bta_hh_co_write(fd, hidreport, sizeof(hidreport));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800235}
236
237/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700238 *
239 * Function create_pbuf
240 *
241 * Description Helper function to create p_buf for send_data or set_report
242 *
243 ******************************************************************************/
244static BT_HDR* create_pbuf(uint16_t len, uint8_t* data) {
245 BT_HDR* p_buf = (BT_HDR*)osi_malloc(len + BTA_HH_MIN_OFFSET + sizeof(BT_HDR));
246 uint8_t* pbuf_data;
Mike J. Chenbe6d58f2014-02-24 18:07:14 -0800247
Myles Watson6bd442f2016-10-19 09:50:22 -0700248 p_buf->len = len;
249 p_buf->offset = BTA_HH_MIN_OFFSET;
Mike J. Chenbe6d58f2014-02-24 18:07:14 -0800250
Myles Watson6bd442f2016-10-19 09:50:22 -0700251 pbuf_data = (uint8_t*)(p_buf + 1) + p_buf->offset;
252 memcpy(pbuf_data, data, len);
Mike J. Chenbe6d58f2014-02-24 18:07:14 -0800253
Myles Watson6bd442f2016-10-19 09:50:22 -0700254 return p_buf;
Mike J. Chenbe6d58f2014-02-24 18:07:14 -0800255}
256
257/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700258 *
259 * Function update_keyboard_lockstates
260 *
261 * Description Sends a report to the keyboard to set the lock states of
Myles Watsonf4548162016-10-19 09:53:56 -0700262 * keys.
Myles Watson6bd442f2016-10-19 09:50:22 -0700263 *
264 ******************************************************************************/
265static void update_keyboard_lockstates(btif_hh_device_t* p_dev) {
266 uint8_t len = 2; /* reportid + 1 byte report*/
Myles Watson6bd442f2016-10-19 09:50:22 -0700267 BT_HDR* p_buf;
268 uint8_t data[] = {0x01, /* report id */
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700269 static_cast<uint8_t>(btif_hh_keylockstates)}; /* keystate */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800270
Myles Watson6bd442f2016-10-19 09:50:22 -0700271 /* Set report for other keyboards */
272 BTIF_TRACE_EVENT("%s: setting report on dev_handle %d to 0x%x", __func__,
273 p_dev->dev_handle, btif_hh_keylockstates);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800274
Myles Watson6bd442f2016-10-19 09:50:22 -0700275 /* Get SetReport buffer */
276 p_buf = create_pbuf(len, data);
277 if (p_buf != NULL) {
278 p_buf->layer_specific = BTA_HH_RPTT_OUTPUT;
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700279 BTA_HhSendData(p_dev->dev_handle, p_dev->bd_addr, p_buf);
Myles Watson6bd442f2016-10-19 09:50:22 -0700280 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800281}
282
283/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700284 *
285 * Function sync_lockstate_on_connect
286 *
287 * Description Function to update the keyboard lock states managed by the
Myles Watsonf4548162016-10-19 09:53:56 -0700288 * OS when a HID keyboard is connected or disconnected and
289 * reconnected
290 *
Myles Watson6bd442f2016-10-19 09:50:22 -0700291 * Returns void
292 ******************************************************************************/
293static void sync_lockstate_on_connect(btif_hh_device_t* p_dev) {
294 int keylockstates;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800295
Myles Watson6bd442f2016-10-19 09:50:22 -0700296 BTIF_TRACE_EVENT(
297 "%s: Syncing keyboard lock states after "
298 "reconnect...",
299 __func__);
300 /*If the device is connected, update keyboard state */
301 update_keyboard_lockstates(p_dev);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800302
Myles Watson6bd442f2016-10-19 09:50:22 -0700303 /*Check if the lockstate of caps,scroll,num is set.
304 If so, send a report to the kernel
305 so the lockstate is in sync */
306 keylockstates = get_keylockstates();
307 if (keylockstates) {
308 BTIF_TRACE_DEBUG(
309 "%s: Sending hid report to kernel "
310 "indicating lock key state 0x%x",
311 __func__, keylockstates);
312 usleep(200000);
313 toggle_os_keylockstates(p_dev->fd, keylockstates);
314 } else {
315 BTIF_TRACE_DEBUG(
316 "%s: NOT sending hid report to kernel "
317 "indicating lock key state 0x%x",
318 __func__, keylockstates);
319 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800320}
321
322/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700323 *
324 * Function btif_hh_find_connected_dev_by_handle
325 *
326 * Description Return the connected device pointer of the specified device
Myles Watsonf4548162016-10-19 09:53:56 -0700327 * handle
Myles Watson6bd442f2016-10-19 09:50:22 -0700328 *
329 * Returns Device entry pointer in the device table
330 ******************************************************************************/
331btif_hh_device_t* btif_hh_find_connected_dev_by_handle(uint8_t handle) {
332 uint32_t i;
333 for (i = 0; i < BTIF_HH_MAX_HID; i++) {
334 if (btif_hh_cb.devices[i].dev_status == BTHH_CONN_STATE_CONNECTED &&
335 btif_hh_cb.devices[i].dev_handle == handle) {
336 return &btif_hh_cb.devices[i];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800337 }
Myles Watson6bd442f2016-10-19 09:50:22 -0700338 }
339 return NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800340}
341
342/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700343 *
344 * Function btif_hh_find_dev_by_bda
345 *
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700346 * Description Return the device pointer of the specified RawAddress.
Myles Watson6bd442f2016-10-19 09:50:22 -0700347 *
348 * Returns Device entry pointer in the device table
349 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700350static btif_hh_device_t* btif_hh_find_dev_by_bda(const RawAddress& bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700351 uint32_t i;
352 for (i = 0; i < BTIF_HH_MAX_HID; i++) {
353 if (btif_hh_cb.devices[i].dev_status != BTHH_CONN_STATE_UNKNOWN &&
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700354 btif_hh_cb.devices[i].bd_addr == bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700355 return &btif_hh_cb.devices[i];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800356 }
Myles Watson6bd442f2016-10-19 09:50:22 -0700357 }
358 return NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800359}
360
361/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700362 *
363 * Function btif_hh_find_connected_dev_by_bda
364 *
365 * Description Return the connected device pointer of the specified
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700366 * RawAddress.
Myles Watson6bd442f2016-10-19 09:50:22 -0700367 *
368 * Returns Device entry pointer in the device table
369 ******************************************************************************/
370static btif_hh_device_t* btif_hh_find_connected_dev_by_bda(
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700371 const RawAddress& bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700372 uint32_t i;
373 for (i = 0; i < BTIF_HH_MAX_HID; i++) {
374 if (btif_hh_cb.devices[i].dev_status == BTHH_CONN_STATE_CONNECTED &&
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700375 btif_hh_cb.devices[i].bd_addr == bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700376 return &btif_hh_cb.devices[i];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800377 }
Myles Watson6bd442f2016-10-19 09:50:22 -0700378 }
379 return NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800380}
381
382/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700383 *
384 * Function btif_hh_stop_vup_timer
385 *
386 * Description stop vitual unplug timer
387 *
388 * Returns void
389 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700390void btif_hh_stop_vup_timer(RawAddress* bd_addr) {
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700391 btif_hh_device_t* p_dev = btif_hh_find_connected_dev_by_bda(*bd_addr);
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800392
Myles Watson6bd442f2016-10-19 09:50:22 -0700393 if (p_dev != NULL) {
394 BTIF_TRACE_DEBUG("stop VUP timer");
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800395 alarm_free(p_dev->vup_timer);
Myles Watson6bd442f2016-10-19 09:50:22 -0700396 p_dev->vup_timer = NULL;
397 }
398}
399/*******************************************************************************
400 *
401 * Function btif_hh_start_vup_timer
402 *
403 * Description start virtual unplug timer
404 *
405 * Returns void
406 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700407void btif_hh_start_vup_timer(const RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700408 BTIF_TRACE_DEBUG("%s", __func__);
409
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700410 btif_hh_device_t* p_dev = btif_hh_find_connected_dev_by_bda(*bd_addr);
Jack Hef2af1c42016-12-13 01:59:12 -0800411 CHECK(p_dev != NULL);
Myles Watson6bd442f2016-10-19 09:50:22 -0700412
413 alarm_free(p_dev->vup_timer);
414 p_dev->vup_timer = alarm_new("btif_hh.vup_timer");
415 alarm_set_on_queue(p_dev->vup_timer, BTIF_TIMEOUT_VUP_MS,
416 btif_hh_timer_timeout, p_dev, btu_general_alarm_queue);
Ganesh Ganapathi Batta33af35c2013-04-09 16:33:31 -0700417}
418
419/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -0700420 *
421 * Function btif_hh_add_added_dev
422 *
423 * Description Add a new device to the added device list.
424 *
425 * Returns true if add successfully, otherwise false.
426 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700427bool btif_hh_add_added_dev(const RawAddress& bda, tBTA_HH_ATTR_MASK attr_mask) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700428 int i;
429 for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700430 if (btif_hh_cb.added_devices[i].bd_addr == bda) {
431 LOG(WARNING) << " Device " << bda << " already added";
Myles Watson6bd442f2016-10-19 09:50:22 -0700432 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800433 }
Myles Watson6bd442f2016-10-19 09:50:22 -0700434 }
435 for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
Jakub Pawlowskib707f442017-07-03 15:39:36 -0700436 if (btif_hh_cb.added_devices[i].bd_addr.IsEmpty()) {
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700437 LOG(WARNING) << " Added device " << bda;
438 btif_hh_cb.added_devices[i].bd_addr = bda;
Myles Watson6bd442f2016-10-19 09:50:22 -0700439 btif_hh_cb.added_devices[i].dev_handle = BTA_HH_INVALID_HANDLE;
440 btif_hh_cb.added_devices[i].attr_mask = attr_mask;
441 return true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800442 }
Myles Watson6bd442f2016-10-19 09:50:22 -0700443 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800444
Myles Watson6bd442f2016-10-19 09:50:22 -0700445 BTIF_TRACE_WARNING("%s: Error, out of space to add device", __func__);
446 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800447}
448
449/*******************************************************************************
450 **
451 ** Function btif_hh_remove_device
452 **
453 ** Description Remove an added device from the stack.
454 **
455 ** Returns void
Myles Watsonee96a3c2016-11-23 14:49:54 -0800456 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700457void btif_hh_remove_device(RawAddress bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700458 int i;
459 btif_hh_device_t* p_dev;
460 btif_hh_added_device_t* p_added_dev;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800461
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700462 LOG(INFO) << __func__ << ": bda = " << bd_addr;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800463
Myles Watson6bd442f2016-10-19 09:50:22 -0700464 for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
465 p_added_dev = &btif_hh_cb.added_devices[i];
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700466 if (p_added_dev->bd_addr == bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700467 BTA_HhRemoveDev(p_added_dev->dev_handle);
468 btif_storage_remove_hid_info(&(p_added_dev->bd_addr));
469 memset(&(p_added_dev->bd_addr), 0, 6);
470 p_added_dev->dev_handle = BTA_HH_INVALID_HANDLE;
471 break;
472 }
473 }
474
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700475 p_dev = btif_hh_find_dev_by_bda(bd_addr);
Myles Watson6bd442f2016-10-19 09:50:22 -0700476 if (p_dev == NULL) {
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700477 LOG(WARNING) << " Oops, can't find device " << bd_addr;
Myles Watson6bd442f2016-10-19 09:50:22 -0700478 return;
479 }
480
481 /* need to notify up-layer device is disconnected to avoid state out of sync
482 * with up-layer */
483 HAL_CBACK(bt_hh_callbacks, connection_state_cb, &(p_dev->bd_addr),
484 BTHH_CONN_STATE_DISCONNECTED);
485
486 p_dev->dev_status = BTHH_CONN_STATE_UNKNOWN;
487 p_dev->dev_handle = BTA_HH_INVALID_HANDLE;
488 p_dev->ready_for_data = false;
489
490 if (btif_hh_cb.device_num > 0) {
491 btif_hh_cb.device_num--;
492 } else {
493 BTIF_TRACE_WARNING("%s: device_num = 0", __func__);
494 }
495
496 p_dev->hh_keep_polling = 0;
497 p_dev->hh_poll_thread_id = -1;
498 BTIF_TRACE_DEBUG("%s: uhid fd = %d", __func__, p_dev->fd);
499 if (p_dev->fd >= 0) {
500 bta_hh_co_destroy(p_dev->fd);
501 p_dev->fd = -1;
502 }
503}
504
505bool btif_hh_copy_hid_info(tBTA_HH_DEV_DSCP_INFO* dest,
506 tBTA_HH_DEV_DSCP_INFO* src) {
507 dest->descriptor.dl_len = 0;
508 if (src->descriptor.dl_len > 0) {
509 dest->descriptor.dsc_list = (uint8_t*)osi_malloc(src->descriptor.dl_len);
510 }
511 memcpy(dest->descriptor.dsc_list, src->descriptor.dsc_list,
512 src->descriptor.dl_len);
513 dest->descriptor.dl_len = src->descriptor.dl_len;
514 dest->vendor_id = src->vendor_id;
515 dest->product_id = src->product_id;
516 dest->version = src->version;
517 dest->ctry_code = src->ctry_code;
518 dest->ssr_max_latency = src->ssr_max_latency;
519 dest->ssr_min_tout = src->ssr_min_tout;
520 return true;
521}
522
523/*******************************************************************************
524 *
525 * Function btif_hh_virtual_unplug
526 *
527 * Description Virtual unplug initiated from the BTIF thread context
528 * Special handling for HID mouse-
529 *
530 * Returns void
531 *
532 ******************************************************************************/
533
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700534bt_status_t btif_hh_virtual_unplug(const RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700535 BTIF_TRACE_DEBUG("%s", __func__);
536 btif_hh_device_t* p_dev;
537 char bd_str[18];
538 snprintf(bd_str, sizeof(bd_str), "%02X:%02X:%02X:%02X:%02X:%02X",
539 bd_addr->address[0], bd_addr->address[1], bd_addr->address[2],
540 bd_addr->address[3], bd_addr->address[4], bd_addr->address[5]);
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700541 p_dev = btif_hh_find_dev_by_bda(*bd_addr);
Myles Watson6bd442f2016-10-19 09:50:22 -0700542 if ((p_dev != NULL) && (p_dev->dev_status == BTHH_CONN_STATE_CONNECTED) &&
543 (p_dev->attr_mask & HID_VIRTUAL_CABLE)) {
544 BTIF_TRACE_DEBUG("%s Sending BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG", __func__);
545 /* start the timer */
546 btif_hh_start_vup_timer(bd_addr);
547 p_dev->local_vup = true;
548 BTA_HhSendCtrl(p_dev->dev_handle, BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG);
549 return BT_STATUS_SUCCESS;
550 } else {
551 BTIF_TRACE_ERROR("%s: Error, device %s not opened.", __func__, bd_str);
552 return BT_STATUS_FAIL;
553 }
554}
555
556/*******************************************************************************
557 *
558 * Function btif_hh_connect
559 *
560 * Description connection initiated from the BTIF thread context
561 *
562 * Returns int status
563 *
564 ******************************************************************************/
565
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700566bt_status_t btif_hh_connect(const RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700567 btif_hh_added_device_t* added_dev = NULL;
Myles Watson6bd442f2016-10-19 09:50:22 -0700568 CHECK_BTHH_INIT();
Marie Janssenc338fe82017-02-01 12:50:00 -0800569 BTIF_TRACE_EVENT("BTHH: %s", __func__);
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700570 btif_hh_device_t* dev = btif_hh_find_dev_by_bda(*bd_addr);
571 if (!dev && btif_hh_cb.device_num >= BTIF_HH_MAX_HID) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700572 // No space for more HID device now.
573 BTIF_TRACE_WARNING(
574 "%s: Error, exceeded the maximum supported HID device number %d",
575 __func__, BTIF_HH_MAX_HID);
576 return BT_STATUS_FAIL;
577 }
578
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700579 for (int i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
580 if (btif_hh_cb.added_devices[i].bd_addr == *bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700581 added_dev = &btif_hh_cb.added_devices[i];
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700582 LOG(WARNING) << __func__ << ": Device " << *bd_addr
583 << " already added, attr_mask = 0x" << std::hex
584 << added_dev->attr_mask;
Myles Watson6bd442f2016-10-19 09:50:22 -0700585 }
586 }
587
588 if (added_dev != NULL) {
589 if (added_dev->dev_handle == BTA_HH_INVALID_HANDLE) {
590 // No space for more HID device now.
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700591 LOG(ERROR) << __func__ << ": Error, device " << *bd_addr
592 << " added but addition failed";
Jakub Pawlowskib707f442017-07-03 15:39:36 -0700593 added_dev->bd_addr = RawAddress::kEmpty;
Myles Watson6bd442f2016-10-19 09:50:22 -0700594 added_dev->dev_handle = BTA_HH_INVALID_HANDLE;
595 return BT_STATUS_FAIL;
596 }
597 }
598
599 /* Not checking the NORMALLY_Connectible flags from sdp record, and anyways
600 sending this
601 request from host, for subsequent user initiated connection. If the remote is
602 not in
603 pagescan mode, we will do 2 retries to connect before giving up */
604 tBTA_SEC sec_mask = BTUI_HH_SECURITY;
605 btif_hh_cb.status = BTIF_HH_DEV_CONNECTING;
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700606 BTA_HhOpen(*bd_addr, BTA_HH_PROTO_RPT_MODE, sec_mask);
Myles Watson6bd442f2016-10-19 09:50:22 -0700607
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700608 // TODO(jpawlowski); make cback accept const and remove tmp!
609 auto tmp = *bd_addr;
610 HAL_CBACK(bt_hh_callbacks, connection_state_cb, &tmp,
Myles Watson6bd442f2016-10-19 09:50:22 -0700611 BTHH_CONN_STATE_CONNECTING);
612 return BT_STATUS_SUCCESS;
613}
614
615/*******************************************************************************
616 *
617 * Function btif_hh_disconnect
618 *
619 * Description disconnection initiated from the BTIF thread context
620 *
621 * Returns void
622 *
623 ******************************************************************************/
624
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700625void btif_hh_disconnect(RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700626 btif_hh_device_t* p_dev;
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700627 p_dev = btif_hh_find_connected_dev_by_bda(*bd_addr);
Myles Watson6bd442f2016-10-19 09:50:22 -0700628 if (p_dev != NULL) {
629 BTA_HhClose(p_dev->dev_handle);
630 } else
631 BTIF_TRACE_DEBUG("%s-- Error: device not connected:", __func__);
632}
633
634/*******************************************************************************
635 *
636 * Function btif_btif_hh_setreport
637 *
638 * Description setreport initiated from the BTIF thread context
639 *
640 * Returns void
641 *
642 ******************************************************************************/
643void btif_hh_setreport(btif_hh_device_t* p_dev, bthh_report_type_t r_type,
644 uint16_t size, uint8_t* report) {
645 BT_HDR* p_buf = create_pbuf(size, report);
646 if (p_buf == NULL) {
647 APPL_TRACE_ERROR("%s: Error, failed to allocate RPT buffer, size = %d",
648 __func__, size);
649 return;
650 }
651 BTA_HhSetReport(p_dev->dev_handle, r_type, p_buf);
652}
653
Hemant Gupta8843cc82014-04-18 12:34:55 +0530654/*******************************************************************************
655 *
656 * Function btif_hh_service_registration
657 *
658 * Description Registers or derigisters the hid host service
659 *
660 * Returns none
661 *
662 ******************************************************************************/
663void btif_hh_service_registration(bool enable) {
664 BTIF_TRACE_API("%s", __func__);
665
666 BTIF_TRACE_API("enable = %d", enable);
Ivan Podogov2a399b32017-01-03 12:29:45 +0000667 if (bt_hh_callbacks == NULL) {
668 // The HID Host service was never initialized (it is either disabled or not
669 // available in this build). We should proceed directly to changing the HID
670 // Device service state (if needed).
671 if (!enable) {
672 btif_hd_service_registration();
673 }
674 } else if (enable) {
Hemant Gupta8843cc82014-04-18 12:34:55 +0530675 BTA_HhEnable(BTA_SEC_ENCRYPT, bte_hh_evt);
676 } else {
677 btif_hh_cb.service_dereg_active = TRUE;
678 BTA_HhDisable();
679 }
680}
681
Myles Watson6bd442f2016-10-19 09:50:22 -0700682/*****************************************************************************
683 * Section name (Group of functions)
684 ****************************************************************************/
685
686/*****************************************************************************
687 *
688 * btif hh api functions (no context switch)
689 *
690 ****************************************************************************/
691
692/*******************************************************************************
693 *
694 * Function btif_hh_upstreams_evt
695 *
696 * Description Executes HH UPSTREAMS events in btif context
697 *
698 * Returns void
699 *
700 ******************************************************************************/
701static void btif_hh_upstreams_evt(uint16_t event, char* p_param) {
702 tBTA_HH* p_data = (tBTA_HH*)p_param;
703 btif_hh_device_t* p_dev = NULL;
704 int i;
705 int len, tmplen;
706
Hemant Gupta8843cc82014-04-18 12:34:55 +0530707 BTIF_TRACE_DEBUG("%s: event=%s dereg = %d", __func__, dump_hh_event(event),
708 btif_hh_cb.service_dereg_active);
Myles Watson6bd442f2016-10-19 09:50:22 -0700709
710 switch (event) {
711 case BTA_HH_ENABLE_EVT:
712 BTIF_TRACE_DEBUG("%s: BTA_HH_ENABLE_EVT: status =%d", __func__,
713 p_data->status);
714 if (p_data->status == BTA_HH_OK) {
715 btif_hh_cb.status = BTIF_HH_ENABLED;
716 BTIF_TRACE_DEBUG("%s--Loading added devices", __func__);
717 /* Add hid descriptors for already bonded hid devices*/
718 btif_storage_load_bonded_hid_info();
719 } else {
720 btif_hh_cb.status = BTIF_HH_DISABLED;
721 BTIF_TRACE_WARNING(
722 "BTA_HH_ENABLE_EVT: Error, HH enabling failed, status = %d",
723 p_data->status);
724 }
725 break;
726
727 case BTA_HH_DISABLE_EVT:
728 btif_hh_cb.status = BTIF_HH_DISABLED;
Hemant Gupta8843cc82014-04-18 12:34:55 +0530729 if (btif_hh_cb.service_dereg_active) {
730 BTIF_TRACE_DEBUG("BTA_HH_DISABLE_EVT: enabling HID Device service");
731 btif_hd_service_registration();
732 btif_hh_cb.service_dereg_active = FALSE;
733 }
Myles Watson6bd442f2016-10-19 09:50:22 -0700734 if (p_data->status == BTA_HH_OK) {
735 int i;
736 // Clear the control block
737 for (i = 0; i < BTIF_HH_MAX_HID; i++) {
738 alarm_free(btif_hh_cb.devices[i].vup_timer);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800739 }
Myles Watson6bd442f2016-10-19 09:50:22 -0700740 memset(&btif_hh_cb, 0, sizeof(btif_hh_cb));
741 for (i = 0; i < BTIF_HH_MAX_HID; i++) {
742 btif_hh_cb.devices[i].dev_status = BTHH_CONN_STATE_UNKNOWN;
743 }
744 } else
745 BTIF_TRACE_WARNING(
746 "BTA_HH_DISABLE_EVT: Error, HH disabling failed, status = %d",
747 p_data->status);
748 break;
749
750 case BTA_HH_OPEN_EVT:
751 BTIF_TRACE_WARNING("%s: BTA_HH_OPN_EVT: handle=%d, status =%d", __func__,
752 p_data->conn.handle, p_data->conn.status);
753 if (p_data->conn.status == BTA_HH_OK) {
754 p_dev = btif_hh_find_connected_dev_by_handle(p_data->conn.handle);
755 if (p_dev == NULL) {
756 BTIF_TRACE_WARNING(
757 "BTA_HH_OPEN_EVT: Error, cannot find device with handle %d",
758 p_data->conn.handle);
759 btif_hh_cb.status = (BTIF_HH_STATUS)BTIF_HH_DEV_DISCONNECTED;
760 // The connect request must come from device side and exceeded the
761 // connected
762 // HID device number.
763 BTA_HhClose(p_data->conn.handle);
764 HAL_CBACK(bt_hh_callbacks, connection_state_cb,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700765 (RawAddress*)&p_data->conn.bda,
Myles Watson6bd442f2016-10-19 09:50:22 -0700766 BTHH_CONN_STATE_DISCONNECTED);
767 } else if (p_dev->fd < 0) {
768 BTIF_TRACE_WARNING(
769 "BTA_HH_OPEN_EVT: Error, failed to find the uhid driver...");
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700770 p_dev->bd_addr = p_data->conn.bda;
Myles Watson6bd442f2016-10-19 09:50:22 -0700771 // remove the connection and then try again to reconnect from the
772 // mouse side to recover
773 btif_hh_cb.status = (BTIF_HH_STATUS)BTIF_HH_DEV_DISCONNECTED;
774 BTA_HhClose(p_data->conn.handle);
775 } else {
776 BTIF_TRACE_WARNING(
777 "BTA_HH_OPEN_EVT: Found device...Getting dscp info for handle "
778 "... %d",
779 p_data->conn.handle);
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700780 p_dev->bd_addr = p_data->conn.bda;
Myles Watson6bd442f2016-10-19 09:50:22 -0700781 btif_hh_cb.status = (BTIF_HH_STATUS)BTIF_HH_DEV_CONNECTED;
782 // Send set_idle if the peer_device is a keyboard
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700783 if (check_cod(&p_data->conn.bda, COD_HID_KEYBOARD) ||
784 check_cod(&p_data->conn.bda, COD_HID_COMBO))
Myles Watson6bd442f2016-10-19 09:50:22 -0700785 BTA_HhSetIdle(p_data->conn.handle, 0);
786 btif_hh_cb.p_curr_dev =
787 btif_hh_find_connected_dev_by_handle(p_data->conn.handle);
788 BTA_HhGetDscpInfo(p_data->conn.handle);
789 p_dev->dev_status = BTHH_CONN_STATE_CONNECTED;
790 HAL_CBACK(bt_hh_callbacks, connection_state_cb, &(p_dev->bd_addr),
791 p_dev->dev_status);
792 }
793 } else {
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700794 RawAddress* bdaddr = &p_data->conn.bda;
Myles Watson6bd442f2016-10-19 09:50:22 -0700795 btif_dm_hh_open_failed(bdaddr);
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700796 p_dev = btif_hh_find_dev_by_bda(*bdaddr);
Myles Watson6bd442f2016-10-19 09:50:22 -0700797 if (p_dev != NULL) {
798 btif_hh_stop_vup_timer(&(p_dev->bd_addr));
799 if (p_dev->fd >= 0) {
800 bta_hh_co_destroy(p_dev->fd);
801 p_dev->fd = -1;
802 }
803 p_dev->dev_status = BTHH_CONN_STATE_DISCONNECTED;
804 }
805 HAL_CBACK(bt_hh_callbacks, connection_state_cb,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700806 (RawAddress*)&p_data->conn.bda, BTHH_CONN_STATE_DISCONNECTED);
Myles Watson6bd442f2016-10-19 09:50:22 -0700807 btif_hh_cb.status = (BTIF_HH_STATUS)BTIF_HH_DEV_DISCONNECTED;
808 }
809 break;
810
811 case BTA_HH_CLOSE_EVT:
812 BTIF_TRACE_DEBUG("BTA_HH_CLOSE_EVT: status = %d, handle = %d",
813 p_data->dev_status.status, p_data->dev_status.handle);
814 p_dev = btif_hh_find_connected_dev_by_handle(p_data->dev_status.handle);
815 if (p_dev != NULL) {
816 BTIF_TRACE_DEBUG("%s: uhid fd=%d local_vup=%d", __func__, p_dev->fd,
817 p_dev->local_vup);
818 btif_hh_stop_vup_timer(&(p_dev->bd_addr));
819 /* If this is a locally initiated VUP, remove the bond as ACL got
820 * disconnected while VUP being processed.
821 */
822 if (p_dev->local_vup) {
823 p_dev->local_vup = false;
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700824 BTA_DmRemoveDevice(p_dev->bd_addr);
Myles Watson6bd442f2016-10-19 09:50:22 -0700825 }
826
827 btif_hh_cb.status = (BTIF_HH_STATUS)BTIF_HH_DEV_DISCONNECTED;
828 p_dev->dev_status = BTHH_CONN_STATE_DISCONNECTED;
829
830 if (p_dev->fd >= 0) {
831 bta_hh_co_destroy(p_dev->fd);
832 p_dev->fd = -1;
833 }
834 HAL_CBACK(bt_hh_callbacks, connection_state_cb, &(p_dev->bd_addr),
835 p_dev->dev_status);
836 } else {
837 BTIF_TRACE_WARNING("Error: cannot find device with handle %d",
838 p_data->dev_status.handle);
839 }
840 break;
841
842 case BTA_HH_GET_RPT_EVT: {
843 BT_HDR* hdr = p_data->hs_data.rsp_data.p_rpt_data;
844 uint8_t* data = NULL;
845 uint16_t len = 0;
846
847 BTIF_TRACE_DEBUG("BTA_HH_GET_RPT_EVT: status = %d, handle = %d",
848 p_data->hs_data.status, p_data->hs_data.handle);
849 p_dev = btif_hh_find_connected_dev_by_handle(p_data->hs_data.handle);
850 if (p_dev) {
851 /* p_rpt_data is NULL in HANDSHAKE response case */
852 if (hdr) {
853 data = (uint8_t*)(hdr + 1) + hdr->offset;
854 len = hdr->len;
855 HAL_CBACK(bt_hh_callbacks, get_report_cb,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700856 (RawAddress*)&(p_dev->bd_addr),
Myles Watson6bd442f2016-10-19 09:50:22 -0700857 (bthh_status_t)p_data->hs_data.status, data, len);
858 } else {
859 HAL_CBACK(bt_hh_callbacks, handshake_cb,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700860 (RawAddress*)&(p_dev->bd_addr),
Myles Watson6bd442f2016-10-19 09:50:22 -0700861 (bthh_status_t)p_data->hs_data.status);
862 }
863 } else {
864 BTIF_TRACE_WARNING("Error: cannot find device with handle %d",
865 p_data->hs_data.handle);
866 }
867 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800868 }
869
Myles Watson6bd442f2016-10-19 09:50:22 -0700870 case BTA_HH_SET_RPT_EVT:
871 BTIF_TRACE_DEBUG("BTA_HH_SET_RPT_EVT: status = %d, handle = %d",
872 p_data->dev_status.status, p_data->dev_status.handle);
873 p_dev = btif_hh_find_connected_dev_by_handle(p_data->dev_status.handle);
874 if (p_dev != NULL) {
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700875 HAL_CBACK(bt_hh_callbacks, handshake_cb, (RawAddress*)&(p_dev->bd_addr),
Myles Watson6bd442f2016-10-19 09:50:22 -0700876 (bthh_status_t)p_data->hs_data.status);
877 }
878 break;
879
880 case BTA_HH_GET_PROTO_EVT:
Hemant Gupta5dae3dd2013-07-30 16:11:33 +0530881 p_dev = btif_hh_find_connected_dev_by_handle(p_data->hs_data.handle);
Myles Watson6bd442f2016-10-19 09:50:22 -0700882 BTIF_TRACE_WARNING(
883 "BTA_HH_GET_PROTO_EVT: status = %d, handle = %d, proto = [%d], %s",
884 p_data->hs_data.status, p_data->hs_data.handle,
885 p_data->hs_data.rsp_data.proto_mode,
886 (p_data->hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)
887 ? "Report Mode"
888 : (p_data->hs_data.rsp_data.proto_mode == BTA_HH_PROTO_BOOT_MODE)
889 ? "Boot Mode"
890 : "Unsupported");
891 if (p_data->hs_data.rsp_data.proto_mode != BTA_HH_PROTO_UNKNOWN) {
892 HAL_CBACK(bt_hh_callbacks, protocol_mode_cb,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700893 (RawAddress*)&(p_dev->bd_addr),
Myles Watson6bd442f2016-10-19 09:50:22 -0700894 (bthh_status_t)p_data->hs_data.status,
895 (bthh_protocol_mode_t)p_data->hs_data.rsp_data.proto_mode);
896 } else {
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700897 HAL_CBACK(bt_hh_callbacks, handshake_cb, (RawAddress*)&(p_dev->bd_addr),
Myles Watson6bd442f2016-10-19 09:50:22 -0700898 (bthh_status_t)p_data->hs_data.status);
899 }
900 break;
901
902 case BTA_HH_SET_PROTO_EVT:
903 BTIF_TRACE_DEBUG("BTA_HH_SET_PROTO_EVT: status = %d, handle = %d",
904 p_data->dev_status.status, p_data->dev_status.handle);
905 p_dev = btif_hh_find_connected_dev_by_handle(p_data->dev_status.handle);
906 if (p_dev) {
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700907 HAL_CBACK(bt_hh_callbacks, handshake_cb, (RawAddress*)&(p_dev->bd_addr),
Myles Watson6bd442f2016-10-19 09:50:22 -0700908 (bthh_status_t)p_data->hs_data.status);
909 }
910 break;
911
912 case BTA_HH_GET_IDLE_EVT:
913 BTIF_TRACE_DEBUG(
914 "BTA_HH_GET_IDLE_EVT: handle = %d, status = %d, rate = %d",
915 p_data->hs_data.handle, p_data->hs_data.status,
916 p_data->hs_data.rsp_data.idle_rate);
Hemant Gupta5dae3dd2013-07-30 16:11:33 +0530917 p_dev = btif_hh_find_connected_dev_by_handle(p_data->hs_data.handle);
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700918 HAL_CBACK(bt_hh_callbacks, idle_time_cb, (RawAddress*)&(p_dev->bd_addr),
Hemant Gupta5dae3dd2013-07-30 16:11:33 +0530919 (bthh_status_t)p_data->hs_data.status,
920 p_data->hs_data.rsp_data.idle_rate);
Myles Watson6bd442f2016-10-19 09:50:22 -0700921 break;
922
923 case BTA_HH_SET_IDLE_EVT:
924 BTIF_TRACE_DEBUG("BTA_HH_SET_IDLE_EVT: status = %d, handle = %d",
925 p_data->dev_status.status, p_data->dev_status.handle);
926 break;
927
928 case BTA_HH_GET_DSCP_EVT:
929 len = p_data->dscp_info.descriptor.dl_len;
930 BTIF_TRACE_DEBUG("BTA_HH_GET_DSCP_EVT: len = %d", len);
931 p_dev = btif_hh_cb.p_curr_dev;
932 if (p_dev == NULL) {
933 BTIF_TRACE_ERROR(
934 "BTA_HH_GET_DSCP_EVT: No HID device is currently connected");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800935 return;
Myles Watson6bd442f2016-10-19 09:50:22 -0700936 }
937 if (p_dev->fd < 0) {
938 LOG_ERROR(
939 LOG_TAG,
940 "BTA_HH_GET_DSCP_EVT: Error, failed to find the uhid driver...");
941 return;
942 }
943 {
944 const char* cached_name = NULL;
945 bt_bdname_t bdname;
946 bt_property_t prop_name;
947 BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME,
948 sizeof(bt_bdname_t), &bdname);
949 if (btif_storage_get_remote_device_property(
950 &p_dev->bd_addr, &prop_name) == BT_STATUS_SUCCESS) {
951 cached_name = (char*)bdname.name;
952 } else {
953 cached_name = "Bluetooth HID";
954 }
955
956 BTIF_TRACE_WARNING("%s: name = %s", __func__, cached_name);
957 bta_hh_co_send_hid_info(p_dev, cached_name, p_data->dscp_info.vendor_id,
958 p_data->dscp_info.product_id,
959 p_data->dscp_info.version,
960 p_data->dscp_info.ctry_code, len,
961 p_data->dscp_info.descriptor.dsc_list);
962 if (btif_hh_add_added_dev(p_dev->bd_addr, p_dev->attr_mask)) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700963 tBTA_HH_DEV_DSCP_INFO dscp_info;
964 bt_status_t ret;
Myles Watson6bd442f2016-10-19 09:50:22 -0700965 btif_hh_copy_hid_info(&dscp_info, &p_data->dscp_info);
Jakub Pawlowski011a6192017-06-09 16:00:25 -0700966 VLOG(1) << "BTA_HH_GET_DSCP_EVT:bda = " << p_dev->bd_addr;
967 BTA_HhAddDev(p_dev->bd_addr, p_dev->attr_mask, p_dev->sub_class,
968 p_dev->app_id, dscp_info);
Myles Watson6bd442f2016-10-19 09:50:22 -0700969 // write hid info to nvram
970 ret = btif_storage_add_hid_device_info(
971 &(p_dev->bd_addr), p_dev->attr_mask, p_dev->sub_class,
972 p_dev->app_id, p_data->dscp_info.vendor_id,
973 p_data->dscp_info.product_id, p_data->dscp_info.version,
974 p_data->dscp_info.ctry_code, p_data->dscp_info.ssr_max_latency,
975 p_data->dscp_info.ssr_min_tout, len,
976 p_data->dscp_info.descriptor.dsc_list);
977
978 ASSERTC(ret == BT_STATUS_SUCCESS, "storing hid info failed", ret);
979 BTIF_TRACE_WARNING("BTA_HH_GET_DSCP_EVT: Called add device");
980
981 // Free buffer created for dscp_info;
982 if (dscp_info.descriptor.dl_len > 0 &&
983 dscp_info.descriptor.dsc_list != NULL) {
984 osi_free_and_reset((void**)&dscp_info.descriptor.dsc_list);
985 dscp_info.descriptor.dl_len = 0;
986 }
987 } else {
988 // Device already added.
989 BTIF_TRACE_WARNING("%s: Device already added ", __func__);
990 }
991 /*Sync HID Keyboard lockstates */
992 tmplen = sizeof(hid_kb_numlock_on_list) / sizeof(tHID_KB_LIST);
993 for (i = 0; i < tmplen; i++) {
994 if (p_data->dscp_info.vendor_id ==
995 hid_kb_numlock_on_list[i].version_id &&
996 p_data->dscp_info.product_id ==
997 hid_kb_numlock_on_list[i].product_id) {
998 BTIF_TRACE_DEBUG(
999 "%s() idx[%d] Enabling "
1000 "NUMLOCK for device :: %s",
1001 __func__, i, hid_kb_numlock_on_list[i].kb_name);
1002 /* Enable NUMLOCK by default so that numeric
1003 keys work from first keyboard connect */
1004 set_keylockstate(BTIF_HH_KEYSTATE_MASK_NUMLOCK, true);
1005 sync_lockstate_on_connect(p_dev);
1006 /* End Sync HID Keyboard lockstates */
1007 break;
1008 }
1009 }
1010 }
1011 break;
1012
1013 case BTA_HH_ADD_DEV_EVT:
1014 BTIF_TRACE_WARNING("BTA_HH_ADD_DEV_EVT: status = %d, handle = %d",
1015 p_data->dev_info.status, p_data->dev_info.handle);
1016 int i;
1017 for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001018 if (btif_hh_cb.added_devices[i].bd_addr == p_data->dev_info.bda) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001019 if (p_data->dev_info.status == BTA_HH_OK) {
1020 btif_hh_cb.added_devices[i].dev_handle = p_data->dev_info.handle;
1021 } else {
Jakub Pawlowskib707f442017-07-03 15:39:36 -07001022 btif_hh_cb.added_devices[i].bd_addr = RawAddress::kEmpty;
Myles Watson6bd442f2016-10-19 09:50:22 -07001023 btif_hh_cb.added_devices[i].dev_handle = BTA_HH_INVALID_HANDLE;
1024 }
1025 break;
1026 }
1027 }
1028 break;
1029 case BTA_HH_RMV_DEV_EVT:
1030 BTIF_TRACE_DEBUG("BTA_HH_RMV_DEV_EVT: status = %d, handle = %d",
1031 p_data->dev_info.status, p_data->dev_info.handle);
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001032 VLOG(1) << "BTA_HH_RMV_DEV_EVT:bda = " << p_data->dev_info.bda;
Myles Watson6bd442f2016-10-19 09:50:22 -07001033 break;
1034
1035 case BTA_HH_VC_UNPLUG_EVT:
1036 BTIF_TRACE_DEBUG("BTA_HH_VC_UNPLUG_EVT: status = %d, handle = %d",
1037 p_data->dev_status.status, p_data->dev_status.handle);
1038 p_dev = btif_hh_find_connected_dev_by_handle(p_data->dev_status.handle);
1039 btif_hh_cb.status = (BTIF_HH_STATUS)BTIF_HH_DEV_DISCONNECTED;
1040 if (p_dev != NULL) {
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001041 VLOG(1) << "BTA_HH_VC_UNPLUG_EVT:bda = " << p_dev->bd_addr;
1042
Myles Watson6bd442f2016-10-19 09:50:22 -07001043 /* Stop the VUP timer */
1044 btif_hh_stop_vup_timer(&(p_dev->bd_addr));
1045 p_dev->dev_status = BTHH_CONN_STATE_DISCONNECTED;
1046 BTIF_TRACE_DEBUG("%s---Sending connection state change", __func__);
1047 HAL_CBACK(bt_hh_callbacks, connection_state_cb, &(p_dev->bd_addr),
1048 p_dev->dev_status);
1049 BTIF_TRACE_DEBUG("%s---Removing HID bond", __func__);
1050 /* If it is locally initiated VUP or remote device has its major COD as
1051 Peripheral removed the bond.*/
1052 if (p_dev->local_vup || check_cod_hid(&(p_dev->bd_addr))) {
1053 p_dev->local_vup = false;
Jakub Pawlowskic2276b02017-06-09 16:00:25 -07001054 BTA_DmRemoveDevice(p_dev->bd_addr);
Myles Watson6bd442f2016-10-19 09:50:22 -07001055 } else
1056 btif_hh_remove_device(p_dev->bd_addr);
1057 HAL_CBACK(bt_hh_callbacks, virtual_unplug_cb, &(p_dev->bd_addr),
1058 (bthh_status_t)p_data->dev_status.status);
1059 }
1060 break;
1061
1062 case BTA_HH_API_ERR_EVT:
1063 LOG_INFO(LOG_TAG, "BTA_HH API_ERR");
1064 break;
1065
1066 default:
1067 BTIF_TRACE_WARNING("%s: Unhandled event: %d", __func__, event);
1068 break;
1069 }
1070}
1071
1072/*******************************************************************************
1073 *
1074 * Function bte_hh_evt
1075 *
1076 * Description Switches context from BTE to BTIF for all HH events
1077 *
1078 * Returns void
1079 *
1080 ******************************************************************************/
1081
Hemant Gupta8843cc82014-04-18 12:34:55 +05301082void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001083 bt_status_t status;
1084 int param_len = 0;
1085
1086 if (BTA_HH_ENABLE_EVT == event)
1087 param_len = sizeof(tBTA_HH_STATUS);
1088 else if (BTA_HH_OPEN_EVT == event)
1089 param_len = sizeof(tBTA_HH_CONN);
1090 else if (BTA_HH_DISABLE_EVT == event)
1091 param_len = sizeof(tBTA_HH_STATUS);
1092 else if (BTA_HH_CLOSE_EVT == event)
1093 param_len = sizeof(tBTA_HH_CBDATA);
1094 else if (BTA_HH_GET_DSCP_EVT == event)
1095 param_len = sizeof(tBTA_HH_DEV_DSCP_INFO);
1096 else if ((BTA_HH_GET_PROTO_EVT == event) || (BTA_HH_GET_RPT_EVT == event) ||
1097 (BTA_HH_GET_IDLE_EVT == event))
1098 param_len = sizeof(tBTA_HH_HSDATA);
1099 else if ((BTA_HH_SET_PROTO_EVT == event) || (BTA_HH_SET_RPT_EVT == event) ||
1100 (BTA_HH_VC_UNPLUG_EVT == event) || (BTA_HH_SET_IDLE_EVT == event))
1101 param_len = sizeof(tBTA_HH_CBDATA);
1102 else if ((BTA_HH_ADD_DEV_EVT == event) || (BTA_HH_RMV_DEV_EVT == event))
1103 param_len = sizeof(tBTA_HH_DEV_INFO);
1104 else if (BTA_HH_API_ERR_EVT == event)
1105 param_len = 0;
1106 /* switch context to btif task context (copy full union size for convenience)
1107 */
1108 status = btif_transfer_context(btif_hh_upstreams_evt, (uint16_t)event,
1109 (char*)p_data, param_len, NULL);
1110
1111 /* catch any failed context transfers */
1112 ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
1113}
1114
1115/*******************************************************************************
1116 *
1117 * Function btif_hh_handle_evt
1118 *
1119 * Description Switches context for immediate callback
1120 *
1121 * Returns void
1122 *
1123 ******************************************************************************/
1124
1125static void btif_hh_handle_evt(uint16_t event, char* p_param) {
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001126 RawAddress* bd_addr = (RawAddress*)p_param;
Myles Watson6bd442f2016-10-19 09:50:22 -07001127 BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
1128 int ret;
1129 switch (event) {
1130 case BTIF_HH_CONNECT_REQ_EVT: {
1131 ret = btif_hh_connect(bd_addr);
1132 if (ret == BT_STATUS_SUCCESS) {
1133 HAL_CBACK(bt_hh_callbacks, connection_state_cb, bd_addr,
1134 BTHH_CONN_STATE_CONNECTING);
1135 } else
1136 HAL_CBACK(bt_hh_callbacks, connection_state_cb, bd_addr,
1137 BTHH_CONN_STATE_DISCONNECTED);
1138 } break;
1139
1140 case BTIF_HH_DISCONNECT_REQ_EVT: {
1141 BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
1142 btif_hh_disconnect(bd_addr);
1143 HAL_CBACK(bt_hh_callbacks, connection_state_cb, bd_addr,
1144 BTHH_CONN_STATE_DISCONNECTING);
1145 } break;
1146
1147 case BTIF_HH_VUP_REQ_EVT: {
1148 BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
1149 ret = btif_hh_virtual_unplug(bd_addr);
1150 } break;
1151
1152 default: {
1153 BTIF_TRACE_WARNING("%s : Unknown event 0x%x", __func__, event);
1154 } break;
1155 }
1156}
1157
1158/*******************************************************************************
1159 *
1160 * Function btif_hh_timer_timeout
1161 *
1162 * Description Process timer timeout
1163 *
1164 * Returns void
1165 ******************************************************************************/
1166void btif_hh_timer_timeout(void* data) {
1167 btif_hh_device_t* p_dev = (btif_hh_device_t*)data;
1168 tBTA_HH_EVT event = BTA_HH_VC_UNPLUG_EVT;
1169 tBTA_HH p_data;
1170 int param_len = sizeof(tBTA_HH_CBDATA);
1171
1172 BTIF_TRACE_DEBUG("%s", __func__);
1173 if (p_dev->dev_status != BTHH_CONN_STATE_CONNECTED) return;
1174
1175 memset(&p_data, 0, sizeof(tBTA_HH));
1176 p_data.dev_status.status = BTHH_ERR;
1177 p_data.dev_status.handle = p_dev->dev_handle;
1178
1179 /* switch context to btif task context */
1180 btif_transfer_context(btif_hh_upstreams_evt, (uint16_t)event, (char*)&p_data,
1181 param_len, NULL);
1182}
1183
1184/*******************************************************************************
1185 *
1186 * Function btif_hh_init
1187 *
1188 * Description initializes the hh interface
1189 *
1190 * Returns bt_status_t
1191 *
1192 ******************************************************************************/
1193static bt_status_t init(bthh_callbacks_t* callbacks) {
1194 uint32_t i;
1195 BTIF_TRACE_EVENT("%s", __func__);
1196
1197 bt_hh_callbacks = callbacks;
1198 memset(&btif_hh_cb, 0, sizeof(btif_hh_cb));
1199 for (i = 0; i < BTIF_HH_MAX_HID; i++) {
1200 btif_hh_cb.devices[i].dev_status = BTHH_CONN_STATE_UNKNOWN;
1201 }
1202 /* Invoke the enable service API to the core to set the appropriate service_id
1203 */
1204 btif_enable_service(BTA_HID_SERVICE_ID);
1205 return BT_STATUS_SUCCESS;
1206}
1207
1208/*******************************************************************************
1209 *
1210 * Function connect
1211 *
1212 * Description connect to hid device
1213 *
1214 * Returns bt_status_t
1215 *
1216 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001217static bt_status_t connect(RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001218 if (btif_hh_cb.status != BTIF_HH_DEV_CONNECTING) {
1219 btif_transfer_context(btif_hh_handle_evt, BTIF_HH_CONNECT_REQ_EVT,
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001220 (char*)bd_addr, sizeof(RawAddress), NULL);
Myles Watson6bd442f2016-10-19 09:50:22 -07001221 return BT_STATUS_SUCCESS;
1222 } else
1223 return BT_STATUS_BUSY;
1224}
1225
1226/*******************************************************************************
1227 *
1228 * Function disconnect
1229 *
1230 * Description disconnect from hid device
1231 *
1232 * Returns bt_status_t
1233 *
1234 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001235static bt_status_t disconnect(RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001236 CHECK_BTHH_INIT();
Marie Janssenc338fe82017-02-01 12:50:00 -08001237 BTIF_TRACE_EVENT("BTHH: %s", __func__);
Myles Watson6bd442f2016-10-19 09:50:22 -07001238 btif_hh_device_t* p_dev;
1239
1240 if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1241 BTIF_TRACE_WARNING("%s: Error, HH status = %d", __func__,
1242 btif_hh_cb.status);
1243 return BT_STATUS_FAIL;
1244 }
Jakub Pawlowskic2276b02017-06-09 16:00:25 -07001245 p_dev = btif_hh_find_connected_dev_by_bda(*bd_addr);
Myles Watson6bd442f2016-10-19 09:50:22 -07001246 if (p_dev != NULL) {
1247 return btif_transfer_context(btif_hh_handle_evt, BTIF_HH_DISCONNECT_REQ_EVT,
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001248 (char*)bd_addr, sizeof(RawAddress), NULL);
Myles Watson6bd442f2016-10-19 09:50:22 -07001249 } else {
1250 BTIF_TRACE_WARNING("%s: Error, device not opened.", __func__);
1251 return BT_STATUS_FAIL;
1252 }
1253}
1254
1255/*******************************************************************************
1256 *
1257 * Function virtual_unplug
1258 *
1259 * Description Virtual UnPlug (VUP) the specified HID device.
1260 *
1261 * Returns bt_status_t
1262 *
1263 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001264static bt_status_t virtual_unplug(RawAddress* bd_addr) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001265 CHECK_BTHH_INIT();
Marie Janssenc338fe82017-02-01 12:50:00 -08001266 BTIF_TRACE_EVENT("BTHH: %s", __func__);
Myles Watson6bd442f2016-10-19 09:50:22 -07001267 btif_hh_device_t* p_dev;
1268 char bd_str[18];
1269 snprintf(bd_str, sizeof(bd_str), "%02X:%02X:%02X:%02X:%02X:%02X",
1270 bd_addr->address[0], bd_addr->address[1], bd_addr->address[2],
1271 bd_addr->address[3], bd_addr->address[4], bd_addr->address[5]);
1272 if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1273 BTIF_TRACE_ERROR("%s: Error, HH status = %d", __func__, btif_hh_cb.status);
1274 return BT_STATUS_FAIL;
1275 }
Jakub Pawlowskic2276b02017-06-09 16:00:25 -07001276 p_dev = btif_hh_find_dev_by_bda(*bd_addr);
Myles Watson6bd442f2016-10-19 09:50:22 -07001277 if (!p_dev) {
1278 BTIF_TRACE_ERROR("%s: Error, device %s not opened.", __func__, bd_str);
1279 return BT_STATUS_FAIL;
1280 }
1281 btif_transfer_context(btif_hh_handle_evt, BTIF_HH_VUP_REQ_EVT, (char*)bd_addr,
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001282 sizeof(RawAddress), NULL);
Myles Watson6bd442f2016-10-19 09:50:22 -07001283 return BT_STATUS_SUCCESS;
1284}
1285
1286/*******************************************************************************
Hemant Gupta5dae3dd2013-07-30 16:11:33 +05301287**
1288** Function get_idle_time
1289**
1290** Description Get the HID idle time
1291**
1292** Returns bt_status_t
1293**
1294*******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001295static bt_status_t get_idle_time(RawAddress* bd_addr) {
Hemant Gupta5dae3dd2013-07-30 16:11:33 +05301296 CHECK_BTHH_INIT();
1297
Jakub Pawlowskib707f442017-07-03 15:39:36 -07001298 BTIF_TRACE_DEBUG("%s: addr = %s", __func__, bd_addr->ToString().c_str());
Hemant Gupta5dae3dd2013-07-30 16:11:33 +05301299
1300 if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1301 BTIF_TRACE_ERROR("%s: Error, HH status = %d", __func__, btif_hh_cb.status);
1302 return BT_STATUS_FAIL;
1303 }
1304
Jakub Pawlowskic2276b02017-06-09 16:00:25 -07001305 btif_hh_device_t* p_dev = btif_hh_find_connected_dev_by_bda(*bd_addr);
Hemant Gupta5dae3dd2013-07-30 16:11:33 +05301306 if (p_dev == NULL) return BT_STATUS_FAIL;
1307
1308 BTA_HhGetIdle(p_dev->dev_handle);
1309 return BT_STATUS_SUCCESS;
1310}
1311
1312/*******************************************************************************
1313**
1314** Function set_idle_time
1315**
1316** Description Set the HID idle time
1317**
1318** Returns bt_status_t
1319**
1320*******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001321static bt_status_t set_idle_time(RawAddress* bd_addr, uint8_t idle_time) {
Hemant Gupta5dae3dd2013-07-30 16:11:33 +05301322 CHECK_BTHH_INIT();
1323
Hemant Gupta5dae3dd2013-07-30 16:11:33 +05301324 BTIF_TRACE_DEBUG("%s: addr = %s, idle time = %d", __func__,
Jakub Pawlowskib707f442017-07-03 15:39:36 -07001325 bd_addr->ToString().c_str(), idle_time);
Hemant Gupta5dae3dd2013-07-30 16:11:33 +05301326
1327 if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1328 BTIF_TRACE_ERROR("%s: Error, HH status = %d", __func__, btif_hh_cb.status);
1329 return BT_STATUS_FAIL;
1330 }
1331
Jakub Pawlowskic2276b02017-06-09 16:00:25 -07001332 btif_hh_device_t* p_dev = p_dev = btif_hh_find_connected_dev_by_bda(*bd_addr);
Hemant Gupta5dae3dd2013-07-30 16:11:33 +05301333 if (p_dev == NULL) {
1334 BTIF_TRACE_WARNING("%s: addr = %s not opened", __func__,
Jakub Pawlowskib707f442017-07-03 15:39:36 -07001335 bd_addr->ToString().c_str());
Hemant Gupta5dae3dd2013-07-30 16:11:33 +05301336 return BT_STATUS_FAIL;
1337 }
1338
1339 BTA_HhSetIdle(p_dev->dev_handle, idle_time);
1340 return BT_STATUS_SUCCESS;
1341}
1342
1343/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001344 *
1345 * Function set_info
1346 *
1347 * Description Set the HID device descriptor for the specified HID device.
1348 *
1349 * Returns bt_status_t
1350 *
1351 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001352static bt_status_t set_info(RawAddress* bd_addr, bthh_hid_info_t hid_info) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001353 CHECK_BTHH_INIT();
1354 tBTA_HH_DEV_DSCP_INFO dscp_info;
Myles Watson6bd442f2016-10-19 09:50:22 -07001355
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001356 VLOG(1) << __func__ << " BTHH: addr = " << *bd_addr;
Myles Watson6bd442f2016-10-19 09:50:22 -07001357 BTIF_TRACE_DEBUG(
Marie Janssenc338fe82017-02-01 12:50:00 -08001358 "BTHH: %s: sub_class = 0x%02x, app_id = %d, vendor_id = 0x%04x, "
Myles Watson6bd442f2016-10-19 09:50:22 -07001359 "product_id = 0x%04x, version= 0x%04x",
1360 __func__, hid_info.sub_class, hid_info.app_id, hid_info.vendor_id,
1361 hid_info.product_id, hid_info.version);
1362
1363 if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1364 BTIF_TRACE_ERROR("%s: Error, HH status = %d", __func__, btif_hh_cb.status);
1365 return BT_STATUS_FAIL;
1366 }
1367
1368 dscp_info.vendor_id = hid_info.vendor_id;
1369 dscp_info.product_id = hid_info.product_id;
1370 dscp_info.version = hid_info.version;
1371 dscp_info.ctry_code = hid_info.ctry_code;
1372
1373 dscp_info.descriptor.dl_len = hid_info.dl_len;
1374 dscp_info.descriptor.dsc_list =
1375 (uint8_t*)osi_malloc(dscp_info.descriptor.dl_len);
1376 memcpy(dscp_info.descriptor.dsc_list, &(hid_info.dsc_list), hid_info.dl_len);
1377
1378 if (btif_hh_add_added_dev(*bd_addr, hid_info.attr_mask)) {
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001379 BTA_HhAddDev(*bd_addr, hid_info.attr_mask, hid_info.sub_class,
1380 hid_info.app_id, dscp_info);
Myles Watson6bd442f2016-10-19 09:50:22 -07001381 }
1382
1383 osi_free_and_reset((void**)&dscp_info.descriptor.dsc_list);
1384
1385 return BT_STATUS_SUCCESS;
1386}
1387
1388/*******************************************************************************
1389 *
1390 * Function get_protocol
1391 *
1392 * Description Get the HID proto mode.
1393 *
1394 * Returns bt_status_t
1395 *
1396 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001397static bt_status_t get_protocol(RawAddress* bd_addr,
Myles Watsond35a6482016-10-27 08:52:16 -07001398 UNUSED_ATTR bthh_protocol_mode_t protocolMode) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001399 CHECK_BTHH_INIT();
Myles Watson6bd442f2016-10-19 09:50:22 -07001400
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001401 VLOG(1) << __func__ << " BTHH: addr = " << *bd_addr;
Myles Watson6bd442f2016-10-19 09:50:22 -07001402
1403 if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1404 BTIF_TRACE_ERROR("%s: Error, HH status = %d", __func__, btif_hh_cb.status);
1405 return BT_STATUS_FAIL;
1406 }
1407
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001408 btif_hh_device_t* p_dev = btif_hh_find_connected_dev_by_bda(*bd_addr);
1409 if (!p_dev) return BT_STATUS_FAIL;
1410
1411 BTA_HhGetProtoMode(p_dev->dev_handle);
Myles Watson6bd442f2016-10-19 09:50:22 -07001412 return BT_STATUS_SUCCESS;
1413}
1414
1415/*******************************************************************************
1416 *
1417 * Function set_protocol
1418 *
1419 * Description Set the HID proto mode.
1420 *
1421 * Returns bt_status_t
1422 *
1423 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001424static bt_status_t set_protocol(RawAddress* bd_addr,
Myles Watson6bd442f2016-10-19 09:50:22 -07001425 bthh_protocol_mode_t protocolMode) {
1426 CHECK_BTHH_INIT();
1427 btif_hh_device_t* p_dev;
1428 uint8_t proto_mode = protocolMode;
Myles Watson6bd442f2016-10-19 09:50:22 -07001429
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001430 VLOG(1) << __func__ << " BTHH: proto_mod=" << protocolMode
1431 << " addr = " << *bd_addr;
Myles Watson6bd442f2016-10-19 09:50:22 -07001432
1433 if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1434 BTIF_TRACE_ERROR("%s: Error, HH status = %d", __func__, btif_hh_cb.status);
1435 return BT_STATUS_FAIL;
1436 }
1437
Jakub Pawlowskic2276b02017-06-09 16:00:25 -07001438 p_dev = btif_hh_find_connected_dev_by_bda(*bd_addr);
Myles Watson6bd442f2016-10-19 09:50:22 -07001439 if (p_dev == NULL) {
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001440 LOG(WARNING) << " Error, device" << *bd_addr << " not opened";
Myles Watson6bd442f2016-10-19 09:50:22 -07001441 return BT_STATUS_FAIL;
1442 } else if (protocolMode != BTA_HH_PROTO_RPT_MODE &&
1443 protocolMode != BTA_HH_PROTO_BOOT_MODE) {
1444 BTIF_TRACE_WARNING("%s: Error, device proto_mode = %d.", __func__,
1445 proto_mode);
1446 return BT_STATUS_FAIL;
1447 } else {
1448 BTA_HhSetProtoMode(p_dev->dev_handle, protocolMode);
1449 }
1450
1451 return BT_STATUS_SUCCESS;
1452}
1453
1454/*******************************************************************************
1455 *
1456 * Function get_report
1457 *
1458 * Description Send a GET_REPORT to HID device.
1459 *
1460 * Returns bt_status_t
1461 *
1462 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001463static bt_status_t get_report(RawAddress* bd_addr,
Myles Watson6bd442f2016-10-19 09:50:22 -07001464 bthh_report_type_t reportType, uint8_t reportId,
1465 int bufferSize) {
1466 CHECK_BTHH_INIT();
1467 btif_hh_device_t* p_dev;
Myles Watson6bd442f2016-10-19 09:50:22 -07001468
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001469 VLOG(1) << __func__ << " BTHH: r_type = " << reportType
1470 << ", rpt_id = " << reportId << ", buf_size = " << bufferSize
1471 << " addr = " << *bd_addr;
Myles Watson6bd442f2016-10-19 09:50:22 -07001472
1473 if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1474 BTIF_TRACE_ERROR("%s: Error, HH status = %d", __func__, btif_hh_cb.status);
1475 return BT_STATUS_FAIL;
1476 }
1477
Jakub Pawlowskic2276b02017-06-09 16:00:25 -07001478 p_dev = btif_hh_find_connected_dev_by_bda(*bd_addr);
Myles Watson6bd442f2016-10-19 09:50:22 -07001479 if (p_dev == NULL) {
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001480 LOG(ERROR) << " Error, device" << *bd_addr << " not opened";
Myles Watson6bd442f2016-10-19 09:50:22 -07001481 return BT_STATUS_FAIL;
1482 } else if (((int)reportType) <= BTA_HH_RPTT_RESRV ||
1483 ((int)reportType) > BTA_HH_RPTT_FEATURE) {
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001484 LOG(ERROR) << " Error, device" << *bd_addr << " not opened";
Myles Watson6bd442f2016-10-19 09:50:22 -07001485 return BT_STATUS_FAIL;
1486 } else {
1487 BTA_HhGetReport(p_dev->dev_handle, reportType, reportId, bufferSize);
1488 }
1489
1490 return BT_STATUS_SUCCESS;
1491}
1492
1493/*******************************************************************************
1494 *
1495 * Function set_report
1496 *
1497 * Description Send a SET_REPORT to HID device.
1498 *
1499 * Returns bt_status_t
1500 *
1501 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001502static bt_status_t set_report(RawAddress* bd_addr,
Myles Watson6bd442f2016-10-19 09:50:22 -07001503 bthh_report_type_t reportType, char* report) {
1504 CHECK_BTHH_INIT();
1505 btif_hh_device_t* p_dev;
Myles Watson6bd442f2016-10-19 09:50:22 -07001506
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001507 VLOG(1) << __func__ << " BTHH: reportType=" << reportType
1508 << " addr=" << *bd_addr;
Myles Watson6bd442f2016-10-19 09:50:22 -07001509
1510 if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1511 BTIF_TRACE_ERROR("%s: Error, HH status = %d", __func__, btif_hh_cb.status);
1512 return BT_STATUS_FAIL;
1513 }
1514
Jakub Pawlowskic2276b02017-06-09 16:00:25 -07001515 p_dev = btif_hh_find_connected_dev_by_bda(*bd_addr);
Myles Watson6bd442f2016-10-19 09:50:22 -07001516 if (p_dev == NULL) {
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001517 LOG(ERROR) << " Error, device" << *bd_addr << " not opened";
Myles Watson6bd442f2016-10-19 09:50:22 -07001518 return BT_STATUS_FAIL;
1519 } else if (((int)reportType) <= BTA_HH_RPTT_RESRV ||
1520 ((int)reportType) > BTA_HH_RPTT_FEATURE) {
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001521 LOG(ERROR) << " Error, device" << *bd_addr << " not opened";
Myles Watson6bd442f2016-10-19 09:50:22 -07001522 return BT_STATUS_FAIL;
1523 } else {
1524 int hex_bytes_filled;
1525 size_t len = (strlen(report) + 1) / 2;
1526 uint8_t* hexbuf = (uint8_t*)osi_calloc(len);
1527
1528 /* Build a SetReport data buffer */
1529 // TODO
1530 hex_bytes_filled = ascii_2_hex(report, len, hexbuf);
1531 LOG_INFO(LOG_TAG, "Hex bytes filled, hex value: %d", hex_bytes_filled);
1532 if (hex_bytes_filled) {
1533 BT_HDR* p_buf = create_pbuf(hex_bytes_filled, hexbuf);
1534 if (p_buf == NULL) {
1535 BTIF_TRACE_ERROR("%s: Error, failed to allocate RPT buffer, len = %d",
1536 __func__, hex_bytes_filled);
1537 osi_free(hexbuf);
1538 return BT_STATUS_FAIL;
1539 }
1540 BTA_HhSetReport(p_dev->dev_handle, reportType, p_buf);
1541 osi_free(hexbuf);
1542 return BT_STATUS_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001543 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001544 osi_free(hexbuf);
1545 return BT_STATUS_FAIL;
1546 }
1547}
The Android Open Source Project5738f832012-12-12 16:00:35 -08001548
Myles Watson6bd442f2016-10-19 09:50:22 -07001549/*******************************************************************************
1550 *
1551 * Function send_data
1552 *
1553 * Description Send a SEND_DATA to HID device.
1554 *
1555 * Returns bt_status_t
1556 *
1557 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001558static bt_status_t send_data(RawAddress* bd_addr, char* data) {
Myles Watson6bd442f2016-10-19 09:50:22 -07001559 CHECK_BTHH_INIT();
1560 btif_hh_device_t* p_dev;
Zhihai Xu03c26932013-11-15 21:18:25 -08001561
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001562 VLOG(1) << __func__ << " addr=" << *bd_addr;
Myles Watson6bd442f2016-10-19 09:50:22 -07001563
1564 if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1565 BTIF_TRACE_ERROR("%s: Error, HH status = %d", __func__, btif_hh_cb.status);
1566 return BT_STATUS_FAIL;
1567 }
1568
Jakub Pawlowskic2276b02017-06-09 16:00:25 -07001569 p_dev = btif_hh_find_connected_dev_by_bda(*bd_addr);
Myles Watson6bd442f2016-10-19 09:50:22 -07001570 if (p_dev == NULL) {
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001571 LOG(ERROR) << " Error, device" << *bd_addr << " not opened";
Myles Watson6bd442f2016-10-19 09:50:22 -07001572 return BT_STATUS_FAIL;
1573 }
1574
1575 else {
1576 int hex_bytes_filled;
1577 size_t len = (strlen(data) + 1) / 2;
1578 uint8_t* hexbuf = (uint8_t*)osi_calloc(len);
1579
1580 /* Build a SendData data buffer */
1581 hex_bytes_filled = ascii_2_hex(data, len, hexbuf);
1582 BTIF_TRACE_ERROR("Hex bytes filled, hex value: %d, %d", hex_bytes_filled,
1583 len);
1584
1585 if (hex_bytes_filled) {
1586 BT_HDR* p_buf = create_pbuf(hex_bytes_filled, hexbuf);
1587 if (p_buf == NULL) {
1588 BTIF_TRACE_ERROR("%s: Error, failed to allocate RPT buffer, len = %d",
1589 __func__, hex_bytes_filled);
1590 osi_free(hexbuf);
1591 return BT_STATUS_FAIL;
1592 }
1593 p_buf->layer_specific = BTA_HH_RPTT_OUTPUT;
Jakub Pawlowski011a6192017-06-09 16:00:25 -07001594 BTA_HhSendData(p_dev->dev_handle, *bd_addr, p_buf);
Myles Watson6bd442f2016-10-19 09:50:22 -07001595 osi_free(hexbuf);
1596 return BT_STATUS_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001597 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001598 osi_free(hexbuf);
1599 return BT_STATUS_FAIL;
1600 }
1601}
The Android Open Source Project689d66b2012-12-12 17:18:15 -08001602
Myles Watson6bd442f2016-10-19 09:50:22 -07001603/*******************************************************************************
1604 *
1605 * Function cleanup
1606 *
1607 * Description Closes the HH interface
1608 *
1609 * Returns bt_status_t
1610 *
1611 ******************************************************************************/
1612static void cleanup(void) {
1613 BTIF_TRACE_EVENT("%s", __func__);
1614 btif_hh_device_t* p_dev;
1615 int i;
1616 if (btif_hh_cb.status == BTIF_HH_DISABLED) {
1617 BTIF_TRACE_WARNING("%s: HH disabling or disabled already, status = %d",
1618 __func__, btif_hh_cb.status);
1619 return;
1620 }
Hemant Gupta8843cc82014-04-18 12:34:55 +05301621 if (bt_hh_callbacks) {
1622 btif_hh_cb.status = BTIF_HH_DISABLING;
1623 /* update flag, not to enable hid device service now as BT is switching off
1624 */
1625 btif_hh_cb.service_dereg_active = FALSE;
1626 btif_disable_service(BTA_HID_SERVICE_ID);
1627 bt_hh_callbacks = NULL;
1628 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001629 for (i = 0; i < BTIF_HH_MAX_HID; i++) {
1630 p_dev = &btif_hh_cb.devices[i];
1631 if (p_dev->dev_status != BTHH_CONN_STATE_UNKNOWN && p_dev->fd >= 0) {
1632 BTIF_TRACE_DEBUG("%s: Closing uhid fd = %d", __func__, p_dev->fd);
1633 if (p_dev->fd >= 0) {
The Android Open Source Project5738f832012-12-12 16:00:35 -08001634 bta_hh_co_destroy(p_dev->fd);
1635 p_dev->fd = -1;
Myles Watson6bd442f2016-10-19 09:50:22 -07001636 }
1637 p_dev->hh_keep_polling = 0;
1638 p_dev->hh_poll_thread_id = -1;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001639 }
Myles Watson6bd442f2016-10-19 09:50:22 -07001640 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001641
The Android Open Source Project5738f832012-12-12 16:00:35 -08001642}
1643
1644static const bthh_interface_t bthhInterface = {
Hemant Gupta5dae3dd2013-07-30 16:11:33 +05301645 sizeof(bthhInterface),
1646 init,
1647 connect,
1648 disconnect,
1649 virtual_unplug,
1650 set_info,
1651 get_protocol,
1652 set_protocol,
1653 get_idle_time,
1654 set_idle_time,
1655 get_report,
1656 set_report,
1657 send_data,
1658 cleanup,
The Android Open Source Project5738f832012-12-12 16:00:35 -08001659};
1660
1661/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001662 *
1663 * Function btif_hh_execute_service
1664 *
1665 * Description Initializes/Shuts down the service
1666 *
1667 * Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
1668 *
1669 ******************************************************************************/
1670bt_status_t btif_hh_execute_service(bool b_enable) {
1671 if (b_enable) {
1672 /* Enable and register with BTA-HH */
1673 BTA_HhEnable(BTUI_HH_SECURITY, bte_hh_evt);
1674 } else {
1675 /* Disable HH */
1676 BTA_HhDisable();
1677 }
1678 return BT_STATUS_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001679}
1680
1681/*******************************************************************************
Myles Watson6bd442f2016-10-19 09:50:22 -07001682 *
1683 * Function btif_hh_get_interface
1684 *
1685 * Description Get the hh callback interface
1686 *
1687 * Returns bthh_interface_t
1688 *
1689 ******************************************************************************/
1690const bthh_interface_t* btif_hh_get_interface() {
1691 BTIF_TRACE_EVENT("%s", __func__);
1692 return &bthhInterface;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001693}