diff options
author | Andre Eisenbach <andre@broadcom.com> | 2012-02-22 13:18:21 -0800 |
---|---|---|
committer | Matthew Xie <mattx@google.com> | 2012-07-14 11:19:11 -0700 |
commit | e448862a47c08eb23185aaed574b39264f5005fc (patch) | |
tree | 2bc6246e3091315e77224fd798ea2fe8074ef972 /bta/ma | |
parent | a2ca4b83ab8bbbfd8d5f6693e927ed4b82094624 (diff) | |
download | external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.zip external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.gz external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.bz2 |
Initial Bluedroid stack commit
Diffstat (limited to 'bta/ma')
-rw-r--r-- | bta/ma/bta_ma_api.c | 1203 | ||||
-rw-r--r-- | bta/ma/bta_ma_util.c | 1750 | ||||
-rw-r--r-- | bta/ma/bta_ma_util.h | 93 | ||||
-rw-r--r-- | bta/ma/bta_mse_act.c | 2763 | ||||
-rw-r--r-- | bta/ma/bta_mse_api.c | 437 | ||||
-rw-r--r-- | bta/ma/bta_mse_cfg.c | 31 | ||||
-rw-r--r-- | bta/ma/bta_mse_ci.c | 251 | ||||
-rw-r--r-- | bta/ma/bta_mse_int.h | 835 | ||||
-rw-r--r-- | bta/ma/bta_mse_main.c | 1367 | ||||
-rw-r--r-- | bta/ma/bta_mse_sdp.c | 63 | ||||
-rw-r--r-- | bta/ma/bta_mse_utils.c | 3867 |
11 files changed, 12660 insertions, 0 deletions
diff --git a/bta/ma/bta_ma_api.c b/bta/ma/bta_ma_api.c new file mode 100644 index 0000000..2157447 --- /dev/null +++ b/bta/ma/bta_ma_api.c @@ -0,0 +1,1203 @@ +/***************************************************************************** +** +** Name: bta_mse_api.c +** +** Description: This is the implementation of the common API for the Message +** Acess Profile of BTA, Broadcom Corp's Bluetooth +** application layer for mobile phones. +** +** Copyright (c) 2009-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 <string.h> +#include "bta_ma_api.h" +#include "bta_ma_util.h" +#include "bta_ma_co.h" +/******************************************************************************* +** +** Function BTA_MaBmsgCreate +** +** Description Create and initialize an instance of a tBTA_MA_BMSG structure. +** +** Parameters None +** +** Returns Pointer to a bMessage object, or NULL if this fails. +** +*******************************************************************************/ +tBTA_MA_BMSG * BTA_MaBmsgCreate(void) +{ + tBTA_MA_BMSG *p_msg = (tBTA_MA_BMSG *) bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG)); + + if ( p_msg ) + { + memset(p_msg, 0, sizeof(tBTA_MA_BMSG)); + } + else + { + APPL_TRACE_ERROR0("BTA_MaBmsgCreate failed"); + } + + return(p_msg); +} + +/******************************************************************************* +** +** Function BTA_MaBmsgFree +** +** Description Destroy (free) the contents of a tBTA_MA_BMSG structure. +** +** Parameters p_bmsg - Pointer to a bMessage object +** +** Returns None +** +*******************************************************************************/ +void BTA_MaBmsgFree(tBTA_MA_BMSG * p_msg) +{ + if ( p_msg ) + { + /* free folder string */ + bta_ma_bmsg_free(p_msg->p_folder); + + /* free all the vCards */ + bta_ma_bmsg_free_vcards(p_msg->p_orig); + + /* free the envelopes */ + bta_ma_bmsg_free_envelope(p_msg->p_envelope); + + /* free b-message structure itself */ + bta_ma_bmsg_free(p_msg); + } +} + +/******************************************************************************* +** +** Function BTA_MaBmsgSetReadSts +** +** Description Set the bmessage-readstatus-property value for the bMessage +** object. If the 'read_sts' is TRUE then value will be "READ", +** otherwise it is "UNREAD". +** +** Parameters p_bmsg - Pointer to a bMessage object +** read_sts - Read status TRUE- read FALSE - unread +** +** Returns None +** +*******************************************************************************/ +void BTA_MaBmsgSetReadSts(tBTA_MA_BMSG * p_msg, BOOLEAN read_sts) +{ + if ( p_msg ) + p_msg->read_sts = read_sts; +} + +/******************************************************************************* +** +** Function BTA_MaBmsgGetReadSts +** +** Description Get the bmessage-readstatus-property value for the bMessage +** object +** +** Parameters p_bmsg - Pointer to a bMessage object +** +** Returns Read status (TRUE/FALSE) for the specified bMessage. +** +*******************************************************************************/ +BOOLEAN BTA_MaBmsgGetReadSts(tBTA_MA_BMSG * p_msg) +{ + return( p_msg ? p_msg->read_sts : FALSE); +} + +/******************************************************************************* +** +** Function BTA_MaBmsgSetMsgType +** +** Description Set the bmessage-type-property value for the bMessage object +** +** Parameters p_bmsg - Pointer to a bMessage object +** msg_type - Message type +** +** Returns None +** +*******************************************************************************/ +void BTA_MaBmsgSetMsgType(tBTA_MA_BMSG * p_msg, tBTA_MA_MSG_TYPE msg_type) +{ + if ( p_msg ) + p_msg->msg_type = msg_type; +} + +/******************************************************************************* +** +** Function BTA_MaBmsgGetMsgType +** +** Description Get the bmessage-type-property value for the specified +** bMessage object +** +** Parameters p_bmsg - Pointer to a bMessage object +** +** Returns Message type +** +*******************************************************************************/ +tBTA_MA_MSG_TYPE BTA_MaBmsgGetMsgType(tBTA_MA_BMSG * p_msg) +{ + /* return 0 (for lack of a better value) */ + return( p_msg ? p_msg->msg_type : 0); +} + +/******************************************************************************* +** +** Function BTA_MaBmsgSetFolder +** +** Description Set the bmessage-folder-property value for the bMessage object +** +** Parameters p_bmsg - Pointer to a bMessage object +** p_folder - Pointer to a folder path +** +** Returns None +** +*******************************************************************************/ +void BTA_MaBmsgSetFolder(tBTA_MA_BMSG *p_msg, char *p_folder) +{ + if ( p_msg && p_folder ) + { + /* free any existing string */ + if ( p_msg->p_folder ) + bta_ma_bmsg_free(p_msg->p_folder); + + /* allocate a new one */ + p_msg->p_folder = (char *) bta_ma_bmsg_alloc(strlen(p_folder)+1); + if ( p_msg->p_folder ) + BCM_STRNCPY_S(p_msg->p_folder, strlen(p_folder)+1, p_folder, strlen(p_folder)+1); + } +} + +/******************************************************************************* +** +** Function BTA_MaBmsgGetFolder +** +** Description Get the bmessage-folder-property value for the specified +** bMessage object +** +** Parameters p_bmsg - Pointer to a bMessage object +** +** Returns Pointer to folder path string, or NULL if it has not been set. +** +*******************************************************************************/ +char * BTA_MaBmsgGetFolder(tBTA_MA_BMSG * p_msg) +{ + return(p_msg ? (char *) p_msg->p_folder : NULL); +} + +/******************************************************************************* +** +** Function BTA_MaBmsgAddOrigToBmsg +** +** Description Add an originator to the bMessage object +** +** Parameters p_bmsg - Pointer to a bMessage object +** +** Returns Pointer to a new vCard structure, or NULL if this function +** fails. +** +*******************************************************************************/ +tBTA_MA_BMSG_VCARD * BTA_MaBmsgAddOrigToBmsg(tBTA_MA_BMSG * p_msg) +{ + tBTA_MA_BMSG_VCARD * p_vcard = NULL; + tBTA_MA_BMSG_VCARD * p_last_vcard = NULL; + + if ( p_msg ) + { + p_vcard = (tBTA_MA_BMSG_VCARD *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_VCARD)); + if ( p_vcard ) + { + memset(p_vcard, 0, sizeof(tBTA_MA_BMSG_VCARD)); + p_vcard->version = BTA_MA_VCARD_VERSION_21; /* default to 2.1 */ + + if ( p_msg->p_orig ) + { + /* set pointer to the last entry in the list */ + p_last_vcard = p_msg->p_orig; + while ( p_last_vcard->p_next ) + p_last_vcard = (tBTA_MA_BMSG_VCARD *) p_last_vcard->p_next; + + p_last_vcard->p_next = p_vcard; + } + else + p_msg->p_orig = p_vcard; + } + } + + return(p_vcard); +} + +/******************************************************************************* +** +** Function BTA_MaBmsgGetOrigFromBmsg +** +** Description Get the first originator vCard information from the specified +** bMessage object +** +** Parameters p_bmsg - Pointer to a bMessage object +** +** Returns Pointer to first 'originator vCard, or NULL not used. +** +*******************************************************************************/ +tBTA_MA_BMSG_VCARD * BTA_MaBmsgGetOrigFromBmsg(tBTA_MA_BMSG * p_msg) +{ + return(p_msg ? (tBTA_MA_BMSG_VCARD *) p_msg->p_orig : NULL); +} + +/******************************************************************************* +** +** Function BTA_MaBmsgAddEnvToBmsg +** +** Description Add a new envelope to the bMessage object. This is the first +** (top) level envelope. bMessage allows up to 3 levels of envelopes. +** application should call BTA_MaBmsgAddEnvToEnv to add the 2nd +** 3rd level enevelope. +** +** Parameters p_bmsg - Pointer to a bMessage object +** +** Returns Pointer to a new envelope structure, or NULL if this +** function fails. +** +*******************************************************************************/ +tBTA_MA_BMSG_ENVELOPE * BTA_MaBmsgAddEnvToBmsg(tBTA_MA_BMSG * p_msg) +{ + tBTA_MA_BMSG_ENVELOPE * p_envelope = NULL; + + if ( p_msg ) + { + p_envelope = (tBTA_MA_BMSG_ENVELOPE *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_ENVELOPE)); + if ( p_envelope ) + { + memset(p_envelope, 0, sizeof(tBTA_MA_BMSG_ENVELOPE)); + p_msg->p_envelope = p_envelope; + } + } + + return( p_envelope ); +} +/******************************************************************************* +** +** Function BTA_MaBmsgAddEnvToEnv +** +** Description Add a child envelope to an existing envelope. +** +** Parameters p_envelope - Pointer to a parent envelope +** +** Returns Pointer to an envelope structure, or NULL if this +** function fails. +** +*******************************************************************************/ +tBTA_MA_BMSG_ENVELOPE * BTA_MaBmsgAddEnvToEnv(tBTA_MA_BMSG_ENVELOPE * p_envelope) +{ + tBTA_MA_BMSG_ENVELOPE * p_new_envelope = NULL; + + if ( p_envelope ) + { + p_new_envelope = (tBTA_MA_BMSG_ENVELOPE *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_ENVELOPE)); + if ( p_new_envelope ) + { + memset(p_new_envelope, 0, sizeof(tBTA_MA_BMSG_ENVELOPE)); + p_envelope->p_next = p_new_envelope; + } + } + + return( p_new_envelope ); +} + +/******************************************************************************* +** +** Function BTA_MaBmsgGetEnv +** +** Description Get the pointer of the first level envelope. +** +** Parameters p_bmsg - Pointer to a bMessage object +** +** Returns Pointer to the first level envelope structure, or NULL if it +** does not exist +** +*******************************************************************************/ +tBTA_MA_BMSG_ENVELOPE * BTA_MaBmsgGetEnv(tBTA_MA_BMSG * p_msg) +{ + return(p_msg ? (tBTA_MA_BMSG_ENVELOPE *) p_msg->p_envelope : NULL); +} + +/******************************************************************************* +** +** Function BTA_MaBmsgGetNextEnv +** +** Description Get the child envelope of the specified parent envelope. +** +** Parameters p_env - Pointer to a parent envelope +** +** Returns Pointer to a child enevelope. NULL if the +** envelope does not have a 'child' envelope. +** +*******************************************************************************/ +tBTA_MA_BMSG_ENVELOPE * BTA_MaBmsgGetNextEnv(tBTA_MA_BMSG_ENVELOPE * p_env) +{ + return(p_env ? (tBTA_MA_BMSG_ENVELOPE *)p_env->p_next : NULL); +} +/******************************************************************************* +** +** Function BTA_MaBmsgAddRecipToEnv +** +** Description Add recipient to the specified envelope. +** +** Parameters p_env - Pointer to a envelope +** +** Returns Pointer to a vCard structure. NULL if it +** fails to allocate a vCard structure. +** +*******************************************************************************/ +tBTA_MA_BMSG_VCARD * BTA_MaBmsgAddRecipToEnv(tBTA_MA_BMSG_ENVELOPE * p_env) +{ + tBTA_MA_BMSG_VCARD * p_vcard = NULL; + tBTA_MA_BMSG_VCARD * p_last_vcard = NULL; + + if ( p_env ) + { + p_vcard = (tBTA_MA_BMSG_VCARD *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_VCARD)); + if ( p_vcard ) + { + memset(p_vcard, 0, sizeof(tBTA_MA_BMSG_VCARD)); + p_vcard->version = BTA_MA_VCARD_VERSION_21; /* default to 2.1 */ + + if ( p_env->p_recip ) + { + /* set pointer to the last entry in the list */ + p_last_vcard = p_env->p_recip; + while ( p_last_vcard->p_next ) + p_last_vcard = (tBTA_MA_BMSG_VCARD *) p_last_vcard->p_next; + + p_last_vcard->p_next = p_vcard; + } + else + p_env->p_recip = p_vcard; + } + } + + return(p_vcard); +} +/******************************************************************************* +** +** Function BTA_MaBmsgGetRecipFromEnv +** +** Description Get the first recipient's vCard from the specified envelope. +** +** Parameters p_env - Pointer to a envelope +** +** Returns Pointer to the first recipient's vCard structure. NULL if it +** has not be set. +** +*******************************************************************************/ +tBTA_MA_BMSG_VCARD * BTA_MaBmsgGetRecipFromEnv(tBTA_MA_BMSG_ENVELOPE * p_env) +{ + return(p_env ? p_env->p_recip : NULL); +} +/******************************************************************************* +** +** Function BTA_MaBmsgAddBodyToEnv +** +** Description Add a message body to the specified envelope. +** +** Parameters p_env - Pointer to a envelope +** +** Returns Pointer to a message body structure. +** NULL if it fails to allocate a message body structure. +** +*******************************************************************************/ +tBTA_MA_BMSG_BODY * BTA_MaBmsgAddBodyToEnv(tBTA_MA_BMSG_ENVELOPE * p_env) +{ + tBTA_MA_BMSG_BODY * p_body = NULL; + + if ( p_env ) + { + /* free any existing body */ + if ( p_env->p_body ) + bta_ma_bmsg_free_body(p_env->p_body); + + /* allocate a new one */ + p_body = (tBTA_MA_BMSG_BODY *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_BODY)); + if ( p_body ) + { + memset(p_body, 0, sizeof(tBTA_MA_BMSG_BODY)); + p_body->encoding = BTA_MA_BMSG_ENC_8BIT; /* default */ + } + + p_env->p_body = p_body; + } + + return(p_body); +} +/******************************************************************************* +** +** Function BTA_MaBmsgGetBodyFromEnv +** +** Description Get the message body pointer from the specified envelope. +** +** Parameters p_env - Pointer to a envelope +** +** Returns Pointer to a message body structure. +** NULL if it has not been set. +** +*******************************************************************************/ +tBTA_MA_BMSG_BODY * BTA_MaBmsgGetBodyFromEnv(tBTA_MA_BMSG_ENVELOPE * p_env) +{ + return( p_env ? p_env->p_body : NULL); +} + +/******************************************************************************* +** +** Function BTA_MaBmsgSetBodyEncoding +** +** Description Set the bmessage-body-encoding-property value for the bMessage +** body. +** +** Parameters p_body - Pointer to a bMessage body +** encoding - encoding scheme +** +** Returns None +** +*******************************************************************************/ +void BTA_MaBmsgSetBodyEncoding(tBTA_MA_BMSG_BODY * p_body, tBTA_MA_BMSG_ENCODING encoding) +{ + if ( p_body ) + p_body->encoding = encoding; +} + +/******************************************************************************* +** +** Function BTA_MaBmsgGetBodyEncoding +** +** Description Get the bmessage-body-encoding-property value for the specified +** bMessage body. +** +** Parameters p_body - Pointer to a bMessage body +** +** Returns Message encoding scheme +** +*******************************************************************************/ +tBTA_MA_BMSG_ENCODING BTA_MaBmsgGetBodyEncoding(tBTA_MA_BMSG_BODY * p_body) +{ + return( p_body ? p_body->encoding : BTA_MA_BMSG_ENC_8BIT ); +} +/******************************************************************************* +** +** Function BTA_MaBmsgSetBodyPartid +** +** Description Set the bmessage-body-part-ID value for the speicified +** bMessage body. +** +** Parameters p_body - Pointer to a bMessage body +** part_id - Part ID (range: from 0 to 65535) +** +** Returns None +** +*******************************************************************************/ +void BTA_MaBmsgSetBodyPartid(tBTA_MA_BMSG_BODY * p_body, UINT16 part_id) +{ + if ( p_body ) + { + p_body->part_id = part_id; + p_body->is_multipart = TRUE; + } +} + +/******************************************************************************* +** +** Function BTA_MaBmsgGetBodyPartid +** +** Description Get the bmessage-body-part-ID value for the specified +** bMessage body. +** +** Parameters p_body - Pointer to a bMessage body +** +** Returns The value of the Part ID +** +*******************************************************************************/ +UINT16 BTA_MaBmsgGetBodyPartid(tBTA_MA_BMSG_BODY * p_body) +{ + return( p_body ? p_body->part_id : 0 ); +} +/******************************************************************************* +** +** Function BTA_MaBmsgIsBodyMultiPart +** +** Description Is this a multi-part body +** +** Parameters p_body - Pointer to a bMessage body +** +** Returns TURE - if this is a multi-part body +** +*******************************************************************************/ +BOOLEAN BTA_MaBmsgIsBodyMultiPart(tBTA_MA_BMSG_BODY * p_body) +{ + return( p_body ? p_body->is_multipart : FALSE ); +} + +/******************************************************************************* +** +** Function BTA_MaBmsgSetBodyCharset +** +** Description Set the bmessage-body-charset-property value for the speicified +** bMessage body. +** +** Parameters p_body - Pointer to a bMessage body +** charset - Charset +** +** Returns None +** +*******************************************************************************/ +void BTA_MaBmsgSetBodyCharset(tBTA_MA_BMSG_BODY * p_body, tBTA_MA_CHARSET charset) +{ + if ( p_body ) + p_body->charset = charset; +} +/******************************************************************************* +** +** Function BTA_MaBmsgGetBodyCharset +** +** Description Get the bmessage-body-charset-property value for the speicified +** bMessage body. +** +** Parameters p_body - Pointer to a bMessage body +** +** Returns Charset +** +*******************************************************************************/ +tBTA_MA_CHARSET BTA_MaBmsgGetBodyCharset(tBTA_MA_BMSG_BODY * p_body) +{ + return( p_body ? p_body->charset : BTA_MA_CHARSET_UNKNOWN ); +} +/******************************************************************************* +** +** Function BTA_MaBmsgSetBodyLanguage +** +** Description Set the bmessage-body-language-property value for the speicified +** bMessage body. +** +** Parameters p_body - Pointer to a bMessage body +** Language - the language of the message +** +** Returns None +** +*******************************************************************************/ +void BTA_MaBmsgSetBodyLanguage(tBTA_MA_BMSG_BODY * p_body, tBTA_MA_BMSG_LANGUAGE language) +{ + if ( p_body ) + p_body->language = language; +} +/******************************************************************************* +** +** Function BTA_MaBmsgGetBodyLanguage +** +** Description Get the bmessage-body-language-property value for the speicified +** bMessage body. +** +** Parameters p_body - Pointer to a bMessage body +** +** Returns the language of the message +** +*******************************************************************************/ +tBTA_MA_BMSG_LANGUAGE BTA_MaBmsgGetBodyLanguage(tBTA_MA_BMSG_BODY * p_body) +{ + return( p_body ? p_body->language : BTA_MA_BMSG_LANG_UNSPECIFIED ); +} +/******************************************************************************* +** +** Function BTA_MaBmsgAddContentToBody +** +** Description Add a message content to the speicified bMessage body. +** +** Parameters p_body - Pointer to a bMessage body +** +** Returns Pointer to a message content. +** NULL if it fails to allocate a message content buffer +** +*******************************************************************************/ +tBTA_MA_BMSG_CONTENT * BTA_MaBmsgAddContentToBody(tBTA_MA_BMSG_BODY * p_body) +{ + tBTA_MA_BMSG_CONTENT * p_content = NULL; + tBTA_MA_BMSG_CONTENT * p_last_content = NULL; + + if ( p_body ) + { + p_content = (tBTA_MA_BMSG_CONTENT *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_CONTENT)); + if ( p_content ) + { + memset(p_content, 0, sizeof(tBTA_MA_BMSG_CONTENT)); + + if ( p_body->p_content ) + { + /* set pointer to the last entry in the list */ + p_last_content = p_body->p_content; + while ( p_last_content->p_next ) + p_last_content = (tBTA_MA_BMSG_CONTENT *)p_last_content->p_next; + + p_last_content->p_next = p_content; + } + else + p_body->p_content = p_content; + } + } + + return(p_content); +} +/******************************************************************************* +** +** Function BTA_MaBmsgGetContentFromBody +** +** Description Get a message content from the speicified bMessage body. +** +** Parameters p_body - Pointer to a bMessage body +** +** Returns Pointer to a message content. +** NULL if it has not been set. +** +*******************************************************************************/ +tBTA_MA_BMSG_CONTENT * BTA_MaBmsgGetContentFromBody(tBTA_MA_BMSG_BODY * p_body) +{ + return(p_body ? p_body->p_content : NULL); +} +/******************************************************************************* +** +** Function BTA_MaBmsgGetNextContent +** +** Description Get the next message content from the speicified message content. +** +** Parameters p_content - Pointer to a message content +** +** Returns Pointer to a message content. +** NULL if it has not been set. +** +*******************************************************************************/ +tBTA_MA_BMSG_CONTENT * BTA_MaBmsgGetNextContent(tBTA_MA_BMSG_CONTENT * p_content) +{ + return(p_content ? (tBTA_MA_BMSG_CONTENT *)p_content->p_next : NULL); +} + +/******************************************************************************* +** +** Function BTA_MaBmsgAddMsgContent +** +** Description Add a text string to the speicified message content. +** +** Parameters p_content - Pointer to a message content +** p_text - Pointer to a text string +** +** Returns None +** +*******************************************************************************/ +void BTA_MaBmsgAddMsgContent(tBTA_MA_BMSG_CONTENT * p_content, char * p_text) +{ + tBTA_MA_BMSG_MESSAGE * p_message; + + if ( p_content ) + { + p_message = (tBTA_MA_BMSG_MESSAGE *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_MESSAGE)); + if ( p_message ) + { + memset(p_message, 0, sizeof(tBTA_MA_BMSG_MESSAGE)); + + p_message->p_text = (char *)bta_ma_bmsg_alloc(strlen(p_text)+1); + + if ( p_message->p_text ) + { + BCM_STRNCPY_S(p_message->p_text, strlen(p_text)+1, p_text, strlen(p_text)+1); + + /* if the content already points to a message, + ** then we tack it on the end of the message list. + */ + if ( p_content->p_message && p_content->p_last ) + p_content->p_last->p_next = p_message; + else + p_content->p_message = p_message; + + /* keep track of the last message text we added */ + p_content->p_last = p_message; + } + else + bta_ma_bmsg_free(p_message); + } + } +} + +/******************************************************************************* +** +** Function BTA_MaBmsgGetMsgContent +** +** Description Get the first text string from the speicified message content. +** +** Parameters p_content - Pointer to a message content +** +** Returns Pointer to the first text string. +** NULL if it has not been set. +** +*******************************************************************************/ +char * BTA_MaBmsgGetMsgContent(tBTA_MA_BMSG_CONTENT * p_content) +{ + char * p_text = NULL; + if ( p_content && p_content->p_message ) + { + /* reset 'last' pointer for when 'get_next' is called. */ + p_content->p_last = p_content->p_message; + + p_text = p_content->p_message->p_text; + } + + return( p_text ); +} +/******************************************************************************* +** +** Function BTA_MaBmsgGetMsgContent +** +** Description Get the next text string from the speicified message content. +** +** Parameters p_content - Pointer to a message content +** +** Returns Pointer to the next text string. +** NULL if it has not been set. +** +*******************************************************************************/ +char * BTA_MaBmsgGetNextMsgContent(tBTA_MA_BMSG_CONTENT * p_content) +{ + char * p_text = NULL; + + if ( p_content && p_content->p_last ) + { + /* advance pointer */ + p_content->p_last = ( tBTA_MA_BMSG_MESSAGE *)p_content->p_last->p_next; + + if ( p_content->p_last ) + p_text = p_content->p_last->p_text; + } + + return( p_text ); +} + + +/******************************************************************************* +** +** Function BTA_MaBmsgGetNextVcard +** +** Description Get the next vCard from the speicified vCard. +** +** Parameters p_vcard - Pointer to a vCard +** +** Returns Pointer to the next vCard. +** NULL if it has not been set. +** +*******************************************************************************/ +tBTA_MA_BMSG_VCARD * BTA_MaBmsgGetNextVcard(tBTA_MA_BMSG_VCARD * p_vcard) +{ + return(p_vcard ? (tBTA_MA_BMSG_VCARD *)p_vcard->p_next : NULL); +} + + +/******************************************************************************* +** +** Function BTA_MaBmsgSetVcardVersion +** +** Description Set the vCard version for the speicified vCard. +** +** Parameters p_vcard - Pointer to a vCard +** version - vcard version +** +** Returns None +** +*******************************************************************************/ +void BTA_MaBmsgSetVcardVersion(tBTA_MA_BMSG_VCARD * p_vcard, tBTA_MA_VCARD_VERSION version) +{ + if ( p_vcard ) + p_vcard->version = version; +} +/******************************************************************************* +** +** Function BTA_MaBmsgGetVcardVersion +** +** Description Get the vCard version from the speicified vCard. +** +** Parameters p_vcard - Pointer to a vCard +** +** Returns vCard version number +** +*******************************************************************************/ +tBTA_MA_VCARD_VERSION BTA_MaBmsgGetVcardVersion(tBTA_MA_BMSG_VCARD * p_vcard) +{ + return(p_vcard ? p_vcard->version : 0); +} +/******************************************************************************* +** +** Function BTA_MaBmsgAddVcardProp +** +** Description Add a property to the speicified vCard. +** +** Parameters p_vcard - Pointer to a vCard +** prop - Indicate which vCard peoperty +** p_value - Pointer to the vCard property value +** p_param - Pointer to the vCard property parameter +** +** Returns Pointer to the vCard peoperty +** +*******************************************************************************/ +tBTA_MA_VCARD_PROPERTY * BTA_MaBmsgAddVcardProp(tBTA_MA_BMSG_VCARD *p_vcard, tBTA_MA_VCARD_PROP prop, char *p_value, char *p_param) +{ + tBTA_MA_VCARD_PROPERTY * p_prop = NULL; + tBTA_MA_VCARD_PROPERTY * p_last_prop = NULL; + + if ( p_vcard && prop < BTA_MA_VCARD_PROP_MAX ) + { + p_prop = (tBTA_MA_VCARD_PROPERTY *) bta_ma_bmsg_alloc(sizeof(tBTA_MA_VCARD_PROPERTY)); + if ( p_prop ) + { + memset(p_prop, 0, sizeof(tBTA_MA_VCARD_PROPERTY)); + + /* Set the value (if given) */ + if ( p_value ) + { + p_prop->p_value = (char *)bta_ma_bmsg_alloc(strlen(p_value)+1); + if ( p_prop->p_value ) + BCM_STRNCPY_S(p_prop->p_value, strlen(p_value)+1, p_value, strlen(p_value)+1); + } + + /* Set the parameter (if given) */ + if ( p_param ) + { + p_prop->p_param = (char *)bta_ma_bmsg_alloc(strlen(p_param)+1); + if ( p_prop->p_param ) + BCM_STRNCPY_S(p_prop->p_param, strlen(p_param)+1, p_param, strlen(p_param)+1); + } + + /* There can be more than one of a property. So add this property to the end of the list. */ + if ( p_vcard->p_prop[prop] == NULL ) + p_vcard->p_prop[prop] = p_prop; + else + { + p_last_prop = p_vcard->p_prop[prop]; + while ( p_last_prop->p_next ) + p_last_prop = (tBTA_MA_VCARD_PROPERTY *)p_last_prop->p_next; + + p_last_prop->p_next = p_prop; + } + } + } + + return(p_prop); +} +/******************************************************************************* +** +** Function BTA_MaBmsgGetVcardProp +** +** Description Get the vCard property from the speicified vCard peoperty enum. +** +** Parameters p_vcard - Pointer to a vCard +** prop - Indicate which vCard peoperty +** +** Returns Pointer to the vCard peoperty. +** NULL if the vCard peoperty does not exist +** +*******************************************************************************/ +tBTA_MA_VCARD_PROPERTY * BTA_MaBmsgGetVcardProp(tBTA_MA_BMSG_VCARD * p_vcard, tBTA_MA_VCARD_PROP prop) +{ + return( p_vcard && prop < BTA_MA_VCARD_PROP_MAX ? p_vcard->p_prop[prop] : NULL); +} +/******************************************************************************* +** +** Function BTA_MaBmsgGetNextVcardProp +** +** Description Get the next vCard property from the speicified vCard peoperty. +** +** Parameters p_prop - Pointer to a vCard property +** +** Returns Pointer to the next vCard peoperty. +** NULL if the next vCard peoperty does not exist +** +*******************************************************************************/ +tBTA_MA_VCARD_PROPERTY * BTA_MaBmsgGetNextVcardProp(tBTA_MA_VCARD_PROPERTY * p_prop) +{ + return(p_prop ? (tBTA_MA_VCARD_PROPERTY *)p_prop->p_next : NULL); +} +/******************************************************************************* +** +** Function BTA_MaBmsgGetVcardPropValue +** +** Description Get the vCard property value from the speicified vCard peoperty. +** +** Parameters p_prop - Pointer to a vCard property +** +** Returns Pointer to the vCard peoperty value. +** NULL if the vCard peoperty value has not been set. +** +*******************************************************************************/ +char * BTA_MaBmsgGetVcardPropValue(tBTA_MA_VCARD_PROPERTY * p_prop) +{ + return(p_prop ? p_prop->p_value : NULL); +} +/******************************************************************************* +** +** Function BTA_MaBmsgGetVcardPropParam +** +** Description Get the vCard property parameter from the speicified vCard peoperty. +** +** Parameters p_prop - Pointer to a vCard property +** +** Returns Poiter to the vCard peoperty parameter. +** NULL if the vCard peoperty parameter has not been set. +** +*******************************************************************************/ +char * BTA_MaBmsgGetVcardPropParam(tBTA_MA_VCARD_PROPERTY * p_prop) +{ + return(p_prop ? p_prop->p_param : NULL); +} + +/******************************************************************************* +** +** Function BTA_MaBuildMapBmsgObj +** +** Description Builds a specification compliant bMessage object given a +** generic bMessage internal structure. +** +** Parameters p_msg - pointer to bMessage object structure (input). +** p_stream - Output stream. +** +** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not. +** +*******************************************************************************/ +tBTA_MA_STATUS BTA_MaBuildMapBmsgObj(tBTA_MA_BMSG * p_msg, + tBTA_MA_STREAM * p_stream) +{ + tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL; + + + if ( p_msg && p_stream ) + { + bta_ma_stream_str(p_stream, "BEGIN:BMSG"); + bta_ma_stream_str(p_stream, "\r\nVERSION:1.0"); + + /* Read Status */ + bta_ma_stream_str(p_stream, "\r\nSTATUS:"); + bta_ma_stream_str(p_stream, (BTA_MaBmsgGetReadSts(p_msg) ? "READ" : "UNREAD")); + + /* Type */ + bta_ma_stream_str(p_stream, "\r\nTYPE:"); + bta_ma_stream_str(p_stream, bta_ma_msg_typ_to_string(BTA_MaBmsgGetMsgType(p_msg))); + + /* Folder */ + bta_ma_stream_str(p_stream, "\r\nFOLDER:"); + bta_ma_stream_str(p_stream, BTA_MaBmsgGetFolder(p_msg)); + + /* Originator(s) */ + bta_ma_stream_vcards(p_stream, BTA_MaBmsgGetOrigFromBmsg(p_msg)); + + /* Envelopes (nested) */ + bta_ma_stream_envelopes(p_stream, BTA_MaBmsgGetEnv(p_msg)); + + bta_ma_stream_str(p_stream, "\r\nEND:BMSG\r\n"); + + /* if buffer overflowed then return failure */ + status = bta_ma_stream_ok(p_stream) + ? BTA_MA_STATUS_OK + : BTA_MA_STATUS_FAIL; + } +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("BTA_MA_STATUS =%d (0-OK) BTA_MaBuildMapBmsgObj", status); +#endif + return( status ); +} +/******************************************************************************* +** +** Function bta_ma_parse_map_bmsg_obj +** +** Description Parses a bMessage object from a stream into a generic +** bMessage internal structure. +** +** Parameters p_msg - pointer to bMessage object structure (output). +** p_stream - Input stream. +** +** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not. +** +*******************************************************************************/ +tBTA_MA_STATUS BTA_MaParseMapBmsgObj(tBTA_MA_BMSG * p_msg, + tBTA_MA_STREAM * p_stream) +{ + char sz[BTA_MA_MAX_SIZE]; + UINT32 prop_mask = 0; + tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL; + tBTA_MA_BMSG_VCARD * p_vcard = NULL; + tBTA_MA_BMSG_ENVELOPE * p_envelope = NULL; + tBTA_MA_MSG_TYPE msg_type = 0; + + APPL_TRACE_EVENT0("BTA_MaParseMapBmsgObj"); + if ( p_msg && p_stream ) + { + /* Must start with BEGIN:MSG */ + if ( bta_ma_get_tag(p_stream, sz, BTA_MA_MAX_SIZE) + && (strcmp(sz, "BEGIN") == 0) + && bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE) + && (strcmp(sz, "BMSG") == 0) ) + { + while ( bta_ma_get_tag(p_stream, sz, BTA_MA_MAX_SIZE) ) + { + /* VERSION */ + if ( strcmp(sz, "VERSION") == 0 ) + { + if ( bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE) + && (strcmp(sz, "1.0") == 0) ) + { + prop_mask |= BTA_MA_PROP_VERSION; + } + else + break; /* incorrect VERSION */ + } + else if ( strcmp(sz, "STATUS") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + BTA_MaBmsgSetReadSts(p_msg, (BOOLEAN) (strcmp(sz, "READ") == 0)); + } + else if ( strcmp(sz, "TYPE") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + if ( bta_ma_str_to_msg_typ(sz, &msg_type) ) + BTA_MaBmsgSetMsgType(p_msg, msg_type); + + } + else if ( strcmp(sz, "FOLDER") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + BTA_MaBmsgSetFolder(p_msg, sz); + } + else if ( strcmp(sz, "BEGIN") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + + if ( strcmp(sz, "VCARD") == 0 ) + { + p_vcard = BTA_MaBmsgAddOrigToBmsg(p_msg); + bta_ma_parse_vcard(p_vcard, p_stream); + } + else if ( strcmp(sz, "BENV") == 0 ) + { + p_envelope = BTA_MaBmsgAddEnvToBmsg(p_msg); + bta_ma_parse_envelope(p_envelope, p_stream); + } + else + { + APPL_TRACE_ERROR1("bta_ma_parse_map_bmsg_obj - Invalid BEGIN: '%s'", sz); + } + } + else if ( strcmp(sz, "END") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + status = BTA_MA_STATUS_OK; + break; + } + else + { + APPL_TRACE_ERROR1("bta_ma_parse_map_bmsg_obj - Invalid tag: '%s'", sz); + } + } + } + } + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("BTA_MaParseMapBmsgObj status=%d(0-OK)", status); +#endif + return( status ); +} + +/******************************************************************************* +** +** Function BTA_MaInitMemStream +** +** Description Initializes a memory based stream +** +** Parameters p_stream - pointer to stream information. +** p_buffer - pointer to buffer to be manipulated. +** size - size of buffer pointed to by 'p_buffer'. +** +** Returns TRUE if stream is opened. +** +*******************************************************************************/ +BOOLEAN BTA_MaInitMemStream(tBTA_MA_STREAM * p_stream, + UINT8 * p_buffer, + UINT16 size) +{ + if ( !p_stream ) + return(FALSE); + + memset(p_stream, 0, sizeof(tBTA_MA_STREAM)); + + p_stream->type = STRM_TYPE_MEMORY; + p_stream->u.mem.p_buffer = p_stream->u.mem.p_next = p_buffer; + p_stream->u.mem.size = size; + + return(TRUE); +} + +/******************************************************************************* +** +** Function BTA_MaInitFileStream +** +** Description Initializes a file stream +** +** Parameters p_stream - pointer to stream information. +** p_path - Full pathname to file to use. +** oflags - permissions and mode +** +** Returns TRUE if file stream is opened. +** +*******************************************************************************/ +BOOLEAN BTA_MaInitFileStream(tBTA_MA_STREAM * p_stream, + const char *p_path, + int oflags) +{ + if ( !p_stream ) + { + APPL_TRACE_ERROR0("Invalid stream pointer"); + return(FALSE); + } + + memset(p_stream, 0, sizeof(tBTA_MA_STREAM)); + + p_stream->type = STRM_TYPE_FILE; + + p_stream->u.file.fd = bta_ma_co_open(p_path, oflags); + + if ( p_stream->u.file.fd == -1 ) + { + APPL_TRACE_ERROR0("Unable to open file "); + p_stream->status = STRM_ERROR_FILE; + } + + /* return TRUE if stream is OK */ + return(p_stream->status == STRM_SUCCESS); +} + +/******************************************************************************* +** +** Function BTA_MaCloseStream +** +** Description Close a stream (do any necessary clean-up). +** +** Parameters p_stream - pointer to stream information. +** +** Returns void +** +*******************************************************************************/ +void BTA_MaCloseStream(tBTA_MA_STREAM * p_stream) +{ + if ( p_stream->type == STRM_TYPE_FILE ) + { + bta_ma_co_close(p_stream->u.file.fd); + p_stream->u.file.fd = BTA_FS_INVALID_FD; + } +} +#endif /* BTA_MSE_INCLUDED */ diff --git a/bta/ma/bta_ma_util.c b/bta/ma/bta_ma_util.c new file mode 100644 index 0000000..6544e6a --- /dev/null +++ b/bta/ma/bta_ma_util.c @@ -0,0 +1,1750 @@ +/***************************************************************************** +** +** Name: bta_ma_util.c +** +** Description: This is the implementation file for the Message Access +** Profile (MAP) utility functions. +** +** Copyright (c) 2009, Broadcom Corp., All Rights Reserved. +** Broadcom Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include "bt_target.h" + +#if defined(BTA_MSE_INCLUDED) && (BTA_MSE_INCLUDED) + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "bta_ma_api.h" +#include "bta_ma_util.h" + +/* +** Static constant data declarations +*/ +/* Charset */static const char * bmsg_body_charset[] = +{ + "native", /* BMSG_CHARSET_NATIVE (native) */ + "UTF-8" /* BMSG_CHARSET_UTF-8 (UTF-8) */ +}; + +static const int num_bmsg_body_charset = sizeof(bmsg_body_charset) / sizeof(char*); + + +/* vCard property names (the order is dicated by the tBTA_MA_BMSG_VCARD_PROP enumeration in bmsg_cnt.h) */ +static const char * vcard_prop_name[] = +{ + "N", /* VCARD_PROP_N */ + "FN", /* VCARD_PROP_FN */ + "TEL", /* VCARD_PROP_TEL */ + "EMAIL" /* VCARD_PROP_EMAIL */ +}; + +/* bMessage encoding names (the order is dictated by the tBTA_MA_BMSG_ENCODING enumeration in bmsg_cnt.h) */ +static const char * bmsg_body_encoding[] = +{ + "8BIT", /* BMSG_ENC_8BIT (8-Bit-Clean encoding) */ + "G-7BIT", /* BMSG_ENC_G7BIT (GSM 7 bit Default Alphabet) */ + "G-7BITEXT", /* BMSG_ENC_G7BITEXT (GSM 7 bit Alphabet with national language extension) */ + "G-UCS2" , /* BMSG_ENC_GUCS2 */ + "G-8BIT", /* BMSG_ENC_G8BIT */ + "C-8BIT", /* BMSG_ENC_C8BIT (Octet, unspecified) */ + "C-EPM", /* BMSG_ENC_CEPM (Extended Protocol Message) */ + "C-7ASCII", /* BMSG_ENC_C7ASCII (7-bit ASCII) */ + "C-IA5", /* BMSG_ENC_CIA5 (IA5) */ + "C-UNICODE", /* BMSG_ENC_CUNICODE (UNICODE) */ + "C-SJIS", /* BMSG_ENC_CSJIS (Shift-JIS) */ + "C-KOREAN", /* BMSG_ENC_CKOREAN (Korean) */ + "C-LATINHEB", /* BMSG_ENC_CLATINHEB (Latin/Hebrew) */ + "C-LATIN" /* BMSG_ENC_CLATIN (Latin) */ +}; + +static const int num_bmsg_body_encoding = sizeof(bmsg_body_encoding) / sizeof(char*); + +static const char * bmsg_body_language[] = +{ + "", /* BMSG_LANG_UNSPECIFIED (not provided in bBody */ + "UNKNOWN", /* BMSG_LANG_UNKNOWN */ + "SPANISH", /* BMSG_LANG_SPANISH */ + "TURKISH", /* BMSG_LANG_TURKISH */ + "PORTUGUESE", /* BMSG_LANG_PORTUGUESE */ + "ENGLISH", /* BMSG_LANG_ENGLISH */ + "FRENCH", /* BMSG_LANG_FRENCH */ + "JAPANESE", /* BMSG_LANG_JAPANESE */ + "KOREAN", /* BMSG_LANG_KOREAN */ + "CHINESE", /* BMSG_LANG_CHINESE */ + "HEBREW" /* BMSG_LANG_HEBREW */ +}; + +static const int num_bmsg_body_language = sizeof(bmsg_body_language) / sizeof(char*); + +#include "bta_ma_co.h" + +#define BTA_MSE_NOTIF_TYPE_NEW_MSG_STR "NewMessage" +#define BTA_MSE_NOTIF_TYPE_DELIVERY_SUCCESS_STR "DeliverySuccess" +#define BTA_MSE_NOTIF_TYPE_SENDING_SUCCESS_STR "SendingSuccess" +#define BTA_MSE_NOTIF_TYPE_DELIVERY_FAILURE_STR "DeliveryFailure" +#define BTA_MSE_NOTIF_TYPE_SENDING_FAILURE_STR "SendingFailure" +#define BTA_MSE_NOTIF_TYPE_MEMORY_FULL_STR "MemoryFull" +#define BTA_MSE_NOTIF_TYPE_MEMORY_AVAILABLE_STR "MemoryAvailable" +#define BTA_MSE_NOTIF_TYPE_MESSAGE_DELETED_STR "MessageDeleted" +#define BTA_MSE_NOTIF_TYPE_MESSAGE_SHIFT_STR "MessageShift" + +#define BTA_MSE_MSG_TYPE_EMAIL "EMAIL" +#define BTA_MSE_MSG_TYPE_SMS_GSM "SMS_GSM" +#define BTA_MSE_MSG_TYPE_SMS_CDMA "SMS_CDMA" +#define BTA_MSE_MSG_TYPE_MMS "MMS" + +#define BTA_MSE_RCV_STATUS_COMPLETE "complete" +#define BTA_MSE_RCV_STATUS_FRACTIONED "fractioned" +#define BTA_MSE_RCV_STATUS_NOTIFICATION "notification" + +#define BTA_MSE_BOOLEAN_YES "yes" +#define BTA_MSE_BOOLEAN_NO "no" + +/******************************************************************************* +** +** Function bta_ma_evt_typ_to_string +** +** Description Utility function to return a pointer to a string holding +** the notifiction "type" for the MAP-Event-Report object. +** +** Parameters notif_type - Notification type +** +** Returns Pointer to static string representing notification type. +** +*******************************************************************************/ + +const char * bta_ma_evt_typ_to_string(tBTA_MSE_NOTIF_TYPE notif_type) +{ + switch (notif_type) + { + case BTA_MSE_NOTIF_TYPE_NEW_MSG: + return(BTA_MSE_NOTIF_TYPE_NEW_MSG_STR); + case BTA_MSE_NOTIF_TYPE_DELIVERY_SUCCESS: + return(BTA_MSE_NOTIF_TYPE_DELIVERY_SUCCESS_STR); + case BTA_MSE_NOTIF_TYPE_SENDING_SUCCESS: + return(BTA_MSE_NOTIF_TYPE_SENDING_SUCCESS_STR); + case BTA_MSE_NOTIF_TYPE_DELIVERY_FAILURE: + return(BTA_MSE_NOTIF_TYPE_DELIVERY_FAILURE_STR); + case BTA_MSE_NOTIF_TYPE_SENDING_FAILURE: + return(BTA_MSE_NOTIF_TYPE_SENDING_FAILURE_STR); + case BTA_MSE_NOTIF_TYPE_MEMORY_FULL: + return(BTA_MSE_NOTIF_TYPE_MEMORY_FULL_STR); + case BTA_MSE_NOTIF_TYPE_MEMORY_AVAILABLE: + return(BTA_MSE_NOTIF_TYPE_MEMORY_AVAILABLE_STR); + case BTA_MSE_NOTIF_TYPE_MESSAGE_DELETED: + return(BTA_MSE_NOTIF_TYPE_MESSAGE_DELETED_STR); + case BTA_MSE_NOTIF_TYPE_MESSAGE_SHIFT: + return(BTA_MSE_NOTIF_TYPE_MESSAGE_SHIFT_STR); + } + + return NULL; +} + +/******************************************************************************* +** +** Function bta_ma_msg_typ_to_string +** +** Description Utility function to return a pointer to a string holding +** the "msg_type" for the MAP-Event-Report object or or the +** the type for the MAP-msg-listing object +** +** Parameters msg_typ - Message type +** +** Returns Pointer to static string representing message type. +** +*******************************************************************************/ + +const char * bta_ma_msg_typ_to_string(tBTA_MA_MSG_TYPE msg_typ) +{ + switch (msg_typ) + { + case BTA_MA_MSG_TYPE_EMAIL: return(BTA_MSE_MSG_TYPE_EMAIL); + case BTA_MA_MSG_TYPE_SMS_GSM: return(BTA_MSE_MSG_TYPE_SMS_GSM); + case BTA_MA_MSG_TYPE_SMS_CDMA: return(BTA_MSE_MSG_TYPE_SMS_CDMA); + case BTA_MA_MSG_TYPE_MMS: return(BTA_MSE_MSG_TYPE_MMS); + } + + return NULL; +} + +/******************************************************************************* +** +** Function bta_ma_rcv_status_to_string +** +** Description Utility function to return a pointer to a string holding +** the "reception_status" for the MAP-msg-listing object +** +** Parameters rcv_status - Reception status +** +** Returns Pointer to static string representing message type. +** +*******************************************************************************/ +const char * bta_ma_rcv_status_to_string(tBTA_MSE_CO_RCV_STATUS rcv_status) +{ + switch (rcv_status) + { + case BTA_MSE_CO_RCV_STATUS_COMPLETE: + return(BTA_MSE_RCV_STATUS_COMPLETE); + case BTA_MSE_CO_RCV_STATUS_FRACTIONED: + return(BTA_MSE_RCV_STATUS_FRACTIONED); + case BTA_MSE_CO_RCV_STATUS_NOTIFICATION: + return(BTA_MSE_RCV_STATUS_NOTIFICATION); + } + + return NULL; +} + +/******************************************************************************* +** +** Function bta_ma_stream_str +** +** Description Input a string into the stream. +** +** Parameters p_stream - pointer to stream information. +** p_str - pointer to string to be put in the buffer. Only the +** string characters, and not the NULL, are put into the +** buffer. +** +** Returns TRUE if the string was successfully added into the stream. +** +*******************************************************************************/ +BOOLEAN bta_ma_stream_str(tBTA_MA_STREAM * p_stream, const char * p_str) +{ + UINT16 buf_size; + UINT16 str_size; + UINT16 size = 0; + + /* ensure stream and string are not NULL */ + if ( !p_str || !p_stream ) + return(FALSE); + + /* get length of string */ + str_size = strlen(p_str); + + switch ( p_stream->type ) + { + case STRM_TYPE_MEMORY: + /* ensure buffer is not full */ + if ( p_stream->status == STRM_SUCCESS ) + { + /* get amount of size left in buffer */ + buf_size = p_stream->u.mem.size - bta_ma_stream_used_size(p_stream); + + /* calculate the size to copy (the minimum of string and buffer size */ + if ( str_size > buf_size ) + { + size = buf_size; + p_stream->status = STRM_ERROR_OVERFLOW; + } + else + size = str_size; + + /* copy the data and move the pointer */ + memcpy(p_stream->u.mem.p_next, p_str, size); + p_stream->u.mem.p_next += size; + } + break; + + case STRM_TYPE_FILE: + /* write string */ + bta_ma_co_write(p_stream->u.file.fd, p_str, str_size); + break; + } + + /* return TRUE if stream is OK */ + return(p_stream->status == STRM_SUCCESS); +} + +/******************************************************************************* +** +** Function bta_ma_stream_buf +** +** Description Stream a buffer into the buffer. +** +** Parameters p_stream - pointer to stream information. +** len - length of buffer +** p_buf - pointer to buffer to stream. +** +** Returns TRUE if the buffer was large enough to hold the data. +** +*******************************************************************************/ +extern BOOLEAN bta_ma_stream_buf(tBTA_MA_STREAM * p_stream, + UINT16 len, + UINT8 * p_buf) +{ + UINT16 buf_size; + UINT16 size = 0; + + /* ensure stream and buffer pointer are not NULL */ + if ( !p_buf || !p_stream ) + return(FALSE); + + switch ( p_stream->type ) + { + case STRM_TYPE_MEMORY: + /* ensure buffer is not full */ + if ( p_stream->status == STRM_SUCCESS ) + { + /* get amount of size left in buffer */ + buf_size = p_stream->u.mem.size - bta_ma_stream_used_size(p_stream); + + /* calculate the size to copy (the minimum of string and buffer size */ + if ( len > buf_size ) + { + size = buf_size; + p_stream->status = STRM_ERROR_OVERFLOW; + } + else + size = len; + + /* copy the data and move the pointer */ + memcpy(p_stream->u.mem.p_next, p_buf, len); + p_stream->u.mem.p_next += size; + } + break; + case STRM_TYPE_FILE: + /* write string */ + bta_ma_co_write(p_stream->u.file.fd, p_buf, len); + break; + } + + /* return TRUE if stream is OK */ + return(p_stream->status == STRM_SUCCESS); +} + + +/******************************************************************************* +** +** Function bta_ma_stream_boolean_yes_no +** +** Description Stream a yes/no string into the buffer. +** +** Parameters p_stream - pointer to stream information. +** val - a boolean value to indicate yes or no +** +** Returns TRUE if the yes/no string was successfully added into +** the stream. +** +*******************************************************************************/ +BOOLEAN bta_ma_stream_boolean_yes_no(tBTA_MA_STREAM * p_stream, BOOLEAN val) +{ + return bta_ma_stream_str(p_stream, + val == FALSE ? BTA_MSE_BOOLEAN_NO : BTA_MSE_BOOLEAN_YES); +} + +/******************************************************************************* +** +** Function bta_ma_stream_value +** +** Description Stream an UINT32 value string into the buffer. +** +** Parameters p_stream - pointer to stream information. +** val - a UINT32 value +** +** Returns TRUE if the buffer was large enough to hold the data. +** +*******************************************************************************/ +BOOLEAN bta_ma_stream_value(tBTA_MA_STREAM * p_stream, UINT32 val) +{ + char temp[50]; + + sprintf(temp, "%lu", val); + return bta_ma_stream_str(p_stream, temp); +} + +/******************************************************************************* +** +** Function bta_ma_stream_handle +** +** Description Stream a message handle into the buffer. +** +** Parameters p_stream - pointer to stream information. +** handle - handle to be put in the buffer. +** +** Returns TRUE if the buffer was large enough to hold the data. +** +*******************************************************************************/ + +BOOLEAN bta_ma_stream_handle(tBTA_MA_STREAM * p_stream, tBTA_MA_MSG_HANDLE handle) +{ + char temp[5]; + int x; + BOOLEAN value_yet = FALSE; + + /* ensure buffer is not full */ + if ( p_stream->status == STRM_SUCCESS ) + { + for ( x=0; x < BTA_MA_HANDLE_SIZE; x++ ) + { + /* Skip any leading 0's */ + if ( (! value_yet) && (handle[x] == 0) ) + continue; + + value_yet = TRUE; + + sprintf(temp, "%02x", handle[x]); + + if ( bta_ma_stream_str(p_stream, temp) == FALSE ) + return(FALSE); + } + } + + /* return TRUE if stream is OK */ + return(p_stream->status == STRM_SUCCESS); +} + + +/******************************************************************************* +** +** Function bta_ma_stream_used_size +** +** Description Returns the used byte count. +** +** Parameters p_stream - pointer to stream information. +** +** Returns Number of bytes used in the buffer. +** +*******************************************************************************/ + +UINT16 bta_ma_stream_used_size(tBTA_MA_STREAM * p_stream) +{ + return(p_stream->u.mem.p_next - p_stream->u.mem.p_buffer); +} + +/******************************************************************************* +** +** Function bta_ma_stream_ok +** +** Description Determines if the stream is ok. +** +** Parameters p_stream - pointer to stream information. +** +** Returns TRUE if stream status is OK. +** +*******************************************************************************/ + +BOOLEAN bta_ma_stream_ok(tBTA_MA_STREAM * p_stream) +{ + return(p_stream && p_stream->status == STRM_SUCCESS); +} + +/******************************************************************************* +** +** Function bta_ma_convert_hex_str_to_64bit_handle +** +** Description Convert a hex string to a 64 bit message handle in Big Endian +** format +** +** Returns void +** +*******************************************************************************/ +void bta_ma_convert_hex_str_to_64bit_handle(char *p_hex_str, tBTA_MA_MSG_HANDLE handle) +{ + UINT32 ul1, ul2; + UINT8 *p; + char tmp[BTA_MA_32BIT_HEX_STR_SIZE]; + UINT8 str_len; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("bta_mse_convert_hex_str_to_64bit_handle"); +#endif + + str_len = strlen(p_hex_str); + memset(handle,0,sizeof(tBTA_MA_MSG_HANDLE)); + + if (str_len >= 8) + { + /* most significant 4 bytes */ + memcpy(tmp,p_hex_str,(str_len-8)); + tmp[str_len-8]='\0'; + ul1 = strtoul(tmp,0,16); + p=handle; + UINT32_TO_BE_STREAM(p, ul1); + + /* least significant 4 bytes */ + memcpy(tmp,&(p_hex_str[str_len-8]),8); + tmp[8]='\0'; + ul2 = strtoul(tmp,0,16); + p=&handle[4]; + UINT32_TO_BE_STREAM(p, ul2); + } + else + { + /* least significant 4 bytes */ + ul1 = strtoul(p_hex_str,0,16); + p=&handle[4]; + UINT32_TO_BE_STREAM(p, ul1); + } +} + +/******************************************************************************* +** +** Function bta_ma_get_char +** +** Description Gets one character from the stream. +** +** Parameters p_stream - pointer to stream information. +** p_char - pointer to where to receive the character. +** +** Returns TRUE if character was read OK. +** +*******************************************************************************/ +BOOLEAN bta_ma_get_char(tBTA_MA_STREAM * p_stream, char * p_char) +{ + BOOLEAN bStatus = FALSE; + + if ( p_char ) + { + *p_char = 0; + + if ( p_stream ) + { + switch ( p_stream->type ) + { + case STRM_TYPE_MEMORY: + if ( (p_stream->u.mem.p_next-p_stream->u.mem.p_buffer) < p_stream->u.mem.size ) + { + *p_char = *p_stream->u.mem.p_next; + p_stream->u.mem.p_next++; + + bStatus = TRUE; + } + break; + case STRM_TYPE_FILE: + /* read character */ + bStatus = bta_ma_co_read(p_stream->u.file.fd, (void *) p_char, 1) == 1; + break; + } + } + } + + return( bStatus ); +} + + +/******************************************************************************* +** +** Function bta_ma_get_tag +** +** Description Parses a tag from the stream. Basically this returns any text +** before a ':' character, ignoring leading whitespace. +** +** Parameters p_stream - Input stream. +** psz - buffer to receive the tag +** max_size - size of the receiving buffer (including space +** for the NULL character. +** +** Returns Size of tag, or 0 if there was an error. +** +*******************************************************************************/ +UINT16 bta_ma_get_tag(tBTA_MA_STREAM * p_stream, char * psz, UINT16 max_size) +{ + char c; + UINT16 count = 0; + + /* handle bad arguments */ + if ( p_stream && psz && (max_size > 0) ) + { + /* reserve last byte for NULL terminator */ + max_size--; + + while ( bta_ma_get_char(p_stream, &c) + && (c != ':') + && (count < max_size) ) + { + /* ignore leading whitespace */ + if ( !count && ((c == ' ') || (c == '\t')) ) + continue; + + /* if we hit a CR, return 0 to indicate an error */ + if ( c == '\r' ) + return( 0 ); + + psz[count++] = c; + } + + /* Either we hit a problem reading from the stream + ** or the buffer was not large enough + */ + if ( c != ':' ) + return( 0 ); + + /* terminate string */ + psz[count] = '\0'; + } + + return( count ); +} + +/******************************************************************************* +** +** Function bta_ma_get_value +** +** Description Parses a value from the stream. Basically this any text +** up to (but not including) the CR LF sequence. +** +** Parameters p_stream - Input stream. +** psz - buffer to receive the value +** max_size - size of the receiving buffer (including space +** for the NULL character. +** +** Returns Size of value, or 0 if there was an error. +** +*******************************************************************************/ +UINT16 bta_ma_get_value(tBTA_MA_STREAM * p_stream, char * psz, UINT16 max_size) +{ + char c; + UINT16 count = 0; + + /* handle bad arguments */ + if ( p_stream && psz && (max_size > 0) ) + { + /* reserve last byte for NULL terminator */ + max_size--; + + while ( bta_ma_get_char(p_stream, &c) + && (c != '\r') + && (count < max_size) ) + { + psz[count++] = c; + } + + /* Either we hit a problem reading from the stream + ** or the buffer was not large enough + */ + if ( c != '\r' ) + return( 0 ); + + /* burn the next character which must be LF */ + if ( ! bta_ma_get_char(p_stream, &c) ) + return( 0 ); + + /* terminate string */ + psz[count] = '\0'; + } + + return( count ); +} + +/******************************************************************************* +** +** Function bta_ma_get_param +** +** Description Parses the parameter from the source string. +** +** Parameters p_src - source paramter string. +** psz - buffer to receive the value +** +** Returns Size of param, or 0 if there was an error. +** +*******************************************************************************/ +UINT16 bta_ma_get_param(char *p_src, char *psz ) +{ + char c; + UINT16 count = 0; + BOOLEAN first_semicolon_found=FALSE; + + /* handle bad arguments */ + if ( p_src && psz ) + { + while ( (c = *p_src++) ) + { + + /* throw away the first ';' */ + if ( !count && (c==';') ) + { + first_semicolon_found = TRUE; + continue; + } + + /* first char should be ';' otherwise return 0 */ + if(!count && !first_semicolon_found && (c!=';')) + return (0); + + /* if we hit a CR, return 0 to indicate an error */ + if ( c == '\r' ) + return( 0 ); + + psz[count++] = c; + } + + if ( !count ) + return( 0 ); + + /* terminate string */ + psz[count] = '\0'; + } + + return( count ); +} + + + + +/******************************************************************************* +** +** Function bta_ma_parse_vcard +** +** Description Parses a vCard from the stream into a generic tBTA_MA_BMSG_VCARD +** structure. +** +** Parameters p_vcard - pointer to generic vCard structure. +** p_stream - Input stream. +** +** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not. +** +*******************************************************************************/ +tBTA_MA_STATUS bta_ma_parse_vcard(tBTA_MA_BMSG_VCARD * p_vcard, + tBTA_MA_STREAM * p_stream) +{ + char sz[BTA_MA_MAX_SIZE]; + tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL; + tBTA_MA_VCARD_VERSION version; + char * psztoken_tel = "TEL"; +// btla-specific ++ + char * psztoken_name = "N;"; +// btla-specific -- + char param[BTA_MA_MAX_SIZE]; + char *p_src; + UINT16 len; + + + while ( bta_ma_get_tag(p_stream, sz, BTA_MA_MAX_SIZE) ) + { + if ( strcmp(sz, "VERSION") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + if ( strcmp(sz, "3.0") == 0 ) + version = BTA_MA_VCARD_VERSION_30; + else if ( strcmp(sz, "2.1") == 0 ) + version = BTA_MA_VCARD_VERSION_21; + else + { + APPL_TRACE_ERROR1("bta_ma_parse_vcard - Invalid vcard version: '%s'", sz); + break; + } + + BTA_MaBmsgSetVcardVersion(p_vcard, version); + } + else if ( strcmp(sz, "N") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + BTA_MaBmsgAddVcardProp(p_vcard, BTA_MA_VCARD_PROP_N, sz, NULL); +// btla-specific ++ + } + else if ( strstr(sz, psztoken_name) == sz ) + { + p_src = sz + strlen(psztoken_name) - 1; // move to (first) semicolon, not past it + len = strlen(p_src); + if ( (len < BTA_MA_MAX_SIZE) && bta_ma_get_param(p_src, param)) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + BTA_MaBmsgAddVcardProp(p_vcard, BTA_MA_VCARD_PROP_N, sz, param); + } +// btla-specific -- + } + else if ( strcmp(sz, "FN") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + BTA_MaBmsgAddVcardProp(p_vcard, BTA_MA_VCARD_PROP_FN, sz, NULL); + } + else if ( strcmp(sz, psztoken_tel ) == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + BTA_MaBmsgAddVcardProp(p_vcard, BTA_MA_VCARD_PROP_TEL, sz, NULL); + } + else if ( strstr(sz, psztoken_tel) == sz ) + { + p_src = sz + strlen(psztoken_tel); + len = strlen(p_src); + if ( (len < BTA_MA_MAX_SIZE) && bta_ma_get_param(p_src, param)) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + BTA_MaBmsgAddVcardProp(p_vcard, BTA_MA_VCARD_PROP_TEL, sz, param); + } + } + else if ( strcmp(sz, "EMAIL") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + BTA_MaBmsgAddVcardProp(p_vcard, BTA_MA_VCARD_PROP_EMAIL, sz, NULL); + } + else if ( strcmp(sz, "END") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + status = BTA_MA_STATUS_OK; + break; + } + else + { + APPL_TRACE_ERROR1("bta_ma_parse_vcard - Invalid tag: '%s'", sz); + } + } + + return( status ); +} + +/******************************************************************************* +** +** Function bta_ma_parse_content +** +** Description Parses a <bmessage-body-content> from the stream into a +** generic tBTA_MA_BMSG_CONTENT structure. This will parse text until +** we see "END:MSG" at the start of a line. +** +** Parameters p_content - pointer to generic content structure. +** p_stream - Input stream. +** +** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not. +** +*******************************************************************************/ +tBTA_MA_STATUS bta_ma_parse_content(tBTA_MA_BMSG_CONTENT * p_content, + tBTA_MA_STREAM * p_stream) +{ +/* This constant defines the size of the work buffer used for parsing. +** It MUST be larger than the 'END:MSG<CRLF>" string size. The larger +** the buffer the more efficient this parser will be. +*/ +#define BTA_MA_PARSE_BUF_SIZE BTA_MA_MAX_SIZE + +/* These constants define the four states the parser can be in. +*/ +#define STATE_WS (0) /* checking for leading whitespace */ +#define STATE_END (1) /* checking for END:MSG */ +#define STATE_CR (2) /* checking for CRLF */ +#define STATE_TEXT (3) /* copying text */ + + static const char * END_MSG = "END:MSG\r\n"; + + char sz[BTA_MA_PARSE_BUF_SIZE+1]; + char c; + int state = STATE_WS; /* start in the 'whitespace' state */ + int idx_commit = 0; + int idx_trial = 0; + int idx_end = 0; + int x; + + /* NOTES - There are 3 primary indices used during parsing: + ** + ** 'idx_commit' these are characters that are commited to being + ** in the message text. We need to be able to save characters + ** (such as <CR><LF>, "END..", etc.) but not actually 'commit' them. + ** + ** 'idx_trial' these are characters that we are saving on a trial + ** basis until we know what to do with them. For example, if + ** we get a sequence "<CR>+<LF>+E+N", we don't want to commit + ** them until we know it is not "END:MSG<CR><LF>". + ** + ** 'idx_end' is used to index through the "END:MSG<CR><LF> string. + */ + + /* Handle bad arguments */ + if ( p_stream && p_content ) + { + /* Get one character from the stream */ + while ( bta_ma_get_char(p_stream, &c) ) + { + switch (state) + { + case STATE_WS: + /* totally ignore leading whitespace */ + if ( (c == ' ') || (c == '\t') ) + continue; + + /* Otherwise intentionaly fall through after resetting the + ** 'end' index so we start comparing from the beginning. + */ + idx_end = 0; + + case STATE_END: + /* Is the character in the "END:MSG<CR><LF> sequence? */ + if ( c == END_MSG[idx_end] ) + { + /* Yes. Did we get to the end of "END:MSG<cr><lf>"? */ + if ( ! END_MSG[++idx_end] ) + { + /* Yes. Commit any characters and get out. */ + if ( idx_commit ) + { + sz[idx_commit] = '\0'; + BTA_MaBmsgAddMsgContent(p_content, sz); + } + + return( BTA_MA_STATUS_OK ); + } + + state = STATE_END; + break; + } + /* If we fell through from the whitespace state + ** then we should commit all chars at this point. + ** It handles the case where we get consecutive CRLF. + */ + if ( state == STATE_WS ) + idx_commit = idx_trial; + + /* And intentionally fall through */ + + case STATE_CR: + /* We got <CR>, is this <LF>? */ + if ( c == '\n' ) + { + /* Now look for any whitespace */ + state = STATE_WS; + break; + } + + /* otherwise intentionally fall through */ + + case STATE_TEXT: + /* is a CR? */ + if ( c == '\r' ) + state = STATE_CR; /* Look for <LF> */ + else + state = STATE_TEXT; /* Copy the text */ + break; + } + + /* All (non-whitespace) characters are copied to + ** the buffer as 'trial' characters possibly + ** committed later. + */ + sz[idx_trial++] = c; + + /* If we are in the text copy state, then + ** commit all characters to this point. + */ + if ( state == STATE_TEXT ) + idx_commit = idx_trial; + + /* The buffer is full. Commit the good characters + ** to the message content, and rearrange the rest + ** of the text to make room for more. + */ + if ( idx_trial == BTA_MA_PARSE_BUF_SIZE ) + { + /* Do we have characters to commit? + ** If we don't we are in trouble. + */ + if ( idx_commit ) + { + /* Save the last character so we can put a NULL there. */ + c = sz[idx_commit]; + sz[idx_commit] = '\0'; + BTA_MaBmsgAddMsgContent(p_content, sz); + + /* Do we need to rearrange uncommited text? */ + if ( idx_commit != idx_trial ) + { + /* Restore character */ + sz[idx_commit] = c; + + /* Copy the 'trial' characters to the beginning of buffer */ + idx_trial -= idx_commit; + for ( x=0; x < idx_trial; x++) + sz[x] = sz[x+idx_commit]; + idx_commit = 0; + } + else + { + idx_trial = idx_commit = 0; + } + } + else + { + /* ERROR - no space to shuffle things around */ + APPL_TRACE_ERROR0("bta_ma_parse_content - work buffer too small"); + break; + } + } + } + } + + return( BTA_MA_STATUS_FAIL ); +} + +/******************************************************************************* +** +** Function bta_ma_parse_body +** +** Description Parses a <bmessage-content> (BBODY) from the stream into a +** generic tBTA_MA_BMSG_BODY structure. This will parse text until +** we see "END:BODY" at the start of a line. +** +** Parameters p_body - pointer to generic content body structure. +** p_stream - Input stream. +** +** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not. +** +*******************************************************************************/ +tBTA_MA_STATUS bta_ma_parse_body(tBTA_MA_BMSG_BODY * p_body, + tBTA_MA_STREAM * p_stream) +{ + char sz[BTA_MA_MAX_SIZE]; + tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL; + tBTA_MA_BMSG_CONTENT *p_content = NULL; + tBTA_MA_BMSG_ENCODING encoding; + tBTA_MA_BMSG_LANGUAGE language; + tBTA_MA_CHARSET charset; + + while ( bta_ma_get_tag(p_stream, sz, BTA_MA_MAX_SIZE) ) + { + if ( strcmp(sz, "PARTID") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + BTA_MaBmsgSetBodyPartid(p_body, (UINT16) atoi(sz)); + } + else if ( strcmp(sz, "ENCODING") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + if ( bta_ma_str_to_encoding(sz, &encoding) ) + BTA_MaBmsgSetBodyEncoding(p_body, encoding); + else + APPL_TRACE_ERROR1("bta_ma_parse_body - Invalid ENCODING: '%s'", sz); + } + else if ( strcmp(sz, "CHARSET") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + if ( bta_ma_str_to_charset(sz, &charset)) + BTA_MaBmsgSetBodyCharset(p_body, charset); + else + APPL_TRACE_ERROR1("bta_ma_parse_body - invalid CHARSET: '%s'", sz); + } + else if ( strcmp(sz, "LANGUAGE") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + if ( bta_ma_str_to_language(sz, &language) ) + BTA_MaBmsgSetBodyLanguage(p_body, language); + else + APPL_TRACE_ERROR1("bta_ma_parse_body - Invalid LANGUAGE: '%s'", sz); + } + else if ( strcmp(sz, "LENGTH") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + /* we don't really care about the length */ + } + else if ( strcmp(sz, "BEGIN") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + + if ( strcmp(sz, "MSG") == 0 ) + { + p_content = BTA_MaBmsgAddContentToBody(p_body); + bta_ma_parse_content(p_content, p_stream); + } + else + { + APPL_TRACE_ERROR1("bta_ma_parse_body - Invalid BEGIN: '%s'", sz); + } + } + else if ( strcmp(sz, "END") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + status = BTA_MA_STATUS_OK; + break; + } + else + { + APPL_TRACE_ERROR1("bta_ma_parse_body - Invalid tag: '%s'", sz); + } + } + + return( status ); +} + +/******************************************************************************* +** +** Function bta_ma_parse_envelope +** +** Description Parses a <bmessage-envelope> from the stream into a +** generic tBTA_MA_BMSG_ENVELOPE structure. This will parse text +** until we see "END:BENV" at the start of a line. +** +** Parameters p_envelope - pointer to generic envelope structure. +** p_stream - Input stream. +** +** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not. +** +*******************************************************************************/ +tBTA_MA_STATUS bta_ma_parse_envelope(tBTA_MA_BMSG_ENVELOPE * p_envelope, + tBTA_MA_STREAM * p_stream) +{ + char sz[BTA_MA_MAX_SIZE]; + tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL; + tBTA_MA_BMSG_VCARD * p_vcard = NULL; + tBTA_MA_BMSG_ENVELOPE * p_new_envelope = NULL; + tBTA_MA_BMSG_BODY * p_body = NULL; + + while ( bta_ma_get_tag(p_stream, sz, BTA_MA_MAX_SIZE) ) + { + if ( strcmp(sz, "BEGIN") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + + if ( strcmp(sz, "VCARD") == 0 ) + { + p_vcard = BTA_MaBmsgAddRecipToEnv(p_envelope); + bta_ma_parse_vcard(p_vcard, p_stream); + } + else if ( strcmp(sz, "BENV") == 0 ) + { + p_new_envelope = BTA_MaBmsgAddEnvToEnv(p_envelope); + bta_ma_parse_envelope(p_new_envelope, p_stream); + } + else if ( strcmp(sz, "BBODY") == 0 ) + { + p_body = BTA_MaBmsgAddBodyToEnv(p_envelope); + bta_ma_parse_body(p_body, p_stream); + } + else + { + APPL_TRACE_ERROR1("bta_ma_parse_envelope - Invalid BEGIN: '%s'", sz); + } + + } + else if ( strcmp(sz, "END") == 0 ) + { + bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); + status = BTA_MA_STATUS_OK; + break; + } + else + { + APPL_TRACE_ERROR1("bta_ma_parse_envelope - Invalid tag: '%s'", sz); + } + } + + return( status ); +} + +/******************************************************************************* +** +** Function bta_ma_stream_vcards +** +** Description Builds vCards into a stream. +** +** Parameters p_stream - Output stream. +** p_vcard - pointer to single vCard that may be linked to +** additional vCards. +** +** Returns void +** +*******************************************************************************/ +void bta_ma_stream_vcards(tBTA_MA_STREAM * p_stream, + tBTA_MA_BMSG_VCARD * p_vcard) +{ + int x; + + /* vCards are formatted one after another */ + while ( p_stream && p_vcard ) + { + bta_ma_stream_str(p_stream, "\r\nBEGIN:VCARD"); + + /* version */ + bta_ma_stream_str(p_stream, "\r\nVERSION:"); + bta_ma_stream_str(p_stream, + p_vcard->version == BTA_MA_VCARD_VERSION_21 ? "2.1" : "3.0"); + + /* vcard properties */ + for (x=0; x < BTA_MA_VCARD_PROP_MAX; x++) + bta_ma_stream_vcard_prop(p_stream, p_vcard,(tBTA_MA_VCARD_PROP) x); + + bta_ma_stream_str(p_stream, "\r\nEND:VCARD"); + + /* Get the next vCard and repeat */ + p_vcard = BTA_MaBmsgGetNextVcard(p_vcard); + } +} + +/******************************************************************************* +** +** Function bta_ma_stream_vcard_prop +** +** Description Builds a property and values into a stream. This will +** build all of the property/values for one property (i.e. +** can be multiple EMAIL propeties set). It will only +** format the property if it has a value (except the N/name +** if a 2.1 vCard and FN/fullname property of a 3.0 vCard +** will always be output). +** +** Parameters p_stream - Output stream. +** p_vcard - pointer to vCard. +** prop - property. +** +** Returns void +** +*******************************************************************************/ +void bta_ma_stream_vcard_prop(tBTA_MA_STREAM * p_stream, + tBTA_MA_BMSG_VCARD * p_vcard, + tBTA_MA_VCARD_PROP prop) +{ + tBTA_MA_VCARD_PROPERTY * p_prop; + tBTA_MA_VCARD_VERSION version; + char * p_param; + char * p_value; + + if ( p_vcard && prop < BTA_MA_VCARD_PROP_MAX ) + { + p_prop = BTA_MaBmsgGetVcardProp(p_vcard, prop); + + do + { + p_param = BTA_MaBmsgGetVcardPropParam(p_prop); + p_value = BTA_MaBmsgGetVcardPropValue(p_prop); + version = BTA_MaBmsgGetVcardVersion(p_vcard); + + if ( (p_value && strlen(p_value)) + || ((version == BTA_MA_VCARD_VERSION_21) && (prop == BTA_MA_VCARD_PROP_N)) + || ((version == BTA_MA_VCARD_VERSION_30) && (prop <= BTA_MA_VCARD_PROP_FN)) ) + { + /* property name */ + bta_ma_stream_str(p_stream, "\r\n"); + bta_ma_stream_str(p_stream, vcard_prop_name[prop]); + + + /* property parameter */ + if ( p_param ) + { + bta_ma_stream_str(p_stream, ";"); + bta_ma_stream_str(p_stream, p_param); + } + + /* property value */ + bta_ma_stream_str(p_stream, ":"); + bta_ma_stream_str(p_stream, p_value); + } + + /* There may be multiple instances of a property (e.g. 2 TEL numbers */ + p_prop = BTA_MaBmsgGetNextVcardProp(p_prop); + + } while ( p_prop ); + } +} + +/******************************************************************************* +** +** Function bta_ma_stream_envelopes +** +** Description Builds a envelope <bmessage-envelope> (or series of +** envelopes) into a stream. +** +** Parameters p_stream - Output stream. +** p_envelope - pointer to envelope structure. +** +** Returns void +** +*******************************************************************************/ +void bta_ma_stream_envelopes(tBTA_MA_STREAM * p_stream, + tBTA_MA_BMSG_ENVELOPE * p_envelope) +{ + tBTA_MA_BMSG_BODY * p_body; + + if ( p_stream && p_envelope ) + { + bta_ma_stream_str(p_stream, "\r\nBEGIN:BENV"); + + /* Recipients */ + bta_ma_stream_vcards(p_stream, BTA_MaBmsgGetRecipFromEnv(p_envelope)); + + /* It will either be another (nested) envelope or the body */ + p_body = BTA_MaBmsgGetBodyFromEnv(p_envelope); + + if ( p_body ) + bta_ma_stream_body(p_stream, p_body); + else + bta_ma_stream_envelopes(p_stream, BTA_MaBmsgGetNextEnv(p_envelope)); + + bta_ma_stream_str(p_stream, "\r\nEND:BENV"); + } +} + +/******************************************************************************* +** +** Function bta_ma_stream_body +** +** Description Builds a bMessage content <bmessage-content> into a stream. +** +** Parameters p_stream - Output stream. +** p_body - pointer to bBody structure. +** +** Returns void +** +*******************************************************************************/ +void bta_ma_stream_body(tBTA_MA_STREAM * p_stream, tBTA_MA_BMSG_BODY * p_body) +{ + UINT16 part_id = 0; + tBTA_MA_BMSG_LANGUAGE language; + tBTA_MA_CHARSET charset; + + if ( p_stream && p_body ) + { + bta_ma_stream_str(p_stream, "\r\nBEGIN:BBODY"); + + /* Part ID (optional) */ + part_id = BTA_MaBmsgGetBodyPartid(p_body); + if ( part_id != 0 ) + { + bta_ma_stream_str(p_stream, "\r\nPARTID:"); + bta_ma_stream_value(p_stream, part_id); + } + + /* Character set */ + charset = BTA_MaBmsgGetBodyCharset(p_body); + switch ( charset) + { + case BTA_MA_CHARSET_UTF_8: + bta_ma_stream_str(p_stream, "\r\nCHARSET:UTF-8"); + break; + case BTA_MA_CHARSET_NATIVE: + bta_ma_stream_str(p_stream, "\r\nCHARSET:NATIVE"); + /* Encoding */ + bta_ma_stream_str(p_stream, "\r\nENCODING:"); + bta_ma_stream_str(p_stream, bmsg_body_encoding[BTA_MaBmsgGetBodyEncoding(p_body)]); + break; + default: + break; + } + + /* Language */ + language = BTA_MaBmsgGetBodyLanguage(p_body); + if ( language != BTA_MA_BMSG_LANG_UNSPECIFIED ) + { + bta_ma_stream_str(p_stream, "\r\nLANGUAGE:"); + bta_ma_stream_str(p_stream, bmsg_body_language[language]); + } + + /* Body content length */ + bta_ma_stream_str(p_stream, "\r\nLENGTH:"); + bta_ma_stream_value(p_stream, bta_ma_get_body_length(p_body)); + + /* Content */ + bta_ma_stream_body_content(p_stream, BTA_MaBmsgGetContentFromBody(p_body)); + + bta_ma_stream_str(p_stream, "\r\nEND:BBODY"); + } +} + +/******************************************************************************* +** +** Function bta_ma_stream_body_content +** +** Description Builds a body content <bmessage-body-content> into a stream. +** +** Parameters p_stream - Output stream. +** p_content - pointer to content structure. +** +** Returns void +** +*******************************************************************************/ +void bta_ma_stream_body_content(tBTA_MA_STREAM * p_stream, + tBTA_MA_BMSG_CONTENT * p_content) +{ + char * p_text; + + APPL_TRACE_EVENT0("bta_ma_stream_body_content"); + while ( p_stream && p_content ) + { + bta_ma_stream_str(p_stream, "\r\nBEGIN:MSG"); + + p_text = BTA_MaBmsgGetMsgContent(p_content); + if ( p_text ) + { + bta_ma_stream_str(p_stream, "\r\n"); + + while ( p_text ) + { + bta_ma_stream_str(p_stream, p_text); + p_text = BTA_MaBmsgGetNextMsgContent(p_content); + } + } + + bta_ma_stream_str(p_stream, "\r\nEND:MSG"); + + p_content = BTA_MaBmsgGetNextContent(p_content); + } +} + +/******************************************************************************* +** +** Function bta_ma_str_to_charset +** +** Description Returns the charset enumeration (tBTA_MA_CHARSET) that +** corresponds to the provided string. +** +** Parameters psz - Input string. +** p_charset - pointer to the charset value to be received. +** +** Returns TRUE if there is a match, otherwise FALSE. +** +*******************************************************************************/ +BOOLEAN bta_ma_str_to_charset(char * psz, tBTA_MA_CHARSET * p_charset) +{ + + tBTA_MA_CHARSET e; + + if ( psz && p_charset ) + { + for (e= BTA_MA_CHARSET_NATIVE; e < num_bmsg_body_charset; e++) + { + if ( strcmp(psz, bmsg_body_charset[e]) == 0 ) + { + *p_charset = e; + return( TRUE ); + } + } + } + + return( FALSE ); +} + + +/******************************************************************************* +** +** Function bta_ma_str_to_encoding +** +** Description Returns the encoding enumeration (tBTA_MA_BMSG_ENCODING) that +** corresponds to the provided string. +** +** Parameters psz - Input string. +** p_encoding - pointer to the encoding value to be received. +** +** Returns TRUE if there is a match, otherwise FALSE. +** +*******************************************************************************/ +BOOLEAN bta_ma_str_to_encoding(char * psz, tBTA_MA_BMSG_ENCODING * p_encoding) +{ + tBTA_MA_BMSG_ENCODING e; + + if ( psz && p_encoding ) + { + for (e= BTA_MA_BMSG_ENC_8BIT; e < num_bmsg_body_encoding; e++) + { + if ( strcmp(psz, bmsg_body_encoding[e]) == 0 ) + { + *p_encoding = e; + return( TRUE ); + } + } + } + + return( FALSE ); +} + +/******************************************************************************* +** +** Function bta_ma_str_to_language +** +** Description Returns the language enumeration (tBTA_MA_BMSG_LANGUAGE) that +** corresponds to the provided string. +** +** Parameters psz - Input string. +** p_language - pointer to the language value to be received. +** +** Returns TRUE if there is a match, otherwise FALSE. +** +*******************************************************************************/ +BOOLEAN bta_ma_str_to_language(char * psz, tBTA_MA_BMSG_LANGUAGE * p_language) +{ + tBTA_MA_BMSG_LANGUAGE l; + + if ( psz && p_language ) + { + for (l=BTA_MA_BMSG_LANG_UNSPECIFIED; l < num_bmsg_body_language; l++) + { + if ( strcmp(psz, bmsg_body_language[l]) == 0 ) + { + *p_language = l; + return( TRUE ); + } + } + } + + return( FALSE ); +} + +/******************************************************************************* +** +** Function bta_ma_str_to_msg_typ +** +** Description Returns the message type enumeration (tBTA_MA_MSG_TYPE) +** that corresponds to the provided string. +** +** Parameters psz - Input string. +** p_msg_type - pointer to the message type value to be +** received. +** +** Returns TRUE if there is a match, otherwise FALSE. +** +*******************************************************************************/ +BOOLEAN bta_ma_str_to_msg_typ(char * psz, tBTA_MA_MSG_TYPE * p_msg_type) +{ + if ( psz && p_msg_type ) + { + if ( strcmp(psz, "EMAIL") == 0 ) + *p_msg_type = BTA_MA_MSG_TYPE_EMAIL; + else if ( strcmp(psz, "SMS_GSM") == 0 ) + *p_msg_type = BTA_MA_MSG_TYPE_SMS_GSM; + else if ( strcmp(psz, "SMS_CDMA") == 0 ) + *p_msg_type = BTA_MA_MSG_TYPE_SMS_CDMA; + else if ( strcmp(psz, "MMS") == 0 ) + *p_msg_type = BTA_MA_MSG_TYPE_MMS; + else + return FALSE; + } + + return( TRUE ); +} + +/******************************************************************************* +** +** Function bta_ma_get_body_length +** +** Description Returns the combined length in characters of the message +** content. +** +** Parameters p_body - pointer to bBody structure. +** +** Returns Length of the body message text. +** +*******************************************************************************/ +UINT32 bta_ma_get_body_length(tBTA_MA_BMSG_BODY * p_body) +{ + UINT32 length = 0, len=0; + tBTA_MA_BMSG_CONTENT * p_content; + char * p_text; + + APPL_TRACE_EVENT0("bta_ma_get_body_length"); + + p_content = BTA_MaBmsgGetContentFromBody(p_body); + + while ( p_content ) + { + p_text= BTA_MaBmsgGetMsgContent(p_content); + + while ( p_text ) + { + len = strlen(p_text); + length += (len + BTA_MA_BMSG_BODY_TAG_CTL_LENGTH); + + APPL_TRACE_EVENT3("total=%d len=%d text=%s",length, len, p_text); + + p_text = BTA_MaBmsgGetNextMsgContent(p_content); + } + + p_content = BTA_MaBmsgGetNextContent(p_content); + } + + APPL_TRACE_EVENT1("bta_ma_get_body_length len=%d", length); + return( length ); + + +} + +/******************************************************************************* +** +** Function bta_ma_bmsg_free_vcards +** +** Description Free buffers used by vVards +** +** Parameters p_vcard - Pointer to the first vCard in the linked vCards +** +** Returns None +** +*******************************************************************************/ + +void bta_ma_bmsg_free_vcards(tBTA_MA_BMSG_VCARD * p_vcard) +{ + int x; + + if ( p_vcard ) + { + /* recursively free any linked vCards */ + bta_ma_bmsg_free_vcards((tBTA_MA_BMSG_VCARD *)p_vcard->p_next); + + /* Free properties */ + for (x=0; x < BTA_MA_VCARD_PROP_MAX; x++) + bta_ma_bmsg_free_vcard_prop(p_vcard->p_prop[x]); + + /* free vcard structure itself */ + bta_ma_bmsg_free(p_vcard); + } +} +/******************************************************************************* +** +** Function bta_ma_bmsg_free_envelope +** +** Description Free buffers used by envelopes +** +** Parameters p_envelope - Pointer to the first envelope in the linked envelopes +** +** Returns None +** +*******************************************************************************/ +void bta_ma_bmsg_free_envelope(tBTA_MA_BMSG_ENVELOPE * p_envelope) +{ + if ( p_envelope ) + { + /* recursively free any linked envelopes */ + bta_ma_bmsg_free_envelope((tBTA_MA_BMSG_ENVELOPE *)p_envelope->p_next); + + /* free the body */ + bta_ma_bmsg_free_body(p_envelope->p_body); + + /* free recipients */ + bta_ma_bmsg_free_vcards(p_envelope->p_recip); + + /* free envelope structure itself */ + bta_ma_bmsg_free(p_envelope); + } +} +/******************************************************************************* +** +** Function bta_ma_bmsg_free_body +** +** Description Free buffers used by a message body +** +** Parameters p_body - Pointer to a message body +** +** Returns None +** +*******************************************************************************/ +void bta_ma_bmsg_free_body(tBTA_MA_BMSG_BODY * p_body) +{ + if ( p_body ) + { + bta_ma_bmsg_free_content(p_body->p_content); + + /* free body structure itself */ + bta_ma_bmsg_free(p_body); + } +} +/******************************************************************************* +** +** Function bta_ma_bmsg_free_content +** +** Description Free buffers used by message contents +** +** Parameters p_envelope - Pointer to the first message content in the +** linked message contents +** +** Returns None +** +*******************************************************************************/ +void bta_ma_bmsg_free_content(tBTA_MA_BMSG_CONTENT * p_content) +{ + if ( p_content ) + { + /* recursively free any linked content */ + bta_ma_bmsg_free_content((tBTA_MA_BMSG_CONTENT *)p_content->p_next); + + /* free all of the message text */ + bta_ma_bmsg_free_message_text(p_content->p_message); + + /* free content structure itself */ + bta_ma_bmsg_free(p_content); + } +} +/******************************************************************************* +** +** Function bta_ma_bmsg_free_message_text +** +** Description Free text string buffers used by a message +** +** Parameters p_envelope - Pointer to a message +** +** Returns None +** +*******************************************************************************/ +void bta_ma_bmsg_free_message_text(tBTA_MA_BMSG_MESSAGE * p_message) +{ + tBTA_MA_BMSG_MESSAGE * p_temp; + + while ( p_message ) + { + p_temp = (tBTA_MA_BMSG_MESSAGE *)p_message->p_next; + + /* free message string */ + bta_ma_bmsg_free(p_message->p_text); + + /* free message text structure */ + bta_ma_bmsg_free(p_message); + + /* now point to the next one */ + p_message = p_temp; + } +} +/******************************************************************************* +** +** Function bta_ma_bmsg_free_vcard_prop +** +** Description Free buffers used by a vCard property +** +** Parameters p_envelope - Pointer to a vCard property +** +** Returns None +** +*******************************************************************************/ +void bta_ma_bmsg_free_vcard_prop(tBTA_MA_VCARD_PROPERTY * p_prop) +{ + if ( p_prop ) + { + /* free the value and the parameter */ + if ( p_prop->p_value ) + bta_ma_bmsg_free(p_prop->p_value); + + if ( p_prop->p_param ) + bta_ma_bmsg_free(p_prop->p_param); + + /* recursively free any linked content */ + if ( p_prop->p_next ) + bta_ma_bmsg_free_vcard_prop((tBTA_MA_VCARD_PROPERTY *)p_prop->p_next); + + /* free property structure itself */ + bta_ma_bmsg_free(p_prop); + } +} + +/******************************************************************************* +** +** Function bta_ma_bmsg_alloc +** +** Description Allocate buffer for the specified size +** +** Parameters cb - request buffer size +** +** Returns None +** +*******************************************************************************/ + +void * bta_ma_bmsg_alloc(size_t cb) +{ + void * p_buf; + + if ((p_buf = GKI_getbuf((UINT16) cb)) == NULL ) + { + APPL_TRACE_ERROR1("Unable to allocate buffer for size=%", (UINT16) cb); + } + return(p_buf); +} +/******************************************************************************* +** +** Function bta_ma_bmsg_free +** +** Description Free buffer +** +** Parameters p - pointer to a buffer +** +** Returns None +** +*******************************************************************************/ +void bta_ma_bmsg_free(void * p) +{ + if ( p ) + GKI_freebuf(p); +} + + +#endif /* BTA_MSE_INCLUDED */ diff --git a/bta/ma/bta_ma_util.h b/bta/ma/bta_ma_util.h new file mode 100644 index 0000000..9040201 --- /dev/null +++ b/bta/ma/bta_ma_util.h @@ -0,0 +1,93 @@ +/***************************************************************************** +** +** Name: bta_ma_util.h +** +** Description: This is the interface file for the Message Access Profile +** (MAP) utility functions. +** +** Copyright (c) 2009, Broadcom Corp., All Rights Reserved. +** Broadcom Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ +#ifndef BTA_MA_UTIL_H +#define BTA_MA_UTIL_H + +#include "bta_ma_def.h" +#include "bta_mse_api.h" +#include "bta_mse_co.h" +#include "bta_ma_api.h" + + +#define BTA_MA_MAX_SIZE (100) + +/* Here are a set of property flags used to keep track +** of properties that are successfully parsed. We use +** this information to determine if all the *required* +** properties have been provided in the parsed object. +*/ +#define BTA_MA_PROP_VERSION 0x00000001 +#define BTA_MA_BMSG_BODY_TAG_CTL_LENGTH 22 /* see MAP Spec. Errata 3603 */ + /* BEGIN:MSG<CRTL>+<CRTL>+END:MSG<CRTL> */ +#ifdef __cplusplus +extern "C" +{ +#endif + + extern const char * bta_ma_evt_typ_to_string(tBTA_MSE_NOTIF_TYPE notif_type); + extern const char * bta_ma_msg_typ_to_string(tBTA_MA_MSG_TYPE msg_typ); + extern const char * bta_ma_rcv_status_to_string(tBTA_MSE_CO_RCV_STATUS rcv_status); + + extern BOOLEAN bta_ma_stream_str(tBTA_MA_STREAM * p_stream, + const char * p_str); + + extern BOOLEAN bta_ma_stream_buf(tBTA_MA_STREAM * p_stream, + UINT16 len, + UINT8 * p_buf); + + extern BOOLEAN bta_ma_stream_boolean_yes_no(tBTA_MA_STREAM * p_stream, BOOLEAN val); + + extern BOOLEAN bta_ma_stream_value(tBTA_MA_STREAM * p_stream, UINT32 val); + + extern BOOLEAN bta_ma_stream_handle(tBTA_MA_STREAM * p_stream, + tBTA_MA_MSG_HANDLE handle); + + extern UINT16 bta_ma_stream_used_size(tBTA_MA_STREAM * p_stream); + + extern BOOLEAN bta_ma_stream_ok(tBTA_MA_STREAM * p_stream); + + extern void bta_ma_convert_hex_str_to_64bit_handle(char *p_hex_str, tBTA_MA_MSG_HANDLE handle); + + extern BOOLEAN bta_ma_get_char(tBTA_MA_STREAM * p_stream, char * p_char); + extern BOOLEAN bta_ma_str_to_charset(char * psz, tBTA_MA_CHARSET * p_charset); + extern BOOLEAN bta_ma_str_to_encoding(char * psz, tBTA_MA_BMSG_ENCODING * p_encoding); + extern BOOLEAN bta_ma_str_to_language(char * psz, tBTA_MA_BMSG_LANGUAGE * p_language); + extern BOOLEAN bta_ma_str_to_msg_typ(char * psz, tBTA_MA_MSG_TYPE * p_msg_type); + + extern void bta_ma_stream_vcards(tBTA_MA_STREAM *, tBTA_MA_BMSG_VCARD *); + extern void bta_ma_stream_envelopes(tBTA_MA_STREAM * p_stream, tBTA_MA_BMSG_ENVELOPE * p_envelope); + extern void bta_ma_stream_body(tBTA_MA_STREAM * p_stream, tBTA_MA_BMSG_BODY * p_body); + extern void bta_ma_stream_body_content(tBTA_MA_STREAM * p_stream, tBTA_MA_BMSG_CONTENT * p_content); + extern void bta_ma_stream_vcard_prop(tBTA_MA_STREAM * p_stream, tBTA_MA_BMSG_VCARD * p_vcard, tBTA_MA_VCARD_PROP prop); + + extern UINT32 bta_ma_get_body_length(tBTA_MA_BMSG_BODY * p_body); + + extern UINT16 bta_ma_get_tag(tBTA_MA_STREAM * p_stream, char * psz, UINT16 max_size); + extern UINT16 bta_ma_get_value(tBTA_MA_STREAM * p_stream, char * psz, UINT16 max_size); + + extern tBTA_MA_STATUS bta_ma_parse_vcard(tBTA_MA_BMSG_VCARD * p_vcard, tBTA_MA_STREAM * p_stream); + extern tBTA_MA_STATUS bta_ma_parse_envelope(tBTA_MA_BMSG_ENVELOPE * p_envelope, tBTA_MA_STREAM * p_stream); + + extern void * bta_ma_bmsg_alloc(size_t cb); + extern void bta_ma_bmsg_free(void * p); + extern void bta_ma_bmsg_free_vcards(tBTA_MA_BMSG_VCARD * p_vcard); + extern void bta_ma_bmsg_free_envelope(tBTA_MA_BMSG_ENVELOPE * p_envelope); + extern void bta_ma_bmsg_free_body(tBTA_MA_BMSG_BODY * p_body); + extern void bta_ma_bmsg_free_content(tBTA_MA_BMSG_CONTENT * p_content); + extern void bta_ma_bmsg_free_message_text(tBTA_MA_BMSG_MESSAGE * p_message); + extern void bta_ma_bmsg_free_vcard_prop(tBTA_MA_VCARD_PROPERTY * p_prop); + +#ifdef __cplusplus +} +#endif + +#endif /* BTA_MA_UTIL_H */ diff --git a/bta/ma/bta_mse_act.c b/bta/ma/bta_mse_act.c new file mode 100644 index 0000000..c8ec487 --- /dev/null +++ b/bta/ma/bta_mse_act.c @@ -0,0 +1,2763 @@ +/***************************************************************************** +** +** Name: bta_mse_act.c +** +** Description: This file contains the message access server action +** functions for the state machine. +** +** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved. +** Broadcom Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include "bt_target.h" + +#if defined(BTA_MSE_INCLUDED) && (BTA_MSE_INCLUDED == TRUE) + +#include <string.h> +#include "gki.h" +#include "sdp_api.h" +#include "bta_sys.h" +#include "port_api.h" +#include "obx_api.h" +#include "sdp_api.h" +#include "bta_fs_api.h" +#include "bta_mse_api.h" +#include "bta_mse_int.h" +#include "bta_fs_co.h" +#include "utl.h" +#include "bd.h" +#include "bta_ma_def.h" + + +/***************************************************************************** +** Local Function prototypes +*****************************************************************************/ +void bta_mse_req_app_access(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); +static void bta_mse_mn_sdp_cback0(UINT16 status); +static void bta_mse_mn_sdp_cback1(UINT16 status); +static void bta_mse_mn_sdp_cback2(UINT16 status); +static void bta_mse_mn_sdp_cback3(UINT16 status); +static void bta_mse_mn_sdp_cback4(UINT16 status); +static void bta_mse_mn_sdp_cback5(UINT16 status); +static void bta_mse_mn_sdp_cback6(UINT16 status); + +static tSDP_DISC_CMPL_CB * const bta_mse_mn_sdp_cback_arr[] = { + bta_mse_mn_sdp_cback0, + bta_mse_mn_sdp_cback1, + bta_mse_mn_sdp_cback2, + bta_mse_mn_sdp_cback3, + bta_mse_mn_sdp_cback4, + bta_mse_mn_sdp_cback5, + bta_mse_mn_sdp_cback6 +}; + +#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE) +static char *bta_mse_obx_evt_code(UINT16 evt_code); +#endif + + +/******************************************************************************* +** Message Access Server (MAS) Action functions +** +*******************************************************************************/ + +/******************************************************************************* +** +** Function bta_mse_ma_int_close +** +** Description Porcesses the Internal MAS session close event +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_int_close(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); + BD_ADDR bd_addr; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_int_close inst idx=%d sess idx=%d",inst_idx, sess_idx); +#endif + + if (OBX_GetPeerAddr(p_cb->obx_handle, bd_addr) != 0) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("Send Obx Discon rsp obx session id=%d", + p_cb->obx_handle); +#endif + /* resources will be freed at BTA_MSE_MA_OBX_CLOSE_EVT */ + OBX_DisconnectRsp(p_cb->obx_handle, OBX_RSP_SERVICE_UNAVL, NULL); + } + else + { + /* OBX close already */ + bta_mse_ma_sm_execute(inst_idx, sess_idx, BTA_MSE_MA_OBX_CLOSE_EVT, p_data); + } +} + +/******************************************************************************* +** +** Function bta_mse_ma_api_upd_ibx_rsp +** +** Description Processes the API update inbox response event. +** If permission had been granted, continue the operation, +** otherwise stop the operation. +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_api_upd_ibx_rsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); + UINT8 rsp_code = OBX_RSP_UNAUTHORIZED; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_api_upd_ibx_rsp inst idx=%d sess idx=%d",inst_idx, sess_idx); +#endif + + /* Process the currently active access response */ + if (p_cb->oper == BTA_MSE_OPER_UPDATE_INBOX) + { + bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE); + if (p_data->api_upd_ibx_rsp.rsp == BTA_MSE_UPDATE_INBOX_ALLOW) + { + bta_mse_co_update_inbox(p_cb->obx_handle, bta_mse_cb.app_id); + rsp_code = OBX_RSP_OK; + } + OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL); + } + else + { + APPL_TRACE_WARNING1("MSE UPDIBXRSP: Unknown tBTA_MSE_OPER value (%d)", + p_cb->oper); + } +} + + +/******************************************************************************* +** +** Function bta_mse_ma_api_set_notif_reg_rsp +** +** Description Processes the API set notification registration response event. +** If permission had been granted, continue the operation, +** otherwise stop the operation. +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_api_set_notif_reg_rsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); + UINT8 rsp_code = OBX_RSP_SERVICE_UNAVL; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_api_set_notif_reg_rsp inst idx=%d sess idx=%d",inst_idx, sess_idx); +#endif + + /* Process the currently active access response */ + if ( p_cb->oper == BTA_MSE_OPER_NOTIF_REG) + { + bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE); + if (p_data->api_set_notif_reg_rsp.rsp == BTA_MSE_SET_NOTIF_REG_ALLOW) + { + bta_mse_proc_notif_reg_status(p_cb->notif_reg_req.notif_status, + inst_idx, sess_idx); + } + else + { + OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL); + } + } + else + { + APPL_TRACE_WARNING1("MSE SETNOTIFREGRSP: Unknown tBTA_MSE_OPER value (%d)", + p_cb->oper); + } +} + + +/******************************************************************************* +** +** Function bta_mse_ma_api_accessrsp +** +** Description Processes the API access response event. +** If permission had been granted, continue the operation, +** otherwise stop the operation. +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ + +void bta_mse_ma_api_accessrsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); + UINT8 rsp_code = OBX_RSP_OK; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT3("bta_mse_ma_api_accessrsp inst idx=%d sess idx=%d access_rsp=%d", + inst_idx, sess_idx, + p_data->api_access_rsp.rsp); +#endif + + if (p_cb->oper != p_data->api_access_rsp.oper ) + { + APPL_TRACE_WARNING2("MSE MA ACCRSP: not match active:%d, rsp:%d", + p_cb->oper, p_data->api_access_rsp.oper); + return; + } + + /* Process the currently active access response */ + switch (p_cb->oper) + { + case BTA_MSE_OPER_SETPATH: + + if (p_data->api_access_rsp.rsp == BTA_MA_ACCESS_TYPE_ALLOW) + { + bta_mse_co_set_folder( p_cb->obx_handle, p_cb->sp.p_path, bta_mse_cb.app_id); + /* updat the working dir */ + BCM_STRNCPY_S(p_cb->p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->sp.p_path, p_bta_fs_cfg->max_path_len); + } + else + { + rsp_code = OBX_RSP_UNAUTHORIZED; + } + + utl_freebuf((void**)&(p_cb->sp.p_path)); + utl_freebuf((void**)&(p_cb->sp.p_name)); + OBX_SetPathRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL); + bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE); + break; + + case BTA_MSE_OPER_GET_MSG_LIST: + + if (p_data->api_access_rsp.rsp == BTA_MA_ACCESS_TYPE_ALLOW) + { + bta_mse_getmsglist(inst_idx,sess_idx, TRUE); + } + else + { + OBX_GetRsp(p_cb->obx_handle, OBX_RSP_UNAUTHORIZED, (BT_HDR *)NULL); + bta_mse_clean_msg_list(inst_idx,sess_idx); + } + break; + + case BTA_MSE_OPER_GET_MSG: + + if (p_data->api_access_rsp.rsp == BTA_MA_ACCESS_TYPE_ALLOW) + { + bta_mse_getmsg(inst_idx,sess_idx, TRUE); + } + else + { + OBX_GetRsp(p_cb->obx_handle, OBX_RSP_UNAUTHORIZED, (BT_HDR *)NULL); + bta_mse_clean_msg(inst_idx,sess_idx); + } + break; + + case BTA_MSE_OPER_PUSH_MSG: + + if (p_data->api_access_rsp.rsp == BTA_MA_ACCESS_TYPE_ALLOW) + { + bta_mse_pushmsg(inst_idx, sess_idx, TRUE); + } + else + { + OBX_PutRsp(p_cb->obx_handle, OBX_RSP_UNAUTHORIZED, (BT_HDR *)NULL); + bta_mse_clean_push_msg(inst_idx,sess_idx); + } + break; + + case BTA_MSE_OPER_DEL_MSG: + + if (p_data->api_access_rsp.rsp == BTA_MA_ACCESS_TYPE_ALLOW) + { + p_cb->cout_active = TRUE; + bta_mse_co_set_msg_delete_status((tBTA_MA_SESS_HANDLE) p_cb->obx_handle, + p_cb->set_msg_sts.handle, + p_cb->set_msg_sts.sts_val, + BTA_MSE_CI_DEL_MSG_EVT, + bta_mse_cb.app_id); + } + else + { + OBX_PutRsp(p_cb->obx_handle, OBX_RSP_UNAUTHORIZED, (BT_HDR *)NULL); + bta_mse_clean_set_msg_sts(inst_idx,sess_idx); + } + break; + + default: + APPL_TRACE_WARNING1("MSE ACCRSP: Unknown tBTA_MSE_OPER value (%d)", + p_cb->oper); + break; + } +} + +/******************************************************************************* +** +** Function bta_mse_ma_ci_get_folder_entry +** +** Description Proceses the get folder entry call-in event +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_ci_get_folder_entry(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); + UINT8 rsp_code = OBX_RSP_PART_CONTENT; + BOOLEAN free_pkt = TRUE; + + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_ci_get_folder_entry inst idx=%d sess idx=%d", + inst_idx, sess_idx); +#endif + + p_cb->cout_active = FALSE; + + if (p_cb->aborting) + { + bta_mse_clean_getput(inst_idx,sess_idx, BTA_MA_STATUS_ABORTED); + return; + } + + /* Process dirent listing call-in event if operation is still active */ + if (p_cb->oper == BTA_MSE_OPER_GET_FOLDER_LIST) + { + switch (p_data->ci_get_fentry.status) + { + case BTA_MA_STATUS_OK: /* Valid new entry */ + free_pkt = FALSE; + rsp_code = bta_mse_add_list_entry(inst_idx, sess_idx); + break; + + case BTA_MA_STATUS_EODIR: /* End of list (entry not valid) */ + free_pkt = FALSE; + rsp_code = OBX_RSP_OK; + break; + + case BTA_MA_STATUS_FAIL: /* Error occurred */ + rsp_code = OBX_RSP_NOT_FOUND; + break; + + default: + APPL_TRACE_ERROR1("bta_mse_ma_ci_get_folder_entry Unknown status=%d ", + p_data->ci_get_fentry.status ); + rsp_code = OBX_RSP_NOT_FOUND; + break; + } + } + + if (rsp_code != OBX_RSP_PART_CONTENT) + bta_mse_end_of_list(inst_idx, sess_idx,rsp_code); + + if (free_pkt) + utl_freebuf((void **)&p_cb->obx.p_pkt); +} + + +/******************************************************************************* +** +** Function bta_mse_ma_ci_get_ml_info +** +** Description Proceses the get message list info call-in event +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_ci_get_ml_info(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); + UINT8 rsp_code = OBX_RSP_PART_CONTENT; + BOOLEAN free_pkt = TRUE; + + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_ci_get_ml_info inst idx=%d sess idx=%d", + inst_idx, sess_idx); +#endif + + p_cb->cout_active = FALSE; + + if (p_cb->aborting) + { + bta_mse_clean_getput(inst_idx,sess_idx, BTA_MA_STATUS_ABORTED); + return; + } + + /* Process dirent listing call-in event if operation is still active */ + if (p_cb->oper == BTA_MSE_OPER_GET_MSG_LIST) + { + switch (p_data->ci_get_ml_info.status) + { + case BTA_MA_STATUS_OK: /* Valid new entry */ + free_pkt = FALSE; + rsp_code = bta_mse_add_msg_list_info(inst_idx, sess_idx); + break; + + case BTA_MA_STATUS_EODIR: /* End of list (entry not valid) */ + free_pkt = FALSE; + rsp_code = OBX_RSP_OK; + break; + + case BTA_MA_STATUS_FAIL: /* Error occurred */ + rsp_code = OBX_RSP_NOT_FOUND; + break; + + default: + APPL_TRACE_ERROR1("bta_mse_ma_ci_get_ml_info Unknown status=%d ", + p_data->ci_get_ml_info.status ); + rsp_code = OBX_RSP_NOT_FOUND; + break; + } + } + + if (rsp_code != OBX_RSP_PART_CONTENT) + bta_mse_end_of_msg_list(inst_idx, sess_idx,rsp_code); + + if (free_pkt) + utl_freebuf((void **)&p_cb->obx.p_pkt); +} + +/******************************************************************************* +** +** Function bta_mse_ma_ci_get_msg_entry +** +** Description Proceses the get message entry call-in event +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_ci_get_ml_entry(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); + UINT8 rsp_code = OBX_RSP_PART_CONTENT; + BOOLEAN free_pkt = TRUE; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_ci_get_msg_entry inst idx=%d sess idx=%d",inst_idx, sess_idx); + APPL_TRACE_EVENT1(" status=%d",p_data->ci_get_ml_entry.status); +#endif + + p_cb->cout_active = FALSE; + + if (p_cb->aborting) + { + bta_mse_clean_getput(inst_idx,sess_idx, BTA_MA_STATUS_ABORTED); + return; + } + + /* Process dirent listing call-in event if operation is still active */ + if (p_cb->oper == BTA_MSE_OPER_GET_MSG_LIST) + { + switch (p_data->ci_get_ml_entry.status) + { + case BTA_MA_STATUS_OK: /* Valid new entry */ + free_pkt = FALSE; + rsp_code = bta_mse_add_msg_list_entry(inst_idx, sess_idx); + break; + + case BTA_MA_STATUS_EODIR: /* End of list (entry not valid) */ + free_pkt = FALSE; + rsp_code = OBX_RSP_OK; + break; + + case BTA_MA_STATUS_FAIL: /* Error occurred */ + rsp_code = OBX_RSP_NOT_FOUND; + break; + + default: + APPL_TRACE_ERROR1("bta_mse_ma_ci_get_ml_entry Unknown status=%d ", + p_data->ci_get_ml_entry.status); + rsp_code = OBX_RSP_NOT_FOUND; + break; + } + } + + if (rsp_code != OBX_RSP_PART_CONTENT) + bta_mse_end_of_msg_list(inst_idx, sess_idx,rsp_code); + + if (free_pkt) + utl_freebuf((void **)&p_cb->obx.p_pkt); +} + + +/******************************************************************************* +** +** Function bta_mse_ma_ci_get_msg +** +** Description Proceses the get message call-in event +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_ci_get_msg(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + 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_CI_GET_MSG *p_ci_get_msg = &p_data->ci_get_msg; + UINT8 rsp_code = OBX_RSP_NOT_FOUND; + BOOLEAN free_pkt = TRUE, end_of_msg= TRUE; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_ci_get_msg inst idx=%d sess idx=%d", + inst_idx, sess_idx); + APPL_TRACE_EVENT1("status=%d",p_data->ci_get_ml_entry.status); +#endif + + p_cb->cout_active = FALSE; + + if (p_cb->aborting) + { + bta_mse_clean_getput(inst_idx,sess_idx, BTA_MA_STATUS_ABORTED); + return; + } + + /* Process get msg call-in event if operation is still active */ + if (p_cb->oper == BTA_MSE_OPER_GET_MSG) + { + switch (p_data->ci_get_msg.status) + { + case BTA_MA_STATUS_OK: /* Valid new entry */ + free_pkt = FALSE; + p_param->frac_deliver_status = p_ci_get_msg->frac_deliver_status; + p_param->filled_buff_size = p_ci_get_msg->filled_buff_size; + + if ( p_ci_get_msg->multi_pkt_status == BTA_MA_MPKT_STATUS_MORE) + { + p_param->byte_get_cnt += p_param->filled_buff_size; + rsp_code = OBX_RSP_CONTINUE; + } + else + rsp_code = OBX_RSP_OK; + + break; + + case BTA_MA_STATUS_FAIL: /* Error occurred */ + break; + + default: + end_of_msg = FALSE; + break; + } + } + + if (end_of_msg) + bta_mse_end_of_msg(inst_idx, sess_idx,rsp_code); + + if (free_pkt) + utl_freebuf((void **)&p_cb->obx.p_pkt); +} + + +/******************************************************************************* +** +** Function bta_mse_ma_ci_push_msg +** +** Description Proceses the push message call-in event +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_ci_push_msg(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + 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; + UINT8 rsp_code = OBX_RSP_INTRNL_SRVR_ERR; + BOOLEAN free_pkt = TRUE; + char handle_buf[BTA_MSE_64BIT_HEX_STR_SIZE]; + tBTA_MA_STREAM strm; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_ci_push_msg inst idx=%d sess idx=%d", + inst_idx, sess_idx); + APPL_TRACE_EVENT4(" status=%d ci_last_pkt=%d obx_final=%d oper=%d", + p_data->ci_push_msg.status, + p_data->ci_push_msg.last_packet, + p_obx->final_pkt, + p_cb->oper); +#endif + + p_cb->cout_active = FALSE; + + if (p_cb->aborting) + { + bta_mse_clean_getput(inst_idx,sess_idx, BTA_MA_STATUS_ABORTED); + return; + } + + /* Process get msg call-in event if operation is still active */ + if (p_cb->oper == BTA_MSE_OPER_PUSH_MSG) + { + switch (p_data->ci_push_msg.status) + { + case BTA_MA_STATUS_OK: /* Valid new entry */ + if (p_obx->final_pkt) + { + APPL_TRACE_EVENT2("final pkt: status=%d oper=%d", + p_data->ci_push_msg.status, p_cb->oper); + + utl_freebuf((void**)&p_obx->p_pkt); + + rsp_code = OBX_RSP_OK; + + p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle, + /* p_cb->peer_mtu */ HCI_CMD_POOL_BUF_SIZE); + if (p_obx->p_pkt) + { + memset(handle_buf, 0,BTA_MSE_64BIT_HEX_STR_SIZE); + BTA_MaInitMemStream(&strm,(UINT8 *) handle_buf, BTA_MSE_64BIT_HEX_STR_SIZE); + bta_ma_stream_handle(&strm, p_data->ci_push_msg.handle); + if (OBX_AddUtf8NameHdr(p_obx->p_pkt, (UINT8 *)handle_buf)) + { + rsp_code = OBX_RSP_OK; + free_pkt = FALSE; + } + else + { + rsp_code = OBX_RSP_INTRNL_SRVR_ERR; + } + } + else + { + rsp_code = OBX_RSP_INTRNL_SRVR_ERR; + } + } + else + rsp_code = OBX_RSP_CONTINUE; + break; + + case BTA_MA_STATUS_FAIL: /* Error occurred */ + rsp_code = OBX_RSP_UNAUTHORIZED; + break; + default: + break; + } + } + + if (rsp_code==OBX_RSP_OK) + { + OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt); + p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */ + } + else + { + OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL); + } + + + if (rsp_code == OBX_RSP_CONTINUE) + { + bta_mse_send_push_msg_in_prog_evt(inst_idx,sess_idx); + } + else + { + if ((rsp_code != OBX_RSP_OK) || + ((p_obx->final_pkt) &&(rsp_code == OBX_RSP_OK))) + { + bta_mse_send_oper_cmpl_evt(inst_idx,sess_idx, p_data->ci_push_msg.status); + bta_mse_clean_push_msg(inst_idx,sess_idx); + } + } + + if (free_pkt) utl_freebuf((void**)&p_obx->p_pkt); + +} + +/******************************************************************************* +** +** Function bta_mse_ma_ci_del_msg +** +** Description Proceses the delete message call-in event +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_ci_del_msg(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); + UINT8 rsp_code = OBX_RSP_OK; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_ci_del_msg inst idx=%d sess idx=%d", + inst_idx, sess_idx); + APPL_TRACE_EVENT2(" status=%d oper=%d",p_data->ci_del_msg.status, p_cb->oper); +#endif + + p_cb->cout_active = FALSE; + + if (p_cb->aborting) + { + /* too late to abort now*/ + bta_mse_abort_too_late(inst_idx,sess_idx); + } + + /* Process get msg call-in event if operation is still active */ + if (p_cb->oper == BTA_MSE_OPER_DEL_MSG) + { + switch (p_data->ci_del_msg.status) + { + case BTA_MA_STATUS_OK: + rsp_code = OBX_RSP_OK; + break; + + case BTA_MA_STATUS_FAIL: /* Error occurred */ + rsp_code = OBX_RSP_FORBIDDEN; + break; + default: + break; + } + } + + OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL); + bta_mse_clean_set_msg_sts(inst_idx,sess_idx); + +} +/******************************************************************************* +** +** Function bta_mse_ma_obx_connect +** +** Description Proceses the obx connect request to open a MAS session +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_obx_connect(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + 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_EVT *p_evt = &p_data->obx_evt; + tBTA_MSE cback_evt_data; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_obx_connect inst idx=%d sess idx=%d", + inst_idx, sess_idx); +#endif + + p_cb->peer_mtu = p_evt->param.conn.mtu; + p_cb->obx_handle = p_evt->handle; + memcpy(p_cb->bd_addr, p_evt->param.conn.peer_addr, BD_ADDR_LEN); + + OBX_ConnectRsp(p_evt->handle, OBX_RSP_OK, (BT_HDR *)NULL); + + /* Reset to the root directory */ + BCM_STRNCPY_S(p_cb->p_workdir, p_bta_fs_cfg->max_path_len+1, p_scb->p_rootpath, p_bta_fs_cfg->max_path_len); + + /* inform role manager */ + bta_mse_pm_conn_open(p_cb->bd_addr); + + bdcpy(cback_evt_data.ma_open.bd_addr, p_cb->bd_addr); + BCM_STRNCPY_S((char *)cback_evt_data.ma_open.dev_name, sizeof(cback_evt_data.ma_open.dev_name), + "", BTM_MAX_REM_BD_NAME_LEN); + cback_evt_data.ma_open.mas_instance_id = p_scb->mas_inst_id; + cback_evt_data.ma_open.mas_session_id = p_cb->obx_handle; + + bta_mse_cb.p_cback(BTA_MSE_MA_OPEN_EVT, (tBTA_MSE *) &cback_evt_data); + + /* Done with Obex packet */ + utl_freebuf((void**)&p_evt->p_pkt); + +} +/******************************************************************************* +** +** Function bta_mse_ma_obx_disc +** +** Description Proceses the obx disconnect request to close a MAS session +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_obx_disc(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt; + UINT8 rsp_code; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_obx_disc inst idx=%d sess idx=%d", + inst_idx, sess_idx); +#endif + rsp_code = (p_evt->obx_event == OBX_DISCONNECT_REQ_EVT) ? OBX_RSP_OK + : OBX_RSP_BAD_REQUEST; + OBX_DisconnectRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL); + + /* Done with Obex packet */ + utl_freebuf((void**)&p_evt->p_pkt); +} +/******************************************************************************* +** +** Function bta_mse_ma_obx_close +** +** Description Proceses the obx close indication to close a MAS connection +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_obx_close(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + 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_ma_obx_close inst idx=%d sess idx=%d", + inst_idx, sess_idx); +#endif + /* finished if not waiting on a call-in function */ + if (!p_cb->cout_active) + bta_mse_ma_sm_execute(inst_idx, sess_idx, BTA_MSE_CLOSE_CMPL_EVT, p_data); + +} + +/******************************************************************************* +** +** Function bta_mse_ma_obx_abort +** +** Description Proceses the obx abort request +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_obx_abort(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); + tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT3("bta_mse_ma_obx_abort inst idx=%d sess idx=%d oper=%d", + inst_idx, sess_idx, p_cb->oper); +#endif + + utl_freebuf((void**)&p_evt->p_pkt); + + switch (p_cb->oper) + { + case BTA_MSE_OPER_SETPATH: + case BTA_MSE_OPER_NONE: + OBX_AbortRsp(p_evt->handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL); + return; + default: + break; + + } + + if (!p_cb->cout_active) + { + bta_mse_clean_getput(inst_idx,sess_idx, BTA_MA_STATUS_ABORTED); + } + else /* Delay the response if a call-out function is active */ + p_cb->aborting = TRUE; + +} +/******************************************************************************* +** +** Function bta_mse_ma_obx_put +** +** Description Proceses the obx put request +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_obx_put(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); + tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt; + tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx; + tBTA_MSE_OPER_PUSH_MSG *p_push_msg = &p_cb->push_msg; + tBTA_MSE_OPER_SET_MSG_STS *p_set_msg_sts = &p_cb->set_msg_sts; + tBTA_MA_SESS_HANDLE mas_session_id; + UINT16 len; + UINT8 *p_type; + UINT8 *p_param; + UINT8 rsp_code = OBX_RSP_OK; + UINT8 num_hdrs; + BOOLEAN free_pkt = TRUE; + BOOLEAN send_rsp = TRUE; + BOOLEAN send_ok_rsp = FALSE; + + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_obx_put inst idx=%d sess idx=%d", + inst_idx, sess_idx); +#endif + + if (OBX_ReadTypeHdr(p_evt->p_pkt, &p_type, &len)) + { + if (!memcmp(p_type, BTA_MA_HDR_TYPE_NOTIF_REG, len)) + { + bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NOTIF_REG); + } + else if (!memcmp(p_type, BTA_MA_HDR_TYPE_MSG, len)) + { + bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_PUSH_MSG); + bta_mse_init_push_msg(inst_idx, sess_idx, &rsp_code); + if (rsp_code != OBX_RSP_OK) + { + OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL); + bta_mse_clean_push_msg(inst_idx, sess_idx); + return; + } + } + else if (!memcmp(p_type, BTA_MA_HDR_TYPE_MSG_UPDATE, len)) + { + bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_UPDATE_INBOX); + } + else if (!memcmp(p_type, BTA_MA_HDR_TYPE_MSG_STATUS, len)) + { + bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_SET_MSG_STATUS); + bta_mse_init_set_msg_sts(inst_idx, sess_idx, &rsp_code); + if (rsp_code != OBX_RSP_OK) + { + OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL); + bta_mse_clean_set_msg_sts(inst_idx, sess_idx); + return; + } + } + } + + switch ( p_cb->oper) + { + case BTA_MSE_OPER_NOTIF_REG: + + p_param = bta_mse_read_app_params(p_evt->p_pkt, BTA_MA_APH_NOTIF_STATUS, &len); + if (p_param) + { + p_cb->notif_reg_req.notif_status_rcv = TRUE; + BE_STREAM_TO_UINT8(p_cb->notif_reg_req.notif_status, p_param); + } + + if (p_evt->param.put.final) + { + /* check end of body is included or not */ + + if ((num_hdrs = OBX_ReadBodyHdr(p_evt->p_pkt, &p_obx->p_start, &p_obx->offset, &p_obx->final_pkt)) && + p_obx->final_pkt) + { + if (p_cb->notif_reg_req.notif_status_rcv) + { + if (!bta_mse_send_set_notif_reg(p_cb->notif_reg_req.notif_status, + inst_idx, sess_idx)) + { + OBX_PutRsp(p_evt->handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL); + } + else + { + /* wait for the set notif reg response from the application*/ + break; + } + } + else + { + OBX_PutRsp(p_evt->handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL); + } + } + else + { + OBX_PutRsp(p_evt->handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL); + } + /* if reach here this is a bad request case so clean up*/ + bta_mse_clean_set_notif_reg(inst_idx,sess_idx); + } + else + { + OBX_PutRsp(p_evt->handle, OBX_RSP_CONTINUE, (BT_HDR *)NULL); + } + + break; + case BTA_MSE_OPER_PUSH_MSG: + + if ((!p_push_msg->rcv_folder_name) && + (OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_push_msg->param.p_folder, + p_bta_mse_cfg->max_name_len))) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("Rcv folder len=%d, name=%s ", + strlen( p_push_msg->param.p_folder), + p_push_msg->param.p_folder); +#endif + p_push_msg->rcv_folder_name = TRUE; + } + + if (!p_push_msg->rcv_charset) + { + p_param = bta_mse_read_app_params(p_evt->p_pkt, BTA_MA_APH_CHARSET, &len); + if (p_param) + { + + p_push_msg->rcv_charset = TRUE; + BE_STREAM_TO_UINT8(p_push_msg->param.charset, p_param); +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("Rcv Charset=%d(0-native 1-UTF8)",p_push_msg->param.charset); +#endif + } + } + + if (!p_push_msg->rcv_transparent) + { + p_param = bta_mse_read_app_params(p_evt->p_pkt, BTA_MA_APH_TRANSPARENT, &len); + if (p_param) + { + p_push_msg->rcv_transparent = TRUE; + BE_STREAM_TO_UINT8(p_push_msg->param.transparent, p_param); +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("Rcv Transparent=%d",p_push_msg->param.transparent); +#endif + } + } + + if (!p_push_msg->rcv_retry) + { + p_param = bta_mse_read_app_params(p_evt->p_pkt, BTA_MA_APH_RETRY, &len); + if (p_param) + { + p_push_msg->rcv_retry = TRUE; + BE_STREAM_TO_UINT8(p_push_msg->param.retry, p_param); +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("Rcv Retry=%d",p_push_msg->param.retry); +#endif + } + } + + /* Read the body header from the obx packet */ + num_hdrs = OBX_ReadBodyHdr(p_evt->p_pkt, &p_obx->p_start, &p_obx->offset, + &p_obx->final_pkt); + /* process body or end of body header */ + if (num_hdrs >= 1 ) + { + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT3("Rcv Body or EndOfBody body_hdr=%d len=%d final=%d", + num_hdrs, + p_obx->offset, + p_obx->final_pkt); +#endif + + if (p_push_msg->rcv_charset && p_push_msg->rcv_folder_name) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("Rcv all Required params"); +#endif + + free_pkt = FALSE; + p_obx->p_pkt = p_evt->p_pkt; + if (p_push_msg->first_req_pkt) + { + p_push_msg->first_req_pkt = FALSE; + bta_mse_req_app_access( inst_idx, sess_idx, p_data); + } + else + { + bta_mse_pushmsg(inst_idx, sess_idx, FALSE); + } + send_rsp = FALSE; + } + else + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_ERROR0("Not all Mandatory params are rcv before body/EndofBody: bad request"); +#endif + rsp_code = OBX_RSP_BAD_REQUEST; + } + } + else + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("No Body or End of Body in this push msg pkt"); +#endif + } + + if (!p_obx->final_pkt) + { + if (rsp_code != OBX_RSP_BAD_REQUEST) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("Not a final pkt and no error set rsp_code=Continue"); +#endif + rsp_code = OBX_RSP_CONTINUE; + } + } + + if (send_rsp) OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL); + if (rsp_code == OBX_RSP_BAD_REQUEST ) + { + if (!p_push_msg->first_req_pkt) + bta_mse_send_oper_cmpl_evt(inst_idx,sess_idx, BTA_MA_STATUS_FAIL); + bta_mse_clean_push_msg(inst_idx,sess_idx); + } + break; + case BTA_MSE_OPER_UPDATE_INBOX: + + if (p_evt->param.put.final) + { + /* check enod of body is included or not */ + + if ((num_hdrs = OBX_ReadBodyHdr(p_evt->p_pkt, &p_obx->p_start, &p_obx->offset, &p_obx->final_pkt)) && + p_obx->final_pkt) + { + + mas_session_id = (tBTA_MA_SESS_HANDLE) p_cb->obx_handle; + bta_mse_cb.p_cback(BTA_MSE_UPDATE_INBOX_EVT, (tBTA_MSE *)&mas_session_id); + } + else + { + OBX_PutRsp(p_evt->handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL); + } + } + else + { + OBX_PutRsp(p_evt->handle, OBX_RSP_CONTINUE, (BT_HDR *)NULL); + } + + + break; + case BTA_MSE_OPER_SET_MSG_STATUS: + + + if ((!p_set_msg_sts->rcv_msg_handle) && + (OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_set_msg_sts->p_msg_handle, + BTA_MSE_64BIT_HEX_STR_SIZE))) + { + bta_ma_convert_hex_str_to_64bit_handle(p_set_msg_sts->p_msg_handle, + p_set_msg_sts->handle); + p_set_msg_sts->rcv_msg_handle = TRUE; + } + + if (!p_set_msg_sts->rcv_sts_ind) + { + p_param = bta_mse_read_app_params(p_evt->p_pkt, BTA_MA_APH_STS_INDCTR, &len); + if (p_param) + { + p_set_msg_sts->rcv_sts_ind = TRUE; + BE_STREAM_TO_UINT8(p_set_msg_sts->sts_ind, p_param); + } + } + + if (!p_set_msg_sts->rcv_sts_val) + { + p_param = bta_mse_read_app_params(p_evt->p_pkt, BTA_MA_APH_STS_VALUE, &len); + if (p_param) + { + p_set_msg_sts->rcv_sts_val = TRUE; + BE_STREAM_TO_UINT8(p_set_msg_sts->sts_val, p_param); + } + } + + /* Read the body header from the obx packet */ + num_hdrs = OBX_ReadBodyHdr(p_evt->p_pkt, &p_obx->p_start, &p_obx->offset, + &p_obx->final_pkt); + /* process body or end of body header */ + if ((num_hdrs >= 1 && p_obx->final_pkt ) ) + { + if (p_set_msg_sts->rcv_msg_handle && p_set_msg_sts->rcv_sts_ind && + p_set_msg_sts->rcv_sts_val) + { + if (p_set_msg_sts->sts_ind == BTA_MA_STS_INDTR_DELETE) + { + p_cb->oper = BTA_MSE_OPER_DEL_MSG; + bta_mse_req_app_access( inst_idx, sess_idx, p_data); + } + else + { + if (bta_mse_co_set_msg_read_status((tBTA_MA_SESS_HANDLE) p_cb->obx_handle, + p_set_msg_sts->handle, + p_set_msg_sts->sts_val, + bta_mse_cb.app_id) != BTA_MA_STATUS_OK) + { + rsp_code = OBX_RSP_FORBIDDEN; + } + send_ok_rsp = TRUE; + } + } + else + { + rsp_code = OBX_RSP_BAD_REQUEST; + } + } + + if (!p_obx->final_pkt) + { + if (rsp_code != OBX_RSP_BAD_REQUEST) + { + rsp_code = OBX_RSP_CONTINUE; + } + } + + if (rsp_code != OBX_RSP_OK) + { + OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL); + if (rsp_code == OBX_RSP_BAD_REQUEST ) + { + bta_mse_clean_set_msg_sts(inst_idx,sess_idx); + } + } + else + { + if (send_ok_rsp) + { + OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL); + bta_mse_clean_set_msg_sts(inst_idx,sess_idx); + } + } + break; + default: + OBX_PutRsp(p_evt->handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL); + break; + } + + /* Done with Obex packet */ + if (free_pkt) utl_freebuf((void**)&p_evt->p_pkt); +} + +/******************************************************************************* +** +** Function bta_mse_ma_obx_get +** +** Description Proceses the obx get request +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_obx_get(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); + tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt; + UINT16 len; + UINT8 *p_type; + tBTA_MSE_MA_GET_ACT get_act = BTA_MSE_MA_GET_ACT_NONE; + tBTA_MSE_MA_GET_TYPE get_type = BTA_MSE_MA_GET_TYPE_NONE; + UINT8 rsp_code = OBX_RSP_BAD_REQUEST; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_obx_get inst idx=%d sess idx=%d",inst_idx, sess_idx); + APPL_TRACE_EVENT1(" oper=%d",p_cb->oper ); +#endif + switch (p_cb->oper) + { + case BTA_MSE_OPER_GET_FOLDER_LIST: + get_type = BTA_MSE_MA_GET_TYPE_CON_FOLDER_LIST; + break; + case BTA_MSE_OPER_GET_MSG_LIST: + get_type = BTA_MSE_MA_GET_TYPE_CON_MSG_LIST; + break; + case BTA_MSE_OPER_GET_MSG: + get_type = BTA_MSE_MA_GET_TYPE_CON_MSG; + break; + case BTA_MSE_OPER_NONE: + if (OBX_ReadTypeHdr(p_evt->p_pkt, &p_type, &len)) + { + if (!memcmp(p_type, BTA_MA_HDR_TYPE_FOLDER_LIST, len)) + { + get_type = BTA_MSE_MA_GET_TYPE_FOLDER_LIST; + } + else if (!memcmp(p_type, BTA_MA_HDR_TYPE_MSG_LIST, len) ) + { + get_type = BTA_MSE_MA_GET_TYPE_MSG_LIST; + } + else if (!memcmp(p_type, BTA_MA_HDR_TYPE_MSG, len) ) + { + + get_type = BTA_MSE_MA_GET_TYPE_MSG; + } + } + break; + default: + break; + } +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("bta_mse_ma_obx_get get_type=%d",get_type); +#endif + switch (get_type) + { + case BTA_MSE_MA_GET_TYPE_FOLDER_LIST: + bta_mse_ma_fl_read_app_params(inst_idx, sess_idx, p_evt->p_pkt); + get_act = BTA_MSE_MA_GET_ACT_NEW_FOLDER_LIST; + break; + + case BTA_MSE_MA_GET_TYPE_MSG_LIST: + if (!p_cb->ml_param.p_name) + { + p_cb->ml_param.p_name = (char *)GKI_getbuf((UINT16)(p_bta_mse_cfg->max_name_len + 1)); + } + + if (!p_cb->ml_param.p_path) + { + p_cb->ml_param.p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1)); + } + + if ((p_cb->ml_param.p_name != NULL) && (p_cb->ml_param.p_path != NULL)) + { + if (!OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->ml_param.p_name, + p_bta_mse_cfg->max_name_len)) + { + rsp_code = OBX_RSP_BAD_REQUEST; + break; + } + else + { + if (!bta_mse_get_msglist_path(inst_idx, sess_idx)) + { + rsp_code = OBX_RSP_NOT_FOUND; + break; + } + } + } + else + { + rsp_code = OBX_RSP_INTRNL_SRVR_ERR; + break; + } + + bta_mse_ma_ml_read_app_params(inst_idx, sess_idx,p_evt->p_pkt); + get_act = BTA_MSE_MA_GET_ACT_NEW_MSG_LIST; + break; + + case BTA_MSE_MA_GET_TYPE_MSG: + + if (!p_cb->msg_param.p_msg_handle) + { + if ((p_cb->msg_param.p_msg_handle = (char *)GKI_getbuf((UINT16)(BTA_MSE_64BIT_HEX_STR_SIZE))) == NULL ) + { + rsp_code = OBX_RSP_INTRNL_SRVR_ERR; + get_act = BTA_MSE_MA_GET_ACT_ERR; + break; + } + } + + if (OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->msg_param.p_msg_handle, + BTA_MSE_64BIT_HEX_STR_SIZE)) + { + bta_ma_convert_hex_str_to_64bit_handle(p_cb->msg_param.p_msg_handle, + p_cb->msg_param.data.handle); + } + else + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("Unable to decode or find Name Header for Message Handle"); +#endif + + get_act = BTA_MSE_MA_GET_ACT_ERR; + break; + } + + if (!bta_mse_ma_msg_read_app_params(inst_idx, sess_idx, p_evt->p_pkt)) + { + get_act = BTA_MSE_MA_GET_ACT_ERR; + break; + } + get_act = BTA_MSE_MA_GET_ACT_NEW_MSG; + break; + + case BTA_MSE_MA_GET_TYPE_CON_FOLDER_LIST: + get_act = BTA_MSE_MA_GET_ACT_CON_FOLDER_LIST; + break; + + case BTA_MSE_MA_GET_TYPE_CON_MSG_LIST: + get_act = BTA_MSE_MA_GET_ACT_CON_MSG_LIST; + break; + + case BTA_MSE_MA_GET_TYPE_CON_MSG: + get_act = BTA_MSE_MA_GET_ACT_CON_MSG; + break; + default: + break; + } +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1(" get_act=%d",get_act); +#endif + switch (get_act) + { + case BTA_MSE_MA_GET_ACT_NEW_FOLDER_LIST: + bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_GET_FOLDER_LIST); + bta_mse_getfolderlist(inst_idx,sess_idx, TRUE); + break; + case BTA_MSE_MA_GET_ACT_CON_FOLDER_LIST: + bta_mse_getfolderlist(inst_idx,sess_idx, FALSE); + break; + + case BTA_MSE_MA_GET_ACT_NEW_MSG_LIST: + bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_GET_MSG_LIST); + bta_mse_req_app_access( inst_idx, sess_idx, p_data); + break; + case BTA_MSE_MA_GET_ACT_CON_MSG_LIST: + bta_mse_getmsglist(inst_idx,sess_idx, FALSE); + break; + + case BTA_MSE_MA_GET_ACT_NEW_MSG: + bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_GET_MSG); + if (p_cb->msg_param.data.fraction_request == BTA_MA_FRAC_REQ_FIRST || + p_cb->msg_param.data.fraction_request == BTA_MA_FRAC_REQ_NEXT) + { + p_cb->msg_param.add_frac_del_hdr = TRUE; + } + p_cb->msg_param.byte_get_cnt = 0; + bta_mse_req_app_access( inst_idx, sess_idx, p_data); + break; + case BTA_MSE_MA_GET_ACT_CON_MSG: + bta_mse_getmsg(inst_idx,sess_idx, FALSE); + break; + + case BTA_MSE_MA_GET_ACT_ERR: + default: + OBX_GetRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL); + utl_freebuf((void**)&p_cb->ml_param.p_name); + utl_freebuf((void**)&p_cb->ml_param.p_path); + break; + } + /* Done with Obex packet */ + utl_freebuf((void**)&p_evt->p_pkt); +} +/******************************************************************************* +** +** Function bta_mse_ma_obx_setpath +** +** Description Proceses the obx setpath request +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_obx_setpath(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); + tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt; + tBTA_MA_DIR_NAV flags = (tBTA_MA_DIR_NAV)p_evt->param.sp.flag; + UINT8 rsp_code = OBX_RSP_BAD_REQUEST; + tBTA_MSE_OPER mse_oper = BTA_MSE_OPER_NONE; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_obx_setpath inst idx=%d sess idx=%d", + inst_idx, sess_idx); + APPL_TRACE_EVENT1(" flags=%d ", flags); +#endif + + /* Verify flags and handle before accepting */ + if ((flags == BTA_MA_DIR_NAV_ROOT_OR_DOWN_ONE_LVL) || + (flags == BTA_MA_DIR_NAV_UP_ONE_LVL)) + { + + p_cb->sp.p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1)); + p_cb->sp.p_name = (char *)GKI_getbuf((UINT16)(p_bta_mse_cfg->max_name_len + 1)); + if (p_cb->sp.p_name != NULL ) + { + p_cb->sp.flags = flags; + + if (!OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->sp.p_name, + p_bta_fs_cfg->max_path_len)) + { + p_cb->sp.p_name[0] = '\0'; + } + + rsp_code = bta_mse_chdir( inst_idx, sess_idx, &mse_oper); + + } + else + { + rsp_code = OBX_RSP_INTRNL_SRVR_ERR; + } + } + + bta_mse_set_ma_oper(inst_idx, sess_idx, mse_oper); + if (mse_oper != BTA_MSE_OPER_NONE) + { + bta_mse_req_app_access( inst_idx, sess_idx, p_data); + } + else + { + OBX_SetPathRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL); + utl_freebuf((void**)&p_cb->sp.p_name); + } + + /* Done with Obex packet */ + utl_freebuf((void**)&p_evt->p_pkt); +} +/******************************************************************************* +** +** Function bta_mse_ma_conn_err_rsp +** +** Description Proceses the inavlid obx connection request +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_conn_err_rsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_conn_err_rsp inst idx=%d sess idx=%d",inst_idx, sess_idx); +#endif + + OBX_ConnectRsp(p_data->obx_evt.handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL); + /* Done with Obex packet */ + utl_freebuf((void**)&(p_data->obx_evt.p_pkt)); +} + +/******************************************************************************* +** +** Function bta_mse_ma_close_complete +** +** Description Proceses the connection close complete event. +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_close_complete(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + 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 cback_evt_data; + tBTA_MSE *p_cevt = &cback_evt_data; + UINT8 num_act_mas=0, num_act_sess=0, i; + tBTA_MA_STATUS clean_getput_status = BTA_MA_STATUS_OK; + UINT8 ccb_idx; + BD_ADDR bd_addr; +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ma_close_complete inst idx=%d sess idx=%d",inst_idx, sess_idx); +#endif + + + p_cb->cout_active = FALSE; + + if (p_cb->aborting) clean_getput_status = BTA_MA_STATUS_ABORTED; + bta_mse_clean_getput(inst_idx, sess_idx, clean_getput_status); + utl_freebuf((void**)&p_cb->p_workdir); + + /* inform role manager */ + + bta_mse_pm_conn_close(p_cb->bd_addr); + bdcpy(bd_addr, p_cb->bd_addr); + memset(p_cb->bd_addr, 0, BD_ADDR_LEN); + p_cb->peer_mtu = 0; + + /* We now done with the close this seesion so issue a BTA_MSE_MA_CLOSE_EVT*/ + p_cevt->ma_close.mas_session_id = p_cb->obx_handle; + p_cevt->ma_close.mas_instance_id = p_scb->mas_inst_id; + p_cevt->ma_close.status = BTA_MA_STATUS_OK ; + bta_mse_cb.p_cback(BTA_MSE_MA_CLOSE_EVT, (tBTA_MSE *) p_cevt); + + + /* turn off the registration status for the associated MAs instance + and also check whether MN connection needs to be closed or not */ + if (bta_mse_find_bd_addr_match_mn_cb_index(bd_addr, &ccb_idx) && + bta_mse_mn_is_inst_id_exist(ccb_idx, p_scb->mas_inst_id)) + { + bta_mse_mn_remove_inst_id(ccb_idx, p_scb->mas_inst_id); + if (!bta_mse_mn_find_num_of_act_inst_id(ccb_idx)) + { + bta_mse_mn_sm_execute(ccb_idx,BTA_MSE_MN_INT_CLOSE_EVT, NULL); + } + } + + /* Check Any MAS instance need to be stopped */ +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("stopping=%d MAS in use=%d", p_scb->stopping,p_scb->in_use); +#endif + if (p_scb->stopping && p_scb->in_use) + { + num_act_sess = 0; + 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_LISTEN_ST) + num_act_sess++; + } +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("num_act_sess=%d ", num_act_sess); +#endif + if (!num_act_sess) + { + p_cevt->stop.status = BTA_MA_STATUS_OK; + p_cevt->stop.mas_instance_id = p_scb->mas_inst_id; + bta_mse_cb.p_cback(BTA_MSE_STOP_EVT, (tBTA_MSE *) p_cevt); + bta_mse_clean_mas_service(inst_idx); + } + } + + if (bta_mse_cb.disabling && bta_mse_cb.enable) + { + num_act_mas=0; + 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_cb.enable = FALSE; + p_cevt->disable.status = BTA_MA_STATUS_OK; + p_cevt->disable.app_id = bta_mse_cb.app_id; + bta_mse_cb.p_cback(BTA_MSE_DISABLE_EVT, (tBTA_MSE *) p_cevt); +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("MSE Disabled location-2"); +#endif + } + } +} + +/******************************************************************************* +** +** Function bta_mse_ignore_obx +** +** Description Ignores the obx event +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ignore_obx(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ignore_obx inst idx=%d sess idx=%d",inst_idx, sess_idx); +#endif + + utl_freebuf((void**)&p_data->obx_evt.p_pkt); +} +/******************************************************************************* +** +** Function bta_mse_ma_obx_cback +** +** Description OBX callback function for MA. +** +** Parameters handle - Handle for Obex session +** obx_event - Obex event +** param - event parameters +** p_pkt - pointer to Obex packet +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event, + tOBX_EVT_PARAM param, BT_HDR *p_pkt) +{ + tBTA_MSE_OBX_EVT *p_obx_msg; + UINT16 event = 0; + + switch (obx_event) + { + case OBX_CONNECT_REQ_EVT: + event = BTA_MSE_MA_OBX_CONN_EVT; + break; + case OBX_DISCONNECT_REQ_EVT: + event = BTA_MSE_MA_OBX_DISC_EVT; + break; + case OBX_PUT_REQ_EVT: + event = BTA_MSE_MA_OBX_PUT_EVT; + break; + case OBX_GET_REQ_EVT: + event = BTA_MSE_MA_OBX_GET_EVT; + break; + case OBX_SETPATH_REQ_EVT: + event = BTA_MSE_MA_OBX_SETPATH_EVT; + break; + case OBX_ABORT_REQ_EVT: + event = BTA_MSE_MA_OBX_ABORT_EVT; + break; + case OBX_CLOSE_IND_EVT: + event = BTA_MSE_MA_OBX_CLOSE_EVT; + break; + case OBX_TIMEOUT_EVT: + break; + case OBX_PASSWORD_EVT: + break; + default: + /* Unrecognized packet; disconnect the session */ + if (p_pkt) + event = BTA_MSE_MA_OBX_DISC_EVT; + } + + /* send event to BTA, if any */ + if (event && (p_obx_msg = + (tBTA_MSE_OBX_EVT *) GKI_getbuf(sizeof(tBTA_MSE_OBX_EVT))) != NULL) + { +#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE) + APPL_TRACE_DEBUG1("MA OBX Event Callback: mse_obx_event [%s]", bta_mse_obx_evt_code(event)); +#endif + p_obx_msg->hdr.event = event; + p_obx_msg->obx_event = obx_event; + p_obx_msg->handle = handle; + p_obx_msg->param = param; + p_obx_msg->p_pkt = p_pkt; + p_obx_msg->hdr.layer_specific = 0xFFFF; + + bta_sys_sendmsg(p_obx_msg); + } +} +/******************************************************************************* +** Message Notification Client (MNC) Action functions +** +*******************************************************************************/ +/****************************************************************************** +** +** Function bta_mse_mn_sdp_cback +** +** Description This is the SDP callback function used by MSE. +** This function will be executed by SDP when the service +** search is completed. If the search is successful, it +** finds the first record in the database that matches the +** UUID of the search. Then retrieves the scn from the +** record. +** +** Parameters ccb_idx - Index to the MN control block +** status - status of the SDP callabck +** +** Returns void. +** +******************************************************************************/ +static void bta_mse_mn_sdp_cback(UINT8 ccb_idx, UINT16 status) +{ + tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); + tBTA_MSE_MN_SDP_OK *p_buf; + tSDP_DISC_REC *p_rec = NULL; + tSDP_PROTOCOL_ELEM pe; + UINT8 scn = 0; + BOOLEAN found = FALSE; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("bta_mse_mn_sdp_cback status:%d", status); +#endif + if (status == SDP_SUCCESS || status == SDP_DB_FULL) + { + /* loop through all records we found */ + do + { + /* get next record; if none found, we're done */ + if ((p_rec = SDP_FindServiceInDb(p_cb->p_db, p_cb->sdp_service, + p_rec)) == NULL) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("SDP Not Found"); +#endif + break; + } + + /* get scn from proto desc list; if not found, go to next record */ + if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) + { + found = TRUE; + scn = (UINT8) pe.params[0]; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("SDP found scn=%d", scn); +#endif + /* we've got everything, we're done */ + break; + } + else + continue; + } while (TRUE); + } + + /* send result in event back to BTA */ + if ((p_buf = (tBTA_MSE_MN_SDP_OK *) GKI_getbuf(sizeof(tBTA_MSE_MN_SDP_OK))) != NULL) + { + p_buf->hdr.event = BTA_MSE_MN_SDP_FAIL_EVT; + p_buf->ccb_idx = ccb_idx; + if (status == SDP_SUCCESS || status == SDP_DB_FULL) + { + if (found == TRUE) + { + p_buf->hdr.event = BTA_MSE_MN_SDP_OK_EVT; + p_buf->scn = scn; + } + else + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("SDP 1 BTA_MSE_MN_SDP_FAIL_EVT"); +#endif + } + } + else + { + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("SDP 2 BTA_MSE_MN_SDP_FAIL_EVT"); +#endif + } + + bta_sys_sendmsg(p_buf); + } +} + +/****************************************************************************** +** +** Function bta_mse_mn_sdp_cback0 +** +** Description This is the SDP callback function used by MN indx = 0 +** +** Parameters status - status of the SDP callabck +** +** Returns void. +** +******************************************************************************/ +static void bta_mse_mn_sdp_cback0(UINT16 status) +{ + bta_mse_mn_sdp_cback(0, status); +} + +/****************************************************************************** +** +** Function bta_mse_mn_sdp_cback1 +** +** Description This is the SDP callback function used by MN indx = 1 +** +** Parameters status - status of the SDP callabck +** +** Returns void. +** +******************************************************************************/ +static void bta_mse_mn_sdp_cback1(UINT16 status) +{ + bta_mse_mn_sdp_cback(1, status); +} + +/****************************************************************************** +** +** Function bta_mse_mn_sdp_cback2 +** +** Description This is the SDP callback function used by MN indx = 2 +** +** Parameters status - status of the SDP callabck +** +** Returns void. +** +******************************************************************************/ +static void bta_mse_mn_sdp_cback2(UINT16 status) +{ + bta_mse_mn_sdp_cback(2, status); +} + +/****************************************************************************** +** +** Function bta_mse_mn_sdp_cback3 +** +** Description This is the SDP callback function used by MN indx = 3 +** +** Parameters status - status of the SDP callabck +** +** Returns void. +** +******************************************************************************/ +static void bta_mse_mn_sdp_cback3(UINT16 status) +{ + bta_mse_mn_sdp_cback(3, status); +} + +/****************************************************************************** +** +** Function bta_mse_mn_sdp_cback4 +** +** Description This is the SDP callback function used by MN indx = 4 +** +** Parameters status - status of the SDP callabck +** +** Returns void. +** +******************************************************************************/ +static void bta_mse_mn_sdp_cback4(UINT16 status) +{ + bta_mse_mn_sdp_cback(4, status); +} + +/****************************************************************************** +** +** Function bta_mse_mn_sdp_cback5 +** +** Description This is the SDP callback function used by MN indx = 5 +** +** Parameters status - status of the SDP callabck +** +** Returns void. +** +******************************************************************************/ +static void bta_mse_mn_sdp_cback5(UINT16 status) +{ + bta_mse_mn_sdp_cback(5, status); +} + +/****************************************************************************** +** +** Function bta_mse_mn_sdp_cback6 +** +** Description This is the SDP callback function used by MN indx = 6 +** +** Parameters status - status of the SDP callabck +** +** Returns void. +** +******************************************************************************/ +static void bta_mse_mn_sdp_cback6(UINT16 status) +{ + bta_mse_mn_sdp_cback(6, status); +} +/******************************************************************************* +** +** Function bta_mse_mn_init_sdp +** +** Description Initialize SDP on message notification server device. +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_init_sdp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_CB *p_cb = &(bta_mse_cb.ccb[ccb_idx]); + tBTA_MSE_MN_INT_OPEN *p_evt = &p_data->mn_int_open; + + tSDP_UUID uuid_list; + UINT16 attr_list[3]; + UINT16 num_attrs = 2; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("bta_mse_mn_init_sdp"); +#endif + + p_cb->in_use = TRUE; + p_cb->sec_mask = p_evt->sec_mask; + bdcpy(p_cb->bd_addr,p_evt->bd_addr); + p_cb->sdp_pending = TRUE; + p_cb->sdp_cback = bta_mse_mn_sdp_cback_arr[ccb_idx]; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT6("SDP INIT BD_ADDR= %x:%x:%x:%x:%x:%x", + p_cb->bd_addr[0], + p_cb->bd_addr[1], + p_cb->bd_addr[2], + p_cb->bd_addr[3], + p_cb->bd_addr[4], + p_cb->bd_addr[5]); +#endif + + if ((p_cb->p_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_MSE_MN_DISC_SIZE)) != NULL) + { + attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST; + attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST; + + uuid_list.len = LEN_UUID_16; + + p_cb->sdp_service = UUID_SERVCLASS_MESSAGE_NOTIFICATION; + uuid_list.uu.uuid16 = UUID_SERVCLASS_MESSAGE_NOTIFICATION; + + SDP_InitDiscoveryDb(p_cb->p_db, BTA_MSE_MN_DISC_SIZE, 1, &uuid_list, num_attrs, attr_list); + if (!SDP_ServiceSearchAttributeRequest(p_cb->bd_addr, p_cb->p_db, p_cb->sdp_cback)) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("SDP Init failed "); +#endif + bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_SDP_FAIL_EVT, p_data); + } + else + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("SDP Init Success "); +#endif + } + } +} + +/******************************************************************************* +** +** Function bta_mse_mn_start_client +** +** Description Starts the OBEX client for Message Notification service. +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_start_client(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + + tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); + tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx; + BOOLEAN connect_fail = TRUE; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("bta_mse_mn_start_client ccb idx=%d ",ccb_idx); +#endif + + /* free discovery data base */ + utl_freebuf((void**)&p_cb->p_db); + p_cb->sdp_pending = FALSE; + /* Allocate an OBX packet */ + if ((p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(OBX_HANDLE_NULL, OBX_CMD_POOL_SIZE)) != NULL) + { + /* set security level */ + BTM_SetSecurityLevel (TRUE, "BTA_MNC", BTM_SEC_SERVICE_MAP, + p_cb->sec_mask, BT_PSM_RFCOMM, + BTM_SEC_PROTO_RFCOMM, p_data->mn_sdp_ok.scn); + + if (p_cb->sdp_service == UUID_SERVCLASS_MESSAGE_NOTIFICATION) + { + OBX_AddTargetHdr(p_obx->p_pkt, (UINT8 *)BTA_MAS_MESSAGE_NOTIFICATION_TARGET_UUID, + BTA_MAS_UUID_LENGTH); + } + if (OBX_ConnectReq(p_cb->bd_addr, p_data->mn_sdp_ok.scn, OBX_MAX_MTU, + bta_mse_mn_obx_cback, &p_cb->obx_handle, p_obx->p_pkt) == OBX_SUCCESS) + { + p_obx->p_pkt = NULL; /* OBX will free the memory */ + connect_fail = FALSE; + } + else + { + utl_freebuf((void**)&p_obx->p_pkt); + } + } + + if (connect_fail) + { + bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_OBX_CLOSE_EVT, p_data); + } +} + +/******************************************************************************* +** +** Function bta_mse_mn_rsp_timeout +** +** Description Process the OBX response timeout event +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_rsp_timeout(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); + + if (p_cb->timer_oper == BTA_MSE_TIMER_OP_ABORT) + { + /* Start stop response timer */ + bta_mse_mn_start_timer(ccb_idx, BTA_MSE_TIMER_OP_STOP); + + OBX_DisconnectReq(p_cb->obx_handle, NULL); + } + else /* Timeout waiting for disconnect response */ + { + bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_OBX_CLOSE_EVT, p_data); + + } +} +/******************************************************************************* +** +** Function bta_mse_mn_stop_client +** +** Description Stop the OBX client for Message Notification service. +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_stop_client(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); + + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("bta_mse_mn_stop_client ccb idx=%d ",ccb_idx); +#endif + + if (!p_cb->sdp_pending) + { + /* Start stop response timer */ + bta_mse_mn_start_timer(ccb_idx, BTA_MSE_TIMER_OP_STOP); + OBX_DisconnectReq(p_cb->obx_handle, NULL); + } + else + { + APPL_TRACE_WARNING0("bta_mase_mn_stop_client: Waiting for SDP to complete"); + } +} +/******************************************************************************* +** +** Function bta_mse_mn_obx_conn_rsp +** +** Description Process OBX connection response. +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_obx_conn_rsp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); + tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt; + tBTA_MSE param; + UINT8 mas_insatnce_id; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("bta_mse_mn_obx_conn_rsp ccb idx=%d ",ccb_idx); +#endif + + p_cb->peer_mtu = p_data->obx_evt.param.conn.mtu; + p_cb->obx_handle = p_evt->handle; + + if (p_cb->sdp_service == UUID_SERVCLASS_MESSAGE_NOTIFICATION) + { + bdcpy(param.mn_open.bd_addr ,p_cb->bd_addr); + BCM_STRNCPY_S((char *)param.mn_open.dev_name, sizeof(param.mn_open.dev_name), "", + BTM_MAX_REM_BD_NAME_LEN); + if (bta_mse_mn_get_first_inst_id(ccb_idx, &mas_insatnce_id)) + { + param.mn_open.first_mas_instance_id = mas_insatnce_id; + } + else + { + APPL_TRACE_ERROR0("Unable to find the first instance ID"); + } + } + + /* inform role manager */ + bta_mse_pm_conn_open(p_cb->bd_addr); + + bta_mse_cb.p_cback(BTA_MSE_MN_OPEN_EVT, ¶m); + + /* Done with Obex packet */ + utl_freebuf((void**)&p_evt->p_pkt); +} +/******************************************************************************* +** +** Function bta_mse_mn_close +** +** Description Process the connection close event. +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_close(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); + + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("bta_mse_mn_close ccb idx=%d ",ccb_idx); +#endif + + bta_mse_mn_remove_all_inst_ids(ccb_idx); + + /* finished if not waiting on a call-in function */ + if (!p_cb->sdp_pending && !p_cb->cout_active) + bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_CLOSE_CMPL_EVT, p_data); +} +/******************************************************************************* +** +** Function bta_mse_mn_send_notif +** +** Description Process send notification request +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_send_notif(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); + tBTA_MSE_MN_API_SEND_NOTIF *p_evt = &p_data->mn_send_notif; + UINT8 *p_buffer; + UINT16 buffer_len; + tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL; + + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("bta_mse_mn_send_notif ccb_idx=%d ",ccb_idx); +#endif + + if ( (p_cb->req_pending == TRUE) && + (p_cb->obx_oper == BTA_MSE_MN_OP_PUT_EVT_RPT)) + { + /* only one pending request per Obex connection is allowed */ + bta_mse_mn_send_notif_evt(p_evt->mas_instance_id, + BTA_MA_STATUS_NO_RESOURCE, + p_cb->bd_addr); + return; + } + + memset(&(p_cb->msg_notif), 0, sizeof(tBTA_MSE_MN_MSG_NOTIF)); + + if ((p_buffer = (UINT8 *)GKI_getbuf(BTA_MSE_MN_MAX_MSG_EVT_OBECT_SIZE)) != NULL) + { + /* Build the Message Event Object */ + buffer_len = BTA_MSE_MN_MAX_MSG_EVT_OBECT_SIZE; + status = bta_mse_build_map_event_rpt_obj( p_evt->notif_type, + p_evt->handle, + p_evt->p_folder, + p_evt->p_old_folder, + p_evt->msg_type, + &buffer_len, + p_buffer); + if (status == BTA_MA_STATUS_OK) + { + p_cb->msg_notif.p_buffer = p_buffer; + p_cb->msg_notif.buffer_len = buffer_len; + p_cb->msg_notif.bytes_sent = 0; + p_cb->msg_notif.mas_instance_id = p_evt->mas_instance_id; + status = bta_mse_mn_cont_send_notif(ccb_idx, TRUE); + } + } + + if ( status != BTA_MA_STATUS_OK) + { + bta_mse_mn_send_notif_evt(p_evt->mas_instance_id, + BTA_MA_STATUS_NO_RESOURCE, + p_cb->bd_addr); + bta_mse_mn_clean_send_notif(ccb_idx); + } + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("status=%d ",status ); +#endif +} +/******************************************************************************* +** +** Function bta_mse_mn_put_rsp +** +** Description Process the obx PUT response. +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_put_rsp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); + tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt; + tBTA_MSE_MN_MSG_NOTIF *p_msg_notif = &p_cb->msg_notif; + tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_mn_put_rsp ccb idx=%d rsp_code=%d", + ccb_idx, p_evt->rsp_code); +#endif + + p_cb->req_pending = FALSE; + /* Done with Obex packet */ + utl_freebuf((void**)&p_evt->p_pkt); + + if (p_cb->obx_oper == BTA_MSE_MN_OP_PUT_EVT_RPT) + { + /* If not finished with Put, start another read */ + if (p_evt->rsp_code == OBX_RSP_CONTINUE) + bta_mse_mn_cont_send_notif(ccb_idx, FALSE); + else + { + /* done with obex operation */ + if ( p_evt->rsp_code == OBX_RSP_OK ) status = BTA_MA_STATUS_OK; + bta_mse_mn_send_notif_evt(p_msg_notif->mas_instance_id, status, + p_cb->bd_addr); + bta_mse_mn_clean_send_notif(ccb_idx); + } + } +} +/******************************************************************************* +** +** Function bta_mse_mn_close_compl +** +** Description Process the close complete event. +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_close_compl(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); + tBTA_MSE param; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("bta_mse_mn_close_compl ccb idx=%d ",ccb_idx); +#endif + + /* free discovery data base */ + utl_freebuf((void**)&p_cb->p_db); + p_cb->sdp_pending = FALSE; + + p_cb->cout_active = FALSE; + bta_mse_mn_stop_timer(ccb_idx, BTA_MSE_TIMER_OP_ALL); + bta_mse_mn_clean_send_notif(ccb_idx); + /* inform role manager */ + bta_mse_pm_conn_close(p_cb->bd_addr); + bdcpy(param.mn_close.bd_addr ,p_cb->bd_addr); + bta_mse_cb.p_cback(BTA_MSE_MN_CLOSE_EVT, ¶m); + memset(p_cb, 0 , sizeof(tBTA_MSE_MN_CB)); +} + +/******************************************************************************* +** +** Function bta_mse_mn_abort +** +** Description Process the abort event. +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_abort(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("bta_mse_mn_abort ccb idx=%d ",ccb_idx); +#endif + /* Abort an active request */ + if (p_cb->obx_oper != BTA_MSE_MN_OP_NONE) + { + p_cb->aborting = BTA_MSE_MN_ABORT_REQ_NOT_SENT; + + /* Issue the abort request only if no request pending. + * some devices do not like out of sequence aborts even though + * the spec allows it */ + if (!p_cb->req_pending) + { + /* Start abort response timer */ + 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_abort_rsp +** +** Description Process the abort response event. +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_abort_rsp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); + tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt; + tBTA_MSE_MN_MSG_NOTIF *p_msg_notif = &p_cb->msg_notif; + tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL; + + + bta_mse_mn_stop_timer(ccb_idx,BTA_MSE_TIMER_OP_ABORT); + + /* Done with Obex packet */ + utl_freebuf((void**)&p_evt->p_pkt); + + if (p_cb->obx_oper != BTA_MSE_MN_OP_NONE) + { + if (p_cb->obx_oper == BTA_MSE_MN_OP_PUT_EVT_RPT ) + { + bta_mse_mn_send_notif_evt(p_msg_notif->mas_instance_id, status, + p_cb->bd_addr); + bta_mse_mn_clean_send_notif(ccb_idx); + } + } +} + +/******************************************************************************* +** +** Function bta_mse_mn_sdp_fail +** +** Description Process the SDP fail event. +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_sdp_fail(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("bta_mse_mn_sdp_fail ccb idx=%d ",ccb_idx); +#endif + /* free discovery data base */ + utl_freebuf((void**)&p_cb->p_db); + p_cb->sdp_pending = FALSE; + bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_OBX_CLOSE_EVT, p_data); +} + +/******************************************************************************* +** +** Function bta_mse_mn_obx_tout +** +** Description Process the obx timeout event. +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_obx_tout(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx); + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("bta_mse_mn_obx_tout ccb idx=%d ",ccb_idx); +#endif + + if (p_cb->req_pending) + { + if (p_cb->obx_oper == BTA_MSE_MN_OP_PUT_EVT_RPT) + { + bta_mse_mn_send_notif_evt( p_cb->msg_notif.mas_instance_id, + BTA_MA_STATUS_FAIL, + p_cb->bd_addr); + bta_mse_mn_clean_send_notif(ccb_idx); + } + } +} +/******************************************************************************* +** +** Function bta_mse_mn_ignore_obx +** +** Description Ignore OBX event. +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_ignore_obx(UINT8 ccb_idx, tBTA_MSE_DATA *p_data) +{ + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("bta_mse_mn_ignore_obx ccb idx=%d ",ccb_idx); +#endif + + utl_freebuf((void **) &p_data->obx_evt.p_pkt); +} + + + +/***************************************************************************** +** MNC Callback Functions +*****************************************************************************/ + +/******************************************************************************* +** +** Function bta_mse_mn_obx_cback +** +** Description OBX callback function. +** +** Parameters handle - Handle for Obex session +** obx_event - Obex event +** rsp_code - Obex response code +** param - event parameters +** p_pkt - pointer to Obex packet +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event, UINT8 rsp_code, + tOBX_EVT_PARAM param, BT_HDR *p_pkt) +{ + tBTA_MSE_OBX_EVT *p_obx_msg; + UINT16 event = 0; + + + + switch (obx_event) + { + case OBX_CONNECT_RSP_EVT: + if (rsp_code == OBX_RSP_OK) + { + event = BTA_MSE_MN_OBX_CONN_RSP_EVT; + } + else /* Obex will disconnect underneath BTA */ + { + APPL_TRACE_WARNING1("MN_OBX_CBACK: Bad connect response 0x%02x", rsp_code); + if (p_pkt) + GKI_freebuf(p_pkt); + return; + } + break; + case OBX_PUT_RSP_EVT: + event = BTA_MSE_MN_OBX_PUT_RSP_EVT; + break; + case OBX_CLOSE_IND_EVT: + event = BTA_MSE_MN_OBX_CLOSE_EVT; + break; + case OBX_TIMEOUT_EVT: + event = BTA_MSE_MN_OBX_TOUT_EVT; + break; + case OBX_ABORT_RSP_EVT: + event = BTA_MSE_MN_OBX_ABORT_RSP_EVT; + break; + case OBX_PASSWORD_EVT: + case OBX_GET_RSP_EVT: + case OBX_SETPATH_RSP_EVT: + default: + /* case OBX_DISCONNECT_RSP_EVT: Handled when OBX_CLOSE_IND_EVT arrives */ + if (p_pkt) + GKI_freebuf(p_pkt); + return; + } + + + + if (event && (p_obx_msg = + (tBTA_MSE_OBX_EVT *) GKI_getbuf(sizeof(tBTA_MSE_OBX_EVT))) != NULL) + { +#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE) + APPL_TRACE_DEBUG1("MN OBX Event Callback: mn_obx_event [%s]", + bta_mse_obx_evt_code(event)); +#endif + /* send event to BTA, if any */ + p_obx_msg->hdr.event = event; + p_obx_msg->hdr.layer_specific = 0xFFFF; /* not used */ + p_obx_msg->obx_event = obx_event; + p_obx_msg->handle = handle; + p_obx_msg->rsp_code = rsp_code; + p_obx_msg->param = param; + p_obx_msg->p_pkt = p_pkt; + + bta_sys_sendmsg(p_obx_msg); + } +} + + +/***************************************************************************** +** Local MSE Event Processing Functions +*****************************************************************************/ + +/******************************************************************************* +** +** Function bta_mse_req_app_access +** +** Description Sends an access request event to the application. +** +** Parameters ccb_idx - Index to the MN control block +** p_data - Pointer to the MN event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_req_app_access (UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx); + tBTA_MSE_ACCESS *p_acc_evt; + char *p_devname; + + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_req_app_access inst idx=%d sess idx=%d", + inst_idx, sess_idx); +#endif + + /* Ask application for the operation's access permission */ + if ((p_acc_evt = (tBTA_MSE_ACCESS *)GKI_getbuf((UINT16) (sizeof(tBTA_MSE_ACCESS)+ + (p_bta_fs_cfg->max_path_len + 1)))) != NULL) + { + memset(p_acc_evt, 0, sizeof(tBTA_MSE_ACCESS)); + p_acc_evt->p_path = (char *) (p_acc_evt+1); + p_acc_evt->p_path[0]='\0'; + + APPL_TRACE_API1("MSE ACCESS REQ: Oper=%d", p_cb->oper); + switch (p_cb->oper) + { + case BTA_MSE_OPER_SETPATH: + BCM_STRNCPY_S(p_acc_evt->p_path, p_bta_fs_cfg->max_path_len+1, + p_cb->sp.p_path, p_bta_fs_cfg->max_path_len); + break; + + case BTA_MSE_OPER_GET_MSG_LIST: + BCM_STRNCPY_S(p_acc_evt->p_path, p_bta_fs_cfg->max_path_len+1, + p_cb->ml_param.p_path, p_bta_fs_cfg->max_path_len); + break; + + case BTA_MSE_OPER_GET_MSG: + memcpy(p_acc_evt->handle, p_cb->msg_param.data.handle, + sizeof(tBTA_MA_MSG_HANDLE)); + break; + case BTA_MSE_OPER_PUSH_MSG: + memset(p_acc_evt->handle, 0, sizeof(tBTA_MA_MSG_HANDLE)); + BCM_STRNCPY_S(p_acc_evt->p_path, p_bta_fs_cfg->max_path_len+1, + p_cb->push_msg.param.p_folder, p_bta_fs_cfg->max_path_len); + break; + case BTA_MSE_OPER_DEL_MSG: + memcpy(p_acc_evt->handle, p_cb->set_msg_sts.handle, + sizeof(tBTA_MA_MSG_HANDLE)); + p_acc_evt->delete_sts = p_cb->set_msg_sts.sts_val; + break; + default: + break; + } + + p_acc_evt->oper = p_cb->oper; + p_acc_evt->mas_session_id = (tBTA_MA_SESS_HANDLE) p_cb->obx_handle; + bdcpy(p_acc_evt->bd_addr, p_cb->bd_addr); + if ((p_devname = BTM_SecReadDevName(p_cb->bd_addr)) != NULL) + BCM_STRNCPY_S((char *)p_acc_evt->dev_name, sizeof(p_acc_evt->dev_name), p_devname, BTM_MAX_REM_BD_NAME_LEN); + + bta_mse_cb.p_cback(BTA_MSE_ACCESS_EVT, (tBTA_MSE *)p_acc_evt); + GKI_freebuf(p_acc_evt); + } +} + +/***************************************************************************** +** Debug Functions +*****************************************************************************/ +#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE) + +/******************************************************************************* +** +** Function bta_mse_obx_evt_code +** +** Description get the obx event string pointer +** +** Parameters evt_code - obex event code +** +** Returns char * - event string pointer +** +*******************************************************************************/ +static char *bta_mse_obx_evt_code(UINT16 evt_code) +{ + switch (evt_code) + { + case BTA_MSE_MA_OBX_CONN_EVT: + return "BTA_MSE_MA_OBX_CONN_EVT"; + case BTA_MSE_MA_OBX_DISC_EVT: + return "BTA_MSE_MA_OBX_DISC_EVT"; + case BTA_MSE_MA_OBX_PUT_EVT: + return "BTA_MSE_MA_OBX_PUT_EVT"; + case BTA_MSE_MA_OBX_GET_EVT: + return "BTA_MSE_MA_OBX_GET_EVT"; + case BTA_MSE_MA_OBX_SETPATH_EVT: + return "BTA_MSE_MA_OBX_SETPATH_EVT"; + case BTA_MSE_MA_OBX_ABORT_EVT: + return "BTA_MSE_MA_OBX_ABORT_EVT"; + case BTA_MSE_MA_OBX_CLOSE_EVT: + return "BTA_MSE_MA_OBX_CLOSE_EVT"; + case BTA_MSE_MN_OBX_TOUT_EVT: + return "BTA_MSE_MN_OBX_TOUT_EVT"; + case BTA_MSE_MN_OBX_CONN_RSP_EVT: + return "BTA_MSE_MN_OBX_CONN_RSP_EVT"; + case BTA_MSE_MN_OBX_PUT_RSP_EVT: + return "BTA_MSE_MN_OBX_PUT_RSP_EVT"; + case BTA_MSE_MN_OBX_CLOSE_EVT: + return "BTA_MSE_MN_OBX_CLOSE_EVT"; + case BTA_MSE_MN_OBX_ABORT_RSP_EVT: + return"BTA_MSE_MN_OBX_ABORT_RSP_EVT"; + default: + return "unknown MSE OBX event code"; + } +} +#endif /* Debug Functions */ + + + + + + + + + + + + + + + +#endif /* BTA_MSE_INCLUDED */ diff --git a/bta/ma/bta_mse_api.c b/bta/ma/bta_mse_api.c new file mode 100644 index 0000000..5a2fd29 --- /dev/null +++ b/bta/ma/bta_mse_api.c @@ -0,0 +1,437 @@ +/***************************************************************************** +** +** Name: bta_mse_api.c +** +** Description: This is the implementation of the API for the Message +** Acess Server subsystem of BTA, Broadcom Corp's Bluetooth +** application layer for mobile phones. +** +** Copyright (c) 2009-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 <string.h> +#include "gki.h" +#include "bd.h" +#include "bta_ma_def.h" +#include "bta_mse_api.h" +#include "bta_fs_api.h" +#include "bta_mse_int.h" + +/***************************************************************************** +** Constants +*****************************************************************************/ +static const tBTA_SYS_REG bta_mse_reg = +{ + bta_mse_hdl_event, + BTA_MseDisable +}; + +/******************************************************************************* +** +** Function BTA_MseEnable +** +** Description Enable the MSE subsystems. This function must be +** called before any other functions in the MSE API are called. +** When the enable operation is completed the callback function +** will be called with an BTA_MSE_ENABLE_EVT event. +** +** Parameters p_cback - MSE event call back function +** app_id - Application ID +** +** Returns void +** +*******************************************************************************/ +void BTA_MseEnable(tBTA_MSE_CBACK *p_cback, UINT8 app_id) +{ + tBTA_MSE_API_ENABLE *p_buf; + + /* register with BTA system manager */ + GKI_sched_lock(); + bta_sys_register(BTA_ID_MSE, &bta_mse_reg); + GKI_sched_unlock(); + + if ((p_buf = (tBTA_MSE_API_ENABLE *)GKI_getbuf(sizeof(tBTA_MSE_API_ENABLE))) != NULL) + { + p_buf->hdr.event = BTA_MSE_API_ENABLE_EVT; + p_buf->p_cback = p_cback; + p_buf->app_id = app_id; + + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_MseDisable +** +** Description Disable the MSE subsystem. +** +** Returns void +** +*******************************************************************************/ +void BTA_MseDisable(void) +{ + BT_HDR *p_buf; + + bta_sys_deregister(BTA_ID_MSE); + if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_buf->event = BTA_MSE_API_DISABLE_EVT; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_MseStart +** +** Description Start a MA server on the MSE +** +** +** Parameters mas_inst_id - MAS instance ID +** sec_mask - Security Setting Mask +** MSE always enables +** (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT) +** p_service_name - Pointer to service name +** p_root_path - Pointer to root path +** (one level above telecom) +** sup_msg_type - supported message type(s) +** +** Returns void +** +*******************************************************************************/ +void BTA_MseStart( tBTA_MA_INST_ID mas_inst_id, + tBTA_SEC sec_mask, const char *p_service_name, + const char *p_root_path, + tBTA_MA_MSG_TYPE sup_msg_type) +{ + tBTA_MSE_API_START *p_buf; + + if ((p_buf = (tBTA_MSE_API_START *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_START) + + p_bta_fs_cfg->max_path_len + 1))) != NULL) + { + p_buf->p_root_path = (char *)(p_buf + 1); + p_buf->hdr.event = BTA_MSE_API_START_EVT; + p_buf->mas_inst_id = mas_inst_id; + p_buf->sec_mask = (sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT); + p_buf->sup_msg_type = sup_msg_type; + + + if (p_service_name) + { + BCM_STRNCPY_S(p_buf->servicename, sizeof(p_buf->servicename), p_service_name, BTA_SERVICE_NAME_LEN); + p_buf->servicename[BTA_SERVICE_NAME_LEN] = '\0'; + } + else + p_buf->servicename[0]= '\0'; + + if (p_root_path) + { + BCM_STRNCPY_S(p_buf->p_root_path, p_bta_fs_cfg->max_path_len+1, p_root_path, p_bta_fs_cfg->max_path_len); + p_buf->p_root_path[p_bta_fs_cfg->max_path_len] = '\0'; + } + else + p_buf->p_root_path[0] = '\0'; + + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_MseStop +** +** Description Stop a MA server on the MSE +** +** Parameters mas_instance_id - MAS Instance ID +** +** Returns void +** +*******************************************************************************/ +void BTA_MseStop (tBTA_MA_INST_ID mas_instance_id) +{ + tBTA_MSE_API_STOP *p_buf; + + if ((p_buf = (tBTA_MSE_API_STOP *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_STOP)))) != NULL) + { + p_buf->hdr.event = BTA_MSE_API_STOP_EVT; + p_buf->mas_inst_id = mas_instance_id; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_MseClose +** +** Description Close all MAS sessions on the specified MAS Instance ID +** +** Parameters mas_instance_id - MAS Inatance ID +** +** Returns void +** +*******************************************************************************/ +void BTA_MseClose(tBTA_MA_INST_ID mas_instance_id) +{ + + tBTA_MSE_API_CLOSE *p_buf; + + if ((p_buf = (tBTA_MSE_API_CLOSE *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_CLOSE)))) != NULL) + { + p_buf->hdr.event = BTA_MSE_API_CLOSE_EVT; + p_buf->mas_instance_id = mas_instance_id; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_MseMaClose +** +** Description Close a MAS sessions on the specified BD address +** +** Parameters bd_addr - remote BD's address +** mas_instance_id - MAS Inatance ID +** +** Returns void +** +*******************************************************************************/ +void BTA_MseMaClose(BD_ADDR bd_addr, tBTA_MA_INST_ID mas_instance_id) +{ + tBTA_MSE_API_MA_CLOSE *p_buf; + + if ((p_buf = (tBTA_MSE_API_MA_CLOSE *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_MA_CLOSE)))) != NULL) + { + memset(p_buf, 0, sizeof(tBTA_MSE_API_MA_CLOSE)); + + p_buf->hdr.event = BTA_MSE_API_MA_CLOSE_EVT; + bdcpy(p_buf->bd_addr, bd_addr); + p_buf->mas_instance_id = mas_instance_id; + bta_sys_sendmsg(p_buf); + } +} +/******************************************************************************* +** +** Function BTA_MseMnClose +** +** Description Close a MN session +** +** Parameters bd_addr - remote BD's address +** +** Returns void +** +*******************************************************************************/ +void BTA_MseMnClose(BD_ADDR bd_addr) +{ + tBTA_MSE_API_MN_CLOSE *p_buf; + + if ((p_buf = (tBTA_MSE_API_MN_CLOSE *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_MN_CLOSE)))) != NULL) + { + p_buf->hdr.event = BTA_MSE_API_MN_CLOSE_EVT; + bdcpy(p_buf->bd_addr, bd_addr); + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_MseAccessRsp +** +** Description Send a response for the access request +** +** Parameters mas_session_id - MAS session ID +** oper - MAS operation type +** access - Access is allowed or not +** p_path - pointer to a path if if the operation +** involves accessing a folder +** Returns void +** +*******************************************************************************/ +void BTA_MseAccessRsp(tBTA_MA_SESS_HANDLE mas_session_id, tBTA_MSE_OPER oper, + tBTA_MA_ACCESS_TYPE access, char *p_path) +{ + tBTA_MSE_API_ACCESSRSP *p_acc_rsp; + UINT16 path_len; + + /* If directory is specified set the length */ + path_len = (p_path && *p_path != '\0') ? (UINT16)(strlen(p_path) + 1): 1; + + if ((p_acc_rsp = (tBTA_MSE_API_ACCESSRSP *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_ACCESSRSP) + + path_len))) != NULL) + { + p_acc_rsp->mas_session_id = mas_session_id; + p_acc_rsp->rsp = access; + p_acc_rsp->oper = oper; + p_acc_rsp->p_path = (char *)(p_acc_rsp + 1); + if (p_path) + { + BCM_STRNCPY_S(p_acc_rsp->p_path, path_len, p_path, path_len-1); + p_acc_rsp->p_path[path_len-1] = '\0'; + } + else + p_acc_rsp->p_path[0] = '\0'; + + p_acc_rsp->hdr.event = BTA_MSE_API_ACCESSRSP_EVT; + bta_sys_sendmsg(p_acc_rsp); + } +} +/******************************************************************************* +** +** Function BTA_MseUpdateInboxRsp +** +** Description Send a response for the update inbox request +** +** +** Parameters mas_session_id - MAS session ID +** update_rsp - update inbox is allowed or not +** +** Returns void +** +*******************************************************************************/ +void BTA_MseUpdateInboxRsp(tBTA_MA_SESS_HANDLE mas_session_id, + tBTA_MSE_UPDATE_INBOX_TYPE update_rsp) +{ + tBTA_MSE_API_UPDINBRSP *p_buf; + + if ((p_buf = (tBTA_MSE_API_UPDINBRSP *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_UPDINBRSP)))) != NULL) + { + p_buf->hdr.event = BTA_MSE_API_UPD_IBX_RSP_EVT; + p_buf->mas_session_id = mas_session_id; + p_buf->rsp = update_rsp; + bta_sys_sendmsg(p_buf); + } +} +/******************************************************************************* +** +** Function BTA_MseSetNotifRegRsp +** +** Description Send a response for the set notification registration +** +** +** Parameters mas_session_id - MAS session ID +** set_notif_reg_rsp - indicate whether the set notification +** registration is allowed or not +** +** Returns void +** +*******************************************************************************/ +void BTA_MseSetNotifRegRsp(tBTA_MA_SESS_HANDLE mas_session_id, + tBTA_MSE_SET_NOTIF_REG_TYPE set_notif_reg_rsp) +{ + tBTA_MSE_API_SETNOTIFREGRSP *p_buf; + + if ((p_buf = (tBTA_MSE_API_SETNOTIFREGRSP *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_UPDINBRSP)))) != NULL) + { + p_buf->hdr.event = BTA_MSE_API_SET_NOTIF_REG_RSP_EVT; + p_buf->mas_session_id = mas_session_id; + p_buf->rsp = set_notif_reg_rsp; + bta_sys_sendmsg(p_buf); + } +} +/******************************************************************************* +** +** Function BTA_MseSendNotif +** +** Description Send a Message notification report to all MCEs registered with +** the specified MAS instance ID +** +** Parameters mas_instance_id - MAS Instance ID +** notif_type - message notification type +** handle - message handle +** p_folder - pointer to current folder +** p_old_folder - pointer to older folder +** msg_type - message type (E_MAIL, SMS_GSM, SMS_CDMA, MMS) +** except_bd_addr - except to the MCE on this BD Address. +** (Note: notification will be not sent to +** this BD Addreess) +** +** Returns void +** +*******************************************************************************/ +void BTA_MseSendNotif(tBTA_MA_INST_ID mas_instance_id, + tBTA_MSE_NOTIF_TYPE notif_type, + tBTA_MA_MSG_HANDLE handle, + char * p_folder, char *p_old_folder, + tBTA_MA_MSG_TYPE msg_type, + BD_ADDR except_bd_addr) +{ + tBTA_MSE_MN_API_SEND_NOTIF *p_buf; + UINT16 folder_len, old_folder_len; + + /* If directory is specified set the length */ + folder_len = (p_folder && *p_folder != '\0') ? (UINT16)(strlen(p_folder) + 1): 0; + old_folder_len = (p_old_folder && *p_old_folder != '\0') ? (UINT16)(strlen(p_old_folder) + 1): 0; + + if ((p_buf = (tBTA_MSE_MN_API_SEND_NOTIF *)GKI_getbuf((UINT16) ((UINT16)sizeof(tBTA_MSE_MN_API_SEND_NOTIF) + + folder_len + + old_folder_len))) != NULL) + { + p_buf->hdr.event = BTA_MSE_API_SEND_NOTIF_EVT; + p_buf->mas_instance_id = mas_instance_id; + p_buf->notif_type = notif_type; + memcpy(p_buf->handle, handle, sizeof(tBTA_MA_MSG_HANDLE)); + + if (folder_len) + { + p_buf->p_folder = (char *)(p_buf + 1); + BCM_STRNCPY_S(p_buf->p_folder, folder_len+1, p_folder, folder_len); + } + else + p_buf->p_folder = NULL; + + if (old_folder_len) + { + if (folder_len) + p_buf->p_old_folder = p_buf->p_folder + folder_len; + else + p_buf->p_old_folder = (char *)(p_buf + 1); + + BCM_STRNCPY_S(p_buf->p_old_folder, old_folder_len+1, p_old_folder, old_folder_len); + } + else + p_buf->p_old_folder = NULL; + + p_buf->msg_type = msg_type; + if (except_bd_addr != NULL) + { + bdcpy(p_buf->except_bd_addr, except_bd_addr); + } + else + { + memset(p_buf->except_bd_addr, 0, sizeof(BD_ADDR)); + } + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_MseMnAbort +** +** Description Abort the current OBEX multi-packt operation in MN +** +** Parameters mas_instance_id - MAS Instance ID +** +** Returns void +** +*******************************************************************************/ +void BTA_MseMnAbort(tBTA_MA_INST_ID mas_instance_id) +{ + tBTA_MSE_MN_API_ABORT *p_buf; + + if ((p_buf = (tBTA_MSE_MN_API_ABORT *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_MN_API_ABORT)))) != NULL) + { + p_buf->hdr.event = BTA_MSE_API_MN_ABORT_EVT; + p_buf->mas_instance_id = mas_instance_id; + bta_sys_sendmsg(p_buf); + } +} + + +#endif /* BTA_MSE_INCLUDED */ diff --git a/bta/ma/bta_mse_cfg.c b/bta/ma/bta_mse_cfg.c new file mode 100644 index 0000000..69953d0 --- /dev/null +++ b/bta/ma/bta_mse_cfg.c @@ -0,0 +1,31 @@ +/***************************************************************************** +** +** Name: bta_mse_cfg.c +** +** Description: This file contains compile-time configurable constants +** for the MSE subsystem. +** +** Copyright (c) 2009, Broadcom Corp., All Rights Reserved. +** Broadcom Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include "bta_mse_api.h" + +#ifndef BTA_MSE_MAX_NAME_LEN + #define BTA_MSE_MAX_NAME_LEN 256 +#endif + +#ifndef BTA_MSE_OBX_RSP_TOUT + #define BTA_MSE_OBX_RSP_TOUT 2000 +#endif + + +const tBTA_MSE_CFG bta_mse_cfg = +{ + BTA_MSE_OBX_RSP_TOUT, + BTA_MSE_MAX_NAME_LEN +}; + +tBTA_MSE_CFG *p_bta_mse_cfg = (tBTA_MSE_CFG *)&bta_mse_cfg; + diff --git a/bta/ma/bta_mse_ci.c b/bta/ma/bta_mse_ci.c new file mode 100644 index 0000000..dfaeb7e --- /dev/null +++ b/bta/ma/bta_mse_ci.c @@ -0,0 +1,251 @@ +/***************************************************************************** +** +** Name: bta_mse_ci.c +** +** Description: This is the implementaion for the Message Server Equipment +** (MSE) subsystem call-in functions. +** +** Copyright (c) 2009, Broadcom Corp., All Rights Reserved. +** Broadcom Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ +#include <stdio.h> +#include <string.h> +#include "bta_api.h" +#include "bta_ma_def.h" +#include "bta_mse_api.h" +#include "bta_mse_co.h" +#include "bta_mse_int.h" +#include "bta_mse_ci.h" + +/******************************************************************************* +** +** Function bta_mse_ci_get_folder_entry +** +** Description This function is called in response to the +** bta_mse_co_get_folder_entry call-out function. +** +** Parameters mas_session_id - MAS session ID +** status - BTA_MA_STATUS_OK if p_entry points to a valid entry. +** BTA_MA_STATUS_EODIR if no more entries (p_entry is ignored). +** BTA_MA_STATUS_FAIL if any errors have occurred. +** evt - evt from the call-out function +** +** Returns void +** +*******************************************************************************/ +BTA_API extern void bta_mse_ci_get_folder_entry(tBTA_MA_SESS_HANDLE mas_session_id, + tBTA_MA_STATUS status, + UINT16 evt) +{ + tBTA_MSE_CI_GET_FENTRY *p_evt; + + if ((p_evt = (tBTA_MSE_CI_GET_FENTRY *)GKI_getbuf(sizeof(tBTA_MSE_CI_GET_FENTRY))) != NULL) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ci_get_folder_entry sess_id=%d, status=%d \n", + mas_session_id, status); +#endif + p_evt->hdr.event = evt; + p_evt->mas_session_id = mas_session_id; + p_evt->status = status; + bta_sys_sendmsg(p_evt); + } +} +/******************************************************************************* +** +** Function bta_mse_ci_get_msg_list_info +** +** Description This function is called in response to the +** bta_mse_co_get_msg_list_info call-out function. +** +** Parameters mas_session_id - MAS session ID +** status - BTA_MA_STATUS_OK operation is successful. +** BTA_MA_STATUS_FAIL if any errors have occurred. +** evt - evt from the call-out function +** +** Returns void +** +*******************************************************************************/ +BTA_API extern void bta_mse_ci_get_msg_list_info(tBTA_MA_SESS_HANDLE mas_session_id, + tBTA_MA_STATUS status, + UINT16 evt) +{ + tBTA_MSE_CI_GET_ML_INFO *p_evt; + + if ((p_evt = (tBTA_MSE_CI_GET_ML_INFO *)GKI_getbuf(sizeof(tBTA_MSE_CI_GET_ML_INFO))) != NULL) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ci_get_msg_list_info sess_id=%d, status=%d \n", + mas_session_id, status); +#endif + p_evt->hdr.event = evt; + p_evt->mas_session_id = mas_session_id; + p_evt->status = status; + bta_sys_sendmsg(p_evt); + } +} + +/******************************************************************************* +** +** Function bta_mse_ci_get_msg_list_entry +** +** Description This function is called in response to the +** bta_mse_co_get_msg_list_entry call-out function. +** +** Parameters mas_session_id - MAS session ID +** status - BTA_MA_STATUS_OK if p_entry points to a valid entry. +** BTA_MA_STATUS_EODIR if no more entries (p_entry is ignored). +** BTA_MA_STATUS_FAIL if any errors have occurred. +** evt - evt from the call-out function +** +** Returns void +** +*******************************************************************************/ +BTA_API extern void bta_mse_ci_get_msg_list_entry(tBTA_MA_SESS_HANDLE mas_session_id, + tBTA_MA_STATUS status, + UINT16 evt) +{ + tBTA_MSE_CI_GET_ML_ENTRY *p_evt; + + if ((p_evt = (tBTA_MSE_CI_GET_ML_ENTRY *)GKI_getbuf(sizeof(tBTA_MSE_CI_GET_ML_ENTRY))) != NULL) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT2("bta_mse_ci_get_msg_list_entry sess_id=%d, status=%d \n", + mas_session_id, status); +#endif + p_evt->hdr.event = evt; + p_evt->mas_session_id = mas_session_id; + p_evt->status = status; + bta_sys_sendmsg(p_evt); + } +} + +/******************************************************************************* +** +** Function bta_mse_ci_get_msg +** +** Description This function is called in response to the +** bta_mse_co_get_msg call-out function. +** +** Parameters mas_session_id - MAS session ID +** status - BTA_MA_STATUS_OK if p_msg points to a valid bmessage. +** BTA_MA_STATUS_FAIL if any errors have occurred. +** filled_buff_size - size of the filled buffer +** multi_pkt_status - BTA_MA_MPKT_STATUS_MORE - need to get more packets +** BTA_MA_MPKT_STATUS_LAST - last packet of the bMessage +** frac_deliver_status - BTA_MA_FRAC_DELIVER_MORE - other fractions following +** this bMessage +** BTA_MA_FRAC_DELIVER_LAST - Last fraction +** evt - evt from the call-out function +** +** Returns void +** +*******************************************************************************/ +BTA_API extern void bta_mse_ci_get_msg(tBTA_MA_SESS_HANDLE mas_session_id, + tBTA_MA_STATUS status, + UINT16 filled_buff_size, + tBTA_MA_MPKT_STATUS multi_pkt_status, + tBTA_MA_FRAC_DELIVER frac_deliver_status, + UINT16 evt) +{ + tBTA_MSE_CI_GET_MSG *p_evt; + + if ((p_evt = (tBTA_MSE_CI_GET_MSG *)GKI_getbuf(sizeof(tBTA_MSE_CI_GET_MSG))) != NULL) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT4("bta_mse_ci_get_msg sess_id=%d, status=%d, multi-pkt status=%d frac=%d\n", + mas_session_id, + status, + multi_pkt_status, + frac_deliver_status); +#endif + p_evt->hdr.event = evt; + p_evt->mas_session_id = mas_session_id; + p_evt->status = status; + p_evt->filled_buff_size = filled_buff_size; + p_evt->multi_pkt_status = multi_pkt_status; + p_evt->frac_deliver_status = frac_deliver_status; + bta_sys_sendmsg(p_evt); + } +} +/******************************************************************************* +** +** Function bta_mse_ci_set_msg_delete_status +** +** Description This function is called in response to the +** bta_mse_co_set_msg_delete_status call-out function. +** +** Parameters mas_session_id - MAS session ID +** status - BTA_MA_STATUS_OK if operation is successful. +** BTA_MA_STATUS_FAIL if any errors have occurred. +** evt - evt from the call-out function +** +** Returns void +** +*******************************************************************************/ +BTA_API extern void bta_mse_ci_set_msg_delete_status(tBTA_MA_SESS_HANDLE mas_session_id, + tBTA_MA_STATUS status, + UINT16 evt) +{ + tBTA_MSE_CI_DEL_MSG *p_evt; + + if ((p_evt = (tBTA_MSE_CI_DEL_MSG *)GKI_getbuf(sizeof(tBTA_MSE_CI_DEL_MSG))) != NULL) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT3("bta_mse_ci_del_msg sess_id=%d, status=%d evt=%d\n", + mas_session_id, status, evt); +#endif + p_evt->hdr.event = evt; + p_evt->mas_session_id = mas_session_id; + p_evt->status = status; + bta_sys_sendmsg(p_evt); + } +} + +/******************************************************************************* +** +** Function bta_mse_ci_push_msg +** +** Description This function is called in response to the +** bta_mse_co_push_msg call-out function. +** +** Parameters mas_session_id - MAS session ID +** status - BTA_MA_STATUS_OK if the message upload is successful. +** BTA_MA_STATUS_FAIL if any errors have occurred. +** last_packet - last packet of a multi-packet message +** handle - message handle for the uploaded message if +** status is BTA_MA_OK and last_packet is TRUE +** Returns void +** +*******************************************************************************/ +BTA_API extern void bta_mse_ci_push_msg(tBTA_MA_SESS_HANDLE mas_session_id, + tBTA_MA_STATUS status, + BOOLEAN last_packet, + tBTA_MA_MSG_HANDLE handle, + UINT16 evt) +{ + tBTA_MSE_CI_PUSH_MSG *p_evt; + + if ((p_evt = (tBTA_MSE_CI_PUSH_MSG *)GKI_getbuf(sizeof(tBTA_MSE_CI_PUSH_MSG))) != NULL) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT4("bta_mse_ci_push_msg sess_id=%d, status=%d, last_pkt=%d evt=%d\n", + mas_session_id, + status, + last_packet, + evt); +#endif + + p_evt->hdr.event = evt; + p_evt->mas_session_id = mas_session_id; + p_evt->status = status; + memcpy(p_evt->handle, + handle, + sizeof(tBTA_MA_MSG_HANDLE)); + p_evt->last_packet = last_packet; + bta_sys_sendmsg(p_evt); + } +} + + diff --git a/bta/ma/bta_mse_int.h b/bta/ma/bta_mse_int.h new file mode 100644 index 0000000..d519b71 --- /dev/null +++ b/bta/ma/bta_mse_int.h @@ -0,0 +1,835 @@ +/***************************************************************************** +** +** Name: bta_mse_int.h +** +** Description: This is the private file for the message access +** equipment (MSE) subsystem. +** +** Copyright (c) 1998-2009, Broadcom Corp., All Rights Reserved. +** Broadcom Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ +#ifndef BTA_MSE_INT_H +#define BTA_MSE_INT_H + +#include "bt_target.h" +#include "bta_sys.h" +#include "obx_api.h" +#include "bta_ma_def.h" +#include "bta_mse_api.h" +#include "bta_mse_co.h" +#include "bta_mse_ci.h" +#include "bta_ma_util.h" + +/***************************************************************************** +** Constants and data types +*****************************************************************************/ +typedef tOBX_STATUS (tBTA_MA_OBX_RSP) (tOBX_HANDLE handle, UINT8 rsp_code, BT_HDR *p_pkt); + +#ifndef BTA_MSE_MN_DISC_SIZE + #define BTA_MSE_MN_DISC_SIZE 500 +#endif + +#define BTA_MSE_64BIT_HEX_STR_SIZE (16+1) +#define BTA_MSE_32BIT_HEX_STR_SIZE (8+1) + +#define BTA_MSE_MN_MAX_MSG_EVT_OBECT_SIZE 1536 /* 1.5 k */ +/* mode field in tBTA_MSE_CO_FOLDER_ENTRY (OR'd together) */ +#define BTA_MSE_A_RDONLY GOEP_A_RDONLY +#define BTA_MSE_A_DIR GOEP_A_DIR /* Entry is a sub directory */ + +enum +{ + BTA_MSE_MA_GET_ACT_NEW_FOLDER_LIST = 0, + BTA_MSE_MA_GET_ACT_CON_FOLDER_LIST, + BTA_MSE_MA_GET_ACT_ERR_FOLDER_LIST, + BTA_MSE_MA_GET_ACT_NEW_MSG_LIST, + BTA_MSE_MA_GET_ACT_CON_MSG_LIST, + BTA_MSE_MA_GET_ACT_ERR_MSG_LIST, + BTA_MSE_MA_GET_ACT_NEW_MSG, + BTA_MSE_MA_GET_ACT_CON_MSG, + BTA_MSE_MA_GET_ACT_ERR_MSG, + BTA_MSE_MA_GET_ACT_ERR, + BTA_MSE_MA_GET_ACT_NONE, + BTA_MSE_MA_GET_ACT_MAX +}; +typedef UINT8 tBTA_MSE_MA_GET_ACT; + +enum +{ + BTA_MSE_MA_GET_TYPE_FOLDER_LIST = 0, + BTA_MSE_MA_GET_TYPE_MSG_LIST, + BTA_MSE_MA_GET_TYPE_MSG, + BTA_MSE_MA_GET_TYPE_CON_FOLDER_LIST, + BTA_MSE_MA_GET_TYPE_CON_MSG_LIST, + BTA_MSE_MA_GET_TYPE_CON_MSG, + BTA_MSE_MA_GET_TYPE_NONE, + BTA_MSE_MA_GET_TYPE_MAX +}; +typedef UINT8 tBTA_MSE_MA_GET_TYPE; + +enum +{ + BTA_MSE_MA_PUT_TYPE_NOTIF_REG = 0, + BTA_MSE_MA_PUT_TYPE_EVT_RPT, + BTA_MSE_MA_PUT_TYPE_NONE, + BTA_MSE_MA_PUT_TYPE_MAX +}; +typedef UINT8 tBTA_MSE_MA_PUT_TYPE; + +enum +{ + BTA_MSE_MN_NOTIF_REG_STS_OFF = 0, + BTA_MSE_MN_NOTIF_REG_STS_ON, + BTA_MSE_MN_NOTIF_REG_STS_NONE, + BTA_MSE_MN_NOTIF_REG_STS_MAX +}; +typedef UINT8 tBTA_MSE_MN_NOTIF_REG_STS; + +enum +{ + BTA_MSE_MN_ACT_TYPE_OPEN_CONN = 0, + BTA_MSE_MN_ACT_TYPE_OPEN_CONN_NONE, + BTA_MSE_MN_ACT_TYPE_OPEN_CONN_ERR, + BTA_MSE_MN_ACT_TYPE_CLOSE_CONN, + BTA_MSE_MN_ACT_TYPE_CLOSE_CONN_NONE, + BTA_MSE_MN_ACT_TYPE_CLOSE_CONN_ERR, + BTA_MSE_MN_ACT_TYPE_NONE, + BTA_MSE_MN_ACT_TYPE_MAX +}; +typedef UINT8 tBTA_MSE_MN_ACT_TYPE; + +typedef tOBX_STATUS (tBTA_MSE_OBX_RSP) (tOBX_HANDLE handle, UINT8 rsp_code, BT_HDR *p_pkt); + +/* MSE Active MA obex operation (Valid in connected state) */ +#define BTA_MSE_MA_OP_NONE 0 +#define BTA_MSE_MA_OP_SETPATH 1 +#define BTA_MSE_MA_OP_GET_FOLDER_LIST 2 +#define BTA_MSE_MA_OP_GET_MSG_LIST 3 +#define BTA_MSE_MA_OP_GET_MSG 4 +#define BTA_MSE_MA_OP_SET_STATUS 5 +#define BTA_MSE_MA_OP_PUSH_MSG 6 + +/* MAS Active MN obex operation (Valid in connected state) */ +#define BTA_MSE_MN_OP_NONE 0 +#define BTA_MSE_MN_OP_PUT_EVT_RPT 1 + + +/* MN Abort state */ +#define BTA_MSE_MN_ABORT_NONE 0x0 +#define BTA_MSE_MN_ABORT_REQ_NOT_SENT 0x1 +#define BTA_MSE_MN_ABORT_REQ_SENT 0x2 +#define BTA_MSE_MN_ABORT_RSP_RCVD 0x4 + + +/* Response Timer Operations */ +#define BTA_MSE_TIMER_OP_NONE 0 +#define BTA_MSE_TIMER_OP_STOP 1 +#define BTA_MSE_TIMER_OP_ABORT 2 +#define BTA_MSE_TIMER_OP_ALL 0xFF /* use to stop all timers */ + +/* State Machine Events */ +enum +{ + /* these events are handled by the state machine */ + BTA_MSE_INT_CLOSE_EVT = BTA_SYS_EVT_START(BTA_ID_MSE), + BTA_MSE_API_ACCESSRSP_EVT, + BTA_MSE_API_UPD_IBX_RSP_EVT, + BTA_MSE_API_SET_NOTIF_REG_RSP_EVT, + BTA_MSE_INT_START_EVT, + BTA_MSE_CI_GET_FENTRY_EVT, + BTA_MSE_CI_GET_ML_INFO_EVT, + BTA_MSE_CI_GET_ML_ENTRY_EVT, + BTA_MSE_CI_GET_MSG_EVT, + BTA_MSE_CI_PUSH_MSG_EVT, + BTA_MSE_CI_DEL_MSG_EVT, + BTA_MSE_MA_OBX_CONN_EVT, /* OBX Channel Connect Request */ + BTA_MSE_MA_OBX_DISC_EVT, /* OBX Channel Disconnect */ + BTA_MSE_MA_OBX_ABORT_EVT, /* OBX_operation aborted */ + BTA_MSE_MA_OBX_CLOSE_EVT, /* OBX Channel Disconnected (Link Lost) */ + BTA_MSE_MA_OBX_PUT_EVT, /* Write file data or delete */ + BTA_MSE_MA_OBX_GET_EVT, /* Read file data or folder listing */ + BTA_MSE_MA_OBX_SETPATH_EVT, /* Make or Change Directory */ + BTA_MSE_CLOSE_CMPL_EVT, /* Finished closing channel */ + + /* Message Notification Client events */ + BTA_MSE_MN_INT_OPEN_EVT, + BTA_MSE_MN_INT_CLOSE_EVT, + BTA_MSE_MN_SDP_OK_EVT, + BTA_MSE_MN_SDP_FAIL_EVT, + BTA_MSE_MN_OBX_CONN_RSP_EVT, + BTA_MSE_MN_OBX_PUT_RSP_EVT, + BTA_MSE_MN_OBX_CLOSE_EVT, + BTA_MSE_MN_OBX_TOUT_EVT, + BTA_MSE_MN_CLOSE_CMPL_EVT, + BTA_MSE_API_SEND_NOTIF_EVT, + BTA_MSE_API_MN_ABORT_EVT, + BTA_MSE_MN_OBX_ABORT_RSP_EVT, + BTA_MSE_MN_RSP_TOUT_EVT, + + /* these events are handled outside the state machine */ + BTA_MSE_MN_RSP0_TOUT_EVT, /* timeout event for MN control block index 0*/ + BTA_MSE_MN_RSP1_TOUT_EVT, + BTA_MSE_MN_RSP2_TOUT_EVT, + BTA_MSE_MN_RSP3_TOUT_EVT, + BTA_MSE_MN_RSP4_TOUT_EVT, + BTA_MSE_MN_RSP5_TOUT_EVT, + BTA_MSE_MN_RSP6_TOUT_EVT, /* Bluetooth limit for upto 7 devices*/ + BTA_MSE_API_ENABLE_EVT, + BTA_MSE_API_DISABLE_EVT, + BTA_MSE_API_START_EVT, + BTA_MSE_API_STOP_EVT, + BTA_MSE_API_CLOSE_EVT, + BTA_MSE_API_MA_CLOSE_EVT, + BTA_MSE_API_MN_CLOSE_EVT + +}; +typedef UINT16 tBTA_MSE_INT_EVT; + +#define BTA_MSE_MN_EVT_MIN BTA_MSE_MN_INT_OPEN_EVT +#define BTA_MSE_MN_EVT_MAX BTA_MSE_MN_RSP_TOUT_EVT + + +/* state machine states */ +enum +{ + BTA_MSE_MA_IDLE_ST = 0, /* Idle */ + BTA_MSE_MA_LISTEN_ST, /* Listen - waiting for OBX/RFC connection */ + BTA_MSE_MA_CONN_ST, /* Connected - MA Session is active */ + BTA_MSE_MA_CLOSING_ST /* Closing is in progress */ +}; +typedef UINT8 tBTA_MSE_MA_STATE; + +/* data type for BTA_MSE_MA_CI_GET_FENTRY_EVT note:sdh */ +typedef struct +{ + BT_HDR hdr; + tBTA_MA_SESS_HANDLE mas_session_id; + tBTA_MA_STATUS status; +} tBTA_MSE_CI_GET_FENTRY; + +/* data type for BTA_MSE_MA_CI_GET_FENTRY_EVT note:sdh */ +typedef struct +{ + BT_HDR hdr; + tBTA_MA_SESS_HANDLE mas_session_id; + tBTA_MA_STATUS status; +} tBTA_MSE_CI_GET_ML_INFO; + + + +typedef struct +{ + BT_HDR hdr; + tBTA_MA_SESS_HANDLE mas_session_id; + tBTA_MA_STATUS status; +} tBTA_MSE_CI_GET_ML_ENTRY; + + +typedef struct +{ + BT_HDR hdr; + tBTA_MA_SESS_HANDLE mas_session_id; + tBTA_MA_STATUS status; + BOOLEAN last_packet; + tBTA_MA_MSG_HANDLE handle; +} tBTA_MSE_CI_PUSH_MSG; + + +typedef struct +{ + BT_HDR hdr; + tBTA_MA_SESS_HANDLE mas_session_id; + tBTA_MA_STATUS status; + UINT16 filled_buff_size; + tBTA_MA_MPKT_STATUS multi_pkt_status; + tBTA_MA_FRAC_DELIVER frac_deliver_status; +} tBTA_MSE_CI_GET_MSG; + +typedef struct +{ + BT_HDR hdr; + tBTA_MA_SESS_HANDLE mas_session_id; + tBTA_MA_STATUS status; +} tBTA_MSE_CI_DEL_MSG; + + + +/* data type for BTA_MSE_API_ENABLE_EVT note:sdh */ +typedef struct +{ + BT_HDR hdr; + tBTA_MSE_CBACK *p_cback; /* pointer to application callback function */ + UINT8 app_id; +} tBTA_MSE_API_ENABLE; + + +/* data type for BTA_MSE_API_DISABLE_EVT note:sdh */ +typedef struct +{ + BT_HDR hdr; + UINT8 app_id; +} tBTA_MSE_API_DISABLE; + +/* data type for BTA_MSE_API_START_EVT note:sdh */ +typedef struct +{ + BT_HDR hdr; + tBTA_MA_INST_ID mas_inst_id; + char servicename[BTA_SERVICE_NAME_LEN + 1]; + char *p_root_path; + tBTA_SEC sec_mask; + tBTA_MA_MSG_TYPE sup_msg_type; +} tBTA_MSE_API_START; + +/* data type for BTA_MSE_API_STOP_EVT note:sdh */ +typedef struct +{ + BT_HDR hdr; + tBTA_MA_INST_ID mas_inst_id; + +} tBTA_MSE_API_STOP; + +/* data type for BTA_MSE_API_CLOSE_EVT */ +typedef struct +{ + BT_HDR hdr; + tBTA_MA_INST_ID mas_instance_id; + +} tBTA_MSE_API_CLOSE; + +/* data type for BTA_MSE_API_MA_CLOSE_EVT */ +typedef struct +{ + BT_HDR hdr; + BD_ADDR bd_addr; + tBTA_MA_INST_ID mas_instance_id; + +} tBTA_MSE_API_MA_CLOSE; + +/* data type for BTA_MSE_INT_CLOSE_EVT */ +typedef struct +{ + BT_HDR hdr; + tBTA_MA_SESS_HANDLE mas_session_id; + +} tBTA_MSE_INT_CLOSE; + + +/* data type for BTA_MSE_API_MN_CLOSE_EVT */ +typedef struct +{ + BT_HDR hdr; + BD_ADDR bd_addr; +} tBTA_MSE_API_MN_CLOSE; + + +typedef struct +{ + BT_HDR hdr; + tBTA_MA_SESS_HANDLE mas_session_id; + tBTA_MSE_OPER oper; + tBTA_MA_ACCESS_TYPE rsp; + char *p_path; +} tBTA_MSE_API_ACCESSRSP; + +typedef struct +{ + BT_HDR hdr; + tBTA_MA_SESS_HANDLE mas_session_id; + tBTA_MSE_UPDATE_INBOX_TYPE rsp; + char *p_path; +} tBTA_MSE_API_UPDINBRSP; + +typedef struct +{ + BT_HDR hdr; + tBTA_MA_SESS_HANDLE mas_session_id; + tBTA_MSE_SET_NOTIF_REG_TYPE rsp; +} tBTA_MSE_API_SETNOTIFREGRSP; + +/* data type for all obex events + hdr.event contains the MAS event +*/ +typedef struct +{ + BT_HDR hdr; + tOBX_HANDLE handle; + tOBX_EVT_PARAM param; + BT_HDR *p_pkt; + tOBX_EVENT obx_event; + UINT8 rsp_code; +} tBTA_MSE_OBX_EVT; + +/* OBX Response Packet Structure - Holds current response packet info */ +typedef struct +{ + BT_HDR *p_pkt; /* (Get/Put) Holds the current OBX header for Put or Get */ + UINT8 *p_start; /* (Get/Put) Start of the Body of the packet */ + UINT16 offset; /* (Get/Put) Contains the current offset into the Body (p_start) */ + UINT16 bytes_left; /* (Get/Put) Holds bytes available left in Obx packet */ + BOOLEAN final_pkt; /* (Put) Holds the final bit of the Put packet */ +} tBTA_MSE_OBX_PKT; + +/* data type for BTA_MSE_MN_INT_OPEN_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT8 ccb_idx; + BD_ADDR bd_addr; + tBTA_SEC sec_mask; +}tBTA_MSE_MN_INT_OPEN; + +/* data type for BTA_MSE_MN_INT_OPEN_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT8 ccb_idx; +}tBTA_MSE_MN_INT_CLOSE; + +/* data type for BTA_MSE_MN_SDP_OK_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT8 ccb_idx; + UINT8 scn; +}tBTA_MSE_MN_SDP_OK; + + +/* data type for BTA_MSE_MN_SDP_FAIL_EVT */ +typedef struct +{ + BT_HDR hdr; + UINT8 ccb_idx; +}tBTA_MSE_MN_SDP_FAIL; + + +/* data type for BTA_MSE_MN_API_SEND_NOTIF_EVT */ +typedef struct +{ + BT_HDR hdr; + tBTA_MA_INST_ID mas_instance_id; + tBTA_MSE_NOTIF_TYPE notif_type; + tBTA_MA_MSG_HANDLE handle; + char *p_folder; + char *p_old_folder; + tBTA_MA_MSG_TYPE msg_type; + BD_ADDR except_bd_addr; +} tBTA_MSE_MN_API_SEND_NOTIF; + +/* data type for BTA_MSE_API_MN_ABORT_EVT */ +typedef struct +{ + BT_HDR hdr; + tBTA_MA_INST_ID mas_instance_id; +}tBTA_MSE_MN_API_ABORT; + + +/* union of all state machine event data types */ +typedef union +{ + BT_HDR hdr; + tBTA_MSE_API_ENABLE api_enable; /* data for BTA_MSE_API_ENABLE_EVT */ + tBTA_MSE_API_DISABLE api_disable; + tBTA_MSE_API_START api_start; + tBTA_MSE_API_STOP api_stop; + tBTA_MSE_API_CLOSE api_close; + tBTA_MSE_INT_CLOSE int_close; + tBTA_MSE_API_MA_CLOSE api_ma_close; + tBTA_MSE_API_MN_CLOSE api_mn_close; + tBTA_MSE_API_ACCESSRSP api_access_rsp; + tBTA_MSE_API_UPDINBRSP api_upd_ibx_rsp; + tBTA_MSE_API_SETNOTIFREGRSP api_set_notif_reg_rsp; + tBTA_MSE_OBX_EVT obx_evt; + tBTA_MSE_CI_GET_FENTRY ci_get_fentry; + tBTA_MSE_CI_GET_ML_INFO ci_get_ml_info; + tBTA_MSE_CI_GET_ML_ENTRY ci_get_ml_entry; + tBTA_MSE_CI_GET_MSG ci_get_msg; + tBTA_MSE_CI_PUSH_MSG ci_push_msg; + tBTA_MSE_CI_DEL_MSG ci_del_msg; + tBTA_MSE_MN_INT_OPEN mn_int_open; + tBTA_MSE_MN_INT_CLOSE mn_int_close; + tBTA_MSE_MN_SDP_OK mn_sdp_ok; + tBTA_MSE_MN_SDP_FAIL mn_sdp_fail; + tBTA_MSE_MN_API_SEND_NOTIF mn_send_notif; + tBTA_MSE_MN_API_ABORT mn_abort; + +} tBTA_MSE_DATA; + +typedef struct +{ + char *p_path; + char *p_name; + tBTA_MA_DIR_NAV flags; +} tBTA_MSE_OPER_SETPATH; + +/* Directory Listing bufer pointer */ +typedef struct +{ + tBTA_MSE_CO_FOLDER_ENTRY *p_entry; /* Holds current directory entry */ + BOOLEAN is_root; /* TRUE if path is root directory */ +} tBTA_MSE_DIRLIST; + +typedef struct +{ + UINT16 max_list_cnt; + UINT16 start_offset; + UINT16 list_cnt; +} tBTA_MSE_OPER_FLIST_PARAM; + +/* Message Listing buffer pointers */ +typedef struct +{ + tBTA_MSE_CO_MSG_LIST_ENTRY *p_entry; + tBTA_MSE_CO_MSG_LIST_INFO *p_info; + BOOLEAN pending_ml_frag; + char *p_xml_buf; + UINT16 offset; + UINT16 remaing_size; +} tBTA_MSE_MSGLIST; + +typedef struct +{ + tBTA_MA_MSG_LIST_FILTER_PARAM filter; + char *p_name; + char *p_path; + BOOLEAN w4info; +} tBTA_MSE_OPER_MLIST_PARAM; + + +typedef struct +{ + BOOLEAN notif_status_rcv; + tBTA_MA_NOTIF_STATUS notif_status; +} tBTA_NOTIF_REG; + +typedef struct +{ + tBTA_MA_GET_MSG_PARAM data; + char *p_msg_handle; + UINT8 *p_frac_delivery; + UINT16 byte_get_cnt; + UINT16 filled_buff_size; + BOOLEAN add_frac_del_hdr; + tBTA_MA_FRAC_DELIVER frac_deliver_status; +} tBTA_MSE_OPER_MSG_PARAM; + +typedef struct +{ + tBTA_MA_PUSH_MSG_PARAM param; + UINT16 push_byte_cnt; + BOOLEAN rcv_folder_name; + BOOLEAN rcv_charset; + BOOLEAN rcv_transparent; + BOOLEAN rcv_retry; + BOOLEAN first_req_pkt; +} tBTA_MSE_OPER_PUSH_MSG; + +typedef struct +{ + char *p_msg_handle; + BOOLEAN rcv_msg_handle; + BOOLEAN rcv_sts_ind; + BOOLEAN rcv_sts_val; + tBTA_MA_MSG_HANDLE handle; + tBTA_MA_STS_INDCTR sts_ind; + tBTA_MA_STS_VALUE sts_val; +} tBTA_MSE_OPER_SET_MSG_STS; + + +/* MAS control block */ +typedef struct +{ + tBTA_NOTIF_REG notif_reg_req; + tBTA_MSE_OPER_PUSH_MSG push_msg; + tBTA_MSE_OPER_SET_MSG_STS set_msg_sts; + tBTA_MSE_OPER_SETPATH sp; + tBTA_MSE_OPER_FLIST_PARAM fl_param; + tBTA_MSE_DIRLIST dir; + tBTA_MSE_OPER_MLIST_PARAM ml_param; + tBTA_MSE_MSGLIST ml; /* point to the Message-Listing object buffer */ + tBTA_MSE_OPER_MSG_PARAM msg_param; + tBTA_MSE_OBX_PKT obx; + char *p_workdir; /* Current working folder */ + tOBX_HANDLE obx_handle; /* OBEX handle,used as MAS session ID as well */ + UINT16 peer_mtu; + BOOLEAN cout_active; /* TRUE when waiting for a call-in function */ + BOOLEAN aborting; + BD_ADDR bd_addr; /* Device currently connected to */ + tBTA_MSE_OPER oper; + tBTA_MSE_MA_STATE state; /* state machine state */ + +} tBTA_MSE_MA_SESS_CB; + +typedef struct +{ + tBTA_MSE_MA_SESS_CB sess_cb[BTA_MSE_NUM_SESS]; + UINT32 sdp_handle; /* SDP record handle */ + char *p_rootpath; + tOBX_HANDLE obx_handle; /* OBEX handle ID */ + BOOLEAN stopping; + BOOLEAN in_use; + tBTA_SEC sec_mask; + tBTA_MA_MSG_TYPE sup_msg_type; + char servicename[BTA_SERVICE_NAME_LEN + 1]; + UINT8 scn; /* SCN of the MA server */ + tBTA_MA_INST_ID mas_inst_id; /* MAS instance id */ +}tBTA_MSE_MA_CB; + +/* state machine states */ +enum +{ + BTA_MSE_MN_IDLE_ST = 0, /* Idle */ + BTA_MSE_MN_W4_CONN_ST, /* wait for connection state */ + BTA_MSE_MN_CONN_ST, /* Connected - MAS Session is active */ + BTA_MSE_MN_CLOSING_ST /* Closing is in progress */ +}; +typedef UINT8 tBTA_MSE_MN_STATE; + +/* notification registration status */ +typedef struct +{ + BOOLEAN status; + tBTA_MA_INST_ID mas_inst_id; /* only valid when status == TRUE*/ +} tBTA_MSE_MN_REG_STATUS; + +/* Message notification report */ +typedef struct +{ + UINT16 buffer_len; + UINT16 bytes_sent; + BOOLEAN final_pkt; + UINT8 pkt_cnt; + tBTA_MA_INST_ID mas_instance_id; + UINT8 *p_buffer; +}tBTA_MSE_MN_MSG_NOTIF; + +typedef struct +{ + tBTA_MSE_MN_REG_STATUS notif_reg[BTA_MSE_NUM_INST]; + tBTA_MSE_OBX_PKT obx; /* Holds the current OBX packet information */ + tBTA_MSE_MN_MSG_NOTIF msg_notif; + TIMER_LIST_ENT rsp_timer; /* response timer */ + tSDP_DISCOVERY_DB *p_db; /* pointer to discovery database */ + tSDP_DISC_CMPL_CB *sdp_cback; + tOBX_HANDLE obx_handle; + UINT16 sdp_service; + UINT16 peer_mtu; + BOOLEAN in_use; + BOOLEAN req_pending; /* TRUE when waiting for an obex response */ + BOOLEAN cout_active; /* TRUE if call-out is currently active */ + BOOLEAN sdp_pending; + BD_ADDR bd_addr; /* Peer device MNS server address */ + tBTA_MSE_MN_STATE state; /* state machine state */ + tBTA_SEC sec_mask; + UINT8 timer_oper; /* current active response timer action (abort or close) */ + UINT8 obx_oper; /* current active OBX operation PUT or GET operations */ + UINT8 aborting; +}tBTA_MSE_MN_CB; + +typedef struct +{ + BOOLEAN in_use; + BD_ADDR bd_addr; + BOOLEAN opened; + BOOLEAN busy; +}tBTA_MSE_PM_CB; + + +typedef struct +{ + tBTA_MSE_MA_CB scb[BTA_MSE_NUM_INST]; /* MA Server Control Blocks */ + tBTA_MSE_MN_CB ccb[BTA_MSE_NUM_MN]; /* MN Client Control Blocks */ + tBTA_MSE_PM_CB pcb[BTA_MSE_NUM_MN]; + tBTA_MSE_CBACK *p_cback; /* pointer to application event callback function */ + BOOLEAN enable; + BOOLEAN disabling; + UINT8 app_id; +}tBTA_MSE_CB; + +/****************************************************************************** +** Configuration Definitions +*******************************************************************************/ +/* Configuration structure */ +typedef struct +{ + INT32 abort_tout; /* Timeout in milliseconds to wait for abort OBEX response (client only) */ + INT32 stop_tout; /* Timeout in milliseconds to wait for close OBEX response (client only) */ + +} tBTA_MSE_MA_CFG; + +/***************************************************************************** +** Global data +*****************************************************************************/ + +/* MAS control block */ +#if BTA_DYNAMIC_MEMORY == FALSE +extern tBTA_MSE_CB bta_mse_cb; +#else +extern tBTA_MSE_CB *bta_mse_cb_ptr; + #define bta_mse_cb (*bta_mse_cb_ptr) +#endif + +#define BTA_MSE_GET_INST_CB_PTR(inst_idx) &(bta_mse_cb.scb[(inst_idx)]) +#define BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx ) &(bta_mse_cb.scb[(inst_idx)].sess_cb[(sess_idx)]) +#define BTA_MSE_GET_MN_CB_PTR(ccb_idx) &(bta_mse_cb.ccb[(ccb_idx)]) +#define BTA_MSE_GET_PM_CB_PTR(pcb_idx) &(bta_mse_cb.pcb[(pcb_idx)]) +/* MAS configuration constants */ +extern tBTA_MSE_MA_CFG * p_bta_ms_cfg; + +/***************************************************************************** +** Function prototypes +*****************************************************************************/ +/* MSE event handler for MA and MN */ + +#ifdef __cplusplus +extern "C" +{ +#endif + + extern BOOLEAN bta_mse_hdl_event(BT_HDR *p_msg); + +/* State machine drivers */ + extern void bta_mse_ma_sm_execute(UINT8 inst_idx, UINT8 sess_idx, UINT16 event, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_sm_execute(UINT8 ccb_idx, UINT16 event, tBTA_MSE_DATA *p_data); + + extern void bta_mse_ma_sdp_register (tBTA_MSE_MA_CB *p_scb, char *p_service_name, tBTA_MA_INST_ID inst_id, tBTA_MA_MSG_TYPE msg_type); + +/* Obx callback functions */ + extern void bta_mse_ma_obx_cback (tOBX_HANDLE handle, tOBX_EVENT event, + tOBX_EVT_PARAM param, BT_HDR *p_pkt); + + extern void bta_mse_mn_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event, UINT8 rsp_code, + tOBX_EVT_PARAM param, BT_HDR *p_pkt); + +/* action functions for MA */ + extern void bta_mse_ma_int_close(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_api_accessrsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_api_upd_ibx_rsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_api_set_notif_reg_rsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + + extern void bta_mse_ma_ci_get_folder_entry(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_ci_get_ml_info(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_ci_get_ml_entry(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_ci_get_msg(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_ci_push_msg(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_ci_del_msg(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + + extern void bta_mse_ma_obx_disc(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_obx_connect(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_obx_close(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_obx_abort(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_obx_put(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_obx_get(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_obx_setpath(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_conn_err_rsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_ma_close_complete(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + +/* action function for MN */ + extern void bta_mse_mn_init_sdp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_start_client(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_stop_client(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_obx_conn_rsp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_close(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_send_notif(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_rsp_timeout(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_put_rsp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_obx_tout(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_close_compl(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_ignore_obx(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_sdp_fail(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_abort(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + extern void bta_mse_mn_abort_rsp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + + +/* miscellaneous functions */ + extern void bta_mse_discard_data(UINT16 event, tBTA_MSE_DATA *p_data); + +/* utility functions */ + + extern void bta_mse_send_push_msg_in_prog_evt(UINT8 inst_idx, UINT8 sess_idx); + extern void bta_mse_send_get_msg_in_prog_evt(UINT8 inst_idx, UINT8 sess_idx); + extern void bta_mse_send_oper_cmpl_evt(UINT8 inst_idx, UINT8 sess_idx, tBTA_MA_STATUS status); + extern void bta_mse_pushmsg(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN first_pkt); + extern void bta_mse_clean_set_msg_sts(UINT8 inst_idx, UINT8 sess_idx); + extern void bta_mse_clean_set_notif_reg(UINT8 inst_idx, UINT8 sess_idx); + extern void bta_mse_clean_push_msg(UINT8 inst_idx, UINT8 sess_idx); + extern void bta_mse_init_set_msg_sts(UINT8 inst_idx, UINT8 sess_idx, UINT8 *p_rsp_code); + extern void bta_mse_init_push_msg(UINT8 inst_idx, UINT8 sess_idx, UINT8 *p_rsp_code); + extern void bta_mse_remove_uuid(void); + extern void bta_mse_clean_mas_service(UINT8 inst_idx); + extern void bta_mse_abort_too_late(UINT8 inst_idx, UINT8 sess_idx); + extern void bta_mse_clean_getput(UINT8 inst_idx, UINT8 sess_idx, tBTA_MA_STATUS status); + extern void bta_mse_clean_msg(UINT8 inst_idx, UINT8 sess_idx); + extern void bta_mse_end_of_msg(UINT8 inst_idx, UINT8 sess_idx, UINT8 rsp_code); + extern void bta_mse_getmsg(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN new_req); + extern tBTA_MA_STATUS bta_mse_build_msg_listing_obj(tBTA_MSE_CO_MSG_LIST_ENTRY *p_entry, + UINT16 *p_size, char *p_buf ); + extern void bta_mse_clean_msg_list(UINT8 inst_idx, UINT8 sess_idx); + extern void bta_mse_end_of_msg_list(UINT8 inst_idx, UINT8 sess_idx, UINT8 rsp_code); + extern UINT8 bta_mse_add_msg_list_info(UINT8 inst_idx, UINT8 sess_idx); + extern UINT8 bta_mse_add_msg_list_entry(UINT8 inst_idx, UINT8 sess_idx); + extern void bta_mse_getmsglist(UINT8 inst_idx, UINT8 sess_idx,BOOLEAN new_req); + extern UINT8 * bta_mse_read_app_params(BT_HDR *p_pkt, UINT8 tag, UINT16 *param_len); + extern void bta_mse_clean_list(UINT8 inst_idx, UINT8 sess_idx); + extern void bta_mse_end_of_list(UINT8 inst_idx, UINT8 sess_idx, UINT8 rsp_code); + extern UINT8 bta_mse_add_list_entry(UINT8 inst_idx, UINT8 sess_idx); + extern void bta_mse_getfolderlist(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN new_req); + extern UINT8 bta_mse_chdir(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_OPER *p_oper); + extern BOOLEAN bta_mse_send_set_notif_reg(UINT8 status, + UINT8 inst_idx, UINT8 sess_idx); + extern void bta_mse_proc_notif_reg_status(UINT8 status, + UINT8 inst_idx, UINT8 sess_idx); + extern void bta_mse_discard_data(UINT16 event, tBTA_MSE_DATA *p_data); + extern BOOLEAN bta_mse_find_bd_addr_match_sess_cb_idx(BD_ADDR bd_addr, UINT8 inst_idx, UINT8 *p_idx); + extern BOOLEAN bta_mse_find_mas_inst_id_match_cb_idx(tBTA_MA_INST_ID mas_inst_id, UINT8 *p_idx); + extern BOOLEAN bta_mse_find_handle_match_mas_inst_cb_idx(tOBX_HANDLE obx_handle, UINT8 *p_idx); + extern BOOLEAN bta_mse_find_mas_sess_cb_idx(tOBX_HANDLE obx_handle, UINT8 *p_mas_inst_idx, UINT8 *p_mas_sess_idx); + extern BOOLEAN bta_mse_find_ma_cb_indexes(tBTA_MSE_DATA *p_msg, UINT8 *p_inst_idx, UINT8 *p_sess_idx); + extern void bta_mse_ma_cleanup(tBTA_MSE_DATA *p_msg); + extern BOOLEAN bta_mse_is_a_duplicate_id(tBTA_MA_INST_ID mas_inst_id); + extern BOOLEAN bta_mse_find_avail_mas_inst_cb_idx(UINT8 *p_idx); + extern BOOLEAN bta_mse_find_avail_mas_sess_cb_idx(tBTA_MSE_MA_CB *p_scb, UINT8 *p_idx); + extern 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); + extern BOOLEAN bta_mse_find_avail_mn_cb_idx(UINT8 *p_idx); + extern BOOLEAN bta_mse_find_bd_addr_match_mn_cb_index(BD_ADDR p_bd_addr, UINT8 *p_idx); + extern BOOLEAN bta_mse_find_sess_id_match_mn_cb_index(tBTA_MA_SESS_HANDLE mas_session_id, + UINT8 *p_idx); + extern BOOLEAN bta_mse_find_mn_cb_index(tBTA_MSE_DATA *p_msg, UINT8 *p_ccb_idx); + extern void bta_mse_mn_cleanup(tBTA_MSE_DATA *p_msg); + extern 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); + extern void bta_mse_mn_start_timer(UINT8 ccb_idx, UINT8 timer_id); + extern void bta_mse_mn_stop_timer(UINT8 ccb_idx, UINT8 timer_id); + extern BOOLEAN bta_mse_mn_add_inst_id(UINT8 ccb_idx, tBTA_MA_INST_ID mas_inst_id); + extern BOOLEAN bta_mse_mn_remove_inst_id(UINT8 ccb_idx, tBTA_MA_INST_ID mas_inst_id); + extern void bta_mse_mn_remove_all_inst_ids(UINT8 ccb_idx); + extern UINT8 bta_mse_mn_find_num_of_act_inst_id(UINT8 ccb_idx); + extern BOOLEAN bta_mse_mn_is_inst_id_exist(UINT8 ccb_idx, tBTA_MA_INST_ID mas_inst_id ); + extern BOOLEAN bta_mse_mn_is_ok_to_close_mn(BD_ADDR bd_addr, tBTA_MA_INST_ID mas_inst_id ); + extern BOOLEAN bta_mse_mn_get_first_inst_id(UINT8 ccb_idx, tBTA_MA_INST_ID *p_mas_inst_id); + extern tBTA_MA_STATUS bta_mse_mn_cont_send_notif(UINT8 ccb_idx, BOOLEAN first_pkt); + extern void bta_mse_mn_send_notif_evt(tBTA_MA_INST_ID mas_instance_id, tBTA_MA_STATUS status, + BD_ADDR bd_addr ); + extern void bta_mse_mn_clean_send_notif(UINT8 ccb_idx); + extern void bta_mse_ma_fl_read_app_params(UINT8 inst_idx, UINT8 sess_idx, BT_HDR *p_pkt); + extern void bta_mse_ma_ml_read_app_params(UINT8 inst_idx, UINT8 sess_idx, BT_HDR *p_pkt); + extern BOOLEAN bta_mse_ma_msg_read_app_params(UINT8 inst_idx, UINT8 sess_idx, BT_HDR *p_pkt); + extern BOOLEAN bta_mse_get_msglist_path(UINT8 inst_idx, UINT8 sess_idx); + + extern BOOLEAN bta_mse_find_pm_cb_index(BD_ADDR p_bd_addr, UINT8 *p_idx); + extern BOOLEAN bta_mse_find_avail_pm_cb_idx(UINT8 *p_idx); + extern void bta_mse_pm_conn_open(BD_ADDR bd_addr); + extern void bta_mse_pm_conn_close(BD_ADDR bd_addr); + extern void bta_mse_set_ma_oper(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_OPER oper); + extern void bta_mse_set_mn_oper(UINT8 ccb_idx, UINT8 oper); +#ifdef __cplusplus +} +#endif +#endif /* BTA_MSE_INT_H */ diff --git a/bta/ma/bta_mse_main.c b/bta/ma/bta_mse_main.c new file mode 100644 index 0000000..feddd09 --- /dev/null +++ b/bta/ma/bta_mse_main.c @@ -0,0 +1,1367 @@ +/***************************************************************************** +** +** Name: bta_mse_main.c +** +** Description: This file contains the Message Access Server main functions +** and state machine. +** +** Copyright (c) 1998-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 <string.h> + +#include "bta_fs_api.h" +#include "bta_mse_int.h" +#include "gki.h" +#include "utl.h" +#include "obx_api.h" + +/***************************************************************************** +** Message Access Server State Table +*****************************************************************************/ +/***************************************************************************** +** Constants and types +*****************************************************************************/ +/* state machine action enumeration list for MAS */ +enum +{ + BTA_MSE_MA_INT_CLOSE, + BTA_MSE_MA_API_ACCESSRSP, + BTA_MSE_MA_API_UPD_IBX_RSP, + BTA_MSE_MA_API_SET_NOTIF_REG_RSP, + BTA_MSE_MA_CI_GET_FENTRY, + BTA_MSE_MA_CI_GET_ML_INFO, + BTA_MSE_MA_CI_GET_ML_ENTRY, + BTA_MSE_MA_CI_GET_MSG, + BTA_MSE_MA_CI_PUSH_MSG, + BTA_MSE_MA_CI_DEL_MSG, + BTA_MSE_MA_OBX_CONNECT, + BTA_MSE_MA_OBX_DISC, + BTA_MSE_MA_OBX_CLOSE, + BTA_MSE_MA_OBX_ABORT, + BTA_MSE_MA_OBX_PUT, + BTA_MSE_MA_OBX_GET, + BTA_MSE_MA_OBX_SETPATH, + BTA_MSE_MA_CONN_ERR_RSP, + BTA_MSE_MA_CLOSE_COMPLETE, + BTA_MSE_MA_IGNORE +}; + +/* type for action functions */ +typedef void (*tBTA_MSE_MA_ACTION)(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data); + +/* action function list for MAS */ +const tBTA_MSE_MA_ACTION bta_mse_ma_action[] = +{ + bta_mse_ma_int_close, + bta_mse_ma_api_accessrsp, + bta_mse_ma_api_upd_ibx_rsp, + bta_mse_ma_api_set_notif_reg_rsp, + bta_mse_ma_ci_get_folder_entry, + bta_mse_ma_ci_get_ml_info, + bta_mse_ma_ci_get_ml_entry, + bta_mse_ma_ci_get_msg, + bta_mse_ma_ci_push_msg, + bta_mse_ma_ci_del_msg, + bta_mse_ma_obx_connect, + bta_mse_ma_obx_disc, + bta_mse_ma_obx_close, + bta_mse_ma_obx_abort, + bta_mse_ma_obx_put, + bta_mse_ma_obx_get, + bta_mse_ma_obx_setpath, + bta_mse_ma_conn_err_rsp, + bta_mse_ma_close_complete, +}; + + +/* state table information */ +#define BTA_MSE_MA_ACTIONS 1 /* number of actions */ +#define BTA_MSE_MA_NEXT_STATE 1 /* position of next state */ +#define BTA_MSE_MA_NUM_COLS 2 /* number of columns in state tables */ + + +/* state table for MAS idle state */ +static const UINT8 bta_mse_ma_st_idle[][BTA_MSE_MA_NUM_COLS] = +{ +/* Event Action 1 Next state */ +/* BTA_MSE_INT_CLOSE_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_API_ACCESSRSP_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_API_UPD_IBX_RSP_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_API_SET_NOTIF_REG_RSP_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_INT_START_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, + +/* BTA_MSE_CI_GET_FENTRY_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_CI_GET_ML_INFO_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_CI_GET_ML_ENTRY_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_CI_GET_MSG_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_CI_PUSH_MSG_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_CI_DEL_MSG_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, + +/* BTA_MSE_MA_OBX_CONN_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_MA_OBX_DISC_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_MA_OBX_ABORT_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_MA_OBX_CLOSE_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_MA_OBX_PUT_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_MA_OBX_GET_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_MA_OBX_SETPATH_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +/* BTA_MSE_CLOSE_CMPL_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST}, +}; + +/* state table for obex/rfcomm connection state */ +static const UINT8 bta_mse_ma_st_listen[][BTA_MSE_MA_NUM_COLS] = +{ +/* Event Action 1 Next state */ +/* BTA_MSE_INT_CLOSE_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_API_ACCESSRSP_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_API_UPD_IBX_RSP_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_API_SET_NOTIF_REG_RSP_EVT*/{BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_MA_INT_START_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_CI_GET_FENTRY_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_CI_GET_ML_INFO_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_CI_GET_ML_ENTRY_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_CI_GET_MSG_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_CI_PUSH_MSG_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_CI_DEL_MSG_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_MA_OBX_CONN_EVT */ {BTA_MSE_MA_OBX_CONNECT, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_MA_OBX_DISC_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_MA_OBX_ABORT_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_MA_OBX_CLOSE_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_MA_OBX_PUT_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_MA_OBX_GET_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_MA_OBX_SETPATH_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +/* BTA_MSE_CLOSE_CMPL_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST}, +}; + +/* state table for open state */ +static const UINT8 bta_mse_ma_st_connected[][BTA_MSE_MA_NUM_COLS] = +{ +/* Event Action 1 Next state */ +/* BTA_MSE_INT_CLOSE_EVT */ {BTA_MSE_MA_INT_CLOSE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_API_ACCESSRSP_EVT */ {BTA_MSE_MA_API_ACCESSRSP, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_API_UPD_IBX_RSP_EVT*/ {BTA_MSE_MA_API_UPD_IBX_RSP, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_API_SET_NOTIF_REG_RSP_EVT*/{BTA_MSE_MA_API_SET_NOTIF_REG_RSP,BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_MA_INT_START_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_CI_GET_FENTRY_EVT */ {BTA_MSE_MA_CI_GET_FENTRY, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_CI_GET_ML_INFO_EVT */ {BTA_MSE_MA_CI_GET_ML_INFO, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_CI_GET_ML_ENTRY_EVT*/ {BTA_MSE_MA_CI_GET_ML_ENTRY, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_CI_GET_MSG_EVT */ {BTA_MSE_MA_CI_GET_MSG, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_CI_PUSH_MSG_EVT */ {BTA_MSE_MA_CI_PUSH_MSG, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_CI_DEL_MSG_EVT */ {BTA_MSE_MA_CI_DEL_MSG, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_MA_OBX_CONN_EVT */ {BTA_MSE_MA_CONN_ERR_RSP, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_MA_OBX_DISC_EVT */ {BTA_MSE_MA_OBX_DISC, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_MA_OBX_ABORT_EVT */ {BTA_MSE_MA_OBX_ABORT, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_MA_OBX_CLOSE_EVT */ {BTA_MSE_MA_OBX_CLOSE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_MA_OBX_PUT_EVT */ {BTA_MSE_MA_OBX_PUT, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_MA_OBX_GET_EVT */ {BTA_MSE_MA_OBX_GET, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_MA_OBX_SETPATH_EVT*/ {BTA_MSE_MA_OBX_SETPATH, BTA_MSE_MA_CONN_ST}, +/* BTA_MSE_CLOSE_CMPL_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CONN_ST}, +}; + +/* state table for closing state */ +static const UINT8 bta_mse_ma_st_closing[][BTA_MSE_MA_NUM_COLS] = +{ +/* Event Action 1 Next state */ +/* BTA_MSE_INT_CLOSE_EVT */ {BTA_MSE_MA_INT_CLOSE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_API_ACCESSRSP_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_API_UPD_IBX_RSP_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_API_SET_NOTIF_REG_RSP_EVT*/{BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_MA_INT_START_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_CI_GET_FENTRY_EVT */ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_CI_GET_ML_INFO_EVT*/ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_CI_GET_ML_ENTRY_EVT*/ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_CI_GET_MSG_EVT */ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_CI_PUSH_MSG_EVT */ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_CI_DEL_MSG_EVT */ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_MA_OBX_CONN_EVT */ {BTA_MSE_MA_CONN_ERR_RSP, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_MA_OBX_DISC_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_MA_OBX_ABORT_EVT */ {BTA_MSE_MA_OBX_ABORT, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_MA_OBX_CLOSE_EVT */ {BTA_MSE_MA_OBX_CLOSE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_MA_OBX_PUT_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_MA_OBX_GET_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_MA_OBX_SETPATH_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST}, +/* BTA_MSE_CLOSE_CMPL_EVT */ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_LISTEN_ST}, +}; + +/* type for state table MAS */ +typedef const UINT8 (*tBTA_MSE_MA_ST_TBL)[BTA_MSE_MA_NUM_COLS]; + +/* MAS state table */ +const tBTA_MSE_MA_ST_TBL bta_mse_ma_st_tbl[] = +{ + bta_mse_ma_st_idle, + bta_mse_ma_st_listen, + bta_mse_ma_st_connected, + bta_mse_ma_st_closing +}; + +/***************************************************************************** +** Message Notification Client State Table +*****************************************************************************/ +/***************************************************************************** +** Constants and types +*****************************************************************************/ +/* state machine action enumeration list for MNC */ +/* The order of this enumeration must be the same as bta_mse_mn_act_tbl[] */ +enum +{ + BTA_MSE_MN_INIT_SDP, + BTA_MSE_MN_START_CLIENT, + BTA_MSE_MN_STOP_CLIENT, + BTA_MSE_MN_OBX_CONN_RSP, + BTA_MSE_MN_CLOSE, + BTA_MSE_MN_SEND_NOTIF, + BTA_MSE_MN_RSP_TIMEOUT, + BTA_MSE_MN_PUT_RSP, + BTA_MSE_MN_OBX_TOUT, + BTA_MSE_MN_CLOSE_COMPL, + BTA_MSE_MN_ABORT, + BTA_MSE_MN_ABORT_RSP, + BTA_MSE_MN_SDP_FAIL, + BTA_MSE_MN_IGNORE_OBX, + BTA_MSE_MN_IGNORE +}; + +typedef void (*tBTA_MSE_MN_ACTION)(UINT8 ccb_idx, tBTA_MSE_DATA *p_data); + +static const tBTA_MSE_MN_ACTION bta_mse_mn_action[] = +{ + bta_mse_mn_init_sdp, + bta_mse_mn_start_client, + bta_mse_mn_stop_client, + bta_mse_mn_obx_conn_rsp, + bta_mse_mn_close, + bta_mse_mn_send_notif, + bta_mse_mn_rsp_timeout, + bta_mse_mn_put_rsp, + bta_mse_mn_obx_tout, + bta_mse_mn_close_compl, + bta_mse_mn_abort, + bta_mse_mn_abort_rsp, + bta_mse_mn_sdp_fail, + bta_mse_mn_ignore_obx +}; + + +/* state table information */ +#define BTA_MSE_MN_ACTIONS 1 /* number of actions */ +#define BTA_MSE_MN_ACTION_COL 0 /* position of action */ +#define BTA_MSE_MN_NEXT_STATE 1 /* position of next state */ +#define BTA_MSE_MN_NUM_COLS 2 /* number of columns in state tables */ + +/* state table for idle state */ +static const UINT8 bta_mse_mn_st_idle[][BTA_MSE_MN_NUM_COLS] = +{ +/* Event Action 1 Next state */ +/* BTA_MSE_MN_INT_OPEN_EVT */ {BTA_MSE_MN_INIT_SDP, BTA_MSE_MN_W4_CONN_ST}, +/* BTA_MSE_MN_INT_CLOSE_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_MN_SDP_OK_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_MN_SDP_FAIL_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_MN_OBX_CONN_RSP_EVT */ {BTA_MSE_MN_IGNORE_OBX, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_MN_OBX_PUT_RSP_EVT */ {BTA_MSE_MN_IGNORE_OBX, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_MN_OBX_CLOSE_EVT */ {BTA_MSE_MN_IGNORE_OBX, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_MN_OBX_TOUT_EVT */ {BTA_MSE_MN_IGNORE_OBX, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_MN_CLOSE_CMPL_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_API_SEND_NOTIF_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_API_MN_ABORT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_MN_OBX_ABORT_RSP_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_MN_RSP_TOUT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST} +}; + + +/* state table for wait for authentication state */ +static const UINT8 bta_mse_mn_st_w4_conn[][BTA_MSE_MN_NUM_COLS] = +{ +/* Event Action 1 Next state */ +/* BTA_MSE_MN_INT_OPEN_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST}, +/* BTA_MSE_MN_INT_CLOSE_EVT */ {BTA_MSE_MN_STOP_CLIENT, BTA_MSE_MN_CLOSING_ST}, +/* BTA_MSE_MN_SDP_OK_EVT */ {BTA_MSE_MN_START_CLIENT, BTA_MSE_MN_W4_CONN_ST}, +/* BTA_MSE_MN_SDP_FAIL_EVT */ {BTA_MSE_MN_SDP_FAIL, BTA_MSE_MN_W4_CONN_ST}, +/* BTA_MSE_MN_OBX_CONN_RSP_EVT */ {BTA_MSE_MN_OBX_CONN_RSP, BTA_MSE_MN_CONN_ST}, +/* BTA_MSE_MN_OBX_PUT_RSP_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST}, +/* BTA_MSE_MN_OBX_CLOSE_EVT */ {BTA_MSE_MN_CLOSE, BTA_MSE_MN_CLOSING_ST}, +/* BTA_MSE_MN_OBX_TOUT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST}, +/* BTA_MSE_MN_CLOSE_CMPL_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST}, +/* BTA_MSE_API_SEND_NOTIF_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST}, +/* BTA_MSE_API_MN_ABORT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST}, +/* BTA_MSE_MN_OBX_ABORT_RSP_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST}, +/* BTA_MSE_MN_RSP_TOUT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST} +}; + +/* state table for connected state */ +static const UINT8 bta_mse_mn_st_connected[][BTA_MSE_MN_NUM_COLS] = +{ +/* Event Action 1 Next state */ +/* BTA_MSE_MN_INT_OPEN_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CONN_ST}, +/* BTA_MSE_MN_INT_CLOSE_EVT */ {BTA_MSE_MN_STOP_CLIENT, BTA_MSE_MN_CLOSING_ST}, +/* BTA_MSE_MN_SDP_OK_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CONN_ST}, +/* BTA_MSE_MN_SDP_FAIL_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CONN_ST}, +/* BTA_MSE_MN_OBX_CONN_RSP_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CONN_ST}, +/* BTA_MSE_MN_OBX_PUT_RSP_EVT */ {BTA_MSE_MN_PUT_RSP, BTA_MSE_MN_CONN_ST}, +/* BTA_MSE_MN_OBX_CLOSE_EVT */ {BTA_MSE_MN_CLOSE, BTA_MSE_MN_CLOSING_ST}, +/* BTA_MSE_MN_OBX_TOUT_EVT */ {BTA_MSE_MN_OBX_TOUT, BTA_MSE_MN_CONN_ST}, +/* BTA_MSE_MN_CLOSE_CMPL_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CONN_ST}, +/* BTA_MSE_API_SEND_NOTIF_EVT */ {BTA_MSE_MN_SEND_NOTIF, BTA_MSE_MN_CONN_ST}, +/* BTA_MSE_API_MN_ABORT_EVT */ {BTA_MSE_MN_ABORT, BTA_MSE_MN_CONN_ST}, +/* BTA_MSE_MN_OBX_ABORT_RSP_EVT */ {BTA_MSE_MN_ABORT_RSP, BTA_MSE_MN_CONN_ST}, +/* BTA_MSE_MN_RSP_TOUT_EVT */ {BTA_MSE_MN_RSP_TIMEOUT, BTA_MSE_MN_CLOSING_ST} +}; + +/* state table for closing state */ +static const UINT8 bta_mse_mn_st_closing[][BTA_MSE_MN_NUM_COLS] = +{ +/* Event Action 1 Next state */ +/* BTA_MSE_MN_INT_OPEN_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST}, +/* BTA_MSE_MN_INT_CLOSE_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST}, +/* BTA_MSE_MN_SDP_OK_EVT */ {BTA_MSE_MN_CLOSE_COMPL, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_MN_SDP_FAIL_EVT */ {BTA_MSE_MN_CLOSE_COMPL, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_MN_OBX_CONN_RSP_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST}, +/* BTA_MSE_MN_OBX_PUT_RSP_EVT */ {BTA_MSE_MN_IGNORE_OBX, BTA_MSE_MN_CLOSING_ST}, +/* BTA_MSE_MN_OBX_CLOSE_EVT */ {BTA_MSE_MN_CLOSE, BTA_MSE_MN_CLOSING_ST}, +/* BTA_MSE_MN_OBX_TOUT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST}, +/* BTA_MSE_MN_CLOSE_CMPL_EVT */ {BTA_MSE_MN_CLOSE_COMPL, BTA_MSE_MN_IDLE_ST}, +/* BTA_MSE_API_SEND_NOTIF_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST}, +/* BTA_MSE_API_MN_ABORT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST}, +/* BTA_MSE_MN_OBX_ABORT_RSP_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST}, +/* BTA_MSE_MN_RSP_TOUT_EVT */ {BTA_MSE_MN_RSP_TIMEOUT, BTA_MSE_MN_CLOSING_ST} +}; + +/* type for state table */ +typedef const UINT8 (*tBTA_MSE_MN_ST_TBL)[BTA_MSE_MN_NUM_COLS]; + +/* state table */ +const tBTA_MSE_MN_ST_TBL bta_mse_mn_st_tbl[] = +{ + bta_mse_mn_st_idle, + bta_mse_mn_st_w4_conn, + bta_mse_mn_st_connected, + bta_mse_mn_st_closing +}; +/***************************************************************************** +** Global data +*****************************************************************************/ + +/* MSE control block */ +#if BTA_DYNAMIC_MEMORY == FALSE +tBTA_MSE_CB bta_mse_cb; +#endif + +#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE) + +static char *bta_mse_evt_code(tBTA_MSE_INT_EVT evt_code); +static char *bta_mse_ma_state_code(tBTA_MSE_MA_STATE state_code); +static char *bta_mse_mn_state_code(tBTA_MSE_MN_STATE state_code); +#endif + +/******************************************************************************* +** +** Function bta_mse_ma_sm_execute +** +** Description State machine event handling function for MA +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** event - MA event +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_ma_sm_execute(UINT8 inst_idx, UINT8 sess_idx, UINT16 event, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MA_ST_TBL state_table; + UINT8 action; + int i; + tBTA_MSE_MA_SESS_CB *p_cb = &(bta_mse_cb.scb[inst_idx].sess_cb[sess_idx]); + +#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE) + tBTA_MSE_MA_STATE in_state = p_cb->state; + UINT16 cur_evt = event; + APPL_TRACE_EVENT3("MSE MA Event Handler: State 0x%02x [%s], Event [%s]", in_state, + bta_mse_ma_state_code(in_state), + bta_mse_evt_code(cur_evt)); +#endif + + /* look up the state table for the current state */ + state_table = bta_mse_ma_st_tbl[p_cb->state]; + + event &= 0x00FF; + + /* set next state */ + p_cb->state = state_table[event][BTA_MSE_MA_NEXT_STATE]; + + /* execute action functions */ + for (i = 0; i < BTA_MSE_MA_ACTIONS; i++) + { + if ((action = state_table[event][i]) != BTA_MSE_MA_IGNORE) + { + (*bta_mse_ma_action[action])(inst_idx, sess_idx, p_data); + } + else + { + /* discard mas data */ + bta_mse_discard_data(p_data->hdr.event, p_data); + break; + } + } +#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE) + if (in_state != p_cb->state) + { + APPL_TRACE_EVENT3("MSE MA State Change: [%s] -> [%s] after Event [%s]", + bta_mse_ma_state_code(in_state), + bta_mse_ma_state_code(p_cb->state), + bta_mse_evt_code(cur_evt)); + } +#endif + +} + +/******************************************************************************* +** +** Function bta_mse_mn_sm_execute +** +** Description State machine event handling function for MNC +** +** Parameters mn_cb_idx - Index to the MN control block +** event - MN event +** p_data - Pointer to the event data +** +** Returns void +** +*******************************************************************************/ +void bta_mse_mn_sm_execute(UINT8 mn_cb_idx, UINT16 event, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_CB *p_cb = &(bta_mse_cb.ccb[mn_cb_idx]); + tBTA_MSE_MN_ST_TBL state_table; + UINT8 action; + int i; + + + +#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE) + tBTA_MSE_MN_STATE in_state = p_cb->state; + UINT16 cur_evt = event; + APPL_TRACE_EVENT3("MSE MN Event Handler: State 0x%02x [%s], Event [%s]", in_state, + bta_mse_mn_state_code(in_state), + bta_mse_evt_code(cur_evt)); +#endif + + /* look up the state table for the current state */ + state_table = bta_mse_mn_st_tbl[p_cb->state]; + event -= BTA_MSE_MN_EVT_MIN; + + /* set next state */ + p_cb->state = state_table[event][BTA_MSE_MN_NEXT_STATE]; + + /* execute action functions */ + for (i = 0; i < BTA_MSE_MN_ACTIONS; i++) + { + if ((action = state_table[event][i]) != BTA_MSE_MN_IGNORE) + { + (*bta_mse_mn_action[action])(mn_cb_idx, p_data); + } + else + { + /* discard mas data */ + bta_mse_discard_data(p_data->hdr.event, p_data); + break; + } + } + + +#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE) + if (in_state != p_cb->state) + { + APPL_TRACE_EVENT3("MSE MN State Change: [%s] -> [%s] after Event [%s]", + bta_mse_mn_state_code(in_state), + bta_mse_mn_state_code(p_cb->state), + bta_mse_evt_code(cur_evt)); + } +#endif +} +/******************************************************************************* +** +** Function bta_mse_ma_api_enable +** +** Description Process API enable request to enable MCE subsystem +** +** Parameters p_cb - Pointer to MSE control block +** p_data - Pointer to MSE event data +** +** Returns void +** +*******************************************************************************/ +static void bta_mse_ma_api_enable(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE evt_data; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("bta_mse_ma_api_enable" ); +#endif + /* If already enabled then reject this request */ + if (p_cb->enable) + { + APPL_TRACE_ERROR0("MSE is already enabled"); + evt_data.enable.app_id = p_data->api_enable.app_id; + evt_data.enable.status = BTA_MA_STATUS_FAIL; + p_data->api_enable.p_cback(BTA_MSE_ENABLE_EVT, (tBTA_MSE *) &evt_data); + return; + } + + /* Done with checking. now perform the enable oepration*/ + /* initialize control block */ + memset(p_cb, 0, sizeof(tBTA_MSE_CB)); + + p_cb->p_cback = p_data->api_enable.p_cback; + p_cb->app_id = p_data->api_enable.app_id; + p_cb->enable = TRUE; + + evt_data.enable.app_id = p_cb->app_id; + evt_data.enable.status = BTA_MA_STATUS_OK; + p_cb->p_cback(BTA_MSE_ENABLE_EVT, (tBTA_MSE *) &evt_data); +} +/******************************************************************************* +** +** Function bta_mse_ma_api_disable +** +** Description Process API disable request +** +** Parameters p_cb - Pointer to MSE control block +** p_data - Pointer to MSE event data +** +** Returns void +** +*******************************************************************************/ +static void bta_mse_ma_api_disable(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE evt_data; + tBTA_MA_STATUS status = BTA_MA_STATUS_OK; + UINT8 app_id = p_data->api_disable.app_id; + UINT8 i,j, num_act_mas=0, num_act_sess=0; + tBTA_MSE_MA_CB *p_scb; + tBTA_MSE_MA_SESS_CB *p_sess_cb; + BOOLEAN send_disable_evt =FALSE; + tBTA_MSE_MN_CB *p_ccb; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("bta_mse_ma_api_disable" ); +#endif + + if (p_cb->enable) + { + /* close all MN connections */ + for (i=0; i < BTA_MSE_NUM_MN; i ++) + { + p_ccb = BTA_MSE_GET_MN_CB_PTR(i); + if (p_ccb->in_use && + (p_ccb->state != BTA_MSE_MN_IDLE_ST)) + { + bta_mse_mn_remove_all_inst_ids(i); + bta_mse_mn_sm_execute(i,BTA_MSE_MN_INT_CLOSE_EVT, NULL); + } + } + + 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++; + p_cb->disabling = TRUE; + p_scb->stopping = TRUE; + num_act_sess =0; + for (j=0; j<BTA_MSE_NUM_SESS; j++ ) + { + p_sess_cb = BTA_MSE_GET_SESS_CB_PTR(i, j); + if (p_sess_cb->state != BTA_MSE_MA_LISTEN_ST) + { + bta_mse_ma_sm_execute(i, j, BTA_MSE_INT_CLOSE_EVT, p_data); + num_act_sess++; + } + } + + if (!num_act_sess) + { + evt_data.stop.status = BTA_MA_STATUS_OK; + evt_data.stop.mas_instance_id = p_scb->mas_inst_id; + p_cb->p_cback(BTA_MSE_STOP_EVT, (tBTA_MSE *) &evt_data); + bta_mse_clean_mas_service(i); + num_act_mas--; + } + } + } + + if (!num_act_mas) + { + send_disable_evt = TRUE; + p_cb->enable = FALSE; + } + } + else + { + send_disable_evt = TRUE; + status = BTA_MA_STATUS_FAIL; + } + + + if (send_disable_evt) + { + evt_data.enable.app_id = app_id; + evt_data.enable.status = status; + p_cb->p_cback(BTA_MSE_DISABLE_EVT, (tBTA_MSE *) &evt_data); +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("MSE Disabled location-1"); +#endif + } + +} +/******************************************************************************* +** +** Function bta_mse_ma_api_start +** +** Description Process API MA server start request +** +** Parameters p_cb - Pointer to MSE control block +** p_data - Pointer to MSE event data +** +** Returns void +** +*******************************************************************************/ +static void bta_mse_ma_api_start(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data) +{ + UINT8 i = 0; + tBTA_MSE evt_data; /* event call back */ + tBTA_MSE_MA_CB *p_scb = NULL; /* MA instance control block*/ + tOBX_StartParams start_msg; + tBTA_MSE_API_START *p_api = &p_data->api_start; + tOBX_TARGET target; + tOBX_STATUS status; + tBTA_UTL_COD cod; + UINT8 mas_instance_idx; + UINT16 root_folder_len; + tBTA_MA_STATUS ma_status = BTA_MA_STATUS_OK; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("bta_mse_ma_api_start" ); +#endif + if (!p_cb->enable || ((p_cb->enable) && bta_mse_is_a_duplicate_id(p_api->mas_inst_id)) ) + { + ma_status = BTA_MA_STATUS_DUPLICATE_ID; + } + + if ((ma_status == BTA_MA_STATUS_OK) && bta_mse_find_avail_mas_inst_cb_idx(&mas_instance_idx)) + { + APPL_TRACE_EVENT1("bta_mse_ma_api_start inst_idx=%d",mas_instance_idx ); + + /* initialize the MA Instance control block */ + p_scb = &(p_cb->scb[mas_instance_idx]); + memset(p_scb, 0, sizeof(tBTA_MSE_MA_CB)); + + p_scb->in_use = TRUE; + BCM_STRNCPY_S(p_scb->servicename, sizeof(p_scb->servicename), p_api->servicename, BTA_SERVICE_NAME_LEN); + p_scb->mas_inst_id = p_api->mas_inst_id; + p_scb->sec_mask = p_api->sec_mask; + p_scb->sup_msg_type = p_api->sup_msg_type; + + /* If directory is specified set the length */ + root_folder_len = p_bta_fs_cfg->max_path_len + 1; + + /* Allocate an aligned memory buffer to hold the root path in the */ + /* MAS instance cb as well as the session cbs */ + /* Add 1 byte for '\0' */ + if ((p_scb->p_rootpath = (char *)GKI_getbuf((UINT16)(root_folder_len+1))) != NULL) + { + memcpy(target.target, BTA_MAS_MESSAGE_ACCESS_TARGET_UUID, BTA_MAS_UUID_LENGTH); + target.len = BTA_MAS_UUID_LENGTH; + p_scb->scn = BTM_AllocateSCN(); + BCM_STRNCPY_S(p_scb->p_rootpath, root_folder_len+1, p_api->p_root_path, root_folder_len); + p_scb->p_rootpath[root_folder_len] = '\0'; + + /* Register MAP security requirements with BTM */ + BTM_SetSecurityLevel(FALSE, p_api->servicename, BTM_SEC_SERVICE_MAP, + p_api->sec_mask, BT_PSM_RFCOMM, + BTM_SEC_PROTO_RFCOMM, (UINT32)p_scb->scn); + + /* Start up the MSE service */ + memset(&start_msg, 0, sizeof(tOBX_StartParams)); + start_msg.p_target = ⌖ + /* Make the MTU fit into one RFC frame */ + start_msg.mtu = OBX_MAX_MTU; + start_msg.scn = p_scb->scn; + start_msg.authenticate = FALSE; /* OBX authentication is disabled */ + start_msg.auth_option = (UINT8) NULL; + start_msg.p_cback = bta_mse_ma_obx_cback; + start_msg.realm_len =(UINT8) NULL; + start_msg.p_realm = (UINT8) NULL; + start_msg.realm_charset = (tOBX_CHARSET) NULL; + start_msg.max_sessions = BTA_MSE_NUM_SESS; + + if ((status = OBX_StartServer (&start_msg, &p_scb->obx_handle)) == OBX_SUCCESS) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("Obx start for MAS server: obx_hdl=%d", p_scb->obx_handle); +#endif + /* initialze all session states */ + for (i=0; i<BTA_MSE_NUM_SESS; i++ ) + { + p_scb->sess_cb[i].state = BTA_MSE_MA_LISTEN_ST; + } + + if (ma_status == BTA_MA_STATUS_OK) + { + /* Set the File Transfer service class bit */ + cod.service = BTM_COD_SERVICE_OBJ_TRANSFER; + utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS); + + /* Set up the SDP record for pbs service */ + bta_mse_ma_sdp_register(p_scb, p_api->servicename, p_scb->mas_inst_id, p_scb->sup_msg_type ); + } + else + { + /* release resources */ + OBX_StopServer(p_scb->obx_handle); + for (i=0; i < BTA_MSE_NUM_SESS; i++ ) + { + utl_freebuf((void**)&p_scb->sess_cb[i].p_workdir ); + } + } + } + else + { + /* release resources */ + utl_freebuf((void**)&p_scb->p_rootpath); + APPL_TRACE_ERROR1("OBX_StartServer returns error (%d)", status); + ma_status = BTA_MA_STATUS_NO_RESOURCE; + } + } + else /* Cannot allocate resources to run Server */ + { + APPL_TRACE_ERROR0("Not enough Resources to run MSE Server"); + ma_status = BTA_MA_STATUS_NO_RESOURCE; + } + + if (ma_status != BTA_MA_STATUS_OK) + { + /* clearn up the contrl block*/ + memset(p_scb, 0, sizeof(tBTA_MSE_MA_CB)); + } + } + + evt_data.start.mas_instance_id = p_api->mas_inst_id; + evt_data.start.status = ma_status; + p_cb->p_cback(BTA_MSE_START_EVT, (tBTA_MSE *) &evt_data); + +} +/******************************************************************************* +** +** Function bta_mse_ma_api_stop +** +** Description Process API MA server stop request +** +** Parameters p_cb - Pointer to MSE control block +** p_data - Pointer to MSE event data +** +** Returns void +** +*******************************************************************************/ +static void bta_mse_ma_api_stop(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_API_STOP *p_stop = &p_data->api_stop; + BOOLEAN send_stop_evt = FALSE; + tBTA_MA_STATUS status = BTA_MA_STATUS_OK; + tBTA_MSE_MA_CB *p_scb; + tBTA_MSE_MA_SESS_CB *p_sess_cb; + tBTA_MSE_MN_CB *p_ccb; + UINT8 i, inst_idx; + UINT8 num_act_sess=0; + tBTA_MSE evt_data; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("bta_mse_ma_api_stop" ); +#endif + + + if (bta_mse_find_mas_inst_id_match_cb_idx(p_stop->mas_inst_id, &inst_idx)) + { + p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx); + p_scb->stopping = TRUE; + + for (i=0; i < BTA_MSE_NUM_MN; i ++) + { + p_ccb = BTA_MSE_GET_MN_CB_PTR(i); + if (p_ccb->in_use && + (p_ccb->state != BTA_MSE_MN_IDLE_ST) && + bta_mse_mn_is_ok_to_close_mn(p_ccb->bd_addr,p_scb->mas_inst_id)) + { + /* close the MN connection if mas_inst_id is the last active inst_id */ + bta_mse_mn_remove_inst_id(i, p_scb->mas_inst_id); + bta_mse_mn_sm_execute(i,BTA_MSE_MN_INT_CLOSE_EVT, NULL); + } + } + /* close all active session */ + for (i=0; i < BTA_MSE_NUM_SESS; i ++) + { + p_sess_cb = &(p_scb->sess_cb[i]); + if (p_sess_cb->state != BTA_MSE_MA_LISTEN_ST) + { + APPL_TRACE_EVENT2("Send API CLOSE to SM for STOP sess ind=%d state=%d",i,p_sess_cb->state); + bta_mse_ma_sm_execute(inst_idx, i, BTA_MSE_INT_CLOSE_EVT, p_data); + num_act_sess++; + } + } + + if (!num_act_sess) + { + bta_mse_clean_mas_service(inst_idx); + send_stop_evt = TRUE; + } + } + else + { + send_stop_evt = TRUE; + status = BTA_MA_STATUS_FAIL; + } + + if (send_stop_evt) + { + evt_data.stop.status = status; + evt_data.stop.mas_instance_id = p_stop->mas_inst_id; + p_cb->p_cback(BTA_MSE_STOP_EVT, (tBTA_MSE *) &evt_data); + } +} + +/******************************************************************************* +** +** Function bta_mse_ma_api_close +** +** Description Process API close request. It will close all MA +** sesions on the specified MAS instance ID +** +** Parameters p_cb - Pointer to MSE control block +** p_data - Pointer to MSE event data +** +** Returns void +** +*******************************************************************************/ +static void bta_mse_ma_api_close(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_API_CLOSE *p_close = &p_data->api_close; + BOOLEAN send_close_evt = FALSE; + tBTA_MA_STATUS status = BTA_MA_STATUS_OK; + tBTA_MSE_MA_CB *p_scb; + tBTA_MSE_MA_SESS_CB *p_sess_cb; + UINT8 i, inst_idx; + UINT8 num_act_sess=0; + tBTA_MSE evt_data; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("bta_mse_ma_api_close" ); +#endif + if (bta_mse_find_mas_inst_id_match_cb_idx(p_close->mas_instance_id, &inst_idx)) + { + p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx); + /* close all active sessions for the specified MA Server */ + for (i=0; i < BTA_MSE_NUM_SESS; i ++) + { + p_sess_cb = &(p_scb->sess_cb[i]); + if (p_sess_cb->state != BTA_MSE_MA_LISTEN_ST) + { +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT4("Disconnect inst_id=%d, sess_id=%d, inst_idx=%d, sess_idx=%d", + p_close->mas_instance_id, + p_sess_cb->obx_handle, + inst_idx, + i); +#endif + + bta_mse_ma_sm_execute(inst_idx, i, BTA_MSE_INT_CLOSE_EVT, p_data); + num_act_sess++; + } + } + + if (!num_act_sess) + { + send_close_evt = TRUE; + } + } + else + { + send_close_evt = TRUE; + status = BTA_MA_STATUS_FAIL; + } + + if (send_close_evt) + { + evt_data.ma_close.status = status; + evt_data.ma_close.mas_session_id = 0; + evt_data.ma_close.mas_instance_id = p_close->mas_instance_id ; + p_cb->p_cback(BTA_MSE_MA_CLOSE_EVT, (tBTA_MSE *) &evt_data); + } +} + +/******************************************************************************* +** +** Function bta_mse_ma_api_ma_close +** +** Description Process API MA close request. It will close the +** specified MA session. +** +** Parameters p_cb - Pointer to MSE control block +** p_data - Pointer to MSE event data +** +** +** Returns void +** +*******************************************************************************/ +static void bta_mse_ma_api_ma_close(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_API_MA_CLOSE *p_ma_close = &p_data->api_ma_close; + UINT8 inst_idx, sess_idx; + tBTA_MSE evt_data; + + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("bta_mse_ma_api_ma_close" ); +#endif + + if (bta_mse_find_mas_inst_id_match_cb_idx (p_ma_close->mas_instance_id, &inst_idx)&& + bta_mse_find_bd_addr_match_sess_cb_idx(p_ma_close->bd_addr,inst_idx,&sess_idx)) + { + bta_mse_ma_sm_execute(inst_idx, sess_idx, BTA_MSE_INT_CLOSE_EVT, p_data); + } + else + { + evt_data.ma_close.mas_session_id = 0xFF; + evt_data.ma_close.mas_instance_id = p_ma_close->mas_instance_id; + evt_data.ma_close.status = BTA_MA_STATUS_FAIL ; + p_cb->p_cback(BTA_MSE_MA_CLOSE_EVT, (tBTA_MSE *) &evt_data); + } +} + + +/******************************************************************************* +** +** Function bta_mse_mn_api_close +** +** Description Process API MN close request. +** +** Parameters p_cb - Pointer to MSE control block +** p_data - Pointer to MSE event data +** +** Returns void +** +*******************************************************************************/ +static void bta_mse_mn_api_close(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_API_MN_CLOSE *p_mn_close = &p_data->api_mn_close; + UINT8 ccb_idx; + tBTA_MSE evt_data; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("bta_mse_mn_api_close" ); +#endif + + if (bta_mse_find_bd_addr_match_mn_cb_index(p_mn_close->bd_addr, &ccb_idx)) + { + bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_INT_CLOSE_EVT, p_data); + } + else + { + evt_data.mn_close.bd_addr[0] = '\0'; + evt_data.mn_close.dev_name[0] = '\0'; + p_cb->p_cback(BTA_MSE_MN_CLOSE_EVT, (tBTA_MSE *) &evt_data); + } +} + +/******************************************************************************* +** +** Function bta_mse_mn_api_send_notif +** +** Description Process API send message notification report to all MCEs +** registered with the specified MAS instance ID +** +** Parameters p_cb - Pointer to MSE control block +** p_data - Pointer to MSE event data +** +** Returns void +** +*******************************************************************************/ +static void bta_mse_mn_api_send_notif(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_API_SEND_NOTIF *p_mn_send_notif = &p_data->mn_send_notif; + UINT8 i; + tBTA_MSE evt_data; + tBTA_MSE_MN_CB *p_ccb; + UINT8 active_sess_cnt; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("bta_mse_mn_api_send_notif" ); +#endif + + active_sess_cnt =0 ; + for (i=0; i < BTA_MSE_NUM_MN; i ++) + { + p_ccb = BTA_MSE_GET_MN_CB_PTR(i); + + if (p_ccb->in_use && + (p_ccb->state == BTA_MSE_MN_CONN_ST) && + (memcmp(p_ccb->bd_addr, p_mn_send_notif->except_bd_addr, BD_ADDR_LEN) != 0 ) && + bta_mse_mn_is_inst_id_exist(i,p_mn_send_notif->mas_instance_id)) + { + bta_mse_mn_sm_execute(i, BTA_MSE_API_SEND_NOTIF_EVT, p_data); + active_sess_cnt++; + } + } + + if (!active_sess_cnt) + { + evt_data.send_notif.mas_instance_id = p_mn_send_notif->mas_instance_id; + evt_data.send_notif.status = BTA_MA_STATUS_FAIL; + memset(evt_data.send_notif.bd_addr,0, sizeof(evt_data.send_notif.bd_addr)); + p_cb->p_cback(BTA_MSE_SEND_NOTIF_EVT, (tBTA_MSE *) &evt_data); + } + +} + + +/******************************************************************************* +** +** Function bta_mse_mn_api_abort +** +** Description Abort the current OBEX multi-packet oepration +** +** Parameters p_cb - Pointer to MSE control block +** p_data - Pointer to MSE event data +** +** Returns void +** +*******************************************************************************/ +static void bta_mse_mn_api_abort(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data) +{ + tBTA_MSE_MN_API_ABORT *p_mn_abort = &p_data->mn_abort; + UINT8 i; + tBTA_MSE_MN_CB *p_ccb; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("bta_mse_mn_api_abort" ); +#endif + + for (i=0; i < BTA_MSE_NUM_MN; i ++) + { + p_ccb = BTA_MSE_GET_MN_CB_PTR(i); + if (p_ccb->in_use && + (p_ccb->state == BTA_MSE_MN_CONN_ST) && + bta_mse_mn_is_inst_id_exist(i,p_mn_abort->mas_instance_id)) + { + bta_mse_mn_sm_execute(i, BTA_MSE_API_MN_ABORT_EVT, p_data); + } + } + +} + +/******************************************************************************* +** +** Function bta_mse_mn_rsp_tout +** +** Description Process MN response timer timeout event +** +** Parameters p_cb - Pointer to MSE control block +** p_data - Pointer to MSE event data +** +** Returns void +** +*******************************************************************************/ +static void bta_mse_mn_rsp_tout(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data) +{ + UINT8 ccb_idx; + + ccb_idx = (UINT8)(p_data->hdr.event - BTA_MSE_MN_RSP0_TOUT_EVT); + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("bta_mse_mn_rsp_tout ccd_idx=%d",ccb_idx); +#endif + bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_RSP_TOUT_EVT, p_data); +} +/******************************************************************************* +** +** Function bta_mse_hdl_event +** +** Description MSE main event handling function. +** +** Parameters p_msg - Pointer to MSE event data +** +** Returns void +** +*******************************************************************************/ +BOOLEAN bta_mse_hdl_event(BT_HDR *p_msg){ + UINT8 inst_idx, sess_idx, ccb_idx; + BOOLEAN success = TRUE; + +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT1("MSE Event Handler: Event [%s]", + bta_mse_evt_code(p_msg->event)); +#endif + + switch (p_msg->event) + { + case BTA_MSE_API_ENABLE_EVT: + bta_mse_ma_api_enable(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg); + break; + + case BTA_MSE_API_START_EVT: + bta_mse_ma_api_start(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg); + break; + + case BTA_MSE_API_STOP_EVT: + bta_mse_ma_api_stop(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg); + break; + + case BTA_MSE_API_DISABLE_EVT: + bta_mse_ma_api_disable(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg); + break; + + case BTA_MSE_API_CLOSE_EVT: + bta_mse_ma_api_close(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg); + break; + + case BTA_MSE_API_MA_CLOSE_EVT: + bta_mse_ma_api_ma_close(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg); + break; + + case BTA_MSE_API_MN_CLOSE_EVT: + bta_mse_mn_api_close(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg); + break; + + case BTA_MSE_API_SEND_NOTIF_EVT: + bta_mse_mn_api_send_notif(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg); + break; + + case BTA_MSE_API_MN_ABORT_EVT: + bta_mse_mn_api_abort(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg); + break; + + case BTA_MSE_MN_RSP0_TOUT_EVT: + case BTA_MSE_MN_RSP1_TOUT_EVT: + case BTA_MSE_MN_RSP2_TOUT_EVT: + case BTA_MSE_MN_RSP3_TOUT_EVT: + case BTA_MSE_MN_RSP4_TOUT_EVT: + case BTA_MSE_MN_RSP5_TOUT_EVT: + case BTA_MSE_MN_RSP6_TOUT_EVT: + bta_mse_mn_rsp_tout(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg); + break; + + default: + + if (p_msg->event < BTA_MSE_MN_EVT_MIN) + { + if (bta_mse_find_ma_cb_indexes((tBTA_MSE_DATA *) p_msg, &inst_idx, &sess_idx)) + { + bta_mse_ma_sm_execute( inst_idx , + sess_idx , + p_msg->event, (tBTA_MSE_DATA *) p_msg); + } + else + { + APPL_TRACE_ERROR1("unable to find inst_idx and sess_idx: event=%s", + bta_mse_evt_code(p_msg->event)); + success = FALSE; + bta_mse_ma_cleanup ((tBTA_MSE_DATA *) p_msg); + } + } + else + { + if (bta_mse_find_mn_cb_index((tBTA_MSE_DATA *) p_msg, &ccb_idx)) + { + bta_mse_mn_sm_execute( ccb_idx, + p_msg->event , + (tBTA_MSE_DATA *) p_msg); + } + else + { + APPL_TRACE_ERROR1("unable to find ccb_idx: event=%s", + bta_mse_evt_code(p_msg->event)); + success = FALSE; + bta_mse_mn_cleanup ((tBTA_MSE_DATA *) p_msg); + } + } + break; + } + + return(success); +} + + +/***************************************************************************** +** Debug Functions +*****************************************************************************/ +#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE) +/******************************************************************************* +** +** Function bta_mse_ma_evt_code +** +** Description Maps MA event code to the corresponding event string +** +** Parameters evt_code - MA event code +** +** Returns string pointer for the associated event name +** +*******************************************************************************/ +static char *bta_mse_evt_code(tBTA_MSE_INT_EVT evt_code){ + switch (evt_code) + { + case BTA_MSE_API_CLOSE_EVT: + return "BTA_MSE_API_CLOSE_EVT"; + case BTA_MSE_API_MA_CLOSE_EVT: + return "BTA_MSE_API_MA_CLOSE_EVT"; + case BTA_MSE_API_MN_CLOSE_EVT: + return "BTA_MSE_API_MN_CLOSE_EVT"; + case BTA_MSE_INT_CLOSE_EVT: + return "BTA_MSE_INT_CLOSE_EVT"; + case BTA_MSE_API_ACCESSRSP_EVT: + return "BTA_MSE_API_ACCESSRSP_EVT"; + case BTA_MSE_API_UPD_IBX_RSP_EVT: + return "BTA_MSE_API_UPD_IBX_RSP_EVT"; + case BTA_MSE_API_SET_NOTIF_REG_RSP_EVT: + return "BTA_MSE_API_SET_NOTIF_REG_RSP_EVT"; + case BTA_MSE_INT_START_EVT: + return "BTA_MSE_INT_START_EVT"; + case BTA_MSE_CI_GET_FENTRY_EVT: + return "BTA_MSE_CI_GET_FENTRY_EVT"; + case BTA_MSE_CI_GET_ML_INFO_EVT: + return "BTA_MSE_CI_GET_ML_INFO_EVT"; + case BTA_MSE_CI_GET_ML_ENTRY_EVT: + return "BTA_MSE_CI_GET_ML_ENTRY_EVT"; + case BTA_MSE_CI_GET_MSG_EVT: + return "BTA_MSE_CI_GET_MSG_EVT"; + case BTA_MSE_CI_PUSH_MSG_EVT: + return "BTA_MSE_CI_PUSH_MSG_EVT"; + case BTA_MSE_CI_DEL_MSG_EVT: + return "BTA_MSE_CI_DEL_MSG_EVT"; + case BTA_MSE_MA_OBX_CONN_EVT: + return "BTA_MSE_MA_OBX_CONN_EVT"; + case BTA_MSE_MA_OBX_DISC_EVT: + return "BTA_MSE_MA_OBX_DISC_EVT"; + case BTA_MSE_MA_OBX_ABORT_EVT: + return "BTA_MSE_MA_OBX_ABORT_EVT"; + case BTA_MSE_MA_OBX_CLOSE_EVT: + return "BTA_MSE_MA_OBX_CLOSE_EVT"; + case BTA_MSE_MA_OBX_PUT_EVT: + return "BTA_MSE_MA_OBX_PUT_EVT"; + case BTA_MSE_MA_OBX_GET_EVT: + return "BTA_MSE_MA_OBX_GET_EVT"; + case BTA_MSE_MA_OBX_SETPATH_EVT: + return "BTA_MSE_MA_OBX_SETPATH_EVT"; + case BTA_MSE_CLOSE_CMPL_EVT: + return "BTA_MSE_CLOSE_CMPL_EVT"; + case BTA_MSE_MN_INT_OPEN_EVT: + return "BTA_MSE_MN_INT_OPEN_EVT"; + case BTA_MSE_MN_INT_CLOSE_EVT: + return "BTA_MSE_MN_INT_CLOSE_EVT"; + case BTA_MSE_MN_SDP_OK_EVT: + return "BTA_MSE_MN_SDP_OK_EVT"; + case BTA_MSE_MN_SDP_FAIL_EVT: + return "BTA_MSE_MN_SDP_FAIL_EVT"; + case BTA_MSE_MN_OBX_CONN_RSP_EVT: + return "BTA_MSE_MN_OBX_CONN_RSP_EVT"; + case BTA_MSE_MN_OBX_PUT_RSP_EVT: + return "BTA_MSE_MN_OBX_PUT_RSP_EVT"; + case BTA_MSE_MN_OBX_CLOSE_EVT: + return "BTA_MSE_MN_OBX_CLOSE_EVT"; + case BTA_MSE_MN_OBX_TOUT_EVT: + return "BTA_MSE_MN_OBX_TOUT_EVT"; + case BTA_MSE_MN_CLOSE_CMPL_EVT: + return "BTA_MSE_MN_CLOSE_CMPL_EVT"; + case BTA_MSE_API_SEND_NOTIF_EVT: + return "BTA_MSE_API_SEND_NOTIF_EVT"; + case BTA_MSE_API_MN_ABORT_EVT: + return "BTA_MSE_API_MN_ABORT_EVT"; + case BTA_MSE_MN_OBX_ABORT_RSP_EVT: + return "BTA_MSE_MN_OBX_ABORT_RSP_EVT"; + case BTA_MSE_API_ENABLE_EVT: + return "BTA_MSE_API_ENABLE_EVT"; + case BTA_MSE_API_START_EVT: + return "BTA_MSE_API_START_EVT"; + case BTA_MSE_API_STOP_EVT: + return "BTA_MSE_API_STOP_EVT"; + default: + return "Unknown MSE event code"; + } +} + +/******************************************************************************* +** +** Function bta_mse_ma_state_code +** +** Description Maps MA state code to the corresponding state string +** +** Parameters state_code - MA state code +** +** Returns string pointer for the associated state name +** +*******************************************************************************/ +static char *bta_mse_ma_state_code(tBTA_MSE_MA_STATE state_code){ + switch (state_code) + { + case BTA_MSE_MA_IDLE_ST: + return "BTA_MSE_MA_IDLE_ST"; + case BTA_MSE_MA_LISTEN_ST: + return "BTA_MSE_MA_LISTEN_ST"; + case BTA_MSE_MA_CONN_ST: + return "BTA_MSE_MA_CONN_ST"; + case BTA_MSE_MA_CLOSING_ST: + return "BTA_MSE_MA_CLOSING_ST"; + default: + return "Unknown MA state code"; + } +} + + +/******************************************************************************* +** +** Function bta_mse_mn_state_code +** +** Description Maps MN state code to the corresponding state string +** +** Parameters state_code - MN state code +** +** Returns string pointer for the associated state name +** +*******************************************************************************/ +static char *bta_mse_mn_state_code(tBTA_MSE_MN_STATE state_code){ + switch (state_code) + { + case BTA_MSE_MN_IDLE_ST: + return "BTA_MSE_MN_IDLE_ST"; + case BTA_MSE_MN_W4_CONN_ST: + return "BTA_MSE_MN_W4_CONN_ST"; + case BTA_MSE_MN_CONN_ST: + return "BTA_MSE_MN_CONN_ST"; + case BTA_MSE_MN_CLOSING_ST: + return "BTA_MSE_MN_CLOSING_ST"; + default: + return "Unknown MN state code"; + } +} + +#endif /* Debug Functions */ + + + + + + + + + + + + + + +#endif /* BTA_MSE_INCLUDED */ diff --git a/bta/ma/bta_mse_sdp.c b/bta/ma/bta_mse_sdp.c new file mode 100644 index 0000000..a56e07f --- /dev/null +++ b/bta/ma/bta_mse_sdp.c @@ -0,0 +1,63 @@ +/***************************************************************************** +** +** Name: bta_mse_sdp.c +** +** File: Implements the SDP functions used by Message Access Server +** +** Copyright (c) 1998-2009, Broadcom Corp., All Rights Reserved. +** Broadcom Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include <string.h> + +#include "sdp_api.h" +#include "bta_mse_int.h" +#include "goep_util.h" + +/***************************************************************************** +** +** Function: bta_mas_sdp_register +** +** Purpose: Register the Message Access service with SDP +** +** Parameters: p_cb - Pointer to MA instance control block +** p_service_name - MA server name +** inst_id - MAS instance ID +** msg_type - Supported message type(s) +** +** +** Returns: void +** +*****************************************************************************/ +void bta_mse_ma_sdp_register (tBTA_MSE_MA_CB *p_cb, char *p_service_name, + tBTA_MA_INST_ID inst_id, + tBTA_MA_MSG_TYPE msg_type) +{ + UINT16 mas_service = UUID_SERVCLASS_MESSAGE_ACCESS; + tGOEP_ERRORS goep_status; + + goep_status = GOEP_Register(p_service_name, &p_cb->sdp_handle, p_cb->scn, + 1, &mas_service, UUID_SERVCLASS_MAP_PROFILE, + BTA_MAS_DEFAULT_VERSION); + if (goep_status == GOEP_SUCCESS) + { + /* add instance ID */ + SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE, + (UINT32)1, (UINT8*)&inst_id); + + /* add supported message type */ + SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE, + (UINT32)1, (UINT8*)&msg_type); + + bta_sys_add_uuid(mas_service); /* UUID_SERVCLASS_MESSAGE_ACCESS */ + APPL_TRACE_DEBUG1("MAS: SDP Registered (handle 0x%08x)", p_cb->sdp_handle); + } + else + { + if (p_cb->sdp_handle) SDP_DeleteRecord(p_cb->sdp_handle); + APPL_TRACE_ERROR0("bta_mse_ma_sdp_register FAILED"); + } + + return; +} diff --git a/bta/ma/bta_mse_utils.c b/bta/ma/bta_mse_utils.c new file mode 100644 index 0000000..2b14b7a --- /dev/null +++ b/bta/ma/bta_mse_utils.c @@ -0,0 +1,3867 @@ +/*********************************************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 <stdio.h> +#include <string.h> +#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 ( "<?xml version=\"1.0\"?>\n" \ + "<!DOCTYPE folder-listing SYSTEM \"obex-folder-listing.dtd\">\n" \ + "<folder-listing version=\"1.0\">\n" ) + +#define BTA_MSE_FOLDER_LISTING_END ( "</folder-listing>" ) +#define BTA_MSE_PARENT_FOLDER (" <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 ( "<MAP-msg-listing version=\"1.0\">\n" ) +#define BTA_MSE_MSG_LISTING_END ( "</MAP-msg-listing>" ) + + +// 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; j<BTA_MSE_NUM_SESS; j++ ) + { + if ((bta_mse_cb.scb[i].in_use) && + (bta_mse_cb.scb[i].sess_cb[j].obx_handle == (tOBX_HANDLE) mas_session_id )) + { + found = TRUE; + *p_inst_idx = i; + *p_sess_idx = j; + return found; + } + } + } + + return found; +} + +/******************************************************************************* +** +** Function bta_mse_find_sess_id_match_mn_cb_index +** +** Description Finds the MN control block index +** based on the specified MAS session ID +** +** Parameters mas_session_id - MAS instance ID +** p_idx - (output) pointer to the MN control +** block index +** +** Returns BOOLEAN - TRUE found +** FALSE not found +** +*******************************************************************************/ +BOOLEAN bta_mse_find_sess_id_match_mn_cb_index(tBTA_MA_SESS_HANDLE mas_session_id, + UINT8 *p_idx) +{ + BOOLEAN found=FALSE; + + UINT8 i,j; +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("bta_mse_find_sess_id_match_mn_cb_index"); +#endif + for (i=0; i < BTA_MSE_NUM_INST ; i ++) + { + for (j=0; j<BTA_MSE_NUM_SESS; j++ ) + { + if ((bta_mse_cb.scb[i].in_use) && + (bta_mse_cb.scb[i].sess_cb[j].obx_handle == (tOBX_HANDLE) mas_session_id )) + { + found = TRUE; + break; + } + } + if (found) break; + } + + /* found session index now need to match BD address*/ + if (found) + { + found = FALSE; + if ( bta_mse_find_bd_addr_match_mn_cb_index(bta_mse_cb.scb[i].sess_cb[j].bd_addr, p_idx)) + { + found = TRUE; + } + } + return found; +} + + +/******************************************************************************* +** +** Function bta_mse_find_mn_cb_index +** +** Description Finds the MN control block index +** based on the specified event +** +** Parameters p_msg - Pointer to MSE msg data +** p_ccb_idx - (output) pointer to the MN control block index +** +** Returns BOOLEAN - TRUE found +** FALSE not found +** +*******************************************************************************/ +BOOLEAN bta_mse_find_mn_cb_index(tBTA_MSE_DATA *p_msg, UINT8 *p_ccb_idx) +{ + BOOLEAN found = TRUE; +#if BTA_MSE_DEBUG == TRUE + APPL_TRACE_EVENT0("bta_mse_find_mn_cb_index"); +#endif + switch (p_msg->hdr.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, "<MAP-event-report version=\"1.0\">\n" + "<event type = \""); + bta_ma_stream_str(&strm, bta_ma_evt_typ_to_string(notif_type)); + + /* Some things are not used for "MemoryFull" and "MemoryAvailable" */ + if ( (BTA_MSE_NOTIF_TYPE_MEMORY_FULL != notif_type) + && (BTA_MSE_NOTIF_TYPE_MEMORY_AVAILABLE != notif_type) ) + { + /* stream handle label and value */ + bta_ma_stream_str(&strm, "\" handle = \""); + bta_ma_stream_handle(&strm, handle); + + if (p_folder && (*p_folder !='\0')) + { + /* stream folder */ + bta_ma_stream_str(&strm, "\" folder = \""); + bta_ma_stream_str(&strm, p_folder); + } + + /* stream old_folder if it is a "MessageShift" */ + if ( (BTA_MSE_NOTIF_TYPE_MESSAGE_SHIFT == notif_type) && + p_old_folder && (*p_old_folder !='\0')) + { + /* stream folder */ + bta_ma_stream_str(&strm, "\" old_folder = \""); + bta_ma_stream_str(&strm, p_old_folder); + } + + /* stream message type */ + bta_ma_stream_str(&strm, "\" msg_type = \""); + bta_ma_stream_str(&strm, bta_ma_msg_typ_to_string(msg_typ)); + } + + /* we are done with this evnet */ + bta_ma_stream_str(&strm, "\" />\n</MAP-event-report>"); + + /* 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 "); + /* stream msg attributes */ + bta_ma_stream_str(&strm, "handle = \""); + bta_ma_stream_handle(&strm, p_entry->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; i<BTA_MSE_NUM_INST; i++) + { + if (bta_mse_find_bd_addr_match_sess_cb_idx(bd_addr, i, &sess_idx)) + { + found_bd_addr = TRUE; + break; + } + } + + if (!found_bd_addr) + { + if ( bta_mse_find_bd_addr_match_mn_cb_index(bd_addr, &mn_idx)) + { + found_bd_addr = TRUE; + + } + } + + if (!found_bd_addr) + { + memset(p_pcb, 0, sizeof(tBTA_MSE_PM_CB)); + bta_sys_conn_close(BTA_ID_MSE , bta_mse_cb.app_id, bd_addr); + } + } + } +} + +/******************************************************************************* +** +** Function bta_mse_set_ma_oper +** +** Description Set MA operation and power management's busy/idle status based on +** MA operation +** +** Parameters inst_idx - Index to the MA instance control block +** sess_idx - Index to the MA session control block +** oper - MA operation +** +** Returns None +*******************************************************************************/ +void bta_mse_set_ma_oper(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_OPER oper) +{ + tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_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("bta_mse_set_ma_oper old=%d new=%d", p_cb->oper, 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; i<BTA_MSE_NUM_INST; i++) + { + if (bta_mse_find_bd_addr_match_sess_cb_idx( p_cb->bd_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; i<BTA_MSE_NUM_INST; i++) + { + if (bta_mse_find_bd_addr_match_sess_cb_idx( p_cb->bd_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 */ |