summaryrefslogtreecommitdiffstats
path: root/bta/pb
diff options
context:
space:
mode:
authorAndre Eisenbach <andre@broadcom.com>2012-02-22 13:18:21 -0800
committerMatthew Xie <mattx@google.com>2012-07-14 11:19:11 -0700
commite448862a47c08eb23185aaed574b39264f5005fc (patch)
tree2bc6246e3091315e77224fd798ea2fe8074ef972 /bta/pb
parenta2ca4b83ab8bbbfd8d5f6693e927ed4b82094624 (diff)
downloadexternal_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.zip
external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.gz
external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.bz2
Initial Bluedroid stack commit
Diffstat (limited to 'bta/pb')
-rw-r--r--bta/pb/bta_pbs_act.c1134
-rw-r--r--bta/pb/bta_pbs_api.c222
-rw-r--r--bta/pb/bta_pbs_cfg.c38
-rw-r--r--bta/pb/bta_pbs_ci.c119
-rw-r--r--bta/pb/bta_pbs_int.h305
-rw-r--r--bta/pb/bta_pbs_main.c515
-rw-r--r--bta/pb/bta_pbs_sdp.c113
-rw-r--r--bta/pb/bta_pbs_utils.c734
8 files changed, 3180 insertions, 0 deletions
diff --git a/bta/pb/bta_pbs_act.c b/bta/pb/bta_pbs_act.c
new file mode 100644
index 0000000..98f6463
--- /dev/null
+++ b/bta/pb/bta_pbs_act.c
@@ -0,0 +1,1134 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_act.c
+**
+** Description: This file contains the phone book access server
+** functions for the state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_fs_api.h"
+#include "bta_pbs_api.h"
+#include "bta_pbs_int.h"
+#include "btm_api.h"
+#include "utl.h"
+#include "bd.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+#define FLAGS_ARE_MASK (OBX_SPF_BACKUP | OBX_SPF_NO_CREATE)
+#define FLAGS_ARE_ILLEGAL 0x1 /* 'Backup and Create flag combo is BAD */
+/*****************************************************************************
+** Local Function prototypes
+*****************************************************************************/
+#if BTA_PBS_DEBUG == TRUE
+static char *pbs_obx_evt_code(tOBX_EVENT evt_code);
+#endif
+
+/*****************************************************************************
+** Action Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_pbs_api_disable
+**
+** Description Stop PBS server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_api_disable(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ /* Free any outstanding headers and control block memory */
+ bta_pbs_clean_getput(p_cb, TRUE);
+
+ /* Stop the OBEX server */
+ OBX_StopServer(p_cb->obx_handle);
+
+ /* Remove the PBS service from the SDP database */
+ SDP_DeleteRecord(p_cb->sdp_handle);
+ bta_sys_remove_uuid(UUID_SERVCLASS_PBAP_PSE);
+ /* Free the allocated server channel number */
+ BTM_FreeSCN(p_cb->scn);
+ BTM_SecClrService(BTM_SEC_SERVICE_PBAP);
+
+ utl_freebuf((void**)&p_cb->p_rootpath); /* Free buffer containing root and working paths */
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_api_authrsp
+**
+** Description Pass the response to an authentication request back to the
+** client.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_api_authrsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ UINT8 *p_pwd = NULL;
+ UINT8 *p_userid = NULL;
+
+ if (p_data->auth_rsp.key_len > 0)
+ p_pwd = (UINT8 *)p_data->auth_rsp.key;
+ if (p_data->auth_rsp.userid_len > 0)
+ p_userid = (UINT8 *)p_data->auth_rsp.userid;
+
+ OBX_Password(p_cb->obx_handle, p_pwd, p_data->auth_rsp.key_len,
+ p_userid, p_data->auth_rsp.userid_len);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_api_close
+**
+** Description Handle an api close event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_api_close(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ BD_ADDR bd_addr;
+ if (OBX_GetPeerAddr(p_cb->obx_handle, bd_addr) != 0)
+ {
+ /* resources will be freed at BTA_PBS_OBX_CLOSE_EVT */
+ OBX_DisconnectRsp(p_cb->obx_handle, OBX_RSP_SERVICE_UNAVL, NULL);
+ }
+ else
+ {
+ p_cb->p_cback(BTA_PBS_CLOSE_EVT, 0);
+}
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_api_accessrsp
+**
+** Description Process the access API event.
+** If permission had been granted, continue the operation,
+** otherwise stop the operation.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_api_accessrsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ UINT8 rsp_code = OBX_RSP_OK;
+ tBTA_PBS_CO_STATUS status = BTA_PBS_CO_EACCES;
+ tBTA_PBS_ACCESS_TYPE access = p_data->access_rsp.flag;
+ tBTA_PBS_OPER old_acc_active = p_cb->acc_active;
+ tBTA_PBS_OBX_RSP *p_rsp = NULL;
+ tBTA_PBS_OBJECT objevt;
+
+ if(p_cb->acc_active != p_data->access_rsp.oper )
+ {
+ APPL_TRACE_WARNING2("PBS ACCRSP: not match active:%d, rsp:%d",
+ p_cb->acc_active, p_data->access_rsp.oper);
+ return;
+ }
+
+ p_cb->acc_active = 0;
+ /* Process the currently active access response */
+ switch (old_acc_active)
+ {
+ case BTA_PBS_OPER_PULL_PB:
+ case BTA_PBS_OPER_PULL_VCARD_ENTRY:
+ if (access == BTA_PBS_ACCESS_TYPE_ALLOW)
+ {
+ p_cb->cout_active = TRUE;
+ bta_pbs_co_open(p_cb->p_path, p_cb->obx_oper, &p_cb->pullpb_app_params);
+ }
+
+ /* Case where application determined requested vCard handle has been modified: Requests a new listing to clear */
+ else if (access == BTA_PBS_ACCESS_TYPE_PRECONDITION && old_acc_active == BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ bta_pbs_get_file_rsp(OBX_RSP_PRECONDTN_FAILED, 0);
+ else /* Denied */
+ bta_pbs_get_file_rsp(OBX_RSP_UNAUTHORIZED, 0);
+ break;
+ case BTA_PBS_OPER_PULL_VCARD_LIST:
+ if (access == BTA_PBS_ACCESS_TYPE_ALLOW)
+ {
+ /* continue with get vlist */
+ bta_pbs_getvlist(p_cb->p_name);
+ }
+ else
+ bta_pbs_get_file_rsp(OBX_RSP_UNAUTHORIZED, 0);
+ break;
+
+ case BTA_PBS_OPER_SET_PB: /* Request is a Change Folder */
+ p_rsp = OBX_SetPathRsp;
+ if (access == BTA_PBS_ACCESS_TYPE_ALLOW)
+ {
+ status = BTA_PBS_CO_OK;
+ /* set obj type based on path */
+ if (!memcmp(p_cb->p_name, BTA_PBS_PBFOLDER_NAME, sizeof(BTA_PBS_PBFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_PB_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_ICHFOLDER_NAME, sizeof(BTA_PBS_ICHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_ICH_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_OCHFOLDER_NAME, sizeof(BTA_PBS_OCHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_OCH_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_MCHFOLDER_NAME, sizeof(BTA_PBS_MCHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_MCH_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_CCHFOLDER_NAME, sizeof(BTA_PBS_CCHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_CCH_OBJ;
+ BCM_STRNCPY_S(p_cb->p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->p_path, p_bta_fs_cfg->max_path_len);
+ p_cb->p_workdir[p_bta_fs_cfg->max_path_len] = '\0';
+ APPL_TRACE_DEBUG1("PBS: SET NEW PATH [%s]", p_cb->p_workdir);
+ }
+ break;
+
+ default:
+ p_cb->acc_active = old_acc_active;
+ APPL_TRACE_WARNING1("PBS ACCRSP: Unknown tBTA_PBS_OPER value (%d)",
+ p_cb->acc_active);
+ break;
+ }
+
+ /* Set Path Done */
+ if(p_rsp && old_acc_active == BTA_PBS_OPER_SET_PB)
+ {
+ switch (status)
+ {
+ case BTA_PBS_CO_OK:
+ rsp_code = OBX_RSP_OK;
+ break;
+ case BTA_PBS_CO_EACCES:
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ break;
+ default:
+ rsp_code = OBX_RSP_SERVICE_UNAVL;
+ break;
+ }
+ if (p_cb->p_cback)
+ {
+ objevt.operation = p_cb->obx_oper;
+ objevt.p_name = p_cb->p_path;
+ objevt.status = (status == BTA_PBS_CO_OK ? BTA_PBS_OK: BTA_PBS_FAIL);
+ (p_cb->p_cback) (BTA_PBS_OPER_CMPL_EVT, (tBTA_PBS *) &objevt);
+ }
+ utl_freebuf((void**)&p_cb->p_name);
+ utl_freebuf((void**)&p_cb->p_path);
+ p_cb->obx_oper = BTA_PBS_OPER_NONE;
+ (*p_rsp)(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_ci_vlist_act
+**
+** Description Continue getting the current vlist entry operation
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_ci_vlist_act(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ UINT8 rsp_code;
+ tBTA_PBS_CI_VLIST_EVT *p_revt = &p_data->vlist_evt;
+
+ p_cb->cout_active = FALSE;
+
+ /* Process vcard listing call-in event if operation is still active */
+ if (p_cb->obx_oper == BTA_PBS_OPER_PULL_VCARD_LIST)
+ {
+ switch (p_revt->status)
+ {
+ case BTA_PBS_CO_OK:
+ p_cb->num_vlist_idxs++;
+
+ /* Valid new entry */
+ if (!strcmp(p_cb->vlist.handle, ".") || !strcmp(p_cb->vlist.handle, "..")
+ || p_cb->vlist.handle[0] == '\0') {
+ /* don't count this entry */
+ p_cb->num_vlist_idxs--;
+
+ /* continue get */
+ if (p_revt->final) {
+ /* if it is final */
+ bta_pbs_end_of_list(OBX_RSP_OK);
+ } else {
+ p_cb->cout_active = TRUE;
+ bta_pbs_co_getvlist(p_cb->p_path, &p_cb->getvlist_app_params,
+ FALSE, &p_cb->vlist);
+ }
+ } else if ((rsp_code = bta_pbs_add_list_entry()) == OBX_RSP_OK) {
+ /* if we can add the entry */
+ if (p_revt->final) {
+ /* if it is final */
+ bta_pbs_end_of_list(rsp_code);
+ } else {
+ /* continue get */
+ p_cb->cout_active = TRUE;
+ bta_pbs_co_getvlist(p_cb->p_path, &p_cb->getvlist_app_params,
+ FALSE, &p_cb->vlist);
+ }
+ } else if (rsp_code == OBX_RSP_CONTINUE) {
+ /* do not have enough data buffer, send obex continue to client */
+ if (p_revt->final) {
+ /* if this is the last VCard list entry */
+ p_cb->obx.final_pkt = TRUE;
+ }
+ bta_pbs_end_of_list(rsp_code);
+ } else {
+ bta_pbs_end_of_list(rsp_code);
+ }
+ break;
+
+ case BTA_PBS_CO_FAIL: /* Error occurred */
+ bta_pbs_end_of_list(OBX_RSP_SERVICE_UNAVL);
+ break;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_ci_read
+**
+** Description Handles the response to a read call-out request.
+** This is called within the OBX get file request. If the
+** operation has completed, the OBX response is sent out;
+** otherwise a read for additional data is made.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_ci_read_act(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_CI_READ_EVT *p_revt = &p_data->read_evt;
+ UINT8 rsp_code = OBX_RSP_SERVICE_UNAVL;
+
+ p_cb->cout_active = FALSE;
+ if (p_cb->aborting)
+ {
+ bta_pbs_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_OK, (BT_HDR *)NULL);
+ return;
+ }
+
+ /* Process read call-in event if operation is still active */
+ if ((p_cb->obx_oper == BTA_PBS_OPER_PULL_PB || p_cb->obx_oper == BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ && p_revt->fd == p_cb->fd)
+ {
+ /* Read was successful, not finished yet */
+ if (p_revt->status == BTA_PBS_CO_OK && !p_revt->final)
+ rsp_code = OBX_RSP_CONTINUE;
+ if (p_revt->status == BTA_PBS_CO_OK && p_revt->final)
+ rsp_code = OBX_RSP_OK;
+
+ /* Process response to OBX client */
+ bta_pbs_get_file_rsp(rsp_code, p_revt->num_read);
+ }
+ else
+ {
+ bta_pbs_get_file_rsp(rsp_code, 0);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_ci_open
+**
+** Description Continue with the current file open operation
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_ci_open_act(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_CI_OPEN_EVT *p_open = &p_data->open_evt;
+ UINT8 rsp_code = OBX_RSP_OK;
+ tBTA_PBS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT16 pb_size = 0, new_missed_call = 0, len=0;
+ UINT8 *p, *p_start;
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->aborting)
+ {
+ bta_pbs_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_OK, (BT_HDR *)NULL);
+ return;
+ }
+
+ /* Only process file get operations */
+ if (p_cb->obx_oper == BTA_PBS_OPER_PULL_PB || p_cb->obx_oper == BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ {
+ if (p_open->status == BTA_PBS_CO_OK)
+ {
+ p_cb->file_length = p_open->file_size;
+ p_cb->fd = p_open->fd;
+
+ /* add other application header */
+ if (p_cb->obx_oper == BTA_PBS_OPER_PULL_PB)
+ {
+ if (p_cb->pullpb_app_params.max_count == 0 ||
+ p_cb->obj_type == BTA_PBS_MCH_OBJ)
+ {
+ p_start = OBX_AddByteStrStart(p_obx->p_pkt, &len);
+ bta_pbs_co_getpbinfo(p_cb->obx_oper, p_cb->obj_type, &pb_size, &new_missed_call);
+ p = p_start;
+ if (p_cb->pullpb_app_params.max_count == 0)
+ {
+ *p++ = BTA_PBS_TAG_PB_SIZE;
+ *p++ = 2;
+ UINT16_TO_BE_STREAM(p, pb_size);
+ /* if max count = 0, client want to know the pb size */
+ p_cb->file_length = 0;
+ }
+ if (p_cb->obj_type == BTA_PBS_MCH_OBJ)
+ {
+ *p++ = BTA_PBS_TAG_NEW_MISSED_CALLS;
+ *p++ = 1;
+ *p++ = (UINT8) new_missed_call;
+ }
+ OBX_AddByteStrHdr(p_obx->p_pkt, OBX_HI_APP_PARMS, NULL, (UINT16)(p - p_start));
+ }
+ }
+
+ if (p_cb->file_length > 0)
+ {
+ /* contiune to get file */
+ bta_pbs_proc_get_file(p_cb->p_name, p_cb->obx_oper);
+ }
+ else
+ {
+ /* If file length is zero, add end body header */
+ if (((p_cb->obx_oper == BTA_PBS_OPER_PULL_PB) && p_cb->pullpb_app_params.max_count) || p_cb->obx_oper == BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ {
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, 0, TRUE);
+ }
+ bta_pbs_get_file_rsp(rsp_code, 0);
+ }
+ }
+ else
+ {
+ if (p_open->status == BTA_PBS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ else /* File could not be found */
+ rsp_code = OBX_RSP_NOT_FOUND;
+
+ /* Send OBX response if an error occurred */
+ bta_pbs_get_file_rsp(rsp_code, 0);
+ }
+ }
+
+ return;
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_connect
+**
+** Description Process the OBX connect event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_connect(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ tBTA_PBS_OPEN open_evt;
+ char *p_devname;
+
+ p_cb->peer_mtu = p_evt->param.conn.mtu;
+ memcpy(p_cb->bd_addr, p_evt->param.conn.peer_addr, BD_ADDR_LEN);
+ APPL_TRACE_EVENT1("PBS Connect: peer mtu 0x%04x", p_cb->peer_mtu);
+
+ OBX_ConnectRsp(p_evt->handle, OBX_RSP_OK, (BT_HDR *)NULL);
+
+ /* Reset to the root directory */
+ BCM_STRNCPY_S(p_cb->p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->p_rootpath, p_bta_fs_cfg->max_path_len);
+ p_cb->p_workdir[p_bta_fs_cfg->max_path_len] = '\0';
+
+ /* inform role manager */
+ bta_sys_conn_open(BTA_ID_PBS ,p_cb->app_id, p_cb->bd_addr);
+
+ /* Notify the MMI that a connection has been opened */
+ memcpy(open_evt.bd_addr, p_evt->param.conn.peer_addr, BD_ADDR_LEN);
+ if ((p_devname = BTM_SecReadDevName(p_cb->bd_addr)) != NULL)
+ BCM_STRNCPY_S((char *)open_evt.dev_name, sizeof(tBTM_BD_NAME), p_devname, BTM_MAX_REM_BD_NAME_LEN);
+
+ p_cb->p_cback(BTA_PBS_OPEN_EVT, (tBTA_PBS *) &open_evt);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_disc
+**
+** Description Process the OBX disconnect event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_disc(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code;
+
+ rsp_code = (p_evt->obx_event == OBX_DISCONNECT_REQ_EVT) ? OBX_RSP_OK
+ : OBX_RSP_BAD_REQUEST;
+ OBX_DisconnectRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_close
+**
+** Description Process the OBX link lost event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_close(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ /* finished if not waiting on a call-in function */
+ if (!p_cb->cout_active)
+ bta_pbs_sm_execute(p_cb, BTA_PBS_CLOSE_CMPL_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_abort
+**
+** Description Process the OBX abort event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_abort(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_OK;
+
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ if (!p_cb->cout_active)
+ {
+ bta_pbs_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ }
+ else /* Delay the response if a call-out function is active */
+ p_cb->aborting = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_password
+**
+** Description Process the OBX password request
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_password(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ tBTA_PBS_AUTH *p_auth;
+ BOOLEAN is_challenged;
+ tOBX_AUTH_OPT options;
+
+ if ((p_auth = (tBTA_PBS_AUTH *)GKI_getbuf(sizeof(tBTA_PBS_AUTH))) != NULL)
+ {
+ memset(p_auth, 0, sizeof(tBTA_PBS_AUTH));
+
+ /* Extract user id from packet (if available) */
+ if (OBX_ReadAuthParams(p_data->obx_evt.p_pkt, &p_auth->p_userid,
+ &p_auth->userid_len,
+ &is_challenged, &options))
+ {
+ if (options & OBX_AO_USR_ID)
+ p_auth->userid_required = TRUE;
+ }
+
+
+ /* Notify application */
+ p_cb->p_cback(BTA_PBS_AUTH_EVT, (tBTA_PBS *)p_auth);
+
+ GKI_freebuf(p_auth);
+ }
+ /* Don't need OBX packet any longer */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_get
+**
+** Description Process the OBX file get and folder listing events
+** If the type header is not folder listing, then pulling a file.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_get(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT16 len;
+ UINT8 *p_type;
+ UINT8 *p_param;
+ UINT16 param_len;
+ tBTA_PBS_OPER operation = 0;
+
+ /* If currently processing a GET, use the current name */
+ if (bta_pbs_cb.obx_oper == BTA_PBS_OPER_PULL_VCARD_LIST)
+ bta_pbs_getvlist(p_cb->p_name);
+ else if (bta_pbs_cb.obx_oper == BTA_PBS_OPER_PULL_PB ||
+ bta_pbs_cb.obx_oper == BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ bta_pbs_proc_get_file(p_cb->p_name, bta_pbs_cb.obx_oper);
+ else /* This is a new request */
+ {
+ /* Pull out the name header if it exists */
+ if ((p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_file_len + 1))) != NULL)
+ {
+ if (!OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->p_name, p_bta_fs_cfg->max_file_len))
+ {
+
+ GKI_freebuf(p_cb->p_name);
+ p_cb->p_name = NULL;
+
+#if 0 /* Peer spec violation, but some platforms do this wrong, so relaxing requirement.
+ enable this if strict error checking needed */
+ utl_freebuf((void**)&p_evt->p_pkt);
+ OBX_GetRsp(p_cb->obx_handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ return;
+#endif
+ }
+ } else {
+ OBX_GetRsp(p_cb->obx_handle, OBX_RSP_SERVICE_UNAVL, (BT_HDR *)NULL);
+ utl_freebuf((void**)&p_evt->p_pkt);
+ return;
+ }
+
+ /* See what type of operations */
+ if (OBX_ReadTypeHdr(p_evt->p_pkt, &p_type, &len))
+ {
+ if (!memcmp(p_type, BTA_PBS_GETVCARD_LISTING_TYPE, len))
+ {
+
+ if ((p_cb->p_name) && strlen(p_cb->p_name))
+ {
+ APPL_TRACE_EVENT1("PBS VList Get: Name [%s]", p_cb->p_name);
+ }
+ else /* This is a peer spec violation, but allowing for better IOP */
+ {
+ APPL_TRACE_WARNING0("PBS OBX GET: Missing Name Header...Assuming current directory");
+
+ /* Errata 1824: It is illegal to issue a PullvCardListing request with an empty
+ name header from the "telecom" folder */
+ if (p_cb->p_workdir && !strcmp(&(p_cb->p_workdir[strlen(p_cb->p_workdir) - 7]), "telecom"))
+ {
+ utl_freebuf((void**)&p_evt->p_pkt);
+ OBX_GetRsp(p_cb->obx_handle, OBX_RSP_NOT_FOUND, (BT_HDR *)NULL);
+ return;
+ }
+ }
+
+ /* read application params */
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_MAX_LIST_COUNT, &param_len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT16(p_cb->getvlist_app_params.max_count, p_param);
+ }
+ else
+ {
+ p_cb->getvlist_app_params.max_count = BTA_PBS_MAX_LIST_COUNT;
+ }
+
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_LIST_START_OFFSET, &param_len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT16(p_cb->getvlist_app_params.start_offset, p_param);
+ }
+ else
+ {
+ p_cb->getvlist_app_params.start_offset = 0;
+ }
+
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_ORDER, &param_len);
+ if (p_param)
+ {
+ p_cb->getvlist_app_params.order = *p_param;
+ }
+ else
+ {
+ p_cb->getvlist_app_params.order = BTA_PBS_ORDER_INDEX;
+ }
+
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_SEARCH_ATTRIBUTE, &param_len);
+ if (p_param)
+ {
+ p_cb->getvlist_app_params.attribute = *p_param;
+ }
+ else
+ {
+ p_cb->getvlist_app_params.attribute = 0;
+ }
+
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_SEARCH_VALUE, &param_len);
+ if (p_param)
+ {
+ memcpy(p_cb->getvlist_app_params.p_value, p_param, param_len);
+ p_cb->getvlist_app_params.value_len = param_len;
+ }
+ else
+ {
+ p_cb->getvlist_app_params.value_len = 0;
+ }
+
+ /* Assume downloading vCard Listing if no name */
+ p_cb->obj_type = BTA_PBS_PB_OBJ;
+
+ if (p_cb->p_name)
+ {
+/* if (!memcmp(p_cb->p_name, BTA_PBS_PBFOLDER_NAME, sizeof(BTA_PBS_PBFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_PB_OBJ; <-- default type */
+ if (!memcmp(p_cb->p_name, BTA_PBS_ICHFOLDER_NAME, sizeof(BTA_PBS_ICHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_ICH_OBJ;
+ else if (!memcmp(p_cb->p_name, BTA_PBS_OCHFOLDER_NAME, sizeof(BTA_PBS_OCHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_OCH_OBJ;
+ else if (!memcmp(p_cb->p_name, BTA_PBS_MCHFOLDER_NAME, sizeof(BTA_PBS_MCHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_MCH_OBJ;
+ else if (!memcmp(p_cb->p_name, BTA_PBS_CCHFOLDER_NAME, sizeof(BTA_PBS_CCHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_CCH_OBJ;
+ }
+ bta_pbs_getvlist(p_cb->p_name);
+ }
+ else if (!memcmp(p_type, BTA_PBS_GETFILE_TYPE, len) ||
+ !memcmp(p_type, BTA_PBS_GETVARD_ENTRY_TYPE, len))
+ {
+ if (!memcmp(p_type, BTA_PBS_GETFILE_TYPE, len))
+ operation = BTA_PBS_OPER_PULL_PB;
+ else
+ operation = BTA_PBS_OPER_PULL_VCARD_ENTRY;
+ /* read application params */
+ if (p_cb->p_name)
+ {
+ APPL_TRACE_EVENT2("PBS File Get: Name [%s], operation %d", p_cb->p_name, operation);
+ }
+
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_FILTER, &param_len);
+ if (p_param)
+ {
+ if (param_len == 8)
+ p_param += 4; /* skip the first 4 bytes, we do not handle proprietary AttributesMask */
+ BE_STREAM_TO_UINT32(p_cb->pullpb_app_params.filter, p_param);
+ }
+ else
+ {
+ p_cb->pullpb_app_params.filter = BTA_PBS_FILTER_ALL;
+ }
+
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_FORMAT, &param_len);
+ if (p_param)
+ {
+ p_cb->pullpb_app_params.format = *p_param;
+ }
+ else
+ {
+ p_cb->pullpb_app_params.format = BTA_PBS_VCF_FMT_21;
+ }
+
+ /* set the object type for pull pb */
+ if (operation == BTA_PBS_OPER_PULL_PB)
+ {
+ if (p_cb->p_name == NULL)
+ OBX_GetRsp(p_cb->obx_handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ else
+ {
+ if (!memcmp(p_cb->p_name, BTA_PBS_PULLPB_NAME, sizeof(BTA_PBS_PULLPB_NAME)))
+ p_cb->obj_type = BTA_PBS_PB_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_PULLICH_NAME, sizeof(BTA_PBS_PULLICH_NAME)))
+ p_cb->obj_type = BTA_PBS_ICH_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_PULLOCH_NAME, sizeof(BTA_PBS_PULLOCH_NAME)))
+ p_cb->obj_type = BTA_PBS_OCH_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_PULLMCH_NAME, sizeof(BTA_PBS_PULLMCH_NAME)))
+ p_cb->obj_type = BTA_PBS_MCH_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_PULLCCH_NAME, sizeof(BTA_PBS_PULLCCH_NAME)))
+ p_cb->obj_type = BTA_PBS_CCH_OBJ;
+ }
+ }
+ /* for pull pb, read app params for max list count and start offset */
+ if (operation == BTA_PBS_OPER_PULL_PB)
+ {
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_MAX_LIST_COUNT, &param_len);
+ if (p_param)
+ BE_STREAM_TO_UINT16(p_cb->pullpb_app_params.max_count, p_param);
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_LIST_START_OFFSET, &param_len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT16(p_cb->pullpb_app_params.start_offset, p_param);
+ }
+ else
+ {
+ p_cb->pullpb_app_params.start_offset = 0;
+ }
+ }
+ bta_pbs_proc_get_file(p_cb->p_name, operation);
+ }
+ else {
+ OBX_GetRsp(p_cb->obx_handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ }
+ }
+ }
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_setpath
+**
+** Description Process the PBS change directory requests
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_setpath(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_BAD_REQUEST;
+ tOBX_SETPATH_FLAG *p_flag = &p_evt->param.sp.flag;
+ tBTA_PBS_OPER pbs_op = 0;
+ tBTA_PBS_OBJECT objevt;
+
+ /* Verify flags and handle before accepting */
+ if (p_evt->handle == p_cb->obx_handle &&
+ (((*p_flag) & FLAGS_ARE_MASK) != FLAGS_ARE_ILLEGAL))
+ {
+ p_cb->obx_oper = BTA_PBS_OPER_SET_PB;
+ p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_file_len + 1));
+ p_cb->p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len +
+ p_bta_fs_cfg->max_file_len + 2));
+ if (p_cb->p_name != NULL && p_cb->p_path != NULL)
+ {
+ if (!OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->p_name, p_bta_fs_cfg->max_file_len))
+ {
+ p_cb->p_name[0] = 0;
+ }
+
+ rsp_code = bta_pbs_chdir(p_evt->p_pkt, (BOOLEAN)((*p_flag) & OBX_SPF_BACKUP), &pbs_op);
+ }
+ else
+ rsp_code = OBX_RSP_SERVICE_UNAVL;
+ }
+
+ if(pbs_op)
+ {
+ bta_pbs_req_app_access(pbs_op, p_cb);
+ }
+ else
+ {
+ if (p_cb->p_cback)
+ {
+ objevt.operation = BTA_PBS_OPER_SET_PB;
+ objevt.p_name = p_cb->p_path;
+ objevt.status = (rsp_code == OBX_RSP_OK ? BTA_PBS_OK: BTA_PBS_FAIL);
+ (p_cb->p_cback) (BTA_PBS_OPER_CMPL_EVT, (tBTA_PBS *) &objevt);
+ }
+ p_cb->obx_oper = BTA_PBS_OPER_NONE;
+ OBX_SetPathRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ utl_freebuf((void**)&p_cb->p_name);
+ utl_freebuf((void**)&p_cb->p_path);
+ }
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_appl_tout
+**
+** Description Process the PBS application timeout event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_appl_tout(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_conn_err_rsp
+**
+** Description Process the OBX error response
+** Connect request received in wrong state, or bad request
+** from client
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_conn_err_rsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ OBX_ConnectRsp(p_data->obx_evt.handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_disc_err_rsp
+**
+** Description Process the OBX error response
+** Disconnect request received in wrong state, or bad request
+** from client
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_disc_err_rsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ OBX_DisconnectRsp(p_data->obx_evt.handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_gasp_err_rsp
+**
+** Description Process the OBX error response for Get, Abort, Setpath.
+**
+** The rsp_code field of tBTA_PBS_DATA (obx_evt) contains the
+** response code to be sent to OBEX, and the obx_event field
+** contains the current OBEX event.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_gasp_err_rsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+
+ switch (p_evt->obx_event)
+ {
+ case OBX_GET_REQ_EVT:
+ OBX_GetRsp(p_evt->handle, p_evt->rsp_code, (BT_HDR *)NULL);
+ break;
+ case OBX_SETPATH_REQ_EVT:
+ OBX_SetPathRsp(p_evt->handle, p_evt->rsp_code, (BT_HDR *)NULL);
+ break;
+ case OBX_ABORT_REQ_EVT:
+ OBX_AbortRsp(p_evt->handle, p_evt->rsp_code, (BT_HDR *)NULL);
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_close_complete
+**
+** Description Finishes the memory cleanup after a channel is closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_close_complete(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ p_cb->cout_active = FALSE;
+ bta_pbs_clean_getput(p_cb, TRUE);
+
+ /* inform role manager */
+ bta_sys_conn_close( BTA_ID_PBS ,p_cb->app_id, p_cb->bd_addr);
+
+ memset(p_cb->bd_addr, 0, BD_ADDR_LEN);
+
+ /* Notify the MMI that a connection has been closed */
+ p_cb->p_cback(BTA_PBS_CLOSE_EVT, 0);
+
+ if (p_data->obx_evt.p_pkt)
+ APPL_TRACE_WARNING0("PBS: OBX CLOSE CALLED WITH non-NULL Packet!!!");
+}
+
+/*****************************************************************************
+** Callback Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_pbs_obx_cback
+**
+** Description OBX callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt)
+{
+ tBTA_PBS_OBX_EVENT *p_obx_msg;
+ UINT16 event = 0;
+
+#if BTA_PBS_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("OBX Event Callback: obx_event [%s]", pbs_obx_evt_code(obx_event));
+#endif
+
+ switch(obx_event)
+ {
+ case OBX_CONNECT_REQ_EVT:
+ event = BTA_PBS_OBX_CONN_EVT;
+ break;
+ case OBX_DISCONNECT_REQ_EVT:
+ event = BTA_PBS_OBX_DISC_EVT;
+ break;
+ case OBX_GET_REQ_EVT:
+ event = BTA_PBS_OBX_GET_EVT;
+ break;
+ case OBX_SETPATH_REQ_EVT:
+ event = BTA_PBS_OBX_SETPATH_EVT;
+ break;
+ case OBX_ABORT_REQ_EVT:
+ event = BTA_PBS_OBX_ABORT_EVT;
+ break;
+ case OBX_CLOSE_IND_EVT:
+ event = BTA_PBS_OBX_CLOSE_EVT;
+ break;
+ case OBX_TIMEOUT_EVT:
+ break;
+ case OBX_PASSWORD_EVT:
+ event = BTA_PBS_OBX_PASSWORD_EVT;
+ break;
+ /* send Bad Request for Obex put request */
+ case OBX_PUT_REQ_EVT:
+ OBX_PutRsp(handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ if (p_pkt)
+ utl_freebuf((void**)&p_pkt);
+ return;
+ break;
+ default:
+ /* Unrecognized packet; disconnect the session */
+ if (p_pkt)
+ {
+ event = BTA_PBS_OBX_DISC_EVT;
+ utl_freebuf((void**)&p_pkt);
+ }
+ break;
+ }
+
+ /* send event to BTA, if any */
+ if (event && (p_obx_msg =
+ (tBTA_PBS_OBX_EVENT *) GKI_getbuf(sizeof(tBTA_PBS_OBX_EVENT))) != NULL)
+ {
+ p_obx_msg->hdr.event = event;
+ p_obx_msg->obx_event = obx_event;
+ p_obx_msg->handle = handle;
+ p_obx_msg->param = param;
+ p_obx_msg->p_pkt = p_pkt;
+
+ bta_sys_sendmsg(p_obx_msg);
+ }
+}
+
+/*****************************************************************************
+** Local PBS Event Processing Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_pbs_req_app_access
+**
+** Description Sends an access request event to the application.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_req_app_access (tBTA_PBS_OPER oper, tBTA_PBS_CB *p_cb)
+{
+ tBTA_PBS_ACCESS *p_acc_evt;
+ char *p_devname;
+
+ /* Notify the application that a get file has been requested */
+ if ((p_acc_evt = (tBTA_PBS_ACCESS *)GKI_getbuf(sizeof(tBTA_PBS_ACCESS))) != NULL)
+ {
+ memset(p_acc_evt, 0, sizeof(tBTA_PBS_ACCESS));
+
+ APPL_TRACE_API1("ACCESS REQ: [%s]", p_cb->p_path);
+ p_acc_evt->p_name = p_cb->p_path;
+ p_acc_evt->oper = p_cb->acc_active = oper;
+ bdcpy(p_acc_evt->bd_addr, p_cb->bd_addr);
+ if ((p_devname = BTM_SecReadDevName(p_cb->bd_addr)) != NULL)
+ BCM_STRNCPY_S((char *)p_acc_evt->dev_name, sizeof(tBTM_BD_NAME), p_devname, BTM_MAX_REM_BD_NAME_LEN);
+
+ p_cb->p_cback(BTA_PBS_ACCESS_EVT, (tBTA_PBS *)p_acc_evt);
+ GKI_freebuf(p_acc_evt);
+ }
+}
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_PBS_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function pbs_obx_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *pbs_obx_evt_code(tOBX_EVENT evt_code)
+{
+ switch(evt_code)
+ {
+ case OBX_CONNECT_REQ_EVT:
+ return "OBX_CONNECT_REQ_EVT";
+ case OBX_DISCONNECT_REQ_EVT:
+ return "OBX_DISCONNECT_REQ_EVT";
+ case OBX_GET_REQ_EVT:
+ return "OBX_GET_REQ_EVT";
+ case OBX_SETPATH_REQ_EVT:
+ return "OBX_SETPATH_REQ_EVT";
+ case OBX_ABORT_REQ_EVT:
+ return "OBX_ABORT_REQ_EVT";
+ case OBX_CLOSE_IND_EVT:
+ return "OBX_CLOSE_IND_EVT";
+ case OBX_TIMEOUT_EVT:
+ return "OBX_TIMEOUT_EVT";
+ case OBX_PASSWORD_EVT:
+ return "OBX_PASSWORD_EVT";
+ default:
+ return "unknown OBX event code";
+ }
+}
+#endif /* Debug Functions */
+#endif /* BTA_PBS_INCLUDED */
diff --git a/bta/pb/bta_pbs_api.c b/bta/pb/bta_pbs_api.c
new file mode 100644
index 0000000..c8466f6
--- /dev/null
+++ b/bta/pb/bta_pbs_api.c
@@ -0,0 +1,222 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_api.c
+**
+** Description: This is the implementation of the API for the phone book
+** access server subsystem of BTA, Widcomm's Bluetooth
+** application layer for mobile phones.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_fs_api.h"
+#include "bta_pbs_api.h"
+#include "bta_pbs_int.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_pbs_reg =
+{
+ bta_pbs_hdl_event,
+ BTA_PbsDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_PbsEnable
+**
+** Description Enable the phone book access server. This function must be
+** called before any other functions in the PB Server API are called.
+** When the enable operation is complete the callback function
+** will be called with an BTA_PBS_ENABLE_EVT event.
+** Note: Pbs always enable (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_PbsEnable(tBTA_SEC sec_mask, const char *p_service_name,
+ const char *p_root_path, BOOLEAN enable_authen,
+ UINT8 realm_len, UINT8 *p_realm,
+ tBTA_PBS_CBACK *p_cback, UINT8 app_id)
+{
+ tBTA_PBS_API_ENABLE *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_PBS, &bta_pbs_reg);
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_PBS_API_ENABLE *)GKI_getbuf((UINT16)(sizeof(tBTA_PBS_API_ENABLE) +
+ p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_PBS_API_ENABLE));
+
+ p_buf->p_root_path = (char *)(p_buf + 1);
+ p_buf->p_root_path[0] = '\0';
+
+ p_buf->hdr.event = BTA_PBS_API_ENABLE_EVT;
+ p_buf->p_cback = p_cback;
+ p_buf->sec_mask = (sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+ p_buf->app_id = app_id;
+ p_buf->auth_enabled = enable_authen;
+
+ p_buf->realm_len = (realm_len < OBX_MAX_REALM_LEN) ? realm_len :
+ OBX_MAX_REALM_LEN;
+ if (p_realm)
+ memcpy(p_buf->realm, p_realm, p_buf->realm_len);
+
+ if (p_service_name)
+ {
+ BCM_STRNCPY_S(p_buf->servicename, sizeof(p_buf->servicename), p_service_name, BTA_SERVICE_NAME_LEN);
+ p_buf->servicename[BTA_SERVICE_NAME_LEN] = '\0';
+ }
+
+ if (p_root_path)
+ {
+ BCM_STRNCPY_S(p_buf->p_root_path, p_bta_fs_cfg->max_path_len+1, p_root_path, p_bta_fs_cfg->max_path_len);
+ p_buf->p_root_path[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_PbsDisable
+**
+** Description Disable the Phone book access server. If the server is currently
+** connected to a peer device the connection will be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_PbsDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_PBS);
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_PBS_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+/*******************************************************************************
+**
+** Function BTA_PbsAuthRsp
+**
+** Description Respond to obex client authenticate repond by sending back password to
+** BTA. Called in response to an BTA_PBS_AUTH_EVT event.
+** Used when "enable_authen" is set to TRUE in BTA_PbapsEnable().
+**
+** Note: If the "userid_required" is TRUE in the BTA_PBS_AUTH_EVT
+** event, then p_userid is required, otherwise it is optional.
+**
+** p_password must be less than BTA_PBS_MAX_AUTH_KEY_SIZE (16 bytes)
+** p_userid must be less than OBX_MAX_REALM_LEN (defined in target.h)
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_PbsAuthRsp (char *p_password, char *p_userid)
+{
+ tBTA_PBS_API_AUTHRSP *p_auth_rsp;
+
+ if ((p_auth_rsp = (tBTA_PBS_API_AUTHRSP *)GKI_getbuf(sizeof(tBTA_PBS_API_AUTHRSP))) != NULL)
+ {
+ memset(p_auth_rsp, 0, sizeof(tBTA_PBS_API_AUTHRSP));
+
+ p_auth_rsp->hdr.event = BTA_PBS_API_AUTHRSP_EVT;
+
+ if (p_password)
+ {
+ p_auth_rsp->key_len = strlen(p_password);
+ if (p_auth_rsp->key_len > BTA_PBS_MAX_AUTH_KEY_SIZE)
+ p_auth_rsp->key_len = BTA_PBS_MAX_AUTH_KEY_SIZE;
+ memcpy(p_auth_rsp->key, p_password, p_auth_rsp->key_len);
+ }
+
+ if (p_userid)
+ {
+ p_auth_rsp->userid_len = strlen(p_userid);
+ if (p_auth_rsp->userid_len > OBX_MAX_REALM_LEN)
+ p_auth_rsp->userid_len = OBX_MAX_REALM_LEN;
+ memcpy(p_auth_rsp->userid, p_userid, p_auth_rsp->userid_len);
+ }
+
+ bta_sys_sendmsg(p_auth_rsp);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_PbsAccessRsp
+**
+** Description Sends a reply to an access request event (BTA_PBS_ACCESS_EVT).
+** This call MUST be made whenever the event occurs.
+**
+** Parameters oper - operation being accessed.
+** access - BTA_PBS_ACCESS_ALLOW or BTA_PBS_ACCESS_FORBID
+** p_name - path of file or directory to be accessed.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_PbsAccessRsp(tBTA_PBS_OPER oper, tBTA_PBS_ACCESS_TYPE access, char *p_name)
+{
+ tBTA_PBS_API_ACCESSRSP *p_acc_rsp;
+ UINT16 max_full_name = p_bta_fs_cfg->max_path_len + p_bta_fs_cfg->max_file_len + 1;
+
+ if ((p_acc_rsp = (tBTA_PBS_API_ACCESSRSP *)GKI_getbuf((UINT16)(sizeof(tBTA_PBS_API_ACCESSRSP)
+ + max_full_name + 1))) != NULL)
+ {
+ p_acc_rsp->flag = access;
+ p_acc_rsp->oper = oper;
+ p_acc_rsp->p_name = (char *)(p_acc_rsp + 1);
+ if (p_name)
+ {
+ BCM_STRNCPY_S(p_acc_rsp->p_name, max_full_name+1, p_name, max_full_name);
+ p_acc_rsp->p_name[max_full_name] = '\0';
+ }
+ else
+ p_acc_rsp->p_name[0] = '\0';
+
+ p_acc_rsp->hdr.event = BTA_PBS_API_ACCESSRSP_EVT;
+ bta_sys_sendmsg(p_acc_rsp);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_PbsClose
+**
+** Description Close the current connection.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_PbsClose(void)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_PBS_API_CLOSE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+#endif /* BTA_PBS_INCLUDED */
diff --git a/bta/pb/bta_pbs_cfg.c b/bta/pb/bta_pbs_cfg.c
new file mode 100644
index 0000000..0dc303c
--- /dev/null
+++ b/bta/pb/bta_pbs_cfg.c
@@ -0,0 +1,38 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_cfg.c
+**
+** Description: This file contains compile-time configurable constants
+** for the BTA Phone Book Access Server.
+**
+** Copyright (c) 2003-2005, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+#include "bta_pbs_int.h"
+
+/* Realm Character Set */
+#ifndef BTA_PBS_REALM_CHARSET
+#define BTA_PBS_REALM_CHARSET 0 /* ASCII */
+#endif
+
+/* Specifies whether or not client's user id is required during obex authentication */
+#ifndef BTA_PBS_USERID_REQ
+#define BTA_PBS_USERID_REQ FALSE
+#endif
+
+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,
+};
+
+tBTA_PBS_CFG *p_bta_pbs_cfg = (tBTA_PBS_CFG *)&bta_pbs_cfg;
+#endif /* BTA_PBS_INCLUDED */
diff --git a/bta/pb/bta_pbs_ci.c b/bta/pb/bta_pbs_ci.c
new file mode 100644
index 0000000..fa2644b
--- /dev/null
+++ b/bta/pb/bta_pbs_ci.c
@@ -0,0 +1,119 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_ci.c
+**
+** Description: This is the implementation file for the phone book access server
+** call-in functions.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_pbs_ci.h"
+#include "bta_pbs_int.h"
+#include "gki.h"
+
+/*******************************************************************************
+**
+** Function bta_pbs_ci_read
+**
+** Description This function sends an event to BTA indicating the phone has
+** read in the requested amount of data specified in the
+** bta_pbs_co_read() call-out function.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_pbs_ci_open call-in function.
+** num_bytes_read - number of bytes read into the buffer
+** specified in the read callout-function.
+** status - BTA_PBS_CO_OK if get buffer of data,
+** BTA_PBS_CO_FAIL if an error has occurred.
+** final - indicate whether it is the final data
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_ci_read(int fd, UINT16 num_bytes_read,
+ tBTA_PBS_CO_STATUS status, BOOLEAN final)
+{
+ tBTA_PBS_CI_READ_EVT *p_evt;
+
+ if ((p_evt = (tBTA_PBS_CI_READ_EVT *) GKI_getbuf(sizeof(tBTA_PBS_CI_READ_EVT))) != NULL)
+ {
+ p_evt->hdr.event = BTA_PBS_CI_READ_EVT;
+ p_evt->fd = fd;
+ p_evt->status = status;
+ p_evt->num_read = num_bytes_read;
+ p_evt->final = final;
+
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_ci_open
+**
+** Description This function sends an event to BTA indicating the phone has
+** finished opening a pb for reading.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_pbs_ci_open call-in function.
+** status - BTA_PBS_CO_OK if file was opened in mode specified
+** in the call-out function.
+** BTA_PBS_CO_EACCES if the file exists, but contains
+** the wrong access permissions.
+** BTA_PBS_CO_FAIL if any other error has occurred.
+** file_size - The total size of the file
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_ci_open(int fd, tBTA_PBS_CO_STATUS status, UINT32 file_size)
+{
+ tBTA_PBS_CI_OPEN_EVT *p_evt;
+
+ if ((p_evt = (tBTA_PBS_CI_OPEN_EVT *) GKI_getbuf(sizeof(tBTA_PBS_CI_OPEN_EVT))) != NULL)
+ {
+ p_evt->hdr.event = BTA_PBS_CI_OPEN_EVT;
+ p_evt->fd = fd;
+ p_evt->status = status;
+ p_evt->file_size = file_size;
+
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_ci_getvlist
+**
+** Description This function sends an event to BTA indicating the phone has
+** finished reading a VCard list entry.
+**
+** Parameters
+** status - BTA_PBS_CO_OK if reading Vcard list entry
+** BTA_PBS_CO_FAIL if any other error has occurred.
+** final - whether it is the last entry
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pbs_ci_getvlist(tBTA_PBS_CO_STATUS status, BOOLEAN final)
+{
+ tBTA_PBS_CI_VLIST_EVT *p_evt;
+
+ if ((p_evt = (tBTA_PBS_CI_VLIST_EVT *) GKI_getbuf(sizeof(tBTA_PBS_CI_VLIST_EVT))) != NULL)
+ {
+ p_evt->hdr.event = BTA_PBS_CI_VLIST_EVT;
+ p_evt->status = status;
+ p_evt->final = final;
+
+ bta_sys_sendmsg(p_evt);
+ }
+}
diff --git a/bta/pb/bta_pbs_int.h b/bta/pb/bta_pbs_int.h
new file mode 100644
index 0000000..19045fd
--- /dev/null
+++ b/bta/pb/bta_pbs_int.h
@@ -0,0 +1,305 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_int.h
+**
+** Description: This is the private file for the phone book access
+** server (PBS).
+**
+** Copyright (c) 2003-2010, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_PBS_INT_H
+#define BTA_PBS_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_pbs_api.h"
+#include "bta_pbs_co.h"
+#include "bta_pbs_ci.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+#define BTA_PBS_TARGET_UUID "\x79\x61\x35\xf0\xf0\xc5\x11\xd8\x09\x66\x08\x00\x20\x0c\x9a\x66"
+#define BTA_PBS_UUID_LENGTH 16
+#define BTA_PBS_MAX_AUTH_KEY_SIZE 16 /* Must not be greater than OBX_MAX_AUTH_KEY_SIZE */
+
+#define BTA_PBS_DEFAULT_VERSION 0x0101 /* for PBAP PSE version 1.1 */
+
+#define BTA_PBS_GETVCARD_LISTING_TYPE "x-bt/vcard-listing"
+#define BTA_PBS_GETFILE_TYPE "x-bt/phonebook"
+#define BTA_PBS_GETVARD_ENTRY_TYPE "x-bt/vcard"
+#define BTA_PBS_PULLPB_NAME "telecom/pb.vcf"
+#define BTA_PBS_PULLICH_NAME "telecom/ich.vcf"
+#define BTA_PBS_PULLOCH_NAME "telecom/och.vcf"
+#define BTA_PBS_PULLMCH_NAME "telecom/mch.vcf"
+#define BTA_PBS_PULLCCH_NAME "telecom/cch.vcf"
+#define BTA_PBS_PBFOLDER_NAME "pb"
+#define BTA_PBS_ICHFOLDER_NAME "ich"
+#define BTA_PBS_OCHFOLDER_NAME "och"
+#define BTA_PBS_MCHFOLDER_NAME "mch"
+#define BTA_PBS_CCHFOLDER_NAME "cch"
+
+/* Tags for application parameter obex headers */
+/* application parameter len: number of bytes + 2 (tag&len) */
+#define BTA_PBS_TAG_ORDER 1 /* UINT8 */
+#define BTA_PBS_TAG_SEARCH_VALUE 2 /* string */
+#define BTA_PBS_TAG_SEARCH_ATTRIBUTE 3 /* UINT8 */
+#define BTA_PBS_TAG_MAX_LIST_COUNT 4 /* UINT16 */
+#define BTA_PBS_TAG_LIST_START_OFFSET 5 /* UINT16 */
+#define BTA_PBS_TAG_FILTER 6 /* UINT32 */
+#define BTA_PBS_TAG_FORMAT 7 /* UINT8 */
+#define BTA_PBS_TAG_PB_SIZE 8 /* UINT16 */
+#define BTA_PBS_TAG_NEW_MISSED_CALLS 9 /* UINT8 */
+
+#define BTA_PBS_MAX_LIST_COUNT 65535
+
+typedef tOBX_STATUS (tBTA_PBS_OBX_RSP) (tOBX_HANDLE handle, UINT8 rsp_code, BT_HDR *p_pkt);
+
+/* state machine events */
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_PBS_API_DISABLE_EVT = BTA_SYS_EVT_START(BTA_ID_PBS),
+
+ BTA_PBS_API_AUTHRSP_EVT, /* Response to password request */
+ BTA_PBS_API_ACCESSRSP_EVT, /* Response to an access request */
+ BTA_PBS_API_CLOSE_EVT, /* Response to a close request */
+ BTA_PBS_CI_READ_EVT, /* Response to Read request */
+ BTA_PBS_CI_OPEN_EVT, /* Response to File Open request */
+ BTA_PBS_CI_VLIST_EVT, /* Response to Get Vcard Entry request */
+ BTA_PBS_OBX_CONN_EVT, /* OBX Channel Connect Request */
+ BTA_PBS_OBX_DISC_EVT, /* OBX Channel Disconnect */
+ BTA_PBS_OBX_ABORT_EVT, /* OBX_operation aborted */
+ BTA_PBS_OBX_PASSWORD_EVT, /* OBX password requested */
+ BTA_PBS_OBX_CLOSE_EVT, /* OBX Channel Disconnected (Link Lost) */
+ BTA_PBS_OBX_GET_EVT, /* Read file data or folder listing */
+ BTA_PBS_OBX_SETPATH_EVT, /* Make or Change Directory */
+ BTA_PBS_APPL_TOUT_EVT, /* Timeout waiting for application */
+ BTA_PBS_DISC_ERR_EVT, /* Sends OBX_DisconnectRsp with error code */
+ BTA_PBS_GASP_ERR_EVT, /* Sends Err Resp to Get, Abort, Setpath */
+ BTA_PBS_CLOSE_CMPL_EVT, /* Finished closing channel */
+
+ /* these events are handled outside the state machine */
+ BTA_PBS_API_ENABLE_EVT
+};
+
+typedef UINT16 tBTA_PBS_INT_EVT;
+
+typedef UINT8 tBTA_PBS_STATE;
+
+/* data type for BTA_PBS_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_PBS_CBACK *p_cback;
+ char servicename[BTA_SERVICE_NAME_LEN + 1];
+ char *p_root_path;
+ UINT8 realm [OBX_MAX_REALM_LEN]; /* The realm is intended to be
+ displayed to users so they know
+ which userid and password to use.
+ The first byte of the string is
+ the character set of the string.
+ */
+ UINT8 realm_len;
+ UINT8 sec_mask;
+ UINT8 app_id;
+ BOOLEAN auth_enabled;
+} tBTA_PBS_API_ENABLE;
+
+/* data type for BTA_PBS_API_AUTHRSP_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 key [BTA_PBS_MAX_AUTH_KEY_SIZE]; /* The authentication key.*/
+ UINT8 key_len;
+ UINT8 userid [OBX_MAX_REALM_LEN]; /* The authentication user id.*/
+ UINT8 userid_len;
+} tBTA_PBS_API_AUTHRSP;
+
+/* data type for BTA_PBS_API_ACCESSRSP_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char *p_name;
+ tBTA_PBS_OPER oper;
+ tBTA_PBS_ACCESS_TYPE flag;
+} tBTA_PBS_API_ACCESSRSP;
+
+typedef struct
+{
+ BT_HDR hdr;
+ UINT32 file_size;
+ int fd;
+ tBTA_PBS_CO_STATUS status;
+} tBTA_PBS_CI_OPEN_EVT;
+
+/* Read Ready Event */
+typedef struct
+{
+ BT_HDR hdr;
+ int fd;
+ UINT16 num_read;
+ tBTA_PBS_CO_STATUS status;
+ BOOLEAN final;
+} tBTA_PBS_CI_READ_EVT;
+
+/* Get Vlist Entry Ready Event */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_PBS_CO_STATUS status;
+ BOOLEAN final;
+} tBTA_PBS_CI_VLIST_EVT;
+
+
+/* data type for all obex events
+ hdr.event contains the PBS event
+*/
+typedef struct
+{
+ BT_HDR hdr;
+ tOBX_HANDLE handle;
+ tOBX_EVT_PARAM param;
+ BT_HDR *p_pkt;
+ tOBX_EVENT obx_event;
+ UINT8 rsp_code;
+} tBTA_PBS_OBX_EVENT;
+
+/* union of all event data types */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_PBS_API_ENABLE api_enable;
+ tBTA_PBS_API_AUTHRSP auth_rsp;
+ tBTA_PBS_API_ACCESSRSP access_rsp;
+ tBTA_PBS_OBX_EVENT obx_evt;
+ tBTA_PBS_CI_OPEN_EVT open_evt;
+ tBTA_PBS_CI_READ_EVT read_evt;
+ tBTA_PBS_CI_VLIST_EVT vlist_evt;
+} tBTA_PBS_DATA;
+
+
+/* OBX Response Packet Structure - Holds current response packet info */
+typedef struct
+{
+ BT_HDR *p_pkt; /* (Get/Put) Holds the current OBX header for Put or Get */
+ UINT8 *p_start; /* (Get/Put) Start of the Body of the packet */
+ UINT16 offset; /* (Get/Put) Contains the current offset into the Body (p_start) */
+ UINT16 bytes_left; /* (Get/Put) Holds bytes available left in Obx packet */
+ BOOLEAN final_pkt; /* (Put) Holds the final bit of the Put packet */
+} tBTA_PBS_OBX_PKT;
+
+
+/* PBS control block */
+typedef struct
+{
+ tBTA_PBS_CBACK *p_cback; /* pointer to application callback function */
+ char *p_name; /* Holds name of current operation */
+ char *p_path; /* Holds path of current operation */
+ char *p_rootpath;
+ char *p_workdir; /* Current working directory */
+ UINT8 *p_stream_indexes; /* Contains pointer to beginning of phonebook size area in ob hdr */
+ tBTA_PBS_OBX_PKT obx; /* Holds the current OBX packet information */
+ tBTA_PBS_PULLPB_APP_PARAMS pullpb_app_params; /* PULLPB Application params */
+ tBTA_PBS_VCARDLIST_APP_PARAMS getvlist_app_params; /* Get VLIST Application params */
+ tBTA_PBS_VCARDLIST vlist; /* Holds current directory list information */
+ UINT32 sdp_handle; /* SDP record handle */
+ UINT32 file_length; /* length of file being PUT/GET */
+ int fd; /* File Descriptor of opened file */
+ BD_ADDR bd_addr; /* Device currently connected to */
+ tOBX_HANDLE obx_handle;
+ UINT16 peer_mtu;
+ UINT16 num_vlist_idxs; /* keeps track of number of indexes in vCard listing */
+ UINT8 scn; /* SCN of the FTP server */
+ tBTA_PBS_STATE state; /* state machine state */
+ UINT8 obx_oper; /* current active OBX operation GET FILE, LISTING, etc */
+ UINT8 app_id;
+ BOOLEAN auth_enabled; /* Is OBEX authentication enabled */
+ BOOLEAN cout_active; /* TRUE when waiting for a call-in function */
+ BOOLEAN aborting;
+ BOOLEAN get_only_indexes; /* True if PCE only wants num indexes for vListing response */
+ tBTA_PBS_OPER acc_active; /* op code when waiting for an access rsp (API) (0 not active) */
+ tBTA_PBS_OBJ_TYPE obj_type;
+ UINT8 realm [OBX_MAX_REALM_LEN]; /* The realm is intended to be
+ displayed to users so they know
+ which userid and password to use.
+ The first byte of the string is
+ the character set of the string.
+ */
+ UINT8 realm_len;
+} tBTA_PBS_CB;
+
+
+
+/* Configuration structure */
+typedef struct
+{
+ UINT8 realm_charset; /* Server only */
+ BOOLEAN userid_req; /* TRUE if user id is required during obex authentication (Server only) */
+ UINT8 supported_features; /* Server supported features */
+ UINT8 supported_repositories; /* Server supported repositories */
+
+} tBTA_PBS_CFG;
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* PBS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_PBS_CB bta_pbs_cb;
+#else
+extern tBTA_PBS_CB *bta_pbs_cb_ptr;
+#define bta_pbs_cb (*bta_pbs_cb_ptr)
+#endif
+
+/* PBS configuration constants */
+extern tBTA_PBS_CFG * p_bta_pbs_cfg;
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+extern BOOLEAN bta_pbs_hdl_event(BT_HDR *p_msg);
+extern void bta_pbs_sm_execute(tBTA_PBS_CB *p_cb, UINT16 event, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_sdp_register (tBTA_PBS_CB *p_cb, char *p_service_name);
+extern void bta_pbs_obx_cback (tOBX_HANDLE handle, tOBX_EVENT event,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt);
+
+/* action functions */
+extern void bta_pbs_api_disable(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_api_authrsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_api_accessrsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_api_close(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_connect(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_disc(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_close(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_abort(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_password(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_get(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_setpath(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_appl_tout(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_conn_err_rsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_disc_err_rsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_gasp_err_rsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_close_complete(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_ci_open_act(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_ci_read_act(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_ci_vlist_act(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+/* object store */
+extern void bta_pbs_proc_get_file(char *p_name, tBTA_PBS_OPER operation);
+extern void bta_pbs_req_app_access (tBTA_PBS_OPER oper, tBTA_PBS_CB *p_cb);
+extern void bta_pbs_getvlist(char *p_name);
+/* miscellaneous functions */
+extern void bta_pbs_get_file_rsp(UINT8 rsp_code, UINT16 num_read);
+extern void bta_pbs_clean_getput(tBTA_PBS_CB *p_cb, BOOLEAN is_aborted);
+extern void bta_pbs_end_of_list(UINT8 rsp_code);
+extern UINT8 bta_pbs_add_list_entry(void);
+extern UINT8 bta_pbs_chdir(BT_HDR *p_pkt, BOOLEAN backup_flag, tBTA_PBS_OPER *p_op);
+extern UINT8 * bta_pbs_read_app_params(BT_HDR *p_pkt, UINT8 tag, UINT16 *param_len);
+
+#endif /* BTA_PBS_INT_H */
diff --git a/bta/pb/bta_pbs_main.c b/bta/pb/bta_pbs_main.c
new file mode 100644
index 0000000..1ed892d
--- /dev/null
+++ b/bta/pb/bta_pbs_main.c
@@ -0,0 +1,515 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_main.c
+**
+** Description: This file contains the phone book access server main functions
+** and state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_fs_api.h"
+#include "bta_pbs_api.h"
+#include "bta_pbs_int.h"
+#include "gki.h"
+#include "utl.h"
+#include "obx_api.h"
+#include "rfcdefs.h" /* BT_PSM_RFCOMM */
+#include "bta_fs_co.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* state machine states */
+enum
+{
+ BTA_PBS_IDLE_ST = 0, /* Idle */
+ BTA_PBS_LISTEN_ST, /* Listen - waiting for OBX/RFC connection */
+ BTA_PBS_W4_AUTH_ST, /* Wait for Authentication - (optional) */
+ BTA_PBS_CONN_ST, /* Connected - PBS Session is active */
+ BTA_PBS_CLOSING_ST /* Closing is in progress */
+};
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_PBS_API_DISABLE,
+ BTA_PBS_API_AUTHRSP,
+ BTA_PBS_API_ACCESSRSP,
+ BTA_PBS_API_CLOSE,
+ BTA_PBS_CI_READ,
+ BTA_PBS_CI_OPEN,
+ BTA_PBS_CI_VLIST,
+ BTA_PBS_OBX_CONNECT,
+ BTA_PBS_OBX_DISC,
+ BTA_PBS_OBX_CLOSE,
+ BTA_PBS_OBX_ABORT,
+ BTA_PBS_OBX_PASSWORD,
+ BTA_PBS_OBX_GET,
+ BTA_PBS_OBX_SETPATH,
+ BTA_PBS_APPL_TOUT,
+ BTA_PBS_CONN_ERR_RSP,
+ BTA_PBS_DISC_ERR_RSP,
+ BTA_PBS_GASP_ERR_RSP,
+ BTA_PBS_CLOSE_COMPLETE,
+ BTA_PBS_IGNORE
+};
+
+/* type for action functions */
+typedef void (*tBTA_PBS_ACTION)(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+
+/* action function list */
+const tBTA_PBS_ACTION bta_pbs_action[] =
+{
+ bta_pbs_api_disable,
+ bta_pbs_api_authrsp,
+ bta_pbs_api_accessrsp,
+ bta_pbs_api_close,
+ bta_pbs_ci_read_act,
+ bta_pbs_ci_open_act,
+ bta_pbs_ci_vlist_act,
+ bta_pbs_obx_connect,
+ bta_pbs_obx_disc,
+ bta_pbs_obx_close,
+ bta_pbs_obx_abort,
+ bta_pbs_obx_password,
+ bta_pbs_obx_get,
+ bta_pbs_obx_setpath,
+ bta_pbs_appl_tout,
+ bta_pbs_conn_err_rsp,
+ bta_pbs_disc_err_rsp,
+ bta_pbs_gasp_err_rsp,
+ bta_pbs_close_complete
+};
+
+
+/* state table information */
+#define BTA_PBS_ACTIONS 1 /* number of actions */
+#define BTA_PBS_NEXT_STATE 1 /* position of next state */
+#define BTA_PBS_NUM_COLS 2 /* number of columns in state tables */
+
+/* state table for idle state */
+static const UINT8 bta_pbs_st_idle[][BTA_PBS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_PBS_API_ENABLE_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST}
+};
+
+/* state table for obex/rfcomm connection state */
+static const UINT8 bta_pbs_st_listen[][BTA_PBS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_PBS_API_DISABLE_EVT */ {BTA_PBS_API_DISABLE, BTA_PBS_IDLE_ST},
+/* BTA_PBS_API_AUTHRSP_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_API_ACCESSRSP_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_API_CLOSE_EVT */ {BTA_PBS_API_CLOSE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_CI_READ_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_CI_OPEN_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_CI_VLIST_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_OBX_CONN_EVT */ {BTA_PBS_OBX_CONNECT, BTA_PBS_CONN_ST},
+/* BTA_PBS_OBX_DISC_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_OBX_ABORT_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_OBX_PASSWORD_EVT */ {BTA_PBS_OBX_PASSWORD, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_CLOSE_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_OBX_GET_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_OBX_SETPATH_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_APPL_TOUT_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_DISC_ERR_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_GASP_ERR_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_CLOSE_CMPL_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST}
+};
+
+/* state table for wait for authentication response state */
+static const UINT8 bta_pbs_st_w4_auth[][BTA_PBS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_PBS_API_DISABLE_EVT */ {BTA_PBS_API_DISABLE, BTA_PBS_IDLE_ST},
+/* BTA_PBS_API_AUTHRSP_EVT */ {BTA_PBS_API_AUTHRSP, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_API_ACCESSRSP_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_API_CLOSE_EVT */ {BTA_PBS_API_CLOSE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_CI_READ_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_CI_OPEN_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_CI_VLIST_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_CONN_EVT */ {BTA_PBS_CONN_ERR_RSP, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_DISC_EVT */ {BTA_PBS_OBX_DISC, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_ABORT_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_PASSWORD_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_CLOSE_EVT */ {BTA_PBS_OBX_CLOSE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_GET_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_SETPATH_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_APPL_TOUT_EVT */ {BTA_PBS_APPL_TOUT, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_DISC_ERR_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_GASP_ERR_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_CLOSE_CMPL_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_pbs_st_connected[][BTA_PBS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_PBS_API_DISABLE_EVT */ {BTA_PBS_API_DISABLE, BTA_PBS_IDLE_ST},
+/* BTA_PBS_API_AUTHRSP_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CONN_ST},
+/* BTA_PBS_API_ACCESSRSP_EVT */ {BTA_PBS_API_ACCESSRSP, BTA_PBS_CONN_ST},
+/* BTA_PBS_API_CLOSE_EVT */ {BTA_PBS_API_CLOSE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_CI_READ_EVT */ {BTA_PBS_CI_READ, BTA_PBS_CONN_ST},
+/* BTA_PBS_CI_OPEN_EVT */ {BTA_PBS_CI_OPEN, BTA_PBS_CONN_ST},
+/* BTA_PBS_CI_VLIST_EVT */ {BTA_PBS_CI_VLIST, BTA_PBS_CONN_ST},
+/* BTA_PBS_OBX_CONN_EVT */ {BTA_PBS_CONN_ERR_RSP, BTA_PBS_CONN_ST},
+/* BTA_PBS_OBX_DISC_EVT */ {BTA_PBS_OBX_DISC, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_ABORT_EVT */ {BTA_PBS_OBX_ABORT, BTA_PBS_CONN_ST},
+/* BTA_PBS_OBX_PASSWORD_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_CLOSE_EVT */ {BTA_PBS_OBX_CLOSE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_GET_EVT */ {BTA_PBS_OBX_GET, BTA_PBS_CONN_ST},
+/* BTA_PBS_OBX_SETPATH_EVT */ {BTA_PBS_OBX_SETPATH, BTA_PBS_CONN_ST},
+/* BTA_PBS_APPL_TOUT_EVT */ {BTA_PBS_APPL_TOUT, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_DISC_ERR_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CONN_ST},
+/* BTA_PBS_GASP_ERR_EVT */ {BTA_PBS_GASP_ERR_RSP, BTA_PBS_CONN_ST},
+/* BTA_PBS_CLOSE_CMPL_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CONN_ST}
+};
+
+/* state table for closing state */
+static const UINT8 bta_pbs_st_closing[][BTA_PBS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_PBS_API_DISABLE_EVT */ {BTA_PBS_API_DISABLE, BTA_PBS_IDLE_ST},
+/* BTA_PBS_API_AUTHRSP_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_API_ACCESSRSP_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_API_CLOSE_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_CI_READ_EVT */ {BTA_PBS_CLOSE_COMPLETE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_CI_OPEN_EVT */ {BTA_PBS_CLOSE_COMPLETE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_CI_VLIST_EVT */ {BTA_PBS_CLOSE_COMPLETE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_OBX_CONN_EVT */ {BTA_PBS_CONN_ERR_RSP, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_DISC_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_ABORT_EVT */ {BTA_PBS_OBX_ABORT, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_PASSWORD_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_CLOSE_EVT */ {BTA_PBS_OBX_CLOSE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_GET_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_SETPATH_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_APPL_TOUT_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_DISC_ERR_EVT */ {BTA_PBS_DISC_ERR_RSP, BTA_PBS_CONN_ST},
+/* BTA_PBS_GASP_ERR_EVT */ {BTA_PBS_GASP_ERR_RSP, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_CLOSE_CMPL_EVT */ {BTA_PBS_CLOSE_COMPLETE, BTA_PBS_LISTEN_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_PBS_ST_TBL)[BTA_PBS_NUM_COLS];
+
+/* state table */
+const tBTA_PBS_ST_TBL bta_pbs_st_tbl[] =
+{
+ bta_pbs_st_idle,
+ bta_pbs_st_listen,
+ bta_pbs_st_w4_auth,
+ bta_pbs_st_connected,
+ bta_pbs_st_closing
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* PBS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_PBS_CB bta_pbs_cb;
+#endif
+
+#if BTA_PBS_DEBUG == TRUE
+static char *pbs_evt_code(tBTA_PBS_INT_EVT evt_code);
+static char *pbs_state_code(tBTA_PBS_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function bta_pbs_sm_execute
+**
+** Description State machine event handling function for PBS
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_sm_execute(tBTA_PBS_CB *p_cb, UINT16 event, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_ST_TBL state_table;
+ UINT8 action;
+ int i;
+ tBTA_PBS_OBX_EVENT *p_obex_event;
+#if BTA_PBS_DEBUG == TRUE
+ tBTA_PBS_STATE in_state = bta_pbs_cb.state;
+ UINT16 in_event = event;
+ APPL_TRACE_EVENT3("PBS Event : State 0x%02x [%s], Event [%s]", in_state,
+ pbs_state_code(in_state),
+ pbs_evt_code(event));
+#endif
+
+ /* look up the state table for the current state */
+ state_table = bta_pbs_st_tbl[p_cb->state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_cb->state = state_table[event][BTA_PBS_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_PBS_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_PBS_IGNORE)
+ {
+ (*bta_pbs_action[action])(p_cb, p_data);
+ }
+ else
+ {
+ if (event >= BTA_PBS_OBX_CONN_EVT && event <= BTA_PBS_OBX_SETPATH_EVT) {
+ p_obex_event = (tBTA_PBS_OBX_EVENT *) p_data;
+ utl_freebuf((void**)&(p_obex_event->p_pkt));
+ }
+ break;
+ }
+ }
+
+#if BTA_PBS_DEBUG == TRUE
+ if (in_state != bta_pbs_cb.state)
+ {
+ APPL_TRACE_DEBUG3("PBS State Change: [%s] -> [%s] after Event [%s]",
+ pbs_state_code(in_state),
+ pbs_state_code(bta_pbs_cb.state),
+ pbs_evt_code(in_event));
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_api_enable
+**
+** Description Handle an api enable event. This function enables the PBS
+** Server by opening an Obex/Rfcomm channel and placing it into
+** listen mode.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_pbs_api_enable(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tOBX_StartParams start_msg;
+ tBTA_PBS_API_ENABLE *p_api = &p_data->api_enable;
+ tOBX_TARGET target;
+ UINT16 len;
+ tOBX_STATUS status;
+ tBTA_UTL_COD cod;
+
+ /* initialize control block */
+ memset(p_cb, 0, sizeof(tBTA_PBS_CB));
+
+ /* Allocate an aligned memory buffer to hold the root path and working directory */
+ /* Add 1 byte for '\0' */
+ len = p_bta_fs_cfg->max_path_len + 1;
+ if ((p_cb->p_rootpath = (char *)GKI_getbuf((UINT16)(len * 2))) != NULL)
+ {
+ p_cb->p_workdir = p_cb->p_rootpath + len;
+ memcpy(target.target, BTA_PBS_TARGET_UUID, BTA_PBS_UUID_LENGTH);
+ target.len = BTA_PBS_UUID_LENGTH;
+
+ /* store parameters */
+ p_cb->app_id = p_api->app_id;
+ p_cb->p_cback = p_api->p_cback;
+ p_cb->scn = BTM_AllocateSCN();
+ p_cb->auth_enabled = p_api->auth_enabled;
+ p_cb->fd = BTA_FS_INVALID_FD;
+ p_cb->realm_len = p_api->realm_len;
+ memcpy(p_cb->realm, p_api->realm, p_api->realm_len);
+
+ /* Initialize the current working directory to be the root directory */
+ BCM_STRNCPY_S(p_cb->p_rootpath, len, p_api->p_root_path, p_bta_fs_cfg->max_path_len);
+ p_cb->p_rootpath[len-1] = '\0';
+ BCM_STRNCPY_S(p_cb->p_workdir, len, p_api->p_root_path, p_bta_fs_cfg->max_path_len);
+ p_cb->p_workdir[len-1] = '\0';
+
+ /* Register PBS security requirements with BTM */
+ BTM_SetSecurityLevel(FALSE, p_api->servicename, BTM_SEC_SERVICE_PBAP,
+ p_api->sec_mask, BT_PSM_RFCOMM,
+ BTM_SEC_PROTO_RFCOMM, (UINT32)p_cb->scn);
+
+ /* Start up the PBS service */
+ memset (&start_msg, 0, sizeof(tOBX_StartParams));
+ start_msg.p_target = &target;
+
+ /* Make the MTU fit into one RFC frame */
+ start_msg.mtu = OBX_MAX_MTU;
+ start_msg.scn = p_cb->scn;
+ start_msg.authenticate = p_cb->auth_enabled;
+
+ start_msg.auth_option = (p_bta_pbs_cfg->userid_req) ? OBX_AO_USR_ID : OBX_AO_NONE;
+ start_msg.p_cback = bta_pbs_obx_cback;
+
+ start_msg.realm_len = p_api->realm_len;
+ start_msg.p_realm = p_api->realm;
+ start_msg.realm_charset = (tOBX_CHARSET) p_bta_pbs_cfg->realm_charset;
+
+ if ((status = OBX_StartServer (&start_msg, &p_cb->obx_handle)) == OBX_SUCCESS)
+ {
+ p_cb->state = BTA_PBS_LISTEN_ST;
+
+ /* Set the File Transfer service class bit */
+ cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
+ utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
+
+ /* Set up the SDP record for pbs service */
+ bta_pbs_sdp_register(p_cb, p_api->servicename);
+ }
+ else
+ APPL_TRACE_ERROR1("OBX_StartServer returns error (%d)", status);
+ }
+ else /* Cannot allocate resources to run Server */
+ APPL_TRACE_ERROR0("Not enough Resources to run PBS Server");
+
+ p_cb->p_cback(BTA_PBS_ENABLE_EVT, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_hdl_event
+**
+** Description File transfer server main event handling function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_pbs_hdl_event(BT_HDR *p_msg)
+{
+#if BTA_PBS_DEBUG == TRUE
+ tBTA_PBS_STATE in_state = bta_pbs_cb.state;
+#endif
+
+ switch (p_msg->event)
+ {
+ case BTA_PBS_API_ENABLE_EVT:
+#if BTA_PBS_DEBUG == TRUE
+ APPL_TRACE_EVENT3("PBS Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ pbs_state_code(in_state),
+ pbs_evt_code(p_msg->event));
+#endif
+ bta_pbs_api_enable(&bta_pbs_cb, (tBTA_PBS_DATA *) p_msg);
+
+#if BTA_PBS_DEBUG == TRUE
+ if (in_state != bta_pbs_cb.state)
+ {
+ APPL_TRACE_DEBUG3("PBS State Change: [%s] -> [%s] after Event [%s]",
+ pbs_state_code(in_state),
+ pbs_state_code(bta_pbs_cb.state),
+ pbs_evt_code(p_msg->event));
+ }
+#endif
+ break;
+
+ default:
+ bta_pbs_sm_execute(&bta_pbs_cb, p_msg->event, (tBTA_PBS_DATA *) p_msg);
+ break;
+ }
+
+ return (TRUE);
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_PBS_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function pbs_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *pbs_evt_code(tBTA_PBS_INT_EVT evt_code)
+{
+ switch(evt_code)
+ {
+ case BTA_PBS_API_DISABLE_EVT:
+ return "BTA_PBS_API_DISABLE_EVT";
+ case BTA_PBS_API_AUTHRSP_EVT:
+ return "BTA_PBS_API_AUTHRSP_EVT";
+ case BTA_PBS_API_ACCESSRSP_EVT:
+ return "BTA_PBS_API_ACCESSRSP_EVT";
+ case BTA_PBS_API_CLOSE_EVT:
+ return "BTA_PBS_API_CLOSE_EVT";
+ case BTA_PBS_CI_READ_EVT:
+ return "BTA_PBS_CI_READ_EVT";
+ case BTA_PBS_CI_OPEN_EVT:
+ return "BTA_PBS_CI_OPEN_EVT";
+ case BTA_PBS_CI_VLIST_EVT:
+ return "BTA_PBS_CI_VLIST_EVT";
+ case BTA_PBS_OBX_CONN_EVT:
+ return "BTA_PBS_OBX_CONN_EVT";
+ case BTA_PBS_OBX_DISC_EVT:
+ return "BTA_PBS_OBX_DISC_EVT";
+ case BTA_PBS_OBX_ABORT_EVT:
+ return "BTA_PBS_OBX_ABORT_EVT";
+ case BTA_PBS_OBX_PASSWORD_EVT:
+ return "BTA_PBS_OBX_PASSWORD_EVT";
+ case BTA_PBS_OBX_CLOSE_EVT:
+ return "BTA_PBS_OBX_CLOSE_EVT";
+ case BTA_PBS_OBX_GET_EVT:
+ return "BTA_PBS_OBX_GET_EVT";
+ case BTA_PBS_OBX_SETPATH_EVT:
+ return "BTA_PBS_OBX_SETPATH_EVT";
+ case BTA_PBS_APPL_TOUT_EVT:
+ return "BTA_PBS_APPL_TOUT_EVT";
+ case BTA_PBS_DISC_ERR_EVT:
+ return "BTA_PBS_DISC_ERR_EVT";
+ case BTA_PBS_GASP_ERR_EVT:
+ return "BTA_PBS_GASP_ERR_EVT";
+ case BTA_PBS_API_ENABLE_EVT:
+ return "BTA_PBS_API_ENABLE_EVT";
+ case BTA_PBS_CLOSE_CMPL_EVT:
+ return "BTA_PBS_CLOSE_CMPL_EVT";
+ default:
+ APPL_TRACE_EVENT1("unknown PBS Event: %d", evt_code)
+ return "unknown PBS event code";
+ }
+}
+
+/*******************************************************************************
+**
+** Function pbs_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *pbs_state_code(tBTA_PBS_STATE state_code)
+{
+ switch(state_code)
+ {
+ case BTA_PBS_IDLE_ST:
+ return "BTA_PBS_IDLE_ST";
+ case BTA_PBS_LISTEN_ST:
+ return "BTA_PBS_LISTEN_ST";
+ case BTA_PBS_W4_AUTH_ST:
+ return "BTA_PBS_W4_AUTH_ST";
+ case BTA_PBS_CONN_ST:
+ return "BTA_PBS_CONN_ST";
+ case BTA_PBS_CLOSING_ST:
+ return "BTA_PBS_CLOSING_ST";
+ default:
+ return "unknown PBS state code";
+ }
+}
+
+#endif /* Debug Functions */
+#endif /* BTA_PBS_INCLUDED */
diff --git a/bta/pb/bta_pbs_sdp.c b/bta/pb/bta_pbs_sdp.c
new file mode 100644
index 0000000..eeec573
--- /dev/null
+++ b/bta/pb/bta_pbs_sdp.c
@@ -0,0 +1,113 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_sdp.c
+**
+** File: Implements the SDP functions used by Phone Book Access Server
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "sdp_api.h"
+#include "bta_pbs_int.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+
+/*****************************************************************************
+**
+** Function: bta_pbs_sdp_register()
+**
+** Purpose: Registers the PBS service with SDP
+**
+** Parameters:
+**
+**
+** Returns: void
+**
+*****************************************************************************/
+void bta_pbs_sdp_register (tBTA_PBS_CB *p_cb, char *p_service_name)
+{
+ tSDP_PROTOCOL_ELEM protoList [3];
+ UINT16 pbs_service = UUID_SERVCLASS_PBAP_PSE;
+// btla-specific ++
+ UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
+// btla-specific --
+ BOOLEAN status = FALSE;
+
+ if ((p_cb->sdp_handle = SDP_CreateRecord()) == 0)
+ {
+ APPL_TRACE_WARNING0("PBS SDP: Unable to register PBS Service");
+ return;
+ }
+
+ /* add service class */
+ if (SDP_AddServiceClassIdList(p_cb->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] = p_cb->scn;
+ protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
+ protoList[2].num_params = 0;
+
+ if (SDP_AddProtocolList(p_cb->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(p_cb->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(p_cb->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)
+ {
+// btla-specific ++
+ // SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE,
+ // (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_features);
+ SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE,
+ (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_repositories);
+
+ /* Make the service browseable */
+ SDP_AddUuidSequence (p_cb->sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
+// btla-specific --
+ }
+
+ if (!status)
+ {
+ SDP_DeleteRecord(p_cb->sdp_handle);
+ 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)", p_cb->sdp_handle);
+ }
+
+ return;
+}
+#endif /* BTA_PBS_INCLUDED */
diff --git a/bta/pb/bta_pbs_utils.c b/bta/pb/bta_pbs_utils.c
new file mode 100644
index 0000000..61d7401
--- /dev/null
+++ b/bta/pb/bta_pbs_utils.c
@@ -0,0 +1,734 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_utils.c
+**
+** Description: This file implements utils functions for phone book access
+** server.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+#include <stdio.h>
+#include <string.h>
+#include "bta_fs_api.h"
+#include "bta_pbs_int.h"
+#include "bta_fs_co.h"
+#include "gki.h"
+#include "utl.h"
+
+/*******************************************************************************
+** Constants
+*******************************************************************************/
+
+/*******************************************************************************
+** Local Function Prototypes
+*******************************************************************************/
+static void bta_pbs_translate_special_character(char *buffer, const char *str);
+/*******************************************************************************
+* Macros for PBS
+*******************************************************************************/
+#define BTA_PBS_XML_EOL "\n"
+#define BTA_PBS_FOLDER_LISTING_START ( "<?xml version=\"1.0\"?>\n" \
+ "<!DOCTYPE vcard-listing SYSTEM \"vcard-listing.dtd\">\n" \
+ "<vCard-listing version=\"1.0\">\n" )
+
+#define BTA_PBS_FOLDER_LISTING_END ( "</vCard-listing>" )
+#define BTA_PBS_PARENT_FOLDER (" <parent-folder/>\n")
+
+#define BTA_PBS_CARD_ELEM "card handle"
+#define BTA_PBS_NAME_ATTR "name"
+
+/*******************************************************************************
+* Exported Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function bta_pbs_getdirlist
+**
+** Description Processes the retrieval of a directory listing.
+**
+** Parameters p_pkt - Pointer to the OBX Get request
+** name directory to list.
+**
+**
+** Returns UINT8 - OBX response code. OBX_RSP_OK if initiated.
+**
+*******************************************************************************/
+void bta_pbs_getvlist(char *p_name)
+{
+ tBTA_PBS_CB *p_cb = &bta_pbs_cb;
+ tBTA_PBS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT16 temp_len;
+ UINT8 rsp_code = OBX_RSP_OK;
+ UINT16 pb_size, new_missed_call, len=0;
+ UINT8 *p, *p_start;
+ char *p_sep = NULL;
+
+
+ /* if this the first time asking for access */
+ if (!p_cb->p_path)
+ {
+ p_cb->p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1));
+ /* If not specified, use the current work directory */
+ if (!p_name || p_name[0] == '\0')
+ {
+ BCM_STRNCPY_S(p_cb->p_path, p_bta_fs_cfg->max_path_len+1, p_cb->p_workdir, p_bta_fs_cfg->max_path_len);
+ p_sep = strchr((char *)p_cb->p_path, '/');
+ if (p_sep)
+ *p_sep = p_bta_fs_cfg->path_separator;
+ }
+ else
+ {
+ if ((strlen(p_cb->p_workdir) + strlen(p_name) + 2) <= p_bta_fs_cfg->max_path_len)
+ {
+ sprintf(p_cb->p_path, "%s%c%s", p_cb->p_workdir,
+ p_bta_fs_cfg->path_separator, p_name);
+ if (p_bta_fs_cfg->path_separator == 0x5c)
+ {
+ while ((p_sep = strchr((char *)p_cb->p_path, '/')) != NULL)
+ {
+ if (p_sep)
+ *p_sep = p_bta_fs_cfg->path_separator;
+ }
+ }
+ }
+ else
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+ if (rsp_code == OBX_RSP_OK)
+ {
+ p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /* p_cb->peer_mtu */ OBX_LRG_DATA_POOL_SIZE);
+ if (p_obx->p_pkt)
+ {
+ /* Notify the application that a get file has been requested */
+ bta_pbs_req_app_access (BTA_PBS_OPER_PULL_VCARD_LIST, p_cb);
+ return;
+ }
+ else
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ bta_pbs_clean_getput(p_cb, TRUE);
+ }
+ else if (p_cb->p_path)
+ {
+ /* Build the listing */
+ if (rsp_code == OBX_RSP_OK)
+ {
+ if (!p_obx->p_pkt)
+ p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /* p_cb->peer_mtu */ OBX_LRG_DATA_POOL_SIZE);
+ if (p_obx->p_pkt)
+ {
+ /* Is this a new request or continuation? */
+ if ((p_cb->obx_oper == BTA_PBS_OPER_NONE))
+ {
+ p_cb->get_only_indexes = FALSE;
+
+ if (p_cb->getvlist_app_params.max_count == 0 ||
+ p_cb->obj_type == BTA_PBS_MCH_OBJ)
+ {
+ p_start = OBX_AddByteStrStart(p_obx->p_pkt, &len);
+ bta_pbs_co_getpbinfo(p_cb->obx_oper, p_cb->obj_type, &pb_size, &new_missed_call);
+ p = p_start;
+ /* Just looking for number of indexes only ? */
+ if (p_cb->getvlist_app_params.max_count == 0)
+ {
+ *p++ = BTA_PBS_TAG_PB_SIZE;
+ *p++ = 2;
+ p_cb->p_stream_indexes = p; /* save location to store entries later */
+ UINT16_TO_BE_STREAM(p, p_cb->getvlist_app_params.max_count);
+
+ /* overwrite appl params max count so entries will be retrieved */
+ p_cb->getvlist_app_params.max_count = BTA_PBS_MAX_LIST_COUNT;
+ /* ignore the list start offset */
+ p_cb->getvlist_app_params.start_offset = 0;
+ p_cb->get_only_indexes = TRUE;
+ p_cb->num_vlist_idxs = 0;
+ APPL_TRACE_EVENT1("PBS Get Vcard List: Name [p_stream = 0x%07x] (Indexes Only)", /*p_cb->p_path*/(UINT32)p_cb->p_stream_indexes);
+ }
+
+ if (p_cb->obj_type == BTA_PBS_MCH_OBJ)
+ {
+ *p++ = BTA_PBS_TAG_NEW_MISSED_CALLS;
+ *p++ = 1;
+ *p++ = (UINT8) new_missed_call;
+ }
+ OBX_AddByteStrHdr(p_obx->p_pkt, OBX_HI_APP_PARMS, NULL, (UINT16)(p - p_start));
+ }
+
+ /* By pass Body Header if only requesting number of entries */
+ if (!p_cb->get_only_indexes)
+ {
+ /* Add the start of the Body Header */
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+
+ temp_len = strlen(BTA_PBS_FOLDER_LISTING_START);
+
+ /* Add the beginning label of vard list */
+ memcpy(p_obx->p_start, BTA_PBS_FOLDER_LISTING_START, temp_len);
+ p_obx->bytes_left -= (UINT16)(temp_len + strlen(BTA_PBS_FOLDER_LISTING_END));
+ p_obx->offset += temp_len;
+
+ APPL_TRACE_EVENT1("PBS Get Vcard List: Name [%s]", p_cb->p_path);
+ }
+
+ p_cb->obx_oper = BTA_PBS_OPER_PULL_VCARD_LIST;
+ p_cb->cout_active = TRUE;
+
+ bta_pbs_co_getvlist(p_cb->p_path, &p_cb->getvlist_app_params,
+ TRUE, &p_cb->vlist);
+
+ /* List is not complete, so don't send the response yet */
+ rsp_code = OBX_RSP_PART_CONTENT;
+ }
+ else /* continue case */
+ {
+ /* By pass Body Header if only requesting number of entries */
+ if (!p_cb->get_only_indexes)
+ {
+ /* Add the start of the Body Header */
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+ APPL_TRACE_EVENT1("PBS Get Vcard List: Name [%s] continue", p_cb->p_path);
+ }
+
+ /* Add the entry previously retrieved */
+ rsp_code = bta_pbs_add_list_entry();
+
+ if (!p_obx->final_pkt) {
+ p_cb->cout_active = TRUE;
+
+ bta_pbs_co_getvlist(p_cb->p_path, &p_cb->getvlist_app_params,
+ FALSE, &p_cb->vlist);
+ /* List is not complete, so don't send the response yet */
+ rsp_code = OBX_RSP_PART_CONTENT;
+ } else
+ p_obx->final_pkt = FALSE;
+ }
+ }
+ else
+ rsp_code = OBX_RSP_SERVICE_UNAVL;
+ }
+ }
+ else /* Error occurred */
+ rsp_code = OBX_RSP_SERVICE_UNAVL;
+
+ /* Response goes out if complete or error occurred */
+ if (rsp_code != OBX_RSP_PART_CONTENT)
+ bta_pbs_end_of_list(rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_proc_get_file
+**
+** Description Processes a Get File Operation.
+** If first OBX request, the file is opened, otherwise if it is
+** a continuation the next read is initiated.
+**
+** Parameters p_pkt - Pointer to the OBX Get request
+** name of file to read.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_proc_get_file(char *p_name, tBTA_PBS_OPER operation)
+{
+ tBTA_PBS_CB *p_cb = &bta_pbs_cb;
+ tBTA_PBS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 rsp_code = OBX_RSP_SERVICE_UNAVL;
+ char *p_sep;
+
+ if (operation != BTA_PBS_OPER_PULL_PB && operation != BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ return;
+ /* Allocate an OBX packet */
+ if (p_obx->p_pkt != NULL || (p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /*p_cb->peer_mtu*/OBX_LRG_DATA_POOL_SIZE)) != NULL)
+ {
+ /* Is this a new request or continuation? */
+ if ((p_cb->obx_oper == BTA_PBS_OPER_NONE))
+ {
+ /* Validate the name */
+ if (p_name)
+ {
+ if ((p_cb->p_path =
+ (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ /* Build a fully qualified path for Pull Vcard entry */
+ if (operation == BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ {
+ if ((strlen(p_cb->p_workdir) + strlen(p_name) + 2)
+ <= p_bta_fs_cfg->max_path_len)
+ {
+ rsp_code = OBX_RSP_OK;
+ sprintf(p_cb->p_path, "%s%c%s", p_cb->p_workdir,
+ p_bta_fs_cfg->path_separator, p_name);
+ if (p_bta_fs_cfg->path_separator == 0x5c) {
+ while ((p_sep = strchr((char *)p_cb->p_path, '/')) != NULL)
+ {
+ if (p_sep)
+ *p_sep = p_bta_fs_cfg->path_separator;
+ }
+ }
+
+ APPL_TRACE_EVENT1("PBS PULL VCARD ENTRY: Name [%s]", p_cb->p_path);
+
+ p_cb->obx_oper = BTA_PBS_OPER_PULL_VCARD_ENTRY;
+
+ /* Notify the application that a get file has been requested */
+ bta_pbs_req_app_access (BTA_PBS_OPER_PULL_VCARD_ENTRY, p_cb);
+ }
+ }
+
+ /* Build a fully qualified path for Pull PBentry */
+ if (operation == BTA_PBS_OPER_PULL_PB)
+ {
+ if ((strlen(p_cb->p_rootpath) + strlen(p_name) + 2)
+ <= p_bta_fs_cfg->max_path_len)
+ {
+ rsp_code = OBX_RSP_OK;
+ sprintf(p_cb->p_path, "%s%c%s", p_cb->p_rootpath,
+ p_bta_fs_cfg->path_separator, p_name);
+ if (p_bta_fs_cfg->path_separator == 0x5c) {
+ while ((p_sep = strchr((char *)p_cb->p_path, '/')) != NULL)
+ {
+ if (p_sep)
+ *p_sep = p_bta_fs_cfg->path_separator;
+ }
+ }
+
+ APPL_TRACE_EVENT1("PBS PULL PB : Name [%s]", p_cb->p_path);
+
+ p_cb->obx_oper = BTA_PBS_OPER_PULL_PB;
+
+ /* Notify the application that a get file has been requested */
+ bta_pbs_req_app_access (BTA_PBS_OPER_PULL_PB, p_cb);
+ }
+ }
+
+ }
+ }
+ }
+ else /* Continue reading from the file */
+ {
+ /* Add the start of the Body Header */
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+
+ rsp_code = OBX_RSP_OK;
+ p_cb->cout_active = TRUE;
+ bta_pbs_co_read(p_cb->fd, p_cb->obx_oper, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left);
+ }
+ }
+ if (rsp_code != OBX_RSP_OK)
+ bta_pbs_get_file_rsp(rsp_code, 0);
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_chdir
+**
+** Description Changes the current path to the specified directory.
+**
+** Parameters p_pkt - Pointer to the OBX packet
+** backup_flag - if TRUE, path adjusted up one level.
+**
+** Returns UINT8 - OBX response code
+**
+*******************************************************************************/
+UINT8 bta_pbs_chdir(BT_HDR *p_pkt, BOOLEAN backup_flag, tBTA_PBS_OPER *p_op)
+{
+ tBTA_PBS_CB *p_cb = &bta_pbs_cb;
+ char *p_path;
+ char *p_name;
+ char *p_workdir = p_cb->p_workdir;
+ UINT8 rsp_code = OBX_RSP_SERVICE_UNAVL;
+ BOOLEAN is_dir;
+
+ if (!backup_flag)
+ {
+ p_path = p_cb->p_path;
+ p_name = p_cb->p_name;
+
+ /* If No Name header, or if it is NULL, set to root path */
+ if (*p_name == '\0')
+ {
+ BCM_STRNCPY_S(p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->p_rootpath, p_bta_fs_cfg->max_path_len);
+ p_workdir[p_bta_fs_cfg->max_path_len] = '\0';
+ p_cb->obj_type = BTA_PBS_NONE_OBJ;
+ rsp_code = OBX_RSP_OK;
+ APPL_TRACE_DEBUG0("PBS: Setting current path to ROOT");
+ }
+ /* Make sure the new path is not too big */
+ else if ((strlen(p_name) + strlen(p_workdir) + 2)
+ <= p_bta_fs_cfg->max_path_len)
+ {
+ if (!strcmp(p_name, "pb") || !strcmp(p_name, "telecom") ||
+ !strcmp(p_name, "ich") || !strcmp(p_name, "och") ||
+ !strcmp(p_name, "mch") || !strcmp(p_name, "cch") ||
+ !strcmp(p_name, "SIM1"))
+ {
+
+ /* create a temporary path for creation attempt */
+ sprintf(p_path, "%s%c%s", p_workdir,
+ p_bta_fs_cfg->path_separator, p_name);
+
+ if (((bta_fs_co_access(p_path, BTA_FS_ACC_EXIST,
+ &is_dir, p_cb->app_id)) == BTA_FS_CO_OK) && is_dir)
+ {
+ *p_op = BTA_PBS_OPER_SET_PB;
+ }
+ else
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+ else
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+ }
+ else /* Backing up a directory */
+ {
+ /* Backup a level unless already at root */
+ if (strcmp(p_workdir, p_cb->p_rootpath))
+ {
+ /* Find the last occurrence of separator and replace with '\0' */
+ if ((p_path = strrchr(p_workdir, (int)p_bta_fs_cfg->path_separator)) != NULL)
+ *p_path = '\0';
+ p_cb->obj_type = BTA_PBS_NONE_OBJ;
+ APPL_TRACE_DEBUG1("PBS: SET NEW PATH [%s]", p_cb->p_workdir);
+
+ rsp_code = OBX_RSP_OK;
+ }
+ else
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+
+ return (rsp_code);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_end_of_list
+**
+** Description Finishes up the end body of the listing, and sends out the
+** OBX response
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_end_of_list(UINT8 rsp_code)
+{
+ tBTA_PBS_CB *p_cb = &bta_pbs_cb;
+ tBTA_PBS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT16 temp_len;
+
+ /* Add the end of folder listing string if successful operation */
+ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE)
+ {
+ /* If only getting entries add the number to the response */
+ if (p_cb->get_only_indexes)
+ {
+ if (rsp_code != OBX_RSP_OK)
+ {
+ rsp_code = OBX_RSP_OK;
+ APPL_TRACE_WARNING0("bta_pbs_end_of_list: index ONLY, but received OBX_RSP_CONTINUE??");
+ }
+ APPL_TRACE_DEBUG2("bta_pbs_end_of_list: indexes = %d, p_stream_indexes = 0x%07x",
+ p_cb->num_vlist_idxs, p_cb->p_stream_indexes);
+ UINT16_TO_BE_STREAM(p_cb->p_stream_indexes, p_cb->num_vlist_idxs);
+ }
+ else
+ {
+ /* If listing has completed, add on end string (http) */
+ if (rsp_code == OBX_RSP_OK)
+ {
+ temp_len = strlen(BTA_PBS_FOLDER_LISTING_END);
+ memcpy(&p_obx->p_start[p_obx->offset], BTA_PBS_FOLDER_LISTING_END, temp_len);
+ p_obx->offset += temp_len;
+
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, TRUE);
+ }
+ else /* More listing data to be sent */
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, FALSE);
+ }
+
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+ if (rsp_code == OBX_RSP_OK)
+ bta_pbs_clean_getput(p_cb, FALSE);
+ }
+ else /* An error occurred */
+ {
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ bta_pbs_clean_getput(p_cb, TRUE);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_get_file_rsp
+**
+** Description Finishes up the end body of the file get, and sends out the
+** OBX response
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_get_file_rsp(UINT8 rsp_code, UINT16 num_read)
+{
+ tBTA_PBS_CB *p_cb = &bta_pbs_cb;
+ tBTA_PBS_OBX_PKT *p_obx = &p_cb->obx;
+ BOOLEAN done = TRUE;
+
+ /* Send the response packet if successful operation */
+ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE)
+ {
+ p_obx->offset += num_read;
+
+ /* More to be sent */
+ if (rsp_code == OBX_RSP_CONTINUE)
+ {
+ if (p_obx->bytes_left != num_read)
+ APPL_TRACE_WARNING2("PBS Read: Requested (0x%04x), Read In (0x%04x)",
+ p_obx->bytes_left, num_read);
+ done = FALSE;
+ }
+
+ if (num_read)
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, done);
+ }
+ else
+ p_cb->obx_oper = BTA_PBS_OPER_NONE;
+
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+
+ /* Final response packet sent out */
+ if (done && rsp_code == OBX_RSP_OK)
+ bta_pbs_clean_getput(p_cb, FALSE);
+ /* If there is error */
+ if (rsp_code != OBX_RSP_OK && rsp_code != OBX_RSP_CONTINUE)
+ bta_pbs_clean_getput(p_cb, TRUE);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_add_list_entry
+**
+** Description used by bta_pbs_getdirlist to write a list entry to an
+** obex packet (byte array).
+**
+** Returns UINT8 - OBX response code
+** OBX_RSP_OK
+** OBX_RSP_CONTINUE
+** Others send error response out
+**
+*******************************************************************************/
+UINT8 bta_pbs_add_list_entry(void)
+{
+ tBTA_PBS_CB *p_cb = &bta_pbs_cb;
+ tBTA_PBS_OBX_PKT *p_obx = &p_cb->obx;
+ char *p_buf;
+ UINT16 size;
+ UINT8 rsp_code = OBX_RSP_SERVICE_UNAVL;
+
+ /* Skip filling in entry; just counting */
+ if (p_cb->get_only_indexes)
+ {
+ return (OBX_RSP_OK);
+ }
+
+ if ((p_buf = (char *)GKI_getbuf(GKI_MAX_BUF_SIZE)) != NULL)
+ {
+ p_buf[0] = '\0';
+
+ APPL_TRACE_DEBUG2("bta_pbs_add_list_entry: handle:%s, name:%s",
+ p_cb->vlist.handle, p_cb->vlist.name);
+
+ sprintf(p_buf, " <" BTA_PBS_CARD_ELEM " = \"%s\" " BTA_PBS_NAME_ATTR " = \"",p_cb->vlist.handle);
+ /* Need to translate special characters to XML format */
+ bta_pbs_translate_special_character(strlen(p_buf) + p_buf, p_cb->vlist.name);
+ sprintf(strlen(p_buf)+p_buf, "\"/>" BTA_PBS_XML_EOL);
+ /* Make sure the entry fits into the current obx packet */
+ size = strlen(p_buf);
+ if (size <= p_obx->bytes_left)
+ {
+ if (size > 0)
+ {
+ memcpy (&p_obx->p_start[p_obx->offset], p_buf, size);
+ p_obx->offset += size;
+ p_obx->bytes_left -= size;
+ }
+ rsp_code = OBX_RSP_OK;
+ }
+ else /* entry did not fit in current obx packet; try to add entry in next obx req */
+ rsp_code = OBX_RSP_CONTINUE;
+
+ /* Done with temporary buffer */
+ GKI_freebuf(p_buf);
+ }
+ else
+ rsp_code = OBX_RSP_SERVICE_UNAVL;
+
+ return (rsp_code);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_clean_getput
+**
+** Description Cleans up the get resources and control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_clean_getput(tBTA_PBS_CB *p_cb, BOOLEAN is_aborted)
+{
+ tBTA_PBS_OBJECT objdata;
+
+ /* Clean up control block */
+ utl_freebuf((void**)&p_cb->obx.p_pkt);
+
+ /* Close any open files */
+ if (p_cb->fd >= 0)
+ {
+ bta_pbs_co_close(p_cb->fd);
+ p_cb->fd = BTA_FS_INVALID_FD;
+ }
+
+ /* Notify the application */
+ objdata.p_name = p_cb->p_path;
+
+ if (is_aborted)
+ objdata.status = BTA_PBS_FAIL;
+ else
+ objdata.status = BTA_PBS_OK;
+
+ if (p_cb->p_cback && p_cb->obx_oper != 0)
+ {
+ objdata.operation = p_cb->obx_oper;
+ /* Notify application of operation complete */
+ p_cb->p_cback(BTA_PBS_OPER_CMPL_EVT, (tBTA_PBS *)&objdata);
+ }
+
+ utl_freebuf((void**)&p_cb->p_name);
+ utl_freebuf((void**)&p_cb->p_path);
+
+ p_cb->obx_oper = BTA_PBS_OPER_NONE;
+ p_cb->obj_type = BTA_PBS_NONE_OBJ;
+ p_cb->obx.bytes_left = 0;
+ p_cb->file_length = BTA_FS_LEN_UNKNOWN;
+ p_cb->acc_active = 0;
+// btla-specific ++
+ p_cb->aborting = FALSE;
+// btla-specific --
+ memset(&p_cb->getvlist_app_params, 0, sizeof(p_cb->getvlist_app_params));
+ memset(&p_cb->pullpb_app_params, 0, sizeof(p_cb->pullpb_app_params));
+ memset(&p_cb->vlist, 0, sizeof(p_cb->vlist));
+}
+
+/*****************************************************************************
+* Function: bta_pbs_read_app_params
+* Purpose: Read the application parameters from the given OBX packet
+*****************************************************************************/
+UINT8 * bta_pbs_read_app_params(BT_HDR *p_pkt, UINT8 tag, UINT16 *param_len)
+{
+ UINT8 *p_data = NULL, *p = NULL;
+ UINT16 data_len = 0;
+ int left, len;
+
+ if(OBX_ReadByteStrHdr(p_pkt, OBX_HI_APP_PARMS, &p_data, &data_len, 0))
+ {
+ left = data_len;
+ while(left > 0)
+ {
+ len = *(p_data + 1);
+ if(*p_data == tag)
+ {
+ p_data += 2;
+ p = p_data;
+ *param_len = (UINT16) len;
+ break;
+ }
+ p_data += (len+2);
+ left -= (len+2);
+ }
+ }
+ return p;
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_handle_special_character
+**
+** Description Translate special characters to XML format
+**
+**
+** Returns Void
+**
+*******************************************************************************/
+static void bta_pbs_translate_special_character(char *buffer, const char *str)
+{
+ char *buf=buffer;
+ int slen = strlen(str);
+ int i;
+ for (i=0; i < slen;i++)
+ {
+
+ char c = str[i];
+ switch (c)
+ {
+ case '<':
+ BCM_STRCPY_S(buf,4,"&lt;");
+ buf+=4;
+ break;
+ case '>':
+ BCM_STRCPY_S(buf,4,"&gt;");
+ buf+=4;
+ break;
+ case '\"':
+ BCM_STRCPY_S(buf,6,"&quot;");
+ buf+=6;
+ break;
+ case '\'':
+ BCM_STRCPY_S(buf,6,"&apos;");
+ buf+=6;
+ break;
+ case '&':
+ BCM_STRCPY_S(buf,5,"&amp;");
+ buf+=5;
+ break;
+ default:
+ buf[0]=c;
+ buf++;
+ }
+ }
+ buf[0]='\0';
+
+}
+
+
+
+#endif /* BTA_PBS_INCLUDED */