diff options
author | Kausik Sinnaswamy <kausik@broadcom.com> | 2012-03-09 10:54:02 -0800 |
---|---|---|
committer | Matthew Xie <mattx@google.com> | 2012-07-14 11:19:13 -0700 |
commit | 837acf40a4968449f044cfd3cd15f7f120617eb5 (patch) | |
tree | d2e71deec39c3a5e2e9651726662748fdf6440ac | |
parent | 5140bed9a19aadca962184ebc9ed823d5d7cb745 (diff) | |
download | external_bluetooth_bluedroid-837acf40a4968449f044cfd3cd15f7f120617eb5.zip external_bluetooth_bluedroid-837acf40a4968449f044cfd3cd15f7f120617eb5.tar.gz external_bluetooth_bluedroid-837acf40a4968449f044cfd3cd15f7f120617eb5.tar.bz2 |
Added support to handle AVRCP 1.0 and incoming A2DP connections
Change-Id: I7863920895aa9fd77eccee4083319701bcbf4300
-rw-r--r-- | bta/av/bta_av_act.c | 79 | ||||
-rw-r--r-- | bta/av/bta_av_int.h | 1 | ||||
-rw-r--r-- | btif/co/bta_av_co.c | 9 | ||||
-rw-r--r-- | btif/include/uinput.h | 611 | ||||
-rw-r--r-- | btif/src/btif_av.c | 137 | ||||
-rw-r--r-- | btif/src/btif_rc.c | 435 | ||||
-rw-r--r-- | include/buildcfg_crespo.h | 2 | ||||
-rw-r--r-- | include/buildcfg_maguro.h | 2 | ||||
-rw-r--r-- | main/Android.mk | 3 |
9 files changed, 1237 insertions, 42 deletions
diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c index e501e52..9fafd76 100644 --- a/bta/av/bta_av_act.c +++ b/bta/av/bta_av_act.c @@ -87,7 +87,8 @@ void bta_av_del_rc(tBTA_AV_RCB *p_rcb) p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1]; if(p_scb) { - APPL_TRACE_DEBUG3("bta_av_del_rc shdl:%d, srch:%d rc_handle:%d", p_rcb->shdl, p_scb->rc_handle, p_rcb->handle); + APPL_TRACE_DEBUG3("bta_av_del_rc shdl:%d, srch:%d rc_handle:%d", p_rcb->shdl, + p_scb->rc_handle, p_rcb->handle); if(p_scb->rc_handle == p_rcb->handle) p_scb->rc_handle = BTA_AV_RC_HANDLE_NONE; /* just in case the RC timer is active @@ -317,7 +318,7 @@ UINT8 bta_av_rc_create(tBTA_AV_CB *p_cb, UINT8 role, UINT8 shdl, UINT8 lidx) ccb.company_id = p_bta_av_cfg->company_id; ccb.conn = role; /* note: BTA_AV_FEAT_RCTG = AVRC_CT_TARGET, BTA_AV_FEAT_RCCT = AVRC_CT_CONTROL */ - ccb.control = p_cb->features & (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | AVRC_CT_PASSIVE); + ccb.control = p_cb->features & (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | AVRC_CT_PASSIVE); if (AVRC_Open(&rc_handle, &ccb, bda) != AVRC_SUCCESS) @@ -497,7 +498,8 @@ void bta_av_rc_opened(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data) if (p_cb->rcb[i].lidx == (BTA_AV_NUM_LINKS + 1) && shdl != 0) { - /* rc is opened on the RC only ACP channel, but is for a specific SCB -> need to switch RCBs */ + /* rc is opened on the RC only ACP channel, but is for a specific + * SCB -> need to switch RCBs */ p_rcb = bta_av_get_rcb_by_shdl(shdl); if (p_rcb) { @@ -507,7 +509,8 @@ void bta_av_rc_opened(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data) p_cb->rcb[i].lidx = tmp; p_cb->rc_acp_handle = p_rcb->handle; p_cb->rc_acp_idx = (p_rcb - p_cb->rcb) + 1; - APPL_TRACE_DEBUG2("switching RCB rc_acp_handle:%d idx:%d", p_cb->rc_acp_handle, p_cb->rc_acp_idx); + APPL_TRACE_DEBUG2("switching RCB rc_acp_handle:%d idx:%d", + p_cb->rc_acp_handle, p_cb->rc_acp_idx); } } @@ -538,7 +541,8 @@ void bta_av_rc_opened(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data) bdcpy(rc_open.peer_addr, p_data->rc_conn_chg.peer_addr); rc_open.peer_features = p_cb->rcb[i].peer_features; rc_open.status = BTA_AV_SUCCESS; - APPL_TRACE_DEBUG2("local features:x%x peer_features:x%x", p_cb->features, rc_open.peer_features); + APPL_TRACE_DEBUG2("local features:x%x peer_features:x%x", p_cb->features, + rc_open.peer_features); if(rc_open.peer_features == 0) { /* we have not done SDP on peer RC capabilities. @@ -549,8 +553,8 @@ void bta_av_rc_opened(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data) (*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open); #if (AVRC_ADV_CTRL_INCLUDED == TRUE && AVCT_BROWSE_INCLUDED == TRUE) - /* if local initiated AVRCP connection and both peer and locals device support browsing channel, - * open the browsing channel now */ + /* if local initiated AVRCP connection and both peer and locals device support + * browsing channel, open the browsing channel now */ if ((p_cb->features & BTA_AV_FEAT_BROWSE) && (rc_open.peer_features & BTA_AV_FEAT_BROWSE) && ((p_cb->rcb[i].status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT)) { @@ -652,7 +656,8 @@ void bta_av_rc_meta_rsp(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data) (!p_data->api_meta_rsp.is_rsp && (p_cb->features & BTA_AV_FEAT_RCCT)) ) { p_rcb = &p_cb->rcb[p_data->hdr.layer_specific]; - AVRC_MsgReq(p_rcb->handle, p_data->api_meta_rsp.label, p_data->api_meta_rsp.rsp_code, p_data->api_meta_rsp.p_pkt); + AVRC_MsgReq(p_rcb->handle, p_data->api_meta_rsp.label, p_data->api_meta_rsp.rsp_code, + p_data->api_meta_rsp.p_pkt); free = FALSE; } } @@ -798,13 +803,15 @@ tBTA_AV_EVT bta_av_proc_meta_cmd(tAVRC_RESPONSE *p_rc_rsp, tBTA_AV_RC_MSG *p_ms { *p_ctype = AVRC_RSP_IMPL_STBL; p_rc_rsp->get_caps.count = p_bta_av_cfg->num_co_ids; - memcpy(p_rc_rsp->get_caps.param.company_id, p_bta_av_cfg->p_meta_co_ids, (p_bta_av_cfg->num_co_ids << 2)); + memcpy(p_rc_rsp->get_caps.param.company_id, p_bta_av_cfg->p_meta_co_ids, + (p_bta_av_cfg->num_co_ids << 2)); } else if (u8 == AVRC_CAP_EVENTS_SUPPORTED) { *p_ctype = AVRC_RSP_IMPL_STBL; p_rc_rsp->get_caps.count = p_bta_av_cfg->num_evt_ids; - memcpy(p_rc_rsp->get_caps.param.event_id, p_bta_av_cfg->p_meta_evt_ids, p_bta_av_cfg->num_evt_ids); + memcpy(p_rc_rsp->get_caps.param.event_id, p_bta_av_cfg->p_meta_evt_ids, + p_bta_av_cfg->num_evt_ids); } else { @@ -864,7 +871,9 @@ void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data) p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_NOT_IMPL; #if (AVRC_METADATA_INCLUDED == TRUE) if (p_cb->features & BTA_AV_FEAT_METADATA) - p_data->rc_msg.msg.hdr.ctype = bta_av_group_navi_supported(p_data->rc_msg.msg.pass.pass_len, p_data->rc_msg.msg.pass.p_pass_data); + p_data->rc_msg.msg.hdr.ctype = + bta_av_group_navi_supported(p_data->rc_msg.msg.pass.pass_len, + p_data->rc_msg.msg.pass.p_pass_data); #endif } else @@ -1081,7 +1090,8 @@ void bta_av_stream_chg(tBTA_AV_SCB *p_scb, BOOLEAN started) tBTA_AV_SCB *p_scbi; started_msk = BTA_AV_HNDL_TO_MSK(p_scb->hdi); - APPL_TRACE_DEBUG3 ("bta_av_stream_chg started:%d started_msk:x%x chnl:x%x", started, started_msk, p_scb->chnl); + APPL_TRACE_DEBUG3 ("bta_av_stream_chg started:%d started_msk:x%x chnl:x%x", started, + started_msk, p_scb->chnl); if (BTA_AV_CHNL_AUDIO == p_scb->chnl) p_streams = &bta_av_cb.audio_streams; else @@ -1114,7 +1124,8 @@ void bta_av_stream_chg(tBTA_AV_SCB *p_scb, BOOLEAN started) for (; i<BTA_AV_NUM_STRS; i++) { p_scbi = bta_av_cb.p_scb[i]; - if ( p_scbi && (bta_av_cb.audio_streams & BTA_AV_HNDL_TO_MSK(i)) /* scb is used and started */ + /* scb is used and started */ + if ( p_scbi && (bta_av_cb.audio_streams & BTA_AV_HNDL_TO_MSK(i)) && bdcmp(p_scbi->peer_addr, p_scb->peer_addr) == 0) { no_streams = FALSE; @@ -1125,7 +1136,8 @@ void bta_av_stream_chg(tBTA_AV_SCB *p_scb, BOOLEAN started) } } - APPL_TRACE_DEBUG4 ("no_streams:%d i:%d, audio_streams:x%x, video_streams:x%x", no_streams, i, bta_av_cb.audio_streams, bta_av_cb.video_streams); + APPL_TRACE_DEBUG4 ("no_streams:%d i:%d, audio_streams:x%x, video_streams:x%x", no_streams, i, + bta_av_cb.audio_streams, bta_av_cb.video_streams); if (no_streams) { /* Let L2CAP know this channel is processed with low priority */ @@ -1178,7 +1190,9 @@ void bta_av_conn_chg(tBTA_AV_DATA *p_data) if (bta_av_cb.rcb[i].lidx == p_lcb->lidx) { bta_av_cb.rcb[i].shdl = index + 1; - APPL_TRACE_DEBUG5("conn_chg up[%d]: %d, status=0x%x, shdl:%d, lidx:%d", i, bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status, bta_av_cb.rcb[i].shdl, bta_av_cb.rcb[i].lidx); + APPL_TRACE_DEBUG5("conn_chg up[%d]: %d, status=0x%x, shdl:%d, lidx:%d", i, + bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status, + bta_av_cb.rcb[i].shdl, bta_av_cb.rcb[i].lidx); break; } } @@ -1206,13 +1220,17 @@ void bta_av_conn_chg(tBTA_AV_DATA *p_data) if(p_lcb && p_cb->rc_acp_handle != BTA_AV_RC_HANDLE_NONE && p_cb->rc_acp_idx) { p_lcb_rc = &p_cb->lcb[BTA_AV_NUM_LINKS]; - APPL_TRACE_DEBUG1("rc_acp is connected && conn_chg on same addr p_lcb_rc->conn_msk:x%x", p_lcb_rc->conn_msk); + APPL_TRACE_DEBUG1("rc_acp is connected && conn_chg on same addr p_lcb_rc->conn_msk:x%x", + p_lcb_rc->conn_msk); /* check if the RC is connected to the scb addr */ APPL_TRACE_DEBUG6 ("p_lcb_rc->addr: %02x:%02x:%02x:%02x:%02x:%02x", - p_lcb_rc->addr[0], p_lcb_rc->addr[1], p_lcb_rc->addr[2], p_lcb_rc->addr[3], p_lcb_rc->addr[4], p_lcb_rc->addr[5]); + p_lcb_rc->addr[0], p_lcb_rc->addr[1], p_lcb_rc->addr[2], p_lcb_rc->addr[3], + p_lcb_rc->addr[4], p_lcb_rc->addr[5]); APPL_TRACE_DEBUG6 ("conn_chg.peer_addr: %02x:%02x:%02x:%02x:%02x:%02x", - p_data->conn_chg.peer_addr[0], p_data->conn_chg.peer_addr[1], p_data->conn_chg.peer_addr[2], - p_data->conn_chg.peer_addr[3], p_data->conn_chg.peer_addr[4], p_data->conn_chg.peer_addr[5]); + p_data->conn_chg.peer_addr[0], p_data->conn_chg.peer_addr[1], + p_data->conn_chg.peer_addr[2], + p_data->conn_chg.peer_addr[3], p_data->conn_chg.peer_addr[4], + p_data->conn_chg.peer_addr[5]); if (p_lcb_rc->conn_msk && bdcmp(p_lcb_rc->addr, p_data->conn_chg.peer_addr) == 0) { /* AVRCP is already connected. @@ -1222,7 +1240,8 @@ void bta_av_conn_chg(tBTA_AV_DATA *p_data) p_scb->rc_handle = p_cb->rc_acp_handle; p_rcb = &p_cb->rcb[p_cb->rc_acp_idx - 1]; p_rcb->shdl = bta_av_get_shdl(p_scb); - APPL_TRACE_DEBUG3("update rc_acp shdl:%d/%d srch:%d", index + 1, p_rcb->shdl, p_scb->rc_handle ); + APPL_TRACE_DEBUG3("update rc_acp shdl:%d/%d srch:%d", index + 1, p_rcb->shdl, + p_scb->rc_handle ); p_rcb2 = bta_av_get_rcb_by_shdl(p_rcb->shdl); if (p_rcb2) @@ -1230,12 +1249,15 @@ void bta_av_conn_chg(tBTA_AV_DATA *p_data) /* found the RCB that was created to associated with this SCB */ p_cb->rc_acp_handle = p_rcb2->handle; p_cb->rc_acp_idx = (p_rcb2 - p_cb->rcb) + 1; - APPL_TRACE_DEBUG2("new rc_acp_handle:%d, idx:%d", p_cb->rc_acp_handle, p_cb->rc_acp_idx); + APPL_TRACE_DEBUG2("new rc_acp_handle:%d, idx:%d", p_cb->rc_acp_handle, + p_cb->rc_acp_idx); p_rcb2->lidx = (BTA_AV_NUM_LINKS + 1); - APPL_TRACE_DEBUG3("rc2 handle:%d lidx:%d/%d",p_rcb2->handle, p_rcb2->lidx, p_cb->lcb[p_rcb2->lidx-1].lidx); + APPL_TRACE_DEBUG3("rc2 handle:%d lidx:%d/%d",p_rcb2->handle, p_rcb2->lidx, + p_cb->lcb[p_rcb2->lidx-1].lidx); } p_rcb->lidx = p_lcb->lidx; - APPL_TRACE_DEBUG3("rc handle:%d lidx:%d/%d",p_rcb->handle, p_rcb->lidx, p_cb->lcb[p_rcb->lidx-1].lidx); + APPL_TRACE_DEBUG3("rc handle:%d lidx:%d/%d",p_rcb->handle, p_rcb->lidx, + p_cb->lcb[p_rcb->lidx-1].lidx); } } } @@ -1276,7 +1298,9 @@ void bta_av_conn_chg(tBTA_AV_DATA *p_data) APPL_TRACE_DEBUG1("bta_av_conn_chg shdl:%d", index + 1); for (i=0; i<BTA_AV_NUM_RCB; i++) { - APPL_TRACE_DEBUG5("conn_chg dn[%d]: %d, status=0x%x, shdl:%d, lidx:%d", i, bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status, bta_av_cb.rcb[i].shdl, bta_av_cb.rcb[i].lidx); + APPL_TRACE_DEBUG5("conn_chg dn[%d]: %d, status=0x%x, shdl:%d, lidx:%d", i, + bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status, + bta_av_cb.rcb[i].shdl, bta_av_cb.rcb[i].lidx); if(bta_av_cb.rcb[i].shdl == index + 1) { bta_av_del_rc(&bta_av_cb.rcb[i]); @@ -1431,7 +1455,12 @@ void bta_av_sig_chg(tBTA_AV_DATA *p_data) p_cb->p_scb[xx]->use_rc = TRUE; /* allowing RC for incoming connection */ bta_av_ssm_execute(p_cb->p_scb[xx], BTA_AV_ACP_CONNECT_EVT, p_data); - bta_sys_start_timer(&p_cb->sig_tmr, BTA_AV_SIG_TIMER_EVT, BTA_AV_SIG_TIME_VAL); + /* The Pending Event should be sent as soon as the L2CAP signalling channel + * is set up, which is NOW. Earlier this was done only after + * BTA_AV_SIG_TIME_VAL milliseconds. + * The following function shall send the event and start the recurring timer + */ + bta_av_sig_timer(NULL); /* Possible collision : need to avoid outgoing processing while the timer is running */ p_cb->p_scb[xx]->coll_mask = BTA_AV_COLL_INC_TMR; diff --git a/bta/av/bta_av_int.h b/bta/av/bta_av_int.h index 9e7f510..41fb565 100644 --- a/bta/av/bta_av_int.h +++ b/bta/av/bta_av_int.h @@ -18,6 +18,7 @@ #include "avdt_api.h" #include "bta_av_co.h" +#define BTA_AV_DEBUG TRUE /***************************************************************************** ** Constants *****************************************************************************/ diff --git a/btif/co/bta_av_co.c b/btif/co/bta_av_co.c index 34a9a00..1dbd940 100644 --- a/btif/co/bta_av_co.c +++ b/btif/co/bta_av_co.c @@ -216,7 +216,7 @@ static tBTA_AV_CO_PEER *bta_av_co_get_peer(tBTA_AV_HNDL hndl) FUNC_TRACE(); index = BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl); - + APPL_TRACE_ERROR2("%s index:%d", __FUNCTION__, index); /* Sanity check */ if (index >= BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers)) { @@ -1008,7 +1008,6 @@ static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT /* Configure the codec type to look for */ codec_type = bta_av_co_cb.codec_cfg.id; - for (index = 0; index < p_peer->num_sup_snks; index++) { if (p_peer->snks[index].codec_type == codec_type) @@ -1379,6 +1378,12 @@ void bta_av_co_init(void) /* Reset the control block */ memset(&bta_av_co_cb, 0, sizeof(bta_av_co_cb)); +#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) + bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_NEVER); +#else + bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_FREE); +#endif + /* Reset the current config */ bta_av_co_audio_codec_reset(); } diff --git a/btif/include/uinput.h b/btif/include/uinput.h new file mode 100644 index 0000000..303f4f3 --- /dev/null +++ b/btif/include/uinput.h @@ -0,0 +1,611 @@ +/************************************************************************************ + * + * Copyright (C) 2009-2011 Broadcom Corporation + * + * This program is the proprietary software of Broadcom Corporation and/or its + * licensors, and may only be used, duplicated, modified or distributed + * pursuant to the terms and conditions of a separate, written license + * agreement executed between you and Broadcom (an "Authorized License"). + * Except as set forth in an Authorized License, Broadcom grants no license + * (express or implied), right to use, or waiver of any kind with respect to + * the Software, and Broadcom expressly reserves all rights in and to the + * Software and all intellectual property rights therein. + * IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS + * SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE + * ALL USE OF THE SOFTWARE. + * + * Except as expressly set forth in the Authorized License, + * + * 1. This program, including its structure, sequence and organization, + * constitutes the valuable trade secrets of Broadcom, and you shall + * use all reasonable efforts to protect the confidentiality thereof, + * and to use this information only in connection with your use of + * Broadcom integrated circuit products. + * + * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED + * "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, + * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, + * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY + * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, + * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, + * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR + * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT + * OF USE OR PERFORMANCE OF THE SOFTWARE. + * + * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR + * ITS LICENSORS BE LIABLE FOR + * (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY + * DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO + * YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM + * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR + * (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE + * SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE + * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF + * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. + * + ************************************************************************************/ +/* TBD: tmp code here */ + +#ifndef __UINPUT_H +#define __UINPUT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <sys/time.h> +#include <sys/ioctl.h> + +/* Events */ + +#define EV_SYN 0x00 +#define EV_KEY 0x01 +#define EV_REL 0x02 +#define EV_ABS 0x03 +#define EV_MSC 0x04 +#define EV_LED 0x11 +#define EV_SND 0x12 +#define EV_REP 0x14 +#define EV_FF 0x15 +#define EV_PWR 0x16 +#define EV_FF_STATUS 0x17 +#define EV_MAX 0x1f + +/* Synchronization events */ + +#define SYN_REPORT 0 +#define SYN_CONFIG 1 + +/* Keys and buttons */ + +#define KEY_RESERVED 0 +#define KEY_ESC 1 +#define KEY_1 2 +#define KEY_2 3 +#define KEY_3 4 +#define KEY_4 5 +#define KEY_5 6 +#define KEY_6 7 +#define KEY_7 8 +#define KEY_8 9 +#define KEY_9 10 +#define KEY_0 11 +#define KEY_MINUS 12 +#define KEY_EQUAL 13 +#define KEY_BACKSPACE 14 +#define KEY_TAB 15 +#define KEY_Q 16 +#define KEY_W 17 +#define KEY_E 18 +#define KEY_R 19 +#define KEY_T 20 +#define KEY_Y 21 +#define KEY_U 22 +#define KEY_I 23 +#define KEY_O 24 +#define KEY_P 25 +#define KEY_LEFTBRACE 26 +#define KEY_RIGHTBRACE 27 +#define KEY_ENTER 28 +#define KEY_LEFTCTRL 29 +#define KEY_A 30 +#define KEY_S 31 +#define KEY_D 32 +#define KEY_F 33 +#define KEY_G 34 +#define KEY_H 35 +#define KEY_J 36 +#define KEY_K 37 +#define KEY_L 38 +#define KEY_SEMICOLON 39 +#define KEY_APOSTROPHE 40 +#define KEY_GRAVE 41 +#define KEY_LEFTSHIFT 42 +#define KEY_BACKSLASH 43 +#define KEY_Z 44 +#define KEY_X 45 +#define KEY_C 46 +#define KEY_V 47 +#define KEY_B 48 +#define KEY_N 49 +#define KEY_M 50 +#define KEY_COMMA 51 +#define KEY_DOT 52 +#define KEY_SLASH 53 +#define KEY_RIGHTSHIFT 54 +#define KEY_KPASTERISK 55 +#define KEY_LEFTALT 56 +#define KEY_SPACE 57 +#define KEY_CAPSLOCK 58 +#define KEY_F1 59 +#define KEY_F2 60 +#define KEY_F3 61 +#define KEY_F4 62 +#define KEY_F5 63 +#define KEY_F6 64 +#define KEY_F7 65 +#define KEY_F8 66 +#define KEY_F9 67 +#define KEY_F10 68 +#define KEY_NUMLOCK 69 +#define KEY_SCROLLLOCK 70 +#define KEY_KP7 71 +#define KEY_KP8 72 +#define KEY_KP9 73 +#define KEY_KPMINUS 74 +#define KEY_KP4 75 +#define KEY_KP5 76 +#define KEY_KP6 77 +#define KEY_KPPLUS 78 +#define KEY_KP1 79 +#define KEY_KP2 80 +#define KEY_KP3 81 +#define KEY_KP0 82 +#define KEY_KPDOT 83 +#define KEY_103RD 84 +#define KEY_F13 85 +#define KEY_102ND 86 +#define KEY_F11 87 +#define KEY_F12 88 +#define KEY_F14 89 +#define KEY_F15 90 +#define KEY_F16 91 +#define KEY_F17 92 +#define KEY_F18 93 +#define KEY_F19 94 +#define KEY_F20 95 +#define KEY_KPENTER 96 +#define KEY_RIGHTCTRL 97 +#define KEY_KPSLASH 98 +#define KEY_SYSRQ 99 +#define KEY_RIGHTALT 100 +#define KEY_LINEFEED 101 +#define KEY_HOME 102 +#define KEY_UP 103 +#define KEY_PAGEUP 104 +#define KEY_LEFT 105 +#define KEY_RIGHT 106 +#define KEY_END 107 +#define KEY_DOWN 108 +#define KEY_PAGEDOWN 109 +#define KEY_INSERT 110 +#define KEY_DELETE 111 +#define KEY_MACRO 112 +#define KEY_MUTE 113 +#define KEY_VOLUMEDOWN 114 +#define KEY_VOLUMEUP 115 +#define KEY_POWER 116 +#define KEY_KPEQUAL 117 +#define KEY_KPPLUSMINUS 118 +#define KEY_PAUSE 119 +#define KEY_F21 120 +#define KEY_F22 121 +#define KEY_F23 122 +#define KEY_F24 123 +#define KEY_KPCOMMA 124 +#define KEY_LEFTMETA 125 +#define KEY_RIGHTMETA 126 +#define KEY_COMPOSE 127 + +#define KEY_STOP 128 +#define KEY_AGAIN 129 +#define KEY_PROPS 130 +#define KEY_UNDO 131 +#define KEY_FRONT 132 +#define KEY_COPY 133 +#define KEY_OPEN 134 +#define KEY_PASTE 135 +#define KEY_FIND 136 +#define KEY_CUT 137 +#define KEY_HELP 138 +#define KEY_MENU 139 +#define KEY_CALC 140 +#define KEY_SETUP 141 +#define KEY_SLEEP 142 +#define KEY_WAKEUP 143 +#define KEY_FILE 144 +#define KEY_SENDFILE 145 +#define KEY_DELETEFILE 146 +#define KEY_XFER 147 +#define KEY_PROG1 148 +#define KEY_PROG2 149 +#define KEY_WWW 150 +#define KEY_MSDOS 151 +#define KEY_COFFEE 152 +#define KEY_DIRECTION 153 +#define KEY_CYCLEWINDOWS 154 +#define KEY_MAIL 155 +#define KEY_BOOKMARKS 156 +#define KEY_COMPUTER 157 +#define KEY_BACK 158 +#define KEY_FORWARD 159 +#define KEY_CLOSECD 160 +#define KEY_EJECTCD 161 +#define KEY_EJECTCLOSECD 162 +#define KEY_NEXTSONG 163 +#define KEY_PLAYPAUSE 164 +#define KEY_PREVIOUSSONG 165 +#define KEY_STOPCD 166 +#define KEY_RECORD 167 +#define KEY_REWIND 168 +#define KEY_PHONE 169 +#define KEY_ISO 170 +#define KEY_CONFIG 171 +#define KEY_HOMEPAGE 172 +#define KEY_REFRESH 173 +#define KEY_EXIT 174 +#define KEY_MOVE 175 +#define KEY_EDIT 176 +#define KEY_SCROLLUP 177 +#define KEY_SCROLLDOWN 178 +#define KEY_KPLEFTPAREN 179 +#define KEY_KPRIGHTPAREN 180 + +#define KEY_INTL1 181 +#define KEY_INTL2 182 +#define KEY_INTL3 183 +#define KEY_INTL4 184 +#define KEY_INTL5 185 +#define KEY_INTL6 186 +#define KEY_INTL7 187 +#define KEY_INTL8 188 +#define KEY_INTL9 189 +#define KEY_LANG1 190 +#define KEY_LANG2 191 +#define KEY_LANG3 192 +#define KEY_LANG4 193 +#define KEY_LANG5 194 +#define KEY_LANG6 195 +#define KEY_LANG7 196 +#define KEY_LANG8 197 +#define KEY_LANG9 198 + +#define KEY_PLAYCD 200 +#define KEY_PAUSECD 201 +#define KEY_PROG3 202 +#define KEY_PROG4 203 +#define KEY_SUSPEND 205 +#define KEY_CLOSE 206 +#define KEY_PLAY 207 + +#define KEY_UNKNOWN 220 + +#define KEY_BRIGHTNESSDOWN 224 +#define KEY_BRIGHTNESSUP 225 + +#define BTN_MISC 0x100 +#define BTN_0 0x100 +#define BTN_1 0x101 +#define BTN_2 0x102 +#define BTN_3 0x103 +#define BTN_4 0x104 +#define BTN_5 0x105 +#define BTN_6 0x106 +#define BTN_7 0x107 +#define BTN_8 0x108 +#define BTN_9 0x109 + +#define BTN_MOUSE 0x110 +#define BTN_LEFT 0x110 +#define BTN_RIGHT 0x111 +#define BTN_MIDDLE 0x112 +#define BTN_SIDE 0x113 +#define BTN_EXTRA 0x114 +#define BTN_FORWARD 0x115 +#define BTN_BACK 0x116 +#define BTN_TASK 0x117 + +#define BTN_JOYSTICK 0x120 +#define BTN_TRIGGER 0x120 +#define BTN_THUMB 0x121 +#define BTN_THUMB2 0x122 +#define BTN_TOP 0x123 +#define BTN_TOP2 0x124 +#define BTN_PINKIE 0x125 +#define BTN_BASE 0x126 +#define BTN_BASE2 0x127 +#define BTN_BASE3 0x128 +#define BTN_BASE4 0x129 +#define BTN_BASE5 0x12a +#define BTN_BASE6 0x12b +#define BTN_DEAD 0x12f + +#define BTN_GAMEPAD 0x130 +#define BTN_A 0x130 +#define BTN_B 0x131 +#define BTN_C 0x132 +#define BTN_X 0x133 +#define BTN_Y 0x134 +#define BTN_Z 0x135 +#define BTN_TL 0x136 +#define BTN_TR 0x137 +#define BTN_TL2 0x138 +#define BTN_TR2 0x139 +#define BTN_SELECT 0x13a +#define BTN_START 0x13b +#define BTN_MODE 0x13c +#define BTN_THUMBL 0x13d +#define BTN_THUMBR 0x13e + +#define BTN_DIGI 0x140 +#define BTN_TOOL_PEN 0x140 +#define BTN_TOOL_RUBBER 0x141 +#define BTN_TOOL_BRUSH 0x142 +#define BTN_TOOL_PENCIL 0x143 +#define BTN_TOOL_AIRBRUSH 0x144 +#define BTN_TOOL_FINGER 0x145 +#define BTN_TOOL_MOUSE 0x146 +#define BTN_TOOL_LENS 0x147 +#define BTN_TOUCH 0x14a +#define BTN_STYLUS 0x14b +#define BTN_STYLUS2 0x14c +#define BTN_TOOL_DOUBLETAP 0x14d +#define BTN_TOOL_TRIPLETAP 0x14e + +#define BTN_WHEEL 0x150 +#define BTN_GEAR_DOWN 0x150 +#define BTN_GEAR_UP 0x151 + +#define KEY_OK 0x160 +#define KEY_SELECT 0x161 +#define KEY_GOTO 0x162 +#define KEY_CLEAR 0x163 +#define KEY_POWER2 0x164 +#define KEY_OPTION 0x165 +#define KEY_INFO 0x166 +#define KEY_TIME 0x167 +#define KEY_VENDOR 0x168 +#define KEY_ARCHIVE 0x169 +#define KEY_PROGRAM 0x16a +#define KEY_CHANNEL 0x16b +#define KEY_FAVORITES 0x16c +#define KEY_EPG 0x16d +#define KEY_PVR 0x16e +#define KEY_MHP 0x16f +#define KEY_LANGUAGE 0x170 +#define KEY_TITLE 0x171 +#define KEY_SUBTITLE 0x172 +#define KEY_ANGLE 0x173 +#define KEY_ZOOM 0x174 +#define KEY_MODE 0x175 +#define KEY_KEYBOARD 0x176 +#define KEY_SCREEN 0x177 +#define KEY_PC 0x178 +#define KEY_TV 0x179 +#define KEY_TV2 0x17a +#define KEY_VCR 0x17b +#define KEY_VCR2 0x17c +#define KEY_SAT 0x17d +#define KEY_SAT2 0x17e +#define KEY_CD 0x17f +#define KEY_TAPE 0x180 +#define KEY_RADIO 0x181 +#define KEY_TUNER 0x182 +#define KEY_PLAYER 0x183 +#define KEY_TEXT 0x184 +#define KEY_DVD 0x185 +#define KEY_AUX 0x186 +#define KEY_MP3 0x187 +#define KEY_AUDIO 0x188 +#define KEY_VIDEO 0x189 +#define KEY_DIRECTORY 0x18a +#define KEY_LIST 0x18b +#define KEY_MEMO 0x18c +#define KEY_CALENDAR 0x18d +#define KEY_RED 0x18e +#define KEY_GREEN 0x18f +#define KEY_YELLOW 0x190 +#define KEY_BLUE 0x191 +#define KEY_CHANNELUP 0x192 +#define KEY_CHANNELDOWN 0x193 +#define KEY_FIRST 0x194 +#define KEY_LAST 0x195 +#define KEY_AB 0x196 +#define KEY_NEXT 0x197 +#define KEY_RESTART 0x198 +#define KEY_SLOW 0x199 +#define KEY_SHUFFLE 0x19a +#define KEY_BREAK 0x19b +#define KEY_PREVIOUS 0x19c +#define KEY_DIGITS 0x19d +#define KEY_TEEN 0x19e +#define KEY_TWEN 0x19f + +#define KEY_FRAMEBACK 0x1b2 +#define KEY_FRAMEFORWARD 0x1b3 +#define KEY_CONTEXT_MENU 0x1fb + +#define KEY_MAX 0x1ff + +/* Relative axes */ + +#define REL_X 0x00 +#define REL_Y 0x01 +#define REL_Z 0x02 +#define REL_RX 0x03 +#define REL_RY 0x04 +#define REL_RZ 0x05 +#define REL_HWHEEL 0x06 +#define REL_DIAL 0x07 +#define REL_WHEEL 0x08 +#define REL_MISC 0x09 +#define REL_MAX 0x0f + +/* Absolute axes */ + +#define ABS_X 0x00 +#define ABS_Y 0x01 +#define ABS_Z 0x02 +#define ABS_RX 0x03 +#define ABS_RY 0x04 +#define ABS_RZ 0x05 +#define ABS_THROTTLE 0x06 +#define ABS_RUDDER 0x07 +#define ABS_WHEEL 0x08 +#define ABS_GAS 0x09 +#define ABS_BRAKE 0x0a +#define ABS_HAT0X 0x10 +#define ABS_HAT0Y 0x11 +#define ABS_HAT1X 0x12 +#define ABS_HAT1Y 0x13 +#define ABS_HAT2X 0x14 +#define ABS_HAT2Y 0x15 +#define ABS_HAT3X 0x16 +#define ABS_HAT3Y 0x17 +#define ABS_PRESSURE 0x18 +#define ABS_DISTANCE 0x19 +#define ABS_TILT_X 0x1a +#define ABS_TILT_Y 0x1b +#define ABS_TOOL_WIDTH 0x1c +#define ABS_VOLUME 0x20 +#define ABS_MISC 0x28 +#define ABS_MAX 0x3f + +/* Switch events */ + +#define SW_0 0x00 +#define SW_1 0x01 +#define SW_2 0x02 +#define SW_3 0x03 +#define SW_4 0x04 +#define SW_5 0x05 +#define SW_6 0x06 +#define SW_7 0x07 +#define SW_MAX 0x0f + +/* Misc events */ + +#define MSC_SERIAL 0x00 +#define MSC_PULSELED 0x01 +#define MSC_GESTURE 0x02 +#define MSC_RAW 0x03 +#define MSC_SCAN 0x04 +#define MSC_MAX 0x07 + +/* LEDs */ + +#define LED_NUML 0x00 +#define LED_CAPSL 0x01 +#define LED_SCROLLL 0x02 +#define LED_COMPOSE 0x03 +#define LED_KANA 0x04 +#define LED_SLEEP 0x05 +#define LED_SUSPEND 0x06 +#define LED_MUTE 0x07 +#define LED_MISC 0x08 +#define LED_MAIL 0x09 +#define LED_CHARGING 0x0a +#define LED_MAX 0x0f + +/* Autorepeat values */ + +#define REP_DELAY 0x00 +#define REP_PERIOD 0x01 +#define REP_MAX 0x01 + +/* Sounds */ + +#define SND_CLICK 0x00 +#define SND_BELL 0x01 +#define SND_TONE 0x02 +#define SND_MAX 0x07 + +/* Identifiers */ + +#define ID_BUS 0 +#define ID_VENDOR 1 +#define ID_PRODUCT 2 +#define ID_VERSION 3 + +#define BUS_PCI 0x01 +#define BUS_ISAPNP 0x02 +#define BUS_USB 0x03 +#define BUS_HIL 0x04 +#define BUS_BLUETOOTH 0x05 + +#define BUS_ISA 0x10 +#define BUS_I8042 0x11 +#define BUS_XTKBD 0x12 +#define BUS_RS232 0x13 +#define BUS_GAMEPORT 0x14 +#define BUS_PARPORT 0x15 +#define BUS_AMIGA 0x16 +#define BUS_ADB 0x17 +#define BUS_I2C 0x18 +#define BUS_HOST 0x19 +#define BUS_GSC 0x1A + +/* User input interface */ + +#define UINPUT_IOCTL_BASE 'U' + +#define UI_DEV_CREATE _IO(UINPUT_IOCTL_BASE, 1) +#define UI_DEV_DESTROY _IO(UINPUT_IOCTL_BASE, 2) + +#define UI_SET_EVBIT _IOW(UINPUT_IOCTL_BASE, 100, int) +#define UI_SET_KEYBIT _IOW(UINPUT_IOCTL_BASE, 101, int) +#define UI_SET_RELBIT _IOW(UINPUT_IOCTL_BASE, 102, int) +#define UI_SET_ABSBIT _IOW(UINPUT_IOCTL_BASE, 103, int) +#define UI_SET_MSCBIT _IOW(UINPUT_IOCTL_BASE, 104, int) +#define UI_SET_LEDBIT _IOW(UINPUT_IOCTL_BASE, 105, int) +#define UI_SET_SNDBIT _IOW(UINPUT_IOCTL_BASE, 106, int) +#define UI_SET_FFBIT _IOW(UINPUT_IOCTL_BASE, 107, int) +#define UI_SET_PHYS _IOW(UINPUT_IOCTL_BASE, 108, char*) +#define UI_SET_SWBIT _IOW(UINPUT_IOCTL_BASE, 109, int) + +#ifndef NBITS +#define NBITS(x) ((((x) - 1) / (sizeof(long) * 8)) + 1) +#endif + +#define UINPUT_MAX_NAME_SIZE 80 + +struct uinput_id { + uint16_t bustype; + uint16_t vendor; + uint16_t product; + uint16_t version; +}; + +struct uinput_dev { + char name[UINPUT_MAX_NAME_SIZE]; + struct uinput_id id; + int ff_effects_max; + int absmax[ABS_MAX + 1]; + int absmin[ABS_MAX + 1]; + int absfuzz[ABS_MAX + 1]; + int absflat[ABS_MAX + 1]; +}; + +struct uinput_event { + struct timeval time; + uint16_t type; + uint16_t code; + int32_t value; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __UINPUT_H */ diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c index d383926..a822c7f 100644 --- a/btif/src/btif_av.c +++ b/btif/src/btif_av.c @@ -62,12 +62,16 @@ #include "bta_api.h" #include "bta_av_api.h" #include "gki.h" +#include "bd.h" +#include "btu.h" /***************************************************************************** ** Constants & Macros ******************************************************************************/ #define BTIF_AV_SERVICE_NAME "Advanced Audio" +#define BTIF_TIMEOUT_AV_OPEN_ON_RC 2 /* 2 seconds */ + typedef enum { BTIF_AV_STATE_IDLE = 0x0, BTIF_AV_STATE_OPENING, @@ -99,6 +103,8 @@ typedef struct static btav_callbacks_t *bt_av_callbacks = NULL; static btif_av_cb_t btif_av_cb; +static TIMER_LIST_ENT tle_av_open_on_rc; + #define CHECK_BTAV_INIT() if (bt_av_callbacks == NULL)\ {\ BTIF_TRACE_WARNING1("%s: BTAV not initialized", __FUNCTION__);\ @@ -109,6 +115,18 @@ else\ BTIF_TRACE_EVENT1("%s", __FUNCTION__);\ } +/* Helper macro to avoid code duplication in the state machine handlers */ +#define CHECK_RC_EVENT(e, d) \ + case BTA_AV_RC_OPEN_EVT: \ + case BTA_AV_RC_CLOSE_EVT: \ + case BTA_AV_REMOTE_CMD_EVT: \ + case BTA_AV_VENDOR_CMD_EVT: \ + case BTA_AV_META_MSG_EVT: \ + case BTA_AV_RC_FEAT_EVT: \ + { \ + btif_rc_handler(e, d);\ + }break; \ + static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *data); static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *data); static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *data); @@ -123,6 +141,13 @@ static const btif_sm_handler_t btif_av_state_handlers[] = }; +/************************************************************************* +** Extern functions +*************************************************************************/ +extern void btif_rc_init(void); +extern void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data); +extern BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr); + /***************************************************************************** ** Local helper functions ******************************************************************************/ @@ -173,6 +198,36 @@ const char *dump_av_sm_event_name(btif_av_sm_event_t event) } } + +/**************************************************************************** +** Local helper functions +*****************************************************************************/ +/******************************************************************************* +** +** Function btif_initiate_av_open_tmr_hdlr +** +** Description Timer to trigger AV open if the remote headset establishes +** RC connection w/o AV connection. The timer is needed to IOP +** with headsets that do establish AV after RC connection. +** +** Returns void +** +*******************************************************************************/ +static void btif_initiate_av_open_tmr_hdlr(TIMER_LIST_ENT *tle) +{ + BD_ADDR peer_addr; + + /* is there at least one RC connection - There should be */ + if (btif_rc_get_connected_peer(peer_addr)) { + BTIF_TRACE_DEBUG1("%s Issuing connect to the remote RC peer", __FUNCTION__); + btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (void*)&peer_addr); + } + else + { + BTIF_TRACE_ERROR1("%s No connected RC peers", __FUNCTION__); + } +} + /***************************************************************************** ** Static functions ******************************************************************************/ @@ -210,16 +265,54 @@ static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data) { btif_av_cb.bta_handle = ((tBTA_AV*)p_data)->registr.hndl; } break; - + case BTA_AV_PENDING_EVT: case BTIF_AV_CONNECT_REQ_EVT: { + if (event == BTIF_AV_CONNECT_REQ_EVT) + { memcpy(&btif_av_cb.peer_bda, (bt_bdaddr_t*)p_data, sizeof(bt_bdaddr_t)); - BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle, TRUE, BTA_SEC_NONE); - + } + else if (event == BTA_AV_PENDING_EVT) + { + bdcpy(btif_av_cb.peer_bda.address, ((tBTA_AV*)p_data)->pend.bd_addr); + } btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENING); } break; + case BTA_AV_RC_OPEN_EVT: + { + /* IOP_FIX: Jabra 620 only does RC open without AV open whenever it connects. So + * as per the AV WP, an AVRC connection cannot exist without an AV connection. Therefore, + * we initiate an AV connection if an RC_OPEN_EVT is received when we are in AV_CLOSED state. + * We initiate the AV connection after a small 3s timeout to avoid any collisions from the + * headsets, as some headsets initiate the AVRC connection first and then + * immediately initiate the AV connection + * + * TODO: We may need to do this only on an AVRCP Play. FixMe + */ + BTIF_TRACE_DEBUG0("BTA_AV_RC_OPEN_EVT received w/o AV"); + memset(&tle_av_open_on_rc, 0, sizeof(tle_av_open_on_rc)); + tle_av_open_on_rc.param = (UINT32)btif_initiate_av_open_tmr_hdlr; + btu_start_timer(&tle_av_open_on_rc, BTU_TTYPE_USER_FUNC, + BTIF_TIMEOUT_AV_OPEN_ON_RC); + btif_rc_handler(event, p_data); + }break; + case BTA_AV_REMOTE_CMD_EVT: + case BTA_AV_VENDOR_CMD_EVT: + case BTA_AV_META_MSG_EVT: + case BTA_AV_RC_FEAT_EVT: + { + btif_rc_handler(event, (tBTA_AV*)p_data); + }break; + case BTA_AV_RC_CLOSE_EVT: + { + if (tle_av_open_on_rc.in_use) { + BTIF_TRACE_DEBUG0("BTA_AV_RC_CLOSE_EVT: Stopping AV timer."); + btu_stop_timer(&tle_av_open_on_rc); + } + btif_rc_handler(event, p_data); + }break; default: BTIF_TRACE_WARNING2("%s Unhandled event:%s", __FUNCTION__, @@ -228,7 +321,6 @@ static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data) return TRUE; } - static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data) { BTIF_TRACE_DEBUG2("%s event:%s", __FUNCTION__, dump_av_sm_event_name(event)); @@ -248,26 +340,30 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data case BTA_AV_OPEN_EVT: { tBTA_AV *p_bta_data = (tBTA_AV*)p_data; - btav_connection_state_t state = BTAV_CONNECTION_STATE_DISCONNECTED; + btav_connection_state_t state; + btif_sm_state_t av_state; BTIF_TRACE_DEBUG1("status:%d", p_bta_data->open.status); if (p_bta_data->open.status == BTA_AV_SUCCESS) { state = BTAV_CONNECTION_STATE_CONNECTED; - /* change state to open */ - btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED); + av_state = BTIF_AV_STATE_OPENED; } else { BTIF_TRACE_WARNING1("BTA_AV_OPEN_EVT::FAILED status: %d", p_bta_data->open.status ); - /* change state to idle */ - btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE); + state = BTAV_CONNECTION_STATE_DISCONNECTED; + av_state = BTIF_AV_STATE_IDLE; } /* inform the application of the event */ CHECK_CALL_CBACK(bt_av_callbacks, connection_state_cb, state, &(btif_av_cb.peer_bda)); + /* change state to open/idle based on the status */ + btif_sm_change_state(btif_av_cb.sm_handle, av_state); } break; + CHECK_RC_EVENT(event, p_data); + default: BTIF_TRACE_WARNING2("%s Unhandled event:%s", __FUNCTION__, dump_av_sm_event_name(event)); @@ -284,7 +380,15 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data) { case BTIF_SM_ENTER_EVT: - BTIF_TRACE_DEBUG0("starting av"); + BTIF_TRACE_DEBUG0("starting av...sleeping before that"); + + /* Auto-starting on Open could introduce race conditions. So delaying + * the start. + * + * This is anyway temporary and will be removed once the START/STOP stream + * requests are processed. + */ + GKI_delay(3000); btif_a2dp_upon_start_req(); @@ -331,6 +435,8 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data) btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE); } break; + CHECK_RC_EVENT(event, p_data); + default: BTIF_TRACE_WARNING2("%s Unhandled event:%s", __FUNCTION__, dump_av_sm_event_name(event)); @@ -338,7 +444,7 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data) return TRUE; } -static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *data) +static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data) { BTIF_TRACE_DEBUG2("%s event:%s", __FUNCTION__, dump_av_sm_event_name(event)); @@ -364,6 +470,8 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *data) btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED); } break; + CHECK_RC_EVENT(event, p_data); + default: BTIF_TRACE_WARNING2("%s Unhandled event:%s", __FUNCTION__, dump_av_sm_event_name(event)); @@ -414,6 +522,8 @@ static bt_status_t init(btav_callbacks_t* callbacks ) bt_av_callbacks = callbacks; btif_enable_service(BTA_A2DP_SERVICE_ID); + /* Initialize the AVRC CB */ + btif_rc_init(); /* Also initialize the AV state machine */ btif_av_cb.sm_handle = btif_sm_init((const btif_sm_handler_t*)btif_av_state_handlers, BTIF_AV_STATE_IDLE); @@ -516,7 +626,10 @@ bt_status_t btif_av_execute_service(BOOLEAN b_enable) BTA_AV_FEAT_RCTG|BTA_AV_FEAT_METADATA|BTA_AV_FEAT_VENDOR, bte_av_callback); #else - BTA_AvEnable(BTA_SEC_AUTHENTICATE|BTA_SEC_AUTHORIZE, BTA_AV_FEAT_RCTG, + /* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not + * handle this request in order to allow incoming connections to succeed. + * We need to put this back once support for this is added */ + BTA_AvEnable(BTA_SEC_AUTHENTICATE, BTA_AV_FEAT_RCTG, bte_av_callback); #endif BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0); diff --git a/btif/src/btif_rc.c b/btif/src/btif_rc.c new file mode 100644 index 0000000..04d5681 --- /dev/null +++ b/btif/src/btif_rc.c @@ -0,0 +1,435 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * This program is the proprietary software of Broadcom Corporation and/or its + * licensors, and may only be used, duplicated, modified or distributed + * pursuant to the terms and conditions of a separate, written license + * agreement executed between you and Broadcom (an "Authorized License"). + * Except as set forth in an Authorized License, Broadcom grants no license + * (express or implied), right to use, or waiver of any kind with respect to + * the Software, and Broadcom expressly reserves all rights in and to the + * Software and all intellectual property rights therein. + * IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS + * SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE + * ALL USE OF THE SOFTWARE. + * + * Except as expressly set forth in the Authorized License, + * + * 1. This program, including its structure, sequence and organization, + * constitutes the valuable trade secrets of Broadcom, and you shall + * use all reasonable efforts to protect the confidentiality thereof, + * and to use this information only in connection with your use of + * Broadcom integrated circuit products. + * + * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED + * "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, + * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, + * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY + * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, + * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, + * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR + * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING + * OUT OF USE OR PERFORMANCE OF THE SOFTWARE. + * + * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM + * OR ITS LICENSORS BE LIABLE FOR + * (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY + * DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO + * YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM + * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR + * (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE + * SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE + * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF + * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. + * + *****************************************************************************/ + + +/***************************************************************************** + * + * Filename: btif_rc.c + * + * Description: Bluetooth AVRC implementation + * + *****************************************************************************/ +#include <hardware/bluetooth.h> +#include <fcntl.h> +#include "bta_api.h" +#include "bta_av_api.h" +#include "avrc_defs.h" +#include "bd.h" +#include "gki.h" + +#define LOG_TAG "BTIF_RC" +#include "btif_common.h" + +/***************************************************************************** +** Constants & Macros +******************************************************************************/ +#if (!defined(AVRC_METADATA_INCLUDED) || (AVRC_METADATA_INCLUDED == FALSE)) +#define BTIF_RC_USE_UINPUT TRUE +#include "uinput.h" +#else +#error "AVRCP 1.3 is not supported on Bluedroid yet." +#endif + +/***************************************************************************** +** Local type definitions +******************************************************************************/ +typedef struct { + BOOLEAN rc_connected; + UINT8 rc_handle; + BD_ADDR rc_addr; + UINT16 rc_pending_play; +} btif_rc_cb_t; + +#ifdef BTIF_RC_USE_UINPUT +#define MAX_UINPUT_PATHS 3 +static const char* uinput_dev_path[] = + {"/dev/uinput", "/dev/input/uinput", "/dev/misc/uinput" }; +static int uinput_fd = -1; + +static int send_event (int fd, uint16_t type, uint16_t code, int32_t value); +static void send_key (int fd, uint16_t key, int pressed); +static int uinput_driver_check(); +static int uinput_create(char *name); +static int init_uinput (void); +static void close_uinput (void); + +static struct { + const char *name; + uint8_t avrcp; + uint16_t mapped_id; + uint8_t release_quirk; +} key_map[] = { + { "PLAY", AVRC_ID_PLAY, KEY_PLAYCD, 1 }, + { "STOP", AVRC_ID_STOP, KEY_STOPCD, 0 }, + { "PAUSE", AVRC_ID_PAUSE, KEY_PAUSECD, 1 }, + { "FORWARD", AVRC_ID_FORWARD, KEY_NEXTSONG, 0 }, + { "BACKWARD", AVRC_ID_BACKWARD, KEY_PREVIOUSSONG, 0 }, + { "REWIND", AVRC_ID_REWIND, KEY_REWIND, 0 }, + { "FAST FORWARD", AVRC_ID_FAST_FOR, KEY_FORWARD, 0 }, + { NULL, 0, 0, 0 } +}; +#endif /* BTIF_RC_USE_UINPUT */ + + +/***************************************************************************** +** Static variables +******************************************************************************/ +static btif_rc_cb_t btif_rc_cb; + +/***************************************************************************** +** Static functions +******************************************************************************/ + +/***************************************************************************** +** Externs +******************************************************************************/ + +/***************************************************************************** +** Functions +******************************************************************************/ + + +#ifdef BTIF_RC_USE_UINPUT +/***************************************************************************** +** Local uinput helper functions +******************************************************************************/ +int send_event (int fd, uint16_t type, uint16_t code, int32_t value) +{ + struct uinput_event event; + + memset(&event, 0, sizeof(event)); + event.type = type; + event.code = code; + event.value = value; + + return write(fd, &event, sizeof(event)); +} + +void send_key (int fd, uint16_t key, int pressed) +{ + if (fd < 0) { + return; + } + + BTIF_TRACE_DEBUG3("AVRCP: Send key %d (%d) fd=%d", key, pressed, fd); + send_event(fd, EV_KEY, key, pressed); + send_event(fd, EV_SYN, SYN_REPORT, 0); +} + +/************** uinput related functions **************/ +int uinput_driver_check() +{ + uint32_t i; + for (i=0; i < MAX_UINPUT_PATHS; i++) + { + if (access(uinput_dev_path[i], O_RDWR) == 0) { + return 0; + } + } + BTIF_TRACE_ERROR1("%s ERROR: uinput device is not in the system", __FUNCTION__); + return -1; +} + +int uinput_create(char *name) +{ + struct uinput_dev dev; + int fd, err, x = 0; + + for(x=0; x < MAX_UINPUT_PATHS; x++) + { + fd = open(uinput_dev_path[x], O_RDWR); + if (fd < 0) + continue; + break; + } + if (x == MAX_UINPUT_PATHS) { + BTIF_TRACE_ERROR1("%s ERROR: uinput device open failed", __FUNCTION__); + return -1; + } + memset(&dev, 0, sizeof(dev)); + if (name) + strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE); + + dev.id.bustype = BUS_BLUETOOTH; + dev.id.vendor = 0x0000; + dev.id.product = 0x0000; + dev.id.version = 0x0000; + + if (write(fd, &dev, sizeof(dev)) < 0) { + BTIF_TRACE_ERROR1("%s Unable to write device information", __FUNCTION__); + close(fd); + return -1; + } + + ioctl(fd, UI_SET_EVBIT, EV_KEY); + ioctl(fd, UI_SET_EVBIT, EV_REL); + ioctl(fd, UI_SET_EVBIT, EV_SYN); + + for (x = 0; key_map[x].name != NULL; x++) + ioctl(fd, UI_SET_KEYBIT, key_map[x].mapped_id); + + for(x = 0; x < KEY_MAX; x++) + ioctl(fd, UI_SET_KEYBIT, x); + + if (ioctl(fd, UI_DEV_CREATE, NULL) < 0) { + BTIF_TRACE_ERROR1("%s Unable to create uinput device", __FUNCTION__); + close(fd); + return -1; + } + return fd; +} + +int init_uinput (void) +{ + char *name = "AVRCP"; + + BTIF_TRACE_DEBUG1("%s", __FUNCTION__); + uinput_fd = uinput_create(name); + if (uinput_fd < 0) { + BTIF_TRACE_ERROR3("%s AVRCP: Failed to initialize uinput for %s (%d)", + __FUNCTION__, name, uinput_fd); + } else { + BTIF_TRACE_DEBUG3("%s AVRCP: Initialized uinput for %s (fd=%d)", + __FUNCTION__, name, uinput_fd); + } + return uinput_fd; +} + +void close_uinput (void) +{ + BTIF_TRACE_DEBUG1("%s", __FUNCTION__); + if (uinput_fd > 0) { + ioctl(uinput_fd, UI_DEV_DESTROY); + + close(uinput_fd); + uinput_fd = -1; + } +} +#endif // BTA_AVRCP_FORCE_USE_UINPUT + +const char *dump_rc_event_name(tBTA_AV_EVT event) +{ + switch(event) { + case BTA_AV_RC_OPEN_EVT: return "BTA_AV_RC_OPEN_EVT"; + case BTA_AV_RC_CLOSE_EVT: return "BTA_AV_RC_CLOSE_EVT"; + case BTA_AV_REMOTE_CMD_EVT: return "BTA_AV_REMOTE_CMD_EVT"; + case BTA_AV_REMOTE_RSP_EVT: return "BTA_AV_REMOTE_RSP_EVT"; + case BTA_AV_VENDOR_CMD_EVT: return "BTA_AV_VENDOR_CMD_EVT"; + case BTA_AV_VENDOR_RSP_EVT: return "BTA_AV_VENDOR_RSP_EVT"; + default: return "UNKNOWN_EVENT"; + } +} + +/*************************************************************************** + * Function handle_rc_connect + * + * - Argument: tBTA_AV_RC_OPEN RC open data structure + * + * - Description: RC connection event handler + * + ***************************************************************************/ +void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open) +{ + BTIF_TRACE_DEBUG2("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle); + +#ifdef BTIF_RC_USE_UINPUT + init_uinput(); +#endif + + memcpy(btif_rc_cb.rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR)); + btif_rc_cb.rc_connected = TRUE; + btif_rc_cb.rc_handle = p_rc_open->rc_handle; +} + +/*************************************************************************** + * Function handle_rc_disconnect + * + * - Argument: tBTA_AV_RC_CLOSE RC close data structure + * + * - Description: RC disconnection event handler + * + ***************************************************************************/ +void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close) +{ + BTIF_TRACE_DEBUG2("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle); + + btif_rc_cb.rc_handle = 0; + btif_rc_cb.rc_connected = FALSE; + memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR)); +#ifdef BTIF_RC_USE_UINPUT + close_uinput(); +#endif /* BTIF_RC_USE_UINPUT */ +} + +/*************************************************************************** + * Function handle_rc_passthrough_cmd + * + * - Argument: tBTA_AV_RC rc_id remote control command ID + * tBTA_AV_STATE key_state status of key press + * + * - Description: Remote control command handler + * + ***************************************************************************/ +void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd) +{ + const char *status; + int pressed, i; + + if (p_remote_cmd->key_state == AVRC_STATE_RELEASE) { + status = "released"; + pressed = 0; + } else { + status = "pressed"; + pressed = 1; + } + + for (i = 0; key_map[i].name != NULL; i++) { + if (p_remote_cmd->rc_id == key_map[i].avrcp) { + BTIF_TRACE_DEBUG3("%s: %s %s", __FUNCTION__, key_map[i].name, status); + + /* MusicPlayer uses a long_press_timeout of 1 second for PLAYPAUSE button + * and maps that to autoshuffle. So if for some reason release for PLAY/PAUSE + * comes 1 second after the press, the MediaPlayer UI goes into a bad state. + * The reason for the delay could be sniff mode exit or some AVDTP procedure etc. + * The fix is to generate a release right after the press and drown the 'actual' + * release. + */ + if ((key_map[i].release_quirk == 1) && (pressed == 0)) + { + BTIF_TRACE_DEBUG2("%s: AVRC %s Release Faked earlier, drowned now", + __FUNCTION__, key_map[i].name); + return; + } +#ifdef BTIF_RC_USE_UINPUT + send_key(uinput_fd, key_map[i].mapped_id, pressed); +#endif + if ((key_map[i].release_quirk == 1) && (pressed == 1)) + { + GKI_delay(30); // 30ms + BTIF_TRACE_DEBUG2("%s: AVRC %s Release quirk enabled, send release now", + __FUNCTION__, key_map[i].name); +#ifdef BTIF_RC_USE_UINPUT + send_key(uinput_fd, key_map[i].mapped_id, 0); +#endif + } + break; + } + } + + if (key_map[i].name == NULL) + BTIF_TRACE_ERROR3("%s AVRCP: unknown button 0x%02X %s", __FUNCTION__, + p_remote_cmd->rc_id, status); +} + +/***************************************************************************** +** +** Function btif_rc_init +** +** Description Initialize RC +** +** Returns Returns 0 on success, -1 otherwise +** +*******************************************************************************/ +int btif_rc_init() +{ + BTIF_TRACE_DEBUG1("%s", __FUNCTION__); + memset (&btif_rc_cb, 0, sizeof(btif_rc_cb)); + +#ifdef BTIF_RC_USE_UINPUT + return uinput_driver_check(); +#endif /* BTIF_RC_USE_UINPUT */ +} + +/*************************************************************************** + ** + ** Function btif_rc_handler + ** + ** Description RC event handler + ** + ***************************************************************************/ +void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data) +{ + BTIF_TRACE_DEBUG2 ("%s event:%s", __FUNCTION__, dump_rc_event_name(event)); + switch (event) + { + case BTA_AV_RC_OPEN_EVT: + { + BTIF_TRACE_DEBUG1("Peer_features:%x", p_data->rc_open.peer_features); + handle_rc_connect( &(p_data->rc_open) ); + }break; + + case BTA_AV_RC_CLOSE_EVT: + { + handle_rc_disconnect( &(p_data->rc_close) ); + }break; + + case BTA_AV_REMOTE_CMD_EVT: + { + BTIF_TRACE_DEBUG2("rc_id:0x%x key_state:%d", p_data->remote_cmd.rc_id, + p_data->remote_cmd.key_state); + handle_rc_passthrough_cmd( (&p_data->remote_cmd) ); + }break; + default: + BTIF_TRACE_DEBUG0("Unhandled RC event"); + } +} + +/*************************************************************************** + ** + ** Function btif_rc_get_connected_peer + ** + ** Description Fetches the connected headset's BD_ADDR if any + ** + ***************************************************************************/ +BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr) +{ + if (btif_rc_cb.rc_connected == TRUE) { + bdcpy(peer_addr, btif_rc_cb.rc_addr); + return TRUE; + } + return FALSE; +} diff --git a/include/buildcfg_crespo.h b/include/buildcfg_crespo.h index 0060149..da4d475 100644 --- a/include/buildcfg_crespo.h +++ b/include/buildcfg_crespo.h @@ -2,7 +2,7 @@ #define BUILDCFG_H #define AVCT_INCLUDED TRUE #define AVRC_INCLUDED TRUE -#define AVRC_METADATA_INCLUDED TRUE +#define AVRC_METADATA_INCLUDED FALSE #define AVRC_ADV_CTRL_INCLUDED FALSE #define AVDT_INCLUDED TRUE #define AVDTC_INCLUDED FALSE # Makefile only diff --git a/include/buildcfg_maguro.h b/include/buildcfg_maguro.h index a2e0123..196c792 100644 --- a/include/buildcfg_maguro.h +++ b/include/buildcfg_maguro.h @@ -2,7 +2,7 @@ #define BUILDCFG_H #define AVCT_INCLUDED TRUE #define AVRC_INCLUDED TRUE -#define AVRC_METADATA_INCLUDED TRUE +#define AVRC_METADATA_INCLUDED FALSE #define AVRC_ADV_CTRL_INCLUDED FALSE #define AVDT_INCLUDED TRUE #define AVDTC_INCLUDED FALSE # Makefile only diff --git a/main/Android.mk b/main/Android.mk index 8e78c61..e1c17bc 100644 --- a/main/Android.mk +++ b/main/Android.mk @@ -25,7 +25,8 @@ LOCAL_SRC_FILES += \ ../btif/src/btif_util.c \ ../btif/src/btif_sm.c \ ../btif/src/btif_hf.c \ - ../btif/src/btif_av.c + ../btif/src/btif_av.c \ + ../btif/src/btif_rc.c # callouts LOCAL_SRC_FILES+= \ |