/*********************************************a******************************** ** ** Name: bta_mse_utils.c ** ** Description: This file implements utility functions for the ** file transfer server. ** ** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved. ** Broadcom Bluetooth Core. Proprietary and confidential. ** *****************************************************************************/ #include "bt_target.h" #if defined(BTA_MSE_INCLUDED) && (BTA_MSE_INCLUDED == TRUE) #include #include #include "gki.h" #include "utl.h" #include "bd.h" #include "bta_fs_api.h" #include "bta_mse_int.h" #include "bta_fs_co.h" #include "bta_mse_co.h" #include "bta_ma_util.h" /******************************************************************************* * Macros for MSE *******************************************************************************/ #define BTA_MSE_XML_EOL "\n" #define BTA_MSE_FOLDER_LISTING_START ( "\n" \ "\n" \ "\n" ) #define BTA_MSE_FOLDER_LISTING_END ( "" ) #define BTA_MSE_PARENT_FOLDER (" \n") #define BTA_MSE_FILE_ELEM "file" #define BTA_MSE_FOLDER_ELEM "folder" #define BTA_MSE_NAME_ATTR "name" #define BTA_MSE_SIZE_ATTR "size" #define BTA_MSE_TYPE_ATTR "type" #define BTA_MSE_MODIFIED_ATTR "modified" #define BTA_MSE_CREATED_ATTR "created" #define BTA_MSE_ACCESSED_ATTR "accessed" #define BTA_MSE_USER_PERM_ATTR "user-perm" #define BTA_MSE_MSG_LISTING_START ( "\n" ) #define BTA_MSE_MSG_LISTING_END ( "" ) // btla-specific ++ #define BTA_MSE_ENABLE_FS_CO FALSE // btla-specific -- /******************************************************************************* ** ** Function bta_mse_send_push_msg_in_prog_evt ** ** Description send the push message in progress event ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns void ** *******************************************************************************/ void bta_mse_send_push_msg_in_prog_evt(UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OPER_PUSH_MSG *p_push_msg = &p_cb->push_msg; tBTA_MSE cback_evt_data; tBTA_MSE *p_data = &cback_evt_data; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_send_push_msg_in_prog_evt inst_idx=%d sess_idx=%d", inst_idx,sess_idx); #endif p_data->push_msg_in_prog.mas_session_id = p_cb->obx_handle; p_data->push_msg_in_prog.bytes = p_cb->obx.offset; p_data->push_msg_in_prog.obj_size = p_push_msg->push_byte_cnt; bta_mse_cb.p_cback(BTA_MSE_PUSH_MSG_IN_PROG_EVT, (tBTA_MSE *) p_data); } /******************************************************************************* ** ** Function bta_mse_send_get_msg_in_prog_evt ** ** Description Sends the get message in progress event ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns void ** *******************************************************************************/ void bta_mse_send_get_msg_in_prog_evt(UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OPER_MSG_PARAM *p_param = &p_cb->msg_param; tBTA_MSE cback_evt_data; tBTA_MSE *p_data = &cback_evt_data; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_send_get_msg_in_prog_evt inst_idx=%d sess_idx=%d", inst_idx,sess_idx); #endif p_data->get_msg_in_prog.mas_session_id = (tBTA_MA_SESS_HANDLE) p_cb->obx_handle; p_data->get_msg_in_prog.bytes = p_param->filled_buff_size; p_data->get_msg_in_prog.obj_size = p_param->byte_get_cnt; bta_mse_cb.p_cback(BTA_MSE_GET_MSG_IN_PROG_EVT, (tBTA_MSE *) p_data); } /******************************************************************************* ** ** Function bta_mse_send_oper_cmpl_evt ** ** Description Sends the operartion complete event based on the specified status ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** status - MA status code ** ** Returns void ** *******************************************************************************/ void bta_mse_send_oper_cmpl_evt(UINT8 inst_idx, UINT8 sess_idx, tBTA_MA_STATUS status) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OPER_MSG_PARAM *p_param = &p_cb->msg_param; tBTA_MSE_OPER_PUSH_MSG *p_push_msg = &p_cb->push_msg; tBTA_MSE cback_evt_data; tBTA_MSE *p_data = &cback_evt_data; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT3("bta_mse_send_oper_cmpl_evt inst_idx=%d sess_idx=%d status=%d", inst_idx, sess_idx, status); #endif p_data->oper_cmpl.mas_session_id = p_cb->obx_handle; p_data->oper_cmpl.operation = p_cb->oper; p_data->oper_cmpl.status = status; switch (p_cb->oper) { case BTA_MSE_OPER_GET_MSG: p_data->oper_cmpl.obj_size = p_param->byte_get_cnt; break; case BTA_MSE_OPER_PUSH_MSG: p_data->oper_cmpl.obj_size = p_push_msg->push_byte_cnt; break; default: p_data->oper_cmpl.obj_size = 0; break; } bta_mse_cb.p_cback(BTA_MSE_OPER_CMPL_EVT, (tBTA_MSE *) p_data); } /******************************************************************************* ** ** Function bta_mse_pushmsg ** ** Description Process the push message request ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** first_pkt - first packet of the push message request ** ** Returns void ** *******************************************************************************/ void bta_mse_pushmsg(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN first_pkt) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OPER_PUSH_MSG *p_push_msg = &p_cb->push_msg; tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx; tBTA_MA_MPKT_STATUS mpkt_status; p_push_msg->push_byte_cnt += p_obx->offset; p_cb->cout_active = TRUE; mpkt_status = BTA_MA_MPKT_STATUS_LAST; if (!p_obx->final_pkt) mpkt_status = BTA_MA_MPKT_STATUS_MORE; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT5("bta_mse_pushmsg i_idx=%d s_idx=%d first=%d final=%d cnt=%d", inst_idx, sess_idx, first_pkt, p_obx->final_pkt, p_push_msg->push_byte_cnt); #endif bta_mse_co_push_msg((tBTA_MA_SESS_HANDLE) p_cb->obx_handle, &p_push_msg->param, p_obx->offset, p_obx->p_start, first_pkt, mpkt_status, BTA_MSE_CI_PUSH_MSG_EVT, bta_mse_cb.app_id); } /******************************************************************************* ** ** Function bta_mse_clean_set_msg_sts ** ** Description Cleans up the set message status resources and cotrol block ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns void ** *******************************************************************************/ void bta_mse_clean_set_msg_sts(UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OPER_SET_MSG_STS *p_set_msg_sts = &p_cb->set_msg_sts; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_clean_set_msg_sts"); #endif utl_freebuf((void**)&(p_set_msg_sts->p_msg_handle)); bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE); } /******************************************************************************* ** ** Function bta_mse_clean_set_notif_reg ** ** Description Cleans up the set notification registration resources and cotrol block ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns void ** *******************************************************************************/ void bta_mse_clean_set_notif_reg(UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_clean_set_notif_reg"); #endif p_cb->notif_reg_req.notif_status_rcv = FALSE; bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE); } /******************************************************************************* ** ** Function bta_mse_clean_push_msg ** ** Description Cleans up the push message resources and cotrol block ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns void ** *******************************************************************************/ void bta_mse_clean_push_msg(UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OPER_PUSH_MSG *p_push_msg = &p_cb->push_msg; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_clean_push_msg"); #endif utl_freebuf((void**)&(p_push_msg->param.p_folder)); bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE); } /******************************************************************************* ** ** Function bta_mse_init_set_msg_sts ** ** Description Initializes the set message status resources and cotrol block ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** p_rsp_code - (output) pointer to the obex response code ** ** Returns void ** *******************************************************************************/ void bta_mse_init_set_msg_sts(UINT8 inst_idx, UINT8 sess_idx, UINT8 *p_rsp_code) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OPER_SET_MSG_STS *p_set_msg_sts = &p_cb->set_msg_sts; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_init_set_msg_sts"); #endif *p_rsp_code = OBX_RSP_OK; p_set_msg_sts->rcv_msg_handle = FALSE; p_set_msg_sts->rcv_sts_ind = FALSE; p_set_msg_sts->rcv_sts_val = FALSE; if (!p_set_msg_sts->p_msg_handle) { if ((p_set_msg_sts->p_msg_handle = (char *)GKI_getbuf((UINT16)(BTA_MSE_64BIT_HEX_STR_SIZE))) == NULL ) { *p_rsp_code = OBX_RSP_INTRNL_SRVR_ERR; } } } /******************************************************************************* ** ** Function bta_mse_init_push_msg ** ** Description initializes the push message resources and control block ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** p_rsp_code - (output) pointer to the obex response code ** ** Returns void ** *******************************************************************************/ void bta_mse_init_push_msg(UINT8 inst_idx, UINT8 sess_idx, UINT8 *p_rsp_code) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OPER_PUSH_MSG *p_push_msg = &p_cb->push_msg; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_init_push_msg"); #endif *p_rsp_code = OBX_RSP_OK; p_push_msg->push_byte_cnt = 0; p_push_msg->first_req_pkt = TRUE; p_push_msg->rcv_charset = FALSE; p_push_msg->rcv_folder_name = FALSE; p_push_msg->rcv_retry = FALSE; p_push_msg->rcv_transparent = FALSE; p_push_msg->param.transparent = BTA_MA_TRANSP_OFF; p_push_msg->param.retry = BTA_MA_RETRY_OFF; if (!p_push_msg->param.p_folder) { if ((p_push_msg->param.p_folder = (char *)GKI_getbuf((UINT16)(p_bta_mse_cfg->max_name_len + 1))) == NULL ) { *p_rsp_code = OBX_RSP_INTRNL_SRVR_ERR; } } } /******************************************************************************* ** ** Function bta_mse_remove_uuid ** ** Description Remove UUID and clear service ** ** Parameters none ** ** Returns void ** *******************************************************************************/ void bta_mse_remove_uuid(void) { bta_sys_remove_uuid(UUID_SERVCLASS_MESSAGE_ACCESS); BTM_SecClrService(BTM_SEC_SERVICE_MAP); } /******************************************************************************* ** ** Function bta_mse_clean_mas_service ** ** Description Cleans up the MAS service resources and control block ** ** Parameters inst_idx - Index to the MA instance control block ** ** Returns void ** *******************************************************************************/ void bta_mse_clean_mas_service(UINT8 inst_idx) { tBTA_MSE_MA_CB *p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx); tBTA_MSE_MA_SESS_CB *p_cb; int i, num_act_mas =0; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_clean_mas_service"); #endif OBX_StopServer(p_scb->obx_handle); BTM_FreeSCN(p_scb->scn); if (p_scb->sdp_handle) SDP_DeleteRecord(p_scb->sdp_handle); utl_freebuf((void**)&p_scb->p_rootpath); for (i=0; i < BTA_MSE_NUM_SESS; i++ ) { p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, i); utl_freebuf((void**)&p_cb->p_workdir); } p_scb->in_use = FALSE; /* check all other MAS instances */ for (i=0; i < BTA_MSE_NUM_INST ; i ++) { p_scb = BTA_MSE_GET_INST_CB_PTR(i); if (p_scb->in_use) num_act_mas++; } if (!num_act_mas) bta_mse_remove_uuid(); } /******************************************************************************* ** ** Function bta_mse_abort_too_late ** ** Description It is too late to abort the operation ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns void ** *******************************************************************************/ void bta_mse_abort_too_late(UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT1("bta_mse_abort_too_late oper=%d ",p_cb->oper ); #endif OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_FORBIDDEN, (BT_HDR *)NULL); p_cb->aborting = FALSE; } /******************************************************************************* ** ** Function bta_mse_clean_getput ** ** Description Cleans up get and put resources and control blocks ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** status - operation status ** ** Returns void ** *******************************************************************************/ void bta_mse_clean_getput(UINT8 inst_idx, UINT8 sess_idx, tBTA_MA_STATUS status) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_clean_getput oper=%d status=%d",p_cb->oper, status ); #endif if (status == BTA_MA_STATUS_ABORTED) { OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_OK, (BT_HDR *)NULL); p_cb->aborting = FALSE; } switch (p_cb->oper) { case BTA_MSE_OPER_UPDATE_INBOX: bta_mse_set_ma_oper(inst_idx,sess_idx, BTA_MSE_OPER_NONE); break; case BTA_MSE_OPER_GET_FOLDER_LIST: bta_mse_clean_list(inst_idx,sess_idx); break; case BTA_MSE_OPER_GET_MSG_LIST: bta_mse_clean_msg_list(inst_idx,sess_idx); break; case BTA_MSE_OPER_GET_MSG: bta_mse_send_oper_cmpl_evt(inst_idx,sess_idx, status); bta_mse_clean_msg(inst_idx,sess_idx); break; case BTA_MSE_OPER_PUSH_MSG: bta_mse_send_oper_cmpl_evt(inst_idx,sess_idx, status); bta_mse_clean_push_msg(inst_idx,sess_idx); break; case BTA_MSE_OPER_DEL_MSG: case BTA_MSE_OPER_SET_MSG_STATUS: bta_mse_clean_set_msg_sts(inst_idx,sess_idx); break; default: break; } utl_freebuf((void**)&p_cb->obx.p_pkt); p_cb->obx.bytes_left = 0; } /******************************************************************************* ** ** Function bta_mse_clean_msg ** ** Description Cleans up the get message resources and control block ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns void ** *******************************************************************************/ void bta_mse_clean_msg(UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); /* Clean up control block */ #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_clean_msg"); #endif utl_freebuf((void **)&p_cb->msg_param.p_msg_handle); bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE); } /******************************************************************************* ** ** Function bta_mse_end_of_msg ** ** Description Complete the end body of the get message response, and ** sends out the OBX get response ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** rsp_code - Obex response code ** ** Returns void ** *******************************************************************************/ void bta_mse_end_of_msg(UINT8 inst_idx, UINT8 sess_idx, UINT8 rsp_code) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx; tBTA_MSE_OPER_MSG_PARAM *p_param = &p_cb->msg_param; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_end_of_msg"); #endif /* Add the end of folder listing string if successful operation */ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE) { /* If get message has completed, update the fraction delivery status */ if (p_param->add_frac_del_hdr) { *(p_param->p_frac_delivery) = p_param->frac_deliver_status; p_param->add_frac_del_hdr = FALSE; } p_obx->offset += p_param->filled_buff_size; if (rsp_code == OBX_RSP_OK) { OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, TRUE); } else /* More 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_CONTINUE) { bta_mse_send_get_msg_in_prog_evt(inst_idx, sess_idx); } else { bta_mse_clean_getput(inst_idx, sess_idx, BTA_MA_STATUS_OK); } } else /* An error occurred */ { OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL); bta_mse_clean_getput(inst_idx, sess_idx, BTA_MA_STATUS_FAIL); } } /******************************************************************************* ** ** Function bta_mse_getmsg ** ** Description Processes the get message request ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns void ** *******************************************************************************/ void bta_mse_getmsg(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN new_req) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx; tBTA_MSE_OPER_MSG_PARAM *p_param = &p_cb->msg_param; UINT8 rsp_code = OBX_RSP_OK; UINT8 *p, *p_start; UINT16 len = 0; BOOLEAN first_get=FALSE; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_getmsg"); #endif 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 (new_req) { first_get = TRUE; if (p_param->add_frac_del_hdr) { /* Add Fraction Deliver Header */ p_start = OBX_AddByteStrStart(p_obx->p_pkt, &len); p = p_start; *p++ = BTA_MA_APH_FRAC_DELVR; *p++ = 1; p_param->p_frac_delivery = p; /* use Last as default and it can be changed to More if application indicates more */ UINT8_TO_BE_STREAM(p, BTA_MA_FRAC_DELIVER_LAST); OBX_AddByteStrHdr(p_obx->p_pkt, OBX_HI_APP_PARMS, NULL, (UINT16)(p - p_start)); } } /* 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); p_cb->cout_active = TRUE; bta_mse_co_get_msg((tBTA_MA_SESS_HANDLE) p_cb->obx_handle, &p_param->data, first_get, p_obx->bytes_left, p_obx->p_start, BTA_MSE_CI_GET_MSG_EVT, bta_mse_cb.app_id); /* List is not complete, so don't send the response yet */ rsp_code = OBX_RSP_PART_CONTENT; } else rsp_code = OBX_RSP_INTRNL_SRVR_ERR; /* Response goes out if complete or error occurred */ if (rsp_code != OBX_RSP_PART_CONTENT) bta_mse_end_of_msg(inst_idx, sess_idx,rsp_code); } /******************************************************************************* ** ** Function bta_mse_clean_msg_list ** ** Description Cleans up the get message list resources and control block ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns void ** *******************************************************************************/ void bta_mse_clean_msg_list(UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_MSGLIST *p_ml = &p_cb->ml; /* Clean up control block */ #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_clean_msg_list"); #endif bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE); p_ml->remaing_size =0; p_ml->offset =0; p_ml->pending_ml_frag = FALSE; utl_freebuf((void**)&p_ml->p_entry); utl_freebuf((void**)&p_ml->p_info); utl_freebuf((void**)&p_ml->p_xml_buf); utl_freebuf((void**)&p_cb->ml_param.p_name); utl_freebuf((void**)&p_cb->ml_param.p_path); } /******************************************************************************* ** ** Function bta_mse_end_of_msg_list ** ** Description Complete the end body of the get message listing response, and ** sends out the OBX get response ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** rsp_code - Obex response code ** ** Returns void ** *******************************************************************************/ void bta_mse_end_of_msg_list(UINT8 inst_idx, UINT8 sess_idx, UINT8 rsp_code) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx; tBTA_MSE_OPER_MLIST_PARAM *p_ml_param = &p_cb->ml_param; UINT16 len; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_end_of_msg_list"); #endif /* Add the end of folder listing string if successful operation */ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE) { /* If listing has completed, check the max list count */ if (rsp_code == OBX_RSP_OK) { if (p_ml_param->filter.max_list_cnt) { len = strlen(BTA_MSE_MSG_LISTING_END); memcpy(&p_obx->p_start[p_obx->offset], BTA_MSE_MSG_LISTING_END, len); p_obx->offset += len; OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, TRUE); } /* Clean up control block */ bta_mse_clean_msg_list(inst_idx, sess_idx); } 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 */ } else /* An error occurred */ { OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL); bta_mse_clean_msg_list(inst_idx, sess_idx); } } /******************************************************************************* ** ** Function bta_mse_add_msg_list_info ** ** Description Adds applications paramter headers for new message and ** message list size ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns UINT8 - OBX response code ** OBX_RSP_PART_CONTENT if not finished yet. ** *******************************************************************************/ UINT8 bta_mse_add_msg_list_info(UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx; tBTA_MSE_MSGLIST *p_ml = &p_cb->ml; tBTA_MSE_CO_MSG_LIST_INFO *p_info = p_ml->p_info; tBTA_MSE_CO_MSG_LIST_ENTRY *p_entry = p_ml->p_entry; tBTA_MA_MSG_LIST_FILTER_PARAM *p_filter = &p_cb->ml_param.filter; UINT8 rsp_code = OBX_RSP_PART_CONTENT; UINT8 *p, *p_start; UINT16 len = 0; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_add_msg_list_info: new msg=%d, list size=%d", p_info->new_msg, p_info->msg_list_size ); #endif /* add app params for GetMessageListing */ p_start = OBX_AddByteStrStart(p_obx->p_pkt, &len); p = p_start; *p++ = BTA_MA_APH_NEW_MSG; *p++ = 1; UINT8_TO_BE_STREAM(p, p_info->new_msg); *p++ = BTA_MA_APH_MSG_LST_SIZE; *p++ = 2; UINT16_TO_BE_STREAM(p, p_info->msg_list_size); *p++ = BTA_MA_APH_MSE_TIME; *p++ = p_info->mse_time_len; memcpy(p, p_info->mse_time, p_info->mse_time_len); p += p_info->mse_time_len; if (p != p_start) { OBX_AddByteStrHdr(p_obx->p_pkt, OBX_HI_APP_PARMS, NULL, (UINT16)(p - p_start)); } if (p_filter->max_list_cnt) { /* 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); len = strlen(BTA_MSE_MSG_LISTING_START); memcpy(&p_obx->p_start[p_obx->offset], BTA_MSE_MSG_LISTING_START, len); p_obx->bytes_left -= (UINT16)(len + strlen(BTA_MSE_MSG_LISTING_END)); p_obx->offset += len; p_cb->cout_active = TRUE; bta_mse_co_get_msg_list_entry((tBTA_MA_SESS_HANDLE) p_cb->obx_handle, p_cb->ml_param.p_name, p_filter, TRUE, p_entry, BTA_MSE_CI_GET_ML_ENTRY_EVT, bta_mse_cb.app_id); } else { /* done with get msg list request */ rsp_code = OBX_RSP_OK; } return(rsp_code); } /******************************************************************************* ** ** Function bta_mse_add_msg_list_entry ** ** Description Adds one entry of the message list to the message list object ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns UINT8 - OBX response code ** OBX_RSP_PART_CONTENT if not finished yet. ** OBX_RSP_CONTINUE [packet done] ** Others send error response out ** *******************************************************************************/ UINT8 bta_mse_add_msg_list_entry(UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx; tBTA_MSE_MSGLIST *p_ml = &p_cb->ml; tBTA_MSE_CO_MSG_LIST_ENTRY *p_entry = p_ml->p_entry; tBTA_MA_MSG_LIST_FILTER_PARAM *p_filter = &p_cb->ml_param.filter; char *p_buf; UINT16 size; UINT8 rsp_code = OBX_RSP_PART_CONTENT; tBTA_MA_STATUS status; BOOLEAN release_xml_buf = TRUE; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_add_msg_list_entry"); #endif if (p_ml->pending_ml_frag) { if (p_ml->remaing_size <= p_obx->bytes_left) { size = p_ml->remaing_size; p_ml->pending_ml_frag = FALSE; } else { rsp_code = OBX_RSP_CONTINUE; size = p_obx->bytes_left; } p_buf = p_ml->p_xml_buf + p_ml->offset; memcpy (&p_obx->p_start[p_obx->offset], p_buf, size); p_obx->offset += size; p_obx->bytes_left -= size; p_ml->remaing_size -= size; p_ml->offset += size; if ( !p_ml->pending_ml_frag ) { utl_freebuf((void **) &p_ml->p_xml_buf); } if (rsp_code == OBX_RSP_PART_CONTENT) { /* Get the next msg list entry */ p_cb->cout_active = TRUE; bta_mse_co_get_msg_list_entry((tBTA_MA_SESS_HANDLE) p_cb->obx_handle, p_cb->ml_param.p_name, p_filter, FALSE, p_entry, BTA_MSE_CI_GET_ML_ENTRY_EVT, bta_mse_cb.app_id); } return rsp_code; } if ((p_buf = (char *)GKI_getbuf(GKI_MAX_BUF_SIZE)) != NULL) { p_buf[0] = '\0'; size = GKI_MAX_BUF_SIZE; status = bta_mse_build_msg_listing_obj( p_entry, &size, p_buf ); if (status == BTA_MA_STATUS_OK) { 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; } /* Get the next msg list entry */ p_cb->cout_active = TRUE; bta_mse_co_get_msg_list_entry((tBTA_MA_SESS_HANDLE) p_cb->obx_handle, p_cb->ml_param.p_name, p_filter, FALSE, p_entry, BTA_MSE_CI_GET_ML_ENTRY_EVT, bta_mse_cb.app_id); } else /* entry did not fit in current obx packet; try to add entry in next obx req */ { p_ml->pending_ml_frag = TRUE; p_ml->p_xml_buf= p_buf; p_ml->offset =0; p_ml->remaing_size = size - p_obx->bytes_left; p_ml->offset += p_obx->bytes_left; release_xml_buf = FALSE; memcpy (&p_obx->p_start[p_obx->offset], p_buf, p_obx->bytes_left); p_obx->offset += p_obx->bytes_left; p_obx->bytes_left = 0; APPL_TRACE_EVENT2("1st msg list fragment peer_mtu=%d msg_list_size=%d", p_cb->peer_mtu, size); APPL_TRACE_EVENT3("pending_flag=%d offset=%d remaining_size=%d", p_ml->pending_ml_frag, p_ml->offset, p_ml->remaing_size); APPL_TRACE_EVENT2("obx offset=%d byte_left=%d", p_obx->offset, p_obx->bytes_left ); rsp_code = OBX_RSP_CONTINUE; } } else rsp_code = OBX_RSP_INTRNL_SRVR_ERR; /* Done with temporary buffer */ if (release_xml_buf) utl_freebuf((void **) &p_buf); } else rsp_code = OBX_RSP_INTRNL_SRVR_ERR; return(rsp_code); } /******************************************************************************* ** ** Function bta_mse_getmsglist ** ** Description Process the retrieval of a msg listing. ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns None ** *******************************************************************************/ void bta_mse_getmsglist(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN new_req) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx; tBTA_MSE_MSGLIST *p_ml = &p_cb->ml; UINT8 rsp_code = OBX_RSP_OK; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_getmsglist "); #endif p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle, /* p_cb->peer_mtu */ OBX_LRG_DATA_POOL_SIZE); if (!p_ml->p_entry) { /* Allocate enough space for the structure */ p_ml->p_entry = (tBTA_MSE_CO_MSG_LIST_ENTRY *) GKI_getbuf((UINT16)(sizeof(tBTA_MSE_CO_MSG_LIST_ENTRY))); } if (p_ml->p_entry && p_obx->p_pkt) { /* Is this a new request or continuation? */ if (new_req) { if (!p_ml->p_info) { /* Allocate enough space for the structure */ p_ml->p_info = (tBTA_MSE_CO_MSG_LIST_INFO *) GKI_getbuf((UINT16)(sizeof(tBTA_MSE_CO_MSG_LIST_INFO))); } if (p_ml->p_info) { p_cb->ml_param.w4info =TRUE; p_cb->cout_active = TRUE; bta_mse_co_get_msg_list_info((tBTA_MA_SESS_HANDLE) p_cb->obx_handle, p_cb->ml_param.p_name, &(p_cb->ml_param.filter), p_ml->p_info, BTA_MSE_CI_GET_ML_INFO_EVT, bta_mse_cb.app_id); /* List is not complete, so don't send the response yet */ rsp_code = OBX_RSP_PART_CONTENT; } else rsp_code = OBX_RSP_INTRNL_SRVR_ERR; } else /* Add the entry previously retrieved */ { /* 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 = bta_mse_add_msg_list_entry(inst_idx, sess_idx); } } else rsp_code = OBX_RSP_INTRNL_SRVR_ERR; /* Response goes out if complete or error occurred */ if (rsp_code != OBX_RSP_PART_CONTENT) bta_mse_end_of_msg_list(inst_idx, sess_idx,rsp_code); } /******************************************************************************* ** ** Function bta_mse_read_app_params ** ** Description Read the specified application parameter from the given OBX packet ** ** Parameters p_pkt - obex packet pointer ** tag - application parameter tag ** param_len - (output) pointer to the length of application paramter ** ** Returns pointer to the application parameter found ** NULL - not found ** *******************************************************************************/ UINT8 * bta_mse_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 BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_read_app_params"); #endif 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_mse_clean_list ** ** Description Cleans up the get folder list resources and control block ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns void ** *******************************************************************************/ void bta_mse_clean_list(UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_DIRLIST *p_dir = &p_cb->dir; /*tBTA_MSE_CO_FOLDER_ENTRY *p_entry = p_dir->p_entry; */ /* Clean up control block */ #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_clean_list"); #endif bta_mse_set_ma_oper(inst_idx,sess_idx, BTA_MSE_OPER_NONE); utl_freebuf((void**)&(p_dir->p_entry)); } /******************************************************************************* ** ** Function bta_mse_end_of_list ** ** Description Finishes up the end body of the get folder listing, and sends out the ** OBX response ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** rsp_code - obex response code ** ** Returns void ** *******************************************************************************/ void bta_mse_end_of_list(UINT8 inst_idx, UINT8 sess_idx, UINT8 rsp_code) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx; UINT16 len = 0; UINT8 *p, *p_start; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_end_of_list"); #endif /* Add the end of folder listing string if successful operation */ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE) { /* If listing has completed, add on end string (http) */ if (rsp_code == OBX_RSP_OK) { if (p_cb->fl_param.max_list_cnt) { len = strlen(BTA_MSE_FOLDER_LISTING_END); memcpy(&p_obx->p_start[p_obx->offset], BTA_MSE_FOLDER_LISTING_END, len); p_obx->offset += len; OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, TRUE); } else { #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT1("list_cnt=%d",p_cb->fl_param.list_cnt); #endif /* send the folder list size header only*/ p_start = OBX_AddByteStrStart(p_obx->p_pkt, &len); p = p_start; *p++ = BTA_MA_APH_FOLDER_LST_SIZE; *p++ = 2; UINT16_TO_BE_STREAM(p, p_cb->fl_param.list_cnt); if (p != p_start) { OBX_AddByteStrHdr(p_obx->p_pkt, OBX_HI_APP_PARMS, NULL, (UINT16)(p - p_start)); } } /* Clean up control block */ bta_mse_clean_list(inst_idx, sess_idx); } 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 */ } else /* An error occurred */ { OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL); bta_mse_clean_list(inst_idx, sess_idx); } } /******************************************************************************* ** ** Function bta_mse_add_list_entry ** ** Description Adds an subfolder entry to the folder list object ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns UINT8 - OBX response code ** OBX_RSP_PART_CONTENT if not finished yet. ** OBX_RSP_CONTINUE [packet done] ** Others send error response out ** *******************************************************************************/ UINT8 bta_mse_add_list_entry(UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx; tBTA_MSE_DIRLIST *p_dir = &p_cb->dir; tBTA_MSE_CO_FOLDER_ENTRY *p_entry = p_dir->p_entry; char *p_buf; UINT16 size; UINT8 rsp_code = OBX_RSP_PART_CONTENT; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_add_list_entry"); #endif if ((p_buf = (char *)GKI_getbuf(GKI_MAX_BUF_SIZE)) != NULL) { p_buf[0] = '\0'; APPL_TRACE_DEBUG2("bta_mse_add_list_entry: attr:0x%02x, name:%s", p_entry->mode, p_entry->p_name); if (p_entry->mode & BTA_MA_A_DIR) /* only process Subdirectory ignore files */ { /* ignore "." and ".." */ if (strcmp(p_entry->p_name, ".") && strcmp(p_entry->p_name, "..")) { p_cb->fl_param.list_cnt++; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT1("list_cnt=%d",p_cb->fl_param.list_cnt); #endif if (p_cb->fl_param.max_list_cnt) { if (p_cb->fl_param.list_cnt <= p_cb->fl_param.max_list_cnt) { if (p_cb->fl_param.list_cnt > p_cb->fl_param.start_offset ) { sprintf(p_buf, " <" BTA_MSE_FOLDER_ELEM " " BTA_MSE_NAME_ATTR "=\"%s\"/>" BTA_MSE_XML_EOL, p_entry->p_name); } } } /* if max_list_cnt==0 only count the list size - but no body should be included*/ } }/* ignore files i.e. non-folder items */ 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; } if ((p_cb->fl_param.list_cnt < p_cb->fl_param.max_list_cnt) || (p_cb->fl_param.max_list_cnt == 0) ) { /* Get the next directory entry */ p_cb->cout_active = TRUE; bta_mse_co_get_folder_entry((tBTA_MA_SESS_HANDLE) p_cb->obx_handle, p_cb->p_workdir, FALSE, p_dir->p_entry, BTA_MSE_CI_GET_FENTRY_EVT, bta_mse_cb.app_id); } else { /* reach the max allowed */ rsp_code = OBX_RSP_OK; } } else /* entry did not fit in current obx packet; try to add entry in next obx req */ { p_cb->fl_param.list_cnt--; rsp_code = OBX_RSP_CONTINUE; } /* Done with temporary buffer */ GKI_freebuf(p_buf); } else rsp_code = OBX_RSP_INTRNL_SRVR_ERR; return(rsp_code); } /******************************************************************************* ** ** Function bta_mse_getfolderlist ** ** Description Processes the retrieval of a folder listing. ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns void ** *******************************************************************************/ void bta_mse_getfolderlist(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN new_req) { tBTA_MSE_MA_CB *p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx); tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx; tBTA_MSE_DIRLIST *p_dir = &p_cb->dir; UINT16 temp_len; UINT8 rsp_code = OBX_RSP_OK; #if BTA_MSE_ENABLE_FS_CO == TRUE BOOLEAN is_dir; #endif #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_getfolderlist"); #endif #if BTA_MSE_ENABLE_FS_CO == TRUE /* Make sure the Name is a directory and accessible */ if (((bta_fs_co_access(p_cb->p_workdir, BTA_FS_ACC_EXIST, &is_dir, bta_mse_cb.app_id))!= BTA_FS_CO_OK) || !is_dir) rsp_code = OBX_RSP_NOT_FOUND; #endif /* Build the listing */ 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 (!(strcmp(p_cb->p_workdir, p_scb->p_rootpath))) p_dir->is_root = TRUE; else p_dir->is_root = FALSE; if (!p_dir->p_entry) { /* Allocate enough space for the structure and the folder name */ if ((p_dir->p_entry = (tBTA_MSE_CO_FOLDER_ENTRY *) GKI_getbuf((UINT16)(sizeof(tBTA_MSE_CO_FOLDER_ENTRY) + p_bta_mse_cfg->max_name_len + 1))) != NULL) p_dir->p_entry->p_name = (char *)(p_dir->p_entry + 1); } if (p_dir->p_entry && p_obx->p_pkt) { if (p_cb->fl_param.max_list_cnt) { /* 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); } /* Is this a new request or continuation? */ if (new_req) { APPL_TRACE_EVENT1("Folder List Directory: [%s]", p_cb->p_workdir); p_cb->fl_param.list_cnt =0; /* add body header if max_list_cnt is not 0 if max_list_cnt =0 then only report the actual number accessible folders. Use FolderListingSize header only */ if (p_cb->fl_param.max_list_cnt) { temp_len = strlen(BTA_MSE_FOLDER_LISTING_START); /* Add the beginning label of http */ memcpy(p_obx->p_start, BTA_MSE_FOLDER_LISTING_START, temp_len); p_obx->bytes_left -= (UINT16)(temp_len + strlen(BTA_MSE_FOLDER_LISTING_END)); p_obx->offset += temp_len; /* Add the parent directory if not the root */ if (strcmp(p_cb->p_workdir, p_scb->p_rootpath)) { APPL_TRACE_EVENT0("Add parent folder"); temp_len = strlen(BTA_MSE_PARENT_FOLDER); memcpy(p_obx->p_start + p_obx->offset, BTA_MSE_PARENT_FOLDER, temp_len); p_obx->bytes_left -= temp_len; p_obx->offset += temp_len; } } p_cb->cout_active = TRUE; bta_mse_co_get_folder_entry((tBTA_MA_SESS_HANDLE) p_cb->obx_handle, p_cb->p_workdir, TRUE, p_dir->p_entry, BTA_MSE_CI_GET_FENTRY_EVT, bta_mse_cb.app_id); /* List is not complete, so don't send the response yet */ rsp_code = OBX_RSP_PART_CONTENT; } else /* Add the entry previously retrieved */ rsp_code = bta_mse_add_list_entry(inst_idx, sess_idx); } else rsp_code = OBX_RSP_INTRNL_SRVR_ERR; } /* Response goes out if complete or error occurred */ if (rsp_code != OBX_RSP_PART_CONTENT) bta_mse_end_of_list(inst_idx, sess_idx,rsp_code); } /******************************************************************************* ** ** Function bta_mse_chdir ** ** Description Changes the current path based on received setpath paramters ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** p_oper - (output) pointer to the MSE operation code ** ** Returns UINT8 - OBX response code ** output *p_oper set to BTA_MSE_OPER_SETPATH if the ** the resulting path is a valid path *******************************************************************************/ UINT8 bta_mse_chdir(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_OPER *p_oper) { tBTA_MSE_MA_CB *p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx); tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); char *p_path = p_cb->sp.p_path; char *p_name = p_cb->sp.p_name; char *p_tmp; char *p_workdir = p_cb->p_workdir; UINT8 rsp_code = OBX_RSP_OK; #if BTA_MSE_ENABLE_FS_CO == TRUE BOOLEAN is_dir; #endif #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_chdir flag=%d name=%s",p_cb->sp.flags,p_cb->sp.p_name ); #endif *p_oper = BTA_MSE_OPER_NONE; switch (p_cb->sp.flags) { case BTA_MA_DIR_NAV_ROOT_OR_DOWN_ONE_LVL: p_path = p_cb->sp.p_path; p_name = p_cb->sp.p_name; rsp_code = OBX_RSP_OK; if (*p_name == '\0') { /* backup to root */ if (strcmp(p_workdir, p_scb->p_rootpath)) { BCM_STRNCPY_S(p_path, p_bta_fs_cfg->max_path_len+1, p_scb->p_rootpath, p_bta_fs_cfg->max_path_len); /* go back up to the root folder*/ *p_oper = BTA_MSE_OPER_SETPATH; } } /* Make sure the new path is not too big */ /* +1 is for the separator */ else if ((strlen(p_workdir)+1+strlen(p_name)) <= p_bta_fs_cfg->max_path_len) { /* 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_MSE_ENABLE_FS_CO == TRUE if (((bta_fs_co_access(p_path, BTA_FS_ACC_EXIST, &is_dir, bta_mse_cb.app_id)) == BTA_FS_CO_OK) && is_dir) { /* go back down one level to the name folder*/ *p_oper = BTA_MSE_OPER_SETPATH; } else rsp_code = OBX_RSP_NOT_FOUND; #else *p_oper = BTA_MSE_OPER_SETPATH; #endif } else { rsp_code = OBX_RSP_INTRNL_SRVR_ERR; } break; case BTA_MA_DIR_NAV_UP_ONE_LVL: if (strcmp(p_workdir, p_scb->p_rootpath)) { /* Find the last occurrence of separator and replace with '\0' */ BCM_STRNCPY_S(p_path, p_bta_fs_cfg->max_path_len+1, p_workdir, p_bta_fs_cfg->max_path_len); if ((p_tmp = strrchr(p_path, (int)p_bta_fs_cfg->path_separator)) != NULL) { *p_tmp = '\0'; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT1("path=[%s]",p_path ); APPL_TRACE_EVENT1("name=[%s]", p_name ); #endif /* now check we need to go down one level if name is not empty*/ if (*p_name !='\0') { if ((strlen(p_workdir)+1+strlen(p_name)) <= p_bta_fs_cfg->max_path_len) { sprintf(p_path, "%s%c%s", p_path, p_bta_fs_cfg->path_separator, p_name); #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("Up one level and then down one" ); APPL_TRACE_EVENT1("path=[%s]",p_path ); #endif #if BTA_MSE_ENABLE_FS_CO == TRUE if (((bta_fs_co_access(p_path, BTA_FS_ACC_EXIST, &is_dir, bta_mse_cb.app_id)) == BTA_FS_CO_OK) && is_dir) { /* go up one level and then go down one level to the name folder */ *p_oper = BTA_MSE_OPER_SETPATH; } else { rsp_code = OBX_RSP_NOT_FOUND; } #else *p_oper = BTA_MSE_OPER_SETPATH; #endif } else { rsp_code = OBX_RSP_INTRNL_SRVR_ERR; } } else { /* just go up one level to the parent directory */ *p_oper = BTA_MSE_OPER_SETPATH; } } else { rsp_code = OBX_RSP_INTRNL_SRVR_ERR; } } else { rsp_code = OBX_RSP_NOT_FOUND; } break; default: rsp_code = OBX_RSP_INTRNL_SRVR_ERR; break; } return(rsp_code); } /******************************************************************************* ** ** Function bta_mse_send_set_notif_reg ** ** Description Send a set notification registration event to application ** so application can decide whether the request is allowed or not ** ** Parameters status - (output) pointer to the MSE operation code ** inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns TRUE - request is sent FALSE - requestr is not sent due to ** error in the request *******************************************************************************/ BOOLEAN bta_mse_send_set_notif_reg(UINT8 status, UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_MA_CB *p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx); tBTA_MSE cback_evt_data; tBTA_MA_NOTIF_STATUS notif_sts = BTA_MA_NOTIF_OFF; BOOLEAN send_status = TRUE; UINT8 ccb_idx; if (status & BTA_MA_NOTIF_STS_ON) notif_sts = BTA_MA_NOTIF_ON; if (notif_sts == BTA_MA_NOTIF_OFF) { if (!bta_mse_find_bd_addr_match_mn_cb_index(p_cb->bd_addr, &ccb_idx)) { send_status = FALSE; } } if (send_status) { cback_evt_data.set_notif_reg.mas_session_id = p_cb->obx_handle; cback_evt_data.set_notif_reg.mas_instance_id = p_scb->mas_inst_id; cback_evt_data.set_notif_reg.notif_status = notif_sts; bdcpy(cback_evt_data.set_notif_reg.bd_addr, p_cb->bd_addr); bta_mse_cb.p_cback(BTA_MSE_SET_NOTIF_REG_EVT, (tBTA_MSE *) &cback_evt_data); } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT1("bta_mse_send_set_notif_reg send_status=%d",send_status ); #endif return send_status; } /******************************************************************************* ** ** Function bta_mse_proc_notif_reg_status ** ** Description Process the notification registration status to determine ** whether a MN conenction should be opened or closed ** ** Parameters status - (output) pointer to the MSE operation code ** inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** ** Returns None ** *******************************************************************************/ void bta_mse_proc_notif_reg_status(UINT8 status, UINT8 inst_idx, UINT8 sess_idx ) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); tBTA_MSE_MA_CB *p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx); tBTA_MA_NOTIF_STATUS notif_sts = BTA_MA_NOTIF_OFF; tBTA_MSE_MN_CB *p_ccb; UINT8 ccb_idx; tBTA_MSE_MN_ACT_TYPE mn_act_type = BTA_MSE_MN_ACT_TYPE_NONE; tOBX_RSP_CODE rsp_code = OBX_RSP_OK; tBTA_MSE cback_evt_data; tBTA_MSE_MN_INT_OPEN *p_open_evt; tBTA_MSE_MN_INT_CLOSE *p_close_evt; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_proc_notif_reg_status"); #endif if (status & BTA_MA_NOTIF_STS_ON) notif_sts = BTA_MA_NOTIF_ON; switch (notif_sts) { case BTA_MA_NOTIF_ON: if (!bta_mse_find_bd_addr_match_mn_cb_index(p_cb->bd_addr, &ccb_idx)) { if (bta_mse_find_avail_mn_cb_idx(&ccb_idx)) mn_act_type = BTA_MSE_MN_ACT_TYPE_OPEN_CONN; else mn_act_type = BTA_MSE_MN_ACT_TYPE_OPEN_CONN_ERR; } else { /* it is connected already */ mn_act_type = BTA_MSE_MN_ACT_TYPE_OPEN_CONN_NONE; } break; case BTA_MA_NOTIF_OFF: if (!bta_mse_find_bd_addr_match_mn_cb_index(p_cb->bd_addr, &ccb_idx)) { mn_act_type = BTA_MSE_MN_ACT_TYPE_CLOSE_CONN_ERR; break; } p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); if ((p_ccb->state !=BTA_MSE_MN_W4_CONN_ST) && (p_ccb->state !=BTA_MSE_MN_CONN_ST)) { /* MN is either idle or to be closed shortly so do nothing*/ mn_act_type = BTA_MSE_MN_ACT_TYPE_CLOSE_CONN_NONE; } else { if (bta_mse_mn_is_ok_to_close_mn(p_cb->bd_addr, p_scb->mas_inst_id)) { /* This is the last active MN session using this conncection*/ mn_act_type = BTA_MSE_MN_ACT_TYPE_CLOSE_CONN; } else { mn_act_type = BTA_MSE_MN_ACT_TYPE_CLOSE_CONN_NONE; } } break; } switch (mn_act_type) { case BTA_MSE_MN_ACT_TYPE_OPEN_CONN: if ((p_open_evt = (tBTA_MSE_MN_INT_OPEN *) GKI_getbuf(sizeof(tBTA_MSE_MN_INT_OPEN))) != NULL) { bta_mse_mn_add_inst_id(ccb_idx, p_scb->mas_inst_id); p_open_evt->hdr.event = BTA_MSE_MN_INT_OPEN_EVT; p_open_evt->ccb_idx = ccb_idx; p_open_evt->sec_mask = (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT); memcpy(p_open_evt->bd_addr, p_cb->bd_addr, sizeof(BD_ADDR)); bta_sys_sendmsg(p_open_evt); } else { rsp_code = OBX_RSP_FAILED; } break; case BTA_MSE_MN_ACT_TYPE_CLOSE_CONN: if ((p_close_evt = (tBTA_MSE_MN_INT_CLOSE *) GKI_getbuf(sizeof(tBTA_MSE_MN_INT_CLOSE))) != NULL) { bta_mse_mn_remove_inst_id(ccb_idx, p_scb->mas_inst_id); p_close_evt->hdr.event = BTA_MSE_MN_INT_CLOSE_EVT; p_close_evt->ccb_idx = ccb_idx; bta_sys_sendmsg(p_close_evt); } else { rsp_code = OBX_RSP_FAILED; } break; case BTA_MSE_MN_ACT_TYPE_OPEN_CONN_ERR: rsp_code = OBX_RSP_FAILED; break; case BTA_MSE_MN_ACT_TYPE_OPEN_CONN_NONE: bta_mse_mn_add_inst_id(ccb_idx, p_scb->mas_inst_id); break; case BTA_MSE_MN_ACT_TYPE_CLOSE_CONN_NONE: bta_mse_mn_remove_inst_id(ccb_idx, p_scb->mas_inst_id); break; default: break; } OBX_PutRsp(p_cb->obx_handle , rsp_code, NULL); if (rsp_code == OBX_RSP_OK) cback_evt_data.notif_reg.status = BTA_MA_STATUS_OK; else cback_evt_data.notif_reg.status = BTA_MA_STATUS_FAIL; cback_evt_data.notif_reg.mas_session_id = p_cb->obx_handle; cback_evt_data.notif_reg.mas_instance_id = p_scb->mas_inst_id; cback_evt_data.notif_reg.notif_status = notif_sts; bdcpy(cback_evt_data.notif_reg.bd_addr, p_cb->bd_addr); bta_mse_clean_set_notif_reg(inst_idx,sess_idx); bta_mse_cb.p_cback(BTA_MSE_NOTIF_REG_EVT, (tBTA_MSE *) &cback_evt_data); } /******************************************************************************* ** ** Function bta_mse_discard_data ** ** Description frees the data ** ** Parameters event - MSE event ** p_data - Pointer to the MSE event data ** ** Returns void ** *******************************************************************************/ void bta_mse_discard_data(UINT16 event, tBTA_MSE_DATA *p_data) { #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_discard_data"); #endif switch (event) { case BTA_MSE_MA_OBX_CONN_EVT: case BTA_MSE_MA_OBX_DISC_EVT: case BTA_MSE_MA_OBX_ABORT_EVT: case BTA_MSE_MA_OBX_CLOSE_EVT: case BTA_MSE_MA_OBX_PUT_EVT: case BTA_MSE_MA_OBX_GET_EVT: case BTA_MSE_MA_OBX_SETPATH_EVT: utl_freebuf((void**)&p_data->obx_evt.p_pkt); break; default: /*Nothing to free*/ break; } } /******************************************************************************* ** ** Function bta_mse_find_mas_inst_id_match_cb_idx ** ** Description Finds the MAS instance control block index based on the specified ** MAS instance ID ** ** Parameters mas_inst_id - MAS instance ID ** p_idx - (output) pointer to the MA control block index ** ** Returns BOOLEAN - TRUE found ** FALSE not found *******************************************************************************/ BOOLEAN bta_mse_find_mas_inst_id_match_cb_idx(tBTA_MA_INST_ID mas_inst_id, UINT8 *p_idx) { BOOLEAN found=FALSE; UINT8 i; for (i=0; i < BTA_MSE_NUM_INST ; i ++) { if (bta_mse_cb.scb[i].in_use) { if (bta_mse_cb.scb[i].mas_inst_id == mas_inst_id) { found = TRUE; *p_idx = i; break; } } } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT3("bta_mse_find_mas_inst_id_match_cb_idx found=%d, inst_id=%d inst_idx=%d", found, mas_inst_id, i); #endif return found; } /******************************************************************************* ** ** Function bta_mse_find_bd_addr_match_sess_cb_idx ** ** Description Finds the Session control block index based on the specified ** MAS instance control block index and BD address ** ** Parameters bd_addr - BD address ** inst_idx - MA control block index ** p_idx - (output) pointer to the MA server control block ** index ** ** ** Returns BOOLEAN - TRUE found ** FALSE not found *******************************************************************************/ BOOLEAN bta_mse_find_bd_addr_match_sess_cb_idx(BD_ADDR bd_addr, UINT8 inst_idx, UINT8 *p_idx) { tBTA_MSE_MA_SESS_CB *p_cb; BOOLEAN found=FALSE; UINT8 i; for (i=0; i < BTA_MSE_NUM_SESS ; i ++) { p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, i); if ((p_cb->state == BTA_MSE_MA_CONN_ST) && !memcmp (p_cb->bd_addr, bd_addr, BD_ADDR_LEN)) { found = TRUE; *p_idx = i; break; } } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT3("bta_mse_find_bd_addr_match_sess_cb_idx found=%d, inst_idx=%d p_idx=%d", found, inst_idx, i); #endif return found; } /******************************************************************************* ** ** Function bta_mse_find_handle_match_mas_inst_cb_idx ** ** Description Finds the MAS instance control block index based on the specified Obx handle ** ** Parameters obx_handle - Obex session handle ** p_idx - (output) pointer to the MA server control block index ** ** ** Returns BOOLEAN - TRUE found ** FALSE not found ** *******************************************************************************/ BOOLEAN bta_mse_find_handle_match_mas_inst_cb_idx(tOBX_HANDLE obx_handle, UINT8 *p_idx) { BOOLEAN found=FALSE; UINT8 i; for (i=0; i < BTA_MSE_NUM_INST ; i ++) { if (bta_mse_cb.scb[i].in_use) { if (bta_mse_cb.scb[i].obx_handle == obx_handle) { found = TRUE; *p_idx = i; break; } } } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_find_handle_match_mas_inst_cb_idx found=%d idx=%d",found, i); #endif return found; } /******************************************************************************* ** ** Function bta_mse_find_mas_sess_cb_idx ** ** Description Finds the MAS instance and session control block indexes ** based on Obx handle ** ** Parameters obx_handle - Obex session handle ** p_mas_inst_idx - (output) pointer to the MA server control ** block index ** p_mas_sess_idx - (output) pointer to the MA session control ** block index ** ** Returns BOOLEAN - TRUE found ** FALSE not found ** *******************************************************************************/ BOOLEAN bta_mse_find_mas_sess_cb_idx(tOBX_HANDLE obx_handle, UINT8 *p_mas_inst_idx, UINT8 *p_mas_sess_idx) { BOOLEAN found=FALSE; UINT8 i, j; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_find_mas_sess_cb_idx"); #endif for (i=0; i< BTA_MSE_NUM_INST; i++) { if (bta_mse_cb.scb[i].in_use) { for (j=0; j < BTA_MSE_NUM_SESS; j++ ) { if ( (bta_mse_cb.scb[i].sess_cb[j].state != BTA_MSE_MA_LISTEN_ST) && (bta_mse_cb.scb[i].sess_cb[j].obx_handle == obx_handle) ) { found = TRUE; *p_mas_inst_idx = i; *p_mas_sess_idx = j; return found; } } } } return found; } /******************************************************************************* ** ** Function bta_mse_find_ma_cb_indexes ** ** Description Finds the MAS instance and session control block indexes ** based on the received internal event ** ** Parameters p_msg - Pointer to MSE msg data ** p_mas_inst_idx - (output) pointer to the MA server control ** block index ** p_mas_sess_idx - (output) pointer to the MA session control ** block index ** ** Returns BOOLEAN - TRUE found ** FALSE not found ** *******************************************************************************/ BOOLEAN bta_mse_find_ma_cb_indexes(tBTA_MSE_DATA *p_msg, UINT8 *p_inst_idx, UINT8 *p_sess_idx) { BOOLEAN found = FALSE; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_find_ma_cb_indexes"); #endif switch (p_msg->hdr.event) { case BTA_MSE_MA_OBX_CONN_EVT: if (bta_mse_find_handle_match_mas_inst_cb_idx( p_msg->obx_evt.param.conn.handle, p_inst_idx)) { if (bta_mse_find_avail_mas_sess_cb_idx(&(bta_mse_cb.scb[*p_inst_idx]), p_sess_idx)) found = TRUE; } break; case BTA_MSE_API_ACCESSRSP_EVT: if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->api_access_rsp.mas_session_id, p_inst_idx,p_sess_idx)) found = TRUE; break; case BTA_MSE_API_UPD_IBX_RSP_EVT: if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->api_upd_ibx_rsp.mas_session_id, p_inst_idx,p_sess_idx)) found = TRUE; break; case BTA_MSE_API_SET_NOTIF_REG_RSP_EVT: if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->api_set_notif_reg_rsp.mas_session_id, p_inst_idx,p_sess_idx)) found = TRUE; break; case BTA_MSE_INT_CLOSE_EVT: if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->int_close.mas_session_id, p_inst_idx,p_sess_idx)) found = TRUE; break; case BTA_MSE_CI_GET_FENTRY_EVT: if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->ci_get_fentry.mas_session_id, p_inst_idx,p_sess_idx)) found = TRUE; break; case BTA_MSE_CI_GET_ML_INFO_EVT: if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->ci_get_ml_info.mas_session_id, p_inst_idx,p_sess_idx)) found = TRUE; break; case BTA_MSE_CI_GET_ML_ENTRY_EVT: if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->ci_get_ml_entry.mas_session_id, p_inst_idx,p_sess_idx)) found = TRUE; break; case BTA_MSE_CI_GET_MSG_EVT: if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->ci_get_msg.mas_session_id, p_inst_idx,p_sess_idx)) found = TRUE; break; case BTA_MSE_CI_PUSH_MSG_EVT: if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->ci_push_msg.mas_session_id, p_inst_idx,p_sess_idx)) found = TRUE; break; case BTA_MSE_CI_DEL_MSG_EVT: if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->ci_del_msg.mas_session_id, p_inst_idx,p_sess_idx)) found = TRUE; break; case BTA_MSE_MA_OBX_DISC_EVT: case BTA_MSE_MA_OBX_ABORT_EVT: case BTA_MSE_MA_OBX_CLOSE_EVT: case BTA_MSE_MA_OBX_PUT_EVT: case BTA_MSE_MA_OBX_GET_EVT: case BTA_MSE_MA_OBX_SETPATH_EVT: if (bta_mse_find_mas_sess_cb_idx( p_msg->obx_evt.handle, p_inst_idx, p_sess_idx)) found = TRUE; break; default: break; } return found; } /******************************************************************************* ** ** Function bta_mse_ma_cleanup ** ** Description Free resources if unable to find MA control block indexes ** ** Parameters p_msg - Pointer to MSE msg data ** ** Returns none ** *******************************************************************************/ void bta_mse_ma_cleanup(tBTA_MSE_DATA *p_msg) { tBTA_MSE_OBX_EVT *p_evt = &p_msg->obx_evt; tBTA_MA_OBX_RSP *p_rsp = NULL; UINT8 rsp_code = OBX_RSP_BAD_REQUEST; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_ma_cleanup"); #endif switch (p_msg->hdr.event) { case BTA_MSE_MA_OBX_CONN_EVT: p_rsp = OBX_ConnectRsp; rsp_code = OBX_RSP_SERVICE_UNAVL; break; case BTA_MSE_MA_OBX_DISC_EVT: p_rsp = OBX_DisconnectRsp; break; case BTA_MSE_MA_OBX_ABORT_EVT: p_rsp = OBX_AbortRsp; break; case BTA_MSE_MA_OBX_PUT_EVT: p_rsp = OBX_PutRsp; break; case BTA_MSE_MA_OBX_GET_EVT: p_rsp = OBX_GetRsp; break; case BTA_MSE_MA_OBX_SETPATH_EVT: p_rsp = OBX_SetPathRsp; break; default: break; } if (p_rsp) { (*p_rsp)(p_evt->handle, rsp_code, (BT_HDR *)NULL); /* Done with Obex packet */ utl_freebuf((void**)&p_evt->p_pkt); } } /******************************************************************************* ** ** Function bta_mse_is_a_duplicate_id ** ** Description Determine the MAS instance ID has been used or not by other MAS instance ** ** Parameters mas_inst_id - MAS instance ID ** ** Returns BOOLEAN - TRUE the MAS isntance is a duplicate ID ** FALSE not a duplicate ID *******************************************************************************/ BOOLEAN bta_mse_is_a_duplicate_id(tBTA_MA_INST_ID mas_inst_id) { BOOLEAN is_duplicate=FALSE; UINT8 i; for (i=0; i < BTA_MSE_NUM_INST ; i ++) { if (bta_mse_cb.scb[i].in_use && (bta_mse_cb.scb[i].mas_inst_id == mas_inst_id)) { is_duplicate = TRUE; break; } } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_is_a_duplicate_id inst_id=%d status=%d", mas_inst_id, is_duplicate); #endif return is_duplicate; } /******************************************************************************* ** ** Function bta_mse_find_avail_mas_inst_cb_idx ** ** Description Finds a not in used MAS instance control block index ** ** Parameters p_idx - (output) pointer to the MA server control ** block index ** ** Returns BOOLEAN - TRUE found ** FALSE not found ** *******************************************************************************/ BOOLEAN bta_mse_find_avail_mas_inst_cb_idx(UINT8 *p_idx) { BOOLEAN found=FALSE; UINT8 i; for (i=0; i < BTA_MSE_NUM_INST ; i ++) { if (!bta_mse_cb.scb[i].in_use) { found = TRUE; *p_idx = i; break; } } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_find_avail_mas_inst_cb_idx found=%d inst_idx=%d", found, i); #endif return found; } /******************************************************************************* ** ** Function bta_mse_find_avail_mas_sess_cb_idx ** ** Description Finds a not in used MAS session control block index ** ** Parameters p_scb - Pointer to the MA control block ** p_idx - (output) pointer to the MA session control ** block index ** ** Returns BOOLEAN - TRUE found ** FALSE not found *******************************************************************************/ BOOLEAN bta_mse_find_avail_mas_sess_cb_idx(tBTA_MSE_MA_CB *p_scb, UINT8 *p_idx) { BOOLEAN found=FALSE; UINT8 i; for (i=0; i < BTA_MSE_NUM_SESS ; i ++) { if (p_scb->sess_cb[i].state == BTA_MSE_MA_LISTEN_ST) { if ((p_scb->sess_cb[i].p_workdir = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1))) != NULL) { found = TRUE; *p_idx = i; } break; } } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_find_avail_mas_sess_cb_idx found=%d idx=%d", found, i); #endif return found; } /******************************************************************************* ** ** Function bta_mse_find_avail_mn_cb_idx ** ** Description Finds a not in use MN control block index ** ** Parameters p_idx - (output) pointer to the MN control block index ** ** Returns BOOLEAN - TRUE found ** FALSE not found ** *******************************************************************************/ BOOLEAN bta_mse_find_avail_mn_cb_idx(UINT8 *p_idx) { BOOLEAN found=FALSE; UINT8 i; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_find_avail_mn_cb_idx"); #endif for (i=0; i < BTA_MSE_NUM_MN ; i ++) { if (!bta_mse_cb.ccb[i].in_use) { found = TRUE; *p_idx = i; break; } } return found; } /******************************************************************************* ** ** Function bta_mse_find_bd_addr_match_mn_cb_index ** ** Description Find the MN control block index based on the specified BD address ** ** Parameters p_bd_addr - Pointer to the BD address ** p_idx - (output) pointer to the MN control block index ** ** Returns BOOLEAN - TRUE found ** FALSE not found ** *******************************************************************************/ BOOLEAN bta_mse_find_bd_addr_match_mn_cb_index(BD_ADDR p_bd_addr, UINT8 *p_idx) { BOOLEAN found=FALSE; UINT8 i; for (i=0; i < BTA_MSE_NUM_MN ; i ++) { if ((bta_mse_cb.ccb[i].in_use) && (!memcmp (bta_mse_cb.ccb[i].bd_addr, p_bd_addr, BD_ADDR_LEN))) { found = TRUE; *p_idx = i; break; } } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_find_bd_addr_match_mn_cb_index found=%d index=%d", found, i); #endif return found; } /******************************************************************************* ** ** Function bta_mse_find_bd_addr_match_mn_cb_index ** ** Description Find the MN control block index based on the specified obx handle ** ** Parameters obx_hdl - Obex session handle ** p_idx - (output) pointer to the MN control block index ** ** Returns BOOLEAN - TRUE found ** FALSE not found ** *******************************************************************************/ BOOLEAN bta_mse_find_obx_hdl_match_mn_cb_index(tOBX_HANDLE obx_hdl, UINT8 *p_idx) { BOOLEAN found=FALSE; UINT8 i; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_find_obx_hdl_match_mn_cb_index"); #endif for (i=0; i < BTA_MSE_NUM_INST ; i ++) { if ((bta_mse_cb.ccb[i].in_use) && (bta_mse_cb.ccb[i].obx_handle == obx_hdl)) { found = TRUE; *p_idx = i; break; } } return found; } /******************************************************************************* ** ** Function bta_mse_find_sess_id_match_ma_cb_indexes ** ** Description Finds the MAS instance and session control block indexes ** based on the specified MAS session ID ** ** Parameters mas_session_id - MAS instance ID ** p_inst_idx - (output) pointer to the MA server control ** block index ** p_sess_idx - (output) pointer to the MA session control ** block index ** ** Returns BOOLEAN - TRUE found ** FALSE not found ** *******************************************************************************/ BOOLEAN bta_mse_find_sess_id_match_ma_cb_indexes(tBTA_MA_SESS_HANDLE mas_session_id, UINT8 *p_inst_idx, UINT8 *p_sess_idx) { BOOLEAN found=FALSE; UINT8 i,j; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_find_sess_id_match_ma_cb_indexes"); #endif for (i=0; i < BTA_MSE_NUM_INST ; i ++) { for (j=0; jhdr.event) { case BTA_MSE_MN_INT_OPEN_EVT: *p_ccb_idx= p_msg->mn_int_open.ccb_idx; break; case BTA_MSE_MN_INT_CLOSE_EVT: *p_ccb_idx= p_msg->mn_int_close.ccb_idx; break; case BTA_MSE_MN_OBX_CONN_RSP_EVT: if (!bta_mse_find_bd_addr_match_mn_cb_index( p_msg->obx_evt.param.conn.peer_addr, p_ccb_idx)) { found = FALSE; } break; case BTA_MSE_MN_OBX_TOUT_EVT: case BTA_MSE_MN_OBX_CLOSE_EVT: case BTA_MSE_MN_OBX_PUT_RSP_EVT: if (!bta_mse_find_obx_hdl_match_mn_cb_index( p_msg->obx_evt.handle, p_ccb_idx)) { found = FALSE; } break; case BTA_MSE_MN_SDP_OK_EVT: *p_ccb_idx = p_msg->mn_sdp_ok.ccb_idx; break; case BTA_MSE_MN_SDP_FAIL_EVT: *p_ccb_idx = p_msg->mn_sdp_fail.ccb_idx; break; default: found = FALSE; break; } return found; } /******************************************************************************* ** ** Function bta_mse_mn_cleanup ** ** Description Free resources if unable to find MN control block index ** ** Parameters p_msg - Pointer to MSE msg data ** ** Returns none ** *******************************************************************************/ void bta_mse_mn_cleanup(tBTA_MSE_DATA *p_msg) { tBTA_MSE_OBX_EVT *p_evt = &p_msg->obx_evt; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_mn_cleanup"); #endif switch (p_msg->hdr.event) { case BTA_MSE_MN_OBX_CONN_RSP_EVT: case BTA_MSE_MN_OBX_PUT_RSP_EVT: /* Done with Obex packet */ utl_freebuf((void**)&p_evt->p_pkt); break; default: break; } } /******************************************************************************* ** ** Function bta_mse_build_map_event_rpt_obj ** ** Description Create a MAP-Event-Report object in the ** specified buffer. ** ** Parameters notif_type - Notification type ** handle (input only) - handle of the message that the "type" ** indication refers to. Ignored when the event "type" is ** "MemoryFull" or "MemoryAvailable". ** p_folder - name of the folder in which the corresponding ** message has been filed by the MSE. NULL when the event ** "type" is "MemoryFull" or "MemoryAvailable". ** p_old_folder - Used only in case of a message shift to ** indicate the folder on the MSE from which the message ** has been shifted out. ** msg_typ - Gives the type of the message. Ignored when the ** event "type" is "MemoryFull" or "MemoryAvailable". ** p_len - Pointer to value containing the size of ** the buffer (p_buffer). Receives the output size of ** filled XML object. ** p_buffer - Pointer to buffer to receive the XML object. ** ** Returns BTA_MA_STATUS_FAIL if buffer was not large enough, otherwise ** returns BTA_MA_STATUS_OK. ** *******************************************************************************/ tBTA_MA_STATUS bta_mse_build_map_event_rpt_obj(tBTA_MSE_NOTIF_TYPE notif_type, tBTA_MA_MSG_HANDLE handle, char * p_folder, char * p_old_folder, tBTA_MA_MSG_TYPE msg_typ, UINT16 * p_len, UINT8 * p_buffer) { tBTA_MA_STREAM strm; memset(p_buffer, 0, *p_len); BTA_MaInitMemStream(&strm, p_buffer, *p_len); /* stream event attribute and event type */ bta_ma_stream_str(&strm, "\n" "\n"); /* set the output length (i.e. amount of buffer that got used) */ *p_len = bta_ma_stream_used_size(&strm); /* return status based on the stream status */ return(bta_ma_stream_ok(&strm) ? BTA_MA_STATUS_OK : BTA_MA_STATUS_FAIL); } /******************************************************************************* ** ** Function bta_mse_build_msg_listing_obj ** ** Description Build the message listing object in the specified buffer ** ** Parameters p_entry - Pointer to the message listing entry ** p_size - input: pointer to the available buffer size ** output: pointer to the filled buffer size ** p_buf - pointer to the buffer for building the msg listing ** object ** ** Returns status - BTA_MA_STATUS_OK - build the object successfully ** BTA_MA_STATUS_FAIL - failed to build the object ** *******************************************************************************/ tBTA_MA_STATUS bta_mse_build_msg_listing_obj(tBTA_MSE_CO_MSG_LIST_ENTRY *p_entry, UINT16 *p_size, char *p_buf ) { tBTA_MA_STREAM strm; memset(p_buf, 0, *p_size); BTA_MaInitMemStream(&strm, (UINT8 *)p_buf, *p_size); /* stream msg element */ bta_ma_stream_str(&strm, "msg_handle); if (p_entry->parameter_mask &BTA_MA_ML_MASK_SUBJECT) { bta_ma_stream_str(&strm, "\" subject = \""); bta_ma_stream_str(&strm, p_entry->subject); } if (p_entry->parameter_mask & BTA_MA_ML_MASK_DATETIME) { bta_ma_stream_str(&strm, "\" datetime = \""); bta_ma_stream_str(&strm, p_entry->date_time); } if (p_entry->parameter_mask & BTA_MA_ML_MASK_SENDER_NAME) { bta_ma_stream_str(&strm, "\" sender_name = \""); bta_ma_stream_str(&strm, p_entry->sender_name); } if (p_entry->parameter_mask & BTA_MA_ML_MASK_SENDER_ADDRESSING) { bta_ma_stream_str(&strm, "\" sender_addressing = \""); bta_ma_stream_str(&strm, p_entry->sender_addressing); } if (p_entry->parameter_mask & BTA_MA_ML_MASK_REPLYTO_ADDRESSING) { bta_ma_stream_str(&strm, "\" replyto_addressing = \""); bta_ma_stream_str(&strm, p_entry->replyto_addressing); } if (p_entry->parameter_mask & BTA_MA_ML_MASK_RECIPIENT_NAME) { bta_ma_stream_str(&strm, "\" recipient_name = \""); bta_ma_stream_str(&strm, p_entry->recipient_name); } if (p_entry->parameter_mask & BTA_MA_ML_MASK_RECIPIENT_ADDRESSING) { bta_ma_stream_str(&strm, "\" recipient_addressing = \""); bta_ma_stream_str(&strm, p_entry->recipient_addressing); } if (p_entry->parameter_mask & BTA_MA_ML_MASK_TYPE) { bta_ma_stream_str(&strm, "\" type = \""); if (!bta_ma_stream_str(&strm, bta_ma_msg_typ_to_string(p_entry->type))) { return BTA_MA_STATUS_FAIL; } } if (p_entry->parameter_mask & BTA_MA_ML_MASK_SIZE) { bta_ma_stream_str(&strm, "\" size = \""); bta_ma_stream_value(&strm, p_entry->org_msg_size); } if (p_entry->parameter_mask & BTA_MA_ML_MASK_TEXT) { bta_ma_stream_str(&strm, "\" text = \""); bta_ma_stream_boolean_yes_no(&strm, p_entry->text); } if (p_entry->parameter_mask & BTA_MA_ML_MASK_RECEPTION_STATUS) { bta_ma_stream_str(&strm, "\" reception_status = \""); if (!bta_ma_stream_str(&strm, bta_ma_rcv_status_to_string(p_entry->reception_status))) { return BTA_MA_STATUS_FAIL; } } if (p_entry->parameter_mask & BTA_MA_ML_MASK_ATTACHMENT_SIZE) { bta_ma_stream_str(&strm, "\" attachment_size = \""); bta_ma_stream_value(&strm, p_entry->attachment_size); } if (p_entry->parameter_mask & BTA_MA_ML_MASK_PRIORITY) { bta_ma_stream_str(&strm, "\" priority = \""); bta_ma_stream_boolean_yes_no(&strm, p_entry->high_priority); } if (p_entry->parameter_mask & BTA_MA_ML_MASK_READ) { bta_ma_stream_str(&strm, "\" read = \""); bta_ma_stream_boolean_yes_no(&strm, p_entry->read); } if (p_entry->parameter_mask & BTA_MA_ML_MASK_SENT) { bta_ma_stream_str(&strm, "\" sent = \""); bta_ma_stream_boolean_yes_no(&strm, p_entry->sent); } if (p_entry->parameter_mask & BTA_MA_ML_MASK_PROTECTED) { bta_ma_stream_str(&strm, "\" protected = \""); bta_ma_stream_boolean_yes_no(&strm, p_entry->is_protected); } /* stream msg element end tag*/ bta_ma_stream_str(&strm, "\"/> "); /* set the output length (i.e. amount of buffer that got used) */ *p_size = bta_ma_stream_used_size(&strm); /* return status based on the stream status */ return(bta_ma_stream_ok(&strm) ? BTA_MA_STATUS_OK : BTA_MA_STATUS_FAIL); } /******************************************************************************* ** ** Function bta_mse_mn_start_timer ** ** Description Start a wait for obx response timer ** ** Parameters ccb_inx - MN control block index ** timer_id - indicating this timer is for which operation ** ** Returns None ** *******************************************************************************/ void bta_mse_mn_start_timer(UINT8 ccb_idx, UINT8 timer_id) { tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); UINT16 event_id; p_cb->rsp_timer.param = (UINT32) (ccb_idx+1); event_id = (UINT16) BTA_MSE_MN_RSP0_TOUT_EVT + ccb_idx; bta_sys_start_timer(&p_cb->rsp_timer, event_id, p_bta_mse_cfg->obx_rsp_tout); p_cb->timer_oper = timer_id; } /******************************************************************************* ** ** Function bta_mse_mn_start_stop_timer ** ** Description Stop a wait for obx response timer ** ** Parameters ccb_inx - MN control block index ** timer_id - indicating this timer is for which operation ** ** Returns None ** *******************************************************************************/ void bta_mse_mn_stop_timer(UINT8 ccb_idx, UINT8 timer_id) { tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); if ((p_cb->timer_oper == timer_id) || (timer_id == BTA_MSE_TIMER_OP_ALL)) { p_cb->rsp_timer.param = 0; bta_sys_stop_timer(&p_cb->rsp_timer ); p_cb->timer_oper = BTA_MSE_TIMER_OP_NONE; } } /******************************************************************************* ** ** Function bta_mse_mn_add_inst_id ** ** Description Add mas_inst_id to the MN notif_reg data base ** ** Parameters ccb_inx - MN control block index ** mas_inst_id - MAS instance ID ** ** Returns BOOLEAN - TRUE OK ** FALSE not OK ** *******************************************************************************/ BOOLEAN bta_mse_mn_add_inst_id(UINT8 ccb_idx, tBTA_MA_INST_ID mas_inst_id) { BOOLEAN found=FALSE; BOOLEAN add_status=FALSE; UINT8 i; tBTA_MSE_MN_CB *p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_mn_add_inst_id ccb_idx=%d mas_inst_id=%d", ccb_idx, mas_inst_id); #endif for (i=0; i < BTA_MSE_NUM_INST ; i ++) { if (p_ccb->notif_reg[i].status && (p_ccb->notif_reg[i].mas_inst_id == mas_inst_id)) { found = TRUE; add_status = TRUE; break; } } if (!found) { for (i=0; i < BTA_MSE_NUM_INST ; i ++) { if (!p_ccb->notif_reg[i].status) { /* find an available entry to add */ p_ccb->notif_reg[i].mas_inst_id = mas_inst_id; p_ccb->notif_reg[i].status = TRUE; add_status = TRUE; break; } } } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT1("add_status=%d", add_status); #endif return add_status; } /******************************************************************************* ** ** Function bta_mse_mn_remove_inst_id ** ** Description Remove mas_inst_id from the MN notif_reg data base ** ** Parameters ccb_inx - MN control block index ** mas_inst_id - MAS instance ID ** ** Returns BOOLEAN - TRUE OK ** FALSE not OK ** *******************************************************************************/ BOOLEAN bta_mse_mn_remove_inst_id(UINT8 ccb_idx, tBTA_MA_INST_ID mas_inst_id) { BOOLEAN remove_status=FALSE; UINT8 i; tBTA_MSE_MN_CB *p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_mn_remove_inst_id ccb_idx=%d mas_inst_id=%d", ccb_idx, mas_inst_id); #endif for (i=0; i < BTA_MSE_NUM_INST ; i ++) { if (p_ccb->notif_reg[i].status && (p_ccb->notif_reg[i].mas_inst_id == mas_inst_id)) { p_ccb->notif_reg[i].status = FALSE; p_ccb->notif_reg[i].mas_inst_id =(tBTA_MA_INST_ID )0; remove_status = TRUE; break; } } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT1("remove_status=%d", remove_status); #endif return remove_status; } /******************************************************************************* ** ** Function bta_mse_mn_remove_all_inst_ids ** ** Description Remove all mas_inst_ids from the MN notif_reg data base ** ** Parameters ccb_inx - MN control block index ** ** Returns None ** *******************************************************************************/ void bta_mse_mn_remove_all_inst_ids(UINT8 ccb_idx) { UINT8 i; tBTA_MSE_MN_CB *p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT1("bta_mse_mn_remove_all_inst_ids ccb_idx=%d ", ccb_idx); #endif for (i=0; i < BTA_MSE_NUM_INST ; i ++) { if (p_ccb->notif_reg[i].status) { p_ccb->notif_reg[i].status = FALSE; p_ccb->notif_reg[i].mas_inst_id =(tBTA_MA_INST_ID) 0; } } } /******************************************************************************* ** ** Function bta_mse_mn_find_num_of_act_inst_id ** ** Description fin the number of Mas Instance IDs with registration status on ** ** Parameters ccb_inx - MN control block index ** ** Returns UINT8 - Number of active Mas Instance ID ** *******************************************************************************/ UINT8 bta_mse_mn_find_num_of_act_inst_id(UINT8 ccb_idx) { UINT8 i,cnt; tBTA_MSE_MN_CB *p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);; cnt =0; for (i=0; i < BTA_MSE_NUM_INST ; i ++) { if (p_ccb->notif_reg[i].status) cnt++; } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_mn_find_num_of_act_inst_id ccb_idx=%d cnt=%d", ccb_idx, cnt); #endif return cnt; } /******************************************************************************* ** ** Function bta_mse_mn_is_inst_id_exist ** ** Description Check whether the specified mas_inst_id is in the ** MN notif_reg data base ** ** Parameters ccb_inx - MN control block index ** mas_inst_id - MAS instance ID ** ** Returns BOOLEAN - TRUE found ** FALSE not found ** ** *******************************************************************************/ BOOLEAN bta_mse_mn_is_inst_id_exist(UINT8 ccb_idx, tBTA_MA_INST_ID mas_inst_id ) { BOOLEAN found = FALSE; UINT8 i; tBTA_MSE_MN_CB *p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);; for (i=0; i < BTA_MSE_NUM_INST ; i ++) { if (p_ccb->notif_reg[i].status && (p_ccb->notif_reg[i].mas_inst_id == mas_inst_id)) { found = TRUE; break; } } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT3("bta_mse_mn_is_inst_id_exist ccb_idx=%d mas_inst_id=%d found=%d", ccb_idx, mas_inst_id, found); #endif return found; } /******************************************************************************* ** ** Function bta_mse_mn_is_ok_to_close_mn ** ** Description Determine is ok to close MN connection ** ** Parameters bd_addr - BD address ** mas_inst_id - MAS instance ID ** ** Returns BOOLEAN - TRUE OK ** FALSE not OK ** *******************************************************************************/ BOOLEAN bta_mse_mn_is_ok_to_close_mn(BD_ADDR bd_addr, tBTA_MA_INST_ID mas_inst_id ) { UINT8 ccb_idx; BOOLEAN ok_status= FALSE; if (bta_mse_find_bd_addr_match_mn_cb_index(bd_addr, &ccb_idx) && (bta_mse_mn_find_num_of_act_inst_id(ccb_idx) == 1) && (bta_mse_mn_is_inst_id_exist(ccb_idx, mas_inst_id))) { ok_status = TRUE; } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_mn_is_ok_to_close_mn mas_inst_id=%d ok_status=%d", mas_inst_id, ok_status); #endif return ok_status; } /******************************************************************************* ** ** Function bta_mse_mn_get_first_inst_id ** ** Description Get the first active mas_inst_id from the MN notif_reg data base ** ** Parameters ccb_inx - MN control block index ** mas_inst_id - MAS instance ID ** ** Returns BOOLEAN - TRUE OK ** FALSE not OK ** *******************************************************************************/ BOOLEAN bta_mse_mn_get_first_inst_id(UINT8 ccb_idx, tBTA_MA_INST_ID *p_mas_inst_id) { BOOLEAN found=FALSE; UINT8 i; tBTA_MSE_MN_CB *p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); for (i=0; i < BTA_MSE_NUM_INST ; i ++) { if (p_ccb->notif_reg[i].status ) { *p_mas_inst_id = p_ccb->notif_reg[i].mas_inst_id; found = TRUE; break; } } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT3("bta_mse_mn_get_inst_id ccb_idx=%d found status =%d mas_inst_id=%d", ccb_idx, found, *p_mas_inst_id); #endif return found; } /******************************************************************************* ** ** Function bta_mse_mn_send_abort_req ** ** Description Send an abort request. ** ** Parameters ccb_inx - MN control block index ** ** Returns void ** *******************************************************************************/ void bta_mse_mn_send_abort_req(UINT8 ccb_idx) { tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); if (BTA_MSE_MN_ABORT_REQ_NOT_SENT == p_cb->aborting) { bta_mse_mn_start_timer(ccb_idx, BTA_MSE_TIMER_OP_ABORT); OBX_AbortReq(p_cb->obx_handle, (BT_HDR *)NULL); p_cb->aborting = BTA_MSE_MN_ABORT_REQ_SENT; } } /******************************************************************************* ** ** Function bta_mse_mn_cont_send_notif ** ** Description Continues the send notification operation. Builds a new OBX packet ** ** Parameters ccb_idx - MN control block index ** first_pkt - first obex packet indicator ** ** Returns tBTA_MA_STATUS : BTA_MA_STATUS_OK if msg notification sent is ok ** otherwise BTA_MA_STATUS_FAIL *******************************************************************************/ tBTA_MA_STATUS bta_mse_mn_cont_send_notif(UINT8 ccb_idx, BOOLEAN first_pkt) { tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx; tBTA_MSE_MN_MSG_NOTIF *p_msg_notif = &p_cb->msg_notif; tOBX_TRIPLET app_param[1]; UINT16 body_len; BOOLEAN final_pkt = FALSE; tBTA_MA_STATUS status = BTA_MA_STATUS_OK; /* Do not start another request if currently aborting */ if (p_cb->aborting) { bta_mse_mn_send_abort_req(ccb_idx); return status; } if ((p_obx->p_pkt = OBX_HdrInit(p_cb->obx_handle, p_cb->peer_mtu)) != NULL) { if (first_pkt) { OBX_AddTypeHdr(p_obx->p_pkt, BTA_MA_HDR_TYPE_EVENT_RPT); app_param[0].tag = BTA_MA_NAS_INST_ID_TAG_ID; app_param[0].len = BTA_MA_NAS_INST_ID_LEN; app_param[0].p_array = &(p_msg_notif->mas_instance_id); OBX_AddAppParamHdr(p_obx->p_pkt, app_param, 1); } else { p_obx->offset = p_obx->bytes_left = 0; /* 0 -length available */ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left); body_len = p_obx->bytes_left; final_pkt = ( (p_msg_notif->buffer_len - p_msg_notif->bytes_sent) < body_len) ? TRUE : FALSE ; if (final_pkt) body_len = (p_msg_notif->buffer_len - p_msg_notif->bytes_sent); memcpy(&p_obx->p_start[p_obx->offset], &(p_msg_notif->p_buffer[p_msg_notif->bytes_sent]), body_len); p_msg_notif->bytes_sent += body_len; p_obx->offset += body_len; OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, TRUE); } OBX_PutReq(p_cb->obx_handle, final_pkt , p_obx->p_pkt); p_obx->p_pkt = NULL; p_cb->req_pending = TRUE; bta_mse_set_mn_oper(ccb_idx, BTA_MSE_MN_OP_PUT_EVT_RPT); p_msg_notif->final_pkt = final_pkt; p_msg_notif->pkt_cnt++; } else { status = BTA_MA_STATUS_FAIL; } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT4("bta_mse_mn_cont_send_notif ccb_idx=%d first_pkt=%d send_status=%d final=%d", ccb_idx, first_pkt, status, final_pkt); #endif return status; } /******************************************************************************* ** ** Function bta_mse_mn_send_notif_evt ** ** Description Issue a send notification event ** ** Parameters mas_instance_id - MAS instance ID ** status - MS sttaus ** bd_addr - BD address ** ** ** Returns UINT8 OBX response code ** *******************************************************************************/ void bta_mse_mn_send_notif_evt(tBTA_MA_INST_ID mas_instance_id, tBTA_MA_STATUS status, BD_ADDR bd_addr ) { tBTA_MSE param; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_mn_send_notif_evt mas_instance_id=%d status=%d", mas_instance_id, status); #endif param.send_notif.mas_instance_id = mas_instance_id; param.send_notif.status = status; bdcpy(param.send_notif.bd_addr, bd_addr); bta_mse_cb.p_cback(BTA_MSE_SEND_NOTIF_EVT, ¶m); } /******************************************************************************* ** ** Function bta_mse_mn_clean_send_notif ** ** Description Clean up send notif resources and cotrol block ** ** Parameters ccb_idx - MN control block index ** ** Returns void ** *******************************************************************************/ void bta_mse_mn_clean_send_notif(UINT8 ccb_idx) { tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("bta_mse_mn_clean_send_notif"); #endif utl_freebuf((void**)&(p_cb->msg_notif.p_buffer)); bta_mse_set_mn_oper(ccb_idx, BTA_MSE_MN_OP_NONE); p_cb->req_pending = FALSE; p_cb->aborting = BTA_MSE_MN_ABORT_NONE; memset(&(p_cb->msg_notif), 0, sizeof(tBTA_MSE_MN_MSG_NOTIF)); } /******************************************************************************* ** ** Function bta_mse_ma_fl_read_app_params ** ** Description Read application parameters for the get folder list requst ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** p_pkt - Pointer to the obex packet ** ** Returns void ** *******************************************************************************/ void bta_mse_ma_fl_read_app_params(UINT8 inst_idx, UINT8 sess_idx, BT_HDR *p_pkt) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); UINT8 *p_param; UINT16 len; p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_MAX_LIST_COUNT, &len); if (p_param) { BE_STREAM_TO_UINT16(p_cb->fl_param.max_list_cnt, p_param); } else p_cb->fl_param.max_list_cnt = BTA_MA_DEFAULT_MAX_LIST_CNT; p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_START_STOFF, &len); if (p_param) { BE_STREAM_TO_UINT16(p_cb->fl_param.start_offset, p_param); } else p_cb->fl_param.start_offset = 0; } /******************************************************************************* ** ** Function bta_mse_ma_ml_read_app_params ** ** Description Read application parameters for the get message list requst ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** p_pkt - Pointer to the obex packet ** ** Returns void ** *******************************************************************************/ void bta_mse_ma_ml_read_app_params(UINT8 inst_idx, UINT8 sess_idx, BT_HDR *p_pkt) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); UINT8 *p_param; UINT16 len; memset(&(p_cb->ml_param.filter), 0x00, sizeof(tBTA_MA_MSG_LIST_FILTER_PARAM)); p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_MAX_LIST_COUNT, &len); if (p_param) { BE_STREAM_TO_UINT16(p_cb->ml_param.filter.max_list_cnt, p_param); } else { p_cb->ml_param.filter.max_list_cnt = BTA_MA_DEFAULT_MAX_LIST_CNT; } p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_START_STOFF, &len); if (p_param) { BE_STREAM_TO_UINT16(p_cb->ml_param.filter.list_start_offset, p_param); } else { p_cb->ml_param.filter.list_start_offset = 0; } p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_SUBJ_LEN, &len); if (p_param) { BE_STREAM_TO_UINT8(p_cb->ml_param.filter.subject_length, p_param); } else { p_cb->ml_param.filter.subject_length = 0xff; } p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_PARAM_MASK, &len); if (p_param) { BE_STREAM_TO_UINT32(p_cb->ml_param.filter.parameter_mask, p_param); } else { p_cb->ml_param.filter.parameter_mask = 0; } p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_MSG_TYPE, &len); if (p_param) { BE_STREAM_TO_UINT8(p_cb->ml_param.filter.msg_mask, p_param); } else { p_cb->ml_param.filter.msg_mask = 0; } p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_PRD_BEGIN, &len); if (p_param) { p_cb->ml_param.filter.period_begin[BTA_MA_LTIME_LEN]='\0'; if (len < BTA_MA_LTIME_LEN) { p_cb->ml_param.filter.period_begin[0] = '\0'; } else { BCM_STRNCPY_S((char *)p_cb->ml_param.filter.period_begin, sizeof(p_cb->ml_param.filter.period_begin), (const char *)p_param, BTA_MA_LTIME_LEN); } } else { p_cb->ml_param.filter.period_begin[0] = '\0'; } p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_PRD_END, &len); if (p_param) { p_cb->ml_param.filter.period_end[BTA_MA_LTIME_LEN] = '\0'; if (len < BTA_MA_LTIME_LEN) { p_cb->ml_param.filter.period_end[0] = '\0'; } else { BCM_STRNCPY_S((char *)p_cb->ml_param.filter.period_end, sizeof(p_cb->ml_param.filter.period_end), (const char *)p_param, BTA_MA_LTIME_LEN); } } else { p_cb->ml_param.filter.period_end[0] = '\0'; } p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_READ_STS, &len); if (p_param) { BE_STREAM_TO_UINT8(p_cb->ml_param.filter.read_status, p_param); } else { p_cb->ml_param.filter.read_status = 0; } p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_RECEIP, &len); p_cb->ml_param.filter.recipient[0] = '\0'; if (p_param && len) { if (len >= BTA_MA_MAX_FILTER_TEXT_SIZE) { p_cb->ml_param.filter.recipient[BTA_MA_MAX_FILTER_TEXT_SIZE] = '\0'; len = BTA_MA_MAX_FILTER_TEXT_SIZE; } BCM_STRNCPY_S((char *)p_cb->ml_param.filter.recipient, sizeof(p_cb->ml_param.filter.recipient), (const char *)p_param, len); } p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_ORIGIN, &len); p_cb->ml_param.filter.originator[0] = '\0'; if (p_param && len) { if (len >= BTA_MA_MAX_FILTER_TEXT_SIZE) { p_cb->ml_param.filter.originator[BTA_MA_MAX_FILTER_TEXT_SIZE] = '\0'; len = BTA_MA_MAX_FILTER_TEXT_SIZE; } BCM_STRNCPY_S((char *)p_cb->ml_param.filter.originator, sizeof(p_cb->ml_param.filter.originator), (const char *)p_param, len); } p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_PRIORITY, &len); if (p_param) { BE_STREAM_TO_UINT8(p_cb->ml_param.filter.pri_status, p_param); } else { p_cb->ml_param.filter.pri_status = 0; } } /******************************************************************************* ** ** Function bta_mse_ma_msg_read_app_params ** ** Description Read application parameters for the get message list requst ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** p_pkt - Pointer to the obex packet ** ** Returns BOOLEAN TRUE - operation is successful ** *******************************************************************************/ BOOLEAN bta_mse_ma_msg_read_app_params(UINT8 inst_idx, UINT8 sess_idx, BT_HDR *p_pkt) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); UINT8 *p_param; UINT16 len; p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_CHARSET, &len); if (p_param) { BE_STREAM_TO_UINT8(p_cb->msg_param.data.charset, p_param); } else { #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT0("Unable to decode or find charset in application parameter "); #endif return FALSE; } p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_ATTACH, &len); if (p_param) { BE_STREAM_TO_UINT8(p_cb->msg_param.data.attachment, p_param); } else { p_cb->msg_param.data.attachment = FALSE; } p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FRAC_REQ, &len); if (p_param) { BE_STREAM_TO_UINT8(p_cb->msg_param.data.fraction_request, p_param); } else { p_cb->msg_param.data.fraction_request = BTA_MA_FRAC_REQ_NO; } return TRUE; } /******************************************************************************* ** ** Function bta_mse_get_msglist_path ** ** Description Get the path based on received folder name for the get ** message list ** ** Parameters inst_idx - Index to the MA instance control block ** sess_idx - Index to the MA session control block ** p_path - (output) pointer to the folder path ** ** Returns BOOLEAN TRUE-get path is successful *******************************************************************************/ BOOLEAN bta_mse_get_msglist_path(UINT8 inst_idx, UINT8 sess_idx) { tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); char *p_name = p_cb->ml_param.p_name; char *p_path = p_cb->ml_param.p_path; char *p_workdir = p_cb->p_workdir; BOOLEAN status = TRUE; #if BTA_MSE_ENABLE_FS_CO == TRUE BOOLEAN is_dir; #endif if (*p_name == '\0') { BCM_STRNCPY_S(p_path, p_bta_fs_cfg->max_path_len+1, p_workdir, p_bta_fs_cfg->max_path_len); } /* Make sure the new path is not too big */ /* +1 is for the separator */ else if ((strlen(p_workdir)+1+strlen(p_name)) <= p_bta_fs_cfg->max_path_len) { /* 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_MSE_ENABLE_FS_CO == TRUE if (((bta_fs_co_access(p_path, BTA_FS_ACC_EXIST, &is_dir, bta_mse_cb.app_id)) != BTA_FS_CO_OK) || !is_dir) { status = FALSE; } #endif } else { status = FALSE; } #if BTA_MSE_DEBUG == TRUE APPL_TRACE_EVENT2("bta_mse_get_msglist_path status=%d pth=%s",status, p_path ); #endif return status; } /******************************************************************************* ** ** Function bta_mse_find_bd_addr_match_pm_cb_index ** ** Description Finds the PM control block index ** based on the specified BD address ** ** Parameters app_id - app_id ** p_bd_addr - BD address ** p_idx - (output) pointer to the MN control ** block index ** ** Returns BOOLEAN - TRUE found ** FALSE not found ** *******************************************************************************/ BOOLEAN bta_mse_find_pm_cb_index(BD_ADDR p_bd_addr, UINT8 *p_idx) { BOOLEAN found=FALSE; UINT8 i; for (i=0; i < BTA_MSE_NUM_MN ; i ++) { if ((bta_mse_cb.pcb[i].in_use) && (!memcmp (bta_mse_cb.pcb[i].bd_addr, p_bd_addr, BD_ADDR_LEN))) { found = TRUE; *p_idx = i; break; } } #if BTA_MSE_DEBUG == TRUE if (!found) APPL_TRACE_DEBUG2("dbg bta_mse_find_pm_cb_index found=%d index=%d", found, i); #endif return found; } /******************************************************************************* ** ** Function bta_mse_find_avail_pm_cb_idx ** ** Description Finds a not in use PM control block index ** ** Parameters p_idx - (output) pointer to the PM control block index ** ** Returns BOOLEAN - TRUE found ** FALSE not found ** *******************************************************************************/ BOOLEAN bta_mse_find_avail_pm_cb_idx(UINT8 *p_idx) { BOOLEAN found=FALSE; UINT8 i; for (i=0; i < BTA_MSE_NUM_MN ; i ++) { if (!bta_mse_cb.pcb[i].in_use) { found = TRUE; *p_idx = i; break; } } #if BTA_MSE_DEBUG == TRUE if (!found) APPL_TRACE_DEBUG2("bta_mse_find_avail_pm_cb_idx found=%d i=%d", found, i); #endif return found; } /******************************************************************************* ** ** Function bta_mse_pm_conn_open ** ** Description Determine whether or not bta_sys_conn_open should be called ** ** Parameters bd_addr - peer BD address ** ** Returns None ** *******************************************************************************/ void bta_mse_pm_conn_open(BD_ADDR bd_addr) { tBTA_MSE_PM_CB *p_pcb; UINT8 idx; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_DEBUG0("bta_mse_pm_conn_open"); #endif if (!bta_mse_find_pm_cb_index(bd_addr, &idx)) { if (bta_mse_find_avail_pm_cb_idx(&idx)) { p_pcb = BTA_MSE_GET_PM_CB_PTR(idx); p_pcb->in_use = TRUE; p_pcb->opened = TRUE; bdcpy(p_pcb->bd_addr, bd_addr); bta_sys_conn_open(BTA_ID_MSE , bta_mse_cb.app_id, bd_addr); } } } /******************************************************************************* ** ** Function bta_mse_pm_conn_close ** ** Description Determine whether or not bta_sys_conn_close should be called ** ** Parameters bd_addr - peer BD address ** ** Returns None *******************************************************************************/ void bta_mse_pm_conn_close(BD_ADDR bd_addr) { tBTA_MSE_PM_CB *p_pcb; UINT8 i, pm_idx, sess_idx, mn_idx; BOOLEAN found_bd_addr=FALSE; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_DEBUG0("bta_mse_pm_conn_close"); #endif if (bta_mse_find_pm_cb_index(bd_addr, &pm_idx)) { p_pcb = BTA_MSE_GET_PM_CB_PTR(pm_idx); if (p_pcb->opened) { for (i=0; ioper, oper); #endif if (p_cb->oper != oper) { p_cb->oper = oper; if (bta_mse_find_pm_cb_index(p_cb->bd_addr, &pm_idx)) { p_pcb = BTA_MSE_GET_PM_CB_PTR(pm_idx); if (oper != BTA_MSE_OPER_NONE ) { if (!p_pcb->busy) { p_pcb->busy = TRUE; bta_sys_busy(BTA_ID_MSE, bta_mse_cb.app_id, p_cb->bd_addr); } } else { if (p_pcb->busy) { for (i=0; ibd_addr, i, &j) && (i != inst_idx) && (j != sess_idx)) { p_scb = BTA_MSE_GET_SESS_CB_PTR(i, j); if (p_scb->oper != BTA_MSE_OPER_NONE ) { still_busy = TRUE; break; } } } if ((!still_busy) && bta_mse_find_bd_addr_match_mn_cb_index( p_cb->bd_addr, &mn_idx)) { p_mcb = BTA_MSE_GET_MN_CB_PTR(mn_idx); if (p_mcb->obx_oper != BTA_MSE_MN_OP_NONE ) { still_busy = TRUE; } } if (!still_busy) { p_pcb->busy = FALSE; bta_sys_idle(BTA_ID_MSE, bta_mse_cb.app_id, p_cb->bd_addr); } } } } } } /******************************************************************************* ** ** Function bta_mse_set_mn_oper ** ** Description Set MN operation and power management's busy/idle status based on ** MN operation ** ** Parameters ccb_idx - MN control block index ** oper - MN operation ** ** Returns None *******************************************************************************/ void bta_mse_set_mn_oper(UINT8 ccb_idx, UINT8 oper) { tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); tBTA_MSE_MA_SESS_CB *p_scb; tBTA_MSE_MN_CB *p_mcb; tBTA_MSE_PM_CB *p_pcb; UINT8 i, j, pm_idx, mn_idx; BOOLEAN still_busy = FALSE; #if BTA_MSE_DEBUG == TRUE APPL_TRACE_DEBUG2("dbg bta_mse_set_mn_oper old=%d new=%d", p_cb->obx_oper, oper); #endif if (p_cb->obx_oper != oper) { p_cb->obx_oper = oper; if (bta_mse_find_pm_cb_index(p_cb->bd_addr, &pm_idx)) { p_pcb = BTA_MSE_GET_PM_CB_PTR(pm_idx); if (oper != BTA_MSE_MN_OP_NONE ) { if (!p_pcb->busy) { p_pcb->busy = TRUE; bta_sys_busy(BTA_ID_MSE, bta_mse_cb.app_id, p_cb->bd_addr); } } else { if (p_pcb->busy) { for (i=0; ibd_addr, i, &j)) { p_scb = BTA_MSE_GET_SESS_CB_PTR(i, j); if (p_scb->oper != BTA_MSE_OPER_NONE ) { still_busy = TRUE; break; } } } if ((!still_busy) && bta_mse_find_bd_addr_match_mn_cb_index(p_cb->bd_addr, &mn_idx) && (mn_idx != ccb_idx)) { p_mcb = BTA_MSE_GET_MN_CB_PTR(mn_idx); if (p_mcb->obx_oper != BTA_MSE_MN_OP_NONE ) { still_busy = TRUE; } } if (!still_busy) { p_pcb->busy = FALSE; bta_sys_idle(BTA_ID_MSE, bta_mse_cb.app_id, p_cb->bd_addr); } } } } } } #endif /* BTA_MSE_INCLUDED */