From 2f338f25530d2aaab7acf45701c271d10b81d96d Mon Sep 17 00:00:00 2001 From: Ganesh Ganapathi Batta Date: Sun, 24 Mar 2013 03:11:59 +0100 Subject: [PATCH] BT: JV rfcomm socket sniff support Bug:8322094 Change-Id: Ib472f39488b685ac396289e65c1da21fdfd93c4c --- bta/dm/bta_dm_cfg.c | 5 +- bta/include/bta_jv_api.h | 64 +++++ bta/jv/bta_jv_act.c | 600 +++++++++++++++++++++++++++++++++++++++-------- bta/jv/bta_jv_api.c | 62 ++++- bta/jv/bta_jv_int.h | 67 +++++- bta/jv/bta_jv_main.c | 4 +- btif/src/btif_sock_rfc.c | 15 +- 7 files changed, 700 insertions(+), 117 deletions(-) diff --git a/bta/dm/bta_dm_cfg.c b/bta/dm/bta_dm_cfg.c index a7c3cc4ec..14360d99d 100644 --- a/bta/dm/bta_dm_cfg.c +++ b/bta/dm/bta_dm_cfg.c @@ -27,6 +27,7 @@ #include "bta_sys.h" #include "bta_api.h" #include "bta_dm_int.h" +#include "bta_jv_api.h" #ifndef BTA_DM_LINK_POLICY_SETTINGS #define BTA_DM_LINK_POLICY_SETTINGS (HCI_ENABLE_MASTER_SLAVE_SWITCH | HCI_ENABLE_HOLD_MODE | HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_PARK_MODE) @@ -124,8 +125,8 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_CFG bta_dm_pm_cfg[] = {BTA_ID_OPC, BTA_ALL_APP_ID, 6}, /* reuse ftc spec table */ {BTA_ID_OPS, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */ {BTA_ID_MSE, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */ - {BTA_ID_JV1, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */ - {BTA_ID_JV2, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */ + {BTA_ID_JV, BTA_JV_PM_ID_1, 6}, /* app BTA_JV_PM_ID_1, reuse ftc spec table */ + {BTA_ID_JV, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */ {BTA_ID_HL, BTA_ALL_APP_ID, 8} /* reuse fts spec table */ }; diff --git a/bta/include/bta_jv_api.h b/bta/include/bta_jv_api.h index 8336c8737..7e53ab664 100644 --- a/bta/include/bta_jv_api.h +++ b/bta/include/bta_jv_api.h @@ -37,6 +37,7 @@ #define BTA_JV_FAILURE 1 /* Generic failure. */ #define BTA_JV_BUSY 2 /* Temporarily can not handle this request. */ #define BTA_JV_NO_DATA 3 /* no data. */ +#define BTA_JV_NO_RESOURCE 4 /* No more set pm control block */ typedef UINT8 tBTA_JV_STATUS; #define BTA_JV_INTERNAL_ERR (-1) /* internal error. */ @@ -103,7 +104,34 @@ typedef UINT32 tBTA_JV_ROLE; #define BTA_JV_SERVICE_TELEPHONY BTM_COD_SERVICE_TELEPHONY /* 0x4000 */ #define BTA_JV_SERVICE_INFORMATION BTM_COD_SERVICE_INFORMATION /* 0x8000 */ +/* JV ID type */ +#define BTA_JV_PM_ID_1 1 /* PM example profile 1 */ +#define BTA_JV_PM_ID_2 2 /* PM example profile 2 */ +#define BTA_JV_PM_ID_CLEAR 0 /* Special JV ID used to clear PM profile */ +#define BTA_JV_PM_ALL 0xFF /* Generic match all id, see bta_dm_cfg.c */ +typedef UINT8 tBTA_JV_PM_ID; +#define BTA_JV_PM_HANDLE_CLEAR 0xFF /* Special JV ID used to clear PM profile */ + +/* define maximum number of registered PM entities. should be in sync with bta pm! */ +#ifndef BTA_JV_PM_MAX_NUM +#define BTA_JV_PM_MAX_NUM 5 +#endif + +/* JV pm connection states */ +enum +{ + BTA_JV_CONN_OPEN = 0, /* Connection opened state */ + BTA_JV_CONN_CLOSE, /* Connection closed state */ + BTA_JV_APP_OPEN, /* JV Application opened state */ + BTA_JV_APP_CLOSE, /* JV Application closed state */ + BTA_JV_SCO_OPEN, /* SCO connection opened state */ + BTA_JV_SCO_CLOSE, /* SCO connection opened state */ + BTA_JV_CONN_IDLE, /* Connection idle state */ + BTA_JV_CONN_BUSY, /* Connection busy state */ + BTA_JV_MAX_CONN_STATE /* Max number of connection state */ +}; +typedef UINT8 tBTA_JV_CONN_STATE; /* Java I/F callback events */ /* events received by tBTA_JV_DM_CBACK */ @@ -364,6 +392,21 @@ typedef struct BOOLEAN cong; /* congestion status */ } tBTA_JV_RFCOMM_WRITE; +/* data associated with BTA_JV_API_SET_PM_PROFILE_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Status of the operation */ + UINT32 handle; /* Connection handle */ + tBTA_JV_PM_ID app_id; /* JV app ID */ +} tBTA_JV_SET_PM_PROFILE; + +/* data associated with BTA_JV_API_NOTIFY_PM_STATE_CHANGE_EVT */ +typedef struct +{ + UINT32 handle; /* Connection handle */ + tBTA_JV_CONN_STATE state; /* JV connection stata */ +} tBTA_JV_NOTIFY_PM_STATE_CHANGE; + /* union of data associated with JV callback */ typedef union @@ -1101,6 +1144,27 @@ BTA_API extern tBTA_JV_STATUS BTA_JvRfcommReady(UINT32 handle, UINT32 *p_data_si *******************************************************************************/ BTA_API extern tBTA_JV_STATUS BTA_JvRfcommWrite(UINT32 handle, UINT32 req_id); +/******************************************************************************* + ** + ** Function BTA_JVSetPmProfile + ** + ** Description This function set or free power mode profile for different JV application + ** + ** Parameters: handle, JV handle from RFCOMM or L2CAP + ** app_id: app specific pm ID, can be BTA_JV_PM_ALL, see bta_dm_cfg.c for details + ** BTA_JV_PM_ID_CLEAR: removes pm management on the handle. init_st is ignored and + ** BTA_JV_CONN_CLOSE is called implicitely + ** init_st: state after calling this API. typically it should be BTA_JV_CONN_OPEN + ** + ** Returns BTA_JV_SUCCESS, if the request is being processed. + ** BTA_JV_FAILURE, otherwise. + ** + ** NOTE: BTA_JV_PM_ID_CLEAR: In general no need to be called as jv pm calls automatically + ** BTA_JV_CONN_CLOSE to remove in case of connection close! + ** + *******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvSetPmProfile(UINT32 handle, tBTA_JV_PM_ID app_id, + tBTA_JV_CONN_STATE init_st); /******************************************************************************* ** diff --git a/bta/jv/bta_jv_act.c b/bta/jv/bta_jv_act.c index 160bafefc..b296f1bd7 100644 --- a/bta/jv/bta_jv_act.c +++ b/bta/jv/bta_jv_act.c @@ -18,10 +18,9 @@ /****************************************************************************** * - * This file contains action functions for advanced audio. + * This file contains action functions for BTA JV APIs. * ******************************************************************************/ - #include #include @@ -43,6 +42,8 @@ #include "rfcdefs.h" #include "avct_api.h" #include "avdt_api.h" +#include "gap_api.h" + #define HDL2CB(handle) \ UINT32 __hi = ((handle) & BTA_JV_RFC_HDL_MASK) - 1; \ @@ -60,6 +61,12 @@ static inline void logu(const char* title, const uint8_t * p_uuid) static tBTA_JV_PCB * bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb_open); +static tBTA_JV_STATUS bta_jv_free_set_pm_profile_cb(UINT32 jv_handle); +static void bta_jv_pm_conn_busy(tBTA_JV_PM_CB *p_cb); +static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB *p_cb); +static void bta_jv_pm_state_change(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE state); +tBTA_JV_STATUS bta_jv_set_pm_conn_state(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE + new_st); /******************************************************************************* ** @@ -127,8 +134,9 @@ static int get_sec_id_used(void) if(bta_jv_cb.sec_id[i]) used++; } - if(used == BTA_JV_NUM_SERVICE_ID) - APPL_TRACE_ERROR1("get_sec_id_used, sec id exceeds the limit:%d", BTA_JV_NUM_SERVICE_ID); + if (used == BTA_JV_NUM_SERVICE_ID) + APPL_TRACE_ERROR1("get_sec_id_used, sec id exceeds the limit:%d", + BTA_JV_NUM_SERVICE_ID); return used; } static int get_rfc_cb_used(void) @@ -140,8 +148,9 @@ static int get_rfc_cb_used(void) if(bta_jv_cb.rfc_cb[i].handle ) used++; } - if(used == BTA_JV_MAX_RFC_CONN) - APPL_TRACE_ERROR1("get_sec_id_used, rfc ctrl block exceeds the limit:%d", BTA_JV_MAX_RFC_CONN); + if (used == BTA_JV_MAX_RFC_CONN) + APPL_TRACE_ERROR1("get_sec_id_used, rfc ctrl block exceeds the limit:%d", + BTA_JV_MAX_RFC_CONN); return used; } @@ -178,29 +187,35 @@ tBTA_JV_RFC_CB * bta_jv_alloc_rfc_cb(UINT16 port_handle, tBTA_JV_PCB **pp_pcb) { tBTA_JV_RFC_CB *p_cb = NULL; tBTA_JV_PCB *p_pcb; - int i; + int i, j; for(i=0; ihandle = i + 1; + /* mask handle to distinguish it with L2CAP handle */ + p_cb->handle = (i + 1) | BTA_JV_RFCOMM_MASK; + p_cb->max_sess = 1; p_cb->curr_sess = 1; + for (j = 0; j < BTA_JV_MAX_RFC_SR_SESSION; j++) + p_cb->rfc_hdl[j] = 0; p_cb->rfc_hdl[0] = port_handle; - APPL_TRACE_DEBUG2( "bta_jv_alloc_rfc_cb port_handle:%d handle:%d", - port_handle, p_cb->handle); + APPL_TRACE_DEBUG2( "bta_jv_alloc_rfc_cb port_handle:%d handle:0x%2x", + port_handle, p_cb->handle); + p_pcb = &bta_jv_cb.port_cb[port_handle - 1]; p_pcb->handle = p_cb->handle; p_pcb->port_handle = port_handle; + p_pcb->p_pm_cb = NULL; *pp_pcb = p_pcb; break; } } if(p_cb == NULL) { - APPL_TRACE_ERROR2( "bta_jv_alloc_rfc_cb: port_handle:%d, ctrl block exceeds limit:%d", - port_handle, BTA_JV_MAX_RFC_CONN); + APPL_TRACE_ERROR2( "bta_jv_alloc_rfc_cb: port_handle:%d, ctrl block exceeds " + "limit:%d", port_handle, BTA_JV_MAX_RFC_CONN); } return p_cb; } @@ -218,7 +233,8 @@ tBTA_JV_PCB * bta_jv_rfc_port_to_pcb(UINT16 port_handle) { tBTA_JV_PCB *p_pcb = NULL; - if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS) && bta_jv_cb.port_cb[port_handle - 1].handle) + if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS) + && bta_jv_cb.port_cb[port_handle - 1].handle) { p_pcb = &bta_jv_cb.port_cb[port_handle - 1]; } @@ -240,83 +256,106 @@ tBTA_JV_RFC_CB * bta_jv_rfc_port_to_cb(UINT16 port_handle) tBTA_JV_RFC_CB *p_cb = NULL; UINT32 handle; - if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS) && bta_jv_cb.port_cb[port_handle - 1].handle) + if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS) + && bta_jv_cb.port_cb[port_handle - 1].handle) { handle = bta_jv_cb.port_cb[port_handle - 1].handle; handle &= BTA_JV_RFC_HDL_MASK; + handle &= ~BTA_JV_RFCOMM_MASK; if (handle) p_cb = &bta_jv_cb.rfc_cb[handle - 1]; } + else + { + APPL_TRACE_WARNING2("bta_jv_rfc_port_to_cb(port_handle:0x%x):jv handle:0x%x not" + " FOUND", port_handle, bta_jv_cb.port_cb[port_handle - 1].handle); + } return p_cb; } + static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb) { tBTA_JV_STATUS status = BTA_JV_SUCCESS; - UINT8 i; - if(!p_cb || !p_pcb) + BOOLEAN remove_server = FALSE; + int close_pending = 0; + + if (!p_cb || !p_pcb) { APPL_TRACE_ERROR0("bta_jv_free_sr_rfc_cb, p_cb or p_pcb cannot be null"); return BTA_JV_FAILURE; } - APPL_TRACE_DEBUG5("bta_jv_free_sr_rfc_cb: max_sess:%d, curr_sess:%d, p_pcb:%p, user:%d, state:%d" - ,p_cb->max_sess, p_cb->curr_sess, p_pcb, (int)p_pcb->user_data, p_pcb->state); + APPL_TRACE_DEBUG6("bta_jv_free_sr_rfc_cb: max_sess:%d, curr_sess:%d, p_pcb:%p, user:" + "%d, state:%d, jv handle: 0x%x" ,p_cb->max_sess, p_cb->curr_sess, p_pcb, + (int)p_pcb->user_data, p_pcb->state, p_pcb->handle); - if(p_cb->curr_sess <= 0) + if (p_cb->curr_sess <= 0) return BTA_JV_SUCCESS; - int state = p_pcb->state; - int close_pending = 0; - if(p_pcb->state == BTA_JV_ST_SR_LISTEN) + + switch (p_pcb->state) { - APPL_TRACE_DEBUG2("bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_SR_LISTEN, scn:%d, ueser_data:%d" - , p_cb->scn, (int)p_pcb->user_data); + case BTA_JV_ST_CL_CLOSING: + case BTA_JV_ST_SR_CLOSING: + APPL_TRACE_WARNING4("bta_jv_free_sr_rfc_cb: return on closing, port state:%d, " + "scn:%d, p_pcb:%p, user_data:%d", p_pcb->state, p_cb->scn, p_pcb, + (int)p_pcb->user_data); + status = BTA_JV_FAILURE; + return status; + case BTA_JV_ST_CL_OPEN: + p_pcb->state = BTA_JV_ST_CL_CLOSING; + APPL_TRACE_DEBUG2("bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_CL_OPEN, scn:%d," + " user_data:%d", p_cb->scn, (int)p_pcb->user_data); + break; + case BTA_JV_ST_SR_LISTEN: p_pcb->state = BTA_JV_ST_SR_CLOSING; - if(RFCOMM_RemoveServer(p_pcb->port_handle) != PORT_SUCCESS) - status = BTA_JV_FAILURE; - } - else if(p_pcb->state == BTA_JV_ST_SR_OPEN) - { - APPL_TRACE_DEBUG2("bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_SR_OPEN, scn:%d, ueser_data:%d" - , p_cb->scn, (int)p_pcb->user_data); + remove_server = TRUE; + APPL_TRACE_DEBUG2("bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_SR_LISTEN, scn:%d," + " user_data:%d", p_cb->scn, (int)p_pcb->user_data); + break; + case BTA_JV_ST_SR_OPEN: p_pcb->state = BTA_JV_ST_SR_CLOSING; - if(RFCOMM_RemoveConnection(p_pcb->port_handle) != PORT_SUCCESS) - status = BTA_JV_FAILURE; - //else close_pending = 1; - } - else if(p_pcb->state == BTA_JV_ST_CL_OPEN) - { - APPL_TRACE_DEBUG2("bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_CL_OPEN, scn:%d, ueser_data:%d" - ,p_cb->scn, (int)p_pcb->user_data); - p_pcb->state = BTA_JV_ST_CL_CLOSING; - if(RFCOMM_RemoveConnection(p_pcb->port_handle) != PORT_SUCCESS) - status = BTA_JV_FAILURE; - //else close_pending = 1; - } - else if(p_pcb->state == BTA_JV_ST_CL_CLOSING || p_pcb->state == BTA_JV_ST_SR_CLOSING) - { - APPL_TRACE_WARNING4("bta_jv_free_sr_rfc_cb: return on closing, port state:%d, scn:%d, p_pcb:%p, ueser_data:%d" - , p_pcb->state, p_cb->scn, p_pcb, (int)p_pcb->user_data); - status = BTA_JV_FAILURE; - return status; + APPL_TRACE_DEBUG2("bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_SR_OPEN, scn:%d," + " user_data:%d", p_cb->scn, (int)p_pcb->user_data); + break; + default: + APPL_TRACE_WARNING6("bta_jv_free_sr_rfc_cb():failed, ignore port state:%d, scn:" + "%d, p_pcb:%p, jv handle: 0x%x, port_handle: %d, user_data:%d", + p_pcb->state, p_cb->scn, p_pcb, p_pcb->handle, p_pcb->port_handle, + (int)p_pcb->user_data); + status = BTA_JV_FAILURE; + break; } - else + if (BTA_JV_SUCCESS == status) { - APPL_TRACE_WARNING4("bta_jv_free_sr_rfc_cb: failed, ignore port state:%d, scn:%d, p_pcb:%p, ueser_data:%d" - , p_pcb->state, p_cb->scn, p_pcb, (int)p_pcb->user_data); - status = BTA_JV_FAILURE; + int port_status; + + if (!remove_server) + port_status = RFCOMM_RemoveConnection(p_pcb->port_handle); + else + port_status = RFCOMM_RemoveServer(p_pcb->port_handle); + if (port_status != PORT_SUCCESS) + { + status = BTA_JV_FAILURE; + APPL_TRACE_WARNING5("bta_jv_free_rfc_cb(jv handle: 0x%x, state %d)::" + "port_status: %d, port_handle: %d, close_pending: %d:Remove", + p_pcb->handle, p_pcb->state, port_status, p_pcb->port_handle, + close_pending); + } } - if(!close_pending) + if (!close_pending) { p_pcb->port_handle = 0; p_pcb->state = BTA_JV_ST_NONE; + bta_jv_free_set_pm_profile_cb(p_pcb->handle); //Initialize congestion flags p_pcb->cong = FALSE; p_pcb->user_data = 0; int si = BTA_JV_RFC_HDL_TO_SIDX(p_pcb->handle); - if(0 <= si && si < BTA_JV_MAX_RFC_SR_SESSION) + if (0 <= si && si < BTA_JV_MAX_RFC_SR_SESSION) p_cb->rfc_hdl[si] = 0; + p_pcb->handle = 0; p_cb->curr_sess--; - if(p_cb->curr_sess == 0) + if (p_cb->curr_sess == 0) { p_cb->scn = 0; bta_jv_free_sec_id(&p_cb->sec_id); @@ -327,6 +366,7 @@ static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pc } return status; } + /******************************************************************************* ** ** Function bta_jv_free_l2c_cb @@ -356,8 +396,11 @@ tBTA_JV_STATUS bta_jv_free_l2c_cb(tBTA_JV_L2C_CB *p_cb) } else #endif - if(GAP_ConnClose(p_cb->handle) != BT_PASS) - status = BTA_JV_FAILURE; + { + bta_jv_free_set_pm_profile_cb((UINT32)p_cb->handle); + if (GAP_ConnClose(p_cb->handle) != BT_PASS) + status = BTA_JV_FAILURE; + } } p_cb->psm = 0; p_cb->state = BTA_JV_ST_NONE; @@ -369,14 +412,178 @@ tBTA_JV_STATUS bta_jv_free_l2c_cb(tBTA_JV_L2C_CB *p_cb) } /******************************************************************************* -** -** Function bta_jv_alloc_sdp_id -** -** Description allocate a SDP id for the given SDP record handle -** -** Returns -** -*******************************************************************************/ + ** + ** Function bta_jv_clear_pm_cb + ** + ** Description clears jv pm control block and optionally calls bta_sys_conn_close() + ** In general close_conn should be set to TRUE to remove registering with + ** dm pm! + ** + ** WARNING: Make sure to clear pointer form port or l2c to this control block too! + ** + *******************************************************************************/ +static void bta_jv_clear_pm_cb(tBTA_JV_PM_CB *p_pm_cb, BOOLEAN close_conn) +{ + /* needs to be called if registered with bta pm, otherwise we may run out of dm pm slots! */ + if (close_conn) + bta_sys_conn_close(BTA_ID_JV, p_pm_cb->app_id, p_pm_cb->peer_bd_addr); + p_pm_cb->state = BTA_JV_PM_FREE_ST; + p_pm_cb->app_id = BTA_JV_PM_ALL; + p_pm_cb->handle = BTA_JV_PM_HANDLE_CLEAR; + bdcpy(p_pm_cb->peer_bd_addr, bd_addr_null); +} + +/******************************************************************************* + ** + ** Function bta_jv_free_set_pm_profile_cb + ** + ** Description free pm profile control block + ** + ** Returns BTA_JV_SUCCESS if cb has been freed correctly, + ** BTA_JV_FAILURE in case of no profile has been registered or already freed + ** + *******************************************************************************/ +static tBTA_JV_STATUS bta_jv_free_set_pm_profile_cb(UINT32 jv_handle) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_PM_CB **p_cb; + int i; + + for (i = 0; i < BTA_JV_PM_MAX_NUM; i++) + { + p_cb = NULL; + if ((bta_jv_cb.pm_cb[i].state != BTA_JV_PM_FREE_ST) && + (jv_handle == bta_jv_cb.pm_cb[i].handle)) + { + APPL_TRACE_API3("bta_jv_free_set_pm_profile_cb(jv_handle: 0x%2x), idx: %d, " + "app_id: 0x%x", jv_handle, i, bta_jv_cb.pm_cb[i].app_id); + + bta_jv_clear_pm_cb(&bta_jv_cb.pm_cb[i], TRUE); + + if (BTA_JV_RFCOMM_MASK & jv_handle) + { + UINT32 hi = ((jv_handle & BTA_JV_RFC_HDL_MASK) & ~BTA_JV_RFCOMM_MASK) - 1; + UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(jv_handle); + if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback && si + < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si]) + { + tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(bta_jv_cb.rfc_cb[hi].rfc_hdl[si]); + if (p_pcb) + { + if (NULL == p_pcb->p_pm_cb) + APPL_TRACE_WARNING3("bta_jv_free_set_pm_profile_cb(jv_handle:" + " 0x%x):port_handle: 0x%x, p_pm_cb: %d: no link to " + "pm_cb?", jv_handle, p_pcb->port_handle, i); + p_cb = &p_pcb->p_pm_cb; + } + } + } + else + { + if (jv_handle < BTA_JV_MAX_L2C_CONN) + { + tBTA_JV_L2C_CB *p_l2c_cb = &bta_jv_cb.l2c_cb[jv_handle]; + if (NULL == p_l2c_cb->p_pm_cb) + APPL_TRACE_WARNING2("bta_jv_free_set_pm_profile_cb(jv_handle: " + "0x%x): p_pm_cb: %d: no link to pm_cb?", jv_handle, i); + p_cb = &p_l2c_cb->p_pm_cb; + } + } + if (p_cb) + { + *p_cb = NULL; + status = BTA_JV_SUCCESS; + } + } + } + return status; +} + +/******************************************************************************* + ** + ** Function bta_jv_alloc_set_pm_profile_cb + ** + ** Description set PM profile control block + ** + ** Returns pointer to allocated cb or NULL in case of failure + ** + *******************************************************************************/ +static tBTA_JV_PM_CB *bta_jv_alloc_set_pm_profile_cb(UINT32 jv_handle, tBTA_JV_PM_ID app_id) +{ + BOOLEAN bRfcHandle = (jv_handle & BTA_JV_RFCOMM_MASK) != 0; + BD_ADDR peer_bd_addr; + int i, j; + tBTA_JV_PM_CB **pp_cb; + + for (i = 0; i < BTA_JV_PM_MAX_NUM; i++) + { + pp_cb = NULL; + if (bta_jv_cb.pm_cb[i].state == BTA_JV_PM_FREE_ST) + { + /* rfc handle bd addr retrieval requires core stack handle */ + if (bRfcHandle) + { + UINT32 hi = ((jv_handle & BTA_JV_RFC_HDL_MASK) & ~BTA_JV_RFCOMM_MASK) - 1; + UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(jv_handle); + for (j = 0; j < BTA_JV_MAX_RFC_CONN; j++) + { + if (jv_handle == bta_jv_cb.port_cb[j].handle) + { + pp_cb = &bta_jv_cb.port_cb[j].p_pm_cb; + if (PORT_SUCCESS != PORT_CheckConnection( + bta_jv_cb.port_cb[j].port_handle, peer_bd_addr, NULL)) + i = BTA_JV_PM_MAX_NUM; + break; + } + } + } + else + { + /* use jv handle for l2cap bd address retrieval */ + for (j = 0; j < BTA_JV_MAX_L2C_CONN; j++) + { + if (jv_handle == bta_jv_cb.l2c_cb[j].handle) + { + pp_cb = &bta_jv_cb.l2c_cb[j].p_pm_cb; + UINT8 *p_bd_addr = GAP_ConnGetRemoteAddr((UINT16)jv_handle); + if (NULL != p_bd_addr) + bdcpy(peer_bd_addr, p_bd_addr); + else + i = BTA_JV_PM_MAX_NUM; + break; + } + } + } + APPL_TRACE_API5("bta_jv_alloc_set_pm_profile_cb(handle 0x%2x, app_id %d): " + "idx: %d, (BTA_JV_PM_MAX_NUM: %d), pp_cb: 0x%x", jv_handle, app_id, + i, BTA_JV_PM_MAX_NUM, pp_cb); + break; + } + } + + if ((i != BTA_JV_PM_MAX_NUM) && (NULL != pp_cb)) + { + *pp_cb = &bta_jv_cb.pm_cb[i]; + bta_jv_cb.pm_cb[i].handle = jv_handle; + bta_jv_cb.pm_cb[i].app_id = app_id; + bdcpy(bta_jv_cb.pm_cb[i].peer_bd_addr, peer_bd_addr); + bta_jv_cb.pm_cb[i].state = BTA_JV_PM_IDLE_ST; + return &bta_jv_cb.pm_cb[i]; + } + APPL_TRACE_WARNING2("bta_jv_alloc_set_pm_profile_cb(jv_handle: 0x%x, app_id: %d) " + "return NULL", jv_handle, app_id); + return (tBTA_JV_PM_CB *)NULL; +} + +/******************************************************************************* + ** + ** Function bta_jv_alloc_sdp_id + ** + ** Description allocate a SDP id for the given SDP record handle + ** + ** Returns + ** + *******************************************************************************/ UINT32 bta_jv_alloc_sdp_id(UINT32 sdp_handle) { int j; @@ -1689,6 +1896,7 @@ void bta_jv_l2cap_write(tBTA_JV_MSG *p_data) p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET; p_msg->len = ls->len; memcpy(p, ls->p_data, p_msg->len); + bta_jv_pm_conn_busy(ls->p_cb->p_pm_cb); if(SDP_WriteData (bta_jv_cb.sdp_for_jv, p_msg)) { evt_data.len = ls->len; @@ -1698,13 +1906,16 @@ void bta_jv_l2cap_write(tBTA_JV_MSG *p_data) } else #endif - if (!evt_data.cong && - BT_PASS == GAP_ConnWriteData(ls->handle, ls->p_data, ls->len, &evt_data.len)) { - evt_data.status = BTA_JV_SUCCESS; + bta_jv_pm_conn_busy(ls->p_cb->p_pm_cb); + if (!evt_data.cong && + BT_PASS == GAP_ConnWriteData(ls->handle, ls->p_data, ls->len, &evt_data.len)) + { + evt_data.status = BTA_JV_SUCCESS; + } } - ls->p_cb->p_cback(BTA_JV_L2CAP_WRITE_EVT, (tBTA_JV *)&evt_data); + bta_jv_set_pm_conn_state(ls->p_cb->p_pm_cb, BTA_JV_CONN_IDLE); #endif } @@ -1837,6 +2048,11 @@ static void bta_jv_port_event_cl_cback(UINT32 code, UINT16 port_handle) evt_data.rfc_cong.status = BTA_JV_SUCCESS; p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, p_pcb->user_data); } + + if (code & PORT_EV_TXEMPTY) + { + bta_jv_pm_conn_idle(p_pcb->p_pm_cb); + } } /******************************************************************************* @@ -1851,7 +2067,7 @@ static void bta_jv_port_event_cl_cback(UINT32 code, UINT16 port_handle) void bta_jv_rfcomm_connect(tBTA_JV_MSG *p_data) { UINT16 handle = 0; - UINT32 event_mask = (PORT_EV_RXCHAR | PORT_EV_FC | PORT_EV_FCS); + UINT32 event_mask = BTA_JV_RFC_EV_MASK; tPORT_STATE port_state; UINT8 sec_id = 0; tBTA_JV_RFC_CB *p_cb = NULL; @@ -1922,24 +2138,30 @@ void bta_jv_rfcomm_connect(tBTA_JV_MSG *p_data) RFCOMM_RemoveConnection(handle); } } + static int find_rfc_pcb(void* user_data, tBTA_JV_RFC_CB **cb, tBTA_JV_PCB **pcb) { *cb = NULL; *pcb = NULL; int i; - for(i = 0; i < MAX_RFC_PORTS; i++) + for (i = 0; i < MAX_RFC_PORTS; i++) { - UINT32 rfc_handle = bta_jv_cb.port_cb[i].handle & BTA_JV_RFC_HDL_MASK; - if(rfc_handle && bta_jv_cb.port_cb[i].user_data == user_data) + UINT32 rfc_handle = bta_jv_cb.port_cb[i].handle & BTA_JV_RFC_HDL_MASK; + rfc_handle &= ~BTA_JV_RFCOMM_MASK; + if (rfc_handle && bta_jv_cb.port_cb[i].user_data == user_data) { *pcb = &bta_jv_cb.port_cb[i]; *cb = &bta_jv_cb.rfc_cb[rfc_handle - 1]; + APPL_TRACE_DEBUG4("find_rfc_pcb(): FOUND rfc_cb_handle 0x%x, port.jv_handle:" + " 0x%x, state: %d, rfc_cb->handle: 0x%x", rfc_handle, (*pcb)->handle, + (*pcb)->state, (*cb)->handle); return 1; } } APPL_TRACE_DEBUG1("find_rfc_pcb: cannot find rfc_cb from user data:%d", (UINT32)user_data); return 0; } + /******************************************************************************* ** ** Function bta_jv_rfcomm_close @@ -1955,14 +2177,14 @@ void bta_jv_rfcomm_close(tBTA_JV_MSG *p_data) tBTA_JV_RFC_CB *p_cb = NULL; tBTA_JV_PCB *p_pcb = NULL; APPL_TRACE_DEBUG1("bta_jv_rfcomm_close, rfc handle:%d", cc->handle); - if(!cc->handle) + if (!cc->handle) { APPL_TRACE_ERROR0("bta_jv_rfcomm_close, rfc handle is null"); return; } void* user_data = cc->user_data; - if(!find_rfc_pcb(user_data, &p_cb, &p_pcb)) + if (!find_rfc_pcb(user_data, &p_cb, &p_pcb)) return; bta_jv_free_rfc_cb(p_cb, p_pcb); APPL_TRACE_DEBUG2("bta_jv_rfcomm_close: sec id in use:%d, rfc_cb in use:%d", @@ -2029,27 +2251,28 @@ static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle) return; } void *user_data = p_pcb->user_data; - APPL_TRACE_DEBUG5( "bta_jv_port_mgmt_sr_cback code=%d port_handle:%d handle:%d, p_pcb:%p, user:%d", + APPL_TRACE_DEBUG5( "bta_jv_port_mgmt_sr_cback code=%d port_handle:0x%x handle:0x%x, p_pcb:%p, user:%d", code, port_handle, p_cb->handle, p_pcb, p_pcb->user_data); PORT_CheckConnection(port_handle, rem_bda, &lcid); int failed = TRUE; - if(code == PORT_SUCCESS) + if (code == PORT_SUCCESS) { evt_data.rfc_srv_open.handle = p_pcb->handle; evt_data.rfc_srv_open.status = BTA_JV_SUCCESS; bdcpy(evt_data.rfc_srv_open.rem_bda, rem_bda); tBTA_JV_PCB *p_pcb_new_listen = bta_jv_add_rfc_port(p_cb, p_pcb); - if(p_pcb_new_listen) + if (p_pcb_new_listen) { evt_data.rfc_srv_open.new_listen_handle = p_pcb_new_listen->handle; p_pcb_new_listen->user_data = p_cb->p_cback(BTA_JV_RFCOMM_SRV_OPEN_EVT, &evt_data, user_data); APPL_TRACE_DEBUG2("PORT_SUCCESS: curr_sess:%d, max_sess:%d", p_cb->curr_sess, p_cb->max_sess); failed = FALSE; } - else APPL_TRACE_ERROR0("bta_jv_add_rfc_port failed to create new listen port"); + else + APPL_TRACE_ERROR0("bta_jv_add_rfc_port failed to create new listen port"); } - if(failed) + if (failed) { evt_data.rfc_close.handle = p_cb->handle; evt_data.rfc_close.status = BTA_JV_FAILURE; @@ -2110,6 +2333,11 @@ static void bta_jv_port_event_sr_cback(UINT32 code, UINT16 port_handle) evt_data.rfc_cong.status = BTA_JV_SUCCESS; p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, user_data); } + + if (code & PORT_EV_TXEMPTY) + { + bta_jv_pm_conn_idle(p_pcb->p_pm_cb); + } } /******************************************************************************* @@ -2126,11 +2354,11 @@ static tBTA_JV_PCB * bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pc UINT8 used = 0, i, listen=0; UINT32 si = 0; tPORT_STATE port_state; - UINT32 event_mask = (PORT_EV_RXCHAR | PORT_EV_FC | PORT_EV_FCS); + UINT32 event_mask = BTA_JV_RFC_EV_MASK; tBTA_JV_PCB *p_pcb = NULL; if (p_cb->max_sess > 1) { - for (i=0; imax_sess; i++) + for (i=0; i < p_cb->max_sess; i++) { if (p_cb->rfc_hdl[i] != 0) { @@ -2157,13 +2385,13 @@ static tBTA_JV_PCB * bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pc } else if (si == 0) { - si = (UINT32)(i + 1); + si = i + 1; } } APPL_TRACE_DEBUG5("bta_jv_add_rfc_port max_sess=%d used:%d curr_sess:%d, listen:%d si:%d", p_cb->max_sess, used, p_cb->curr_sess, listen, si); - if (used max_sess && listen == 1 && si) + if (used < p_cb->max_sess && listen == 1 && si) { si--; if (RFCOMM_CreateConnection(p_cb->sec_id, p_cb->scn, TRUE, @@ -2191,7 +2419,8 @@ FALSE-POSITIVE: port_state is initialized at PORT_GetState() */ p_pcb->handle, p_cb->curr_sess); } } - else APPL_TRACE_ERROR0("bta_jv_add_rfc_port, cannot create new rfc listen port"); + else + APPL_TRACE_ERROR0("bta_jv_add_rfc_port, cannot create new rfc listen port"); } APPL_TRACE_DEBUG2("bta_jv_add_rfc_port: sec id in use:%d, rfc_cb in use:%d", get_sec_id_used(), get_rfc_cb_used()); @@ -2211,7 +2440,7 @@ FALSE-POSITIVE: port_state is initialized at PORT_GetState() */ void bta_jv_rfcomm_start_server(tBTA_JV_MSG *p_data) { UINT16 handle = 0; - UINT32 event_mask = (PORT_EV_RXCHAR | PORT_EV_FC | PORT_EV_FCS); + UINT32 event_mask = BTA_JV_RFC_EV_MASK; tPORT_STATE port_state; UINT8 sec_id = 0; tBTA_JV_RFC_CB *p_cb = NULL; @@ -2304,9 +2533,9 @@ void bta_jv_rfcomm_stop_server(tBTA_JV_MSG *p_data) tBTA_JV_RFC_CB *p_cb = NULL; tBTA_JV_PCB *p_pcb = NULL; APPL_TRACE_ERROR0("bta_jv_rfcomm_stop_server"); - if(!ls->rfc_handle) + if(!ls->handle) { - APPL_TRACE_ERROR0("bta_jv_rfcomm_stop_server, rfc handle is null"); + APPL_TRACE_ERROR0("bta_jv_rfcomm_stop_server, jv handle is null"); return; } void* user_data = ls->user_data; @@ -2315,7 +2544,7 @@ void bta_jv_rfcomm_stop_server(tBTA_JV_MSG *p_data) APPL_TRACE_DEBUG2("bta_jv_rfcomm_stop_server: p_pcb:%p, p_pcb->port_handle:%d", p_pcb, p_pcb->port_handle); bta_jv_free_rfc_cb(p_cb, p_pcb); - APPL_TRACE_DEBUG2("bta_jv_rfcomm_stop_server: sec id in use:%d, rfc_cb in use:%d", + APPL_TRACE_DEBUG2("bta_jv_rfcomm_stop_server: sec id in use:%d, rfc_cb in use:%d", get_sec_id_used(), get_rfc_cb_used()); } @@ -2369,6 +2598,7 @@ void bta_jv_rfcomm_write(tBTA_JV_MSG *p_data) evt_data.req_id = wc->req_id; evt_data.cong = p_pcb->cong; evt_data.len = 0; + bta_jv_pm_conn_busy(p_pcb->p_pm_cb); if (!evt_data.cong && PORT_WriteDataCO(p_pcb->port_handle, &evt_data.len) == PORT_SUCCESS) @@ -2387,3 +2617,189 @@ void bta_jv_rfcomm_write(tBTA_JV_MSG *p_data) } } +/******************************************************************************* + ** + ** Function bta_jv_set_pm_profile + ** + ** Description Set or free power mode profile for a JV application + ** + ** Returns void + ** + *******************************************************************************/ +void bta_jv_set_pm_profile(tBTA_JV_MSG *p_data) +{ + tBTA_JV_STATUS status; + tBTA_JV_PM_CB *p_cb; + + APPL_TRACE_API3("bta_jv_set_pm_profile(handle: 0x%x, app_id: %d, init_st: %d)", + p_data->set_pm.handle, p_data->set_pm.app_id, p_data->set_pm.init_st); + + /* clear PM control block */ + if (p_data->set_pm.app_id == BTA_JV_PM_ID_CLEAR) + { + status = bta_jv_free_set_pm_profile_cb(p_data->set_pm.handle); + + if (status != BTA_JV_SUCCESS) + { + APPL_TRACE_WARNING1("bta_jv_set_pm_profile() free pm cb failed: reason %d", + status); + } + } + else /* set PM control block */ + { + p_cb = bta_jv_alloc_set_pm_profile_cb(p_data->set_pm.handle, + p_data->set_pm.app_id); + + if (NULL != p_cb) + bta_jv_pm_state_change(p_cb, p_data->set_pm.init_st); + else + APPL_TRACE_WARNING0("bta_jv_alloc_set_pm_profile_cb() failed"); + } +} + +/******************************************************************************* + ** + ** Function bta_jv_change_pm_state + ** + ** Description change jv pm connect state, used internally + ** + ** Returns void + ** + *******************************************************************************/ +void bta_jv_change_pm_state(tBTA_JV_MSG *p_data) +{ + tBTA_JV_API_PM_STATE_CHANGE *p_msg = (tBTA_JV_API_PM_STATE_CHANGE *)p_data; + + if (p_msg->p_cb) + bta_jv_pm_state_change(p_msg->p_cb, p_msg->state); +} + + +/******************************************************************************* + ** + ** Function bta_jv_set_pm_conn_state + ** + ** Description Send pm event state change to jv state machine to serialize jv pm changes + ** in relation to other jv messages. internal API use mainly. + ** + ** Params: p_cb: jv pm control block, NULL pointer returns failure + ** new_state: new PM connections state, setting is forced by action function + ** + ** Returns BTA_JV_SUCCESS, BTA_JV_FAILURE (buffer allocation, or NULL ptr!) + ** + *******************************************************************************/ +tBTA_JV_STATUS bta_jv_set_pm_conn_state(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE + new_st) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_PM_STATE_CHANGE *p_msg; + + if (NULL == p_cb) + return status; + + APPL_TRACE_API2("bta_jv_set_pm_conn_state(handle:0x%x, state: %d)", p_cb->handle, + new_st); + if ((p_msg = (tBTA_JV_API_PM_STATE_CHANGE *)GKI_getbuf( + sizeof(tBTA_JV_API_PM_STATE_CHANGE))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_PM_STATE_CHANGE_EVT; + p_msg->p_cb = p_cb; + p_msg->state = new_st; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + return (status); +} + +/******************************************************************************* + ** + ** Function bta_jv_pm_conn_busy + ** + ** Description set pm connection busy state (input param safe) + ** + ** Params p_cb: pm control block of jv connection + ** + ** Returns void + ** + *******************************************************************************/ +static void bta_jv_pm_conn_busy(tBTA_JV_PM_CB *p_cb) +{ + if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST == p_cb->state)) + bta_jv_pm_state_change(p_cb, BTA_JV_CONN_BUSY); +} + +/******************************************************************************* + ** + ** Function bta_jv_pm_conn_busy + ** + ** Description set pm connection busy state (input param safe) + ** + ** Params p_cb: pm control block of jv connection + ** + ** Returns void + ** + *******************************************************************************/ +static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB *p_cb) +{ + if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST != p_cb->state)) + bta_jv_pm_state_change(p_cb, BTA_JV_CONN_IDLE); +} + +/******************************************************************************* + ** + ** Function bta_jv_pm_state_change + ** + ** Description Notify power manager there is state change + ** + ** Params p_cb: must be NONE NULL + ** + ** Returns void + ** + *******************************************************************************/ +static void bta_jv_pm_state_change(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE state) +{ + APPL_TRACE_API5("bta_jv_pm_state_change(p_cb: 0x%x, handle: 0x%x, busy/idle_state: %d" + ", app_id: %d, conn_state: %d)", p_cb, p_cb->handle, p_cb->state, + p_cb->app_id, state); + + switch (state) + { + case BTA_JV_CONN_OPEN: + bta_sys_conn_open(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr); + break; + + case BTA_JV_CONN_CLOSE: + bta_sys_conn_close(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr); + break; + + case BTA_JV_APP_OPEN: + bta_sys_app_open(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr); + break; + + case BTA_JV_APP_CLOSE: + bta_sys_app_close(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr); + break; + + case BTA_JV_SCO_OPEN: + bta_sys_sco_open(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr); + break; + + case BTA_JV_SCO_CLOSE: + bta_sys_sco_close(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr); + break; + + case BTA_JV_CONN_IDLE: + p_cb->state = BTA_JV_PM_IDLE_ST; + bta_sys_idle(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr); + break; + + case BTA_JV_CONN_BUSY: + p_cb->state = BTA_JV_PM_BUSY_ST; + bta_sys_busy(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr); + break; + + default: + APPL_TRACE_WARNING1("bta_jv_pm_state_change(state: %d): Invalid state", state); + break; + } +} diff --git a/bta/jv/bta_jv_api.c b/bta/jv/bta_jv_api.c index c1dbe1625..542559f9b 100644 --- a/bta/jv/bta_jv_api.c +++ b/bta/jv/bta_jv_api.c @@ -22,7 +22,6 @@ * Technology (JABWT) as specified by the JSR82 specificiation * ******************************************************************************/ - #include "bta_api.h" #include "bd.h" #include "bta_sys.h" @@ -61,11 +60,17 @@ tBTA_JV_STATUS BTA_JvEnable(tBTA_JV_DM_CBACK *p_cback) { tBTA_JV_STATUS status = BTA_JV_FAILURE; tBTA_JV_API_ENABLE *p_buf; + int i; APPL_TRACE_API0( "BTA_JvEnable"); if(p_cback && FALSE == bta_sys_is_register(BTA_ID_JV)) { memset(&bta_jv_cb, 0, sizeof(tBTA_JV_CB)); + /* set handle to invalid value by default */ + for (i=0; ihdr.event = BTA_JV_API_RFCOMM_STOP_SERVER_EVT; - p_msg->rfc_handle = handle; + p_msg->handle = handle; p_msg->user_data = user_data; //caller's private data bta_sys_sendmsg(p_msg); status = BTA_JV_SUCCESS; @@ -1472,7 +1481,7 @@ tBTA_JV_STATUS BTA_JvRfcommRead(UINT32 handle, UINT32 req_id, UINT8 *p_data, UIN { tBTA_JV_STATUS status = BTA_JV_FAILURE; tBTA_JV_API_RFCOMM_READ *p_msg; - UINT32 hi = (handle & BTA_JV_RFC_HDL_MASK) - 1; + UINT32 hi = ((handle & BTA_JV_RFC_HDL_MASK)&~BTA_JV_RFCOMM_MASK) - 1; UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(handle); APPL_TRACE_API0( "BTA_JvRfcommRead"); @@ -1506,7 +1515,7 @@ tBTA_JV_STATUS BTA_JvRfcommRead(UINT32 handle, UINT32 req_id, UINT8 *p_data, UIN *******************************************************************************/ UINT16 BTA_JvRfcommGetPortHdl(UINT32 handle) { - UINT32 hi = (handle & BTA_JV_RFC_HDL_MASK) - 1; + UINT32 hi = ((handle & BTA_JV_RFC_HDL_MASK) & BTA_JV_RFCOMM_MASK) - 1; UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(handle); if (hi < BTA_JV_MAX_RFC_CONN && @@ -1532,7 +1541,7 @@ tBTA_JV_STATUS BTA_JvRfcommReady(UINT32 handle, UINT32 *p_data_size) { tBTA_JV_STATUS status = BTA_JV_FAILURE; UINT16 size = 0; - UINT32 hi = (handle & BTA_JV_RFC_HDL_MASK) - 1; + UINT32 hi = ((handle & BTA_JV_RFC_HDL_MASK)&~BTA_JV_RFCOMM_MASK) - 1; UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(handle); APPL_TRACE_API0( "BTA_JvRfcommReady"); @@ -1562,7 +1571,7 @@ tBTA_JV_STATUS BTA_JvRfcommWrite(UINT32 handle, UINT32 req_id) { tBTA_JV_STATUS status = BTA_JV_FAILURE; tBTA_JV_API_RFCOMM_WRITE *p_msg; - UINT32 hi = (handle & BTA_JV_RFC_HDL_MASK) - 1; + UINT32 hi = ((handle & BTA_JV_RFC_HDL_MASK)&~BTA_JV_RFCOMM_MASK) - 1; UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(handle); APPL_TRACE_API0( "BTA_JvRfcommWrite"); @@ -1584,3 +1593,42 @@ tBTA_JV_STATUS BTA_JvRfcommWrite(UINT32 handle, UINT32 req_id) return(status); } + +/******************************************************************************* + ** + ** Function BTA_JVSetPmProfile + ** + ** Description This function set or free power mode profile for different JV application + ** + ** Parameters: handle, JV handle from RFCOMM or L2CAP + ** app_id: app specific pm ID, can be BTA_JV_PM_ALL, see bta_dm_cfg.c for details + ** BTA_JV_PM_ID_CLEAR: removes pm management on the handle. init_st is ignored and + ** BTA_JV_CONN_CLOSE is called implicitely + ** init_st: state after calling this API. typically it should be BTA_JV_CONN_OPEN + ** + ** Returns BTA_JV_SUCCESS, if the request is being processed. + ** BTA_JV_FAILURE, otherwise. + ** + ** NOTE: BTA_JV_PM_ID_CLEAR: In general no need to be called as jv pm calls automatically + ** BTA_JV_CONN_CLOSE to remove in case of connection close! + ** + *******************************************************************************/ +tBTA_JV_STATUS BTA_JvSetPmProfile(UINT32 handle, tBTA_JV_PM_ID app_id, tBTA_JV_CONN_STATE init_st) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_SET_PM_PROFILE *p_msg; + + APPL_TRACE_API2("BTA_JVSetPmProfile handle:0x%x, app_id:%d", handle, app_id); + if ((p_msg = (tBTA_JV_API_SET_PM_PROFILE *)GKI_getbuf(sizeof(tBTA_JV_API_SET_PM_PROFILE))) + != NULL) + { + p_msg->hdr.event = BTA_JV_API_SET_PM_PROFILE_EVT; + p_msg->handle = handle; + p_msg->app_id = app_id; + p_msg->init_st = init_st; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return (status); +} diff --git a/bta/jv/bta_jv_int.h b/bta/jv/bta_jv_int.h index 493a96d86..436c0a543 100644 --- a/bta/jv/bta_jv_int.h +++ b/bta/jv/bta_jv_int.h @@ -28,6 +28,7 @@ #include "bta_api.h" #include "bta_jv_api.h" #include "rfcdefs.h" +#include "port_api.h" /***************************************************************************** ** Constants @@ -67,9 +68,15 @@ enum BTA_JV_API_RFCOMM_STOP_SERVER_EVT, BTA_JV_API_RFCOMM_READ_EVT, BTA_JV_API_RFCOMM_WRITE_EVT, + BTA_JV_API_SET_PM_PROFILE_EVT, + BTA_JV_API_PM_STATE_CHANGE_EVT, BTA_JV_MAX_INT_EVT }; +#ifndef BTA_JV_RFC_EV_MASK +#define BTA_JV_RFC_EV_MASK (PORT_EV_RXCHAR | PORT_EV_TXEMPTY | PORT_EV_FC | PORT_EV_FCS) +#endif + /* data type for BTA_JV_API_ENABLE_EVT */ typedef struct { @@ -122,7 +129,7 @@ typedef struct typedef struct { BT_HDR hdr; - void *user_data; /* piggyback caller's private data*/ + void *user_data; /* piggyback caller's private data*/ } tBTA_JV_API_CANCEL_DISCOVERY; @@ -150,6 +157,22 @@ typedef struct enum { + BTA_JV_PM_FREE_ST = 0, /* empty PM slot */ + BTA_JV_PM_IDLE_ST, + BTA_JV_PM_BUSY_ST +}; + +/* BTA JV PM control block */ +typedef struct +{ + UINT32 handle; /* The connection handle */ + UINT8 state; /* state: see above enum */ + tBTA_JV_PM_ID app_id; /* JV app specific id indicating power table to use */ + BD_ADDR peer_bd_addr; /* Peer BD address */ +} tBTA_JV_PM_CB; + +enum +{ BTA_JV_ST_NONE = 0, BTA_JV_ST_CL_OPENING, BTA_JV_ST_CL_OPEN, @@ -168,11 +191,14 @@ typedef struct UINT16 psm; /* the psm used for this server connection */ tBTA_JV_STATE state; /* the state of this control block */ tBTA_SERVICE_ID sec_id; /* service id */ - UINT16 handle; /* the handle reported to java app (same as gap handle) */ + UINT32 handle; /* the handle reported to java app (same as gap handle) */ BOOLEAN cong; /* TRUE, if congested */ + tBTA_JV_PM_CB *p_pm_cb; /* ptr to pm control block, NULL: unused */ } tBTA_JV_L2C_CB; #define BTA_JV_RFC_HDL_MASK 0xFF +#define BTA_JV_RFCOMM_MASK 0x80 +#define BTA_JV_ALL_APP_ID 0xFF #define BTA_JV_RFC_HDL_TO_SIDX(r) (((r)&0xFF00) >> 8) #define BTA_JV_RFC_H_S_TO_HDL(h, s) ((h)|(s<<8)) @@ -185,6 +211,7 @@ typedef struct UINT8 max_sess; /* max sessions */ void *user_data; /* piggyback caller's private data*/ BOOLEAN cong; /* TRUE, if congested */ + tBTA_JV_PM_CB *p_pm_cb; /* ptr to pm control block, NULL: unused */ } tBTA_JV_PCB; /* JV RFCOMM control block */ @@ -226,7 +253,7 @@ typedef struct typedef struct { BT_HDR hdr; - UINT16 handle; + UINT32 handle; tBTA_JV_L2C_CB *p_cb; } tBTA_JV_API_L2CAP_CLOSE; @@ -234,7 +261,7 @@ typedef struct typedef struct { BT_HDR hdr; - UINT16 handle; + UINT32 handle; UINT32 req_id; tBTA_JV_L2CAP_CBACK *p_cback; UINT8* p_data; @@ -245,7 +272,7 @@ typedef struct typedef struct { BT_HDR hdr; - UINT16 handle; + UINT32 handle; UINT32 req_id; tBTA_JV_L2C_CB *p_cb; UINT8 *p_data; @@ -272,7 +299,7 @@ typedef struct tBTA_JV_ROLE role; UINT8 local_scn; UINT8 max_session; - int rfc_handle; + UINT32 handle; tBTA_JV_RFCOMM_CBACK *p_cback; void *user_data; } tBTA_JV_API_RFCOMM_SERVER; @@ -281,7 +308,7 @@ typedef struct typedef struct { BT_HDR hdr; - UINT16 handle; + UINT32 handle; UINT32 req_id; UINT8 *p_data; UINT16 len; @@ -289,11 +316,28 @@ typedef struct tBTA_JV_PCB *p_pcb; } tBTA_JV_API_RFCOMM_READ; +/* data type for BTA_JV_API_SET_PM_PROFILE_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT32 handle; + tBTA_JV_PM_ID app_id; + tBTA_JV_CONN_STATE init_st; +} tBTA_JV_API_SET_PM_PROFILE; + +/* data type for BTA_JV_API_PM_STATE_CHANGE_EVT */ +typedef struct +{ + BT_HDR hdr; + tBTA_JV_PM_CB *p_cb; + tBTA_JV_CONN_STATE state; +} tBTA_JV_API_PM_STATE_CHANGE; + /* data type for BTA_JV_API_RFCOMM_WRITE_EVT */ typedef struct { BT_HDR hdr; - UINT16 handle; + UINT32 handle; UINT32 req_id; UINT8 *p_data; int len; @@ -305,7 +349,7 @@ typedef struct typedef struct { BT_HDR hdr; - UINT16 handle; + UINT32 handle; tBTA_JV_RFC_CB *p_cb; tBTA_JV_PCB *p_pcb; void *user_data; @@ -372,6 +416,8 @@ typedef union tBTA_JV_API_RFCOMM_CONNECT rfcomm_connect; tBTA_JV_API_RFCOMM_READ rfcomm_read; tBTA_JV_API_RFCOMM_WRITE rfcomm_write; + tBTA_JV_API_SET_PM_PROFILE set_pm; + tBTA_JV_API_PM_STATE_CHANGE change_pm_state; tBTA_JV_API_RFCOMM_CLOSE rfcomm_close; tBTA_JV_API_RFCOMM_SERVER rfcomm_server; } tBTA_JV_MSG; @@ -402,6 +448,7 @@ typedef struct UINT8 sdp_active; /* see BTA_JV_SDP_ACT_* */ tSDP_UUID uuid; /* current uuid of sdp discovery*/ void *user_data; /* piggyback user data*/ + tBTA_JV_PM_CB pm_cb[BTA_JV_PM_MAX_NUM]; /* PM on a per JV handle bases */ } tBTA_JV_CB; enum @@ -459,5 +506,7 @@ extern void bta_jv_rfcomm_start_server (tBTA_JV_MSG *p_data); extern void bta_jv_rfcomm_stop_server (tBTA_JV_MSG *p_data); extern void bta_jv_rfcomm_read (tBTA_JV_MSG *p_data); extern void bta_jv_rfcomm_write (tBTA_JV_MSG *p_data); +extern void bta_jv_set_pm_profile (tBTA_JV_MSG *p_data); +extern void bta_jv_change_pm_state(tBTA_JV_MSG *p_data); #endif /* BTA_JV_INT_H */ diff --git a/bta/jv/bta_jv_main.c b/bta/jv/bta_jv_main.c index 0cba56b90..686ff17be 100644 --- a/bta/jv/bta_jv_main.c +++ b/bta/jv/bta_jv_main.c @@ -74,7 +74,9 @@ const tBTA_JV_ACTION bta_jv_action[] = bta_jv_rfcomm_start_server, /* BTA_JV_API_RFCOMM_START_SERVER_EVT */ bta_jv_rfcomm_stop_server, /* BTA_JV_API_RFCOMM_STOP_SERVER_EVT */ bta_jv_rfcomm_read, /* BTA_JV_API_RFCOMM_READ_EVT */ - bta_jv_rfcomm_write /* BTA_JV_API_RFCOMM_WRITE_EVT */ + bta_jv_rfcomm_write, /* BTA_JV_API_RFCOMM_WRITE_EVT */ + bta_jv_set_pm_profile, /* BTA_JV_API_SET_PM_PROFILE_EVT */ + bta_jv_change_pm_state, /* BTA_JV_API_PM_STATE_CHANGE_EVT */ }; /******************************************************************************* diff --git a/btif/src/btif_sock_rfc.c b/btif/src/btif_sock_rfc.c index 9d7f9bdf7..41521f134 100644 --- a/btif/src/btif_sock_rfc.c +++ b/btif/src/btif_sock_rfc.c @@ -291,9 +291,12 @@ static inline rfc_slot_t* create_srv_accept_rfc_slot(rfc_slot_t* srv_rs, const b accept_rs->role = srv_rs->role; accept_rs->rfc_handle = open_handle; accept_rs->rfc_port_handle = BTA_JvRfcommGetPortHdl(open_handle); - //now update listen handle of server slot + //now update listen rfc_handle of server slot srv_rs->rfc_handle = new_listen_handle; srv_rs->rfc_port_handle = BTA_JvRfcommGetPortHdl(new_listen_handle); + BTIF_TRACE_DEBUG4("create_srv_accept__rfc_slot(open_handle: 0x%x, new_listen_handle:" + "0x%x) accept_rs->rfc_handle:0x%x, srv_rs_listen->rfc_handle:0x%x" + ,open_handle, new_listen_handle, accept_rs->rfc_port_handle, srv_rs->rfc_port_handle); asrt(accept_rs->rfc_port_handle != srv_rs->rfc_port_handle); //now swap the slot id uint32_t new_listen_id = accept_rs->id; @@ -499,7 +502,7 @@ static void cleanup_rfc_slot(rfc_slot_t* rs) } if(rs->rfc_handle && !rs->f.closing && !rs->f.server) { - APPL_TRACE_DEBUG1("closing rfcomm connection, rfc_handle:%d", rs->rfc_handle); + APPL_TRACE_DEBUG1("closing rfcomm connection, rfc_handle:0x%x", rs->rfc_handle); BTA_JvRfcommClose(rs->rfc_handle, (void*)rs->id); rs->rfc_handle = 0; } @@ -642,7 +645,7 @@ static void on_rfc_close(tBTA_JV_RFCOMM_CLOSE * p_close, uint32_t id) APPL_TRACE_DEBUG4("on_rfc_close, slot id:%d, fd:%d, rfc scn:%d, server:%d", rs->id, rs->fd, rs->scn, rs->f.server); free_rfc_slot_scn(rs); - //rfc_handle already closed when receiving rfcomm close event from stack. + // rfc_handle already closed when receiving rfcomm close event from stack. rs->f.connected = FALSE; cleanup_rfc_slot(rs); } @@ -690,9 +693,11 @@ static void *rfcomm_cback(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data) break; case BTA_JV_RFCOMM_OPEN_EVT: + BTA_JvSetPmProfile(p_data->rfc_open.handle,BTA_JV_PM_ID_1,BTA_JV_CONN_OPEN); on_cli_rfc_connect(&p_data->rfc_open, (uint32_t)user_data); break; case BTA_JV_RFCOMM_SRV_OPEN_EVT: + BTA_JvSetPmProfile(p_data->rfc_srv_open.handle,BTA_JV_PM_ALL,BTA_JV_CONN_OPEN); new_user_data = (void*)on_srv_rfc_connect(&p_data->rfc_srv_open, (uint32_t)user_data); break; @@ -922,8 +927,7 @@ void btsock_rfc_signaled(int fd, int flags, uint32_t user_id) } unlock_slot(&slot_lock); } -//stack rfcomm callout functions -//[ + int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf) { uint32_t id = (uint32_t)user_data; @@ -1002,5 +1006,4 @@ int bta_co_rfc_data_outgoing(void *user_data, UINT8* buf, UINT16 size) unlock_slot(&slot_lock); return ret; } -//] -- 2.11.0