summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarish Paryani <hparyani@broadcom.com>2012-04-03 23:49:45 -0700
committerMatthew Xie <mattx@google.com>2012-07-14 11:19:14 -0700
commit66aa5171e4e7c9f942971a30419c03134e67a4a4 (patch)
tree60fe10f29e7c3a574dcc317567a3c9bf05c85387
parent04db88d9bd23fa98916e031987f3ba2063783acc (diff)
downloadexternal_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
-rw-r--r--bta/Android.mk12
-rwxr-xr-xbta/include/bta_jv_api.h1109
-rwxr-xr-xbta/include/bta_jv_co.h38
-rwxr-xr-xbta/jv/bta_jv_act.c2339
-rwxr-xr-xbta/jv/bta_jv_api.c1572
-rwxr-xr-xbta/jv/bta_jv_cfg.c45
-rwxr-xr-xbta/jv/bta_jv_int.h448
-rwxr-xr-xbta/jv/bta_jv_main.c91
-rw-r--r--btif/include/btif_sock.h65
-rw-r--r--btif/include/btif_sock_rfc.h63
-rw-r--r--btif/include/btif_sock_sdp.h68
-rw-r--r--btif/include/btif_sock_thread.h71
-rw-r--r--btif/include/btif_sock_util.h87
-rwxr-xr-xbtif/src/bluetooth.c5
-rw-r--r--btif/src/btif_sock.c204
-rw-r--r--btif/src/btif_sock_rfc.c984
-rw-r--r--btif/src/btif_sock_sdp.c580
-rw-r--r--btif/src/btif_sock_thread.c591
-rw-r--r--btif/src/btif_sock_util.c295
-rwxr-xr-xmain/Android.mk33
-rw-r--r--stack/include/port_api.h129
-rw-r--r--stack/include/sdp_api.h52
-rw-r--r--stack/rfcomm/port_api.c356
-rw-r--r--stack/rfcomm/port_int.h9
-rw-r--r--stack/rfcomm/port_rfc.c11
-rw-r--r--stack/rfcomm/port_utils.c13
-rw-r--r--stack/sdp/sdp_api.c102
-rw-r--r--stack/sdp/sdp_main.c42
-rw-r--r--stack/sdp/sdpint.h3
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;