diff options
author | Harish Paryani <hparyani@broadcom.com> | 2012-04-03 23:49:45 -0700 |
---|---|---|
committer | Matthew Xie <mattx@google.com> | 2012-07-14 11:19:14 -0700 |
commit | 66aa5171e4e7c9f942971a30419c03134e67a4a4 (patch) | |
tree | 60fe10f29e7c3a574dcc317567a3c9bf05c85387 | |
parent | 04db88d9bd23fa98916e031987f3ba2063783acc (diff) | |
download | external_bluetooth_bluedroid-66aa5171e4e7c9f942971a30419c03134e67a4a4.zip external_bluetooth_bluedroid-66aa5171e4e7c9f942971a30419c03134e67a4a4.tar.gz external_bluetooth_bluedroid-66aa5171e4e7c9f942971a30419c03134e67a4a4.tar.bz2 |
Check in for - new rfc multi accept code
Change-Id: I66794a8821481c58e045bb8acd8b7b758900d3e9
29 files changed, 9195 insertions, 222 deletions
diff --git a/bta/Android.mk b/bta/Android.mk index 0076c3f..79d8677 100644 --- a/bta/Android.mk +++ b/bta/Android.mk @@ -8,9 +8,9 @@ include $(CLEAR_VARS) ifeq ($(BOARD_HAVE_BLUETOOTH_BCM),true) LOCAL_CFLAGS += \ - -DBOARD_HAVE_BLUETOOTH_BCM + -DBOARD_HAVE_BLUETOOTH_BCM endif -LOCAL_CFLAGS += -DBUILDCFG +LOCAL_CFLAGS += -DBUILDCFG LOCAL_PRELINK_MODULE:=false LOCAL_SRC_FILES:= \ @@ -120,9 +120,13 @@ LOCAL_SRC_FILES:= \ ./sys/bta_sys_cfg.c \ ./sys/ptim.c \ ./sys/bd.c \ - ./sys/utl.c + ./sys/utl.c \ + ./jv/bta_jv_act.c \ + ./jv/bta_jv_cfg.c \ + ./jv/bta_jv_main.c \ + ./jv/bta_jv_api.c -LOCAL_MODULE := libbt-brcm_bta +LOCAL_MODULE := libbt-brcm_bta LOCAL_MODULE_TAGS := optional LOCAL_SHARED_LIBRARIES := libcutils libc diff --git a/bta/include/bta_jv_api.h b/bta/include/bta_jv_api.h new file mode 100755 index 0000000..303ef2d --- /dev/null +++ b/bta/include/bta_jv_api.h @@ -0,0 +1,1109 @@ +/***************************************************************************** +** +** Name: bta_jv_api.h +** +** Description: This is the public interface file the BTA Java I/F +** +** Copyright (c) 2006-2009, Broadcom Corp., All Rights Reserved. +** Widcomm Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ +#ifndef BTA_JV_API_H +#define BTA_JV_API_H + +#include "data_types.h" +#include "bt_target.h" +#include "bt_types.h" +#include "bta_api.h" +#include "btm_api.h" +/***************************************************************************** +** Constants and data types +*****************************************************************************/ +/* status values */ +#define BTA_JV_SUCCESS 0 /* Successful operation. */ +#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. */ + +typedef UINT8 tBTA_JV_STATUS; +#define BTA_JV_INTERNAL_ERR (-1) /* internal error. */ + +#define BTA_JV_MAX_UUIDS SDP_MAX_UUID_FILTERS +#define BTA_JV_MAX_ATTRS SDP_MAX_ATTR_FILTERS +#define BTA_JV_MAX_SDP_REC SDP_MAX_RECORDS +#if SDP_FOR_JV_INCLUDED == TRUE +#define BTA_JV_MAX_L2C_CONN (GAP_MAX_CONNECTIONS + 1) +#else +#define BTA_JV_MAX_L2C_CONN GAP_MAX_CONNECTIONS +#endif +#define BTA_JV_MAX_SCN PORT_MAX_RFC_PORTS /* same as BTM_MAX_SCN (in btm_int.h) */ +#define BTA_JV_MAX_RFC_CONN MAX_RFC_PORTS + +#ifndef BTA_JV_DEF_RFC_MTU +#define BTA_JV_DEF_RFC_MTU (3*330) +#endif + +/* */ +#ifndef BTA_JV_MAX_RFC_SR_SESSION +#define BTA_JV_MAX_RFC_SR_SESSION 3 +#endif + +/* BTA_JV_MAX_RFC_SR_SESSION can not be bigger than MAX_BD_CONNECTIONS */ +#if (BTA_JV_MAX_RFC_SR_SESSION > MAX_BD_CONNECTIONS) +#undef BTA_JV_MAX_RFC_SR_SESSION +#define BTA_JV_MAX_RFC_SR_SESSION MAX_BD_CONNECTIONS +#endif + +#define BTA_JV_FIRST_SERVICE_ID BTA_FIRST_JV_SERVICE_ID +#define BTA_JV_LAST_SERVICE_ID BTA_LAST_JV_SERVICE_ID +#define BTA_JV_NUM_SERVICE_ID (BTA_LAST_JV_SERVICE_ID - BTA_FIRST_JV_SERVICE_ID + 1) + +/* Discoverable modes */ +enum +{ + BTA_JV_DISC_NONE, + BTA_JV_DISC_LIMITED, + BTA_JV_DISC_GENERAL +}; +typedef UINT16 tBTA_JV_DISC; + +/* Security Mode (BTA_JvGetSecurityMode) */ +#define BTA_JV_SEC_MODE_UNDEFINED BTM_SEC_MODE_UNDEFINED /* 0 */ +#define BTA_JV_SEC_MODE_NONE BTM_SEC_MODE_NONE /* 1 */ +#define BTA_JV_SEC_MODE_SERVICE BTM_SEC_MODE_SERVICE /* 2 */ +#define BTA_JV_SEC_MODE_LINK BTM_SEC_MODE_LINK /* 3 */ +#define BTA_JV_SEC_MODE_SP BTM_SEC_MODE_SP /* 4 */ +#define BTA_JV_SEC_MODE_SP_DEBUG BTM_SEC_MODE_SP_DEBUG /* 5 */ +typedef UINT8 tBTA_JV_SEC_MODE; + +#define BTA_JV_ROLE_SLAVE BTM_ROLE_SLAVE +#define BTA_JV_ROLE_MASTER BTM_ROLE_MASTER +typedef UINT32 tBTA_JV_ROLE; + +#define BTA_JV_SERVICE_LMTD_DISCOVER BTM_COD_SERVICE_LMTD_DISCOVER /* 0x0020 */ +#define BTA_JV_SERVICE_POSITIONING BTM_COD_SERVICE_POSITIONING /* 0x0100 */ +#define BTA_JV_SERVICE_NETWORKING BTM_COD_SERVICE_NETWORKING /* 0x0200 */ +#define BTA_JV_SERVICE_RENDERING BTM_COD_SERVICE_RENDERING /* 0x0400 */ +#define BTA_JV_SERVICE_CAPTURING BTM_COD_SERVICE_CAPTURING /* 0x0800 */ +#define BTA_JV_SERVICE_OBJ_TRANSFER BTM_COD_SERVICE_OBJ_TRANSFER /* 0x1000 */ +#define BTA_JV_SERVICE_AUDIO BTM_COD_SERVICE_AUDIO /* 0x2000 */ +#define BTA_JV_SERVICE_TELEPHONY BTM_COD_SERVICE_TELEPHONY /* 0x4000 */ +#define BTA_JV_SERVICE_INFORMATION BTM_COD_SERVICE_INFORMATION /* 0x8000 */ + + + +/* Java I/F callback events */ +/* events received by tBTA_JV_DM_CBACK */ +#define BTA_JV_ENABLE_EVT 0 /* JV enabled */ +#define BTA_JV_SET_DISCOVER_EVT 1 /* the result for BTA_JvSetDiscoverability */ +#define BTA_JV_LOCAL_ADDR_EVT 2 /* Local device address */ +#define BTA_JV_LOCAL_NAME_EVT 3 /* Local device name */ +#define BTA_JV_REMOTE_NAME_EVT 4 /* Remote device name */ +#define BTA_JV_SET_ENCRYPTION_EVT 5 /* Set Encryption */ +#define BTA_JV_GET_SCN_EVT 6 /* Reserved an SCN */ +#define BTA_JV_GET_PSM_EVT 7 /* Reserved a PSM */ +#define BTA_JV_DISCOVERY_COMP_EVT 8 /* SDP discovery complete */ +#define BTA_JV_SERVICES_LEN_EVT 9 /* the result for BTA_JvGetServicesLength */ +#define BTA_JV_SERVICE_SEL_EVT 10 /* the result for BTA_JvServiceSelect */ +#define BTA_JV_CREATE_RECORD_EVT 11 /* the result for BTA_JvCreateRecord */ +#define BTA_JV_UPDATE_RECORD_EVT 12 /* the result for BTA_JvUpdateRecord */ +#define BTA_JV_ADD_ATTR_EVT 13 /* the result for BTA_JvAddAttribute */ +#define BTA_JV_DELETE_ATTR_EVT 14 /* the result for BTA_JvDeleteAttribute */ +#define BTA_JV_CANCEL_DISCVRY_EVT 15 /* the result for BTA_JvCancelDiscovery */ + +/* events received by tBTA_JV_L2CAP_CBACK */ +#define BTA_JV_L2CAP_OPEN_EVT 16 /* open status of L2CAP connection */ +#define BTA_JV_L2CAP_CLOSE_EVT 17 /* L2CAP connection closed */ +#define BTA_JV_L2CAP_START_EVT 18 /* L2CAP server started */ +#define BTA_JV_L2CAP_CL_INIT_EVT 19 /* L2CAP client initiated a connection */ +#define BTA_JV_L2CAP_DATA_IND_EVT 20 /* L2CAP connection received data */ +#define BTA_JV_L2CAP_CONG_EVT 21 /* L2CAP connection congestion status changed */ +#define BTA_JV_L2CAP_READ_EVT 22 /* the result for BTA_JvL2capRead */ +#define BTA_JV_L2CAP_RECEIVE_EVT 23 /* the result for BTA_JvL2capReceive*/ +#define BTA_JV_L2CAP_WRITE_EVT 24 /* the result for BTA_JvL2capWrite*/ + +/* events received by tBTA_JV_RFCOMM_CBACK */ +#define BTA_JV_RFCOMM_OPEN_EVT 25 /* open status of RFCOMM Client connection */ +#define BTA_JV_RFCOMM_CLOSE_EVT 26 /* RFCOMM connection closed */ +#define BTA_JV_RFCOMM_START_EVT 27 /* RFCOMM server started */ +#define BTA_JV_RFCOMM_CL_INIT_EVT 28 /* RFCOMM client initiated a connection */ +#define BTA_JV_RFCOMM_DATA_IND_EVT 29 /* RFCOMM connection received data */ +#define BTA_JV_RFCOMM_CONG_EVT 30 /* RFCOMM connection congestion status changed */ +#define BTA_JV_RFCOMM_READ_EVT 31 /* the result for BTA_JvRfcommRead */ +#define BTA_JV_RFCOMM_WRITE_EVT 32 /* the result for BTA_JvRfcommWrite*/ +#define BTA_JV_RFCOMM_SRV_OPEN_EVT 33 /* open status of Server RFCOMM connection */ +#define BTA_JV_MAX_EVT 34 /* max number of JV events */ + +typedef UINT16 tBTA_JV_EVT; + +/* data associated with BTA_JV_SET_DISCOVER_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + tBTA_JV_DISC disc_mode; /* The current discoverable mode */ +} tBTA_JV_SET_DISCOVER; + +/* data associated with BTA_JV_DISCOVERY_COMP_EVT_ */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + int scn; /* channel # */ +} tBTA_JV_DISCOVERY_COMP; + +/* data associated with BTA_JV_SET_ENCRYPTION_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + BD_ADDR bd_addr; /* The peer address */ +} tBTA_JV_SET_ENCRYPTION; + +/* data associated with BTA_JV_SERVICES_LEN_EVT */ +typedef struct +{ + INT32 num_services; /* -1, if error. Otherwise, the number of + * services collected from peer */ + UINT16 *p_services_len; /* this points the same location as the + * parameter in BTA_JvGetServicesLength() */ +} tBTA_JV_SERVICES_LEN; + +/* data associated with BTA_JV_SERVICE_SEL_EVT */ +typedef struct +{ + BD_ADDR bd_addr; /* The peer address */ + UINT16 service_len; /* the length of this record */ +} tBTA_JV_SERVICE_SEL; + +/* data associated with BTA_JV_CREATE_RECORD_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ +} tBTA_JV_CREATE_RECORD; + +/* data associated with BTA_JV_UPDATE_RECORD_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The SDP record handle was updated */ +} tBTA_JV_UPDATE_RECORD; + +/* data associated with BTA_JV_ADD_ATTR_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The SDP record handle was updated */ +} tBTA_JV_ADD_ATTR; + +/* data associated with BTA_JV_DELETE_ATTR_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The SDP record handle was updated */ +} tBTA_JV_DELETE_ATTR; + +/* data associated with BTA_JV_L2CAP_OPEN_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + BD_ADDR rem_bda; /* The peer address */ + INT32 tx_mtu; /* The transmit MTU */ +} tBTA_JV_L2CAP_OPEN; + +/* data associated with BTA_JV_L2CAP_CLOSE_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + BOOLEAN async; /* FALSE, if local initiates disconnect */ +} tBTA_JV_L2CAP_CLOSE; + +/* data associated with BTA_JV_L2CAP_START_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + UINT8 sec_id; /* security ID used by this server */ +} tBTA_JV_L2CAP_START; + +/* data associated with BTA_JV_L2CAP_CL_INIT_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + UINT8 sec_id; /* security ID used by this client */ +} tBTA_JV_L2CAP_CL_INIT; + +/* data associated with BTA_JV_L2CAP_CONG_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + BOOLEAN cong; /* TRUE, congested. FALSE, uncongested */ +} tBTA_JV_L2CAP_CONG; + +/* data associated with BTA_JV_L2CAP_READ_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + UINT32 req_id; /* The req_id in the associated BTA_JvL2capRead() */ + UINT8 *p_data; /* This points the same location as the p_data + * parameter in BTA_JvL2capRead () */ + UINT16 len; /* The length of the data read. */ +} tBTA_JV_L2CAP_READ; + +/* data associated with BTA_JV_L2CAP_RECEIVE_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + UINT32 req_id; /* The req_id in the associated BTA_JvL2capReceive() */ + UINT8 *p_data; /* This points the same location as the p_data + * parameter in BTA_JvL2capReceive () */ + UINT16 len; /* The length of the data read. */ +} tBTA_JV_L2CAP_RECEIVE; + +/* data associated with BTA_JV_L2CAP_WRITE_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + UINT32 req_id; /* The req_id in the associated BTA_JvL2capWrite() */ + UINT16 len; /* The length of the data written. */ + BOOLEAN cong; /* congestion status */ +} tBTA_JV_L2CAP_WRITE; + +/* data associated with BTA_JV_RFCOMM_OPEN_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + BD_ADDR rem_bda; /* The peer address */ +} tBTA_JV_RFCOMM_OPEN; +/* data associated with BTA_JV_RFCOMM_SRV_OPEN_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + UINT32 new_listen_handle; /* The new listen handle */ + BD_ADDR rem_bda; /* The peer address */ +} tBTA_JV_RFCOMM_SRV_OPEN; + + +/* data associated with BTA_JV_RFCOMM_CLOSE_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 port_status; /* PORT status */ + UINT32 handle; /* The connection handle */ + BOOLEAN async; /* FALSE, if local initiates disconnect */ +} tBTA_JV_RFCOMM_CLOSE; + +/* data associated with BTA_JV_RFCOMM_START_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + UINT8 sec_id; /* security ID used by this server */ + BOOLEAN use_co; /* TRUE to use co_rfc_data */ +} tBTA_JV_RFCOMM_START; + +/* data associated with BTA_JV_RFCOMM_CL_INIT_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + UINT8 sec_id; /* security ID used by this client */ + BOOLEAN use_co; /* TRUE to use co_rfc_data */ +} tBTA_JV_RFCOMM_CL_INIT; +/*data associated with BTA_JV_L2CAP_DATA_IND_EVT & BTA_JV_RFCOMM_DATA_IND_EVT */ +typedef struct +{ + UINT32 handle; /* The connection handle */ +} tBTA_JV_DATA_IND; + +/* data associated with BTA_JV_RFCOMM_CONG_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + BOOLEAN cong; /* TRUE, congested. FALSE, uncongested */ +} tBTA_JV_RFCOMM_CONG; + +/* data associated with BTA_JV_RFCOMM_READ_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + UINT32 req_id; /* The req_id in the associated BTA_JvRfcommRead() */ + UINT8 *p_data; /* This points the same location as the p_data + * parameter in BTA_JvRfcommRead () */ + UINT16 len; /* The length of the data read. */ +} tBTA_JV_RFCOMM_READ; + +/* data associated with BTA_JV_RFCOMM_WRITE_EVT */ +typedef struct +{ + tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT32 handle; /* The connection handle */ + UINT32 req_id; /* The req_id in the associated BTA_JvRfcommWrite() */ + int len; /* The length of the data written. */ + BOOLEAN cong; /* congestion status */ +} tBTA_JV_RFCOMM_WRITE; + + +/* union of data associated with JV callback */ +typedef union +{ + tBTA_JV_STATUS status; /* BTA_JV_ENABLE_EVT */ + tBTA_JV_DISCOVERY_COMP disc_comp; /* BTA_JV_DISCOVERY_COMP_EVT */ + tBTA_JV_SET_DISCOVER set_discover; /* BTA_JV_SET_DISCOVER_EVT */ + tBTA_JV_SET_ENCRYPTION set_encrypt; /* BTA_JV_SET_ENCRYPTION_EVT */ + BD_ADDR bd_addr; /* BTA_JV_LOCAL_ADDR_EVT */ + UINT8 *p_name; /* BTA_JV_LOCAL_NAME_EVT, + BTA_JV_REMOTE_NAME_EVT */ + UINT8 scn; /* BTA_JV_GET_SCN_EVT */ + UINT16 psm; /* BTA_JV_GET_PSM_EVT */ + tBTA_JV_SERVICES_LEN servs_len; /* BTA_JV_SERVICES_LEN_EVT */ + tBTA_JV_SERVICE_SEL serv_sel; /* BTA_JV_SERVICE_SEL_EVT */ + tBTA_JV_CREATE_RECORD create_rec; /* BTA_JV_CREATE_RECORD_EVT */ + tBTA_JV_UPDATE_RECORD update_rec; /* BTA_JV_UPDATE_RECORD_EVT */ + tBTA_JV_ADD_ATTR add_attr; /* BTA_JV_ADD_ATTR_EVT */ + tBTA_JV_DELETE_ATTR del_attr; /* BTA_JV_DELETE_ATTR_EVT */ + tBTA_JV_L2CAP_OPEN l2c_open; /* BTA_JV_L2CAP_OPEN_EVT */ + tBTA_JV_L2CAP_CLOSE l2c_close; /* BTA_JV_L2CAP_CLOSE_EVT */ + tBTA_JV_L2CAP_START l2c_start; /* BTA_JV_L2CAP_START_EVT */ + tBTA_JV_L2CAP_CL_INIT l2c_cl_init; /* BTA_JV_L2CAP_CL_INIT_EVT */ + tBTA_JV_L2CAP_CONG l2c_cong; /* BTA_JV_L2CAP_CONG_EVT */ + tBTA_JV_L2CAP_READ l2c_read; /* BTA_JV_L2CAP_READ_EVT */ + tBTA_JV_L2CAP_WRITE l2c_write; /* BTA_JV_L2CAP_WRITE_EVT */ + tBTA_JV_RFCOMM_OPEN rfc_open; /* BTA_JV_RFCOMM_OPEN_EVT */ + tBTA_JV_RFCOMM_SRV_OPEN rfc_srv_open; /* BTA_JV_RFCOMM_SRV_OPEN_EVT */ + tBTA_JV_RFCOMM_CLOSE rfc_close; /* BTA_JV_RFCOMM_CLOSE_EVT */ + tBTA_JV_RFCOMM_START rfc_start; /* BTA_JV_RFCOMM_START_EVT */ + tBTA_JV_RFCOMM_CL_INIT rfc_cl_init; /* BTA_JV_RFCOMM_CL_INIT_EVT */ + tBTA_JV_RFCOMM_CONG rfc_cong; /* BTA_JV_RFCOMM_CONG_EVT */ + tBTA_JV_RFCOMM_READ rfc_read; /* BTA_JV_RFCOMM_READ_EVT */ + tBTA_JV_RFCOMM_WRITE rfc_write; /* BTA_JV_RFCOMM_WRITE_EVT */ + tBTA_JV_DATA_IND data_ind; /* BTA_JV_L2CAP_DATA_IND_EVT + BTA_JV_RFCOMM_DATA_IND_EVT */ +} tBTA_JV; + +/* JAVA DM Interface callback */ +typedef void (tBTA_JV_DM_CBACK)(tBTA_JV_EVT event, tBTA_JV *p_data, void * user_data); + +/* JAVA RFCOMM interface callback */ +typedef void* (tBTA_JV_RFCOMM_CBACK)(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data); + +/* JAVA L2CAP interface callback */ +typedef void (tBTA_JV_L2CAP_CBACK)(tBTA_JV_EVT event, tBTA_JV *p_data); + +/* JV configuration structure */ +typedef struct +{ + UINT16 sdp_raw_size; /* The size of p_sdp_raw_data */ + UINT16 sdp_db_size; /* The size of p_sdp_db */ + UINT8 *p_sdp_raw_data; /* The data buffer to keep raw data */ + tSDP_DISCOVERY_DB *p_sdp_db; /* The data buffer to keep SDP database */ +} tBTA_JV_CFG; + +/***************************************************************************** +** External Function Declarations +*****************************************************************************/ +#ifdef __cplusplus +extern "C" +{ +#endif + +/******************************************************************************* +** +** Function BTA_JvEnable +** +** Description Enable the Java I/F service. When the enable +** operation is complete the callback function will be +** called with a BTA_JV_ENABLE_EVT. This function must +** be called before other functions in the JV API are +** called. +** +** Returns BTA_JV_SUCCESS if successful. +** BTA_JV_FAIL if internal failure. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvEnable(tBTA_JV_DM_CBACK *p_cback); + +/******************************************************************************* +** +** Function BTA_JvDisable +** +** Description Disable the Java I/F +** +** Returns void +** +*******************************************************************************/ +BTA_API extern void BTA_JvDisable(void); + +/******************************************************************************* +** +** Function BTA_JvIsEnable +** +** Description Get the JV registration status. +** +** Returns TRUE, if registered +** +*******************************************************************************/ +BTA_API extern BOOLEAN BTA_JvIsEnable(void); + +/******************************************************************************* +** +** Function BTA_JvSetDiscoverability +** +** Description This function sets the Bluetooth discoverable modes +** of the local device. This controls whether other +** Bluetooth devices can find the local device. +** +** When the operation is complete the tBTA_JV_DM_CBACK callback +** function will be called with a BTA_JV_SET_DISCOVER_EVT. +** +** Returns BTA_JV_SUCCESS if successful. +** BTA_JV_FAIL if internal failure. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvSetDiscoverability(tBTA_JV_DISC disc_mode); + +/******************************************************************************* +** +** Function BTA_JvGetDiscoverability +** +** Description This function gets the Bluetooth +** discoverable modes of local device +** +** Returns The current Bluetooth discoverable mode. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_DISC BTA_JvGetDiscoverability(void); + +/******************************************************************************* +** +** Function BTA_JvGetLocalDeviceAddr +** +** Description This function obtains the local Bluetooth device address. +** The local Bluetooth device address is reported by the +** tBTA_JV_DM_CBACK callback with a BTA_JV_LOCAL_ADDR_EVT. +** +** Returns BTA_JV_SUCCESS if successful. +** BTA_JV_FAIL if internal failure. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvGetLocalDeviceAddr(void); + +/******************************************************************************* +** +** Function BTA_JvGetLocalDeviceName +** +** Description This function obtains the name of the local device +** The local Bluetooth device name is reported by the +** tBTA_JV_DM_CBACK callback with a BTA_JV_LOCAL_NAME_EVT. +** +** Returns BTA_JV_SUCCESS if successful. +** BTA_JV_FAIL if internal failure. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvGetLocalDeviceName(void); + +/******************************************************************************* +** +** Function BTA_JvGetRemoteDeviceName +** +** Description This function obtains the name of the specified device. +** The Bluetooth device name is reported by the +** tBTA_JV_DM_CBACK callback with a BTA_JV_REMOTE_NAME_EVT. +** +** Returns BTA_JV_SUCCESS if successful. +** BTA_JV_FAIL if internal failure. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvGetRemoteDeviceName(BD_ADDR bd_addr); + +/******************************************************************************* +** +** Function BTA_JvGetPreknownDevice +** +** Description This function obtains the Bluetooth address in the inquiry +** database collected via the previous call to BTA_DmSearch(). +** +** Returns The number of preknown devices if p_bd_addr is NULL +** BTA_JV_SUCCESS if successful. +** BTA_JV_INTERNAL_ERR(-1) if internal failure. +** +*******************************************************************************/ +BTA_API extern INT32 BTA_JvGetPreknownDevice(UINT8 * p_bd_addr, UINT32 index); + +/******************************************************************************* +** +** Function BTA_JvGetDeviceClass +** +** Description This function obtains the local Class of Device. +** +** Returns DEV_CLASS, A three-byte array of UINT8 that contains the +** Class of Device information. The definitions are in the +** "Bluetooth Assigned Numbers". +** +*******************************************************************************/ +BTA_API extern UINT8 * BTA_JvGetDeviceClass(void); + +/******************************************************************************* +** +** Function BTA_JvSetServiceClass +** +** Description This function sets the service class of local Class of Device +** +** Returns BTA_JV_SUCCESS if successful. +** BTA_JV_FAIL if internal failure. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvSetServiceClass(UINT32 service); + +/******************************************************************************* +** +** Function BTA_JvSetEncryption +** +** Description This function ensures that the connection to the given device +** is encrypted. +** When the operation is complete the tBTA_JV_DM_CBACK callback +** function will be called with a BTA_JV_SET_ENCRYPTION_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvSetEncryption(BD_ADDR bd_addr); + +/******************************************************************************* +** +** Function BTA_JvIsAuthenticated +** +** Description This function checks if the peer device is authenticated +** +** Returns TRUE if authenticated. +** FALSE if not. +** +*******************************************************************************/ +BTA_API extern BOOLEAN BTA_JvIsAuthenticated(BD_ADDR bd_addr); + +/******************************************************************************* +** +** Function BTA_JvIsTrusted +** +** Description This function checks if the peer device is trusted +** (previously paired) +** +** Returns TRUE if trusted. +** FALSE if not. +** +*******************************************************************************/ +BTA_API extern BOOLEAN BTA_JvIsTrusted(BD_ADDR bd_addr); + +/******************************************************************************* +** +** Function BTA_JvIsAuthorized +** +** Description This function checks if the peer device is authorized +** +** Returns TRUE if authorized. +** FALSE if not. +** +*******************************************************************************/ +BTA_API extern BOOLEAN BTA_JvIsAuthorized(BD_ADDR bd_addr); + +/******************************************************************************* +** +** Function BTA_JvIsEncrypted +** +** Description This function checks if the link to peer device is encrypted +** +** Returns TRUE if encrypted. +** FALSE if not. +** +*******************************************************************************/ +BTA_API extern BOOLEAN BTA_JvIsEncrypted(BD_ADDR bd_addr); + +/******************************************************************************* +** +** Function BTA_JvGetSecurityMode +** +** Description This function returns the current Bluetooth security mode +** of the local device +** +** Returns The current Bluetooth security mode. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_SEC_MODE BTA_JvGetSecurityMode(void); + +/* BTA_JvIsMaster is replaced by BTA_DmIsMaster */ + +/******************************************************************************* +** +** Function BTA_JvGetSCN +** +** Description This function reserves a SCN (server channel number) for +** applications running over RFCOMM. It is primarily called by +** server profiles/applications to register their SCN into the +** SDP database. The SCN is reported by the tBTA_JV_DM_CBACK +** callback with a BTA_JV_GET_SCN_EVT. +** If the SCN reported is 0, that means all SCN resources are +** exhausted. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvGetSCN(void); + +/******************************************************************************* +** +** Function BTA_JvFreeSCN +** +** Description This function frees a server channel number that was used +** by an application running over RFCOMM. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvFreeSCN(UINT8 scn); + +/******************************************************************************* +** +** Function BTA_JvGetPSM +** +** Description This function reserves a PSM (Protocol Service Multiplexer) +** applications running over L2CAP. It is primarily called by +** server profiles/applications to register their PSM into the +** SDP database. +** +** Returns The next free PSM +** +*******************************************************************************/ +BTA_API extern UINT16 BTA_JvGetPSM(void); + +/******************************************************************************* +** +** Function BTA_JvStartDiscovery +** +** Description This function performs service discovery for the services +** provided by the given peer device. When the operation is +** complete the tBTA_JV_DM_CBACK callback function will be +** called with a BTA_JV_DISCOVERY_COMP_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvStartDiscovery(BD_ADDR bd_addr, UINT16 num_uuid, + tSDP_UUID *p_uuid_list, void* user_data); + +/******************************************************************************* +** +** Function BTA_JvCancelDiscovery +** +** Description This function cancels an active service discovery. +** When the operation is +** complete the tBTA_JV_DM_CBACK callback function will be +** called with a BTA_JV_CANCEL_DISCVRY_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvCancelDiscovery(void * user_data); + +/******************************************************************************* +** +** Function BTA_JvGetServicesLength +** +** Description This function obtains the number of services and the length +** of each service found in the SDP database (result of last +** BTA_JvStartDiscovery().When the operation is complete the +** tBTA_JV_DM_CBACK callback function will be called with a +** BTA_JV_SERVICES_LEN_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvGetServicesLength(BOOLEAN inc_hdr, UINT16 *p_services_len); + +/******************************************************************************* +** +** Function BTA_JvGetServicesResult +** +** Description This function returns a number of service records found +** during current service search, equals to the number returned +** by previous call to BTA_JvGetServicesLength. +** The contents of each SDP record will be returned under a +** TLV (type, len, value) representation in the data buffer +** provided by the caller. +** +** Returns -1, if error. Otherwise, the number of services +** +*******************************************************************************/ +BTA_API extern INT32 BTA_JvGetServicesResult(BOOLEAN inc_hdr, UINT8 **TLVs); + +/******************************************************************************* +** +** Function BTA_JvServiceSelect +** +** Description This function checks if the SDP database contains the given +** service UUID. When the operation is complete the +** tBTA_JV_DM_CBACK callback function will be called with a +** BTA_JV_SERVICE_SEL_EVT with the length of the service record. +** If the service is not found or error, -1 is reported. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvServiceSelect(UINT16 uuid); + +/******************************************************************************* +** +** Function BTA_JvServiceResult +** +** Description This function returns the contents of the SDP record from +** last BTA_JvServiceSelect. The contents will be returned under +** a TLV (type, len, value) representation in the data buffer +** provided by the caller. +** +** Returns -1, if error. Otherwise, the length of service record. +** +*******************************************************************************/ +BTA_API extern INT32 BTA_JvServiceResult(UINT8 *TLV); + +/******************************************************************************* +** +** Function BTA_JvCreateRecord +** +** Description Create a service record in the local SDP database by user in +** tBTA_JV_DM_CBACK callback with a BTA_JV_CREATE_RECORD_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvCreateRecordByUser(void* user_data); + +/******************************************************************************* +** +** Function BTA_JvUpdateRecord +** +** Description Update a service record in the local SDP database. +** When the operation is complete the tBTA_JV_DM_CBACK callback +** function will be called with a BTA_JV_UPDATE_RECORD_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvUpdateRecord(UINT32 handle, UINT16 *p_ids, + UINT8 **p_values, INT32 *p_value_sizes, INT32 array_len); + +/******************************************************************************* +** +** Function BTA_JvAddAttribute +** +** Description Add an attribute to a service record in the local SDP database. +** When the operation is complete the tBTA_JV_DM_CBACK callback +** function will be called with a BTA_JV_ADD_ATTR_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvAddAttribute(UINT32 handle, UINT16 attr_id, + UINT8 *p_value, INT32 value_size); + +/******************************************************************************* +** +** Function BTA_JvDeleteAttribute +** +** Description Delete an attribute from a service record in the local SDP database. +** When the operation is complete the tBTA_JV_DM_CBACK callback +** function will be called with a BTA_JV_DELETE_ATTR_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvDeleteAttribute(UINT32 handle, UINT16 attr_id); + +/******************************************************************************* +** +** Function BTA_JvDeleteRecord +** +** Description Delete a service record in the local SDP database. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvDeleteRecord(UINT32 handle); + +/******************************************************************************* +** +** Function BTA_JvReadRecord +** +** Description Read a service record in the local SDP database. +** +** Returns -1, if the record is not found. +** Otherwise, the offset (0 or 1) to start of data in p_data. +** +** The size of data copied into p_data is in *p_data_len. +** +*******************************************************************************/ +BTA_API extern INT32 BTA_JvReadRecord(UINT32 handle, UINT8 *p_data, INT32 *p_data_len); + +/******************************************************************************* +** +** Function BTA_JvL2capConnect +** +** Description Initiate a connection as a L2CAP client to the given BD +** Address. +** When the connection is initiated or failed to initiate, +** tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_CL_INIT_EVT +** When the connection is established or failed, +** tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvL2capConnect(tBTA_SEC sec_mask, + tBTA_JV_ROLE role, UINT16 remote_psm, UINT16 rx_mtu, + BD_ADDR peer_bd_addr, tBTA_JV_L2CAP_CBACK *p_cback); + +/******************************************************************************* +** +** Function BTA_JvL2capClose +** +** Description This function closes an L2CAP client connection +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvL2capClose(UINT32 handle); + +/******************************************************************************* +** +** Function BTA_JvL2capStartServer +** +** Description This function starts an L2CAP server and listens for an L2CAP +** connection from a remote Bluetooth device. When the server +** is started successfully, tBTA_JV_L2CAP_CBACK is called with +** BTA_JV_L2CAP_START_EVT. When the connection is established, +** tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvL2capStartServer(tBTA_SEC sec_mask, tBTA_JV_ROLE role, + UINT16 local_psm, UINT16 rx_mtu, + tBTA_JV_L2CAP_CBACK *p_cback); + +/******************************************************************************* +** +** Function BTA_JvL2capStopServer +** +** Description This function stops the L2CAP server. If the server has an +** active connection, it would be closed. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvL2capStopServer(UINT16 local_psm); + +/******************************************************************************* +** +** Function BTA_JvL2capRead +** +** Description This function reads data from an L2CAP connection +** When the operation is complete, tBTA_JV_L2CAP_CBACK is +** called with BTA_JV_L2CAP_READ_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvL2capRead(UINT32 handle, UINT32 req_id, + UINT8 *p_data, UINT16 len); + +/******************************************************************************* +** +** Function BTA_JvL2capReceive +** +** Description This function reads data from an L2CAP connection +** When the operation is complete, tBTA_JV_L2CAP_CBACK is +** called with BTA_JV_L2CAP_RECEIVE_EVT. +** If there are more data queued in L2CAP than len, the extra data will be discarded. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvL2capReceive(UINT32 handle, UINT32 req_id, + UINT8 *p_data, UINT16 len); + +/******************************************************************************* +** +** Function BTA_JvL2capReady +** +** Description This function determined if there is data to read from +** an L2CAP connection +** +** Returns BTA_JV_SUCCESS, if data queue size is in *p_data_size. +** BTA_JV_FAILURE, if error. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvL2capReady(UINT32 handle, UINT32 *p_data_size); + +/******************************************************************************* +** +** Function BTA_JvL2capWrite +** +** Description This function writes data to an L2CAP connection +** When the operation is complete, tBTA_JV_L2CAP_CBACK is +** called with BTA_JV_L2CAP_WRITE_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvL2capWrite(UINT32 handle, UINT32 req_id, + UINT8 *p_data, UINT16 len); + +/******************************************************************************* +** +** Function BTA_JvRfcommConnect +** +** Description This function makes an RFCOMM conection to a remote BD +** Address. +** When the connection is initiated or failed to initiate, +** tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_CL_INIT_EVT +** When the connection is established or failed, +** tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_OPEN_EVT +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask, + tBTA_JV_ROLE role, UINT8 remote_scn, BD_ADDR peer_bd_addr, + tBTA_JV_RFCOMM_CBACK *p_cback, void *user_data); + +/******************************************************************************* +** +** Function BTA_JvRfcommClose +** +** Description This function closes an RFCOMM connection +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle); + +/******************************************************************************* +** +** Function BTA_JvRfcommStartServer +** +** Description This function starts listening for an RFCOMM connection +** request from a remote Bluetooth device. When the server is +** started successfully, tBTA_JV_RFCOMM_CBACK is called +** with BTA_JV_RFCOMM_START_EVT. +** When the connection is established, tBTA_JV_RFCOMM_CBACK +** is called with BTA_JV_RFCOMM_OPEN_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC sec_mask, + tBTA_JV_ROLE role, UINT8 local_scn, UINT8 max_session, + tBTA_JV_RFCOMM_CBACK *p_cback, void *user_data); + +/******************************************************************************* +** +** Function BTA_JvRfcommStopServer +** +** Description This function stops the RFCOMM server. If the server has an +** active connection, it would be closed. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvRfcommStopServer(UINT32 handle); + +/******************************************************************************* +** +** Function BTA_JvRfcommRead +** +** Description This function reads data from an RFCOMM connection +** When the operation is complete, tBTA_JV_RFCOMM_CBACK is +** called with BTA_JV_RFCOMM_READ_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvRfcommRead(UINT32 handle, UINT32 req_id, + UINT8 *p_data, UINT16 len); + +/******************************************************************************* +** +** Function BTA_JvRfcommReady +** +** Description This function determined if there is data to read from +** an RFCOMM connection +** +** Returns BTA_JV_SUCCESS, if data queue size is in *p_data_size. +** BTA_JV_FAILURE, if error. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvRfcommReady(UINT32 handle, UINT32 *p_data_size); + +/******************************************************************************* +** +** Function BTA_JvRfcommWrite +** +** Description This function writes data to an RFCOMM connection +** When the operation is complete, tBTA_JV_RFCOMM_CBACK is +** called with BTA_JV_RFCOMM_WRITE_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +BTA_API extern tBTA_JV_STATUS BTA_JvRfcommWrite(UINT32 handle, UINT32 req_id); + + +/******************************************************************************* +** +** Function BTA_JvRfcommGetPortHdl +** +** Description This function fetches the rfcomm port handle +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +UINT16 BTA_JvRfcommGetPortHdl(UINT32 handle); + +#ifdef __cplusplus +} +#endif + +#endif /* BTA_JV_API_H */ + diff --git a/bta/include/bta_jv_co.h b/bta/include/bta_jv_co.h new file mode 100755 index 0000000..09e09c5 --- /dev/null +++ b/bta/include/bta_jv_co.h @@ -0,0 +1,38 @@ +/***************************************************************************** +** +** Name: bta_jv_co.h +** +** Description: This is the interface file for java interface call-out +** functions. +** +** Copyright (c) 2007, Widcomm Inc., All Rights Reserved. +** Widcomm Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ +#ifndef BTA_JV_CO_H +#define BTA_JV_CO_H + +#include "bta_jv_api.h" + +/***************************************************************************** +** Function Declarations +*****************************************************************************/ + + +/******************************************************************************* +** +** Function bta_jv_co_rfc_data +** +** Description This function is called by JV to send data to the java glue +** code when the RX data path is configured to use a call-out +** +** Returns void +** +*******************************************************************************/ + +BTA_API extern int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf); +BTA_API extern int bta_co_rfc_data_outgoing_size(void *user_data, int *size); +BTA_API extern int bta_co_rfc_data_outgoing(void *user_data, UINT8* buf, UINT16 size); + +#endif /* BTA_DG_CO_H */ + diff --git a/bta/jv/bta_jv_act.c b/bta/jv/bta_jv_act.c new file mode 100755 index 0000000..60729e3 --- /dev/null +++ b/bta/jv/bta_jv_act.c @@ -0,0 +1,2339 @@ +/***************************************************************************** +** +** Name: bta_jv_act.c +** +** Description: This file contains action functions for advanced audio. +** +** Copyright (c) 2006-2009, Broadcom Corp., All Rights Reserved. +** Widcomm Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include <hardware/bluetooth.h> +#include <arpa/inet.h> + +#include "bt_types.h" +#include "gki.h" +#include "bd.h" +#include "utl.h" +#include "bta_sys.h" +#include "bta_api.h" +#include "bta_jv_api.h" +#include "bta_jv_int.h" +#include "bta_jv_co.h" +#include "btm_api.h" +#include "btm_int.h" +#include "sdp_api.h" +#include "l2c_api.h" +#include "port_api.h" +#include <string.h> +#include "rfcdefs.h" +#include "avct_api.h" +#include "avdt_api.h" + + +#include <cutils/log.h> +#define info(fmt, ...) LOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define debug(fmt, ...) LOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define error(fmt, ...) LOGE ("## ERROR : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__) +#define asrt(s) if(!(s)) LOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__) + + + +#define HDL2CB(handle) \ + UINT32 __hi = ((handle) & BTA_JV_RFC_HDL_MASK) - 1; \ + UINT32 __si = BTA_JV_RFC_HDL_TO_SIDX(handle); \ + tBTA_JV_RFC_CB *p_cb = &bta_jv_cb.rfc_cb[__hi]; \ + tBTA_JV_PCB *p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[__si] - 1] + +extern void uuid_to_string(bt_uuid_t *p_uuid, char *str); +static inline void logu(const char* title, const uint8_t * p_uuid) +{ + char uuids[128]; + uuid_to_string((bt_uuid_t*)p_uuid, uuids); + LOGD("%s: %s", title, uuids); +} + + +static tBTA_JV_PCB * bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb); + +/******************************************************************************* +** +** Function bta_jv_get_local_device_addr_cback +** +** Description Callback from btm after local bdaddr is read +** +** Returns void +** +*******************************************************************************/ +static void bta_jv_get_local_device_addr_cback(BD_ADDR bd_addr) +{ + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_LOCAL_ADDR_EVT, (tBTA_JV *)bd_addr, 0); +} + +/******************************************************************************* +** +** Function bta_jv_get_remote_device_name_cback +** +** Description Callback from btm after remote name is read +** +** Returns void +** +*******************************************************************************/ +static void bta_jv_get_remote_device_name_cback(tBTM_REMOTE_DEV_NAME *p_name) +{ + tBTA_JV evt_data; + evt_data.p_name = p_name->remote_bd_name; + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_REMOTE_NAME_EVT, &evt_data, 0); +} + +/******************************************************************************* +** +** Function bta_jv_alloc_sec_id +** +** Description allocate a security id +** +** Returns +** +*******************************************************************************/ +UINT8 bta_jv_alloc_sec_id(void) +{ + UINT8 ret = 0; + int i; + for(i=0; i<BTA_JV_NUM_SERVICE_ID; i++) + { + if(0 == bta_jv_cb.sec_id[i]) + { + bta_jv_cb.sec_id[i] = BTA_JV_FIRST_SERVICE_ID + i; + ret = bta_jv_cb.sec_id[i]; + break; + } + } + return ret; + +} + +/******************************************************************************* +** +** Function bta_jv_free_sec_id +** +** Description free the given security id +** +** Returns +** +*******************************************************************************/ +static void bta_jv_free_sec_id(UINT8 *p_sec_id) +{ + UINT8 sec_id = *p_sec_id; + *p_sec_id = 0; + if(sec_id >= BTA_JV_FIRST_SERVICE_ID && sec_id <= BTA_JV_LAST_SERVICE_ID) + { + BTM_SecClrService(sec_id); + bta_jv_cb.sec_id[sec_id - BTA_JV_FIRST_SERVICE_ID] = 0; + } +} + +/******************************************************************************* +** +** Function bta_jv_alloc_rfc_cb +** +** Description allocate a control block for the given port handle +** +** Returns +** +*******************************************************************************/ +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; + for(i=0; i<BTA_JV_MAX_RFC_CONN; i++) + { + if(0 == bta_jv_cb.rfc_cb[i].handle ) + { + p_cb = &bta_jv_cb.rfc_cb[i]; + p_cb->handle = i + 1; + p_cb->max_sess = 1; + 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); + p_pcb = &bta_jv_cb.port_cb[port_handle - 1]; + p_pcb->handle = p_cb->handle; + p_pcb->port_handle = port_handle; + *pp_pcb = p_pcb; + break; + } + } + return p_cb; +} + +/******************************************************************************* +** +** Function bta_jv_rfc_port_to_pcb +** +** Description find the port control block associated with the given port handle +** +** Returns +** +*******************************************************************************/ +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) + { + p_pcb = &bta_jv_cb.port_cb[port_handle - 1]; + } + + return p_pcb; +} + +/******************************************************************************* +** +** Function bta_jv_rfc_port_to_cb +** +** Description find the RFCOMM control block associated with the given port handle +** +** Returns +** +*******************************************************************************/ +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) + { + handle = bta_jv_cb.port_cb[port_handle - 1].handle; + handle &= BTA_JV_RFC_HDL_MASK; + if (handle) + p_cb = &bta_jv_cb.rfc_cb[handle - 1]; + } + return p_cb; +} + +/******************************************************************************* +** +** Function bta_jv_free_rfc_pcb +** +** Description free the given port control block +** +** Returns +** +*******************************************************************************/ +tBTA_JV_STATUS bta_jv_free_rfc_pcb(tBTA_JV_PCB *p_pcb) +{ + tBTA_JV_STATUS status = BTA_JV_SUCCESS; + BOOLEAN remove = FALSE; + BOOLEAN is_server = TRUE; + UINT16 port_handle; + + APPL_TRACE_DEBUG2( "bta_jv_free_rfc_pcb handle:%d s:%d", p_pcb->port_handle, p_pcb->state); + + if (p_pcb->port_handle) + { + if(BTA_JV_ST_NONE != p_pcb->state) + { + remove = TRUE; + if(p_pcb->state <= BTA_JV_ST_CL_MAX) + is_server = FALSE; + port_handle = p_pcb->port_handle; + } + p_pcb->port_handle = 0; + p_pcb->state = BTA_JV_ST_NONE; + + //Initialize congestion flags + p_pcb->cong = FALSE; + + if(remove) + { + if(is_server) + { + if(RFCOMM_RemoveServer(port_handle) != PORT_SUCCESS) + status = BTA_JV_FAILURE; + } + else + { + if(RFCOMM_RemoveConnection(port_handle) != PORT_SUCCESS) + status = BTA_JV_FAILURE; + } + } + } + return status; +} + +/******************************************************************************* +** +** Function bta_jv_free_rfc_cb +** +** Description free the given RFCOMM control block +** +** Returns +** +*******************************************************************************/ +tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb) +{ + tBTA_JV_STATUS status = BTA_JV_SUCCESS; + UINT8 i; + APPL_TRACE_DEBUG1( "bta_jv_free_rfc_cb max_sess:%d", p_cb->max_sess); + for (i=0; i<p_cb->max_sess; i++) + { + APPL_TRACE_DEBUG2( "[%d]: port=%d", i, p_cb->rfc_hdl[i]); + if (p_cb->rfc_hdl[i]) + bta_jv_free_rfc_pcb (&bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1]); + } + + p_cb->scn = 0; + bta_jv_free_sec_id(&p_cb->sec_id); + p_cb->p_cback = NULL; + p_cb->handle = 0; + + return status; +} +static tBTA_JV_STATUS bta_jv_free_rfc_listen_cb(tBTA_JV_RFC_CB *p_cb) +{ + tBTA_JV_STATUS status = BTA_JV_SUCCESS; + UINT8 i; + debug( "max_sess:%d", p_cb->max_sess); + for (i=0; i<p_cb->max_sess; i++) + { + APPL_TRACE_DEBUG2( "[%d]: port=%d", i, p_cb->rfc_hdl[i]); + if (p_cb->rfc_hdl[i]) + { + tBTA_JV_PCB *p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1]; + if(p_pcb->state == BTA_JV_ST_SR_LISTEN) + { + debug( "free listen pcb: scn:%d, ueser_data:%d", p_cb->scn, (int)p_pcb->user_data); + p_pcb->user_data = 0; + bta_jv_free_rfc_pcb (p_pcb); + p_cb->max_sess = 1; + break; + } + } + } + //p_cb->scn = 0; + bta_jv_free_sec_id(&p_cb->sec_id); + //p_cb->p_cback = NULL; + //p_cb->handle = 0; + return status; +} + +/******************************************************************************* +** +** Function bta_jv_free_l2c_cb +** +** Description free the given L2CAP control block +** +** Returns +** +*******************************************************************************/ +tBTA_JV_STATUS bta_jv_free_l2c_cb(tBTA_JV_L2C_CB *p_cb) +{ +#if 0 + tBTA_JV_STATUS status = BTA_JV_SUCCESS; + + if(BTA_JV_ST_NONE != p_cb->state) + { +#if SDP_FOR_JV_INCLUDED == TRUE + if(BTA_JV_L2C_FOR_SDP_HDL == p_cb->handle) + { + bta_jv_cb.sdp_data_size = 0; + if(SDP_ConnClose(bta_jv_cb.sdp_for_jv)) + { + bta_jv_cb.sdp_for_jv = 0; + } + else + status = BTA_JV_FAILURE; + } + else +#endif + if(GAP_ConnClose(p_cb->handle) != BT_PASS) + status = BTA_JV_FAILURE; + } + p_cb->psm = 0; + p_cb->state = BTA_JV_ST_NONE; + bta_jv_free_sec_id(&p_cb->sec_id); + p_cb->p_cback = NULL; + return status; +#endif + return 0; +} + +/******************************************************************************* +** +** 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; + UINT32 id = 0; + + /* find a free entry */ + for (j = 0; j < BTA_JV_MAX_SDP_REC; j++) + { + if (bta_jv_cb.sdp_handle[j] == 0) + { + bta_jv_cb.sdp_handle[j] = sdp_handle; + id = (UINT32)(j + 1); + break; + } + } + /* the SDP record handle reported is the (index + 1) to control block */ + return id; +} + +/******************************************************************************* +** +** Function bta_jv_free_sdp_id +** +** Description free the sdp id +** +** Returns +** +*******************************************************************************/ +void bta_jv_free_sdp_id(UINT32 sdp_id) +{ + if(sdp_id > 0 && sdp_id <= BTA_JV_MAX_SDP_REC) + { + bta_jv_cb.sdp_handle[sdp_id - 1] = 0; + } +} + +/******************************************************************************* +** +** Function bta_jv_get_sdp_handle +** +** Description find the SDP handle associated with the given sdp id +** +** Returns +** +*******************************************************************************/ +UINT32 bta_jv_get_sdp_handle(UINT32 sdp_id) +{ + UINT32 sdp_handle = 0; + + if(sdp_id > 0 && sdp_id <= BTA_JV_MAX_SDP_REC) + { + sdp_handle = bta_jv_cb.sdp_handle[sdp_id - 1]; + } + return sdp_handle; +} + +/******************************************************************************* +** +** Function bta_jv_check_psm +** +** Description for now use only the legal PSM per JSR82 spec +** +** Returns TRUE, if allowed +** +*******************************************************************************/ +BOOLEAN bta_jv_check_psm(UINT16 psm) +{ + BOOLEAN ret = FALSE; + + if(L2C_IS_VALID_PSM(psm) ) + { + if(psm < 0x1001) + { + /* see if this is defined by spec */ + switch(psm) + { + case SDP_PSM: /* 1 */ + case BT_PSM_RFCOMM: /* 3 */ + /* do not allow java app to use these 2 PSMs */ + break; + + case TCS_PSM_INTERCOM: /* 5 */ + case TCS_PSM_CORDLESS: /* 7 */ + if( FALSE == bta_sys_is_register(BTA_ID_CT) && + FALSE == bta_sys_is_register(BTA_ID_CG) ) + ret = TRUE; + break; + + case BT_PSM_BNEP: /* F */ + if(FALSE == bta_sys_is_register(BTA_ID_PAN)) + ret = TRUE; + break; + + case HID_PSM_CONTROL: /* 0x11 */ + case HID_PSM_INTERRUPT: /* 0x13 */ + //FIX: allow HID Device and HID Host to coexist + if( FALSE == bta_sys_is_register(BTA_ID_HD) || + FALSE == bta_sys_is_register(BTA_ID_HH) ) + ret = TRUE; + break; + + case AVCT_PSM: /* 0x17 */ + case AVDT_PSM: /* 0x19 */ + if ((FALSE == bta_sys_is_register(BTA_ID_AV)) && + (FALSE == bta_sys_is_register(BTA_ID_AVK))) + ret = TRUE; + break; + + default: + ret = TRUE; + break; + } + } + else + ret = TRUE; + } + return ret; + +} + +/******************************************************************************* +** +** Function bta_jv_enable +** +** Description Initialises the JAVA I/F +** +** Returns void +** +*******************************************************************************/ +void bta_jv_enable(tBTA_JV_MSG *p_data) +{ + tBTA_JV_STATUS status = BTA_JV_SUCCESS; + bta_jv_cb.p_dm_cback = p_data->enable.p_cback; + bta_jv_cb.p_dm_cback(BTA_JV_ENABLE_EVT, (tBTA_JV *)&status, 0); +} + +/******************************************************************************* +** +** Function bta_jv_disable +** +** Description Disables the BT device manager +** free the resources used by java +** +** Returns void +** +*******************************************************************************/ +void bta_jv_disable (tBTA_JV_MSG *p_data) +{ + int i; + + bta_jv_cb.p_dm_cback = NULL; + /* delete the SDP records created by java apps */ + for(i=0; i<BTA_JV_MAX_SDP_REC; i++) + { + if(bta_jv_cb.sdp_handle[i]) + { + APPL_TRACE_DEBUG1( "delete SDP record: %d", bta_jv_cb.sdp_handle[i]); + SDP_DeleteRecord(bta_jv_cb.sdp_handle[i]); + bta_jv_cb.sdp_handle[i] = 0; + } + } + + /* free the SCNs allocated by java apps */ + for(i=0; i<BTA_JV_MAX_SCN; i++) + { + if(bta_jv_cb.scn[i]) + { + APPL_TRACE_DEBUG1( "free scn: %d", (i+1)); + BTM_FreeSCN((UINT8)(i+1)); + bta_jv_cb.scn[i] = FALSE; + } + } + + /* disconnect L2CAP connections */ + for(i=0; i<BTA_JV_MAX_L2C_CONN; i++) + { + bta_jv_free_l2c_cb(&bta_jv_cb.l2c_cb[i]); + } + + /* disconnect RFCOMM connections */ + for(i=0; i<BTA_JV_MAX_RFC_CONN; i++) + { + bta_jv_free_rfc_cb(&bta_jv_cb.rfc_cb[i]); + } + + /* free the service records allocated by java apps */ + for(i=0; i<BTA_JV_NUM_SERVICE_ID; i++) + { + if(bta_jv_cb.sec_id[i]) + { + BTM_SecClrService(bta_jv_cb.sec_id[i]); + bta_jv_cb.sec_id[i] = 0; + } + } +} + +/******************************************************************************* +** +** Function bta_jv_set_discoverability +** +** Description Sets discoverability +** +** Returns void +** +*******************************************************************************/ +void bta_jv_set_discoverability (tBTA_JV_MSG *p_data) +{ + tBTA_JV evt_data; + + evt_data.set_discover.status = BTA_JV_FAILURE; + /* initialize the default value for the event as the current mode */ + evt_data.set_discover.disc_mode = BTM_ReadDiscoverability(NULL, NULL); + + if(BTM_SUCCESS == BTM_SetDiscoverability((UINT8)p_data->set_discoverability.disc_mode, 0, 0)) + { + evt_data.set_discover.status = BTA_JV_SUCCESS; + /* update the mode, after BTM_SetDiscoverability() is successful */ + evt_data.set_discover.disc_mode = p_data->set_discoverability.disc_mode; + } + + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_SET_DISCOVER_EVT, &evt_data, 0); +} + +/******************************************************************************* +** +** Function bta_jv_get_local_device_addr +** +** Description Reads the local Bluetooth device address +** +** Returns void +** +*******************************************************************************/ +void bta_jv_get_local_device_addr(tBTA_JV_MSG *p_data) +{ + BTM_ReadLocalDeviceAddr((tBTM_CMPL_CB *)bta_jv_get_local_device_addr_cback); +} + +/******************************************************************************* +** +** Function bta_jv_get_local_device_name +** +** Description Reads the local Bluetooth device name +** +** Returns void +** +*******************************************************************************/ +void bta_jv_get_local_device_name(tBTA_JV_MSG *p_data) +{ + tBTA_JV evt_data; + char *name; + + BTM_ReadLocalDeviceName(&name); + evt_data.p_name = (UINT8*)name; + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_LOCAL_NAME_EVT, &evt_data, 0); +} + +/******************************************************************************* +** +** Function bta_jv_get_remote_device_name +** +** Description Reads the local Bluetooth device name +** +** Returns void +** +*******************************************************************************/ +void bta_jv_get_remote_device_name(tBTA_JV_MSG *p_data) +{ + + BTM_ReadRemoteDeviceName(p_data->get_rmt_name.bd_addr, + (tBTM_CMPL_CB *)bta_jv_get_remote_device_name_cback); +} + +/******************************************************************************* +** +** Function bta_jv_set_service_class +** +** Description update the service class field of device class +** +** Returns void +** +*******************************************************************************/ +void bta_jv_set_service_class (tBTA_JV_MSG *p_data) +{ + tBTA_UTL_COD cod; + + /* set class of device */ + /* BTA_JvSetServiceClass(UINT32 service) assumes that the service class passed to the API function as defined in the assigned number page. + For example: the object transfer bit is bit 20 of the 24-bit Class of device; the value of this bit is 0x00100000 (value 1) + Our btm_api.h defines this bit as #define BTM_COD_SERVICE_OBJ_TRANSFER 0x1000 // (value 2) + This reflects that the service class defined at btm is UINT16, which starts at bit 8 of the 24 bit Class of Device + The following statement converts from (value 1) into (value 2) */ + cod.service = (p_data->set_service.service >> 8); + utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS); +} + +/******************************************************************************* +** +** Function bta_jv_sec_cback +** +** Description callback function to handle set encryption complete event +** +** Returns void +** +*******************************************************************************/ +static void bta_jv_sec_cback (BD_ADDR bd_addr, void *p_ref_data, tBTM_STATUS result) +{ + tBTA_JV_SET_ENCRYPTION set_enc; + if(bta_jv_cb.p_dm_cback) + { + bdcpy(set_enc.bd_addr, bd_addr); + set_enc.status = result; + if (result > BTA_JV_BUSY) + set_enc.status = BTA_JV_FAILURE; + bta_jv_cb.p_dm_cback(BTA_JV_SET_ENCRYPTION_EVT, (tBTA_JV *)&set_enc, 0); + } +} + +/******************************************************************************* +** +** Function bta_jv_set_encryption +** +** Description Reads the local Bluetooth device name +** +** Returns void +** +*******************************************************************************/ +void bta_jv_set_encryption(tBTA_JV_MSG *p_data) +{ + BTM_SetEncryption(p_data->set_encrypt.bd_addr, bta_jv_sec_cback, NULL); +} + +/******************************************************************************* +** +** Function bta_jv_get_scn +** +** Description obtain a free SCN +** +** Returns void +** +*******************************************************************************/ +void bta_jv_get_scn(tBTA_JV_MSG *p_data) +{ +#if 0 + UINT8 scn; + scn = BTM_AllocateSCN(); + if(scn) + bta_jv_cb.scn[scn-1] = TRUE; + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_GET_SCN_EVT, (tBTA_JV *)&scn); +#endif +} + +/******************************************************************************* +** +** Function bta_jv_free_scn +** +** Description free a SCN +** +** Returns void +** +*******************************************************************************/ +void bta_jv_free_scn(tBTA_JV_MSG *p_data) +{ + UINT8 scn = p_data->free_scn.scn; + + if (scn > 0 && scn <= BTA_JV_MAX_SCN && bta_jv_cb.scn[scn-1]) + { + /* this scn is used by JV */ + bta_jv_cb.scn[scn-1] = FALSE; + BTM_FreeSCN(scn); + } +} +static inline tBT_UUID shorten_sdp_uuid(const tBT_UUID* u) +{ + static uint8_t bt_base_uuid[] = + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; + + logu("in, uuid:", u); + debug("uuid len:%d", u->len); + if(u->len == 16) + { + if(memcmp(&u->uu.uuid128[4], &bt_base_uuid[4], 12) == 0) + { + tBT_UUID su; + memset(&su, 0, sizeof(su)); + if(u->uu.uuid128[0] == 0 && u->uu.uuid128[1] == 0) + { + su.len = 2; + uint16_t u16; + memcpy(&u16, &u->uu.uuid128[2], sizeof(u16)); + su.uu.uuid16 = ntohs(u16); + debug("shorten to 16 bits uuid: %x", su.uu.uuid16); + } + else + { + su.len = 4; + uint32_t u32; + memcpy(&u32, &u->uu.uuid128[0], sizeof(u32)); + su.uu.uuid32 = ntohl(u32); + debug("shorten to 32 bits uuid: %x", su.uu.uuid32); + } + return su; + } + } + debug("cannot shorten none-reserved 128 bits uuid"); + return *u; +} + +/******************************************************************************* +** +** Function bta_jv_start_discovery_cback +** +** Description Callback for Start Discovery +** +** Returns void +** +*******************************************************************************/ +static void bta_jv_start_discovery_cback(UINT16 result, void * user_data) +{ + tBTA_JV_STATUS status; + UINT8 old_sdp_act = bta_jv_cb.sdp_active; + + debug( "bta_jv_start_discovery_cback res: 0x%x", result); + + bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE; + if(bta_jv_cb.p_dm_cback) + { + if (old_sdp_act == BTA_JV_SDP_ACT_CANCEL) + { + debug("BTA_JV_SDP_ACT_CANCEL"); + status = BTA_JV_SUCCESS; + bta_jv_cb.p_dm_cback(BTA_JV_CANCEL_DISCVRY_EVT, (tBTA_JV *)&status, user_data); + } + else + { + tBTA_JV_DISCOVERY_COMP dcomp; + dcomp.scn = 0; + status = BTA_JV_FAILURE; + if (result == SDP_SUCCESS || result == SDP_DB_FULL) + { + tSDP_DISC_REC *p_sdp_rec = NULL; + tSDP_PROTOCOL_ELEM pe; + logu("bta_jv_cb.uuid", bta_jv_cb.uuid.uu.uuid128); + tBT_UUID su = shorten_sdp_uuid(&bta_jv_cb.uuid); + logu("shorten uuid:", su.uu.uuid128); + p_sdp_rec = SDP_FindServiceUUIDInDb(p_bta_jv_cfg->p_sdp_db, &su, p_sdp_rec); + debug("p_sdp_rec:%p", p_sdp_rec); + if(p_sdp_rec && SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)) + { + dcomp.scn = (UINT8) pe.params[0]; + status = BTA_JV_SUCCESS; + } + } + + dcomp.status = status; + bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&dcomp, user_data); + } + //free sdp db + //utl_freebuf(&(p_bta_jv_cfg->p_sdp_db)); + } +} + +/******************************************************************************* +** +** Function bta_jv_start_discovery +** +** Description Discovers services on a remote device +** +** Returns void +** +*******************************************************************************/ +void bta_jv_start_discovery(tBTA_JV_MSG *p_data) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + debug("in, sdp_active:%d", bta_jv_cb.sdp_active); + if (bta_jv_cb.sdp_active != BTA_JV_SDP_ACT_NONE) + { + /* SDP is still in progress */ + status = BTA_JV_BUSY; + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&status, p_data->start_discovery.user_data); + return; + } +/* + if(p_data->start_discovery.num_uuid == 0) + { + p_data->start_discovery.num_uuid = 1; + p_data->start_discovery.uuid_list[0].len = 2; + p_data->start_discovery.uuid_list[0].uu.uuid16 = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + } +*/ + /* init the database/set up the filter */ + debug("call SDP_InitDiscoveryDb, p_data->start_discovery.num_uuid:%d", + p_data->start_discovery.num_uuid); + SDP_InitDiscoveryDb (p_bta_jv_cfg->p_sdp_db, p_bta_jv_cfg->sdp_db_size, + p_data->start_discovery.num_uuid, p_data->start_discovery.uuid_list, 0, NULL); + + /* tell SDP to keep the raw data */ + p_bta_jv_cfg->p_sdp_db->raw_data = p_bta_jv_cfg->p_sdp_raw_data; + p_bta_jv_cfg->p_sdp_db->raw_size = p_bta_jv_cfg->sdp_raw_size; + + bta_jv_cb.p_sel_raw_data = 0; + bta_jv_cb.uuid = p_data->start_discovery.uuid_list[0]; + + bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_YES; + if (!SDP_ServiceSearchAttributeRequest2(p_data->start_discovery.bd_addr, + p_bta_jv_cfg->p_sdp_db, + bta_jv_start_discovery_cback, p_data->start_discovery.user_data)) + { + bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE; + /* failed to start SDP. report the failure right away */ + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&status, p_data->start_discovery.user_data); + } + /* + else report the result when the cback is called + */ +} + +/******************************************************************************* +** +** Function bta_jv_cancel_discovery +** +** Description Cancels an active discovery +** +** Returns void +** +*******************************************************************************/ +void bta_jv_cancel_discovery(tBTA_JV_MSG *p_data) +{ + tBTA_JV_STATUS status = BTA_JV_SUCCESS; + if (bta_jv_cb.sdp_active == BTA_JV_SDP_ACT_YES) + { + if (SDP_CancelServiceSearch (p_bta_jv_cfg->p_sdp_db)) + { + bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_CANCEL; + return; + } + } + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_CANCEL_DISCVRY_EVT, (tBTA_JV *)&status, p_data->cancel_discovery.user_data); +} + +/******************************************************************************* +** +** Function bta_jv_get_services_length +** +** Description Obtain the length of each record in the SDP DB. +** +** Returns void +** +*******************************************************************************/ +void bta_jv_get_services_length(tBTA_JV_MSG *p_data) +{ +#if 0 + tBTA_JV_SERVICES_LEN evt_data; + UINT8 *p, *np, *op, type; + UINT32 raw_used, raw_cur; + UINT32 len; + + evt_data.num_services = -1; + evt_data.p_services_len = p_data->get_services_length.p_services_len; + if(p_bta_jv_cfg->p_sdp_db->p_first_rec) + { + /* the database is valid */ + evt_data.num_services = 0; + p = p_bta_jv_cfg->p_sdp_db->raw_data; + raw_used = p_bta_jv_cfg->p_sdp_db->raw_used; + while(raw_used && p) + { + op = p; + type = *p++; + np = sdpu_get_len_from_type(p, type, &len); + p = np + len; + raw_cur = p - op; + if(raw_used >= raw_cur) + { + raw_used -= raw_cur; + } + else + { + /* error. can not continue */ + break; + } + if(p_data->get_services_length.inc_hdr) + { + evt_data.p_services_len[evt_data.num_services++] = len + np - op; + } + else + { + evt_data.p_services_len[evt_data.num_services++] = len; + } + } /* end of while */ + } + + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_SERVICES_LEN_EVT, (tBTA_JV *)&evt_data); +#endif +} + +/******************************************************************************* +** +** Function bta_jv_service_select +** +** Description Obtain the length of given UUID in the SDP DB. +** +** Returns void +** +*******************************************************************************/ +void bta_jv_service_select(tBTA_JV_MSG *p_data) +{ +#if 0 + tBTA_JV_SERVICE_SEL serv_sel; + tSDP_DISC_REC *p_rec, *p_tmp; + UINT8 *p, *np, *op, type; + UINT32 raw_used, raw_cur; + UINT32 len; + + serv_sel.service_len = 0; + bta_jv_cb.p_sel_raw_data = 0; + p_rec = SDP_FindServiceInDb (p_bta_jv_cfg->p_sdp_db, p_data->service_select.uuid, NULL); + if(p_rec) + { + /* found the record in the database */ + /* the database must be valid */ + p = p_bta_jv_cfg->p_sdp_db->raw_data; + raw_used = p_bta_jv_cfg->p_sdp_db->raw_used; + p_tmp = p_bta_jv_cfg->p_sdp_db->p_first_rec; + while(raw_used && p && p_tmp) + { + op = p; + type = *p++; + np = sdpu_get_len_from_type(p, type, &len); + if(p_tmp == p_rec) + { + bta_jv_cb.p_sel_raw_data = op; + bta_jv_cb.sel_len = len; + serv_sel.service_len = len; + bdcpy(serv_sel.bd_addr, p_rec->remote_bd_addr); + APPL_TRACE_DEBUG1( "bta_jv_service_select found uuid: 0x%x", + p_data->service_select.uuid); + break; + } + p = np + len; + raw_cur = p - op; + if(raw_used >= raw_cur) + { + raw_used -= raw_cur; + } + else + { + /* error. can not continue */ + break; + } + p_tmp = p_tmp->p_next_rec; + } /* end of while */ + } + APPL_TRACE_DEBUG1( "service_len: %d", serv_sel.service_len); + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_SERVICE_SEL_EVT, (tBTA_JV *)&serv_sel); +#endif +} + +/******************************************************************************* +** +** Function bta_jv_create_record +** +** Description Create an SDP record with the given attributes +** +** Returns void +** +*******************************************************************************/ +void bta_jv_create_record(tBTA_JV_MSG *p_data) +{ + tBTA_JV_API_CREATE_RECORD *cr = &(p_data->create_record); + tBTA_JV_CREATE_RECORD evt_data; + evt_data.status = BTA_JV_SUCCESS; + if(bta_jv_cb.p_dm_cback) + //callback user immediately to create his own sdp record in stack thread context + bta_jv_cb.p_dm_cback(BTA_JV_CREATE_RECORD_EVT, (tBTA_JV *)&evt_data, cr->user_data); +} + +/******************************************************************************* +** +** Function bta_jv_update_record +** +** Description Update an SDP record with the given attributes +** +** Returns void +** +*******************************************************************************/ +void bta_jv_update_record(tBTA_JV_MSG *p_data) +{ +#if 0 + tBTA_JV_API_UPDATE_RECORD *ur = &(p_data->update_record); + tBTA_JV_UPDATE_RECORD evt_data; + UINT32 handle; + INT32 i; + UINT8 *ptr; + UINT8 *next_ptr; + UINT8 *end; + UINT32 len; + UINT8 type; + + evt_data.status = BTA_JV_FAILURE; + evt_data.handle = ur->handle; + + handle = bta_jv_get_sdp_handle(ur->handle); + + if(handle) + { + /* this is a record created by JV */ + for (i = 0; i < ur->array_len; i++) + { + ptr = ur->p_values[i]; + end = ptr + ur->p_value_sizes[i]; + + while (ptr < end) + { + type = *ptr; + next_ptr = sdpu_get_len_from_type(ptr + 1, *ptr, &len); + + if(ATTR_ID_SERVICE_RECORD_HDL != ur->p_ids[i]) + { + if (!SDP_AddAttribute(handle, ur->p_ids[i], (UINT8)((type >> 3) & 0x1f), + len, next_ptr)) + { + /* failed on updating attributes. */ + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_UPDATE_RECORD_EVT, (tBTA_JV *)&evt_data); + return; + } + } + + ptr = next_ptr + len; + } /* end of while */ + } /* end of for */ + evt_data.status = BTA_JV_SUCCESS; + } + + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_UPDATE_RECORD_EVT, (tBTA_JV *)&evt_data); +#endif +} + +/******************************************************************************* +** +** Function bta_jv_add_attribute +** +** Description Add an attribute to an SDP record +** +** Returns void +** +*******************************************************************************/ +void bta_jv_add_attribute(tBTA_JV_MSG *p_data) +{ +#if 0 + tBTA_JV_API_ADD_ATTRIBUTE *aa = &(p_data->add_attr); + tBTA_JV_ADD_ATTR evt_data; + UINT32 handle; + UINT8 type; + UINT32 len; + UINT8 *ptr; + UINT8 *next_ptr; + + evt_data.status = BTA_JV_FAILURE; + evt_data.handle = aa->handle; + handle = bta_jv_get_sdp_handle(aa->handle); + + if(handle) + { + /* this is a record created by JV */ + ptr = aa->p_value; + type = *ptr; + next_ptr = sdpu_get_len_from_type(ptr + 1, *ptr, &len); + APPL_TRACE_DEBUG3( "bta_jv_add_attribute: ptr chg:%d len:%d, size:%d", + (next_ptr - ptr), len, aa->value_size); + if(ATTR_ID_SERVICE_RECORD_HDL != aa->attr_id && /* do not allow the SDP record handle to be updated */ + ((INT32)(next_ptr - ptr + len) == aa->value_size) && /* double check data size */ + SDP_AddAttribute(handle, aa->attr_id, (UINT8)((type >> 3) & 0x1f), + len, next_ptr)) + { + evt_data.status = BTA_JV_SUCCESS; + } + } + + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_ADD_ATTR_EVT, (tBTA_JV *)&evt_data); +#endif +} + +/******************************************************************************* +** +** Function bta_jv_delete_attribute +** +** Description Delete an attribute from the given SDP record +** +** Returns void +** +*******************************************************************************/ +void bta_jv_delete_attribute(tBTA_JV_MSG *p_data) +{ +#if 0 + tBTA_JV_API_ADD_ATTRIBUTE *da = &(p_data->add_attr); + tBTA_JV_DELETE_ATTR evt_data; + UINT32 handle; + + evt_data.status = BTA_JV_FAILURE; + evt_data.handle = da->handle; + handle = bta_jv_get_sdp_handle(da->handle); + + if(handle) + { + /* this is a record created by JV */ + if(SDP_DeleteAttribute(handle, da->attr_id)) + evt_data.status = BTA_JV_SUCCESS; + } + + if(bta_jv_cb.p_dm_cback) + bta_jv_cb.p_dm_cback(BTA_JV_DELETE_ATTR_EVT, (tBTA_JV *)&evt_data); +#endif +} + +/******************************************************************************* +** +** Function bta_jv_delete_record +** +** Description Delete an SDP record +** +** +** Returns void +** +*******************************************************************************/ +void bta_jv_delete_record(tBTA_JV_MSG *p_data) +{ + tBTA_JV_API_ADD_ATTRIBUTE *dr = &(p_data->add_attr); + UINT32 handle; + + handle = bta_jv_get_sdp_handle(dr->handle); + + if(handle) + { + /* this is a record created by JV */ + SDP_DeleteRecord(handle); + bta_jv_free_sdp_id(dr->handle); + } +} + +/******************************************************************************* +** +** Function bta_jv_l2cap_client_cback +** +** Description handles the l2cap client events +** +** Returns void +** +*******************************************************************************/ +static void bta_jv_l2cap_client_cback(UINT16 gap_handle, UINT16 event) +{ +#if 0 + tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[gap_handle]; + tBTA_JV evt_data; + + if(gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback) + return; + + APPL_TRACE_DEBUG2( "bta_jv_l2cap_client_cback: %d evt:x%x", + gap_handle, event); + evt_data.l2c_open.status = BTA_JV_SUCCESS; + evt_data.l2c_open.handle = gap_handle; + switch (event) + { + case GAP_EVT_CONN_OPENED: + bdcpy(evt_data.l2c_open.rem_bda, GAP_ConnGetRemoteAddr(gap_handle)); + evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle); + p_cb->state = BTA_JV_ST_CL_OPEN; + p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data); + break; + + case GAP_EVT_CONN_CLOSED: + p_cb->state = BTA_JV_ST_NONE; + bta_jv_free_sec_id(&p_cb->sec_id); + evt_data.l2c_close.async = TRUE; + p_cb->p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data); + p_cb->p_cback = NULL; + break; + + case GAP_EVT_CONN_DATA_AVAIL: + evt_data.handle = gap_handle; + p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data); + break; + + case GAP_EVT_CONN_CONGESTED: + case GAP_EVT_CONN_UNCONGESTED: + p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE; + evt_data.l2c_cong.cong = p_cb->cong; + p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data); + break; + + default: + break; + } +#endif +} + +#if SDP_FOR_JV_INCLUDED == TRUE +/******************************************************************************* +** +** Function bta_jv_sdp_res_cback +** +** Description Callback for Start Discovery +** +** Returns void +** +*******************************************************************************/ +void bta_jv_sdp_res_cback (UINT16 event, tSDP_DATA *p_data) +{ + tBTA_JV evt_data; + tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[BTA_JV_L2C_FOR_SDP_HDL]; + + APPL_TRACE_DEBUG2( "bta_jv_sdp_res_cback: %d evt:x%x", + bta_jv_cb.sdp_for_jv, event); + + if(!bta_jv_cb.sdp_for_jv) + return; + + evt_data.l2c_open.status = BTA_JV_SUCCESS; + evt_data.l2c_open.handle = BTA_JV_L2C_FOR_SDP_HDL; + + switch(event) + { + case SDP_EVT_OPEN: + bdcpy(evt_data.l2c_open.rem_bda, p_data->open.peer_addr); + evt_data.l2c_open.tx_mtu = p_data->open.peer_mtu; + p_cb->state = BTA_JV_ST_SR_OPEN; + p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data); + break; + case SDP_EVT_DATA_IND: + evt_data.handle = BTA_JV_L2C_FOR_SDP_HDL; + memcpy(p_bta_jv_cfg->p_sdp_raw_data, p_data->data.p_data, p_data->data.data_len); + APPL_TRACE_DEBUG2( "data size: %d/%d ", bta_jv_cb.sdp_data_size, p_data->data.data_len); + bta_jv_cb.sdp_data_size = p_data->data.data_len; + p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data); + break; + } +} + +/******************************************************************************* +** +** Function bta_jv_sdp_cback +** +** Description Callback for Start Discovery +** +** Returns void +** +*******************************************************************************/ +static void bta_jv_sdp_cback(UINT16 result) +{ + tBTA_JV_L2CAP_CLOSE close; + tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[BTA_JV_L2C_FOR_SDP_HDL]; + APPL_TRACE_DEBUG1( "bta_jv_sdp_cback: result:x%x", result); + + if(p_cb->p_cback) + { + close.handle = BTA_JV_L2C_FOR_SDP_HDL; + close.async = FALSE; + close.status = BTA_JV_SUCCESS; + bta_jv_free_sec_id(&p_cb->sec_id); + p_cb->p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&close); + } + + bta_jv_cb.sdp_for_jv = 0; + p_cb->p_cback = NULL; + +} +#endif + +/******************************************************************************* +** +** Function bta_jv_l2cap_connect +** +** Description makes an l2cap client connection +** +** Returns void +** +*******************************************************************************/ +void bta_jv_l2cap_connect(tBTA_JV_MSG *p_data) +{ +#if 0 + tBTA_JV_L2C_CB *p_cb; + tBTA_JV_L2CAP_CL_INIT evt_data; + UINT16 handle=GAP_INVALID_HANDLE; + UINT8 sec_id; + tL2CAP_CFG_INFO cfg; + tBTA_JV_API_L2CAP_CONNECT *cc = &(p_data->l2cap_connect); + + memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); + cfg.mtu_present = TRUE; + cfg.mtu = cc->rx_mtu; + /* TODO: DM role manager + L2CA_SetDesireRole(cc->role); + */ + + sec_id = bta_jv_alloc_sec_id(); + evt_data.sec_id = sec_id; + evt_data.status = BTA_JV_FAILURE; + if (sec_id) + { +#if SDP_FOR_JV_INCLUDED == TRUE + if(SDP_PSM == cc->remote_psm && 0 == bta_jv_cb.sdp_for_jv) + { + bta_jv_cb.sdp_for_jv = SDP_ConnOpen(cc->peer_bd_addr, + bta_jv_sdp_res_cback, + bta_jv_sdp_cback); + if(bta_jv_cb.sdp_for_jv) + { + bta_jv_cb.sdp_data_size = 0; + handle = BTA_JV_L2C_FOR_SDP_HDL; + evt_data.status = BTA_JV_SUCCESS; + } + } + else +#endif + if(bta_jv_check_psm(cc->remote_psm)) /* allowed */ + { + if( (handle = GAP_ConnOpen("", sec_id, 0, cc->peer_bd_addr, cc->remote_psm, + &cfg, cc->sec_mask, GAP_FCR_CHAN_OPT_BASIC, + bta_jv_l2cap_client_cback)) != GAP_INVALID_HANDLE ) + { + evt_data.status = BTA_JV_SUCCESS; + } + } + } + + if (evt_data.status == BTA_JV_SUCCESS) + { + p_cb = &bta_jv_cb.l2c_cb[handle]; + p_cb->handle = handle; + p_cb->p_cback = cc->p_cback; + p_cb->psm = 0; /* not a server */ + p_cb->sec_id = sec_id; + p_cb->state = BTA_JV_ST_CL_OPENING; + } + else + { + bta_jv_free_sec_id(&sec_id); + } + evt_data.handle = handle; + cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, (tBTA_JV *)&evt_data); +#endif +} + +/******************************************************************************* +** +** Function bta_jv_l2cap_close +** +** Description Close an L2CAP client connection +** +** Returns void +** +*******************************************************************************/ +void bta_jv_l2cap_close(tBTA_JV_MSG *p_data) +{ +#if 0 + tBTA_JV_L2CAP_CLOSE evt_data; + tBTA_JV_API_L2CAP_CLOSE *cc = &(p_data->l2cap_close); + tBTA_JV_L2CAP_CBACK *p_cback = cc->p_cb->p_cback; + + evt_data.handle = cc->handle; + evt_data.status = bta_jv_free_l2c_cb(cc->p_cb); + evt_data.async = FALSE; + + if (p_cback) + p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data); + else + APPL_TRACE_ERROR0("### NO CALLBACK SET !!! ###"); +#endif +} + +/******************************************************************************* +** +** Function bta_jv_l2cap_server_cback +** +** Description handles the l2cap server callback +** +** Returns void +** +*******************************************************************************/ +static void bta_jv_l2cap_server_cback(UINT16 gap_handle, UINT16 event) +{ +#if 0 + tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[gap_handle]; + tBTA_JV evt_data; + tBTA_JV_L2CAP_CBACK *p_cback; + + if(gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback) + return; + + APPL_TRACE_DEBUG2( "bta_jv_l2cap_server_cback: %d evt:x%x", + gap_handle, event); + evt_data.l2c_open.status = BTA_JV_SUCCESS; + evt_data.l2c_open.handle = gap_handle; + + switch (event) + { + case GAP_EVT_CONN_OPENED: + bdcpy(evt_data.l2c_open.rem_bda, GAP_ConnGetRemoteAddr(gap_handle)); + evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle); + p_cb->state = BTA_JV_ST_SR_OPEN; + p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data); + break; + + case GAP_EVT_CONN_CLOSED: + evt_data.l2c_close.async = TRUE; + evt_data.l2c_close.handle = p_cb->handle; + p_cback = p_cb->p_cback; + evt_data.l2c_close.status = bta_jv_free_l2c_cb(p_cb); + p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data); + break; + + case GAP_EVT_CONN_DATA_AVAIL: + evt_data.handle = gap_handle; + p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data); + break; + + case GAP_EVT_CONN_CONGESTED: + case GAP_EVT_CONN_UNCONGESTED: + p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE; + evt_data.l2c_cong.cong = p_cb->cong; + p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data); + break; + + default: + break; + } +#endif +} + +/******************************************************************************* +** +** Function bta_jv_l2cap_start_server +** +** Description starts an L2CAP server +** +** Returns void +** +*******************************************************************************/ +void bta_jv_l2cap_start_server(tBTA_JV_MSG *p_data) +{ +#if 0 + tBTA_JV_L2C_CB *p_cb; + UINT8 sec_id; + UINT16 handle; + tL2CAP_CFG_INFO cfg; + tBTA_JV_L2CAP_START evt_data; + tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server); + + memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); + + //FIX: MTU=0 means not present + if (ls->rx_mtu >0) + { + cfg.mtu_present = TRUE; + cfg.mtu = ls->rx_mtu; + } + else + { + cfg.mtu_present = FALSE; + cfg.mtu = 0; + } + + /* TODO DM role manager + L2CA_SetDesireRole(ls->role); + */ + + sec_id = bta_jv_alloc_sec_id(); + if (0 == sec_id || (FALSE == bta_jv_check_psm(ls->local_psm)) || + (handle = GAP_ConnOpen("JV L2CAP", sec_id, 1, 0, ls->local_psm, &cfg, + ls->sec_mask, GAP_FCR_CHAN_OPT_BASIC, bta_jv_l2cap_server_cback)) == GAP_INVALID_HANDLE) + { + bta_jv_free_sec_id(&sec_id); + evt_data.status = BTA_JV_FAILURE; + } + else + { + /* default JV implementation requires explicit call + to allow incoming connections when ready*/ + + GAP_SetAcceptReady(handle, FALSE); + + p_cb = &bta_jv_cb.l2c_cb[handle]; + evt_data.status = BTA_JV_SUCCESS; + evt_data.handle = handle; + evt_data.sec_id = sec_id; + p_cb->p_cback = ls->p_cback; + p_cb->handle = handle; + p_cb->sec_id = sec_id; + p_cb->state = BTA_JV_ST_SR_LISTEN; + p_cb->psm = ls->local_psm; + } + ls->p_cback(BTA_JV_L2CAP_START_EVT, (tBTA_JV *)&evt_data); +#endif +} + +/******************************************************************************* +** +** Function bta_jv_l2cap_stop_server +** +** Description stops an L2CAP server +** +** Returns void +** +*******************************************************************************/ +void bta_jv_l2cap_stop_server(tBTA_JV_MSG *p_data) +{ +#if 0 + tBTA_JV_L2C_CB *p_cb; + tBTA_JV_L2CAP_CLOSE evt_data; + tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server); + tBTA_JV_L2CAP_CBACK *p_cback; + int i; + + for(i=0; i<BTA_JV_MAX_L2C_CONN; i++) + { + if(bta_jv_cb.l2c_cb[i].psm == ls->local_psm) + { + p_cb = &bta_jv_cb.l2c_cb[i]; + p_cback = p_cb->p_cback; + evt_data.handle = p_cb->handle; + evt_data.status = bta_jv_free_l2c_cb(p_cb); + evt_data.async = FALSE; + p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data); + break; + } + } +#endif +} + +/******************************************************************************* +** +** Function bta_jv_l2cap_read +** +** Description Read data from an L2CAP connection +** +** Returns void +** +*******************************************************************************/ +void bta_jv_l2cap_read(tBTA_JV_MSG *p_data) +{ +#if 0 + tBTA_JV_L2CAP_READ evt_data; + tBTA_JV_API_L2CAP_READ *rc = &(p_data->l2cap_read); + + evt_data.status = BTA_JV_FAILURE; + evt_data.handle = rc->handle; + evt_data.req_id = rc->req_id; + evt_data.p_data = rc->p_data; + evt_data.len = 0; +#if SDP_FOR_JV_INCLUDED == TRUE + if(BTA_JV_L2C_FOR_SDP_HDL == rc->handle) + { + evt_data.len = rc->len; + if(evt_data.len > bta_jv_cb.sdp_data_size) + evt_data.len = bta_jv_cb.sdp_data_size; + + memcpy(rc->p_data, p_bta_jv_cfg->p_sdp_raw_data, evt_data.len); + bta_jv_cb.sdp_data_size = 0; + evt_data.status = BTA_JV_SUCCESS; + } + else +#endif + if (BT_PASS == GAP_ConnReadData(rc->handle, rc->p_data, rc->len, &evt_data.len)) + { + evt_data.status = BTA_JV_SUCCESS; + } + + rc->p_cback(BTA_JV_L2CAP_READ_EVT, (tBTA_JV *)&evt_data); +#endif +} + + +/******************************************************************************* +** +** Function bta_jv_l2cap_write +** +** Description Write data to an L2CAP connection +** +** Returns void +** +*******************************************************************************/ +void bta_jv_l2cap_write(tBTA_JV_MSG *p_data) +{ +#if 0 + tBTA_JV_L2CAP_WRITE evt_data; + tBTA_JV_API_L2CAP_WRITE *ls = &(p_data->l2cap_write); + + evt_data.status = BTA_JV_FAILURE; + evt_data.handle = ls->handle; + evt_data.req_id = ls->req_id; + evt_data.cong = ls->p_cb->cong; + evt_data.len = 0; +#if SDP_FOR_JV_INCLUDED == TRUE + if(BTA_JV_L2C_FOR_SDP_HDL == ls->handle) + { + UINT8 *p; + BT_HDR *p_msg = (BT_HDR *) GKI_getbuf ((UINT16)(ls->len + BT_HDR_SIZE + L2CAP_MIN_OFFSET)); + if(p_msg) + { + p_msg->offset = L2CAP_MIN_OFFSET; + p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET; + p_msg->len = ls->len; + memcpy(p, ls->p_data, p_msg->len); + if(SDP_WriteData (bta_jv_cb.sdp_for_jv, p_msg)) + { + evt_data.len = ls->len; + evt_data.status = BTA_JV_SUCCESS; + } + } + } + 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; + } + + ls->p_cb->p_cback(BTA_JV_L2CAP_WRITE_EVT, (tBTA_JV *)&evt_data); +#endif +} + +/******************************************************************************* +** +** Function bta_jv_port_data_co_cback +** +** Description port data callback function of rfcomm +** connections +** +** Returns void +** +*******************************************************************************/ +/* +#define DATA_CO_CALLBACK_TYPE_INCOMING 1 +#define DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE 2 +#define DATA_CO_CALLBACK_TYPE_OUTGOING 3 +*/ +static int bta_jv_port_data_co_cback(UINT16 port_handle, UINT8 *buf, UINT16 len, int type) +{ + tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle); + tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle); + + if (p_cb != NULL) + { + switch(type) + { + case DATA_CO_CALLBACK_TYPE_INCOMING: + return bta_co_rfc_data_incoming(p_pcb->user_data, (BT_HDR*)buf); + case DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE: + return bta_co_rfc_data_outgoing_size(p_pcb->user_data, (int*)buf); + case DATA_CO_CALLBACK_TYPE_OUTGOING: + return bta_co_rfc_data_outgoing(p_pcb->user_data, buf, len); + default: + APPL_TRACE_ERROR1("unknown callout type:%d", type); + break; + } + } + return 0; +} + +/******************************************************************************* +** +** Function bta_jv_port_mgmt_cl_cback +** +** Description callback for port mamangement function of rfcomm +** client connections +** +** Returns void +** +*******************************************************************************/ +static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle) +{ + tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle); + tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle); + tBTA_JV evt_data; + BD_ADDR rem_bda; + UINT16 lcid; + tBTA_JV_RFCOMM_CBACK *p_cback; /* the callback function */ + + APPL_TRACE_DEBUG1( "bta_jv_port_mgmt_cl_cback:%d", port_handle); + if(NULL == p_cb || NULL == p_cb->p_cback) + return; + + APPL_TRACE_DEBUG3( "bta_jv_port_mgmt_cl_cback code=%d port_handle:%d handle:%d", + code, port_handle, p_cb->handle); + + PORT_CheckConnection(port_handle, rem_bda, &lcid); + + if(code == PORT_SUCCESS) + { + evt_data.rfc_open.handle = p_cb->handle; + evt_data.rfc_open.status = BTA_JV_SUCCESS; + bdcpy(evt_data.rfc_open.rem_bda, rem_bda); + p_pcb->state = BTA_JV_ST_CL_OPEN; + p_cb->p_cback(BTA_JV_RFCOMM_OPEN_EVT, &evt_data, p_pcb->user_data); + } + else + { + evt_data.rfc_close.handle = p_cb->handle; + evt_data.rfc_close.status = BTA_JV_FAILURE; + evt_data.rfc_close.port_status = code; + evt_data.rfc_close.async = TRUE; + if (p_pcb->state == BTA_JV_ST_CL_CLOSING) + { + evt_data.rfc_close.async = FALSE; + } + p_pcb->state = BTA_JV_ST_NONE; + p_pcb->cong = FALSE; + p_cback = p_cb->p_cback; + bta_jv_free_rfc_cb(p_cb); + + p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, p_pcb->user_data); + } + +} + +/******************************************************************************* +** +** Function bta_jv_port_event_cl_cback +** +** Description Callback for RFCOMM client port events +** +** Returns void +** +*******************************************************************************/ +static void bta_jv_port_event_cl_cback(UINT32 code, UINT16 port_handle) +{ + tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle); + tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle); + tBTA_JV evt_data; + + APPL_TRACE_DEBUG1( "bta_jv_port_event_cl_cback:%d", port_handle); + if(NULL == p_cb || NULL == p_cb->p_cback) + return; + + APPL_TRACE_DEBUG3( "bta_jv_port_event_cl_cback code=x%x port_handle:%d handle:%d", + code, port_handle, p_cb->handle); + if (code & PORT_EV_RXCHAR) + { + evt_data.data_ind.handle = p_cb->handle; + p_cb->p_cback(BTA_JV_RFCOMM_DATA_IND_EVT, &evt_data, p_pcb->user_data); + } + + if (code & PORT_EV_FC) + { + p_pcb->cong = (code & PORT_EV_FCS) ? FALSE : TRUE; + evt_data.rfc_cong.cong = p_pcb->cong; + evt_data.rfc_cong.handle = p_cb->handle; + evt_data.rfc_cong.status = BTA_JV_SUCCESS; + p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, p_pcb->user_data); + } +} + +/******************************************************************************* +** +** Function bta_jv_rfcomm_connect +** +** Description Client initiates an RFCOMM connection +** +** Returns void +** +*******************************************************************************/ +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); + tPORT_STATE port_state; + UINT8 sec_id; + tBTA_JV_RFC_CB *p_cb = NULL; + tBTA_JV_PCB *p_pcb; + tBTA_JV_API_RFCOMM_CONNECT *cc = &(p_data->rfcomm_connect); + tBTA_JV_RFCOMM_CL_INIT evt_data; + + /* TODO DM role manager + L2CA_SetDesireRole(cc->role); + */ + + sec_id = bta_jv_alloc_sec_id(); + evt_data.sec_id = sec_id; + evt_data.status = BTA_JV_SUCCESS; + if (0 == sec_id || + BTM_SetSecurityLevel(TRUE, "", sec_id, cc->sec_mask, BT_PSM_RFCOMM, + BTM_SEC_PROTO_RFCOMM, cc->remote_scn) == FALSE) + { + evt_data.status = BTA_JV_FAILURE; + error("sec_id:%d is zero or BTM_SetSecurityLevel failed, remote_scn:%d", sec_id, cc->remote_scn); + } + + if (evt_data.status == BTA_JV_SUCCESS && + RFCOMM_CreateConnection(UUID_SERVCLASS_SERIAL_PORT, cc->remote_scn, FALSE, + BTA_JV_DEF_RFC_MTU, cc->peer_bd_addr, &handle, bta_jv_port_mgmt_cl_cback) != PORT_SUCCESS) + { + evt_data.status = BTA_JV_FAILURE; + } + if (evt_data.status == BTA_JV_SUCCESS) + { + p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb); + p_cb->p_cback = cc->p_cback; + p_cb->sec_id = sec_id; + p_cb->scn = 0; + p_pcb->state = BTA_JV_ST_CL_OPENING; + p_pcb->user_data = cc->user_data; + evt_data.use_co = TRUE; + + PORT_SetEventCallback(handle, bta_jv_port_event_cl_cback); + PORT_SetEventMask(handle, event_mask); + PORT_SetDataCOCallback (handle, bta_jv_port_data_co_cback); + + PORT_GetState(handle, &port_state); + + port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT); + +/* coverity[uninit_use_in_call] +FALSE-POSITIVE: port_state is initialized at PORT_GetState() */ + PORT_SetState(handle, &port_state); + + evt_data.handle = p_cb->handle; + } + cc->p_cback(BTA_JV_RFCOMM_CL_INIT_EVT, (tBTA_JV *)&evt_data, cc->user_data); + } + +/******************************************************************************* +** +** Function bta_jv_rfcomm_close +** +** Description Close an RFCOMM connection +** +** Returns void +** +*******************************************************************************/ +void bta_jv_rfcomm_close(tBTA_JV_MSG *p_data) +{ + tBTA_JV_RFCOMM_CLOSE evt_data; + tBTA_JV_API_RFCOMM_CLOSE *cc = &(p_data->rfcomm_close); + tBTA_JV_RFC_CB *p_cb = cc->p_cb; + tBTA_JV_PCB *p_pcb = cc->p_pcb; + tBTA_JV_RFCOMM_CBACK *p_cback = p_cb->p_cback; + + evt_data.handle = p_cb->handle; + evt_data.status = BTA_JV_FAILURE; + + void* user_data = p_pcb->user_data; + p_pcb->cong = FALSE; + if(p_pcb->state <= BTA_JV_ST_CL_MAX) + { + if(p_pcb->state == BTA_JV_ST_CL_OPEN) + { + if(PORT_SUCCESS == RFCOMM_RemoveConnection(p_pcb->port_handle)) + { + p_pcb->state = BTA_JV_ST_CL_CLOSING; + return; + } + } + evt_data.status = bta_jv_free_rfc_cb(p_cb); + } + else if(BTA_JV_ST_SR_OPEN == p_pcb->state) + { + /* server is connected */ + if(PORT_SUCCESS == RFCOMM_RemoveConnection(p_pcb->port_handle)) + { + p_pcb->state = BTA_JV_ST_SR_CLOSING; + return; + } + } + + evt_data.async = FALSE; + + if (p_cback) + p_cback(BTA_JV_RFCOMM_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data); + else + error("### NO CALLBACK SET !!! ###"); +} + +/******************************************************************************* +** +** Function bta_jv_get_num_rfc_listen +** +** Description when a RFCOMM connection goes down, make sure that there's only +** one port stays listening on this scn. +** +** Returns +** +*******************************************************************************/ +static UINT8 bta_jv_get_num_rfc_listen(tBTA_JV_RFC_CB *p_cb) +{ + UINT8 i, listen=1; + tBTA_JV_PCB *p_pcb; + + if (p_cb->max_sess > 1) + { + listen = 0; + for (i=0; i<p_cb->max_sess; i++) + { + if (p_cb->rfc_hdl[i] != 0) + { + p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1]; + if (BTA_JV_ST_SR_LISTEN == p_pcb->state) + { + listen++; + } + } + } + } + return listen; +} + +/******************************************************************************* +** +** Function bta_jv_port_mgmt_sr_cback +** +** Description callback for port mamangement function of rfcomm +** server connections +** +** Returns void +** +*******************************************************************************/ +static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle) +{ + tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle); + tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle); + tBTA_JV evt_data; + BD_ADDR rem_bda; + UINT16 lcid; + UINT8 num; + tBTA_JV_RFCOMM_CBACK *p_cback; + UINT32 si; + + if(NULL == p_cb || NULL == p_cb->p_cback) + return; + void *user_data = p_pcb->user_data; + APPL_TRACE_DEBUG4( "bta_jv_port_mgmt_sr_cback code=%d port_handle:%d handle:%d/0x%x", + code, port_handle, p_cb->handle, p_pcb->handle); + + PORT_CheckConnection(port_handle, rem_bda, &lcid); + int failed = TRUE; + 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_open.rem_bda, rem_bda); + p_pcb->state = BTA_JV_ST_SR_OPEN; + tBTA_JV_PCB *p_pcb_new_listen = bta_jv_add_rfc_port(p_cb); + 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); + failed = FALSE; + } + else error("bta_jv_add_rfc_port failed to create new listen port"); + } + if(failed) + { + evt_data.rfc_close.handle = p_cb->handle; + evt_data.rfc_close.status = BTA_JV_SUCCESS; + evt_data.rfc_close.async = TRUE; + if(BTA_JV_ST_SR_CLOSING == p_pcb->state) + { + evt_data.rfc_close.async = FALSE; + } + p_pcb->state = BTA_JV_ST_SR_LISTEN; + p_pcb->cong = FALSE; + p_cback = p_cb->p_cback; + num = bta_jv_get_num_rfc_listen(p_cb); + APPL_TRACE_DEBUG1( "num:%d",num); + if (num > 1) + { + APPL_TRACE_DEBUG1( "removing rfc handle:0x%x", p_pcb->handle); + si = BTA_JV_RFC_HDL_TO_SIDX(p_pcb->handle); + p_cb->rfc_hdl[si] = 0; + p_pcb->state = BTA_JV_ST_NONE; + p_pcb->handle = 0; + RFCOMM_RemoveServer(port_handle); + } + evt_data.rfc_close.port_status = code; + p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, user_data); + } +} + +/******************************************************************************* +** +** Function bta_jv_port_event_sr_cback +** +** Description Callback for RFCOMM server port events +** +** Returns void +** +*******************************************************************************/ +static void bta_jv_port_event_sr_cback(UINT32 code, UINT16 port_handle) +{ + tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle); + tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle); + tBTA_JV evt_data; + + if(NULL == p_cb || NULL == p_cb->p_cback) + return; + + APPL_TRACE_DEBUG3( "bta_jv_port_event_sr_cback code=x%x port_handle:%d handle:%d", + code, port_handle, p_cb->handle); + + void *user_data = p_pcb->user_data; + if (code & PORT_EV_RXCHAR) + { + evt_data.data_ind.handle = p_cb->handle; + p_cb->p_cback(BTA_JV_RFCOMM_DATA_IND_EVT, &evt_data, user_data); + } + + if (code & PORT_EV_FC) + { + p_pcb->cong = (code & PORT_EV_FCS) ? FALSE : TRUE; + evt_data.rfc_cong.cong = p_pcb->cong; + evt_data.rfc_cong.handle = p_cb->handle; + evt_data.rfc_cong.status = BTA_JV_SUCCESS; + p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, user_data); + } +} + +/******************************************************************************* +** +** Function bta_jv_add_rfc_port +** +** Description add a port for server when the existing posts is open +** +** Returns return a pointer to tBTA_JV_PCB just added +** +*******************************************************************************/ +static tBTA_JV_PCB * bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb) +{ + UINT8 used = 0, i, listen=0; + UINT32 si = 0; + tBTA_JV_PCB *p_pcb = NULL; + tPORT_STATE port_state; + UINT32 event_mask = (PORT_EV_RXCHAR | PORT_EV_FC | PORT_EV_FCS); + + if (p_cb->max_sess > 1) + { + for (i=0; i<p_cb->max_sess; i++) + { + if (p_cb->rfc_hdl[i] != 0) + { + p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1]; + if (p_pcb->state == BTA_JV_ST_SR_LISTEN) + listen++; + used++; + } + else if (si==0) + { + si = (UINT32)(i + 1); + } + } + + debug("bta_jv_add_rfc_port max_sess=%d used:%d listen:%d si:%d", + p_cb->max_sess, used, listen, si); + if (used <p_cb->max_sess && listen==0 && si) + { + si--; + if (RFCOMM_CreateConnection(p_cb->sec_id, p_cb->scn, TRUE, + BTA_JV_DEF_RFC_MTU, (UINT8 *) bd_addr_any, &(p_cb->rfc_hdl[si]), bta_jv_port_mgmt_sr_cback) == PORT_SUCCESS) + { + p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[si] - 1]; + p_pcb->state = BTA_JV_ST_SR_LISTEN; + p_pcb->port_handle = p_cb->rfc_hdl[si]; + PORT_SetEventCallback(p_pcb->port_handle, bta_jv_port_event_sr_cback); + PORT_SetDataCOCallback (p_pcb->port_handle, bta_jv_port_data_co_cback); + PORT_SetEventMask(p_pcb->port_handle, event_mask); + PORT_GetState(p_pcb->port_handle, &port_state); + + port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT); + +/* coverity[uninit_use_in_call] +FALSE-POSITIVE: port_state is initialized at PORT_GetState() */ + PORT_SetState(p_pcb->port_handle, &port_state); + p_pcb->handle = BTA_JV_RFC_H_S_TO_HDL(p_cb->handle, si); + APPL_TRACE_DEBUG1( "new rfc handle:0x%x", p_pcb->handle); + } + } + } + return p_pcb; +} + +/******************************************************************************* +** +** Function bta_jv_rfcomm_start_server +** +** Description waits for an RFCOMM client to connect +** +** +** Returns void +** +*******************************************************************************/ +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); + tPORT_STATE port_state; + UINT8 sec_id; + tBTA_JV_RFC_CB *p_cb = NULL; + tBTA_JV_PCB *p_pcb; + tBTA_JV_API_RFCOMM_SERVER *rs = &(p_data->rfcomm_server); + tBTA_JV_RFCOMM_START evt_data; + + /* TODO DM role manager + L2CA_SetDesireRole(rs->role); + */ + evt_data.status = BTA_JV_FAILURE; + do + { + sec_id = bta_jv_alloc_sec_id(); + + if (0 == sec_id || + BTM_SetSecurityLevel(FALSE, "JV PORT", sec_id, rs->sec_mask, + BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, rs->local_scn) == FALSE) + { + break; + } + + if (RFCOMM_CreateConnection(sec_id, rs->local_scn, TRUE, + BTA_JV_DEF_RFC_MTU, (UINT8 *) bd_addr_any, &handle, bta_jv_port_mgmt_sr_cback) != PORT_SUCCESS) + { + break; + } + + p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb); + p_cb->max_sess = rs->max_session; + p_cb->p_cback = rs->p_cback; + p_cb->sec_id = sec_id; + p_cb->scn = rs->local_scn; + p_pcb->state = BTA_JV_ST_SR_LISTEN; + p_pcb->user_data = rs->user_data; + evt_data.status = BTA_JV_SUCCESS; + evt_data.handle = p_cb->handle; + evt_data.sec_id = sec_id; + evt_data.use_co = TRUE; //FALSE; + + PORT_SetEventCallback(handle, bta_jv_port_event_sr_cback); + PORT_SetEventMask(handle, event_mask); + PORT_GetState(handle, &port_state); + + port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT); + +/* coverity[uninit_use_in_call] +FALSE-POSITIVE: port_state is initialized at PORT_GetState() */ + PORT_SetState(handle, &port_state); + } while (0); + + rs->p_cback(BTA_JV_RFCOMM_START_EVT, (tBTA_JV *)&evt_data, rs->user_data); + if(evt_data.status == BTA_JV_SUCCESS) + { + PORT_SetDataCOCallback (handle, bta_jv_port_data_co_cback); + } +} + +/******************************************************************************* +** +** Function bta_jv_rfcomm_stop_server +** +** Description stops an RFCOMM server +** +** Returns void +** +*******************************************************************************/ + +void bta_jv_rfcomm_stop_server(tBTA_JV_MSG *p_data) +{ + tBTA_JV_RFCOMM_CLOSE evt_data; + int i; + tBTA_JV_API_RFCOMM_SERVER *ls = &(p_data->rfcomm_server); + HDL2CB(ls->rfc_handle); + evt_data.status = BTA_JV_FAILURE; + if(p_cb && p_pcb) + { + evt_data.handle = p_cb->handle; + void* user_data = p_pcb->user_data; + evt_data.status = bta_jv_free_rfc_listen_cb(p_cb); + evt_data.async = FALSE; + + /* occasionally when shutting down stack the callback is already + freed, hence make sure we check for this condition (pending investigatation + of rootcause) */ + debug("send BTA_JV_RFCOMM_CLOSE_EVT"); + if( p_cb->p_cback) + p_cb->p_cback(BTA_JV_RFCOMM_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data); + } + else + { + debug("warning, no jv callback set"); + } +} + +/******************************************************************************* +** +** Function bta_jv_rfcomm_read +** +** Description Read data from an RFCOMM connection +** +** Returns void +** +*******************************************************************************/ +void bta_jv_rfcomm_read(tBTA_JV_MSG *p_data) +{ + tBTA_JV_API_RFCOMM_READ *rc = &(p_data->rfcomm_read); + tBTA_JV_RFC_CB *p_cb = rc->p_cb; + tBTA_JV_PCB *p_pcb = rc->p_pcb; + tBTA_JV_RFCOMM_READ evt_data; + + evt_data.status = BTA_JV_FAILURE; + evt_data.handle = p_cb->handle; + evt_data.req_id = rc->req_id; + evt_data.p_data = rc->p_data; + if (PORT_ReadData(rc->p_pcb->port_handle, (char *)rc->p_data, rc->len, &evt_data.len) == + PORT_SUCCESS) + { + evt_data.status = BTA_JV_SUCCESS; + } + + p_cb->p_cback(BTA_JV_RFCOMM_READ_EVT, (tBTA_JV *)&evt_data, p_pcb->user_data); +} + +/******************************************************************************* +** +** Function bta_jv_rfcomm_write +** +** Description write data to an RFCOMM connection +** +** Returns void +** +*******************************************************************************/ +void bta_jv_rfcomm_write(tBTA_JV_MSG *p_data) +{ + tBTA_JV_API_RFCOMM_WRITE *wc = &(p_data->rfcomm_write); + tBTA_JV_RFC_CB *p_cb = wc->p_cb; + tBTA_JV_PCB *p_pcb = wc->p_pcb; + tBTA_JV_RFCOMM_WRITE evt_data; + + evt_data.status = BTA_JV_FAILURE; + evt_data.handle = p_cb->handle; + evt_data.req_id = wc->req_id; + evt_data.cong = p_pcb->cong; + evt_data.len = 0; + if (!evt_data.cong && + PORT_WriteDataCO(p_pcb->port_handle, &evt_data.len) == + PORT_SUCCESS) + { + evt_data.status = BTA_JV_SUCCESS; + } + //update congestion flag + evt_data.cong = p_pcb->cong; + if (p_cb->p_cback) + { + p_cb->p_cback(BTA_JV_RFCOMM_WRITE_EVT, (tBTA_JV *)&evt_data, p_pcb->user_data); + } + else + { + APPL_TRACE_ERROR0("bta_jv_rfcomm_write :: WARNING ! No JV callback set"); + } +} + diff --git a/bta/jv/bta_jv_api.c b/bta/jv/bta_jv_api.c new file mode 100755 index 0000000..fd1c3d3 --- /dev/null +++ b/bta/jv/bta_jv_api.c @@ -0,0 +1,1572 @@ +/***************************************************************************** +** +** Name: bta_jv_api.c +** +** Description: This is the implementation of the JAVA API for +** Bluetooth Wireless Technology (JABWT) +** as specified by the JSR82 specificiation +** +** Copyright (c) 2006-2009, Broadcom Corp., All Rights Reserved. +** WIDCOMM Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include "bta_api.h" +#include "bd.h" +#include "bta_sys.h" +#include "bta_jv_api.h" +#include "bta_jv_int.h" +#include "gki.h" +#include <string.h> +#include "port_api.h" +#include "sdp_api.h" + +/***************************************************************************** +** Constants +*****************************************************************************/ + +static const tBTA_SYS_REG bta_jv_reg = +{ + bta_jv_sm_execute, + NULL +}; + +/******************************************************************************* +** +** Function BTA_JvEnable +** +** Description Enable the Java I/F service. When the enable +** operation is complete the callback function will be +** called with a BTA_JV_ENABLE_EVT. This function must +** be called before other function in the JV API are +** called. +** +** Returns BTA_JV_SUCCESS if successful. +** BTA_JV_FAIL if internal failure. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvEnable(tBTA_JV_DM_CBACK *p_cback) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_ENABLE *p_buf; + + 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)); + + /* register with BTA system manager */ + GKI_sched_lock(); + bta_sys_register(BTA_ID_JV, &bta_jv_reg); + GKI_sched_unlock(); + + if (p_cback && (p_buf = (tBTA_JV_API_ENABLE *) GKI_getbuf(sizeof(tBTA_JV_API_ENABLE))) != NULL) + { + p_buf->hdr.event = BTA_JV_API_ENABLE_EVT; + p_buf->p_cback = p_cback; + bta_sys_sendmsg(p_buf); + status = BTA_JV_SUCCESS; + } + } + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvDisable +** +** Description Disable the Java I/F +** +** Returns void +** +*******************************************************************************/ +void BTA_JvDisable(void) +{ + BT_HDR *p_buf; + + APPL_TRACE_API0( "BTA_JvDisable"); + bta_sys_deregister(BTA_ID_JV); + if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_buf->event = BTA_JV_API_DISABLE_EVT; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_JvIsEnable +** +** Description Get the JV registration status. +** +** Returns TRUE, if registered +** +*******************************************************************************/ +BOOLEAN BTA_JvIsEnable(void) +{ + return bta_sys_is_register(BTA_ID_JV); +} + +/******************************************************************************* +** +** Function BTA_JvSetDiscoverability +** +** Description This function sets the Bluetooth discoverable modes +** of the local device. This controls whether other +** Bluetooth devices can find the local device. +** +** When the operation is complete the tBTA_JV_DM_CBACK callback +** function will be called with a BTA_JV_SET_DISCOVER_EVT. +** +** Returns BTA_JV_SUCCESS if successful. +** BTA_JV_FAIL if internal failure. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvSetDiscoverability(tBTA_JV_DISC disc_mode) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_SET_DISCOVERABILITY *p_msg; + + APPL_TRACE_API0( "BTA_JvSetDiscoverability"); + if ((p_msg = (tBTA_JV_API_SET_DISCOVERABILITY *)GKI_getbuf(sizeof(tBTA_JV_MSG))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_SET_DISCOVERABILITY_EVT; + p_msg->disc_mode = disc_mode; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvGetDiscoverability +** +** Description This function gets the Bluetooth +** discoverable modes of local device +** +** Returns The current Bluetooth discoverable mode. +** +*******************************************************************************/ +tBTA_JV_DISC BTA_JvGetDiscoverability(void) +{ + APPL_TRACE_API0( "BTA_JvGetDiscoverability"); + return BTM_ReadDiscoverability(0, 0); +} + +/******************************************************************************* +** +** Function BTA_JvGetLocalDeviceAddr +** +** Description This function obtains the local Bluetooth device address. +** The local Bluetooth device address is reported by the +** tBTA_JV_DM_CBACK callback with a BTA_JV_LOCAL_ADDR_EVT. +** +** Returns BTA_JV_SUCCESS if successful. +** BTA_JV_FAIL if internal failure. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvGetLocalDeviceAddr(void) +{ + tBTA_JV_STATUS ret = BTA_JV_FAILURE; + BT_HDR *p_msg; + + APPL_TRACE_API0( "BTA_JvGetLocalDeviceAddr"); + if ((p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_msg->event = BTA_JV_API_GET_LOCAL_DEVICE_ADDR_EVT; + bta_sys_sendmsg(p_msg); + ret = BTA_JV_SUCCESS; + } + + return(ret); +} + +/******************************************************************************* +** +** Function BTA_JvGetLocalDeviceName +** +** Description This function obtains the name of the local device +** The local Bluetooth device name is reported by the +** tBTA_JV_DM_CBACK callback with a BTA_JV_LOCAL_NAME_EVT. +** +** Returns BTA_JV_SUCCESS if successful. +** BTA_JV_FAIL if internal failure. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvGetLocalDeviceName(void) +{ + tBTA_JV_STATUS ret = BTA_JV_FAILURE; + BT_HDR *p_msg; + + APPL_TRACE_API0( "BTA_JvGetLocalDeviceName"); + if ((p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_msg->event = BTA_JV_API_GET_LOCAL_DEVICE_NAME_EVT; + bta_sys_sendmsg(p_msg); + ret = BTA_JV_SUCCESS; + } + + return(ret); +} + +/******************************************************************************* +** +** Function BTA_JvGetRemoteDeviceName +** +** Description This function obtains the name of the specified device. +** The Bluetooth device name is reported by the +** tBTA_JV_DM_CBACK callback with a BTA_JV_REMOTE_NAME_EVT. +** +** Returns BTA_JV_SUCCESS if successful. +** BTA_JV_FAIL if internal failure. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvGetRemoteDeviceName(BD_ADDR bd_addr) +{ + tBTA_JV_STATUS ret = BTA_JV_FAILURE; + tBTA_JV_API_GET_REMOTE_NAME *p_msg; + + APPL_TRACE_API0( "BTA_JvGetRemoteDeviceName"); + if ((p_msg = (tBTA_JV_API_GET_REMOTE_NAME *)GKI_getbuf(sizeof(tBTA_JV_API_GET_REMOTE_NAME))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_GET_REMOTE_DEVICE_NAME_EVT; + bdcpy(p_msg->bd_addr, bd_addr); + bta_sys_sendmsg(p_msg); + ret = BTA_JV_SUCCESS; + } + + return(ret); +} + +/******************************************************************************* +** +** Function BTA_JvGetPreknownDevice +** +** Description This function obtains the Bluetooth address in the inquiry +** database collected via the previous call to BTA_DmSearch(). +** +** Returns The number of preknown devices if p_bd_addr is NULL +** BTA_JV_SUCCESS if successful. +** BTA_JV_INTERNAL_ERR(-1) if internal failure. +** +*******************************************************************************/ +INT32 BTA_JvGetPreknownDevice(UINT8 * p_bd_addr, UINT32 index) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTM_INQ_INFO *p_info; + UINT32 count = 0; + INT32 ret = BTA_JV_INTERNAL_ERR; + + APPL_TRACE_API0( "BTA_JvGetPreknownDevice"); + p_info = BTM_InqFirstResult(); + if(p_info) + { + status = BTA_JV_SUCCESS; + /* the database is valid */ + if(NULL == p_bd_addr) + { + /* p_bd_addr is NULL: count the number of preknown devices */ + /* set the index to an invalid size (too big) */ + index = BTM_INQ_DB_SIZE; + } + else if(index >= BTM_INQ_DB_SIZE) + { + /* invalid index - error */ + status = (tBTA_JV_STATUS)BTA_JV_INTERNAL_ERR; + } + + if(BTA_JV_SUCCESS == status) + { + while(p_info && index > count) + { + count++; + p_info = BTM_InqNextResult(p_info); + } + + if(p_bd_addr) + { + if(index == count && p_info) + { + count = BTA_JV_SUCCESS; + bdcpy(p_bd_addr, p_info->results.remote_bd_addr); + } + else + status = (tBTA_JV_STATUS)BTA_JV_INTERNAL_ERR; + } + /* + else report the count + */ + } + /* + else error had happened. + */ + } + + if(BTA_JV_SUCCESS == status) + { + ret = count; + } + return ret; +} + + +/******************************************************************************* +** +** Function BTA_JvGetDeviceClass +** +** Description This function obtains the local Class of Device. This +** function executes in place. The result is returned right away. +** +** Returns DEV_CLASS, A three-byte array of UINT8 that contains the +** Class of Device information. The definitions are in the +** "Bluetooth Assigned Numbers". +** +*******************************************************************************/ +UINT8 * BTA_JvGetDeviceClass(void) +{ + APPL_TRACE_API0( "BTA_JvGetDeviceClass"); + return BTM_ReadDeviceClass(); +} + +/******************************************************************************* +** +** Function BTA_JvSetServiceClass +** +** Description This function sets the service class of local Class of Device +** +** Returns BTA_JV_SUCCESS if successful. +** BTA_JV_FAIL if internal failure. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvSetServiceClass(UINT32 service) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_SET_SERVICE_CLASS *p_msg; + + APPL_TRACE_API0( "BTA_JvSetServiceClass"); + if ((p_msg = (tBTA_JV_API_SET_SERVICE_CLASS *)GKI_getbuf(sizeof(tBTA_JV_API_SET_SERVICE_CLASS))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_SET_SERVICE_CLASS_EVT; + p_msg->service = service; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvSetEncryption +** +** Description This function ensures that the connection to the given device +** is encrypted. +** When the operation is complete the tBTA_JV_DM_CBACK callback +** function will be called with a BTA_JV_SET_ENCRYPTION_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvSetEncryption(BD_ADDR bd_addr) +{ + tBTA_JV_STATUS ret = BTA_JV_FAILURE; + tBTA_JV_API_SET_ENCRYPTION *p_msg; + + APPL_TRACE_API0( "BTA_JvSetEncryption"); + if ((p_msg = (tBTA_JV_API_SET_ENCRYPTION *)GKI_getbuf(sizeof(tBTA_JV_API_SET_ENCRYPTION))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_SET_ENCRYPTION_EVT; + bdcpy(p_msg->bd_addr, bd_addr); + bta_sys_sendmsg(p_msg); + ret = BTA_JV_SUCCESS; + } + + return(ret); +} + +/******************************************************************************* +** +** Function BTA_JvIsAuthenticated +** +** Description This function checks if the peer device is authenticated +** +** Returns TRUE if authenticated. +** FALSE if not. +** +*******************************************************************************/ +BOOLEAN BTA_JvIsAuthenticated(BD_ADDR bd_addr) +{ + BOOLEAN is_authenticated = FALSE; + UINT8 sec_flags; + + if(BTM_GetSecurityFlags(bd_addr, &sec_flags)) + { + if(sec_flags&BTM_SEC_FLAG_AUTHENTICATED) + is_authenticated = TRUE; + } + return is_authenticated; +} + +/******************************************************************************* +** +** Function BTA_JvIsTrusted +** +** Description This function checks if the peer device is trusted +** (previously paired) +** +** Returns TRUE if trusted. +** FALSE if not. +** +*******************************************************************************/ +BOOLEAN BTA_JvIsTrusted(BD_ADDR bd_addr) +{ + BOOLEAN is_trusted = FALSE; + UINT8 sec_flags; + + if(BTM_GetSecurityFlags(bd_addr, &sec_flags)) + { + if ((sec_flags&BTM_SEC_FLAG_AUTHENTICATED) || + (sec_flags&BTM_SEC_FLAG_LKEY_KNOWN)) + { + is_trusted = TRUE; + } + } + return is_trusted; +} + +/******************************************************************************* +** +** Function BTA_JvIsAuthorized +** +** Description This function checks if the peer device is authorized +** +** Returns TRUE if authorized. +** FALSE if not. +** +*******************************************************************************/ +BOOLEAN BTA_JvIsAuthorized(BD_ADDR bd_addr) +{ + BOOLEAN is_authorized = FALSE; + UINT8 sec_flags; + + if(BTM_GetSecurityFlags(bd_addr, &sec_flags)) + { + if(sec_flags&BTM_SEC_FLAG_AUTHORIZED) + is_authorized = TRUE; + } + return is_authorized; +} + +/******************************************************************************* +** +** Function BTA_JvIsEncrypted +** +** Description This function checks if the link to peer device is encrypted +** +** Returns TRUE if encrypted. +** FALSE if not. +** +*******************************************************************************/ +BOOLEAN BTA_JvIsEncrypted(BD_ADDR bd_addr) +{ + BOOLEAN is_encrypted = FALSE; + UINT8 sec_flags; + + if(BTM_GetSecurityFlags(bd_addr, &sec_flags)) + { + if(sec_flags&BTM_SEC_FLAG_ENCRYPTED) + is_encrypted = TRUE; + } + return is_encrypted; +} + +/******************************************************************************* +** +** Function BTA_JvGetSecurityMode +** +** Description This function returns the current Bluetooth security mode +** of the local device +** +** Returns The current Bluetooth security mode. +** +*******************************************************************************/ +tBTA_JV_SEC_MODE BTA_JvGetSecurityMode(void) +{ + return BTM_GetSecurityMode(); +} + +/******************************************************************************* +** +** Function BTA_JvGetSCN +** +** Description This function reserves a SCN (server channel number) for +** applications running over RFCOMM. It is primarily called by +** server profiles/applications to register their SCN into the +** SDP database. The SCN is reported by the tBTA_JV_DM_CBACK +** callback with a BTA_JV_GET_SCN_EVT. +** If the SCN reported is 0, that means all SCN resources are +** exhausted. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvGetSCN(void) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + BT_HDR *p_msg; + + APPL_TRACE_API0( "BTA_JvGetSCN"); + if ((p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_msg->event = BTA_JV_API_GET_SCN_EVT; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvFreeSCN +** +** Description This function frees a server channel number that was used +** by an application running over RFCOMM. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvFreeSCN(UINT8 scn) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_FREE_SCN *p_msg; + + APPL_TRACE_API0( "BTA_JvFreeSCN"); + if ((p_msg = (tBTA_JV_API_FREE_SCN *)GKI_getbuf(sizeof(tBTA_JV_API_FREE_SCN))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_FREE_SCN_EVT; + p_msg->scn = scn; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvGetPSM +** +** Description This function reserves a PSM (Protocol Service Multiplexer) +** applications running over L2CAP. It is primarily called by +** server profiles/applications to register their PSM into the +** SDP database. +** +** Returns The next free PSM +** +*******************************************************************************/ +UINT16 BTA_JvGetPSM(void) +{ +#if 0 + APPL_TRACE_API0( "BTA_JvGetPSM"); + + return (L2CA_AllocatePSM()); +#endif + return 0; +} + + +/******************************************************************************* +** +** Function BTA_JvStartDiscovery +** +** Description This function performs service discovery for the services +** provided by the given peer device. When the operation is +** complete the tBTA_JV_DM_CBACK callback function will be +** called with a BTA_JV_DISCOVERY_COMP_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvStartDiscovery(BD_ADDR bd_addr, UINT16 num_uuid, + tSDP_UUID *p_uuid_list, void * user_data) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_START_DISCOVERY *p_msg; + + APPL_TRACE_API0( "BTA_JvStartDiscovery"); + if ((p_msg = (tBTA_JV_API_START_DISCOVERY *)GKI_getbuf(sizeof(tBTA_JV_API_START_DISCOVERY))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_START_DISCOVERY_EVT; + bdcpy(p_msg->bd_addr, bd_addr); + p_msg->num_uuid = num_uuid; + memcpy(p_msg->uuid_list, p_uuid_list, num_uuid * sizeof(tSDP_UUID)); + p_msg->num_attr = 0; + p_msg->user_data = user_data; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvCancelDiscovery +** +** Description This function cancels an active service discovery. +** When the operation is +** complete the tBTA_JV_DM_CBACK callback function will be +** called with a BTA_JV_CANCEL_DISCVRY_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvCancelDiscovery(void * user_data) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_CANCEL_DISCOVERY *p_msg; + + APPL_TRACE_API0( "BTA_JvCancelDiscovery"); + if ((p_msg = (tBTA_JV_API_CANCEL_DISCOVERY *)GKI_getbuf(sizeof(tBTA_JV_API_CANCEL_DISCOVERY))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_CANCEL_DISCOVERY_EVT; + p_msg->user_data = user_data; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvGetServicesLength +** +** Description This function obtains the number of services and the length +** of each service found in the SDP database (result of last +** BTA_JvStartDiscovery().When the operation is complete the +** tBTA_JV_DM_CBACK callback function will be called with a +** BTA_JV_SERVICES_LEN_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvGetServicesLength(BOOLEAN inc_hdr, UINT16 *p_services_len) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_GET_SERVICES_LENGTH *p_msg; + + APPL_TRACE_API0( "BTA_JvGetServicesLength"); + if ((p_msg = (tBTA_JV_API_GET_SERVICES_LENGTH *)GKI_getbuf(sizeof(tBTA_JV_API_GET_SERVICES_LENGTH))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_GET_SERVICES_LENGTH_EVT; + p_msg->p_services_len = p_services_len; + p_msg->inc_hdr = inc_hdr; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} +/******************************************************************************* +** +** Function BTA_JvGetServicesResult +** +** Description This function returns a number of service records found +** during current service search, equals to the number returned +** by previous call to BTA_JvGetServicesLength. +** The contents of each SDP record will be returned under a +** TLV (type, len, value) representation in the data buffer +** provided by the caller. +** +** Returns -1, if error. Otherwise, the number of services +** +*******************************************************************************/ +INT32 BTA_JvGetServicesResult(BOOLEAN inc_hdr, UINT8 **TLVs) +{ +#if 0 + INT32 num_services = -1; + UINT8 *p, *np, *op, type; + UINT32 raw_used, raw_cur; + UINT32 len; + UINT32 hdr_len; + + APPL_TRACE_API0( "BTA_JvGetServicesResult"); + if(p_bta_jv_cfg->p_sdp_db->p_first_rec) + { + /* the database is valid */ + num_services = 0; + p = p_bta_jv_cfg->p_sdp_db->raw_data; + raw_used = p_bta_jv_cfg->p_sdp_db->raw_used; + while(raw_used && p) + { + op = p; + type = *p++; + np = sdpu_get_len_from_type(p, type, &len); + p = np + len; + raw_cur = p - op; + if(raw_used >= raw_cur) + { + raw_used -= raw_cur; + } + else + { + /* error. can not continue */ + break; + } + if(inc_hdr) + { + hdr_len = np - op; + memcpy(TLVs[num_services++], op, len+hdr_len); + } + else + { + memcpy(TLVs[num_services++], np, len); + } + } /* end of while */ + } + return(num_services); +#endif + return 0; +} +/******************************************************************************* +** +** Function BTA_JvServiceSelect +** +** Description This function checks if the SDP database contains the given +** service UUID. When the operation is complete the +** tBTA_JV_DM_CBACK callback function will be called with a +** BTA_JV_SERVICE_SEL_EVT with the length of the service record. +** If the service is not found or error, -1 is reported. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvServiceSelect(UINT16 uuid) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_SERVICE_SELECT *p_msg; + + APPL_TRACE_API0( "BTA_JvServiceSelect"); + if ((p_msg = (tBTA_JV_API_SERVICE_SELECT *)GKI_getbuf(sizeof(tBTA_JV_API_SERVICE_SELECT))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_SERVICE_SELECT_EVT; + p_msg->uuid = uuid; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvServiceResult +** +** Description This function returns the contents of the SDP record from +** last BTA_JvServiceSelect. The contents will be returned under +** a TLV (type, len, value) representation in the data buffer +** provided by the caller. +** +** Returns -1, if error. Otherwise, the length of service record. +** +*******************************************************************************/ +INT32 BTA_JvServiceResult(UINT8 *TLV) +{ + INT32 serv_sel = -1; + + APPL_TRACE_API0( "BTA_JvServiceResult"); + if(bta_jv_cb.p_sel_raw_data) + { + serv_sel = bta_jv_cb.sel_len; + memcpy(TLV, bta_jv_cb.p_sel_raw_data, serv_sel); + } + + return serv_sel; +} + + +/******************************************************************************* +** +** Function BTA_JvCreateRecord +** +** Description Create a service record in the local SDP database. +** When the operation is complete the tBTA_JV_DM_CBACK callback +** function will be called with a BTA_JV_CREATE_RECORD_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvCreateRecordByUser(void *user_data) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_CREATE_RECORD *p_msg; + + APPL_TRACE_API0( "BTA_JvCreateRecordByUser"); + if ((p_msg = (tBTA_JV_API_CREATE_RECORD *)GKI_getbuf(sizeof(tBTA_JV_API_CREATE_RECORD))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_CREATE_RECORD_EVT; + p_msg->user_data = user_data; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvUpdateRecord +** +** Description Update a service record in the local SDP database. +** When the operation is complete the tBTA_JV_DM_CBACK callback +** function will be called with a BTA_JV_UPDATE_RECORD_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvUpdateRecord(UINT32 handle, UINT16 *p_ids, + UINT8 **p_values, INT32 *p_value_sizes, INT32 array_len) +{ +#if 0 + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_UPDATE_RECORD *p_msg; + + APPL_TRACE_API0( "BTA_JvUpdateRecord"); + if ((p_msg = (tBTA_JV_API_UPDATE_RECORD *)GKI_getbuf(sizeof(tBTA_JV_API_UPDATE_RECORD))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_UPDATE_RECORD_EVT; + p_msg->handle = handle; + p_msg->p_ids = p_ids; + p_msg->p_values = p_values; + p_msg->p_value_sizes = p_value_sizes; + p_msg->array_len = array_len; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + return(status); +#endif + return -1; +} + +/******************************************************************************* +** +** Function BTA_JvAddAttribute +** +** Description Add an attribute to a service record in the local SDP database. +** When the operation is complete the tBTA_JV_DM_CBACK callback +** function will be called with a BTA_JV_ADD_ATTR_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvAddAttribute(UINT32 handle, UINT16 attr_id, + UINT8 *p_value, INT32 value_size) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_ADD_ATTRIBUTE *p_msg; + + APPL_TRACE_API0( "BTA_JvAddAttribute"); + if ((p_msg = (tBTA_JV_API_ADD_ATTRIBUTE *)GKI_getbuf(sizeof(tBTA_JV_API_ADD_ATTRIBUTE))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_ADD_ATTRIBUTE_EVT; + p_msg->handle = handle; + p_msg->attr_id = attr_id; + p_msg->p_value = p_value; + p_msg->value_size = value_size; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvDeleteAttribute +** +** Description Delete an attribute from a service record in the local SDP database. +** When the operation is complete the tBTA_JV_DM_CBACK callback +** function will be called with a BTA_JV_DELETE_ATTR_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvDeleteAttribute(UINT32 handle, UINT16 attr_id) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_ADD_ATTRIBUTE *p_msg; + + APPL_TRACE_API0( "BTA_JvDeleteAttribute"); + if ((p_msg = (tBTA_JV_API_ADD_ATTRIBUTE *)GKI_getbuf(sizeof(tBTA_JV_API_ADD_ATTRIBUTE))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_DELETE_ATTRIBUTE_EVT; + p_msg->handle = handle; + p_msg->attr_id = attr_id; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvDeleteRecord +** +** Description Delete a service record in the local SDP database. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvDeleteRecord(UINT32 handle) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_ADD_ATTRIBUTE *p_msg; + + APPL_TRACE_API0( "BTA_JvDeleteRecord"); + if ((p_msg = (tBTA_JV_API_ADD_ATTRIBUTE *)GKI_getbuf(sizeof(tBTA_JV_API_ADD_ATTRIBUTE))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_DELETE_RECORD_EVT; + p_msg->handle = handle; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvReadRecord +** +** Description Read a service record in the local SDP database. +** +** Returns -1, if the record is not found. +** Otherwise, the offset (0 or 1) to start of data in p_data. +** +** The size of data copied into p_data is in *p_data_len. +** +*******************************************************************************/ +INT32 BTA_JvReadRecord(UINT32 handle, UINT8 *p_data, INT32 *p_data_len) +{ + UINT32 sdp_handle; + + sdp_handle = bta_jv_get_sdp_handle(handle); + + if(sdp_handle) + { + return SDP_ReadRecord(sdp_handle, p_data, p_data_len); + } + + return -1; +} + +/******************************************************************************* +** +** Function BTA_JvL2capConnect +** +** Description Initiate a connection as a L2CAP client to the given BD +** Address. +** When the connection is initiated or failed to initiate, +** tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_CL_INIT_EVT +** When the connection is established or failed, +** tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvL2capConnect(tBTA_SEC sec_mask, + tBTA_JV_ROLE role, UINT16 remote_psm, UINT16 rx_mtu, + BD_ADDR peer_bd_addr, tBTA_JV_L2CAP_CBACK *p_cback) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_L2CAP_CONNECT *p_msg; + + APPL_TRACE_API0( "BTA_JvL2capConnect"); + if (p_cback && + (p_msg = (tBTA_JV_API_L2CAP_CONNECT *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_CONNECT))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_L2CAP_CONNECT_EVT; + p_msg->sec_mask = sec_mask; + p_msg->role = role; + p_msg->remote_psm = remote_psm; + p_msg->rx_mtu = rx_mtu; + memcpy(p_msg->peer_bd_addr, peer_bd_addr, sizeof(BD_ADDR)); + p_msg->p_cback = p_cback; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvL2capClose +** +** Description This function closes an L2CAP client connection +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvL2capClose(UINT32 handle) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_L2CAP_CLOSE *p_msg; + + APPL_TRACE_API0( "BTA_JvL2capClose"); + if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback && + (p_msg = (tBTA_JV_API_L2CAP_CLOSE *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_CLOSE))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_L2CAP_CLOSE_EVT; + p_msg->handle = handle; + p_msg->p_cb = &bta_jv_cb.l2c_cb[handle]; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvL2capStartServer +** +** Description This function starts an L2CAP server and listens for an L2CAP +** connection from a remote Bluetooth device. When the server +** is started successfully, tBTA_JV_L2CAP_CBACK is called with +** BTA_JV_L2CAP_START_EVT. When the connection is established, +** tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvL2capStartServer(tBTA_SEC sec_mask, tBTA_JV_ROLE role, + UINT16 local_psm, UINT16 rx_mtu, + tBTA_JV_L2CAP_CBACK *p_cback) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_L2CAP_SERVER *p_msg; + + APPL_TRACE_API0( "BTA_JvL2capStartServer"); + if (p_cback && + (p_msg = (tBTA_JV_API_L2CAP_SERVER *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_SERVER))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_L2CAP_START_SERVER_EVT; + p_msg->sec_mask = sec_mask; + p_msg->role = role; + p_msg->local_psm = local_psm; + p_msg->rx_mtu = rx_mtu; + p_msg->p_cback = p_cback; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvL2capStopServer +** +** Description This function stops the L2CAP server. If the server has an +** active connection, it would be closed. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvL2capStopServer(UINT16 local_psm) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_L2CAP_SERVER *p_msg; + + APPL_TRACE_API0( "BTA_JvL2capStopServer"); + if ((p_msg = (tBTA_JV_API_L2CAP_SERVER *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_SERVER))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_L2CAP_STOP_SERVER_EVT; + p_msg->local_psm = local_psm; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvL2capRead +** +** Description This function reads data from an L2CAP connecti; + tBTA_JV_RFC_CB *p_cb = rc->p_cb; +on +** When the operation is complete, tBTA_JV_L2CAP_CBACK is +** called with BTA_JV_L2CAP_READ_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvL2capRead(UINT32 handle, UINT32 req_id, UINT8 *p_data, UINT16 len) +{ +#if 0 + tBTA_JV_STATUS status = BTA_JV_FAILURE; +#if SDP_FOR_JV_INCLUDED == TRUE + tBTA_JV_API_L2CAP_READ *p_msg; +#endif + tBTA_JV_L2CAP_READ evt_data; + + APPL_TRACE_API0( "BTA_JvL2capRead"); + +#if SDP_FOR_JV_INCLUDED == TRUE + if(BTA_JV_L2C_FOR_SDP_HDL == handle) + { + if (bta_jv_cb.l2c_cb[handle].p_cback && + (p_msg = (tBTA_JV_API_L2CAP_READ *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_READ))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_L2CAP_READ_EVT; + p_msg->handle = handle; + p_msg->req_id = req_id; + p_msg->p_data = p_data; + p_msg->len = len; + p_msg->p_cback = bta_jv_cb.l2c_cb[handle].p_cback; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + } + else +#endif + if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback) + { + status = BTA_JV_SUCCESS; + evt_data.status = BTA_JV_FAILURE; + evt_data.handle = handle; + evt_data.req_id = req_id; + evt_data.p_data = p_data; + evt_data.len = 0; + + if (BT_PASS == GAP_ConnReadData((UINT16)handle, p_data, len, &evt_data.len)) + { + evt_data.status = BTA_JV_SUCCESS; + } + bta_jv_cb.l2c_cb[handle].p_cback(BTA_JV_L2CAP_READ_EVT, (tBTA_JV *)&evt_data); + } + + return(status); +#endif + return -1; +} + +/******************************************************************************* +** +** Function BTA_JvL2capReceive +** +** Description This function reads data from an L2CAP connection +** When the operation is complete, tBTA_JV_L2CAP_CBACK is +** called with BTA_JV_L2CAP_RECEIVE_EVT. +** If there are more data queued in L2CAP than len, the extra data will be discarded. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvL2capReceive(UINT32 handle, UINT32 req_id, UINT8 *p_data, UINT16 len) +{ +#if 0 + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_L2CAP_RECEIVE evt_data; + UINT32 left_over = 0; + UINT16 max_len, read_len; + + APPL_TRACE_API0( "BTA_JvL2capReceive"); + + if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback) + { + status = BTA_JV_SUCCESS; + evt_data.status = BTA_JV_FAILURE; + evt_data.handle = handle; + evt_data.req_id = req_id; + evt_data.p_data = p_data; + evt_data.len = 0; + + if (BT_PASS == GAP_ConnReadData((UINT16)handle, p_data, len, &evt_data.len)) + { + evt_data.status = BTA_JV_SUCCESS; + GAP_GetRxQueueCnt ((UINT16)handle, &left_over); + while (left_over) + { + max_len = (left_over > 0xFFFF)?0xFFFF:left_over; + GAP_ConnReadData ((UINT16)handle, NULL, max_len, &read_len); + left_over -= read_len; + } + } + bta_jv_cb.l2c_cb[handle].p_cback(BTA_JV_L2CAP_RECEIVE_EVT, (tBTA_JV *)&evt_data); + } + + return(status); +#endif + return -1; +} +/******************************************************************************* +** +** Function BTA_JvL2capReady +** +** Description This function determined if there is data to read from +** an L2CAP connection +** +** Returns BTA_JV_SUCCESS, if data queue size is in *p_data_size. +** BTA_JV_FAILURE, if error. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvL2capReady(UINT32 handle, UINT32 *p_data_size) +{ +#if 0 + tBTA_JV_STATUS status = BTA_JV_FAILURE; + + APPL_TRACE_API1( "BTA_JvL2capReady: %d", handle); + if (p_data_size && handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback) + { + *p_data_size = 0; +#if SDP_FOR_JV_INCLUDED == TRUE + if(BTA_JV_L2C_FOR_SDP_HDL == handle) + { + *p_data_size = bta_jv_cb.sdp_data_size; + status = BTA_JV_SUCCESS; + } + else +#endif + if(BT_PASS == GAP_GetRxQueueCnt((UINT16)handle, p_data_size) ) + { + status = BTA_JV_SUCCESS; + } + } + + return(status); +#endif + return -1; +} + + +/******************************************************************************* +** +** Function BTA_JvL2capWrite +** +** Description This function writes data to an L2CAP connection +** When the operation is complete, tBTA_JV_L2CAP_CBACK is +** called with BTA_JV_L2CAP_WRITE_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvL2capWrite(UINT32 handle, UINT32 req_id, UINT8 *p_data, UINT16 len) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_L2CAP_WRITE *p_msg; + + APPL_TRACE_API0( "BTA_JvL2capWrite"); + if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback && + (p_msg = (tBTA_JV_API_L2CAP_WRITE *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_WRITE))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_L2CAP_WRITE_EVT; + p_msg->handle = handle; + p_msg->req_id = req_id; + p_msg->p_data = p_data; + p_msg->p_cb = &bta_jv_cb.l2c_cb[handle]; + p_msg->len = len; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvRfcommConnect +** +** Description This function makes an RFCOMM conection to a remote BD +** Address. +** When the connection is initiated or failed to initiate, +** tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_CL_INIT_EVT +** When the connection is established or failed, +** tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_OPEN_EVT +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask, + tBTA_JV_ROLE role, UINT8 remote_scn, BD_ADDR peer_bd_addr, + tBTA_JV_RFCOMM_CBACK *p_cback, void* user_data) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_RFCOMM_CONNECT *p_msg; + + APPL_TRACE_API0( "BTA_JvRfcommConnect"); + if (p_cback && + (p_msg = (tBTA_JV_API_RFCOMM_CONNECT *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_CONNECT))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_RFCOMM_CONNECT_EVT; + p_msg->sec_mask = sec_mask; + p_msg->role = role; + p_msg->remote_scn = remote_scn; + memcpy(p_msg->peer_bd_addr, peer_bd_addr, sizeof(BD_ADDR)); + p_msg->p_cback = p_cback; + p_msg->user_data = user_data; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvRfcommClose +** +** Description This function closes an RFCOMM connection +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_RFCOMM_CLOSE *p_msg; + UINT32 hi = (handle & BTA_JV_RFC_HDL_MASK) - 1; + UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(handle); + + APPL_TRACE_API0( "BTA_JvRfcommClose"); + 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] && + (p_msg = (tBTA_JV_API_RFCOMM_CLOSE *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_CLOSE))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_RFCOMM_CLOSE_EVT; + p_msg->handle = handle; + p_msg->p_cb = &bta_jv_cb.rfc_cb[hi]; + p_msg->p_pcb = &bta_jv_cb.port_cb[p_msg->p_cb->rfc_hdl[si] - 1]; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvRfcommStartServer +** +** Description This function starts listening for an RFCOMM connection +** request from a remote Bluetooth device. When the server is +** started successfully, tBTA_JV_RFCOMM_CBACK is called +** with BTA_JV_RFCOMM_START_EVT. +** When the connection is established, tBTA_JV_RFCOMM_CBACK +** is called with BTA_JV_RFCOMM_OPEN_EVT. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC sec_mask, + tBTA_JV_ROLE role, UINT8 local_scn, UINT8 max_session, + tBTA_JV_RFCOMM_CBACK *p_cback, void* user_data) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_RFCOMM_SERVER *p_msg; + + APPL_TRACE_API0( "BTA_JvRfcommStartServer"); + if (p_cback && + (p_msg = (tBTA_JV_API_RFCOMM_SERVER *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_SERVER))) != NULL) + { + if (max_session == 0) + max_session = 1; + if (max_session > BTA_JV_MAX_RFC_SR_SESSION) + { + APPL_TRACE_DEBUG2( "max_session is too big. use max (%d)", max_session, BTA_JV_MAX_RFC_SR_SESSION); + max_session = BTA_JV_MAX_RFC_SR_SESSION; + } + p_msg->hdr.event = BTA_JV_API_RFCOMM_START_SERVER_EVT; + p_msg->sec_mask = sec_mask; + p_msg->role = role; + p_msg->local_scn = local_scn; + p_msg->max_session = max_session; + p_msg->p_cback = p_cback; + p_msg->user_data = user_data; //caller's private data + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvRfcommStopServer +** +** Description This function stops the RFCOMM server. If the server has an +** active connection, it would be closed. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvRfcommStopServer(UINT32 handle) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_RFCOMM_SERVER *p_msg; + APPL_TRACE_API0( "BTA_JvRfcommStopServer"); + if ((p_msg = (tBTA_JV_API_RFCOMM_SERVER *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_SERVER))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_RFCOMM_STOP_SERVER_EVT; + p_msg->rfc_handle = handle; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvRfcommRead +** +** Description This function reads data from an RFCOMM connection +** The actual size of data read is returned in p_len. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvRfcommRead(UINT32 handle, UINT32 req_id, UINT8 *p_data, UINT16 len) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_RFCOMM_READ *p_msg; + UINT32 hi = (handle & BTA_JV_RFC_HDL_MASK) - 1; + UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(handle); + + APPL_TRACE_API0( "BTA_JvRfcommRead"); + 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] && + (p_msg = (tBTA_JV_API_RFCOMM_READ *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_READ))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_RFCOMM_READ_EVT; + p_msg->handle = handle; + p_msg->req_id = req_id; + p_msg->p_data = p_data; + p_msg->len = len; + p_msg->p_cb = &bta_jv_cb.rfc_cb[hi]; + p_msg->p_pcb = &bta_jv_cb.port_cb[p_msg->p_cb->rfc_hdl[si] - 1]; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvRfcommGetPortHdl +** +** Description This function fetches the rfcomm port handle +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +UINT16 BTA_JvRfcommGetPortHdl(UINT32 handle) +{ + UINT32 hi = (handle & BTA_JV_RFC_HDL_MASK) - 1; + UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(handle); + + if (hi < BTA_JV_MAX_RFC_CONN && + si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si]) + return bta_jv_cb.port_cb[bta_jv_cb.rfc_cb[hi].rfc_hdl[si] - 1].port_handle; + else + return 0xffff; +} + + +/******************************************************************************* +** +** Function BTA_JvRfcommReady +** +** Description This function determined if there is data to read from +** an RFCOMM connection +** +** Returns BTA_JV_SUCCESS, if data queue size is in *p_data_size. +** BTA_JV_FAILURE, if error. +** +*******************************************************************************/ +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 si = BTA_JV_RFC_HDL_TO_SIDX(handle); + + APPL_TRACE_API0( "BTA_JvRfcommReady"); + 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]) + { + if(PORT_GetRxQueueCnt(bta_jv_cb.rfc_cb[hi].rfc_hdl[si], &size) == PORT_SUCCESS) + { + status = BTA_JV_SUCCESS; + } + } + *p_data_size = size; + return(status); +} + +/******************************************************************************* +** +** Function BTA_JvRfcommWrite +** +** Description This function writes data to an RFCOMM connection +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +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 si = BTA_JV_RFC_HDL_TO_SIDX(handle); + + APPL_TRACE_API0( "BTA_JvRfcommWrite"); + APPL_TRACE_DEBUG3( "handle:0x%x, hi:%d, si:%d", handle, hi, si); + 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] && + (p_msg = (tBTA_JV_API_RFCOMM_WRITE *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_WRITE))) != NULL) + { + p_msg->hdr.event = BTA_JV_API_RFCOMM_WRITE_EVT; + p_msg->handle = handle; + p_msg->req_id = req_id; + p_msg->p_cb = &bta_jv_cb.rfc_cb[hi]; + p_msg->p_pcb = &bta_jv_cb.port_cb[p_msg->p_cb->rfc_hdl[si] - 1]; + APPL_TRACE_API0( "write ok"); + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return(status); +} + diff --git a/bta/jv/bta_jv_cfg.c b/bta/jv/bta_jv_cfg.c new file mode 100755 index 0000000..b37d5de --- /dev/null +++ b/bta/jv/bta_jv_cfg.c @@ -0,0 +1,45 @@ +/***************************************************************************** +** +** Name: bta_jv_cfg.c +** +** Description: This file contains compile-time configurable constants +** for advanced audio +** +** Copyright (c) 2004, Widcomm Inc., All Rights Reserved. +** Widcomm Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include "gki.h" +#include "bta_api.h" +#include "bd.h" +#include "bta_jv_api.h" + +#ifndef BTA_JV_SDP_DB_SIZE +#define BTA_JV_SDP_DB_SIZE 4500 +#endif + +#ifndef BTA_JV_SDP_RAW_DATA_SIZE +#define BTA_JV_SDP_RAW_DATA_SIZE 1800 +#endif + +/* The platform may choose to use dynamic memory for these data buffers. + * p_bta_jv_cfg->p_sdp_db must be allocated/stay allocated + * between BTA_JvEnable and BTA_JvDisable + * p_bta_jv_cfg->p_sdp_raw_data can be allocated before calling BTA_JvStartDiscovery + * it can be de-allocated after the last call to access the database */ +static UINT8 bta_jv_sdp_raw_data[BTA_JV_SDP_RAW_DATA_SIZE]; +static UINT8 bta_jv_sdp_db_data[BTA_JV_SDP_DB_SIZE]; + +/* JV configuration structure */ +const tBTA_JV_CFG bta_jv_cfg = +{ + BTA_JV_SDP_RAW_DATA_SIZE, /* The size of p_sdp_raw_data */ + BTA_JV_SDP_DB_SIZE, /* The size of p_sdp_db_data */ + bta_jv_sdp_raw_data, /* The data buffer to keep raw data */ + (tSDP_DISCOVERY_DB *)bta_jv_sdp_db_data /* The data buffer to keep SDP database */ +}; + +tBTA_JV_CFG *p_bta_jv_cfg = (tBTA_JV_CFG *) &bta_jv_cfg; + + diff --git a/bta/jv/bta_jv_int.h b/bta/jv/bta_jv_int.h new file mode 100755 index 0000000..7a18ea2 --- /dev/null +++ b/bta/jv/bta_jv_int.h @@ -0,0 +1,448 @@ +/***************************************************************************** +** +** Name: bta_jv_int.h +** +** Description: This is the private interface file for the BTA Java I/F +** +** Copyright (c) 2006-2009, Broadcom Corp., All Rights Reserved. +** Widcomm Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ +#ifndef BTA_JV_INT_H +#define BTA_JV_INT_H + +#include "bta_sys.h" +#include "bta_api.h" +#include "bta_jv_api.h" +#include "rfcdefs.h" + +/***************************************************************************** +** Constants +*****************************************************************************/ + +enum +{ + /* these events are handled by the state machine */ + BTA_JV_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_JV), + BTA_JV_API_DISABLE_EVT, + BTA_JV_API_SET_DISCOVERABILITY_EVT, + BTA_JV_API_GET_LOCAL_DEVICE_ADDR_EVT, + BTA_JV_API_GET_LOCAL_DEVICE_NAME_EVT, + BTA_JV_API_GET_REMOTE_DEVICE_NAME_EVT, + BTA_JV_API_SET_SERVICE_CLASS_EVT, + BTA_JV_API_SET_ENCRYPTION_EVT, + BTA_JV_API_GET_SCN_EVT, + BTA_JV_API_FREE_SCN_EVT, + BTA_JV_API_START_DISCOVERY_EVT, + BTA_JV_API_CANCEL_DISCOVERY_EVT, + BTA_JV_API_GET_SERVICES_LENGTH_EVT, + BTA_JV_API_SERVICE_SELECT_EVT, + BTA_JV_API_CREATE_RECORD_EVT, + BTA_JV_API_UPDATE_RECORD_EVT, + BTA_JV_API_ADD_ATTRIBUTE_EVT, + BTA_JV_API_DELETE_ATTRIBUTE_EVT, + BTA_JV_API_DELETE_RECORD_EVT, + BTA_JV_API_L2CAP_CONNECT_EVT, + BTA_JV_API_L2CAP_CLOSE_EVT, + BTA_JV_API_L2CAP_START_SERVER_EVT, + BTA_JV_API_L2CAP_STOP_SERVER_EVT, + BTA_JV_API_L2CAP_READ_EVT, + BTA_JV_API_L2CAP_WRITE_EVT, + BTA_JV_API_RFCOMM_CONNECT_EVT, + BTA_JV_API_RFCOMM_CLOSE_EVT, + BTA_JV_API_RFCOMM_START_SERVER_EVT, + BTA_JV_API_RFCOMM_STOP_SERVER_EVT, + BTA_JV_API_RFCOMM_READ_EVT, + BTA_JV_API_RFCOMM_WRITE_EVT, + BTA_JV_MAX_INT_EVT +}; + +/* data type for BTA_JV_API_ENABLE_EVT */ +typedef struct +{ + BT_HDR hdr; + tBTA_JV_DM_CBACK *p_cback; +} tBTA_JV_API_ENABLE; + +/* data type for BTA_JV_API_SET_DISCOVERABILITY_EVT */ +typedef struct +{ + BT_HDR hdr; + tBTA_JV_DISC disc_mode; +} tBTA_JV_API_SET_DISCOVERABILITY; + + +/* data type for BTA_JV_API_SET_SERVICE_CLASS_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT32 service; +} tBTA_JV_API_SET_SERVICE_CLASS; + +/* data type for BTA_JV_API_SET_ENCRYPTION_EVT */ +typedef struct +{ + BT_HDR hdr; + BD_ADDR bd_addr; +} tBTA_JV_API_SET_ENCRYPTION; + +/* data type for BTA_JV_API_GET_REMOTE_DEVICE_NAME_EVT */ +typedef struct +{ + BT_HDR hdr; + BD_ADDR bd_addr; +} tBTA_JV_API_GET_REMOTE_NAME; + +/* data type for BTA_JV_API_START_DISCOVERY_EVT */ +typedef struct +{ + BT_HDR hdr; + BD_ADDR bd_addr; + UINT16 num_uuid; + tSDP_UUID uuid_list[BTA_JV_MAX_UUIDS]; + UINT16 num_attr; + UINT16 attr_list[BTA_JV_MAX_ATTRS]; + void *user_data; /* piggyback caller's private data*/ +} tBTA_JV_API_START_DISCOVERY; + +/* data type for BTA_JV_API_CANCEL_DISCOVERY_EVT */ +typedef struct +{ + BT_HDR hdr; + void *user_data; /* piggyback caller's private data*/ +} tBTA_JV_API_CANCEL_DISCOVERY; + + +/* data type for BTA_JV_API_GET_SERVICES_LENGTH_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT16 *p_services_len; + BOOLEAN inc_hdr; +} tBTA_JV_API_GET_SERVICES_LENGTH; + +/* data type for BTA_JV_API_GET_SERVICE_RESULT_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT8 **TLVs; +} tBTA_JV_API_GET_SERVICE_RESULT; + +/* data type for BTA_JV_API_SERVICE_SELECT_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT16 uuid; +} tBTA_JV_API_SERVICE_SELECT; + +enum +{ + BTA_JV_ST_NONE = 0, + BTA_JV_ST_CL_OPENING, + BTA_JV_ST_CL_OPEN, + BTA_JV_ST_CL_CLOSING, + BTA_JV_ST_SR_LISTEN, + BTA_JV_ST_SR_OPEN, + BTA_JV_ST_SR_CLOSING +} ; +typedef UINT8 tBTA_JV_STATE; +#define BTA_JV_ST_CL_MAX BTA_JV_ST_CL_CLOSING + +/* JV L2CAP control block */ +typedef struct +{ + tBTA_JV_L2CAP_CBACK *p_cback; /* the callback function */ + 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) */ + BOOLEAN cong; /* TRUE, if congested */ +} tBTA_JV_L2C_CB; + +#define BTA_JV_RFC_HDL_MASK 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)) + +/* port control block */ +typedef struct +{ + UINT32 handle; /* the rfcomm session handle at jv */ + UINT16 port_handle; /* port handle */ + tBTA_JV_STATE state; /* the state of this control block */ + UINT8 max_sess; /* max sessions */ + void *user_data; /* piggyback caller's private data*/ + BOOLEAN cong; /* TRUE, if congested */ +} tBTA_JV_PCB; + +/* JV RFCOMM control block */ +typedef struct +{ + tBTA_JV_RFCOMM_CBACK *p_cback; /* the callback function */ + UINT16 rfc_hdl[BTA_JV_MAX_RFC_SR_SESSION]; + tBTA_SERVICE_ID sec_id; /* service id */ + UINT8 handle; /* index: the handle reported to java app */ + UINT8 scn; /* the scn of the server */ + UINT8 max_sess; /* max sessions */ +} tBTA_JV_RFC_CB; + +/* data type for BTA_JV_API_L2CAP_CONNECT_EVT */ +typedef struct +{ + BT_HDR hdr; + tBTA_SEC sec_mask; + tBTA_JV_ROLE role; + UINT16 remote_psm; + UINT16 rx_mtu; + BD_ADDR peer_bd_addr; + tBTA_JV_L2CAP_CBACK *p_cback; +} tBTA_JV_API_L2CAP_CONNECT; + +/* data type for BTA_JV_API_L2CAP_SERVER_EVT */ +typedef struct +{ + BT_HDR hdr; + tBTA_SEC sec_mask; + tBTA_JV_ROLE role; + UINT16 local_psm; + UINT16 rx_mtu; + tBTA_JV_L2CAP_CBACK *p_cback; +} tBTA_JV_API_L2CAP_SERVER; + +/* data type for BTA_JV_API_L2CAP_CLOSE_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT16 handle; + tBTA_JV_L2C_CB *p_cb; +} tBTA_JV_API_L2CAP_CLOSE; + +/* data type for BTA_JV_API_L2CAP_READ_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT16 handle; + UINT32 req_id; + tBTA_JV_L2CAP_CBACK *p_cback; + UINT8* p_data; + UINT16 len; +} tBTA_JV_API_L2CAP_READ; + +/* data type for BTA_JV_API_L2CAP_WRITE_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT16 handle; + UINT32 req_id; + tBTA_JV_L2C_CB *p_cb; + UINT8 *p_data; + UINT16 len; +} tBTA_JV_API_L2CAP_WRITE; + +/* data type for BTA_JV_API_RFCOMM_CONNECT_EVT */ +typedef struct +{ + BT_HDR hdr; + tBTA_SEC sec_mask; + tBTA_JV_ROLE role; + UINT8 remote_scn; + BD_ADDR peer_bd_addr; + tBTA_JV_RFCOMM_CBACK *p_cback; + void *user_data; +} tBTA_JV_API_RFCOMM_CONNECT; + +/* data type for BTA_JV_API_RFCOMM_SERVER_EVT */ +typedef struct +{ + BT_HDR hdr; + tBTA_SEC sec_mask; + tBTA_JV_ROLE role; + UINT8 local_scn; + UINT8 max_session; + int rfc_handle; + tBTA_JV_RFCOMM_CBACK *p_cback; + void *user_data; +} tBTA_JV_API_RFCOMM_SERVER; + +/* data type for BTA_JV_API_RFCOMM_READ_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT16 handle; + UINT32 req_id; + UINT8 *p_data; + UINT16 len; + tBTA_JV_RFC_CB *p_cb; + tBTA_JV_PCB *p_pcb; +} tBTA_JV_API_RFCOMM_READ; + +/* data type for BTA_JV_API_RFCOMM_WRITE_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT16 handle; + UINT32 req_id; + UINT8 *p_data; + int len; + tBTA_JV_RFC_CB *p_cb; + tBTA_JV_PCB *p_pcb; +} tBTA_JV_API_RFCOMM_WRITE; + +/* data type for BTA_JV_API_RFCOMM_CLOSE_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT16 handle; + tBTA_JV_RFC_CB *p_cb; + tBTA_JV_PCB *p_pcb; +} tBTA_JV_API_RFCOMM_CLOSE; + +/* data type for BTA_JV_API_CREATE_RECORD_EVT */ +typedef struct +{ + BT_HDR hdr; + void *user_data; +} tBTA_JV_API_CREATE_RECORD; + +/* data type for BTA_JV_API_UPDATE_RECORD_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT32 handle; + UINT16 *p_ids; + UINT8 **p_values; + INT32 *p_value_sizes; + INT32 array_len; +} tBTA_JV_API_UPDATE_RECORD; + +/* data type for BTA_JV_API_ADD_ATTRIBUTE_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT32 handle; + UINT16 attr_id; + UINT8 *p_value; + INT32 value_size; +} tBTA_JV_API_ADD_ATTRIBUTE; + +/* data type for BTA_JV_API_FREE_SCN_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT8 scn; +} tBTA_JV_API_FREE_SCN; +/* union of all data types */ +typedef union +{ + /* GKI event buffer header */ + BT_HDR hdr; + tBTA_JV_API_ENABLE enable; + tBTA_JV_API_SET_DISCOVERABILITY set_discoverability; + tBTA_JV_API_GET_REMOTE_NAME get_rmt_name; + tBTA_JV_API_SET_SERVICE_CLASS set_service; + tBTA_JV_API_SET_ENCRYPTION set_encrypt; + tBTA_JV_API_START_DISCOVERY start_discovery; + tBTA_JV_API_CANCEL_DISCOVERY cancel_discovery; + tBTA_JV_API_GET_SERVICES_LENGTH get_services_length; + tBTA_JV_API_GET_SERVICE_RESULT get_service_result; + tBTA_JV_API_SERVICE_SELECT service_select; + tBTA_JV_API_FREE_SCN free_scn; + tBTA_JV_API_CREATE_RECORD create_record; + tBTA_JV_API_UPDATE_RECORD update_record; + tBTA_JV_API_ADD_ATTRIBUTE add_attr; + tBTA_JV_API_L2CAP_CONNECT l2cap_connect; + tBTA_JV_API_L2CAP_READ l2cap_read; + tBTA_JV_API_L2CAP_WRITE l2cap_write; + tBTA_JV_API_L2CAP_CLOSE l2cap_close; + tBTA_JV_API_L2CAP_SERVER l2cap_server; + tBTA_JV_API_RFCOMM_CONNECT rfcomm_connect; + tBTA_JV_API_RFCOMM_READ rfcomm_read; + tBTA_JV_API_RFCOMM_WRITE rfcomm_write; + tBTA_JV_API_RFCOMM_CLOSE rfcomm_close; + tBTA_JV_API_RFCOMM_SERVER rfcomm_server; +} tBTA_JV_MSG; + +#if SDP_FOR_JV_INCLUDED == TRUE +#define BTA_JV_L2C_FOR_SDP_HDL GAP_MAX_CONNECTIONS +#endif + +/* JV control block */ +typedef struct +{ +#if SDP_FOR_JV_INCLUDED == TRUE + UINT32 sdp_for_jv; /* The SDP client connection handle */ + UINT32 sdp_data_size; /* the data len */ +#endif + /* the SDP handle reported to JV user is the (index + 1) to sdp_handle[]. + * if sdp_handle[i]==0, it's not used. + * otherwise sdp_handle[i] is the stack SDP handle. */ + UINT32 sdp_handle[BTA_JV_MAX_SDP_REC]; /* SDP records created */ + UINT8 *p_sel_raw_data;/* the raw data of last service select */ + INT32 sel_len; /* the SDP record size of last service select */ + tBTA_JV_DM_CBACK *p_dm_cback; + tBTA_JV_L2C_CB l2c_cb[BTA_JV_MAX_L2C_CONN]; /* index is GAP handle (index) */ + tBTA_JV_RFC_CB rfc_cb[BTA_JV_MAX_RFC_CONN]; + tBTA_JV_PCB port_cb[MAX_RFC_PORTS]; /* index of this array is the port_handle, */ + UINT8 sec_id[BTA_JV_NUM_SERVICE_ID]; /* service ID */ + BOOLEAN scn[BTA_JV_MAX_SCN]; /* SCN allocated by java */ + UINT8 sdp_active; /* see BTA_JV_SDP_ACT_* */ + tSDP_UUID uuid; /* current uuid of sdp discovery*/ + void *user_data; /* piggyback user data*/ +} tBTA_JV_CB; + +enum +{ + BTA_JV_SDP_ACT_NONE = 0, + BTA_JV_SDP_ACT_YES, /* waiting for SDP result */ + BTA_JV_SDP_ACT_CANCEL /* waiting for cancel complete */ +}; + +/* JV control block */ +#if BTA_DYNAMIC_MEMORY == FALSE +extern tBTA_JV_CB bta_jv_cb; +#else +extern tBTA_JV_CB *bta_jv_cb_ptr; +#define bta_jv_cb (*bta_jv_cb_ptr) +#endif + +/* config struct */ +extern tBTA_JV_CFG *p_bta_jv_cfg; + +/* this is defined in stack/sdp. used by bta jv */ +extern UINT8 *sdpu_get_len_from_type (UINT8 *p, UINT8 type, UINT32 *p_len); + +extern BOOLEAN bta_jv_sm_execute(BT_HDR *p_msg); + +extern UINT32 bta_jv_get_sdp_handle(UINT32 sdp_id); +extern void bta_jv_enable (tBTA_JV_MSG *p_data); +extern void bta_jv_disable (tBTA_JV_MSG *p_data); +extern void bta_jv_set_discoverability (tBTA_JV_MSG *p_data); +extern void bta_jv_get_local_device_addr (tBTA_JV_MSG *p_data); +extern void bta_jv_get_local_device_name (tBTA_JV_MSG *p_data); +extern void bta_jv_get_remote_device_name (tBTA_JV_MSG *p_data); +extern void bta_jv_set_service_class (tBTA_JV_MSG *p_data); +extern void bta_jv_set_encryption (tBTA_JV_MSG *p_data); +extern void bta_jv_get_scn (tBTA_JV_MSG *p_data); +extern void bta_jv_free_scn (tBTA_JV_MSG *p_data); +extern void bta_jv_start_discovery (tBTA_JV_MSG *p_data); +extern void bta_jv_cancel_discovery (tBTA_JV_MSG *p_data); +extern void bta_jv_get_services_length (tBTA_JV_MSG *p_data); +extern void bta_jv_service_select (tBTA_JV_MSG *p_data); +extern void bta_jv_create_record (tBTA_JV_MSG *p_data); +extern void bta_jv_update_record (tBTA_JV_MSG *p_data); +extern void bta_jv_add_attribute (tBTA_JV_MSG *p_data); +extern void bta_jv_delete_attribute (tBTA_JV_MSG *p_data); +extern void bta_jv_delete_record (tBTA_JV_MSG *p_data); +extern void bta_jv_l2cap_connect (tBTA_JV_MSG *p_data); +extern void bta_jv_l2cap_close (tBTA_JV_MSG *p_data); +extern void bta_jv_l2cap_start_server (tBTA_JV_MSG *p_data); +extern void bta_jv_l2cap_stop_server (tBTA_JV_MSG *p_data); +extern void bta_jv_l2cap_read (tBTA_JV_MSG *p_data); +extern void bta_jv_l2cap_write (tBTA_JV_MSG *p_data); +extern void bta_jv_rfcomm_connect (tBTA_JV_MSG *p_data); +extern void bta_jv_rfcomm_close (tBTA_JV_MSG *p_data); +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); + +#endif /* BTA_JV_INT_H */ diff --git a/bta/jv/bta_jv_main.c b/bta/jv/bta_jv_main.c new file mode 100755 index 0000000..6c97b17 --- /dev/null +++ b/bta/jv/bta_jv_main.c @@ -0,0 +1,91 @@ +/***************************************************************************** +** +** Name: bta_jv_main.c +** +** Description: This is the main implementation file for the BTA +** Java I/F +** +** Copyright (c) 2006, +** Widcomm Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include "bta_api.h" +#include "bta_sys.h" +#include "bta_jv_api.h" +#include "bta_jv_int.h" + +/***************************************************************************** +** Constants and types +*****************************************************************************/ + +#if BTA_DYNAMIC_MEMORY == FALSE +tBTA_JV_CB bta_jv_cb; +#endif + +/* state machine action enumeration list */ +#define BTA_JV_NUM_ACTIONS (BTA_JV_MAX_INT_EVT & 0x00ff) + +/* type for action functions */ +typedef void (*tBTA_JV_ACTION)(tBTA_JV_MSG *p_data); + +/* action function list */ +const tBTA_JV_ACTION bta_jv_action[] = +{ + bta_jv_enable, /* BTA_JV_API_ENABLE_EVT */ + bta_jv_disable, /* BTA_JV_API_DISABLE_EVT */ + bta_jv_set_discoverability, /* BTA_JV_API_SET_DISCOVERABILITY_EVT */ + bta_jv_get_local_device_addr, /* BTA_JV_API_GET_LOCAL_DEVICE_ADDR_EVT */ + bta_jv_get_local_device_name, /* BTA_JV_API_GET_LOCAL_DEVICE_NAME_EVT */ + bta_jv_get_remote_device_name, /* BTA_JV_API_GET_REMOTE_DEVICE_NAME_EVT */ + bta_jv_set_service_class, /* BTA_JV_API_SET_SERVICE_CLASS_EVT */ + bta_jv_set_encryption, /* BTA_JV_API_SET_ENCRYPTION_EVT */ + bta_jv_get_scn, /* BTA_JV_API_GET_SCN_EVT */ + bta_jv_free_scn, /* BTA_JV_API_FREE_SCN_EVT */ + bta_jv_start_discovery, /* BTA_JV_API_START_DISCOVERY_EVT */ + bta_jv_cancel_discovery, /* BTA_JV_API_CANCEL_DISCOVERY_EVT */ + bta_jv_get_services_length, /* BTA_JV_API_GET_SERVICES_LENGTH_EVT */ + bta_jv_service_select, /* BTA_JV_API_SERVICE_SELECT_EVT */ + bta_jv_create_record, /* BTA_JV_API_CREATE_RECORD_EVT */ + bta_jv_update_record, /* BTA_JV_API_UPDATE_RECORD_EVT */ + bta_jv_add_attribute, /* BTA_JV_API_ADD_ATTRIBUTE_EVT */ + bta_jv_delete_attribute, /* BTA_JV_API_DELETE_ATTRIBUTE_EVT */ + bta_jv_delete_record, /* BTA_JV_API_DELETE_RECORD_EVT */ + bta_jv_l2cap_connect, /* BTA_JV_API_L2CAP_CONNECT_EVT */ + bta_jv_l2cap_close, /* BTA_JV_API_L2CAP_CLOSE_EVT */ + bta_jv_l2cap_start_server, /* BTA_JV_API_L2CAP_START_SERVER_EVT */ + bta_jv_l2cap_stop_server, /* BTA_JV_API_L2CAP_STOP_SERVER_EVT */ + bta_jv_l2cap_read, /* BTA_JV_API_L2CAP_READ_EVT */ + bta_jv_l2cap_write, /* BTA_JV_API_L2CAP_WRITE_EVT */ + bta_jv_rfcomm_connect, /* BTA_JV_API_RFCOMM_CONNECT_EVT */ + bta_jv_rfcomm_close, /* BTA_JV_API_RFCOMM_CLOSE_EVT */ + 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 */ +}; + +/******************************************************************************* +** +** Function bta_jv_sm_execute +** +** Description State machine event handling function for JV +** +** +** Returns void +** +*******************************************************************************/ +BOOLEAN bta_jv_sm_execute(BT_HDR *p_msg) +{ + BOOLEAN ret = FALSE; + UINT16 action = (p_msg->event & 0x00ff); + /* execute action functions */ + + if(action < BTA_JV_NUM_ACTIONS) + { + (*bta_jv_action[action])((tBTA_JV_MSG*)p_msg); + ret = TRUE; + } + + return(ret); +} diff --git a/btif/include/btif_sock.h b/btif/include/btif_sock.h new file mode 100644 index 0000000..a307255 --- /dev/null +++ b/btif/include/btif_sock.h @@ -0,0 +1,65 @@ +/************************************************************************************ + * + * 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. + * + ************************************************************************************/ + + +/************************************************************************************ + * + * Filename: btif_sock.h + * + * Description: Bluetooth socket Interface + * + * + ***********************************************************************************/ + +#ifndef btif_sock_h_ +#define btif_sock_h_ +#include <hardware/bt_sock.h> + +bt_status_t btif_sock_init(); +btsock_interface_t *btif_sock_get_interface(); +void btif_sock_cleanup(); +#endif diff --git a/btif/include/btif_sock_rfc.h b/btif/include/btif_sock_rfc.h new file mode 100644 index 0000000..5bf13ed --- /dev/null +++ b/btif/include/btif_sock_rfc.h @@ -0,0 +1,63 @@ +/************************************************************************************ + * + * 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_sock.h + * + * Description: Bluetooth socket Interface + * + * + ***********************************************************************************/ + +#ifndef btif_sock_rfc_h_ +#define btif_sock_rfc_h_ +bt_status_t btsock_rfc_init(); +bt_status_t btsock_rfc_listen(const char* name, const uint8_t* uuid, int channel, int* sock_fd, int flags); +bt_status_t btsock_rfc_connect(const bt_bdaddr_t *bd_addr, const uint8_t* uuid, int channel, int* sock_fd, int flags); +void btsock_rfc_signaled(int fd, int flags, uint32_t user_id); +#endif diff --git a/btif/include/btif_sock_sdp.h b/btif/include/btif_sock_sdp.h new file mode 100644 index 0000000..012e1a9 --- /dev/null +++ b/btif/include/btif_sock_sdp.h @@ -0,0 +1,68 @@ +/************************************************************************************ + * + * 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_sock.h + * + * Description: Bluetooth socket Interface + * + * + ***********************************************************************************/ + +#ifndef btif_sock_sdp_h_ +#define btif_sock_sdp_h_ +static inline BOOLEAN is_uuid_empty(const uint8_t* uuid) +{ + static uint8_t empty_uuid[16]; + return memcmp(uuid, empty_uuid, sizeof(empty_uuid)) == 0; +} +int add_rfc_sdp_rec(const char* name, const uint8_t* uuid, int scn); +void del_rfc_sdp_rec(int handle); +BOOLEAN is_reserved_rfc_channel(int channel); +int get_reserved_rfc_channel(const uint8_t* uuid); +#endif diff --git a/btif/include/btif_sock_thread.h b/btif/include/btif_sock_thread.h new file mode 100644 index 0000000..1e2fe0c --- /dev/null +++ b/btif/include/btif_sock_thread.h @@ -0,0 +1,71 @@ +/************************************************************************************ + * + * 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_sock_thread.h + * + * Description: + * + ***********************************************************************************/ + +#ifndef BTIF_SOCK_THREAD_H +#define BTIF_SOCK_THREAD_H +#include <hardware/bt_sock.h> + +#define SOCK_THREAD_FD_RD 1 //bt socket read signal +#define SOCK_THREAD_FD_WR (1 << 1) //bt socket write signal +#define SOCK_THREAD_FD_EXCEPTION (1 << 2) //bt socket exception singal +#define SOCK_THREAD_ADD_FD_SYNC (1 << 3) //add bt socket fd in current socket poll thread context immediately +int btsock_thread_init(); +int btsock_thread_add_fd(int handle, int fd, int type, int flags, uint32_t user_id); +int btsock_thread_wakeup(int handle); +typedef void (*btsock_signaled_cb)(int fd, int type, int flags, uint32_t user_id); +int btsock_thread_create(btsock_signaled_cb callback); +int btsock_thread_exit(int handle); +#endif + diff --git a/btif/include/btif_sock_util.h b/btif/include/btif_sock_util.h new file mode 100644 index 0000000..b76bb6f --- /dev/null +++ b/btif/include/btif_sock_util.h @@ -0,0 +1,87 @@ +/************************************************************************************ + * + * 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. + * + ************************************************************************************/ + + +/************************************************************************************ + * + * Filename: btif_sock_util.h + * + * Description: Bluetooth socket Interface Helper functions + * + * + ***********************************************************************************/ + +#ifndef btif_sock_util_h_ +#define btif_sock_util_h_ +#include <pthread.h> +#include <cutils/log.h> +static inline void init_slot_lock( pthread_mutex_t* mutex) +{ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); + pthread_mutex_init(mutex, &attr); +} +static inline void lock_slot(pthread_mutex_t* mutex) +{ + if(mutex->value) + pthread_mutex_lock(mutex); + else LOGE("mutex: %p is not initialized", mutex); +} +static inline void unlock_slot(pthread_mutex_t* mutex) +{ + if(mutex->value) + pthread_mutex_unlock(mutex); + else LOGE("mutex: %p is not initialized", mutex); +} +void dump_bin(const char* title, const char* data, int size); +int sock_send_fd(int sock_fd, const uint8_t* buffer, int len, int send_fd); + +int sock_send_all(int sock_fd, const uint8_t* buf, int len); +int sock_recv_all(int sock_fd, uint8_t* buf, int len); + +#endif diff --git a/btif/src/bluetooth.c b/btif/src/bluetooth.c index 358b8c4..5fccd80 100755 --- a/btif/src/bluetooth.c +++ b/btif/src/bluetooth.c @@ -60,6 +60,7 @@ #include <hardware/bluetooth.h> #include <hardware/bt_hf.h> #include <hardware/bt_av.h> +#include <hardware/bt_sock.h> #include <hardware/bt_hh.h> #include <hardware/bt_hl.h> @@ -98,6 +99,8 @@ bt_callbacks_t *bt_hal_cbacks = NULL; extern bthf_interface_t *btif_hf_get_interface(); /* advanced audio profile */ extern btav_interface_t *btif_av_get_interface(); +/*rfc l2cap*/ +extern btsock_interface_t *btif_sock_get_interface(); /* hid host profile */ extern bthh_interface_t *btif_hh_get_interface(); /* health device profile */ @@ -315,6 +318,8 @@ static const void* get_profile_interface (const char *profile_id) if (is_profile(profile_id, BT_PROFILE_HANDSFREE_ID)) return btif_hf_get_interface(); + if (is_profile(profile_id, BT_PROFILE_SOCKETS_ID)) + return btif_sock_get_interface(); if (is_profile(profile_id, BT_PROFILE_ADVANCED_AUDIO_ID)) return btif_av_get_interface(); diff --git a/btif/src/btif_sock.c b/btif/src/btif_sock.c new file mode 100644 index 0000000..859c329 --- /dev/null +++ b/btif/src/btif_sock.c @@ -0,0 +1,204 @@ +/************************************************************************************ + * + * 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. + * + ************************************************************************************/ + + +/************************************************************************************ + * + * Filename: btif_sock.c + * + * Description: Bluetooth Socket Interface + * + * + ***********************************************************************************/ + +#include <hardware/bluetooth.h> +#include <hardware/bt_sock.h> + +#define LOG_TAG "BTIF_SOCK" +#include "btif_common.h" +#include "btif_util.h" + +#include "bd.h" + +#include "bta_api.h" +#include "btif_sock_thread.h" +#include "btif_sock_rfc.h" +#include <cutils/log.h> +#define info(fmt, ...) LOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define debug(fmt, ...) LOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define error(fmt, ...) LOGE ("## ERROR : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__) +#define asrt(s) if(!(s)) LOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__) + +static bt_status_t btsock_listen(btsock_type_t type, const char* service_name, + const uint8_t* uuid, int channel, int* sock_fd, int flags); +static bt_status_t btsock_connect(const bt_bdaddr_t *bd_addr, btsock_type_t type, + const uint8_t* uuid, int channel, int* sock_fd, int flags); + +static void btsock_signaled(int fd, int type, int flags, uint32_t user_id); + +/******************************************************************************* +** +** Function btsock_ini +** +** Description initializes the bt socket interface +** +** Returns bt_status_t +** +*******************************************************************************/ +static btsock_interface_t sock_if = { + sizeof(sock_if), + btsock_listen, + btsock_connect + }; +btsock_interface_t *btif_sock_get_interface() +{ + return &sock_if; +} +bt_status_t btif_sock_init() +{ + static volatile int binit; + if(!binit) + { + binit = 1; + debug("btsock initializing..."); + btsock_thread_init(); + int handle = btsock_thread_create(btsock_signaled); + if(handle >= 0 && btsock_rfc_init(handle) == BT_STATUS_SUCCESS) + { + debug("btsock successfully initialized"); + return BT_STATUS_SUCCESS; + } + } + else error("btsock interface already initialized"); + return BT_STATUS_FAIL; +} +void btif_sock_cleanup() +{ + debug("btif_sock_cleanup()"); +} +static bt_status_t btsock_listen(btsock_type_t type, const char* service_name, + const uint8_t* service_uuid, int channel, int* sock_fd, int flags) +{ + if((service_uuid == NULL && channel <= 0) || sock_fd == NULL) + { + error("invalid parameters, uuid:%p, channel:%d, sock_fd:%p", service_uuid, channel, sock_fd); + return BT_STATUS_PARM_INVALID; + } + *sock_fd = -1; + bt_status_t status = BT_STATUS_FAIL; + switch(type) + { + case BTSOCK_RFCOMM: + status = btsock_rfc_listen(service_name, service_uuid, channel, sock_fd, flags); + break; + case BTSOCK_L2CAP: + error("bt l2cap socket type not supported, type:%d", type); + status = BT_STATUS_UNSUPPORTED; + break; + case BTSOCK_SCO: + error("bt sco socket not supported, type:%d", type); + status = BT_STATUS_UNSUPPORTED; + break; + default: + error("unknown bt socket type:%d", type); + status = BT_STATUS_UNSUPPORTED; + break; + } + return status; +} +static bt_status_t btsock_connect(const bt_bdaddr_t *bd_addr, btsock_type_t type, + const uint8_t* uuid, int channel, int* sock_fd, int flags) +{ + if((uuid == NULL && channel <= 0) || bd_addr == NULL || sock_fd == NULL) + { + error("invalid parameters, bd_addr:%p, uuid:%p, channel:%d, sock_fd:%p", + bd_addr, uuid, channel, sock_fd); + return BT_STATUS_PARM_INVALID; + } + *sock_fd = -1; + bt_status_t status = BT_STATUS_FAIL; + switch(type) + { + case BTSOCK_RFCOMM: + status = btsock_rfc_connect(bd_addr, uuid, channel, sock_fd, flags); + break; + case BTSOCK_L2CAP: + error("bt l2cap socket type not supported, type:%d", type); + status = BT_STATUS_UNSUPPORTED; + break; + case BTSOCK_SCO: + error("bt sco socket not supported, type:%d", type); + status = BT_STATUS_UNSUPPORTED; + break; + default: + error("unknown bt socket type:%d", type); + status = BT_STATUS_UNSUPPORTED; + break; + } + return status; +} +static void btsock_signaled(int fd, int type, int flags, uint32_t user_id) +{ + switch(type) + { + case BTSOCK_RFCOMM: + btsock_rfc_signaled(fd, flags, user_id); + break; + case BTSOCK_L2CAP: + error("bt l2cap socket type not supported, fd:%d, flags:%d", fd, flags); + break; + case BTSOCK_SCO: + error("bt sco socket type not supported, fd:%d, flags:%d", fd, flags); + break; + default: + error("unknown socket type:%d, fd:%d, flags:%d", type, fd, flags); + break; + } +} + + + diff --git a/btif/src/btif_sock_rfc.c b/btif/src/btif_sock_rfc.c new file mode 100644 index 0000000..b0d0538 --- /dev/null +++ b/btif/src/btif_sock_rfc.c @@ -0,0 +1,984 @@ +/************************************************************************************ + * + * 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. + * + ************************************************************************************/ + + +/************************************************************************************ + * + * Filename: btif_hf.c + * + * Description: Handsfree Profile Bluetooth Interface + * + * + ***********************************************************************************/ +#include <hardware/bluetooth.h> +#include <hardware/bt_sock.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <errno.h> +#include <sys/ioctl.h> + +#define LOG_TAG "BTIF_SOCK" +#include "btif_common.h" +#include "btif_util.h" + +#include "bd.h" + +#include "bta_api.h" +#include "btif_sock_thread.h" +#include "btif_sock_sdp.h" +#include "btif_sock_util.h" + +#include "bt_target.h" +#include "gki.h" +#include "hcimsgs.h" +#include "sdp_api.h" +#include "btu.h" +#include "btm_api.h" +#include "btm_int.h" +#include "bta_jv_api.h" +#include "bta_jv_co.h" +#include "port_api.h" + +#include <cutils/log.h> +#include <hardware/bluetooth.h> +#define info(fmt, ...) LOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define debug(fmt, ...) LOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define warn(fmt, ...) LOGW ("## WARNING : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__) +#define error(fmt, ...) LOGE ("## ERROR : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__) +#define asrt(s) if(!(s)) LOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__) + + +extern void uuid_to_string(bt_uuid_t *p_uuid, char *str); +static inline void logu(const char* title, const uint8_t * p_uuid) +{ + char uuids[128]; + uuid_to_string((bt_uuid_t*)p_uuid, uuids); + LOGD("%s: %s", title, uuids); +} + + + +#define MAX_RFC_CHANNEL 30 +#define MAX_RFC_SESSION BTA_JV_MAX_RFC_SR_SESSION //3 by default +typedef struct { + int outgoing_congest : 1; + int pending_sdp_request : 1; + int doing_sdp_request : 1; + int server : 1; + int connected : 1; + int closing : 1; +} flags_t; + +typedef struct { + flags_t f; + uint32_t id; + int security; + int scn; + bt_bdaddr_t addr; + uint8_t service_uuid[16]; + char service_name[256]; + int fd, app_fd; + int mtu; + uint8_t* packet; + int sdp_handle; + int rfc_handle; + int rfc_port_handle; + int role; + BUFFER_Q incoming_que; +} rfc_slot_t; + +static rfc_slot_t rfc_slots[MAX_RFC_CHANNEL]; +static uint32_t rfc_slot_id; +static int pth = -1; //poll thread handle + +static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data); +static void cleanup_rfc_slot(rfc_slot_t* rs); +static inline void close_rfc_connection(int rfc_handle, int server); +static bt_status_t dm_get_remote_service_record(bt_bdaddr_t *remote_addr, + bt_uuid_t *uuid); + +static pthread_mutex_t slot_lock; +static inline void clear_slot_flag(flags_t* f) +{ + memset(f, 0, sizeof(*f)); +} + +static inline void bd_copy(UINT8* dest, UINT8* src, BOOLEAN swap) +{ + if (swap) + { + int i; + for (i =0; i < 6 ;i++) + dest[i]= src[5-i]; + } + else memcpy(dest, src, 6); +} +static inline void free_gki_que(BUFFER_Q* q) +{ + while(!GKI_queue_is_empty(q)) + GKI_freebuf(GKI_dequeue(q)); +} +static void init_rfc_slots() +{ + int i; + memset(rfc_slots, 0, sizeof(rfc_slot_t)*MAX_RFC_CHANNEL); + for(i = 0; i < MAX_RFC_CHANNEL; i++) + { + rfc_slots[i].scn = -1; + rfc_slots[i].sdp_handle = 0; + rfc_slots[i].fd = rfc_slots[i].app_fd = -1; + GKI_init_q(&rfc_slots[i].incoming_que); + } + BTA_JvEnable(jv_dm_cback); + init_slot_lock(&slot_lock); +} +bt_status_t btsock_rfc_init(int poll_thread_handle) +{ + pth = poll_thread_handle; + init_rfc_slots(); + return BT_STATUS_SUCCESS; +} +static inline rfc_slot_t* find_free_slot() +{ + int i; + for(i = 0; i < MAX_RFC_CHANNEL; i++) + { + if(rfc_slots[i].fd == -1) + { + return &rfc_slots[i]; + } + } + return NULL; +} +static inline rfc_slot_t* find_rfc_slot_by_id(uint32_t id) +{ + int i; + if(id) + { + for(i = 0; i < MAX_RFC_CHANNEL; i++) + { + if(rfc_slots[i].id == id) + { + return &rfc_slots[i]; + } + } + } + warn("invalid rfc slot id: %d", id); + return NULL; +} +static inline rfc_slot_t* find_rfc_slot_by_pending_sdp() +{ + uint32_t min_id = (uint32_t)-1; + int slot = -1; + int i; + for(i = 0; i < MAX_RFC_CHANNEL; i++) + { + if(rfc_slots[i].id && rfc_slots[i].f.pending_sdp_request) + { + if(rfc_slots[i].id < min_id) + { + min_id = rfc_slots[i].id; + slot = i; + } + } + } + if(0<= slot && slot < MAX_RFC_CHANNEL) + return &rfc_slots[slot]; + return NULL; +} +static inline rfc_slot_t* find_rfc_slot_requesting_sdp() +{ + int i; + for(i = 0; i < MAX_RFC_CHANNEL; i++) + { + if(rfc_slots[i].id && rfc_slots[i].f.doing_sdp_request) + return &rfc_slots[i]; + } + debug("can not find any slot is requesting sdp"); + return NULL; +} + +static inline rfc_slot_t* find_rfc_slot_by_fd(int fd) +{ + int i; + if(fd >= 0) + { + for(i = 0; i < MAX_RFC_CHANNEL; i++) + { + if(rfc_slots[i].fd == fd) + { + if(rfc_slots[i].id) + return &rfc_slots[i]; + else + { + error("invalid rfc slot id, cannot be 0"); + break; + } + } + } + } + return NULL; +} +static rfc_slot_t* alloc_rfc_slot(const bt_bdaddr_t *addr, const char* name, const uint8_t* uuid, int channel, int flags, BOOLEAN server) +{ + int security = 0; + if(flags & BTSOCK_FLAG_ENCRYPT) + security |= server ? BTM_SEC_IN_ENCRYPT : BTM_SEC_OUT_ENCRYPT; + if(flags & BTSOCK_FLAG_AUTH) + security |= server ? BTM_SEC_IN_AUTHENTICATE : BTM_SEC_OUT_AUTHENTICATE; + + rfc_slot_t* rs = find_free_slot(); + if(rs) + { + int fds[2] = {-1, -1}; + if(socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) + { + error("socketpair failed, errno:%d", errno); + return NULL; + } + rs->fd = fds[0]; + rs->app_fd = fds[1]; + rs->security = security; + rs->scn = channel; + if(uuid) + memcpy(rs->service_uuid, uuid, sizeof(rs->service_uuid)); + if(name && *name) + strncpy(rs->service_name, name, sizeof(rs->service_name) -1); + if(addr) + rs->addr = *addr; + ++rfc_slot_id; + if(rfc_slot_id == 0) + rfc_slot_id = 1; //skip 0 when wrapped + rs->id = rfc_slot_id; + rs->f.server = server; + } + return rs; +} +// rfc_slot_t* accept_rs = create_srv_accept_rfc_slot(srv_rs, p_open->rem_bda,p_opne->handle, p_open->new_listen_handle); +static inline rfc_slot_t* create_srv_accept_rfc_slot(rfc_slot_t* srv_rs, const bt_bdaddr_t* addr, + int open_handle, int new_listen_handle) +{ + rfc_slot_t *accept_rs = alloc_rfc_slot(addr, srv_rs->service_name, srv_rs->service_uuid, srv_rs->scn, 0, FALSE); + clear_slot_flag(&accept_rs->f); + accept_rs->f.server = FALSE; + accept_rs->f.connected = TRUE; + accept_rs->security = srv_rs->security; + accept_rs->mtu = srv_rs->mtu; + accept_rs->role = srv_rs->role; + accept_rs->rfc_handle = open_handle; + accept_rs->rfc_port_handle = BTA_JvRfcommGetPortHdl(open_handle); + asrt(accept_rs->rfc_handle == srv_rs->rfc_handle); + asrt(accept_rs->rfc_port_handle == srv_rs->rfc_port_handle); + //now update listen handle of server slot + srv_rs->rfc_handle = new_listen_handle; + srv_rs->rfc_port_handle = BTA_JvRfcommGetPortHdl(new_listen_handle); + //now swap the slot id + uint32_t new_listen_id = accept_rs->id; + accept_rs->id = srv_rs->id; + srv_rs->id = new_listen_id; + return accept_rs; +} +bt_status_t btsock_rfc_listen(const char* service_name, const uint8_t* service_uuid, int channel, + int* sock_fd, int flags) +{ + if(sock_fd == NULL || (service_uuid == NULL && !is_reserved_rfc_channel(channel))) + { + error("invalid rfc channel:%d or sock_fd:%p, uuid:%p", channel, sock_fd, service_uuid); + return BT_STATUS_PARM_INVALID; + } + + //Check the service_uuid. If it uses a reserved channel number, use it + int reserved_channel = get_reserved_rfc_channel(service_uuid); + if(reserved_channel >0) + { + channel = reserved_channel; + } + + int status = BT_STATUS_FAIL; + *sock_fd = -1; + lock_slot(&slot_lock); + rfc_slot_t* rs = alloc_rfc_slot(NULL, service_name, service_uuid, channel, flags, TRUE); + if(rs) + { + debug("call BTA_JvCreateRecordByUser, slot id:%d, server fd:%d, app_fd:%d, security:0x%x, scn:%d", + rs->id, rs->fd, rs->app_fd, rs->security, rs->scn); + BTA_JvCreateRecordByUser((void *)rs->id); + *sock_fd = rs->app_fd; + rs->app_fd = -1; //the fd ownership is transferred to app + status = BT_STATUS_SUCCESS; + btsock_thread_add_fd(pth, rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_EXCEPTION, rs->id); + } + unlock_slot(&slot_lock); + return status; +} +bt_status_t btsock_rfc_connect(const bt_bdaddr_t *bd_addr, const uint8_t* service_uuid, + int channel, int* sock_fd, int flags) +{ + if(sock_fd == NULL || (service_uuid == NULL && !is_reserved_rfc_channel(channel))) + { + error("invalid rfc channel:%d or sock_fd:%p, uuid:%p", channel, sock_fd, service_uuid); + return BT_STATUS_PARM_INVALID; + } + int status = BT_STATUS_FAIL; + *sock_fd = -1; + lock_slot(&slot_lock); + rfc_slot_t* rs = alloc_rfc_slot(bd_addr, NULL, service_uuid, channel, flags, FALSE); + if(rs) + { + + //BTA_API extern tBTA_JV_STATUS BTA_JvStartDiscovery(BD_ADDR bd_addr, UINT16 num_uuid, + // tSDP_UUID *p_uuid_list, void* user_data); + tSDP_UUID sdp_uuid; + sdp_uuid.len = 16; + memcpy(sdp_uuid.uu.uuid128, service_uuid, sizeof(sdp_uuid.uu.uuid128)); + debug("start service channel discovery, slot id:%d, fd:%d, app_fd:%d, security:0x%x, scn:%d", + rs->id, rs->fd, rs->app_fd, rs->security, rs->scn); + logu("service_uuid", service_uuid); + *sock_fd = rs->app_fd; + rs->app_fd = -1; //the fd ownership is transferred to app + status = BT_STATUS_SUCCESS; + rfc_slot_t* rs_doing_sdp = find_rfc_slot_requesting_sdp(); + if(rs_doing_sdp == NULL) + { + BTA_JvStartDiscovery((UINT8*)bd_addr->address, 1, &sdp_uuid, (void*)rs->id); + rs->f.pending_sdp_request = FALSE; + rs->f.doing_sdp_request = TRUE; + } + else + { + rs->f.pending_sdp_request = TRUE; + rs->f.doing_sdp_request = FALSE; + } + btsock_thread_add_fd(pth, rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_RD, rs->id); + } + unlock_slot(&slot_lock); + return status; +} + +static int create_server_sdp_record(rfc_slot_t* rs) +{ + int scn = rs->scn; + if(rs->scn > 0) + { + if(BTM_TryAllocateSCN(rs->scn) == FALSE) + { + error("rfc channel:%d already in use", scn); + return FALSE; + } + } + else if((rs->scn = BTM_AllocateSCN()) == 0) + { + error("run out of rfc channels"); + return FALSE; + } + if((rs->sdp_handle = add_rfc_sdp_rec(rs->service_name, rs->service_uuid, rs->scn)) <= 0) + { + return FALSE; + } + return TRUE; +} +const char * jv_evt[] = { + "BTA_JV_ENABLE_EVT", + "BTA_JV_SET_DISCOVER_EVT", + "BTA_JV_LOCAL_ADDR_EVT", + "BTA_JV_LOCAL_NAME_EVT", + "BTA_JV_REMOTE_NAME_EVT", + "BTA_JV_SET_ENCRYPTION_EVT", + "BTA_JV_GET_SCN_EVT", + "BTA_JV_GET_PSM_EVT", + "BTA_JV_DISCOVERY_COMP_EVT", + "BTA_JV_SERVICES_LEN_EVT", + "BTA_JV_SERVICE_SEL_EVT", + "BTA_JV_CREATE_RECORD_EVT", + "BTA_JV_UPDATE_RECORD_EVT", + "BTA_JV_ADD_ATTR_EVT", + "BTA_JV_DELETE_ATTR_EVT", + "BTA_JV_CANCEL_DISCVRY_EVT", + + "BTA_JV_L2CAP_OPEN_EVT", + "BTA_JV_L2CAP_CLOSE_EVT", + "BTA_JV_L2CAP_START_EVT", + "BTA_JV_L2CAP_CL_INIT_EVT", + "BTA_JV_L2CAP_DATA_IND_EVT", + "BTA_JV_L2CAP_CONG_EVT", + "BTA_JV_L2CAP_READ_EVT", + "BTA_JV_L2CAP_RECEIVE_EVT", + "BTA_JV_L2CAP_WRITE_EVT", + + "BTA_JV_RFCOMM_OPEN_EVT", + "BTA_JV_RFCOMM_CLOSE_EVT", + "BTA_JV_RFCOMM_START_EVT", + "BTA_JV_RFCOMM_CL_INIT_EVT", + "BTA_JV_RFCOMM_DATA_IND_EVT", + "BTA_JV_RFCOMM_CONG_EVT", + "BTA_JV_RFCOMM_READ_EVT", + "BTA_JV_RFCOMM_WRITE_EVT", + "BTA_JV_RFCOMM_SRV_OPEN_EVT", // 33 /* open status of Server RFCOMM connection */ + "BTA_JV_MAX_EVT" +}; +static inline void free_rfc_slot_scn(rfc_slot_t* rs) +{ + if(rs->scn > 0) + { + if(rs->f.server && !rs->f.closing) + { + BTA_JvRfcommStopServer(rs->rfc_handle); + rs->rfc_handle = 0; + } + BTM_FreeSCN(rs->scn); + rs->scn = 0; + } +} +static void cleanup_rfc_slot(rfc_slot_t* rs) +{ + debug("cleanup slot:%d, fd:%d, scn:%d", rs->id, rs->fd, rs->scn); + if(rs->fd != -1) + { + shutdown(rs->fd, 2); + close(rs->fd); + rs->fd = -1; + } + if(rs->app_fd != -1) + { + close(rs->app_fd); + rs->app_fd = -1; + } + if(rs->sdp_handle > 0) + { + del_rfc_sdp_rec(rs->sdp_handle); + rs->sdp_handle = 0; + } + if(rs->rfc_handle && !rs->f.closing && !rs->f.server) + { + debug("closing rfcomm connection, rfc_handle:%d", rs->rfc_handle); + BTA_JvRfcommClose(rs->rfc_handle); + rs->rfc_handle = 0; + } + free_rfc_slot_scn(rs); + free_gki_que(&rs->incoming_que); + + rs->rfc_port_handle = 0; + //cleanup the flag + memset(&rs->f, 0, sizeof(rs->f)); + rs->id = 0; +} +static inline BOOLEAN send_app_scn(rfc_slot_t* rs) +{ + if(sock_send_all(rs->fd, (const uint8_t*)&rs->scn, sizeof(rs->scn)) == sizeof(rs->scn)) + { + return TRUE; + } + return FALSE; +} +static BOOLEAN send_app_connect_signal(int fd, const bt_bdaddr_t* addr, int channel, int status, int send_fd) +{ +/* + typedef struct { + short size; + bt_bdaddr_t bd_addr; + int channel; + int status; +} __attribute__((packed)) sock_connect_signal_t; +*/ + sock_connect_signal_t cs; + cs.size = sizeof(cs); + cs.bd_addr = *addr; + cs.channel = channel; + cs.status = status; + if(send_fd != -1) + { + if(sock_send_fd(fd, (const uint8_t*)&cs, sizeof(cs), send_fd) == sizeof(cs)) + return TRUE; + else error("sock_send_fd failed, fd:%d, send_fd:%d", fd, send_fd); + } + else if(sock_send_all(fd, (const uint8_t*)&cs, sizeof(cs)) == sizeof(cs)) + { + return TRUE; + } + return FALSE; +} +static void on_cl_rfc_init(tBTA_JV_RFCOMM_CL_INIT *p_init, uint32_t id) +{ + lock_slot(&slot_lock); + rfc_slot_t* rs = find_rfc_slot_by_id(id); + if(rs) + { + if (p_init->status != BTA_JV_SUCCESS) + cleanup_rfc_slot(rs); + else + { + rs->rfc_handle = p_init->handle; + debug("on_cl_rfc_init, slot id:%d, fd:%d, rfc scn:%d, server:%d", rs->id, rs->fd, rs->scn, rs->f.server); + } + } + unlock_slot(&slot_lock); +} +static void on_srv_rfc_listen_started(tBTA_JV_RFCOMM_START *p_start, uint32_t id) +{ + lock_slot(&slot_lock); + rfc_slot_t* rs = find_rfc_slot_by_id(id); + if(rs) + { + if (p_start->status != BTA_JV_SUCCESS) + cleanup_rfc_slot(rs); + else + { + rs->rfc_handle = p_start->handle; + debug("call send_app_scn, slot id:%d, fd:%d, rfc scn:%d, server:%d", rs->id, rs->fd, rs->scn, rs->f.server); + if(!send_app_scn(rs)) + { + //closed + debug("send_app_scn() failed, close rs->id:%d", rs->id); + cleanup_rfc_slot(rs); + } + } + } + unlock_slot(&slot_lock); +} +static uint32_t on_srv_rfc_connect(tBTA_JV_RFCOMM_SRV_OPEN *p_open, uint32_t id) +{ + uint32_t new_listen_slot_id = 0; + lock_slot(&slot_lock); + rfc_slot_t* srv_rs = find_rfc_slot_by_id(id); + if(srv_rs) + { + rfc_slot_t* accept_rs = create_srv_accept_rfc_slot(srv_rs, (const bt_bdaddr_t*)p_open->rem_bda, + p_open->handle, p_open->new_listen_handle); + if(accept_rs) + { + //start monitor the socket + btsock_thread_add_fd(pth, srv_rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_EXCEPTION, srv_rs->id); + btsock_thread_add_fd(pth, accept_rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_RD, accept_rs->id); + debug("sending connect signal & app fd:%dto app server to accept() the connection", accept_rs->app_fd); + debug("server fd:%d, scn:%d", srv_rs->fd, srv_rs->scn); + send_app_connect_signal(srv_rs->fd, &accept_rs->addr, srv_rs->scn, 0, accept_rs->app_fd); + accept_rs->app_fd = -1; //the fd is closed after sent to app + new_listen_slot_id = srv_rs->id; + } + } + unlock_slot(&slot_lock); + return new_listen_slot_id; +} +static void on_cli_rfc_connect(tBTA_JV_RFCOMM_OPEN *p_open, uint32_t id) +{ + lock_slot(&slot_lock); + rfc_slot_t* rs = find_rfc_slot_by_id(id); + if(rs && p_open->status == BTA_JV_SUCCESS) + { + rs->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_open->handle); + bd_copy(rs->addr.address, p_open->rem_bda, 0); + //notify app rfc is connected + debug("call send_app_connect_signal, slot id:%d, fd:%d, rfc scn:%d, server:%d", rs->id, rs->fd, rs->scn, rs->f.server); + if(send_app_connect_signal(rs->fd, &rs->addr, rs->scn, 0, -1)) + { + //start monitoring the socketpair to get call back when app writing data + debug("on_rfc_connect_ind, connect signal sent, slot id:%d, rfc scn:%d, server:%d", rs->id, rs->scn, rs->f.server); + rs->f.connected = TRUE; + } + else error("send_app_connect_signal failed"); + } + else if(rs) + cleanup_rfc_slot(rs); + unlock_slot(&slot_lock); +} +static void on_rfc_close(tBTA_JV_RFCOMM_CLOSE * p_close, uint32_t id) +{ + lock_slot(&slot_lock); + rfc_slot_t* rs = find_rfc_slot_by_id(id); + if(rs) + { + debug("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. + rs->rfc_handle = 0; + rs->f.connected = FALSE; + cleanup_rfc_slot(rs); + } + unlock_slot(&slot_lock); +} +static void on_rfc_write_done(tBTA_JV_RFCOMM_WRITE *p, uint32_t id) +{ + lock_slot(&slot_lock); + rfc_slot_t* rs = find_rfc_slot_by_id(id); + if(rs && !rs->f.outgoing_congest) + { + //mointer the fd for any outgoing data + btsock_thread_add_fd(pth, rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_RD, rs->id); + } + unlock_slot(&slot_lock); +} +static void on_rfc_outgoing_congest(tBTA_JV_RFCOMM_CONG *p, uint32_t id) +{ + lock_slot(&slot_lock); + rfc_slot_t* rs = find_rfc_slot_by_id(id); + if(rs) + { + rs->f.outgoing_congest = p->cong ? 1 : 0; + //mointer the fd for any outgoing data + if(!rs->f.outgoing_congest) + btsock_thread_add_fd(pth, rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_RD, rs->id); + } + unlock_slot(&slot_lock); +} + +static void *rfcomm_cback(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data) +{ + int rc; + void* new_user_data = NULL; + debug("event=%s", jv_evt[event]); + + switch (event) + { + case BTA_JV_RFCOMM_START_EVT: + debug("BTA_JV_RFCOMM_START_EVT"); + on_srv_rfc_listen_started(&p_data->rfc_start, (uint32_t)user_data); + break; + + case BTA_JV_RFCOMM_CL_INIT_EVT: + debug("BTA_JV_RFCOMM_CL_INIT_EVT"); + on_cl_rfc_init(&p_data->rfc_cl_init, (uint32_t)user_data); + break; + + case BTA_JV_RFCOMM_OPEN_EVT: + debug("BTA_JV_RFCOMM_OPEN_EVT"); + on_cli_rfc_connect(&p_data->rfc_open, (uint32_t)user_data); + break; + case BTA_JV_RFCOMM_SRV_OPEN_EVT: + debug("BTA_JV_RFCOMM_SRV_OPEN_EVT"); + new_user_data = (void*)on_srv_rfc_connect(&p_data->rfc_srv_open, (uint32_t)user_data); + break; + + case BTA_JV_RFCOMM_CLOSE_EVT: + debug("BTA_JV_RFCOMM_CLOSE_EVT"); + on_rfc_close(&p_data->rfc_close, (uint32_t)user_data); + break; + + case BTA_JV_RFCOMM_READ_EVT: + debug("BTA_JV_RFCOMM_READ_EVT not used"); + break; + + case BTA_JV_RFCOMM_WRITE_EVT: + debug("BTA_JV_RFCOMM_WRITE_EVT"); + on_rfc_write_done(&p_data->rfc_write, (uint32_t)user_data); + break; + + case BTA_JV_RFCOMM_DATA_IND_EVT: + debug("BTA_JV_RFCOMM_DATA_IND_EVT not used"); + break; + + case BTA_JV_RFCOMM_CONG_EVT: + //on_rfc_cong(&p_data->rfc_cong); + debug("BTA_JV_RFCOMM_CONG_EVT"); + on_rfc_outgoing_congest(&p_data->rfc_cong, (uint32_t)user_data); + break; + default: + error("unhandled event %d, slot id:%d", event, (uint32_t)user_data); + break; + } + return new_user_data; +} + +static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data) +{ + uint32_t id = (uint32_t)user_data; + debug("event:%d, slot id:%d", event, id); + switch(event) + { + case BTA_JV_CREATE_RECORD_EVT: + { + lock_slot(&slot_lock); + rfc_slot_t* rs = find_rfc_slot_by_id(id); + if(rs && create_server_sdp_record(rs)) + { + //now start the rfcomm server after sdp & channel # assigned + debug("BTA_JvCreateRecordByUser callback BTA_JV_CREATE_RECORD_EVT, slot id:%d, fd:%d, security:0x%x, scn:%d", + rs->id, rs->fd, rs->security, rs->scn); + BTA_JvRfcommStartServer(rs->security, rs->role, rs->scn, MAX_RFC_SESSION, rfcomm_cback, (void*)rs->id); + } + unlock_slot(&slot_lock); + break; + } + case BTA_JV_DISCOVERY_COMP_EVT: + { + rfc_slot_t* rs = NULL; + lock_slot(&slot_lock); + if(p_data->disc_comp.status == BTA_JV_SUCCESS && p_data->disc_comp.scn) + { + error("BTA_JV_DISCOVERY_COMP_EVT, slot id:%d, found channle #, status:%d, scn:%d", id, p_data->disc_comp.status, + p_data->disc_comp.scn); + + rs = find_rfc_slot_by_id(id); + if(rs && rs->f.doing_sdp_request) + { + if(BTA_JvRfcommConnect(rs->security, rs->role, p_data->disc_comp.scn, rs->addr.address, + rfcomm_cback, (void*)rs->id) == BTA_JV_SUCCESS) + { + rs->scn = p_data->disc_comp.scn; + rs->f.doing_sdp_request = FALSE; + if(!send_app_scn(rs)) + cleanup_rfc_slot(rs); + } + else cleanup_rfc_slot(rs); + } + else if(rs) + { + error("BTA_JV_DISCOVERY_COMP_EVT rfc can not find pending sdp request, slot id:%d, \ + flag sdp pending:%d, flag sdp doing:%d", + id, rs->f.pending_sdp_request, rs->f.doing_sdp_request); + } + } + else + { + error("BTA_JV_DISCOVERY_COMP_EVT slot id:%d, failed to find channle #, status:%d, scn:%d", id, p_data->disc_comp.status, + p_data->disc_comp.scn); + rs = find_rfc_slot_by_id(id); + if(rs) + cleanup_rfc_slot(rs); + } + rs = find_rfc_slot_by_pending_sdp(); + if(rs) + { + debug("BTA_JV_DISCOVERY_COMP_EVT, start another pending scn sdp request"); + tSDP_UUID sdp_uuid; + sdp_uuid.len = 16; + memcpy(sdp_uuid.uu.uuid128, rs->service_uuid, sizeof(sdp_uuid.uu.uuid128)); + BTA_JvStartDiscovery((UINT8*)rs->addr.address, 1, &sdp_uuid, (void*)rs->id); + rs->f.pending_sdp_request = FALSE; + rs->f.doing_sdp_request = TRUE; + } + unlock_slot(&slot_lock); + break; + } + default: + debug("unhandled event:%d, slot id:%d", event, id); + break; + } + +} +#define SENT_ALL 2 +#define SENT_PARTIAL 1 +#define SENT_NONE 0 +#define SENT_FAILED (-1) +static int send_data_to_app(int fd, BT_HDR *p_buf) +{ + if(p_buf->len == 0) + return SENT_ALL; + int sent = send(fd, (UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len, MSG_DONTWAIT); + if(sent == p_buf->len) + return SENT_ALL; + + if(sent > 0 && sent < p_buf->len) + { + //sent partial + error("send partial, sent:%d, p_buf->len:%d", sent, p_buf->len); + p_buf->offset += sent; + p_buf->len -= sent; + return SENT_PARTIAL; + + } + if(sent < 0 && + (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) + { + error("send none, EAGAIN or EWOULDBLOCK, errno:%d", errno); + return SENT_NONE; + } + error("unknown send() error, sent:%d, p_buf->len:%d, errno:%d", sent, p_buf->len, errno); + return SENT_FAILED; +} +static BOOLEAN flush_incoming_que_on_wr_signal(rfc_slot_t* rs) +{ + while(!GKI_queue_is_empty(&rs->incoming_que)) + { + BT_HDR *p_buf = GKI_dequeue(&rs->incoming_que); + int sent = send_data_to_app(rs->fd, p_buf); + switch(sent) + { + case SENT_NONE: + case SENT_PARTIAL: + //add it back to the queue at same position + GKI_enqueue_head (&rs->incoming_que, p_buf); + //monitor the fd to get callback when app is ready to receive data + btsock_thread_add_fd(pth, rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_WR, rs->id); + return TRUE; + case SENT_ALL: + GKI_freebuf(p_buf); + break; + case SENT_FAILED: + GKI_freebuf(p_buf); + return FALSE; + } + } + + //app is ready to receive data, tell stack to start the data flow + //fix me: need a jv flow control api to serialize the call in stack + PORT_FlowControl(rs->rfc_port_handle, TRUE); + return TRUE; +} +void btsock_rfc_signaled(int fd, int flags, uint32_t user_id) +{ + debug("fd:%d, flags:%x", fd, flags); + lock_slot(&slot_lock); + rfc_slot_t* rs = find_rfc_slot_by_id(user_id); + if(rs) + { + debug("rfc slot id:%d, fd:%d, flags:%x", rs->id, fd, flags); + BOOLEAN need_close = FALSE; + if(flags & SOCK_THREAD_FD_RD) + { + //data available from app, tell stack we have outgoing data + if(!rs->f.server) + { + if(rs->f.connected) + BTA_JvRfcommWrite(rs->rfc_handle, (UINT32)rs->id); + else + { + error("SOCK_THREAD_FD_RD signaled when rfc is not connected, slot id:%d, channel:%d", rs->id, rs->scn); + need_close = TRUE; + } + } + } + if(flags & SOCK_THREAD_FD_WR) + { + //app is ready to receive more data, tell stack to enable the data flow + if(!rs->f.connected || !flush_incoming_que_on_wr_signal(rs)) + { + need_close = TRUE; + error("SOCK_THREAD_FD_WR signaled when rfc is not connected or app closed fd, slot id:%d, channel:%d", rs->id, rs->scn); + } + + } + if(need_close || (flags & SOCK_THREAD_FD_EXCEPTION)) + { + debug("SOCK_THREAD_FD_EXCEPTION, flags:%x", flags); + rs->f.closing = TRUE; + if(rs->f.server) + BTA_JvRfcommStopServer(rs->rfc_handle); + else + BTA_JvRfcommClose(rs->rfc_handle); + } + } + 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; + int ret = 0; + lock_slot(&slot_lock); + rfc_slot_t* rs = find_rfc_slot_by_id(id); + if(rs) + { + + int sent = send_data_to_app(rs->fd, p_buf); + switch(sent) + { + case SENT_NONE: + case SENT_PARTIAL: + //add it to the end of the queue + GKI_enqueue(&rs->incoming_que, p_buf); + //monitor the fd to get callback when app is ready to receive data + btsock_thread_add_fd(pth, rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_WR, rs->id); + break; + case SENT_ALL: + GKI_freebuf(p_buf); + ret = 1;//enable the data flow + break; + case SENT_FAILED: + GKI_freebuf(p_buf); + cleanup_rfc_slot(rs); + break; + } + } + unlock_slot(&slot_lock); + return ret;//return 0 to disable data flow +} +int bta_co_rfc_data_outgoing_size(void *user_data, int *size) +{ + uint32_t id = (uint32_t)user_data; + int ret = FALSE; + *size = 0; + lock_slot(&slot_lock); + rfc_slot_t* rs = find_rfc_slot_by_id(id); + if(rs) + { + if(ioctl(rs->fd, FIONREAD, size) == 0) + { + debug("ioctl read avaiable size:%d, fd:%d", *size, rs->fd); + ret = TRUE; + } + else + { + error("ioctl FIONREAD error, errno:%d, fd:%d", errno, rs->fd); + cleanup_rfc_slot(rs); + } + } + unlock_slot(&slot_lock); + return ret; +} +int bta_co_rfc_data_outgoing(void *user_data, UINT8* buf, UINT16 size) +{ + uint32_t id = (uint32_t)user_data; + int ret = FALSE; + lock_slot(&slot_lock); + rfc_slot_t* rs = find_rfc_slot_by_id(id); + if(rs) + { + int received = recv(rs->fd, buf, size, 0); + if(received == size) + ret = TRUE; + else + { + error("recv error, errno:%d, fd:%d, size:%d, received:%d", errno, rs->fd, size, received); + cleanup_rfc_slot(rs); + } + } + unlock_slot(&slot_lock); + return ret; +} +//] + diff --git a/btif/src/btif_sock_sdp.c b/btif/src/btif_sock_sdp.c new file mode 100644 index 0000000..e3156bd --- /dev/null +++ b/btif/src/btif_sock_sdp.c @@ -0,0 +1,580 @@ +/************************************************************************************ + * + * 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_hf.c + * + * Description: Handsfree Profile Bluetooth Interface + * + * + ***********************************************************************************/ + +#include <hardware/bluetooth.h> +#include <hardware/bt_sock.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <errno.h> + +#define LOG_TAG "BTIF_SOCK_SDP" +#include "btif_common.h" +#include "btif_util.h" + +#include "bd.h" + +#include "bta_api.h" + + +#include "bt_target.h" +#include "gki.h" +#include "hcimsgs.h" +#include "sdp_api.h" +#include "btu.h" +#include "btm_api.h" +#include "btm_int.h" +#include "btif_sock_sdp.h" +#include "utl.h" +#include "../bta/ft/bta_fts_int.h" +#include "../bta/pb/bta_pbs_int.h" +#include "../bta/op/bta_ops_int.h" +#include <cutils/log.h> +#define info(fmt, ...) LOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define debug(fmt, ...) LOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define error(fmt, ...) LOGE ("## ERROR : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__) +#define asrt(s) if(!(s)) LOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__) + + + + +#define RESERVED_SCN_PBS 19 +#define RESERVED_SCN_OPS 12 + + +static int add_ftp_sdp(const char *p_service_name, int scn) +{ + tSDP_PROTOCOL_ELEM protoList [3]; + UINT16 ftp_service = UUID_SERVCLASS_OBEX_FILE_TRANSFER; + UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + BOOLEAN status = FALSE; + int sdp_handle; + + info("scn: %d, service name: %s", scn, p_service_name); + tBTA_UTL_COD cod; + + + /* also set cod service bit for now */ + cod.service = BTM_COD_SERVICE_OBJ_TRANSFER; + utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS); + + if ((sdp_handle = SDP_CreateRecord()) == 0) + { + error("FTS SDP: Unable to register FTP Service"); + return sdp_handle; + } + + /* add service class */ + if (SDP_AddServiceClassIdList(sdp_handle, 1, &ftp_service)) + { + /* add protocol list, including RFCOMM scn */ + protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + protoList[0].num_params = 0; + protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + protoList[1].num_params = 1; + protoList[1].params[0] = scn; + protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; + protoList[2].num_params = 0; + + if (SDP_AddProtocolList(sdp_handle, 3, protoList)) + { + status = TRUE; /* All mandatory fields were successful */ + + /* optional: if name is not "", add a name entry */ + if (*p_service_name != '\0') + SDP_AddAttribute(sdp_handle, + (UINT16)ATTR_ID_SERVICE_NAME, + (UINT8)TEXT_STR_DESC_TYPE, + (UINT32)(strlen(p_service_name) + 1), + (UINT8 *)p_service_name); + + /* Add in the Bluetooth Profile Descriptor List */ + SDP_AddProfileDescriptorList(sdp_handle, + UUID_SERVCLASS_OBEX_FILE_TRANSFER, + BTA_FTS_DEFAULT_VERSION); + + } /* end of setting mandatory protocol list */ + } /* end of setting mandatory service class */ + + /* Make the service browseable */ + SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); + + if (!status) + { + SDP_DeleteRecord(sdp_handle); + sdp_handle = 0; + error("bta_fts_sdp_register FAILED"); + } + else + { + bta_sys_add_uuid(ftp_service); /* UUID_SERVCLASS_OBEX_FILE_TRANSFER */ + error("FTS: SDP Registered (handle 0x%08x)", sdp_handle); + } + + return sdp_handle; +} + + +static int add_spp_sdp(const char *service_name, int scn) +{ +#if 0 + tSPP_STATUS status = SPP_SUCCESS; + UINT16 serviceclassid = UUID_SERVCLASS_SERIAL_PORT; + tSDP_PROTOCOL_ELEM proto_elem_list[SPP_NUM_PROTO_ELEMS]; + int sdp_handle; + + info("scn %d, service name %s", scn, service_name); + + /* register the service */ + if ((sdp_handle = SDP_CreateRecord()) != FALSE) + { + /*** Fill out the protocol element sequence for SDP ***/ + proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + proto_elem_list[0].num_params = 0; + proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + proto_elem_list[1].num_params = 1; + + proto_elem_list[1].params[0] = scn; + + if (SDP_AddProtocolList(sdp_handle, SPP_NUM_PROTO_ELEMS, + proto_elem_list)) + { + if (SDP_AddServiceClassIdList(sdp_handle, 1, &serviceclassid)) + { + if ((SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, + TEXT_STR_DESC_TYPE, (UINT32)(strlen(service_name)+1), + (UINT8 *)service_name)) == FALSE) + + status = SPP_ERR_SDP_ATTR; + else + { + UINT16 list[1]; + + /* Make the service browseable */ + list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + if ((SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, + 1, list)) == FALSE) + + status = SPP_ERR_SDP_CLASSID; + } + } + else + status = SPP_ERR_SDP_CLASSID; + } + else + status = SPP_ERR_SDP_PROTO; + } + else + status = SPP_ERR_SDP_REG; + + return spb_handle; +#endif + return 0; +} +#define BTM_NUM_PROTO_ELEMS 2 +static int add_sdp_by_uuid(const char *name, const uint8_t *service_uuid, UINT16 channel) +{ + + UINT32 btm_sdp_handle; + + tSDP_PROTOCOL_ELEM proto_elem_list[BTM_NUM_PROTO_ELEMS]; + + /* register the service */ + if ((btm_sdp_handle = SDP_CreateRecord()) != FALSE) + { + /*** Fill out the protocol element sequence for SDP ***/ + proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + proto_elem_list[0].num_params = 0; + proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + proto_elem_list[1].num_params = 1; + + proto_elem_list[1].params[0] = channel; + + if (SDP_AddProtocolList(btm_sdp_handle, BTM_NUM_PROTO_ELEMS, + proto_elem_list)) + { + UINT8 buff[48]; + UINT8 *p, *type_buf[1]; + UINT8 type[1], type_len[1]; + p = type_buf[0] = buff; + type[0] = UUID_DESC_TYPE; + +// UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES); + ARRAY_TO_BE_STREAM (p, service_uuid, 16); + type_len[0] = 16; + if( SDP_AddSequence(btm_sdp_handle, (UINT16) ATTR_ID_SERVICE_CLASS_ID_LIST, + 1, type, type_len, type_buf) ) +// if (SDP_AddServiceClassIdList(btm_sdp_handle, 1, &service_uuid)) + { + if ((SDP_AddAttribute(btm_sdp_handle, ATTR_ID_SERVICE_NAME, + TEXT_STR_DESC_TYPE, (UINT32)(strlen(name)+1), + (UINT8 *)name)) ) + { + UINT16 list[1]; + + /* Make the service browseable */ + list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + if ((SDP_AddUuidSequence (btm_sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, + 1, list)) ) + + return btm_sdp_handle; + } + } + } + } + + return 0; +} + + +/* Realm Character Set */ +#define BTA_PBS_REALM_CHARSET 0 /* ASCII */ + +/* Specifies whether or not client's user id is required during obex authentication */ +#define BTA_PBS_USERID_REQ FALSE +extern const tBTA_PBS_CFG bta_pbs_cfg; +const tBTA_PBS_CFG bta_pbs_cfg = +{ + BTA_PBS_REALM_CHARSET, /* Server only */ + BTA_PBS_USERID_REQ, /* Server only */ + (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE), + BTA_PBS_REPOSIT_LOCAL, +}; + +static int add_pbap_sdp(const char* p_service_name, int scn) +{ + + tSDP_PROTOCOL_ELEM protoList [3]; + UINT16 pbs_service = UUID_SERVCLASS_PBAP_PSE; + UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + BOOLEAN status = FALSE; + UINT32 sdp_handle = 0; + tBTA_PBS_CFG *p_bta_pbs_cfg = (tBTA_PBS_CFG *)&bta_pbs_cfg; + + info("scn %d, service name %s", scn, p_service_name); + + if ((sdp_handle = SDP_CreateRecord()) == 0) + { + error("PBS SDP: Unable to register PBS Service"); + return sdp_handle; + } + + /* add service class */ + if (SDP_AddServiceClassIdList(sdp_handle, 1, &pbs_service)) + { + memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) ); + /* add protocol list, including RFCOMM scn */ + protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + protoList[0].num_params = 0; + protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + protoList[1].num_params = 1; + protoList[1].params[0] = scn; + protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; + protoList[2].num_params = 0; + + if (SDP_AddProtocolList(sdp_handle, 3, protoList)) + { + status = TRUE; /* All mandatory fields were successful */ + + /* optional: if name is not "", add a name entry */ + if (*p_service_name != '\0') + SDP_AddAttribute(sdp_handle, + (UINT16)ATTR_ID_SERVICE_NAME, + (UINT8)TEXT_STR_DESC_TYPE, + (UINT32)(strlen(p_service_name) + 1), + (UINT8 *)p_service_name); + + /* Add in the Bluetooth Profile Descriptor List */ + SDP_AddProfileDescriptorList(sdp_handle, + UUID_SERVCLASS_PHONE_ACCESS, + BTA_PBS_DEFAULT_VERSION); + + } /* end of setting mandatory protocol list */ + } /* end of setting mandatory service class */ + + /* add supported feature and repositories */ + if (status) + { + SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE, + (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_features); + SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, + (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_repositories); + + /* Make the service browseable */ + SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); + } + + if (!status) + { + SDP_DeleteRecord(sdp_handle); + sdp_handle = 0; + APPL_TRACE_ERROR0("bta_pbs_sdp_register FAILED"); + } + else + { + bta_sys_add_uuid(pbs_service); /* UUID_SERVCLASS_PBAP_PSE */ + APPL_TRACE_DEBUG1("PBS: SDP Registered (handle 0x%08x)", sdp_handle); + } + + return sdp_handle; +} + + +/* object format lookup table */ +static const tBTA_OP_FMT bta_ops_obj_fmt[] = +{ + BTA_OP_VCARD21_FMT, + BTA_OP_VCARD30_FMT, + BTA_OP_VCAL_FMT, + BTA_OP_ICAL_FMT, + BTA_OP_VNOTE_FMT, + BTA_OP_VMSG_FMT, + BTA_OP_OTHER_FMT +}; + +#define BTA_OPS_NUM_FMTS 7 +#define BTA_OPS_PROTOCOL_COUNT 3 + +#ifndef BTUI_OPS_FORMATS +#define BTUI_OPS_FORMATS (BTA_OP_VCARD21_MASK | BTA_OP_VCARD30_MASK | \ + BTA_OP_VCAL_MASK | BTA_OP_ICAL_MASK | \ + BTA_OP_VNOTE_MASK | BTA_OP_VMSG_MASK | \ + BTA_OP_ANY_MASK ) +#endif + +static int add_ops_sdp(const char *p_service_name,int scn) +{ + + + tSDP_PROTOCOL_ELEM protoList [BTA_OPS_PROTOCOL_COUNT]; + tOBX_StartParams start_params; + UINT16 servclass = UUID_SERVCLASS_OBEX_OBJECT_PUSH; + int i, j; + tBTA_UTL_COD cod; + tOBX_STATUS status; + UINT8 desc_type[BTA_OPS_NUM_FMTS]; + UINT8 type_len[BTA_OPS_NUM_FMTS]; + UINT8 *type_value[BTA_OPS_NUM_FMTS]; + UINT16 browse; + UINT32 sdp_handle; + tBTA_OP_FMT_MASK formats = BTUI_OPS_FORMATS; + + info("scn %d, service name %s", scn, p_service_name); + + sdp_handle = SDP_CreateRecord(); + + /* add service class */ + if (SDP_AddServiceClassIdList(sdp_handle, 1, &servclass)) + { + /* add protocol list, including RFCOMM scn */ + protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + protoList[0].num_params = 0; + protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + protoList[1].num_params = 1; + protoList[1].params[0] = scn; + protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX; + protoList[2].num_params = 0; + + if (SDP_AddProtocolList(sdp_handle, BTA_OPS_PROTOCOL_COUNT, protoList)) + { + SDP_AddAttribute(sdp_handle, + (UINT16)ATTR_ID_SERVICE_NAME, + (UINT8)TEXT_STR_DESC_TYPE, + (UINT32)(strlen(p_service_name) + 1), + (UINT8 *)p_service_name); + + SDP_AddProfileDescriptorList(sdp_handle, + UUID_SERVCLASS_OBEX_OBJECT_PUSH, + 0x0100); + } + } + + /* Make the service browseable */ + browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); + + /* add sequence for supported types */ + for (i = 0, j = 0; i < BTA_OPS_NUM_FMTS; i++) + { + if ((formats >> i) & 1) + { + type_value[j] = (UINT8 *) &bta_ops_obj_fmt[i]; + desc_type[j] = UINT_DESC_TYPE; + type_len[j++] = 1; + } + } + + SDP_AddSequence(sdp_handle, (UINT16) ATTR_ID_SUPPORTED_FORMATS_LIST, + (UINT8) j, desc_type, type_len, type_value); + + /* set class of device */ + cod.service = BTM_COD_SERVICE_OBJ_TRANSFER; + utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS); + + bta_sys_add_uuid(servclass); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */ + + return sdp_handle; +} + + + + + +static int add_rfc_sdp_by_uuid(const char* name, const uint8_t* uuid, int scn) +{ + int handle = 0; + UINT16 uuid_16bit; + + uuid_16bit = (((UINT16)uuid[2]) << 8) | (UINT16)uuid[3]; + + info("name:%s, scn:%d, uuid_16bit: %d", name, scn,uuid_16bit); + + int final_scn = get_reserved_rfc_channel(uuid); + if (final_scn == -1) + { + final_scn=scn; + } + + /* + Bluetooth Socket API relies on having preregistered bluez sdp records for HSAG, HFAG, OPP & PBAP + that are mapped to rc chan 10, 11,12 & 19. Today HSAG and HFAG is routed to BRCM AG and are not + using BT socket API so for now we will need to support OPP and PBAP to enable 3rd party developer + apps running on BRCM Android. + + To do this we will check the UUID for the requested service and mimic the SDP records of bluez + upon reception. See functions add_opush() and add_pbap() in sdptool.c for actual records + */ + + /* special handling for preregistered bluez services (OPP, PBAP) that we need to mimic */ + + if (uuid_16bit == UUID_SERVCLASS_OBEX_OBJECT_PUSH) + { + handle = add_ops_sdp(name,final_scn); + } + else if (uuid_16bit == UUID_SERVCLASS_PBAP_PSE) + { + handle = add_pbap_sdp(name, final_scn); //PBAP Server is always 19 + } + else if(uuid_16bit == UUID_SERVCLASS_OBEX_FILE_TRANSFER) + { + APPL_TRACE_EVENT0("Stopping btld ftp serivce when 3-party registering ftp service"); + //BTA_FtsDisable(); + handle = add_sdp_by_uuid(name, uuid, final_scn); + } + else + { + handle = add_sdp_by_uuid(name, uuid, final_scn); + } + return handle; +} + +BOOLEAN is_reserved_rfc_channel(int scn) +{ + switch(scn) + { + case RESERVED_SCN_PBS: + case RESERVED_SCN_OPS: + return TRUE; + } + return FALSE; +} + + +int get_reserved_rfc_channel (const uint8_t* uuid) +{ + UINT16 uuid_16bit; + uuid_16bit = (((UINT16)uuid[2]) << 8) | (UINT16)uuid[3]; + info("uuid_16bit: %d", uuid_16bit); + if (uuid_16bit == UUID_SERVCLASS_PBAP_PSE) + { + return RESERVED_SCN_PBS; + } + else if (uuid_16bit == UUID_SERVCLASS_OBEX_OBJECT_PUSH) + { + return RESERVED_SCN_OPS; + } + + return -1; +} + +int add_rfc_sdp_rec(const char* name, const uint8_t* uuid, int scn) +{ + int sdp_handle = 0; + if(is_uuid_empty(uuid)) + { + switch(scn) + { + case RESERVED_SCN_PBS: // PBAP Reserved port + add_pbap_sdp(name, scn); + break; + case RESERVED_SCN_OPS: + add_ops_sdp(name,scn); + break; + default://serial port profile + sdp_handle = add_spp_sdp(name, scn); + break; + } + } + else + sdp_handle = add_rfc_sdp_by_uuid(name, uuid, scn); + return sdp_handle; +} + +void del_rfc_sdp_rec(int handle) +{ + if(handle != -1 && handle != 0) + SDP_DeleteRecord( handle ); +} + diff --git a/btif/src/btif_sock_thread.c b/btif/src/btif_sock_thread.c new file mode 100644 index 0000000..5bf014e --- /dev/null +++ b/btif/src/btif_sock_thread.c @@ -0,0 +1,591 @@ +/************************************************************************************ + * + * 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. + * + ************************************************************************************/ + +/************************************************************************************ + * + * Filename: btif_sock_thread.c + * + * Description: socket select thread + * + * + ***********************************************************************************/ + +#include <hardware/bluetooth.h> +#include <hardware/bt_sock.h> + +//bta_jv_co_rfc_data +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <time.h> +#include <fcntl.h> +#include <unistd.h> +#include <signal.h> +#include <pthread.h> +#include <ctype.h> + +#include <sys/select.h> +#include <sys/poll.h> +#include <cutils/sockets.h> + +#define LOG_TAG "BTIF_SOCK" +#include "btif_common.h" +#include "btif_util.h" + +#include "bd.h" + +#include "bta_api.h" +#include "btif_sock.h" +#include "btif_sock_thread.h" +#include "btif_sock_util.h" + +#include <cutils/log.h> +#define info(fmt, ...) LOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define debug(fmt, ...) LOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define error(fmt, ...) LOGE ("## ERROR : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__) +#define asrt(s) if(!(s)) LOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__) +#define print_events(events) do { \ + debug("print poll event:%x", events); \ + if (events & POLLIN) debug( " POLLIN "); \ + if (events & POLLPRI) debug( " POLLPRI "); \ + if (events & POLLOUT) debug( " POLLOUT "); \ + if (events & POLLERR) debug( " POLLERR "); \ + if (events & POLLHUP) debug( " POLLHUP "); \ + if (events & POLLNVAL) debug(" POLLNVAL "); \ + if (events & POLLRDHUP) debug(" POLLRDHUP"); \ + } while(0) + +#define MAX_THREAD 8 +#define MAX_POLL 64 +#define POLL_EXCEPTION_EVENTS (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL) +#define IS_EXCEPTION(e) ((e) & POLL_EXCEPTION_EVENTS) +#define IS_READ(e) ((e) & POLLIN) +#define IS_WRITE(e) ((e) & POLLOUT) +/*cmd executes in socket poll thread */ +#define CMD_WAKEUP 1 +#define CMD_EXIT 2 +#define CMD_ADD_FD 3 + +typedef struct { + struct pollfd pfd; + uint32_t user_id; + int type; + int flags; +} poll_slot_t; +typedef struct { + int cmd_fdr, cmd_fdw; + int poll_count; + poll_slot_t ps[MAX_POLL]; + int psi[MAX_POLL]; //index of poll slot + volatile pid_t thread_id; + btsock_signaled_cb callback; + int used; +} thread_slot_t; +static thread_slot_t ts[MAX_THREAD]; + + + +static void *sock_poll_thread(void *arg); +static inline void close_cmd_fd(int h); + +static inline void add_poll(int h, int fd, int type, int flags, uint32_t user_id); + +static pthread_mutex_t thread_slot_lock; + + +static inline void set_socket_blocking(int s, int blocking) +{ + int opts; + opts = fcntl(s, F_GETFL); + if (opts<0) error("set blocking (%s)", strerror(errno)); + if(blocking) + opts &= ~O_NONBLOCK; + else opts |= O_NONBLOCK; + fcntl(s, F_SETFL, opts); +} + +static inline int create_server_socket(const char* name) +{ + int s = socket(AF_LOCAL, SOCK_STREAM, 0); + debug("covert name to android abstract name:%s", name); + if(socket_local_server_bind(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT) >= 0) + { + if(listen(s, 5) == 0) + { + debug("listen to local socket:%s, fd:%d", name, s); + return s; + } + else error("listen to local socket:%s, fd:%d failed, errno:%d", name, s, errno); + } + else error("create local socket:%s fd:%d, failed, errno:%d", name, s, errno); + close(s); + return -1; +} +static inline int connect_server_socket(const char* name) +{ + int s = socket(AF_LOCAL, SOCK_STREAM, 0); + set_socket_blocking(s, TRUE); + if(socket_local_client_connect(s, name, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) >= 0) + { + debug("connected to local socket:%s, fd:%d", name, s); + return s; + } + else error("connect to local socket:%s, fd:%d failed, errno:%d", name, s, errno); + close(s); + return -1; +} +static inline int accept_server_socket(int s) +{ + struct sockaddr_un client_address; + socklen_t clen; + int fd = accept(s, (struct sockaddr*)&client_address, &clen); + debug("accepted fd:%d for server fd:%d", fd, s); + return fd; +} +static inline pthread_t create_thread(void *(*start_routine)(void *), void * arg) +{ + pthread_attr_t thread_attr; + pthread_attr_init(&thread_attr); + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); + pthread_t thread_id = -1; + if( pthread_create(&thread_id, &thread_attr, start_routine, arg)!=0 ) + { + error("pthread_create : %s", strerror(errno)); + return -1; + } + return thread_id; +} +static void init_poll(int cmd_fd); +static int alloc_thread_slot() +{ + int i; + //revserd order to save guard uninitialized access to 0 index + for(i = MAX_THREAD - 1; i >=0; i--) + if(!ts[i].used) + return i; + error("execeeded max thread count"); + return -1; +} +static void free_thread_slot(int h) +{ + if(0 <= h && h < MAX_THREAD) + { + close_cmd_fd(h); + ts[h].used = 0; + } + else error("invalid thread handle:%d", h); +} +int btsock_thread_init() +{ + debug("in"); + init_slot_lock(&thread_slot_lock); + int h; + for(h = 0; h < MAX_THREAD; h++) + { + ts[h].cmd_fdr = ts[h].cmd_fdw = -1; + ts[h].used = 0; + ts[h].thread_id = -1; + ts[h].poll_count = 0; + ts[h].callback = NULL; + } + return TRUE; +} +int btsock_thread_create(btsock_signaled_cb callback) +{ + int ret = FALSE; + asrt(callback); + lock_slot(&thread_slot_lock); + int h = alloc_thread_slot(); + unlock_slot(&thread_slot_lock); + if(h >= 0) + { + init_poll(h); + if((ts[h].thread_id = create_thread(sock_poll_thread, (void*)h)) != -1) + { + ts[h].callback = callback; + } + else + { + free_thread_slot(h); + h = -1; + } + } + return h; +} + +/* create dummy socket pair used to wake up select loop */ +static inline void init_cmd_fd(int h) +{ + asrt(ts[h].cmd_fdr == -1 && ts[h].cmd_fdw == -1); + if(socketpair(AF_UNIX, SOCK_STREAM, 0, &ts[h].cmd_fdr) < 0) + { + error("socketpair failed: %s", strerror(errno)); + return; + } + debug("h:%d, cmd_fdr:%d, cmd_fdw:%d", h, ts[h].cmd_fdr, ts[h].cmd_fdw); + //add the cmd fd for read & write + add_poll(h, ts[h].cmd_fdr, 0, SOCK_THREAD_FD_RD, 0); +} +static inline void close_cmd_fd(int h) +{ + if(ts[h].cmd_fdr != -1) + { + close(ts[h].cmd_fdr); + ts[h].cmd_fdr = -1; + } + if(ts[h].cmd_fdw != -1) + { + close(ts[h].cmd_fdw); + ts[h].cmd_fdw = -1; + } +} +typedef struct +{ + int id; + int fd; + int type; + int flags; + uint32_t user_id; +} sock_cmd_t; +int btsock_thread_add_fd(int h, int fd, int type, int flags, uint32_t user_id) +{ + if(h < 0 || h >= MAX_THREAD) + { + error("invalid bt thread handle:%d", h); + return FALSE; + } + if(ts[h].cmd_fdw == -1) + { + error("cmd socket is not created. socket thread may not initialized"); + return FALSE; + } + if(flags & SOCK_THREAD_ADD_FD_SYNC) + { + //must executed in socket poll thread + asrt(ts[h].thread_id == gettid()); + //cleanup one-time flags + flags &= ~SOCK_THREAD_ADD_FD_SYNC; + add_poll(h, fd, type, flags, user_id); + return TRUE; + } + sock_cmd_t cmd = {CMD_ADD_FD, fd, type, flags, user_id}; + debug("adding fd:%d, flags:0x%x", fd, flags); + return send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd); +} + +int btsock_thread_wakeup(int h) +{ + if(h < 0 || h >= MAX_THREAD) + { + error("invalid bt thread handle:%d", h); + return FALSE; + } + if(ts[h].cmd_fdw == -1) + { + error("thread handle:%d, cmd socket is not created", h); + return FALSE; + } + sock_cmd_t cmd = {CMD_WAKEUP, 0, 0, 0, 0}; + return send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd); +} +int btsock_thread_exit(int h) +{ + if(h < 0 || h >= MAX_THREAD) + { + error("invalid bt thread handle:%d", h); + return FALSE; + } + if(ts[h].cmd_fdw == -1) + { + error("cmd socket is not created"); + return FALSE; + } + sock_cmd_t cmd = {CMD_EXIT, 0, 0, 0, 0}; + if(send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd)) + { + pthread_join(ts[h].thread_id, 0); + lock_slot(&thread_slot_lock); + free_thread_slot(h); + unlock_slot(&thread_slot_lock); + return TRUE; + } + return FALSE; +} +static void init_poll(int h) +{ + int i; + ts[h].used = 0; + ts[h].poll_count = 0; + ts[h].thread_id = -1; + ts[h].callback = NULL; + for(i = 0; i < MAX_POLL; i++) + { + ts[h].ps[i].pfd.fd = -1; + ts[h].psi[i] = -1; + } + init_cmd_fd(h); +} +static inline unsigned int flags2pevents(int flags) +{ + unsigned int pevents = 0; + if(flags & SOCK_THREAD_FD_WR) + pevents |= POLLOUT; + if(flags & SOCK_THREAD_FD_RD) + pevents |= POLLIN; + pevents |= POLL_EXCEPTION_EVENTS; + return pevents; +} + +static inline void set_poll(poll_slot_t* ps, int fd, int type, int flags, uint32_t user_id) +{ + ps->pfd.fd = fd; + ps->user_id = user_id; + if(ps->type != 0 && ps->type != type) + error("poll socket type should not changed! type was:%d, type now:%d", ps->type, type); + ps->type = type; + ps->flags = flags; + ps->pfd.events = flags2pevents(flags); + ps->pfd.revents = 0; +} +static inline void add_poll(int h, int fd, int type, int flags, uint32_t user_id) +{ + asrt(fd != -1); + int i; + int empty = -1; + poll_slot_t* ps = ts[h].ps; + + for(i = 0; i < MAX_POLL; i++) + { + if(ps[i].pfd.fd == fd) + { + debug("update fd poll, count:%d, slot:%d, fd:%d, \ + type was:%d, now:%d; flags was:%x, now:%x; user_id was:%d, now:%d", + ts[h].poll_count, i, fd, ps[i].type, type, ps[i].flags, flags, ps[i].user_id, user_id); + asrt(ts[h].poll_count < MAX_POLL); + + set_poll(&ps[i], fd, type, flags | ps[i].flags, user_id); + return; + } + else if(empty < 0 && ps[i].pfd.fd == -1) + empty = i; + } + if(empty >= 0) + { + asrt(ts[h].poll_count < MAX_POLL); + set_poll(&ps[empty], fd, type, flags, user_id); + ++ts[h].poll_count; + debug("add new fd poll, count:%d, slot:%d, fd:%d, type:%d; flags:%x; user_id:%d", + ts[h].poll_count, empty, fd, type, flags, user_id); + return; + } + error("exceeded max poll slot:%d!", MAX_POLL); +} +static inline void remove_poll(int h, poll_slot_t* ps, int flags) +{ + if(flags == ps->flags) + { + //all monitored events signaled. To remove it, just clear the slot + --ts[h].poll_count; + debug("remove poll, count:%d, fd:%d, flags:%x", ts[h].poll_count, ps->pfd.fd, ps->flags); + memset(ps, 0, sizeof(*ps)); + ps->pfd.fd = -1; + } + else + { + //one read or one write monitor event signaled, removed the accordding bit + debug("remove poll flag, count:%d, fd:%d, flags signaled:%x, poll flags was:%x, new:%x", + ts[h].poll_count, ps->pfd.fd, flags, ps->flags, ps->flags & (~flags)); + ps->flags &= ~flags; + //update the poll events mask + ps->pfd.events = flags2pevents(ps->flags); + } +} +static int process_cmd_sock(int h) +{ + sock_cmd_t cmd = {-1, 0, 0, 0, 0}; + int fd = ts[h].cmd_fdr; + if(recv(fd, &cmd, sizeof(cmd), MSG_WAITALL) != sizeof(cmd)) + { + error("recv cmd errno:%d", errno); + return FALSE; + } + debug("cmd.id:%d", cmd.id); + switch(cmd.id) + { + case CMD_ADD_FD: + debug("CMD_ADD_FD, fd:%d, flags:%d", cmd.fd, cmd.flags); + add_poll(h, cmd.fd, cmd.type, cmd.flags, cmd.user_id); + break; + case CMD_WAKEUP: + debug("CMD_WAKEUP"); + break; + case CMD_EXIT: + debug("CMD_EXIT"); + return FALSE; + default: + debug("unknown cmd: %d", cmd.id); + break; + } + return TRUE; +} +static void process_data_sock(int h, struct pollfd *pfds, int count) +{ + debug("in, poll count:%d ts[h].poll_count:%d", count, ts[h].poll_count); + asrt(count <= ts[h].poll_count); + int i; + for( i= 1; i < ts[h].poll_count; i++) + { + if(pfds[i].revents) + { + int ps_i = ts[h].psi[i]; + asrt(pfds[i].fd == ts[h].ps[ps_i].pfd.fd); + uint32_t user_id = ts[h].ps[ps_i].user_id; + int type = ts[h].ps[ps_i].type; + int flags = 0; + debug("signaled data fd:%d, start print poll revents[", pfds[i].fd); + print_events(pfds[i].revents); + debug("signaled data fd:%d, end print poll revents]", pfds[i].fd); + if(IS_READ(pfds[i].revents)) + { + debug("read event signaled, fd:%d, user_id:%d", pfds[i].fd, user_id); + flags |= SOCK_THREAD_FD_RD; + } + if(IS_WRITE(pfds[i].revents)) + { + debug("write event signaled, fd:%d, user_id:%d", pfds[i].fd, user_id); + flags |= SOCK_THREAD_FD_WR; + } + if(IS_EXCEPTION(pfds[i].revents)) + { + debug("exception event signaled, fd:%d, user_id:%d", pfds[i].fd, user_id); + flags |= SOCK_THREAD_FD_EXCEPTION; + //remove the whole slot not flags + remove_poll(h, &ts[h].ps[ps_i], ts[h].ps[ps_i].flags); + } + else if(flags) + remove_poll(h, &ts[h].ps[ps_i], flags); //remove the monitor flags that already processed + if(flags) + ts[h].callback(pfds[i].fd, type, flags, user_id); + } + } + debug("out"); +} +static void prepare_poll_fds(int h, struct pollfd* pfds) +{ + int count = 0; + int ps_i = 0; + int pfd_i = 0; + asrt(ts[h].poll_count <= MAX_POLL); + memset(pfds, 0, sizeof(pfds[0])*ts[h].poll_count); + while(count < ts[h].poll_count) + { + if(ps_i >= MAX_POLL) + { + error("exceed max poll range, ps_i:%d, MAX_POLL:%d, count:%d, ts[h].poll_count:%d", + ps_i, MAX_POLL, count, ts[h].poll_count); + return; + } + if(ts[h].ps[ps_i].pfd.fd >= 0) + { + pfds[pfd_i] = ts[h].ps[ps_i].pfd; + ts[h].psi[pfd_i] = ps_i; + count++; + pfd_i++; + } + ps_i++; + } +} +static void *sock_poll_thread(void *arg) +{ + struct pollfd pfds[MAX_POLL]; + memset(pfds, 0, sizeof(pfds)); + int h = (int)arg; + for(;;) + { + prepare_poll_fds(h, pfds); + debug("call poll, thread handle:%d, cmd fd read:%d, ts[h].poll_count:%d", + h, ts[h].cmd_fdr, ts[h].poll_count); + int ret = poll(pfds, ts[h].poll_count, -1); + if(ret == -1) + { + error("poll ret -1, exit the thread, errno:%d, err:%s", errno, strerror(errno)); + debug("ts[h].poll_count:%d", ts[h].poll_count); + break; + } + if(ret != 0) + { + debug("select wake up, ret:%d, ts[h].poll_count:%d", ret, ts[h].poll_count); + int need_process_data_fd = TRUE; + if(pfds[0].revents) //cmd fd always is the first one + { + debug("signaled cmd_fd:%d, start print poll revents[", pfds[0].fd); + print_events(pfds[0].revents); + debug("signaled cmd_fd:%d, end print poll revents]", pfds[0].fd); + asrt(pfds[0].fd == ts[h].cmd_fdr); + if(!process_cmd_sock(h)) + { + debug("process_cmd_sock failed, exit..."); + break; + } + if(ret == 1) + need_process_data_fd = FALSE; + else ret--; //exclude the cmd fd + } + if(need_process_data_fd) + process_data_sock(h, pfds, ret); + } + else debug("no data, select ret: %d", ret); + } + ts[h].thread_id = -1; + debug("socket poll thread exiting"); + return 0; +} + diff --git a/btif/src/btif_sock_util.c b/btif/src/btif_sock_util.c new file mode 100644 index 0000000..0e81e75 --- /dev/null +++ b/btif/src/btif_sock_util.c @@ -0,0 +1,295 @@ +/************************************************************************************ + * + * 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. + * + ************************************************************************************/ + + +/************************************************************************************ + * + * Filename: btif_hf.c + * + * Description: Handsfree Profile Bluetooth Interface + * + * + ***********************************************************************************/ +#include <hardware/bluetooth.h> +#include <hardware/bt_sock.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <sys/ioctl.h> + +#include <cutils/sockets.h> +#include <netinet/tcp.h> + + +#define LOG_TAG "BTIF_SOCK" +#include "btif_common.h" +#include "btif_util.h" + +#include "bd.h" + +#include "bta_api.h" +#include "btif_sock_thread.h" +#include "btif_sock_sdp.h" + +#include "bt_target.h" +#include "gki.h" +#include "hcimsgs.h" +#include "sdp_api.h" +#include "btu.h" +#include "btm_api.h" +#include "btm_int.h" +#include "bta_jv_api.h" +#include "bta_jv_co.h" +#include "port_api.h" + +#include <cutils/log.h> + +#define info(fmt, ...) LOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define debug(fmt, ...) LOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define error(fmt, ...) LOGE ("## ERROR : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__) +#define asrt(s) if(!(s)) LOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__) + + +int sock_send_all(int sock_fd, const uint8_t* buf, int len) +{ + int s = len; + int ret; + while(s) + { + do ret = send(sock_fd, buf, s, 0); + while(ret < 0 && errno == EINTR); + if(ret < 0) + { + error("sock fd:%d send errno:%d", sock_fd, errno); + return -1; + } + buf += ret; + s -= ret; + } + return len; +} +int sock_recv_all(int sock_fd, uint8_t* buf, int len) +{ + int r = len; + int ret = -1; + while(r) + { + do ret = recv(sock_fd, buf, r, MSG_WAITALL); + while(ret < 0 && errno == EINTR); + if(ret < 0) + { + error("sock fd:%d recv errno:%d", sock_fd, errno); + return -1; + } + buf += ret; + r -= ret; + } + return len; +} + +int sock_send_fd(int sock_fd, const uint8_t* buf, int len, int send_fd) +{ + ssize_t ret; + struct msghdr msg; + unsigned char *buffer = (unsigned char *)buf; + memset(&msg, 0, sizeof(msg)); + + struct cmsghdr *cmsg; + char msgbuf[CMSG_SPACE(1)]; + asrt(send_fd != -1); + if(sock_fd == -1 || send_fd == -1) + return -1; + // Add any pending outbound file descriptors to the message + // See "man cmsg" really + msg.msg_control = msgbuf; + msg.msg_controllen = sizeof msgbuf; + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof send_fd); + memcpy(CMSG_DATA(cmsg), &send_fd, sizeof send_fd); + + // We only write our msg_control during the first write + int ret_len = len; + while (len > 0) { + struct iovec iv; + memset(&iv, 0, sizeof(iv)); + + iv.iov_base = buffer; + iv.iov_len = len; + + msg.msg_iov = &iv; + msg.msg_iovlen = 1; + + do { + ret = sendmsg(sock_fd, &msg, MSG_NOSIGNAL); + } while (ret < 0 && errno == EINTR); + + if (ret < 0) { + error("fd:%d, send_fd:%d, sendmsg ret:%d, errno:%d, %s", + sock_fd, send_fd, (int)ret, errno, strerror(errno)); + ret_len = -1; + break; + } + + buffer += ret; + len -= ret; + + // Wipes out any msg_control too + memset(&msg, 0, sizeof(msg)); + } + debug("close fd:%d after sent", send_fd); + close(send_fd); + return ret_len; +} + + +#define PRINT(s) __android_log_write(ANDROID_LOG_DEBUG, NULL, s) +static const char* hex_table = "0123456789abcdef"; +static inline void byte2hex(const char* data, char** str) +{ + **str = hex_table[(*data >> 4) & 0xf]; + ++*str; + **str = hex_table[*data & 0xf]; + ++*str; +} +static inline void byte2char(const char* data, char** str) +{ + **str = *data < ' ' ? '.' : *data > '~' ? '.' : *data; + ++(*str); +} +static inline void word2hex(const char* data, char** hex) +{ + byte2hex(&data[1], hex); + byte2hex(&data[0], hex); +} +void dump_bin(const char* title, const char* data, int size) +{ + char line_buff[256]; + char *line; + int i, j, addr; + const int width = 16; + LOGD("%s, size:%d, dump started {", title, size); + if(size <= 0) + return; + //write offset + line = line_buff; + *line++ = ' '; + *line++ = ' '; + *line++ = ' '; + *line++ = ' '; + *line++ = ' '; + *line++ = ' '; + for(j = 0; j < width; j++) + { + byte2hex((const char*)&j, &line); + *line++ = ' '; + } + *line = 0; + PRINT(line_buff); + + for(i = 0; i < size / width; i++) + { + line = line_buff; + //write address: + addr = i*width; + word2hex((const char*)&addr, &line); + *line++ = ':'; *line++ = ' '; + //write hex of data + for(j = 0; j < width; j++) + { + byte2hex(&data[j], &line); + *line++ = ' '; + } + //write char of data + for(j = 0; j < width; j++) + byte2char(data++, &line); + //wirte the end of line + *line = 0; + //output the line + PRINT(line_buff); + } + //last line of left over if any + int leftover = size % width; + if(leftover > 0) + { + line = line_buff; + //write address: + addr = i*width; + word2hex((const char*)&addr, &line); + *line++ = ':'; *line++ = ' '; + //write hex of data + for(j = 0; j < leftover; j++) { + byte2hex(&data[j], &line); + *line++ = ' '; + } + //write hex padding + for(; j < width; j++) { + *line++ = ' '; + *line++ = ' '; + *line++ = ' '; + } + //write char of data + for(j = 0; j < leftover; j++) + byte2char(data++, &line); + //write the end of line + *line = 0; + //output the line + PRINT(line_buff); + } + LOGD("%s, size:%d, dump ended }", title, size); +} + diff --git a/main/Android.mk b/main/Android.mk index 816fb6f..0de4afc 100755 --- a/main/Android.mk +++ b/main/Android.mk @@ -10,13 +10,13 @@ include $(CLEAR_VARS) # HAL layer LOCAL_SRC_FILES:= \ - ../btif/src/bluetooth.c + ../btif/src/bluetooth.c # platform specific LOCAL_SRC_FILES+= \ bte_main.c \ - bte_init.c \ - bte_version.c \ + bte_init.c \ + bte_version.c \ bte_logmsg.c \ bte_conf.c @@ -32,7 +32,12 @@ LOCAL_SRC_FILES += \ ../btif/src/btif_rc.c \ ../btif/src/btif_media_task.c \ ../btif/src/btif_hh.c \ - ../btif/src/btif_hl.c + ../btif/src/btif_hl.c \ + ../btif/src/btif_sock.c \ + ../btif/src/btif_sock_rfc.c \ + ../btif/src/btif_sock_thread.c \ + ../btif/src/btif_sock_sdp.c \ + ../btif/src/btif_sock_util.c # callouts LOCAL_SRC_FILES+= \ @@ -46,20 +51,20 @@ LOCAL_SRC_FILES+= \ # sbc encoder LOCAL_SRC_FILES+= \ - ../embdrv/sbc/encoder/srce/sbc_analysis.c \ - ../embdrv/sbc/encoder/srce/sbc_dct.c \ - ../embdrv/sbc/encoder/srce/sbc_dct_coeffs.c \ - ../embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c \ - ../embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c \ - ../embdrv/sbc/encoder/srce/sbc_enc_coeffs.c \ - ../embdrv/sbc/encoder/srce/sbc_encoder.c \ - ../embdrv/sbc/encoder/srce/sbc_packing.c \ + ../embdrv/sbc/encoder/srce/sbc_analysis.c \ + ../embdrv/sbc/encoder/srce/sbc_dct.c \ + ../embdrv/sbc/encoder/srce/sbc_dct_coeffs.c \ + ../embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c \ + ../embdrv/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c \ + ../embdrv/sbc/encoder/srce/sbc_enc_coeffs.c \ + ../embdrv/sbc/encoder/srce/sbc_encoder.c \ + ../embdrv/sbc/encoder/srce/sbc_packing.c \ # candidates for vendor lib (keep here for now) LOCAL_SRC_FILES+= \ - ../udrv/ulinux/unv_linux.c\ - ../udrv/ulinux/uipc.c + ../udrv/ulinux/unv_linux.c\ + ../udrv/ulinux/uipc.c LOCAL_C_INCLUDES+= . \ diff --git a/stack/include/port_api.h b/stack/include/port_api.h index 26e0299..b7a7417 100644 --- a/stack/include/port_api.h +++ b/stack/include/port_api.h @@ -17,11 +17,11 @@ ** Constants and Types *****************************************************************************/ -/* -** Define port settings structure send from the application in the +/* +** Define port settings structure send from the application in the ** set settings request, or to the application in the set settings indication. */ -typedef struct +typedef struct { #define PORT_BAUD_RATE_2400 0x00 @@ -79,11 +79,17 @@ typedef struct } tPORT_STATE; -/* +/* ** Define the callback function prototypes. Parameters are specific -** to each event and are described bellow +** to each event and are described bellow */ typedef int (tPORT_DATA_CALLBACK) (UINT16 port_handle, void *p_data, UINT16 len); + +#define DATA_CO_CALLBACK_TYPE_INCOMING 1 +#define DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE 2 +#define DATA_CO_CALLBACK_TYPE_OUTGOING 3 +typedef int (tPORT_DATA_CO_CALLBACK) (UINT16 port_handle, UINT8* p_buf, UINT16 len, int type); + typedef void (tPORT_CALLBACK) (UINT32 code, UINT16 port_handle); /* @@ -112,7 +118,7 @@ typedef void (tPORT_CALLBACK) (UINT32 code, UINT16 port_handle); #define PORT_EV_FCS 0x00020000 /* data flow enable status true = enabled */ /* -** To register for events application should provide bitmask with +** To register for events application should provide bitmask with ** corresponding bit set */ @@ -125,7 +131,7 @@ typedef void (tPORT_CALLBACK) (UINT32 code, UINT16 port_handle); /* -** Define port result codes +** Define port result codes */ #define PORT_SUCCESS 0 @@ -169,18 +175,18 @@ extern "C" ** ** Function RFCOMM_CreateConnection ** -** Description RFCOMM_CreateConnection function is used from the application -** to establish serial port connection to the peer device, -** or allow RFCOMM to accept a connection from the peer -** application. +** Description RFCOMM_CreateConnection function is used from the application +** to establish serial port connection to the peer device, +** or allow RFCOMM to accept a connection from the peer +** application. ** -** Parameters: scn - Service Channel Number as registered with -** the SDP (server) or obtained using SDP from +** Parameters: scn - Service Channel Number as registered with +** the SDP (server) or obtained using SDP from ** the peer device (client). ** is_server - TRUE if requesting application is a server ** mtu - Maximum frame size the application can accept ** bd_addr - BD_ADDR of the peer (client) -** mask - specifies events to be enabled. A value +** mask - specifies events to be enabled. A value ** of zero disables all events. ** p_handle - OUT pointer to the handle. ** p_mgmt_cb - pointer to callback function to receive @@ -220,7 +226,7 @@ RFC_API extern int RFCOMM_RemoveConnection (UINT16 handle); ** ** Description This function is called to close the server port. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** *******************************************************************************/ RFC_API extern int RFCOMM_RemoveServer (UINT16 handle); @@ -233,8 +239,8 @@ RFC_API extern int RFCOMM_RemoveServer (UINT16 handle); ** Description Set event callback the specified connection. ** ** Parameters: handle - Handle of the port returned in the Open -** p_callback - address of the callback function which should -** be called from the RFCOMM when an event +** p_callback - address of the callback function which should +** be called from the RFCOMM when an event ** specified in the mask occurs. ** *******************************************************************************/ @@ -249,15 +255,15 @@ RFC_API extern int PORT_SetEventCallback (UINT16 port_handle, ** Description Set event data callback the specified connection. ** ** Parameters: handle - Handle of the port returned in the Open -** p_callback - address of the callback function which should -** be called from the RFCOMM when a data +** p_callback - address of the callback function which should +** be called from the RFCOMM when a data ** packet is received. ** *******************************************************************************/ RFC_API extern int PORT_SetDataCallback (UINT16 port_handle, tPORT_DATA_CALLBACK *p_cb); - +RFC_API extern int PORT_SetDataCOCallback (UINT16 port_handle, tPORT_DATA_CO_CALLBACK *p_port_cb); /******************************************************************************* ** ** Function PORT_SetEventMask @@ -265,7 +271,7 @@ RFC_API extern int PORT_SetDataCallback (UINT16 port_handle, ** Description This function is called to close the specified connection. ** ** Parameters: handle - Handle of the port returned in the Open -** mask - specifies events to be enabled. A value +** mask - specifies events to be enabled. A value ** of zero disables all events. ** *******************************************************************************/ @@ -304,11 +310,11 @@ RFC_API extern BOOLEAN PORT_IsOpening (BD_ADDR bd_addr); ** ** Function PORT_SetState ** -** Description This function configures connection according to the +** Description This function configures connection according to the ** specifications in the tPORT_STATE structure. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection -** p_settings - Pointer to a tPORT_STATE structure containing +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** p_settings - Pointer to a tPORT_STATE structure containing ** configuration information for the connection. ** *******************************************************************************/ @@ -320,7 +326,7 @@ RFC_API extern int PORT_SetState (UINT16 handle, tPORT_STATE *p_settings); ** ** Description This function return number of buffers on the rx queue. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** p_rx_queue_count - Pointer to return queue count in. ** *******************************************************************************/ @@ -333,7 +339,7 @@ RFC_API extern int PORT_GetRxQueueCnt (UINT16 handle, UINT16 *p_rx_queue_count); ** Description This function is called to fill tPORT_STATE structure ** with the current control settings for the port ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** p_settings - Pointer to a tPORT_STATE structure in which ** configuration information is returned. ** @@ -345,10 +351,10 @@ RFC_API extern int PORT_GetState (UINT16 handle, tPORT_STATE *p_settings); ** ** Function PORT_Control ** -** Description This function directs a specified connection to pass control +** Description This function directs a specified connection to pass control ** control information to the peer device. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** signal - specify the function to be passed ** *******************************************************************************/ @@ -369,11 +375,11 @@ RFC_API extern int PORT_Control (UINT16 handle, UINT8 signal); ** ** Function PORT_FlowControl ** -** Description This function directs a specified connection to pass -** flow control message to the peer device. Enable flag passed +** Description This function directs a specified connection to pass +** flow control message to the peer device. Enable flag passed ** shows if port can accept more data. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** enable - enables data flow ** *******************************************************************************/ @@ -384,12 +390,12 @@ RFC_API extern int PORT_FlowControl (UINT16 handle, BOOLEAN enable); ** ** Function PORT_GetModemStatus ** -** Description This function retrieves modem control signals. Normally -** application will call this function after a callback -** function is called with notification that one of signals +** Description This function retrieves modem control signals. Normally +** application will call this function after a callback +** function is called with notification that one of signals ** has been changed. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** callback. ** p_signal - specify the pointer to control signals info ** @@ -415,14 +421,14 @@ RFC_API extern int PORT_GetModemStatus (UINT16 handle, UINT8 *p_control_signal); ** Function PORT_ClearError ** ** Description This function retreives information about a communications -** error and reports current status of a connection. The +** error and reports current status of a connection. The ** function should be called when an error occures to clear ** the connection error flag and to enable additional read ** and write operations. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** p_errors - pointer of the variable to receive error codes -** p_status - pointer to the tPORT_STATUS structur to receive +** p_status - pointer to the tPORT_STATUS structur to receive ** connection status ** *******************************************************************************/ @@ -456,7 +462,7 @@ RFC_API extern int PORT_ClearError (UINT16 handle, UINT16 *p_errors, ** ** Description This function send a communications error to the peer device ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** errors - receive error codes ** *******************************************************************************/ @@ -467,10 +473,10 @@ RFC_API extern int PORT_SendError (UINT16 handle, UINT8 errors); ** ** Function PORT_GetQueueStatus ** -** Description This function reports current status of a connection. +** Description This function reports current status of a connection. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection -** p_status - pointer to the tPORT_STATUS structur to receive +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** p_status - pointer to the tPORT_STATUS structur to receive ** connection status ** *******************************************************************************/ @@ -481,11 +487,11 @@ RFC_API extern int PORT_GetQueueStatus (UINT16 handle, tPORT_STATUS *p_status); ** ** Function PORT_Purge ** -** Description This function discards all the data from the output or +** Description This function discards all the data from the output or ** input queues of the specified connection. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection -** purge_flags - specify the action to take. +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** purge_flags - specify the action to take. ** *******************************************************************************/ #define PORT_PURGE_TXCLEAR 0x01 @@ -498,15 +504,15 @@ RFC_API extern int PORT_Purge (UINT16 handle, UINT8 purge_flags); ** ** Function PORT_Read ** -** Description This function returns the pointer to the buffer received -** from the peer device. Normally application will call this -** function after receiving PORT_EVT_RXCHAR event. +** Description This function returns the pointer to the buffer received +** from the peer device. Normally application will call this +** function after receiving PORT_EVT_RXCHAR event. ** Application calling this function is responsible to free ** buffer returned. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** callback. -** pp_buf - pointer to address of buffer with data, +** pp_buf - pointer to address of buffer with data, ** *******************************************************************************/ RFC_API extern int PORT_Read (UINT16 handle, BT_HDR **pp_buf); @@ -519,7 +525,7 @@ RFC_API extern int PORT_Read (UINT16 handle, BT_HDR **pp_buf); ** Description Normally application will call this function after receiving ** PORT_EVT_RXCHAR event. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** callback. ** p_data - Data area ** max_len - Byte count requested @@ -537,8 +543,8 @@ RFC_API extern int PORT_ReadData (UINT16 handle, char *p_data, UINT16 max_len, ** Description This function to send BT buffer to the peer device. ** Application should not free the buffer. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection -** p_buf - pointer to the buffer with data, +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** p_buf - pointer to the buffer with data, ** *******************************************************************************/ RFC_API extern int PORT_Write (UINT16 handle, BT_HDR *p_buf); @@ -548,10 +554,10 @@ RFC_API extern int PORT_Write (UINT16 handle, BT_HDR *p_buf); ** ** Function PORT_WriteData ** -** Description This function is called from the legacy application to -** send data. +** Description This function is called from the legacy application to +** send data. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** p_data - Data area ** max_len - Byte count to write ** p_len - Bytes written @@ -560,6 +566,17 @@ RFC_API extern int PORT_Write (UINT16 handle, BT_HDR *p_buf); RFC_API extern int PORT_WriteData (UINT16 handle, char *p_data, UINT16 max_len, UINT16 *p_len); +/******************************************************************************* +** +** Function PORT_WriteDataCO +** +** Description Normally not GKI aware application will call this function +** to send data to the port by callout functions. +** +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** +*******************************************************************************/ +RFC_API extern int PORT_WriteDataCO (UINT16 handle, int* p_len); /******************************************************************************* ** diff --git a/stack/include/sdp_api.h b/stack/include/sdp_api.h index 00de801..e4774c3 100644 --- a/stack/include/sdp_api.h +++ b/stack/include/sdp_api.h @@ -68,6 +68,7 @@ /* Define a callback function for when discovery is complete. */ typedef void (tSDP_DISC_CMPL_CB) (UINT16 result); +typedef void (tSDP_DISC_CMPL_CB2) (UINT16 result, void* user_data); typedef struct { @@ -138,14 +139,14 @@ typedef struct }tSDP_DISCOVERY_DB; /* This structure is used to add protocol lists and find protocol elements */ -typedef struct +typedef struct { UINT16 protocol_uuid; UINT16 num_params; UINT16 params[SDP_MAX_PROTOCOL_PARAMS]; } tSDP_PROTOCOL_ELEM; -typedef struct +typedef struct { UINT16 num_elems; tSDP_PROTOCOL_ELEM list_elem[SDP_MAX_LIST_ELEMS]; @@ -160,7 +161,7 @@ typedef struct t_sdp_di_record UINT16 vendor_id_source; UINT16 product; UINT16 version; - BOOLEAN primary_record; + BOOLEAN primary_record; char client_executable_url[SDP_MAX_ATTR_LEN]; /* optional */ char service_description[SDP_MAX_ATTR_LEN]; /* optional */ char documentation_url[SDP_MAX_ATTR_LEN]; /* optional */ @@ -203,9 +204,9 @@ SDP_API extern BOOLEAN SDP_InitDiscoveryDb (tSDP_DISCOVERY_DB *p_db, UINT32 len, ** ** Function SDP_CancelServiceSearch ** -** Description This function cancels an active query to an SDP server. +** Description This function cancels an active query to an SDP server. ** -** Returns TRUE if discovery cancelled, FALSE if a matching activity is not found. +** Returns TRUE if discovery cancelled, FALSE if a matching activity is not found. ** *******************************************************************************/ SDP_API extern BOOLEAN SDP_CancelServiceSearch (tSDP_DISCOVERY_DB *p_db); @@ -214,9 +215,9 @@ SDP_API extern BOOLEAN SDP_CancelServiceSearch (tSDP_DISCOVERY_DB *p_db); ** ** Function SDP_ServiceSearchRequest ** -** Description This function queries an SDP server for information. +** Description This function queries an SDP server for information. ** -** Returns TRUE if discovery started, FALSE if failed. +** Returns TRUE if discovery started, FALSE if failed. ** *******************************************************************************/ SDP_API extern BOOLEAN SDP_ServiceSearchRequest (UINT8 *p_bd_addr, @@ -228,19 +229,36 @@ SDP_API extern BOOLEAN SDP_ServiceSearchRequest (UINT8 *p_bd_addr, ** ** Function SDP_ServiceSearchAttributeRequest ** -** Description This function queries an SDP server for information. +** Description This function queries an SDP server for information. ** ** The difference between this API function and the function -** SDP_ServiceSearchRequest is that this one does a +** SDP_ServiceSearchRequest is that this one does a ** combined ServiceSearchAttributeRequest SDP function. ** -** Returns TRUE if discovery started, FALSE if failed. +** Returns TRUE if discovery started, FALSE if failed. ** *******************************************************************************/ SDP_API extern BOOLEAN SDP_ServiceSearchAttributeRequest (UINT8 *p_bd_addr, tSDP_DISCOVERY_DB *p_db, tSDP_DISC_CMPL_CB *p_cb); +/******************************************************************************* +** +** Function SDP_ServiceSearchAttributeRequest2 +** +** Description This function queries an SDP server for information. +** +** The difference between this API function and the function +** SDP_ServiceSearchRequest is that this one does a +** combined ServiceSearchAttributeRequest SDP function with the +** user data piggyback +** +** Returns TRUE if discovery started, FALSE if failed. +** +*******************************************************************************/ +SDP_API extern BOOLEAN SDP_ServiceSearchAttributeRequest2 (UINT8 *p_bd_addr, + tSDP_DISCOVERY_DB *p_db, + tSDP_DISC_CMPL_CB2 *p_cb, void * user_data); /* API of utilities to find data in the local discovery database */ @@ -351,7 +369,7 @@ SDP_API extern BOOLEAN SDP_FindAddProtoListsElemInRec (tSDP_DISC_REC *p_rec, ** ** Description This function looks at a specific discovery record for the ** Profile list descriptor, and pulls out the version number. -** The version number consists of an 8-bit major version and +** The version number consists of an 8-bit major version and ** an 8-bit minor version. ** ** Returns TRUE if found, FALSE if not @@ -568,7 +586,7 @@ SDP_API extern BOOLEAN SDP_DeleteAttribute (UINT32 handle, UINT16 attr_id); ** ** Function SDP_SetLocalDiRecord ** -** Description This function adds a DI record to the local SDP database. +** Description This function adds a DI record to the local SDP database. ** ** Returns Returns SDP_SUCCESS if record added successfully, else error ** @@ -622,7 +640,7 @@ SDP_API extern UINT8 SDP_GetNumDiRecords (tSDP_DISCOVERY_DB *p_db); ** Function SDP_GetDiRecord ** ** Description This function retrieves a remote device's DI record from -** the specified database. +** the specified database. ** ** Returns SDP_SUCCESS if record retrieved, else error ** @@ -649,7 +667,7 @@ SDP_API extern UINT8 SDP_SetTraceLevel (UINT8 new_level); ** Function SDP_ConnOpen ** ** Description This function creates a connection to the SDP server on the -** given device. +** given device. ** ** Returns 0, if failed to initiate connection. Otherwise, the handle. ** @@ -663,7 +681,7 @@ SDP_API UINT32 SDP_ConnOpen (UINT8 *p_bd_addr, tSDP_DISC_RES_CB *p_rcb, ** ** Description This function sends data to the connected SDP server. ** -** Returns TRUE if data is sent, FALSE if failed. +** Returns TRUE if data is sent, FALSE if failed. ** *******************************************************************************/ SDP_API BOOLEAN SDP_WriteData (UINT32 handle, BT_HDR *p_msg); @@ -676,7 +694,7 @@ SDP_API BOOLEAN SDP_WriteData (UINT32 handle, BT_HDR *p_msg); ** ** Parameters: handle - Handle of the connection returned by SDP_ConnOpen ** -** Returns TRUE if connection is closed, FALSE if failed to find the handle. +** Returns TRUE if connection is closed, FALSE if failed to find the handle. ** *******************************************************************************/ SDP_API BOOLEAN SDP_ConnClose (UINT32 handle); @@ -690,7 +708,7 @@ SDP_API BOOLEAN SDP_ConnClose (UINT32 handle); ** ** Parameters: p_rec - pointer to a SDP record. ** -** Returns TRUE if found, otherwise FALSE. +** Returns TRUE if found, otherwise FALSE. ** *******************************************************************************/ SDP_API BOOLEAN SDP_FindServiceUUIDInRec(tSDP_DISC_REC *p_rec, tBT_UUID *p_uuid); diff --git a/stack/rfcomm/port_api.c b/stack/rfcomm/port_api.c index fe023a4..50da558 100644 --- a/stack/rfcomm/port_api.c +++ b/stack/rfcomm/port_api.c @@ -24,22 +24,28 @@ /* duration of break in 200ms units */ #define PORT_BREAK_DURATION 1 +#include <cutils/log.h> +#define info(fmt, ...) LOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define debug(fmt, ...) LOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define error(fmt, ...) LOGE ("## ERROR : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__) +#define asrt(s) if(!(s)) LOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__) + /******************************************************************************* ** ** Function RFCOMM_CreateConnection ** -** Description RFCOMM_CreateConnection function is used from the application -** to establish serial port connection to the peer device, -** or allow RFCOMM to accept a connection from the peer -** application. +** Description RFCOMM_CreateConnection function is used from the application +** to establish serial port connection to the peer device, +** or allow RFCOMM to accept a connection from the peer +** application. ** -** Parameters: scn - Service Channel Number as registered with -** the SDP (server) or obtained using SDP from +** Parameters: scn - Service Channel Number as registered with +** the SDP (server) or obtained using SDP from ** the peer device (client). ** is_server - TRUE if requesting application is a server ** mtu - Maximum frame size the application can accept ** bd_addr - BD_ADDR of the peer (client) -** mask - specifies events to be enabled. A value +** mask - specifies events to be enabled. A value ** of zero disables all events. ** p_handle - OUT pointer to the handle. ** p_mgmt_cb - pointer to callback function to receive @@ -55,8 +61,8 @@ ** (scn * 2 + 1) dlci. ** *******************************************************************************/ -int RFCOMM_CreateConnection (UINT16 uuid, UINT8 scn, BOOLEAN is_server, - UINT16 mtu, BD_ADDR bd_addr, UINT16 *p_handle, +int RFCOMM_CreateConnection (UINT16 uuid, UINT8 scn, BOOLEAN is_server, + UINT16 mtu, BD_ADDR bd_addr, UINT16 *p_handle, tPORT_CALLBACK *p_mgmt_cb) { tPORT *p_port; @@ -65,7 +71,7 @@ int RFCOMM_CreateConnection (UINT16 uuid, UINT8 scn, BOOLEAN is_server, tRFC_MCB *p_mcb = port_find_mcb (bd_addr); UINT16 rfcomm_mtu; - RFCOMM_TRACE_API3 ("RFCOMM_CreateConnection() called SCN: %d is_server:%d mtu:%d", + RFCOMM_TRACE_API3 ("RFCOMM_CreateConnection() called SCN: %d is_server:%d mtu:%d", scn, is_server, mtu); RFCOMM_TRACE_API6 ("RFCOMM_CreateConnection() BDA: %02x-%02x-%02x-%02x-%02x-%02x", bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]); @@ -93,7 +99,7 @@ int RFCOMM_CreateConnection (UINT16 uuid, UINT8 scn, BOOLEAN is_server, /* if existing port is also a client port */ if (p_port->is_server == FALSE) { - RFCOMM_TRACE_ERROR3 ("RFCOMM_CreateConnection - already opened state:%d, RFC state:%d, MCB state:%d", + RFCOMM_TRACE_ERROR3 ("RFCOMM_CreateConnection - already opened state:%d, RFC state:%d, MCB state:%d", p_port->state, p_port->rfc.state, p_port->rfc.p_mcb ? p_port->rfc.p_mcb->state : 0); return (PORT_ALREADY_OPENED); } @@ -153,7 +159,7 @@ int RFCOMM_CreateConnection (UINT16 uuid, UINT8 scn, BOOLEAN is_server, p_port->keep_port_handle = TRUE; /* keep mtu that user asked, p_port->mtu could be updated during param negotiation */ - p_port->keep_mtu = p_port->mtu; + p_port->keep_mtu = p_port->mtu; } p_port->local_ctrl.modem_signal = p_port->default_signal_state; @@ -181,7 +187,7 @@ int RFCOMM_CreateConnection (UINT16 uuid, UINT8 scn, BOOLEAN is_server, ** ** Description This function is called to close the specified connection. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** *******************************************************************************/ int RFCOMM_RemoveConnection (UINT16 handle) @@ -217,7 +223,7 @@ int RFCOMM_RemoveConnection (UINT16 handle) ** ** Description This function is called to close the server port. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** *******************************************************************************/ int RFCOMM_RemoveServer (UINT16 handle) @@ -236,7 +242,7 @@ int RFCOMM_RemoveServer (UINT16 handle) /* Do not report any events to the client any more. */ p_port->p_mgmt_callback = NULL; - + if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) { RFCOMM_TRACE_EVENT1 ("RFCOMM_RemoveServer() Not opened:%d", handle); @@ -256,13 +262,13 @@ int RFCOMM_RemoveServer (UINT16 handle) ** ** Function PORT_SetEventCallback ** -** Description This function is called to provide an address of the +** Description This function is called to provide an address of the ** function which will be called when one of the events ** specified in the mask occures. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection -** p_callback - address of the callback function which should -** be called from the RFCOMM when an event +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** p_callback - address of the callback function which should +** be called from the RFCOMM when an event ** specified in the mask occures. ** ** @@ -298,9 +304,9 @@ int PORT_SetEventCallback (UINT16 port_handle, tPORT_CALLBACK *p_port_cb) ** ** Description This function is when a data packet is received ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection -** p_callback - address of the callback function which should -** be called from the RFCOMM when data packet +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** p_callback - address of the callback function which should +** be called from the RFCOMM when data packet ** is received. ** ** @@ -328,6 +334,43 @@ int PORT_SetDataCallback (UINT16 port_handle, tPORT_DATA_CALLBACK *p_port_cb) return (PORT_SUCCESS); } +/******************************************************************************* +** +** Function PORT_SetCODataCallback +** +** Description This function is when a data packet is received +** +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** p_callback - address of the callback function which should +** be called from the RFCOMM when data packet +** is received. +** +** +*******************************************************************************/ +int PORT_SetDataCOCallback (UINT16 port_handle, tPORT_DATA_CO_CALLBACK *p_port_cb) +{ + tPORT *p_port; + + RFCOMM_TRACE_API2 ("PORT_SetDataCOCallback() handle:%d cb 0x%x", port_handle, p_port_cb); + + /* Check if handle is valid to avoid crashing */ + if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS)) + { + return (PORT_BAD_HANDLE); + } + + p_port = &rfc_cb.port.port[port_handle - 1]; + + if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) + { + return (PORT_NOT_OPENED); + } + + p_port->p_data_co_callback = p_port_cb; + + return (PORT_SUCCESS); +} + /******************************************************************************* @@ -336,7 +379,7 @@ int PORT_SetDataCallback (UINT16 port_handle, tPORT_DATA_CALLBACK *p_port_cb) ** ** Description This function is called to close the specified connection. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** mask - Bitmask of the events the host is interested in ** *******************************************************************************/ @@ -372,7 +415,7 @@ int PORT_SetEventMask (UINT16 port_handle, UINT32 mask) ** Description This function returns PORT_SUCCESS if connection referenced ** by handle is up and running ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** bd_addr - OUT bd_addr of the peer ** p_lcid - OUT L2CAP's LCID ** @@ -396,8 +439,8 @@ int PORT_CheckConnection (UINT16 handle, BD_ADDR bd_addr, UINT16 *p_lcid) return (PORT_NOT_OPENED); } - if (!p_port->rfc.p_mcb - || !p_port->rfc.p_mcb->peer_ready + if (!p_port->rfc.p_mcb + || !p_port->rfc.p_mcb->peer_ready || (p_port->rfc.state != RFC_STATE_OPENED)) { return (PORT_LINE_ERR); @@ -453,7 +496,7 @@ BOOLEAN PORT_IsOpening (BD_ADDR bd_addr) } } - if ((!found_port) || + if ((!found_port) || (found_port && (p_port->rfc.state < RFC_STATE_OPENED))) { /* Port is not established yet. */ @@ -470,11 +513,11 @@ BOOLEAN PORT_IsOpening (BD_ADDR bd_addr) ** ** Function PORT_SetState ** -** Description This function configures connection according to the +** Description This function configures connection according to the ** specifications in the tPORT_STATE structure. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection -** p_settings - Pointer to a tPORT_STATE structure containing +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** p_settings - Pointer to a tPORT_STATE structure containing ** configuration information for the connection. ** ** @@ -524,7 +567,7 @@ int PORT_SetState (UINT16 handle, tPORT_STATE *p_settings) ** ** Description This function return number of buffers on the rx queue. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** p_rx_queue_count - Pointer to return queue count in. ** *******************************************************************************/ @@ -567,7 +610,7 @@ int PORT_GetRxQueueCnt (UINT16 handle, UINT16 *p_rx_queue_count) ** Description This function is called to fill tPORT_STATE structure ** with the curremt control settings for the port ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** p_settings - Pointer to a tPORT_STATE structure in which ** configuration information is returned. ** @@ -605,10 +648,10 @@ int PORT_GetState (UINT16 handle, tPORT_STATE *p_settings) ** ** Function PORT_Control ** -** Description This function directs a specified connection to pass control +** Description This function directs a specified connection to pass control ** control information to the peer device. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** signal = specify the function to be passed ** *******************************************************************************/ @@ -691,11 +734,11 @@ int PORT_Control (UINT16 handle, UINT8 signal) ** ** Function PORT_FlowControl ** -** Description This function directs a specified connection to pass -** flow control message to the peer device. Enable flag passed +** Description This function directs a specified connection to pass +** flow control message to the peer device. Enable flag passed ** shows if port can accept more data. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** enable - enables data flow ** *******************************************************************************/ @@ -770,12 +813,12 @@ int PORT_FlowControl (UINT16 handle, BOOLEAN enable) ** ** Function PORT_GetModemStatus ** -** Description This function retrieves modem control signals. Normally -** application will call this function after a callback -** function is called with notification that one of signals +** Description This function retrieves modem control signals. Normally +** application will call this function after a callback +** function is called with notification that one of signals ** has been changed. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** p_signal - specify the pointer to control signals info ** *******************************************************************************/ @@ -798,7 +841,7 @@ int PORT_GetModemStatus (UINT16 handle, UINT8 *p_signal) *p_signal = p_port->peer_ctrl.modem_signal; RFCOMM_TRACE_API2 ("PORT_GetModemStatus() handle:%d signal:%x", handle, *p_signal); - + return (PORT_SUCCESS); } @@ -808,14 +851,14 @@ int PORT_GetModemStatus (UINT16 handle, UINT8 *p_signal) ** Function PORT_ClearError ** ** Description This function retreives information about a communications -** error and reports current status of a connection. The +** error and reports current status of a connection. The ** function should be called when an error occures to clear ** the connection error flag and to enable additional read ** and write operations. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** p_errors - pointer of the variable to receive error codes -** p_status - pointer to the tPORT_STATUS structur to receive +** p_status - pointer to the tPORT_STATUS structur to receive ** connection status ** *******************************************************************************/ @@ -854,7 +897,7 @@ int PORT_ClearError (UINT16 handle, UINT16 *p_errors, tPORT_STATUS *p_status) ** ** Description This function send a communications error to the peer device ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** errors - receive error codes ** *******************************************************************************/ @@ -890,10 +933,10 @@ int PORT_SendError (UINT16 handle, UINT8 errors) ** ** Function PORT_GetQueueStatus ** -** Description This function reports current status of a connection. +** Description This function reports current status of a connection. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection -** p_status - pointer to the tPORT_STATUS structur to receive +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** p_status - pointer to the tPORT_STATUS structur to receive ** connection status ** *******************************************************************************/ @@ -939,11 +982,11 @@ int PORT_GetQueueStatus (UINT16 handle, tPORT_STATUS *p_status) ** ** Function PORT_Purge ** -** Description This function discards all the data from the output or +** Description This function discards all the data from the output or ** input queues of the specified connection. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection -** purge_flags - specify the action to take. +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** purge_flags - specify the action to take. ** *******************************************************************************/ int PORT_Purge (UINT16 handle, UINT8 purge_flags) @@ -951,7 +994,7 @@ int PORT_Purge (UINT16 handle, UINT8 purge_flags) tPORT *p_port; BT_HDR *p_buf; UINT16 count; - UINT32 events; + UINT32 events; RFCOMM_TRACE_API2 ("PORT_Purge() handle:%d flags:0x%x", handle, purge_flags); @@ -994,7 +1037,7 @@ int PORT_Purge (UINT16 handle, UINT8 purge_flags) GKI_freebuf (p_buf); p_port->tx.queue_size = 0; - + PORT_SCHEDULE_UNLOCK; events = PORT_EV_TXEMPTY; @@ -1015,10 +1058,10 @@ int PORT_Purge (UINT16 handle, UINT8 purge_flags) ** ** Function PORT_ReadData ** -** Description Normally not GKI aware application will call this function +** Description Normally not GKI aware application will call this function ** after receiving PORT_EV_RXCHAR event. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** p_data - Data area ** max_len - Byte count requested ** p_len - Byte count received @@ -1114,7 +1157,7 @@ int PORT_ReadData (UINT16 handle, char *p_data, UINT16 max_len, UINT16 *p_len) /* If rfcomm suspended traffic from the peer based on the rx_queue_size */ /* check if it can be resumed now */ port_flow_control_peer (p_port, TRUE, count); - + return (PORT_SUCCESS); } @@ -1126,8 +1169,8 @@ int PORT_ReadData (UINT16 handle, char *p_data, UINT16 max_len, UINT16 *p_len) ** Description Normally application will call this function after receiving ** PORT_EV_RXCHAR event. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection -** pp_buf - pointer to address of buffer with data, +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** pp_buf - pointer to address of buffer with data, ** *******************************************************************************/ int PORT_Read (UINT16 handle, BT_HDR **pp_buf) @@ -1181,17 +1224,17 @@ int PORT_Read (UINT16 handle, BT_HDR **pp_buf) ** ** Function port_write ** -** Description This function when a data packet is received from the apper -** layer task. +** Description This function when a data packet is received from the apper +** layer task. ** -** Parameters: p_port - pointer to address of port control block -** p_buf - pointer to address of buffer with data, +** Parameters: p_port - pointer to address of port control block +** p_buf - pointer to address of buffer with data, ** *******************************************************************************/ static int port_write (tPORT *p_port, BT_HDR *p_buf) { /* We should not allow to write data in to server port when connection is not opened */ - if (p_port->is_server && (p_port->rfc.state != RFC_STATE_OPENED)) + if (p_port->is_server && (p_port->rfc.state != RFC_STATE_OPENED)) { GKI_freebuf (p_buf); return (PORT_CLOSED); @@ -1201,16 +1244,16 @@ static int port_write (tPORT *p_port, BT_HDR *p_buf) /* Peer is not ready or Port is not yet opened or initial port control */ /* command has not been sent */ if (p_port->tx.peer_fc - || !p_port->rfc.p_mcb - || !p_port->rfc.p_mcb->peer_ready - || (p_port->rfc.state != RFC_STATE_OPENED) - || ((p_port->port_ctrl & (PORT_CTRL_REQ_SENT | PORT_CTRL_IND_RECEIVED)) != + || !p_port->rfc.p_mcb + || !p_port->rfc.p_mcb->peer_ready + || (p_port->rfc.state != RFC_STATE_OPENED) + || ((p_port->port_ctrl & (PORT_CTRL_REQ_SENT | PORT_CTRL_IND_RECEIVED)) != (PORT_CTRL_REQ_SENT | PORT_CTRL_IND_RECEIVED))) { if ((p_port->tx.queue_size > PORT_TX_CRITICAL_WM) || (p_port->tx.queue.count > PORT_TX_BUF_CRITICAL_WM)) { - RFCOMM_TRACE_WARNING1 ("PORT_Write: Queue size: %d", + RFCOMM_TRACE_WARNING1 ("PORT_Write: Queue size: %d", p_port->tx.queue_size); GKI_freebuf (p_buf); @@ -1221,8 +1264,8 @@ static int port_write (tPORT *p_port, BT_HDR *p_buf) return (PORT_TX_FULL); } - RFCOMM_TRACE_EVENT4 ("PORT_Write : Data is enqued. flow disabled %d peer_ready %d state %d ctrl_state %x", - p_port->tx.peer_fc, + RFCOMM_TRACE_EVENT4 ("PORT_Write : Data is enqued. flow disabled %d peer_ready %d state %d ctrl_state %x", + p_port->tx.peer_fc, (p_port->rfc.p_mcb && p_port->rfc.p_mcb->peer_ready), p_port->rfc.state, p_port->port_ctrl); @@ -1245,11 +1288,11 @@ static int port_write (tPORT *p_port, BT_HDR *p_buf) ** ** Function PORT_Write ** -** Description This function when a data packet is received from the apper -** layer task. +** Description This function when a data packet is received from the apper +** layer task. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection -** pp_buf - pointer to address of buffer with data, +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** pp_buf - pointer to address of buffer with data, ** *******************************************************************************/ int PORT_Write (UINT16 handle, BT_HDR *p_buf) @@ -1277,7 +1320,7 @@ int PORT_Write (UINT16 handle, BT_HDR *p_buf) if (p_port->line_status) { - RFCOMM_TRACE_WARNING1 ("PORT_Write: Data dropped line_status:0x%x", + RFCOMM_TRACE_WARNING1 ("PORT_Write: Data dropped line_status:0x%x", p_port->line_status); GKI_freebuf (p_buf); return (PORT_LINE_ERR); @@ -1285,7 +1328,7 @@ int PORT_Write (UINT16 handle, BT_HDR *p_buf) rc = port_write (p_port, p_buf); event |= port_flow_control_user (p_port); - + switch (rc) { case PORT_TX_FULL: @@ -1305,16 +1348,165 @@ int PORT_Write (UINT16 handle, BT_HDR *p_buf) return (PORT_SUCCESS); } +/******************************************************************************* +** +** Function PORT_WriteDataCO +** +** Description Normally not GKI aware application will call this function +** to send data to the port by callout functions +** +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** fd - socket fd +** p_len - Byte count returned +** +*******************************************************************************/ +int PORT_WriteDataCO (UINT16 handle, int* p_len) +{ + + tPORT *p_port; + BT_HDR *p_buf; + UINT32 event = 0; + int rc = 0; + UINT16 length; + + RFCOMM_TRACE_API1 ("PORT_WriteDataCO() handle:%d", handle); + int written; + *p_len = 0; + + /* Check if handle is valid to avoid crashing */ + if ((handle == 0) || (handle > MAX_RFC_PORTS)) + { + return (PORT_BAD_HANDLE); + } + p_port = &rfc_cb.port.port[handle - 1]; + + if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) + { + RFCOMM_TRACE_WARNING1 ("PORT_WriteDataByFd() no port state:%d", p_port->state); + return (PORT_NOT_OPENED); + } + + if (!p_port->peer_mtu) + { + RFCOMM_TRACE_ERROR1 ("PORT_WriteDataByFd() peer_mtu:%d", p_port->peer_mtu); + return (PORT_UNKNOWN_ERROR); + } + int available = 0; + //if(ioctl(fd, FIONREAD, &available) < 0) + if(p_port->p_data_co_callback(handle, (UINT8*)&available, sizeof(available), + DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE) == FALSE) + { + RFCOMM_TRACE_ERROR1("p_data_co_callback DATA_CO_CALLBACK_TYPE_INCOMING_SIZE failed, available:%d", available); + return (PORT_UNKNOWN_ERROR); + } + /* Length for each buffer is the smaller of GKI buffer, peer MTU, or max_len */ + length = RFCOMM_DATA_POOL_BUF_SIZE - + (UINT16)(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + RFCOMM_DATA_OVERHEAD); + + /* If there are buffers scheduled for transmission check if requested */ + /* data fits into the end of the queue */ + PORT_SCHEDULE_LOCK; + + if (((p_buf = (BT_HDR *)p_port->tx.queue.p_last) != NULL) + && (((int)p_buf->len + available) <= (int)p_port->peer_mtu) + && (((int)p_buf->len + available) <= (int)length)) + { + //if(recv(fd, (UINT8 *)(p_buf + 1) + p_buf->offset + p_buf->len, available, 0) != available) + if(p_port->p_data_co_callback(handle, (UINT8 *)(p_buf + 1) + p_buf->offset + p_buf->len, + available, DATA_CO_CALLBACK_TYPE_OUTGOING) == FALSE) + + { + error("p_data_co_callback DATA_CO_CALLBACK_TYPE_OUTGOING failed, available:%d", available); + return (PORT_UNKNOWN_ERROR); + } + //memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset + p_buf->len, p_data, max_len); + p_port->tx.queue_size += (UINT16)available; + + *p_len = available; + p_buf->len += (UINT16)available; + + PORT_SCHEDULE_UNLOCK; + + return (PORT_SUCCESS); + } + + PORT_SCHEDULE_UNLOCK; + + //int max_read = length < p_port->peer_mtu ? length : p_port->peer_mtu; + + //max_read = available < max_read ? available : max_read; + + while (available) + { + /* if we're over buffer high water mark, we're done */ + if ((p_port->tx.queue_size > PORT_TX_HIGH_WM) + || (p_port->tx.queue.count > PORT_TX_BUF_HIGH_WM)) + break; + + /* continue with rfcomm data write */ + p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_DATA_POOL_ID); + if (!p_buf) + break; + + p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET; + p_buf->layer_specific = handle; + + if (p_port->peer_mtu < length) + length = p_port->peer_mtu; + if (available < (int)length) + length = (UINT16)available; + p_buf->len = length; + p_buf->event = BT_EVT_TO_BTU_SP_DATA; + + //memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, length); + //if(recv(fd, (UINT8 *)(p_buf + 1) + p_buf->offset, (int)length, 0) != (int)length) + if(p_port->p_data_co_callback(handle, (UINT8 *)(p_buf + 1) + p_buf->offset, length, + DATA_CO_CALLBACK_TYPE_OUTGOING) == FALSE) + { + error("p_data_co_callback DATA_CO_CALLBACK_TYPE_OUTGOING failed, length:%d", length); + return (PORT_UNKNOWN_ERROR); + } + + + RFCOMM_TRACE_EVENT1 ("PORT_WriteData %d bytes", length); + + rc = port_write (p_port, p_buf); + + /* If queue went below the threashold need to send flow control */ + event |= port_flow_control_user (p_port); + + if (rc == PORT_SUCCESS) + event |= PORT_EV_TXCHAR; + + if ((rc != PORT_SUCCESS) && (rc != PORT_CMD_PENDING)) + break; + + *p_len += length; + available -= (int)length; + } + if (!available && (rc != PORT_CMD_PENDING) && (rc != PORT_TX_QUEUE_DISABLED)) + event |= PORT_EV_TXEMPTY; + + /* Mask out all events that are not of interest to user */ + event &= p_port->ev_mask; + + /* Send event to the application */ + if (p_port->p_callback && event) + (p_port->p_callback)(event, p_port->inx); + + return (PORT_SUCCESS); +} + /******************************************************************************* ** ** Function PORT_WriteData ** -** Description Normally not GKI aware application will call this function +** Description Normally not GKI aware application will call this function ** to send data to the port. ** -** Parameters: handle - Handle returned in the RFCOMM_CreateConnection +** Parameters: handle - Handle returned in the RFCOMM_CreateConnection ** p_data - Data area ** max_len - Byte count requested ** p_len - Byte count received @@ -1352,7 +1544,7 @@ int PORT_WriteData (UINT16 handle, char *p_data, UINT16 max_len, UINT16 *p_len) } /* Length for each buffer is the smaller of GKI buffer, peer MTU, or max_len */ - length = RFCOMM_DATA_POOL_BUF_SIZE - + length = RFCOMM_DATA_POOL_BUF_SIZE - (UINT16)(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + RFCOMM_DATA_OVERHEAD); /* If there are buffers scheduled for transmission check if requested */ @@ -1403,7 +1595,7 @@ int PORT_WriteData (UINT16 handle, char *p_data, UINT16 max_len, UINT16 *p_len) RFCOMM_TRACE_EVENT1 ("PORT_WriteData %d bytes", length); rc = port_write (p_port, p_buf); - + /* If queue went below the threashold need to send flow control */ event |= port_flow_control_user (p_port); @@ -1468,7 +1660,7 @@ int PORT_Test (UINT16 handle, UINT8 *p_data, UINT16 len) if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) != NULL) { - + p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET + 2; p_buf->len = len; diff --git a/stack/rfcomm/port_int.h b/stack/rfcomm/port_int.h index acd56b7..c3fbcee 100644 --- a/stack/rfcomm/port_int.h +++ b/stack/rfcomm/port_int.h @@ -35,7 +35,7 @@ #define PORT_FC_CREDIT 2 /* use RFCOMM credit based flow control */ /* -** Define Port Data Transfere control block +** Define Port Data Transfere control block */ typedef struct { @@ -66,7 +66,7 @@ typedef struct #define RFCOMM_CTRL_BREAK_IN_SEQ 1 UINT8 break_signal_seq; /* as soon as possible | in sequence (default) */ - + BOOLEAN fc; /* TRUE when the device is unable to accept frames */ } tPORT_CTRL; @@ -74,7 +74,7 @@ typedef struct /* ** RFCOMM multiplexer Control Block */ -typedef struct +typedef struct { TIMER_LIST_ENT tle; /* Timer list entry */ BUFFER_Q cmd_q; /* Queue for command messages on this mux */ @@ -162,7 +162,7 @@ struct t_port_info tPORT_STATE user_port_pars; /* Port parameters for user connection */ tPORT_STATE peer_port_pars; /* Port parameters for user connection */ - tPORT_CTRL local_ctrl; + tPORT_CTRL local_ctrl; tPORT_CTRL peer_ctrl; #define PORT_CTRL_REQ_SENT 0x01 @@ -180,6 +180,7 @@ struct t_port_info tPORT_CALLBACK *p_callback; /* Pointer to users callback function */ tPORT_CALLBACK *p_mgmt_callback; /* Callback function to receive connection up/down */ tPORT_DATA_CALLBACK *p_data_callback; /* Callback function to receive data indications */ + tPORT_DATA_CO_CALLBACK *p_data_co_callback; /* Callback function with callouts and flowctrl */ UINT16 credit_tx; /* Flow control credits for tx path */ UINT16 credit_rx; /* Flow control credits for rx path, this is */ /* number of buffers peer is allowed to sent */ diff --git a/stack/rfcomm/port_rfc.c b/stack/rfcomm/port_rfc.c index c4ac929..ef84fef 100644 --- a/stack/rfcomm/port_rfc.c +++ b/stack/rfcomm/port_rfc.c @@ -819,6 +819,17 @@ void PORT_DataInd (tRFC_MCB *p_mcb, UINT8 dlci, BT_HDR *p_buf) GKI_freebuf (p_buf); return; } + /* If client registered callout callback with flow control we can just deliver receive data */ + if (p_port->p_data_co_callback) + { + /* Another packet is delivered to user. Send credits to peer if required */ + + if(p_port->p_data_co_callback(p_port->inx, (UINT8*)p_buf, -1, DATA_CO_CALLBACK_TYPE_INCOMING)) + port_flow_control_peer(p_port, TRUE, 1); + else port_flow_control_peer(p_port, FALSE, 0); + //GKI_freebuf (p_buf); + return; + } /* If client registered callback we can just deliver receive data */ if (p_port->p_data_callback) diff --git a/stack/rfcomm/port_utils.c b/stack/rfcomm/port_utils.c index 5a52774..6800b46 100644 --- a/stack/rfcomm/port_utils.c +++ b/stack/rfcomm/port_utils.c @@ -20,6 +20,12 @@ #include "btm_int.h" #include "btu.h" +#include <cutils/log.h> +#define info(fmt, ...) LOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define debug(fmt, ...) LOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define error(fmt, ...) LOGE ("## ERROR : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__) +#define asrt(s) if(!(s)) LOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__) + static const tPORT_STATE default_port_pars = { @@ -73,6 +79,7 @@ tPORT *port_allocate_port (UINT8 dlci, BD_ADDR bd_addr) port_set_defaults (p_port); rfc_cb.rfc.last_port = yy; + debug("rfc_cb.port.port[%d] allocated, last_port:%d", yy, rfc_cb.rfc.last_port); return (p_port); } } @@ -197,7 +204,7 @@ void port_release_port (tPORT *p_port) tPORT_STATE user_port_pars; PORT_SCHEDULE_LOCK; - + debug("port_release_port, p_port:%p", p_port); while ((p_buf = (BT_HDR *)GKI_dequeue (&p_port->rx.queue)) != NULL) GKI_freebuf (p_buf); @@ -506,7 +513,7 @@ void port_flow_control_peer(tPORT *p_port, BOOLEAN enable, UINT16 count) else { /* if client registered data callback, just do what they want */ - if (p_port->p_data_callback) + if (p_port->p_data_callback || p_port->p_data_co_callback) { p_port->rx.peer_fc = TRUE; } @@ -540,7 +547,7 @@ void port_flow_control_peer(tPORT *p_port, BOOLEAN enable, UINT16 count) else { /* if client registered data callback, just do what they want */ - if (p_port->p_data_callback) + if (p_port->p_data_callback || p_port->p_data_co_callback) { p_port->rx.peer_fc = TRUE; RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE); diff --git a/stack/sdp/sdp_api.c b/stack/sdp/sdp_api.c index 2545181..ef13f15 100644 --- a/stack/sdp/sdp_api.c +++ b/stack/sdp/sdp_api.c @@ -23,6 +23,12 @@ #include "sdpint.h" #include "btu.h" +#include <cutils/log.h> +#define info(fmt, ...) LOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define debug(fmt, ...) LOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__) +#define error(fmt, ...) LOGE ("## ERROR : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__) +#define asrt(s) if(!(s)) LOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__) + /********************************************************************** ** C L I E N T F U N C T I O N P R O T O T Y P E S * @@ -94,9 +100,9 @@ BOOLEAN SDP_InitDiscoveryDb (tSDP_DISCOVERY_DB *p_db, UINT32 len, UINT16 num_uui ** ** Function SDP_CancelServiceSearch ** -** Description This function cancels an active query to an SDP server. +** Description This function cancels an active query to an SDP server. ** -** Returns TRUE if discovery cancelled, FALSE if a matching activity is not found. +** Returns TRUE if discovery cancelled, FALSE if a matching activity is not found. ** *******************************************************************************/ BOOLEAN SDP_CancelServiceSearch (tSDP_DISCOVERY_DB *p_db) @@ -118,9 +124,9 @@ BOOLEAN SDP_CancelServiceSearch (tSDP_DISCOVERY_DB *p_db) ** ** Function SDP_ServiceSearchRequest ** -** Description This function queries an SDP server for information. +** Description This function queries an SDP server for information. ** -** Returns TRUE if discovery started, FALSE if failed. +** Returns TRUE if discovery started, FALSE if failed. ** *******************************************************************************/ BOOLEAN SDP_ServiceSearchRequest (UINT8 *p_bd_addr, tSDP_DISCOVERY_DB *p_db, @@ -150,14 +156,14 @@ BOOLEAN SDP_ServiceSearchRequest (UINT8 *p_bd_addr, tSDP_DISCOVERY_DB *p_db, ** ** Function SDP_ServiceSearchAttributeRequest ** -** Description This function queries an SDP server for information. +** Description This function queries an SDP server for information. ** ** The difference between this API function and the function -** SDP_ServiceSearchRequest is that this one does a +** SDP_ServiceSearchRequest is that this one does a ** combined ServiceSearchAttributeRequest SDP function. ** (This is for Unplug Testing) ** -** Returns TRUE if discovery started, FALSE if failed. +** Returns TRUE if discovery started, FALSE if failed. ** *******************************************************************************/ BOOLEAN SDP_ServiceSearchAttributeRequest (UINT8 *p_bd_addr, tSDP_DISCOVERY_DB *p_db, @@ -183,6 +189,44 @@ BOOLEAN SDP_ServiceSearchAttributeRequest (UINT8 *p_bd_addr, tSDP_DISCOVERY_DB * return (FALSE); #endif } +/******************************************************************************* +** +** Function SDP_ServiceSearchAttributeRequest2 +** +** Description This function queries an SDP server for information. +** +** The difference between this API function and the function +** SDP_ServiceSearchRequest is that this one does a +** combined ServiceSearchAttributeRequest SDP function. +** (This is for Unplug Testing) +** +** Returns TRUE if discovery started, FALSE if failed. +** +*******************************************************************************/ +BOOLEAN SDP_ServiceSearchAttributeRequest2 (UINT8 *p_bd_addr, tSDP_DISCOVERY_DB *p_db, + tSDP_DISC_CMPL_CB2 *p_cb2, void * user_data) +{ +#if SDP_CLIENT_ENABLED == TRUE + tCONN_CB *p_ccb; + + /* Specific BD address */ + p_ccb = sdp_conn_originate (p_bd_addr); + + if (!p_ccb) + return (FALSE); + + p_ccb->disc_state = SDP_DISC_WAIT_CONN; + p_ccb->p_db = p_db; + p_ccb->p_cb2 = p_cb2; + + p_ccb->is_attr_search = TRUE; + p_ccb->user_data = user_data; + + return (TRUE); +#else + return (FALSE); +#endif +} #if SDP_CLIENT_ENABLED == TRUE void SDP_SetIdleTimeout (BD_ADDR addr, UINT16 timeout) @@ -272,10 +316,10 @@ tSDP_DISC_ATTR *SDP_FindAttributeInRec (tSDP_DISC_REC *p_rec, UINT16 attr_id) ** Description This function is called to read the service UUID within a record ** if there is any. ** -** Parameters: p_rec - pointer to a SDP record. +** Parameters: p_rec - pointer to a SDP record. ** p_uuid - output parameter to save the UUID found. ** -** Returns TRUE if found, otherwise FALSE. +** Returns TRUE if found, otherwise FALSE. ** *******************************************************************************/ BOOLEAN SDP_FindServiceUUIDInRec(tSDP_DISC_REC *p_rec, tBT_UUID * p_uuid) @@ -612,7 +656,7 @@ BOOLEAN SDP_FindAddProtoListsElemInRec (tSDP_DISC_REC *p_rec, UINT16 layer_uuid, #if SDP_CLIENT_ENABLED == TRUE tSDP_DISC_ATTR *p_attr, *p_sattr; BOOLEAN ret = FALSE; - + p_attr = p_rec->p_first_attr; while (p_attr) { @@ -645,7 +689,7 @@ BOOLEAN SDP_FindAddProtoListsElemInRec (tSDP_DISC_REC *p_rec, UINT16 layer_uuid, ** ** Description This function looks at a specific discovery record for the ** Profile list descriptor, and pulls out the version number. -** The version number consists of an 8-bit major version and +** The version number consists of an 8-bit major version and ** an 8-bit minor version. ** ** Returns TRUE if found, FALSE if not @@ -732,11 +776,11 @@ UINT16 SDP_DiDiscover( BD_ADDR remote_device, tSDP_DISCOVERY_DB *p_db, tSDP_UUID init_uuid; init_uuid.len = 2; init_uuid.uu.uuid16 = di_uuid; - + if( SDP_InitDiscoveryDb(p_db, len, num_uuids, &init_uuid, 0, NULL) ) if( SDP_ServiceSearchRequest(remote_device, p_db, p_cb) ) result = SDP_SUCCESS; - + return result; #else return SDP_DI_DISC_FAILED; @@ -777,7 +821,7 @@ UINT8 SDP_GetNumDiRecords( tSDP_DISCOVERY_DB *p_db ) ** Function SDP_GetDiRecord ** ** Description This function retrieves a remote device's DI record from -** the specified database. +** the specified database. ** ** Returns SDP_SUCCESS if record retrieved, else error ** @@ -788,7 +832,7 @@ UINT16 SDP_GetDiRecord( UINT8 get_record_index, tSDP_DI_GET_RECORD *p_device_inf #if SDP_CLIENT_ENABLED == TRUE UINT16 result = SDP_NO_DI_RECORD_FOUND; UINT8 curr_record_index = 1; - + tSDP_DISC_REC *p_curr_record = NULL; /* find the requested SDP record in the discovery database */ @@ -801,7 +845,7 @@ UINT16 SDP_GetDiRecord( UINT8 get_record_index, tSDP_DI_GET_RECORD *p_device_inf if( curr_record_index++ == get_record_index ) { result = SDP_SUCCESS; - break; + break; } } }while( p_curr_record ); @@ -840,31 +884,31 @@ UINT16 SDP_GetDiRecord( UINT8 get_record_index, tSDP_DI_GET_RECORD *p_device_inf p_device_info->spec_id = p_curr_attr->attr_value.v.u16; else result = SDP_ERR_ATTR_NOT_PRESENT; - + p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_VENDOR_ID ); if( p_curr_attr ) p_device_info->rec.vendor = p_curr_attr->attr_value.v.u16; else result = SDP_ERR_ATTR_NOT_PRESENT; - + p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_VENDOR_ID_SOURCE ); if( p_curr_attr ) p_device_info->rec.vendor_id_source = p_curr_attr->attr_value.v.u16; else result = SDP_ERR_ATTR_NOT_PRESENT; - + p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_PRODUCT_ID ); if( p_curr_attr ) p_device_info->rec.product = p_curr_attr->attr_value.v.u16; else result = SDP_ERR_ATTR_NOT_PRESENT; - + p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_PRODUCT_VERSION ); if( p_curr_attr ) p_device_info->rec.version = p_curr_attr->attr_value.v.u16; else result = SDP_ERR_ATTR_NOT_PRESENT; - + p_curr_attr = SDP_FindAttributeInRec( p_curr_record, ATTR_ID_PRIMARY_RECORD ); if( p_curr_attr ) p_device_info->rec.primary_record = (BOOLEAN)p_curr_attr->attr_value.v.u8; @@ -888,7 +932,7 @@ UINT16 SDP_GetDiRecord( UINT8 get_record_index, tSDP_DI_GET_RECORD *p_device_inf ** ** Description This function adds a DI record to the local SDP database. ** -** +** ** ** Returns Returns SDP_SUCCESS if record added successfully, else error ** @@ -912,7 +956,7 @@ UINT16 SDP_SetLocalDiRecord( tSDP_DI_RECORD *p_device_info, UINT32 *p_handle ) if( p_device_info->primary_record == TRUE && sdp_cb.server_db.di_primary_handle ) handle = sdp_cb.server_db.di_primary_handle; else - { + { if( (handle = SDP_CreateRecord()) == 0 ) return SDP_NO_RESOURCES; } @@ -1013,7 +1057,7 @@ UINT16 SDP_SetLocalDiRecord( tSDP_DI_RECORD *p_device_info, UINT32 *p_handle ) BOOLEAN_DESC_TYPE, 1, &u8)) ) result = SDP_DI_REG_FAILED; } - + /* mandatory */ if ( result == SDP_SUCCESS) { @@ -1028,7 +1072,7 @@ UINT16 SDP_SetLocalDiRecord( tSDP_DI_RECORD *p_device_info, UINT32 *p_handle ) SDP_DeleteRecord( handle ); else if (p_device_info->primary_record == TRUE) sdp_cb.server_db.di_primary_handle = handle; - + return result; #else /* SDP_SERVER_ENABLED is FALSE */ return SDP_DI_REG_FAILED; @@ -1056,7 +1100,7 @@ UINT16 SDP_GetLocalDiRecord(tSDP_DI_GET_RECORD *p_device_info, UINT32 *p_handle tSDP_ATTRIBUTE *p_attr; UINT8 *p_temp; INT32 templen; - + if (*p_handle == 0) *p_handle = sdp_cb.server_db.di_primary_handle; @@ -1172,7 +1216,7 @@ UINT8 SDP_SetTraceLevel (UINT8 new_level) ** Function SDP_ConnOpen ** ** Description This function creates a connection to the SDP server on the -** given device. +** given device. ** ** Returns 0, if failed to initiate connection. Otherwise, the handle. ** @@ -1212,7 +1256,7 @@ UINT32 SDP_ConnOpen (UINT8 *p_bd_addr, tSDP_DISC_RES_CB *p_rcb, ** ** Description This function sends data to the connected SDP server. ** -** Returns TRUE if data is sent, FALSE if failed. +** Returns TRUE if data is sent, FALSE if failed. ** *******************************************************************************/ BOOLEAN SDP_WriteData (UINT32 handle, BT_HDR *p_msg) @@ -1244,7 +1288,7 @@ BOOLEAN SDP_WriteData (UINT32 handle, BT_HDR *p_msg) ** ** Parameters: handle - Handle of the connection returned by SDP_ConnOpen ** -** Returns TRUE if connection is closed, FALSE if failed to find the handle. +** Returns TRUE if connection is closed, FALSE if failed to find the handle. ** *******************************************************************************/ BOOLEAN SDP_ConnClose (UINT32 handle) diff --git a/stack/sdp/sdp_main.c b/stack/sdp/sdp_main.c index 8a9f6c5..8e84b8c 100644 --- a/stack/sdp/sdp_main.c +++ b/stack/sdp/sdp_main.c @@ -79,7 +79,7 @@ void sdp_init (void) #if SDP_SERVER_ENABLED == TRUE /* Register with Security Manager for the specific security level */ - if (!BTM_SetSecurityLevel (FALSE, SDP_SERVICE_NAME, BTM_SEC_SERVICE_SDP_SERVER, + if (!BTM_SetSecurityLevel (FALSE, SDP_SERVICE_NAME, BTM_SEC_SERVICE_SDP_SERVER, SDP_SECURITY_LEVEL, SDP_PSM, 0, 0)) { SDP_TRACE_ERROR0 ("Security Registration Server failed"); @@ -89,7 +89,7 @@ void sdp_init (void) #if SDP_CLIENT_ENABLED == TRUE /* Register with Security Manager for the specific security level */ - if (!BTM_SetSecurityLevel (TRUE, SDP_SERVICE_NAME, BTM_SEC_SERVICE_SDP_SERVER, + if (!BTM_SetSecurityLevel (TRUE, SDP_SERVICE_NAME, BTM_SEC_SERVICE_SDP_SERVER, SDP_SECURITY_LEVEL, SDP_PSM, 0, 0)) { SDP_TRACE_ERROR0 ("Security Registration for Client failed"); @@ -149,7 +149,7 @@ UINT16 sdp_set_max_attr_list_size (UINT16 max_size) ** ** Description This function handles an inbound connection indication ** from L2CAP. This is the case where we are acting as a -** server. +** server. ** ** Returns void ** @@ -171,7 +171,7 @@ static void sdp_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UIN p_ccb->connection_id = l2cap_cid; /* Send response to the L2CAP layer. */ - L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK); + L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK); { tL2CAP_CFG_INFO cfg = sdp_cb.l2cap_my_cfg; @@ -195,7 +195,7 @@ static void sdp_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UIN SDP_TRACE_EVENT1 ("SDP - Rcvd L2CAP conn ind, sent config req, CID 0x%x", p_ccb->connection_id); #else /* No server */ /* Reject the connection */ - L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_NO_PSM, 0); + L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_NO_PSM, 0); #endif } @@ -215,7 +215,7 @@ static void sdp_connect_cfm (UINT16 l2cap_cid, UINT16 result) { tCONN_CB *p_ccb; tL2CAP_CFG_INFO cfg; - + /* Find CCB based on CID */ if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL) { @@ -254,20 +254,25 @@ static void sdp_connect_cfm (UINT16 l2cap_cid, UINT16 result) SDP_TRACE_WARNING2 ("SDP - Rcvd conn cnf with error: 0x%x CID 0x%x", result, p_ccb->connection_id); /* Tell the user if he has a callback */ - if (p_ccb->p_cb) + if (p_ccb->p_cb || p_ccb->p_cb2) { + UINT16 err = -1; if ((result == HCI_ERR_HOST_REJECT_SECURITY) || (result == HCI_ERR_AUTH_FAILURE) || (result == HCI_ERR_PAIRING_NOT_ALLOWED) || (result == HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED) || (result == HCI_ERR_KEY_MISSING)) - (*p_ccb->p_cb) (SDP_SECURITY_ERR); + err = SDP_SECURITY_ERR; else if (result == HCI_ERR_HOST_REJECT_DEVICE) - (*p_ccb->p_cb) (SDP_CONN_REJECTED); + err = SDP_CONN_REJECTED; else - (*p_ccb->p_cb) (SDP_CONN_FAILED); - } + err = SDP_CONN_FAILED; + if(p_ccb->p_cb) + (*p_ccb->p_cb)(err); + else if(p_ccb->p_cb2) + (*p_ccb->p_cb2)(err, p_ccb->user_data); + } sdpu_release_ccb (p_ccb); } } @@ -456,6 +461,10 @@ static void sdp_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed) if (p_ccb->p_cb) (*p_ccb->p_cb) ((UINT16) ((p_ccb->con_state == SDP_STATE_CONNECTED) ? SDP_SUCCESS : SDP_CONN_FAILED)); + else if (p_ccb->p_cb2) + (*p_ccb->p_cb2) ((UINT16) ((p_ccb->con_state == SDP_STATE_CONNECTED) ? + SDP_SUCCESS : SDP_CONN_FAILED), p_ccb->user_data); + #endif sdpu_release_ccb (p_ccb); } @@ -478,7 +487,7 @@ static void sdp_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed) static void sdp_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg) { tCONN_CB *p_ccb; - + /* Find CCB based on CID */ if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) != NULL) { @@ -499,7 +508,7 @@ static void sdp_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg) { SDP_TRACE_WARNING1 ("SDP - Rcvd L2CAP data, unknown CID: 0x%x", l2cap_cid); } - + GKI_freebuf (p_msg); } @@ -628,6 +637,8 @@ void sdp_disconnect (tCONN_CB*p_ccb, UINT16 reason) /* Tell the user if he has a callback */ if (p_ccb->p_cb) (*p_ccb->p_cb) (reason); + else if (p_ccb->p_cb2) + (*p_ccb->p_cb2) (reason, p_ccb->user_data); sdpu_release_ccb (p_ccb); } @@ -659,6 +670,9 @@ static void sdp_disconnect_cfm (UINT16 l2cap_cid, UINT16 result) /* Tell the user if he has a callback */ if (p_ccb->p_cb) (*p_ccb->p_cb) (p_ccb->disconnect_reason); + else if (p_ccb->p_cb2) + (*p_ccb->p_cb2) (p_ccb->disconnect_reason, p_ccb->user_data); + sdpu_release_ccb (p_ccb); } @@ -685,6 +699,8 @@ void sdp_conn_timeout (tCONN_CB*p_ccb) /* Tell the user if he has a callback */ if (p_ccb->p_cb) (*p_ccb->p_cb) (SDP_CONN_FAILED); + else if (p_ccb->p_cb2) + (*p_ccb->p_cb2) (SDP_CONN_FAILED, p_ccb->user_data); #endif sdpu_release_ccb (p_ccb); } diff --git a/stack/sdp/sdpint.h b/stack/sdp/sdpint.h index 0f16b8c..f4416d0 100644 --- a/stack/sdp/sdpint.h +++ b/stack/sdp/sdpint.h @@ -176,6 +176,8 @@ typedef struct #if SDP_CLIENT_ENABLED == TRUE tSDP_DISCOVERY_DB *p_db; /* Database to save info into */ tSDP_DISC_CMPL_CB *p_cb; /* Callback for discovery done */ + tSDP_DISC_CMPL_CB2 *p_cb2; /* Callback for discovery done piggy back with the user data */ + void *user_data; /* piggy back user data */ UINT32 handles[SDP_MAX_DISC_SERVER_RECS]; /* Discovered server record handles */ UINT16 num_handles; /* Number of server handles */ UINT16 cur_handle; /* Current handle being processed */ @@ -200,6 +202,7 @@ typedef struct UINT16 cont_offset; /* Continuation state data in the server response */ tSDP_CONT_INFO cont_info; /* structure to hold continuation information for the server response */ #endif /* SDP_SERVER_ENABLED == TRUE */ + } tCONN_CB; |