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