diff options
author | Andre Eisenbach <andre@broadcom.com> | 2012-02-22 13:18:21 -0800 |
---|---|---|
committer | Matthew Xie <mattx@google.com> | 2012-07-14 11:19:11 -0700 |
commit | e448862a47c08eb23185aaed574b39264f5005fc (patch) | |
tree | 2bc6246e3091315e77224fd798ea2fe8074ef972 /bta/pb | |
parent | a2ca4b83ab8bbbfd8d5f6693e927ed4b82094624 (diff) | |
download | external_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.c | 1134 | ||||
-rw-r--r-- | bta/pb/bta_pbs_api.c | 222 | ||||
-rw-r--r-- | bta/pb/bta_pbs_cfg.c | 38 | ||||
-rw-r--r-- | bta/pb/bta_pbs_ci.c | 119 | ||||
-rw-r--r-- | bta/pb/bta_pbs_int.h | 305 | ||||
-rw-r--r-- | bta/pb/bta_pbs_main.c | 515 | ||||
-rw-r--r-- | bta/pb/bta_pbs_sdp.c | 113 | ||||
-rw-r--r-- | bta/pb/bta_pbs_utils.c | 734 |
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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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 = ⌖ + + /* 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,"<"); + buf+=4; + break; + case '>': + BCM_STRCPY_S(buf,4,">"); + buf+=4; + break; + case '\"': + BCM_STRCPY_S(buf,6,"""); + buf+=6; + break; + case '\'': + BCM_STRCPY_S(buf,6,"'"); + buf+=6; + break; + case '&': + BCM_STRCPY_S(buf,5,"&"); + buf+=5; + break; + default: + buf[0]=c; + buf++; + } + } + buf[0]='\0'; + +} + + + +#endif /* BTA_PBS_INCLUDED */ |