summaryrefslogtreecommitdiffstats
path: root/bta/op
diff options
context:
space:
mode:
authorAndre Eisenbach <andre@broadcom.com>2012-02-22 13:18:21 -0800
committerMatthew Xie <mattx@google.com>2012-07-14 11:19:11 -0700
commite448862a47c08eb23185aaed574b39264f5005fc (patch)
tree2bc6246e3091315e77224fd798ea2fe8074ef972 /bta/op
parenta2ca4b83ab8bbbfd8d5f6693e927ed4b82094624 (diff)
downloadexternal_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.zip
external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.gz
external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.bz2
Initial Bluedroid stack commit
Diffstat (limited to 'bta/op')
-rw-r--r--bta/op/bta_op_fmt.c804
-rw-r--r--bta/op/bta_op_fmt.h92
-rw-r--r--bta/op/bta_op_vcal.c158
-rw-r--r--bta/op/bta_op_vcard.c310
-rw-r--r--bta/op/bta_op_vnote.c99
-rw-r--r--bta/op/bta_opc_act.c1017
-rw-r--r--bta/op/bta_opc_api.c214
-rw-r--r--bta/op/bta_opc_int.h257
-rw-r--r--bta/op/bta_opc_main.c425
-rw-r--r--bta/op/bta_opc_utils.c322
-rw-r--r--bta/op/bta_ops_act.c793
-rw-r--r--bta/op/bta_ops_api.c153
-rw-r--r--bta/op/bta_ops_int.h198
-rw-r--r--bta/op/bta_ops_main.c412
-rw-r--r--bta/op/bta_ops_utils.c487
15 files changed, 5741 insertions, 0 deletions
diff --git a/bta/op/bta_op_fmt.c b/bta/op/bta_op_fmt.c
new file mode 100644
index 0000000..000370a
--- /dev/null
+++ b/bta/op/bta_op_fmt.c
@@ -0,0 +1,804 @@
+/*****************************************************************************
+**
+** Name: bta_op_fmt.c
+**
+** Description: This file contains common functions and data structures
+** used by the OPP object formatting functions.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include <string.h>
+#include <ctype.h>
+#include "bta_op_api.h"
+#include "bta_op_fmt.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#define BTA_OP_ENCODING_LEN 9
+#define BTA_OP_CHARSET_LEN 8
+#define BTA_OP_PARAM_TYPE_HDR_LEN 5
+#define BTA_OP_NUM_NONINLINE_MEDIA 2
+
+const char bta_op_encoding[] = "ENCODING=";
+
+const tBTA_OP_PARAM bta_op_encodings[] =
+{/* the len is (BTA_OP_ENCODING_LEN + 1 + strlen(p_name)) */
+ {NULL, 0},
+ {"QUOTED-PRINTABLE", 26}, /* BTA_OP_ENC_QUOTED_PRINTABLE */
+ {"8BIT", 14}, /* BTA_OP_ENC_8BIT */
+ {"b", 11}, /* BTA_OP_ENC_BINARY */
+// btla-specific ++
+ {"BASE64", 16} /* BTA_OP_ENC_BASE64 */
+// btla-specific --
+};
+
+#define BTA_OP_NUM_ENCODINGS 3
+#define BTA_OP_QP_IDX 1 /* array index for quoted printable in bta_op_encodings */
+
+const char bta_op_charset[] = "CHARSET=";
+
+const char bta_op_param_type_hdr[] = "TYPE=";
+
+const tBTA_OP_PARAM bta_op_charsets[] =
+{/* the len is (BTA_OP_CHARSET_LEN + 1 + strlen(p_name)) */
+ {NULL, 0},
+ {"BIG5", 13}, /* BTA_OP_CHAR_BIG5 */
+ {"EUC-JP", 15}, /* BTA_OP_CHAR_EUC_JP */
+ {"EUC-KR", 15}, /* BTA_OP_CHAR_EUC_KR */
+ {"GB2312", 15}, /* BTA_OP_CHAR_GB2312 */
+ {"ISO-2022-JP", 20}, /* BTA_OP_CHAR_ISO_2022_JP */
+ {"ISO-8859-1", 19}, /* BTA_OP_CHAR_ISO_8859_1 */
+ {"ISO-8859-2", 19}, /* BTA_OP_CHAR_ISO_8859_2 */
+ {"ISO-8859-3", 19}, /* BTA_OP_CHAR_ISO_8859_3 */
+ {"ISO-8859-4", 19}, /* BTA_OP_CHAR_ISO_8859_4 */
+ {"ISO-8859-5", 19}, /* BTA_OP_CHAR_ISO_8859_5 */
+ {"ISO-8859-6", 19}, /* BTA_OP_CHAR_ISO_8859_6 */
+ {"ISO-8859-7", 19}, /* BTA_OP_CHAR_ISO_8859_7 */
+ {"ISO-8859-8", 19}, /* BTA_OP_CHAR_ISO_8859_8 */
+ {"KOI8-R", 15}, /* BTA_OP_CHAR_KOI8_R */
+ {"SHIFT_JIS", 18}, /* BTA_OP_CHAR_SHIFT_JIS */
+ {"UTF-8", 14} /* BTA_OP_CHAR_UTF_8 */
+};
+
+#define BTA_OP_NUM_CHARSETS 16
+
+/* Structure of the 32-bit parameters mask:
+** (same comment is in bta_op_api.h)
+** + property-specific
+** +reserved | + character set
+** | | | + encoding
+** | | | |
+** 0000000000000000 00000000 00000 000
+*/
+#define BTA_OP_GET_PARAM(param, encod, charset, specific) \
+ encod = (UINT8) (param) & 0x00000007; \
+ charset = (UINT8) ((param) >> 3) & 0x0000001F; \
+ specific = (UINT8) ((param) >> 8) & 0x000000FF;
+
+/* mask for properties default 0, filter all */
+static UINT32 bta_op_prop_filter_mask = 0;
+
+const tBTA_OP_PROP_MEDIA bta_op_media[] =
+{
+ {NULL, 2},
+ {"PHOTO", 5},
+ {"SOUND", 5}
+};
+
+/* Place holder constant for safe string functions since there's no way to know how
+** memory is remaining for input parameter to build property.
+** Note: The BCM_STRCPY_S functions should be changed to know how much memory
+** is remaining. When completed this constant can be removed. Also, if safe
+** string functions are not used then this parameter is ignored anyway!
+*/
+#ifndef BTA_OP_REM_MEMORY
+#define BTA_OP_REM_MEMORY 8228
+#endif
+
+/*******************************************************************************
+**
+** Function bta_op_strnicmp
+**
+** Description Case insensitive strncmp.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+INT16 bta_op_strnicmp(const char *pStr1, const char *pStr2, size_t Count)
+{
+ char c1, c2;
+ INT16 v;
+
+ if (Count == 0)
+ return 0;
+
+ do {
+ c1 = *pStr1++;
+ c2 = *pStr2++;
+ /* the casts are necessary when pStr1 is shorter & char is signed */
+ v = (UINT16) tolower(c1) - (UINT16) tolower(c2);
+ } while ((v == 0) && (c1 != '\0') && (--Count > 0));
+
+ return v;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_set_prop_mask
+**
+** Description Set property mask
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_op_set_prop_filter_mask(UINT32 mask)
+{
+ bta_op_prop_filter_mask = mask;
+ return;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_prop_len
+**
+** Description Calculate the length of a property string through lookup
+** tables.
+**
+**
+** Returns Length of string in bytes.
+**
+*******************************************************************************/
+UINT16 bta_op_prop_len(const tBTA_OP_PROP_TBL *p_tbl, tBTA_OP_PROP *p_prop)
+{
+ UINT8 i_e, i_c, i_s;
+ UINT8 len_s = 0;
+ int i;
+
+ /* parse parameters mask */
+ BTA_OP_GET_PARAM(p_prop->parameters, i_e, i_c, i_s);
+
+ /* calculate length of property-specific parameters, if any */
+ if (p_tbl[p_prop->name].p_param_tbl != NULL)
+ {
+ for (i = 1; (i_s != 0) && (i <= p_tbl[p_prop->name].p_param_tbl[0].len); i++)
+ {
+ if (i_s & 1)
+ {
+ len_s += p_tbl[p_prop->name].p_param_tbl[i].len;
+ }
+ i_s >>= 1;
+ }
+ }
+
+ return (p_tbl[p_prop->name].len + len_s + bta_op_charsets[i_c].len +
+ bta_op_encodings[i_e].len + p_prop->len);
+}
+
+/*******************************************************************************
+**
+** Function bta_op_param_conflict
+**
+** Description Check if the parameters of the property for the format
+** conflict/not allowed.
+**
+**
+** Returns TRUE if not allowed, else FALSE
+**
+*******************************************************************************/
+BOOLEAN bta_op_param_conflict(tBTA_OP_SUP_FMT fmt, tBTA_OP_PROP *p_prop)
+{
+ UINT8 i_e, i_c, i_s;
+ BOOLEAN conflict = FALSE;
+
+ if (p_prop->parameters != 0)
+ {
+ BTA_OP_GET_PARAM(p_prop->parameters, i_e, i_c, i_s);
+
+ if (fmt == BTA_OP_FMT_VCARD30)
+ {
+ /* VCard 3.0 does not support CHARSET. If it is present, we
+ should ignore the whole property in the vCard build process */
+ if (bta_op_charsets[i_c].p_name != NULL)
+ conflict = TRUE;
+
+ /* VCard 3.0 only supports 'b' encoding. If any other encoding
+ ex. quoted-printable, is present, then whole property is ignored */
+ if ((bta_op_encodings[i_e].p_name != NULL) && strcmp(bta_op_encodings[i_e].p_name, "b"))
+ conflict = TRUE;
+ }
+ }
+
+ return conflict;
+}
+/*******************************************************************************
+**
+** Function bta_op_add_param
+**
+** Description Add parameter strings to a property string.
+**
+**
+** Returns Pointer to the next byte after the end of the string.
+**
+*******************************************************************************/
+UINT8 *bta_op_add_param(tBTA_OP_SUP_FMT fmt, const tBTA_OP_PROP_TBL *p_tbl, UINT8 *p, tBTA_OP_PROP *p_prop)
+{
+ UINT8 i_e, i_c, i_s;
+ int i;
+ UINT8 bta_op_param_type_delimit = 0;
+
+ if (p_prop->parameters != 0)
+ {
+ BTA_OP_GET_PARAM(p_prop->parameters, i_e, i_c, i_s);
+
+ /* add encoding parameter */
+ if (bta_op_encodings[i_e].p_name != NULL)
+ {
+ *p++ = ';';
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, bta_op_encoding);
+ p += BTA_OP_ENCODING_LEN;
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, bta_op_encodings[i_e].p_name);
+ p += bta_op_encodings[i_e].len - BTA_OP_ENCODING_LEN - 1;
+ }
+
+ /* add character set parameter */
+ if (bta_op_charsets[i_c].p_name != NULL)
+ {
+ *p++ = ';';
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, bta_op_charset);
+ p += BTA_OP_CHARSET_LEN;
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, bta_op_charsets[i_c].p_name);
+ p += bta_op_charsets[i_c].len - BTA_OP_CHARSET_LEN - 1;
+ }
+
+ /* add any property-specific parameters */
+ if (p_tbl[p_prop->name].p_param_tbl != NULL)
+ {
+ for (i = 1; (i_s != 0) && (i <= p_tbl[p_prop->name].p_param_tbl[0].len); i++)
+ {
+ if (i_s & 1)
+ {
+ if (bta_op_param_type_delimit)
+ {
+ *p++ = ',';
+ }
+ else
+ {
+ *p++ = ';';
+
+ if (fmt == BTA_OP_FMT_VCARD30)
+ {
+ BCM_STRNCPY_S((char *) p, BTA_OP_PARAM_TYPE_HDR_LEN+1, bta_op_param_type_hdr, BTA_OP_PARAM_TYPE_HDR_LEN);
+ p += BTA_OP_PARAM_TYPE_HDR_LEN;
+ bta_op_param_type_delimit++;
+ }
+ }
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, p_tbl[p_prop->name].p_param_tbl[i].p_name);
+ p += p_tbl[p_prop->name].p_param_tbl[i].len - 1;
+ }
+ i_s >>= 1;
+ }
+ }
+ }
+ else if (p_prop->p_param)
+ {
+ *p++ = ';';
+ memcpy((char *) p, p_prop->p_param, p_prop->param_len);
+ p += p_prop->param_len;
+ }
+
+ return p;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_add_media_param
+**
+** Description Add parameter strings to a media property string.
+**
+**
+** Returns Pointer to the next byte after the end of the string.
+**
+*******************************************************************************/
+UINT8 *bta_op_add_media_param(const tBTA_OP_PROP_TBL *p_tbl, UINT8 *p, tBTA_OP_PROP *p_prop)
+{
+ UINT8 i_e, i_c, i_s;
+ int i;
+
+ if (p_prop->parameters != 0)
+ {
+ BTA_OP_GET_PARAM(p_prop->parameters, i_e, i_c, i_s);
+
+ /* add encoding parameter */
+ if (bta_op_encodings[i_e].p_name != NULL)
+ {
+ *p++ = ';';
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, bta_op_encoding);
+ p += BTA_OP_ENCODING_LEN;
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, bta_op_encodings[i_e].p_name);
+ p += bta_op_encodings[i_e].len - BTA_OP_ENCODING_LEN - 1;
+ }
+
+ /* add any property-specific parameters */
+ if (p_tbl[p_prop->name].p_param_tbl != NULL)
+ {
+ for (i = 1; (i_s != 0) && (i <= p_tbl[p_prop->name].p_param_tbl[0].len); i++)
+ {
+ if (i_s & 1)
+ {
+ *p++ = ';';
+
+ /* Add "TYPE=" to non-referenced (inline) media */
+ if (i > BTA_OP_NUM_NONINLINE_MEDIA)
+ {
+ BCM_STRNCPY_S((char *) p, BTA_OP_PARAM_TYPE_HDR_LEN+1, bta_op_param_type_hdr, BTA_OP_PARAM_TYPE_HDR_LEN);
+ p += BTA_OP_PARAM_TYPE_HDR_LEN;
+ }
+
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, p_tbl[p_prop->name].p_param_tbl[i].p_name);
+ p += p_tbl[p_prop->name].p_param_tbl[i].len - 1;
+ break;
+ }
+ i_s >>= 1;
+ }
+ }
+ }
+ else if (p_prop->p_param)
+ {
+ *p++ = ';';
+ memcpy((char *) p, p_prop->p_param, p_prop->param_len);
+ p += p_prop->param_len;
+ }
+
+ return p;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_get_property_by_name
+**
+** Description Get the property user data by name.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if there is no property user data.
+**
+*******************************************************************************/
+tBTA_OP_STATUS bta_op_get_property_by_name(const tBTA_OP_PROP_TBL *p_tbl, UINT8 *p_name,
+ tBTA_OP_PROP *p_prop, UINT8 num_prop, UINT8 *p_data,
+ UINT16 *p_len)
+{
+ int i, j;
+ tBTA_OP_STATUS result = BTA_OP_FAIL;
+
+ /* for each property */
+ for(i = 0; num_prop != 0; num_prop--, i++)
+ {
+ /* verify property is valid */
+ if ((p_prop[i].name == 0) || (p_prop[i].name > p_tbl[0].len))
+ {
+ result = BTA_OP_FAIL;
+ break;
+ }
+
+ j = p_prop[i].name;
+
+ if (bta_op_strnicmp(p_tbl[j].p_name, (char *) p_name,
+ (p_tbl[j].len - BTA_OP_PROP_OVHD)) == 0)
+ {
+ memcpy(p_data, p_prop[i].p_data, p_prop[i].len);
+ *p_len = p_prop[i].len;
+ result = BTA_OP_OK;
+ break;
+ }
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_build_obj
+**
+** Description Build an object from property data supplied by the user.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete build.
+**
+*******************************************************************************/
+tBTA_OP_STATUS bta_op_build_obj(const tBTA_OP_OBJ_TBL *p_bld, UINT8 *p_data,
+ UINT16 *p_len, tBTA_OP_PROP *p_prop, UINT8 num_prop)
+{
+ int i,j;
+ tBTA_OP_STATUS result = BTA_OP_OK;
+ UINT8 *p = p_data;
+
+ /* sanity check length */
+ if (*p_len < p_bld->min_len)
+ {
+ result = BTA_OP_MEM;
+ }
+ else
+ {
+ /* adjust p_len to amount of free space minus start and end */
+ *p_len -= p_bld->min_len;
+
+ /* add begin, version */
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, p_bld->p_begin_str);
+ p += p_bld->begin_len;
+
+ /* for each property */
+ for(i = 0; num_prop != 0; num_prop--, i++)
+ {
+ /* verify property is valid */
+ if ((p_prop[i].name == 0) || (p_prop[i].name > p_bld->p_tbl[0].len))
+ {
+ result = BTA_OP_FAIL;
+ break;
+ }
+
+ /* verify property will fit */
+ if (bta_op_prop_len(p_bld->p_tbl, &p_prop[i]) > (p_data + p_bld->begin_len + *p_len - p))
+ {
+ result = BTA_OP_MEM;
+ break;
+ }
+
+ /* check for filter */
+ if (bta_op_prop_filter_mask !=0 && p_bld->p_prop_filter_mask_tbl != NULL &&
+ p_prop[i].name <= p_bld->p_prop_filter_mask_tbl->len)
+ {
+ if (!(bta_op_prop_filter_mask & p_bld->p_prop_filter_mask_tbl->p_prop_filter_mask[p_prop[i].name]))
+ continue;
+ }
+
+ /* Check if the combination of parameters are allowed for
+ the format we are building */
+ if (bta_op_param_conflict(p_bld->fmt, &p_prop[i]))
+ continue;
+
+ /* add property string */
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, p_bld->p_tbl[p_prop[i].name].p_name);
+ p += p_bld->p_tbl[p_prop[i].name].len - BTA_OP_PROP_OVHD;
+
+ for (j= bta_op_media[0].len; j > 0; j--)
+ {
+ if (!bta_op_strnicmp(bta_op_media[j].media_name, p_bld->p_tbl[p_prop[i].name].p_name, bta_op_media[j].len))
+ {
+ p = bta_op_add_media_param(p_bld->p_tbl, p, &p_prop[i]);
+ break;
+ }
+ }
+
+ if (!j)
+ {
+ /* add property parameters */
+ p = bta_op_add_param(p_bld->fmt, p_bld->p_tbl, p, &p_prop[i]);
+ }
+
+ /* add user data */
+// btla-specific ++
+ if(p_prop[i].name != BTA_OP_VCARD_CALL) // If the data is call date-time, use ';' instead of ':'
+ {
+ *p++ = ':';
+ }
+ else
+ {
+ *p++ = ';';
+ }
+// btla-specific --
+
+ memcpy(p, p_prop[i].p_data, p_prop[i].len);
+ p += p_prop[i].len;
+ *p++ = '\r';
+ *p++ = '\n';
+ }
+
+ /* add in end */
+ memcpy(p, p_bld->p_end_str, p_bld->end_len);
+ p += p_bld->end_len;
+ }
+
+ *p_len = (UINT16) (p - p_data);
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_nextline
+**
+** Description Scan to beginning of next property text line.
+**
+**
+** Returns Pointer to beginning of property or NULL if end of
+** data reached.
+**
+*******************************************************************************/
+static UINT8 *bta_op_nextline(UINT8 *p, UINT8 *p_end, BOOLEAN qp)
+{
+// btla-specific ++
+ if (*p == '\r')
+ {
+ p--;
+ }
+// btla-specific --
+
+ if ((p_end - p) > 3)
+ {
+ p_end -= 3;
+ while (p < p_end)
+ {
+ if (*(++p) == '\r')
+ {
+ if (*(p + 1) == '\n')
+ {
+ if (qp)
+ {
+ if (*(p - 1) == '=')
+ {
+ /* this is a soft break for quoted-printable*/
+ continue;
+ }
+ }
+
+ if ((*(p + 2) != ' ') && (*(p + 2) != '\t'))
+ {
+ return(p + 2);
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_scantok
+**
+** Description Scan a line for one or more tokens.
+**
+**
+** Returns Pointer to token or NULL if end of data reached.
+**
+*******************************************************************************/
+static UINT8 *bta_op_scantok(UINT8 *p, UINT8 *p_end, const char *p_tok)
+{
+ int i;
+ UINT8 num_tok = strlen(p_tok);
+
+ for (; p < p_end; p++)
+ {
+ for (i = 0; i < num_tok; i++)
+ {
+ if (*p == p_tok[i])
+ {
+ return p;
+ }
+ }
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_scanstr
+**
+** Description Scan for a matching string.
+**
+**
+** Returns Pointer to end of match or NULL if end of data reached.
+**
+*******************************************************************************/
+UINT8 *bta_op_scanstr(UINT8 *p, UINT8 *p_end, const char *p_str)
+{
+ int len = strlen(p_str);
+
+ for (;;)
+ {
+ /* check for match */
+ if (strncmp((char *) p, p_str, len) == 0)
+ {
+ p += len;
+ break;
+ }
+ /* no match; skip to next line, checking for end */
+ else if ((p = bta_op_nextline(p, p_end, FALSE)) == NULL)
+ {
+ break;
+ }
+ }
+ return p;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_parse_obj
+**
+** Description Parse an object.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid data.
+** BTA_OP_MEM if not enough memory to complete build.
+**
+*******************************************************************************/
+tBTA_OP_STATUS bta_op_parse_obj(const tBTA_OP_OBJ_TBL *p_prs, tBTA_OP_PROP *p_prop,
+ UINT8 *p_num_prop, UINT8 *p_data, UINT16 len)
+{
+ UINT32 j;
+ UINT8 *p_s, *p_e;
+ tBTA_OP_STATUS result = BTA_OP_OK;
+ UINT8 max_prop = *p_num_prop;
+ UINT8 *p_end = p_data + len;
+ UINT8 prop_name = 0;
+ BOOLEAN qp=FALSE;
+
+ *p_num_prop = 0;
+
+ /* sanity check length */
+ if (len < p_prs->min_len)
+ {
+ return BTA_OP_FAIL;
+ }
+
+ /* find beginning */
+ if ((p_s = bta_op_scanstr(p_data, p_end, p_prs->p_begin_str)) == NULL)
+ {
+ return BTA_OP_FAIL;
+ }
+
+ while (*p_num_prop < max_prop)
+ {
+ /* scan for next delimiter */
+ if ((p_e = bta_op_scantok(p_s, p_end, ".;:")) == NULL)
+ {
+ break;
+ }
+
+ /* deal with grouping delimiter */
+ if (*p_e == '.')
+ {
+ p_s = p_e + 1;
+ if ((p_e = bta_op_scantok(p_s, p_end, ";:")) == NULL)
+ {
+ break;
+ }
+ }
+
+ /* we found a property; see if it matches anything in our list */
+ for (j = 1; j <= p_prs->p_tbl[0].len; j++)
+ {
+ if (bta_op_strnicmp(p_prs->p_tbl[j].p_name, (char *) p_s,
+ (p_prs->p_tbl[j].len - BTA_OP_PROP_OVHD)) == 0)
+ {
+ p_prop[*p_num_prop].name = prop_name = j;
+ p_prop[*p_num_prop].parameters = 0;
+ break;
+ }
+ }
+
+ /* if not in our list we can't parse it; continue */
+ if (j > p_prs->p_tbl[0].len)
+ {
+ if ((p_s = bta_op_nextline(p_e, p_end, FALSE)) == NULL)
+ {
+ break;
+ }
+ continue;
+ }
+
+ /* now parse out all the parameters */
+ if (*p_e == ';')
+ {
+ while ((*p_e == ';') || (*p_e == ','))
+ {
+ p_s = p_e + 1;
+
+ if ((p_e = bta_op_scantok(p_s, p_end, ",;:")) == NULL)
+ {
+ break;
+ }
+
+ /* we found a parameter; see if it matches anything */
+
+ /* check for encoding */
+ qp = FALSE;
+ if (bta_op_strnicmp(bta_op_encoding, (char *) p_s, BTA_OP_ENCODING_LEN) == 0)
+ {
+ p_s += BTA_OP_ENCODING_LEN;
+ for (j = 1; j <= BTA_OP_NUM_ENCODINGS; j++)
+ {
+ if (bta_op_strnicmp(bta_op_encodings[j].p_name, (char *) p_s,
+ (bta_op_encodings[j].len - BTA_OP_ENCODING_LEN - 1)) == 0)
+ {
+ if (j == BTA_OP_QP_IDX)
+ {
+ /* encoding = quoted-printable*/
+ qp= TRUE;
+ }
+ p_prop[*p_num_prop].parameters |= j;
+ break;
+ }
+ }
+ }
+ /* check for charset */
+ else if (bta_op_strnicmp(bta_op_charset, (char *) p_s, BTA_OP_CHARSET_LEN) == 0)
+ {
+ p_s += BTA_OP_CHARSET_LEN;
+ for (j = 1; j <= BTA_OP_NUM_CHARSETS; j++)
+ {
+ if (bta_op_strnicmp(bta_op_charsets[j].p_name, (char *) p_s,
+ (bta_op_charsets[j].len - BTA_OP_CHARSET_LEN - 1)) == 0)
+ {
+ p_prop[*p_num_prop].parameters |= j << 3;
+ break;
+ }
+ }
+ }
+ /* check for property-specific parameters */
+ else if (p_prs->p_tbl[prop_name].p_param_tbl != NULL)
+ {
+
+ /* Check for "TYPE=" */
+ if (!bta_op_strnicmp((char *)p_s, bta_op_param_type_hdr, BTA_OP_PARAM_TYPE_HDR_LEN))
+ {
+ p_s += BTA_OP_PARAM_TYPE_HDR_LEN;
+ }
+
+ for (j = p_prs->p_tbl[prop_name].p_param_tbl[0].len; j > 0; j--)
+ {
+ if (bta_op_strnicmp(p_prs->p_tbl[prop_name].p_param_tbl[j].p_name,
+ (char *) p_s, (p_prs->p_tbl[prop_name].p_param_tbl[j].len - 1)) == 0)
+ {
+ p_prop[*p_num_prop].parameters |= ((UINT32) 1) << (j + 7);
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* if this the start of the param */
+ if (!p_prop[*p_num_prop].p_param)
+ p_prop[*p_num_prop].p_param = p_s;
+ if (*p_e == ':')
+ p_prop[*p_num_prop].param_len += (p_e - p_s);
+ else
+ p_prop[*p_num_prop].param_len += (p_e - p_s + 1);
+ }
+ }
+ }
+
+ if (p_e == NULL)
+ {
+ break;
+ }
+
+ /* go to start of next property */
+ p_s = p_e + 1;
+ if ((p_e = bta_op_nextline(p_s, p_end, qp)) == NULL)
+ {
+ break;
+ }
+
+ /* save property info */
+ p_prop[*p_num_prop].p_data = p_s;
+ p_prop[*p_num_prop].len = (UINT16) (p_e - p_s - 2);
+// btla-specific ++
+ if (p_prop[*p_num_prop].len)
+ {
+ (*p_num_prop)++;
+ }
+// btla-specific --
+ p_s = p_e;
+ }
+ return result;
+}
+
diff --git a/bta/op/bta_op_fmt.h b/bta/op/bta_op_fmt.h
new file mode 100644
index 0000000..29bb40c
--- /dev/null
+++ b/bta/op/bta_op_fmt.h
@@ -0,0 +1,92 @@
+/*****************************************************************************
+**
+** Name: bta_op_fmt.h
+**
+** Description: This is the interface file for common functions and data
+** types used by the OPP object formatting functions.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_OP_FMT_H
+#define BTA_OP_FMT_H
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#define BTA_OP_PROP_OVHD 3
+
+/*****************************************************************************
+** Data types
+*****************************************************************************/
+
+enum {
+ BTA_OP_FMT_NONE=0,
+ BTA_OP_FMT_VCARD21,
+ BTA_OP_FMT_VCARD30,
+ BTA_OP_FMT_VCAL10,
+ BTA_OP_FMT_VNOTE11
+};
+
+/*Supported formats */
+typedef UINT8 tBTA_OP_SUP_FMT;
+
+typedef struct
+{
+ const char *p_name;
+ UINT8 len;
+} tBTA_OP_PARAM;
+
+typedef struct
+{
+ const char *p_name;
+ const tBTA_OP_PARAM *p_param_tbl;
+ UINT8 len;
+} tBTA_OP_PROP_TBL;
+
+
+typedef struct
+{
+ const UINT32 *p_prop_filter_mask;
+ UINT8 len;
+} tBTA_OP_PROP_FILTER_MASK_TBL;
+
+typedef struct
+{
+ const tBTA_OP_PROP_TBL *p_tbl;
+ tBTA_OP_SUP_FMT fmt;
+ const char *p_begin_str;
+ const char *p_end_str;
+ UINT8 begin_len;
+ UINT8 end_len;
+ UINT8 min_len;
+ const tBTA_OP_PROP_FILTER_MASK_TBL *p_prop_filter_mask_tbl;
+} tBTA_OP_OBJ_TBL;
+
+typedef struct
+{
+ const char *media_name;
+ UINT8 len;
+} tBTA_OP_PROP_MEDIA;
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+extern tBTA_OP_STATUS bta_op_build_obj(const tBTA_OP_OBJ_TBL *p_bld,
+ UINT8 *p_data, UINT16 *p_len,
+ tBTA_OP_PROP *p_prop, UINT8 num_prop);
+
+extern tBTA_OP_STATUS bta_op_parse_obj(const tBTA_OP_OBJ_TBL *p_prs,
+ tBTA_OP_PROP *p_prop, UINT8 *p_num_prop,
+ UINT8 *p_data, UINT16 len);
+extern tBTA_OP_STATUS bta_op_get_property_by_name(const tBTA_OP_PROP_TBL *p_tbl, UINT8 *p_name,
+ tBTA_OP_PROP *p_prop, UINT8 num_prop, UINT8 *p_data,
+ UINT16 *p_len);
+extern UINT8 *bta_op_scanstr(UINT8 *p, UINT8 *p_end, const char *p_str);
+extern void bta_op_set_prop_filter_mask(UINT32 mask);
+
+#endif /* BTA_OP_FMT_H */
+
diff --git a/bta/op/bta_op_vcal.c b/bta/op/bta_op_vcal.c
new file mode 100644
index 0000000..79aef02
--- /dev/null
+++ b/bta/op/bta_op_vcal.c
@@ -0,0 +1,158 @@
+/*****************************************************************************
+**
+** Name: bta_op_vcal.c
+**
+** Description: This file contains functions for parsing and building
+** vCal objects.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bta_op_api.h"
+#include "bta_op_fmt.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#define BTA_OP_TODO_BEGIN_LEN 43
+#define BTA_OP_TODO_END_LEN 26
+
+#define BTA_OP_TODO_MIN_LEN (BTA_OP_TODO_BEGIN_LEN + BTA_OP_TODO_END_LEN)
+
+#define BTA_OP_EVENT_BEGIN_LEN 44
+#define BTA_OP_EVENT_END_LEN 27
+
+#define BTA_OP_EVENT_MIN_LEN (BTA_OP_EVENT_BEGIN_LEN + BTA_OP_EVENT_END_LEN)
+
+#define BTA_OP_VCAL_BEGIN_LEN 17
+#define BTA_OP_VCAL_END_LEN 15
+#define BTA_OP_VCAL_MIN_LEN (BTA_OP_VCAL_BEGIN_LEN + BTA_OP_VCAL_END_LEN)
+#define BTA_OP_BEGIN_OFFSET 30
+
+const char bta_op_vcal_begin[] = "BEGIN:VCALENDAR\r\n";
+
+const char bta_op_todo_begin[] = "BEGIN:VCALENDAR\r\nVERSION:1.0\r\nBEGIN:VTODO\r\n";
+
+const char bta_op_todo_end[] = "END:VTODO\r\nEND:VCALENDAR\r\n";
+
+const char bta_op_event_begin[] = "BEGIN:VCALENDAR\r\nVERSION:1.0\r\nBEGIN:VEVENT\r\n";
+
+const char bta_op_event_end[] = "END:VEVENT\r\nEND:VCALENDAR\r\n";
+
+const tBTA_OP_PROP_TBL bta_op_vcal_tbl[] =
+{
+ {NULL, NULL, 11}, /* Number of elements in array */
+ {"CATEGORIES", NULL, 13}, /* BTA_OP_VCAL_CATEGORIES */
+ {"COMPLETED", NULL, 12}, /* BTA_OP_VCAL_COMPLETED */
+ {"DESCRIPTION", NULL, 14}, /* BTA_OP_VCAL_DESCRIPTION */
+ {"DTEND", NULL, 8}, /* BTA_OP_VCAL_DTEND */
+ {"DTSTART", NULL, 10}, /* BTA_OP_VCAL_DTSTART */
+ {"DUE", NULL, 6}, /* BTA_OP_VCAL_DUE */
+ {"LOCATION", NULL, 11}, /* BTA_OP_VCAL_LOCATION */
+ {"PRIORITY", NULL, 11}, /* BTA_OP_VCAL_PRIORITY */
+ {"STATUS", NULL, 9}, /* BTA_OP_VCAL_STATUS */
+ {"SUMMARY", NULL, 10}, /* BTA_OP_VCAL_SUMMARY */
+ {"X-IRMC-LUID", NULL, 14} /* BTA_OP_VCAL_LUID */
+};
+
+const tBTA_OP_OBJ_TBL bta_op_todo_bld =
+{
+ bta_op_vcal_tbl,
+ BTA_OP_FMT_VCAL10,
+ bta_op_todo_begin,
+ bta_op_todo_end,
+ BTA_OP_TODO_BEGIN_LEN,
+ BTA_OP_TODO_END_LEN,
+ BTA_OP_TODO_MIN_LEN
+};
+
+const tBTA_OP_OBJ_TBL bta_op_event_bld =
+{
+ bta_op_vcal_tbl,
+ BTA_OP_FMT_VCAL10,
+ bta_op_event_begin,
+ bta_op_event_end,
+ BTA_OP_EVENT_BEGIN_LEN,
+ BTA_OP_EVENT_END_LEN,
+ BTA_OP_EVENT_MIN_LEN
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vcal_prs =
+{
+ bta_op_vcal_tbl,
+ BTA_OP_FMT_VCAL10,
+ bta_op_vcal_begin,
+ NULL,
+ BTA_OP_VCAL_BEGIN_LEN,
+ BTA_OP_VCAL_END_LEN,
+ BTA_OP_VCAL_MIN_LEN
+};
+
+/*******************************************************************************
+**
+** Function BTA_OpBuildCal
+**
+** Description Build a vCal 1.0 object. The input to this function is an
+** array of vCaalproperties and a pointer to memory to store
+** the card. The output is a formatted vCal.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete build.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpBuildCal(UINT8 *p_cal, UINT16 *p_len, tBTA_OP_PROP *p_prop,
+ UINT8 num_prop, tBTA_OP_VCAL vcal_type)
+{
+ tBTA_OP_OBJ_TBL *p_bld;
+
+ if (vcal_type == BTA_OP_VCAL_EVENT)
+ {
+ p_bld = (tBTA_OP_OBJ_TBL *) &bta_op_event_bld;
+ }
+ else
+ {
+ p_bld = ( tBTA_OP_OBJ_TBL *) &bta_op_todo_bld;
+ }
+
+ return bta_op_build_obj(p_bld, p_cal, p_len, p_prop, num_prop);
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpParseCal
+**
+** Description Parse a vCal object. The input to this function is a
+** pointer to vCal data. The output is an array of parsed
+** vCal properties.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete parsing.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpParseCal(tBTA_OP_PROP *p_prop, UINT8 *p_num_prop, UINT8 *p_cal,
+ UINT16 len, tBTA_OP_VCAL *p_vcal_type)
+{
+ if (bta_op_scanstr(p_cal, (p_cal + len), &bta_op_todo_begin[BTA_OP_BEGIN_OFFSET]) != NULL)
+ {
+ *p_vcal_type = BTA_OP_VCAL_TODO;
+ }
+ else if (bta_op_scanstr(p_cal, (p_cal + len), &bta_op_event_begin[BTA_OP_BEGIN_OFFSET]) != NULL)
+ {
+ *p_vcal_type = BTA_OP_VCAL_EVENT;
+ }
+ else
+ {
+ *p_num_prop = 0;
+ return BTA_OP_FAIL;
+ }
+
+ return bta_op_parse_obj(&bta_op_vcal_prs, p_prop, p_num_prop, p_cal, len);
+}
+
diff --git a/bta/op/bta_op_vcard.c b/bta/op/bta_op_vcard.c
new file mode 100644
index 0000000..6a278ba
--- /dev/null
+++ b/bta/op/bta_op_vcard.c
@@ -0,0 +1,310 @@
+/*****************************************************************************
+**
+** Name: bta_op_vcard.c
+**
+** Description: This file contains functions for parsing and building
+** vCard objects.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bta_op_api.h"
+#include "bta_op_fmt.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#define BTA_OP_VCARD_BEGIN_LEN 26
+#define BTA_OP_VCARD_END_LEN 11
+
+#define BTA_OP_VCARD_MIN_LEN (BTA_OP_VCARD_BEGIN_LEN + BTA_OP_VCARD_END_LEN)
+
+const char bta_op_vcard_prs_begin[] = "BEGIN:VCARD\r\n";
+
+const char bta_op_vcard_21_begin[] = "BEGIN:VCARD\r\nVERSION:2.1\r\n";
+
+const char bta_op_vcard_30_begin[] = "BEGIN:VCARD\r\nVERSION:3.0\r\n";
+
+const char bta_op_vcard_end[] = "END:VCARD\r\n";
+
+const tBTA_OP_PARAM bta_op_vcard_adr[] =
+{
+ {NULL, 6}, /* Number of elements in array */
+ {"DOM", 4}, /* BTA_OP_ADR_DOM */
+ {"INTL", 5}, /* BTA_OP_ADR_INTL */
+ {"POSTAL", 7}, /* BTA_OP_ADR_POSTAL */
+ {"PARCEL", 7}, /* BTA_OP_ADR_PARCEL */
+ {"HOME", 5}, /* BTA_OP_ADR_HOME */
+ {"WORK", 5} /* BTA_OP_ADR_WORK */
+};
+
+const tBTA_OP_PARAM bta_op_vcard_email[] =
+{
+ {NULL, 3}, /* Number of elements in array */
+ {"PREF", 5}, /* BTA_OP_EMAIL_PREF */
+ {"INTERNET", 9}, /* BTA_OP_EMAIL_INTERNET */
+ {"X400", 5} /* BTA_OP_EMAIL_X400 */
+};
+
+const tBTA_OP_PARAM bta_op_vcard_tel[] =
+{
+ {NULL, 8}, /* Number of elements in array */
+ {"PREF", 5}, /* BTA_OP_TEL_PREF */
+ {"WORK", 5}, /* BTA_OP_TEL_WORK */
+ {"HOME", 5}, /* BTA_OP_TEL_HOME */
+ {"VOICE", 6}, /* BTA_OP_TEL_VOICE */
+ {"FAX", 4}, /* BTA_OP_TEL_FAX */
+ {"MSG", 4}, /* BTA_OP_TEL_MSG */
+ {"CELL", 5}, /* BTA_OP_TEL_CELL */
+ {"PAGER", 6} /* BTA_OP_TEL_PAGER */
+};
+
+const tBTA_OP_PARAM bta_op_vcard_photo[] =
+{
+ {NULL, 4}, /* Number of elements in array */
+ {"VALUE=URI", 10}, /* BTA_OP_PHOTO_VALUE_URI */
+ {"VALUE=URL", 10}, /* BTA_OP_PHOTO_VALUE_URL */
+ {"JPEG", 5}, /* BTA_OP_PHOTO_TYPE_JPEG */
+ {"GIF", 4} /* BTA_OP_PHOTO_TYPE_GIF */
+};
+
+const tBTA_OP_PARAM bta_op_vcard_sound[] =
+{
+ {NULL, 4}, /* Number of elements in array */
+ {"VALUE=URI", 10}, /* BTA_OP_SOUND_VALUE_URI */
+ {"VALUE=URL", 10}, /* BTA_OP_SOUND_VALUE_URL */
+ {"BASIC", 6}, /* BTA_OP_SOUND_TYPE_BASIC */
+ {"WAVE", 5} /* BTA_OP_SOUND_TYPE_WAVE */
+};
+
+const tBTA_OP_PROP_TBL bta_op_vcard_tbl[] =
+{
+ {NULL, NULL, 15}, /* Number of elements in array */
+ {"ADR", bta_op_vcard_adr, 6}, /* BTA_OP_VCARD_ADR */
+ {"EMAIL", bta_op_vcard_email, 8}, /* BTA_OP_VCARD_EMAIL */
+ {"FN", NULL, 5}, /* BTA_OP_VCARD_FN */
+ {"NOTE", NULL, 7}, /* BTA_OP_VCARD_NOTE */
+ {"NICKNAME", NULL, 11}, /* BTA_OP_VACRD_NICKNAME */
+ {"N", NULL, 4}, /* BTA_OP_VCARD_N */
+ {"ORG", NULL, 6}, /* BTA_OP_VCARD_ORG */
+ {"TEL", bta_op_vcard_tel, 6}, /* BTA_OP_VCARD_TEL */
+ {"TITLE", NULL, 8}, /* BTA_OP_VCARD_TITLE */
+ {"URL", NULL, 6}, /* BTA_OP_VCARD_URL */
+ {"X-IRMC-LUID", NULL, 14}, /* BTA_OP_VNOTE_LUID */
+ {"BDAY", NULL, 7}, /* BTA_OP_VCARD_BDAY */
+ {"PHOTO", bta_op_vcard_photo, 8}, /* BTA_OP_VCARD_PHOTO */
+ {"SOUND", bta_op_vcard_sound, 8}, /* BTA_OP_VCARD_SOUND */
+ {"X-IRMC-CALL-DATETIME", NULL, 23} /* BTA_OP_VCARD_CALL */
+};
+
+const UINT32 bta_op_vcard_prop_filter_mask[] =
+{
+/* table index should be the same as the prop table above */
+ BTA_OP_FILTER_ALL,
+ BTA_OP_FILTER_ADR,
+ BTA_OP_FILTER_EMAIL,
+ BTA_OP_FILTER_FN,
+ BTA_OP_FILTER_NOTE,
+ BTA_OP_FILTER_NICKNAME,
+ BTA_OP_FILTER_N,
+ BTA_OP_FILTER_ORG,
+ BTA_OP_FILTER_TEL,
+ BTA_OP_FILTER_TITLE,
+ BTA_OP_FILTER_URL,
+ BTA_OP_FILTER_UID,
+ BTA_OP_FILTER_BDAY,
+ BTA_OP_FILTER_PHOTO,
+ BTA_OP_FILTER_SOUND,
+ BTA_OP_FILTER_TIME_STAMP
+};
+
+const tBTA_OP_PROP_FILTER_MASK_TBL bta_op_vcard_prop_filter_mask_tbl =
+{
+ bta_op_vcard_prop_filter_mask,
+ 15
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vcard_21_bld =
+{
+ bta_op_vcard_tbl,
+ BTA_OP_FMT_VCARD21,
+ bta_op_vcard_21_begin,
+ bta_op_vcard_end,
+ BTA_OP_VCARD_BEGIN_LEN,
+ BTA_OP_VCARD_END_LEN,
+ BTA_OP_VCARD_MIN_LEN,
+ &bta_op_vcard_prop_filter_mask_tbl
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vcard_30_bld =
+{
+ bta_op_vcard_tbl,
+ BTA_OP_FMT_VCARD30,
+ bta_op_vcard_30_begin,
+ bta_op_vcard_end,
+ BTA_OP_VCARD_BEGIN_LEN,
+ BTA_OP_VCARD_END_LEN,
+ BTA_OP_VCARD_MIN_LEN,
+ &bta_op_vcard_prop_filter_mask_tbl
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vcard_21_prs =
+{
+ bta_op_vcard_tbl,
+ BTA_OP_FMT_VCARD21,
+ bta_op_vcard_prs_begin,
+ bta_op_vcard_end,
+ BTA_OP_VCARD_BEGIN_LEN,
+ BTA_OP_VCARD_END_LEN,
+ BTA_OP_VCARD_MIN_LEN,
+ NULL
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vcard_30_prs =
+{
+ bta_op_vcard_tbl,
+ BTA_OP_FMT_VCARD30,
+ bta_op_vcard_prs_begin,
+ bta_op_vcard_end,
+ BTA_OP_VCARD_BEGIN_LEN,
+ BTA_OP_VCARD_END_LEN,
+ BTA_OP_VCARD_MIN_LEN,
+ NULL
+};
+
+
+/*******************************************************************************
+**
+** Function bta_op_get_card_fmt
+**
+** Description Finds the vCard format contained in buffer pointed by p_card
+**
+**
+** Returns Vcard Format BTA_OP_VCARD21_FMT/BTA_OP_VCARD30_FMT else
+** BTA_OP_OTHER_FMT
+**
+*******************************************************************************/
+static tBTA_OP_SUP_FMT bta_op_get_card_fmt(UINT8 *p_data, UINT16 len)
+{
+ UINT8 *p_end = p_data + len;
+
+ if (bta_op_scanstr(p_data, p_end, bta_op_vcard_21_begin) != NULL)
+ {
+ return BTA_OP_FMT_VCARD21;
+ }
+ else if (bta_op_scanstr(p_data, p_end, bta_op_vcard_30_begin) != NULL)
+ {
+ return BTA_OP_FMT_VCARD30;
+ }
+ else
+ {
+ return BTA_OP_FMT_NONE;
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpBuildCard
+**
+** Description Build a vCard object. The input to this function is
+** requested format(2.1/3.0), an array of vCard properties
+** and a pointer to memory to store the card.
+** The output is a formatted vCard.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete build.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpBuildCard(UINT8 *p_card, UINT16 *p_len, tBTA_OP_FMT fmt,
+ tBTA_OP_PROP *p_prop, UINT8 num_prop)
+{
+ if(fmt == BTA_OP_VCARD21_FMT)
+ {
+ return bta_op_build_obj(&bta_op_vcard_21_bld, p_card, p_len, p_prop, num_prop);
+ }
+ else if(fmt == BTA_OP_VCARD30_FMT)
+ {
+ return bta_op_build_obj(&bta_op_vcard_30_bld, p_card, p_len, p_prop, num_prop);
+ }
+ else
+ {
+ *p_len = 0;
+ return BTA_OP_FAIL;
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpSetCardPropFilterMask
+**
+** Description Set Property Filter Mask
+**
+**
+** Returns
+**
+*******************************************************************************/
+void BTA_OpSetCardPropFilterMask(UINT32 mask)
+{
+ bta_op_set_prop_filter_mask(mask);
+ return;
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpParseCard
+**
+** Description Parse a vCard 2.1 object. The input to this function is
+** a pointer to vCard data. The output is an array of parsed
+** vCard properties.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete parsing.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpParseCard(tBTA_OP_PROP *p_prop, UINT8 *p_num_prop,
+ UINT8 *p_card, UINT16 len)
+{
+ tBTA_OP_SUP_FMT fmt = bta_op_get_card_fmt(p_card, len);
+
+ if (fmt == BTA_OP_FMT_VCARD21)
+ {
+ return bta_op_parse_obj(&bta_op_vcard_21_prs, p_prop, p_num_prop, p_card, len);
+ }
+ else if(fmt == BTA_OP_FMT_VCARD30)
+ {
+ return bta_op_parse_obj(&bta_op_vcard_30_prs, p_prop, p_num_prop, p_card, len);
+ }
+ else
+ {
+ *p_num_prop = 0;
+ return BTA_OP_FAIL;
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpGetCardProperty
+**
+** Description Get Card property value by name. The input to this function is
+** property name. The output is property value and len
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpGetCardProperty(UINT8 *p_value, UINT16 *p_len, tBTA_OP_PROP *p_prop,
+ UINT8 num_prop, UINT8 *p_name)
+{
+ return bta_op_get_property_by_name(bta_op_vcard_tbl, p_name,
+ p_prop, num_prop, p_value, p_len);
+}
+
+
diff --git a/bta/op/bta_op_vnote.c b/bta/op/bta_op_vnote.c
new file mode 100644
index 0000000..ff1c015
--- /dev/null
+++ b/bta/op/bta_op_vnote.c
@@ -0,0 +1,99 @@
+/*****************************************************************************
+**
+** Name: bta_op_vnote.c
+**
+** Description: This file contains functions for parsing and building
+** vNote objects.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bta_op_api.h"
+#include "bta_op_fmt.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#define BTA_OP_VNOTE_BEGIN_LEN 26
+#define BTA_OP_VNOTE_END_LEN 11
+
+#define BTA_OP_VNOTE_MIN_LEN (BTA_OP_VNOTE_BEGIN_LEN + BTA_OP_VNOTE_END_LEN)
+
+const char bta_op_vnote_prs_begin[] = "BEGIN:VNOTE\r\n";
+
+const char bta_op_vnote_begin[] = "BEGIN:VNOTE\r\nVERSION:1.1\r\n";
+
+const char bta_op_vnote_end[] = "END:VNOTE\r\n";
+
+const tBTA_OP_PROP_TBL bta_op_vnote_tbl[] =
+{
+ {NULL, NULL, 2}, /* Number of elements in array */
+ {"BODY", NULL, 7}, /* BTA_OP_VNOTE_BODY */
+ {"X-IRMC-LUID", NULL, 14} /* BTA_OP_VNOTE_LUID */
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vnote_bld =
+{
+ bta_op_vnote_tbl,
+ BTA_OP_FMT_VNOTE11,
+ bta_op_vnote_begin,
+ bta_op_vnote_end,
+ BTA_OP_VNOTE_BEGIN_LEN,
+ BTA_OP_VNOTE_END_LEN,
+ BTA_OP_VNOTE_MIN_LEN
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vnote_prs =
+{
+ bta_op_vnote_tbl,
+ BTA_OP_FMT_VNOTE11,
+ bta_op_vnote_prs_begin,
+ bta_op_vnote_end,
+ BTA_OP_VNOTE_BEGIN_LEN,
+ BTA_OP_VNOTE_END_LEN,
+ BTA_OP_VNOTE_MIN_LEN
+};
+
+/*******************************************************************************
+**
+** Function BTA_OpBuildNote
+**
+** Description Build a vNote object. The input to this function is an
+** array of vNote properties and a pointer to memory to store
+** the card. The output is a formatted vNote.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete build.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpBuildNote(UINT8 *p_note, UINT16 *p_len, tBTA_OP_PROP *p_prop,
+ UINT8 num_prop)
+{
+ return bta_op_build_obj(&bta_op_vnote_bld, p_note, p_len, p_prop, num_prop);
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpParseNote
+**
+** Description Parse a vNote object. The input to this function is a
+** pointer to vNote data. The output is an array of parsed
+** vNote properties.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete parsing.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpParseNote(tBTA_OP_PROP *p_prop, UINT8 *p_num_prop, UINT8 *p_note,
+ UINT16 len)
+{
+ return bta_op_parse_obj(&bta_op_vnote_prs, p_prop, p_num_prop, p_note, len);
+}
+
diff --git a/bta/op/bta_opc_act.c b/bta/op/bta_opc_act.c
new file mode 100644
index 0000000..cf4780d
--- /dev/null
+++ b/bta/op/bta_opc_act.c
@@ -0,0 +1,1017 @@
+/*****************************************************************************
+**
+** Name: bta_opc_act.c
+**
+** Description: This file contains the file transfer action
+** functions for the state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "bd.h"
+#include "port_api.h"
+#include "obx_api.h"
+#include "goep_util.h"
+#include "sdp_api.h"
+#include "bta_fs_api.h"
+#include "bta_op_api.h"
+#include "bta_opc_int.h"
+#include "bta_fs_co.h"
+#include "bta_fs_ci.h"
+#include "btm_api.h"
+#include "rfcdefs.h"
+#include "utl.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+/* sdp discovery database size */
+#define BTA_OPC_DISC_SIZE 450
+
+
+/*****************************************************************************
+** Local Function prototypes
+*****************************************************************************/
+#if BTA_OPC_DEBUG == TRUE
+static char *opc_obx_evt_code(tOBX_EVENT evt_code);
+#endif
+
+static void bta_opc_sdp_cback(UINT16 status);
+
+
+/*****************************************************************************
+** Action Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_opc_enable
+**
+** Description Handle an api enable event. This function enables the OP
+** Client by opening an Obex/Rfcomm channel with a peer device.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_enable(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+
+ /* store parameters */
+ p_cb->p_cback = p_data->api_enable.p_cback;
+ p_cb->sec_mask = p_data->api_enable.sec_mask;
+ p_cb->app_id = p_data->api_enable.app_id;
+ p_cb->srm = p_data->api_enable.srm;
+ p_cb->single_op = p_data->api_enable.single_op;
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ /* callback with enable event */
+ (*p_cb->p_cback)(BTA_OPC_ENABLE_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_init_push
+**
+** Description Push an object to the OPP server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_init_push(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ p_cb->status = BTA_OPC_FAIL;
+ p_cb->exch_status = BTA_OPC_OK;
+
+ if ((p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ p_cb->to_do = BTA_OPC_PUSH_MASK;
+ p_cb->format = p_data->api_push.format;
+ BCM_STRNCPY_S(p_cb->p_name, p_bta_fs_cfg->max_path_len+1, p_data->api_push.p_name, p_bta_fs_cfg->max_path_len);
+ p_cb->p_name[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+ else
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, (tBTA_OPC_DATA *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_init_pull
+**
+** Description Pull an object off the server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_init_pull(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ p_cb->status = BTA_OPC_FAIL;
+ p_cb->exch_status = BTA_OPC_OK;
+
+ if ((p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_file_len +
+ p_bta_fs_cfg->max_path_len + 2))) != NULL)
+ {
+ p_cb->p_rcv_path = p_cb->p_name + p_bta_fs_cfg->max_file_len + 1;
+ p_cb->to_do = BTA_OPC_PULL_MASK;
+ p_cb->first_get_pkt = TRUE;
+ BCM_STRNCPY_S(p_cb->p_rcv_path, p_bta_fs_cfg->max_path_len+1, p_data->api_pull.p_path, p_bta_fs_cfg->max_path_len);
+ p_cb->p_rcv_path[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+ else
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, (tBTA_OPC_DATA *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_init_exch
+**
+** Description Exchange business cards with a server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_init_exch(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ p_cb->status = BTA_OPC_FAIL;
+ p_cb->exch_status = BTA_OPC_OK;
+
+ /* Need room to hold the receive path, along with path and file name to push */
+ if ((p_cb->p_name =
+ (char *)GKI_getbuf((UINT16)((p_bta_fs_cfg->max_path_len + 1) * 2))) != NULL)
+ {
+ p_cb->p_rcv_path = p_cb->p_name + p_bta_fs_cfg->max_path_len + 1;
+ p_cb->to_do = BTA_OPC_PULL_MASK | BTA_OPC_PUSH_MASK;
+ p_cb->first_get_pkt = TRUE;
+ BCM_STRNCPY_S(p_cb->p_name, p_bta_fs_cfg->max_path_len+1, p_data->api_exch.p_send, p_bta_fs_cfg->max_path_len);
+ p_cb->p_name[p_bta_fs_cfg->max_path_len] = '\0';
+ BCM_STRNCPY_S(p_cb->p_rcv_path, p_bta_fs_cfg->max_path_len+1, p_data->api_exch.p_rcv_path, p_bta_fs_cfg->max_path_len);
+ p_cb->p_rcv_path[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+ else
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, (tBTA_OPC_DATA *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_trans_cmpl
+**
+** Description push/pull complete
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_trans_cmpl(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBJECT param;
+ tBTA_OPC_EVT evt = BTA_OPC_OBJECT_EVT;
+ tBTA_FS_CO_STATUS status;
+
+ if (p_data)
+ {
+ p_cb->status = bta_opc_convert_obx_to_opc_status(p_data->obx_evt.rsp_code);
+ }
+ else
+ {
+ /* some action functions send the event to SM with NULL p_data */
+ p_cb->status = BTA_OPC_FAIL;
+ }
+
+ if (p_cb->obx_oper == OPC_OP_PUSH_OBJ)
+ evt = BTA_OPC_OBJECT_PSHD_EVT;
+
+ /* rearrange the code a little bit to make sure p_cb->status is for the current op
+ * (previously, we might use the ststus from the PUSH op, if this is an exchange card) */
+ param.status = p_cb->status;
+
+ /* If exchange, and push received an error use this error */
+ if (p_cb->exch_status != BTA_OPC_OK)
+ param.status = p_cb->exch_status;
+
+ /* Notify appl the result of the pull or push */
+ param.p_name = p_cb->p_name;
+ p_cb->p_cback(evt, (tBTA_OPC *)&param);
+
+ /* Close any open files */
+ if (p_cb->fd >= 0)
+ {
+ bta_fs_co_close(p_cb->fd, p_cb->app_id);
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ /* Delete an aborted unfinished get vCard operation */
+ if (p_cb->obx_oper == OPC_OP_PULL_OBJ && p_cb->status != BTA_OPC_OK)
+ {
+ status = bta_fs_co_unlink(p_cb->p_name, p_cb->app_id);
+ APPL_TRACE_WARNING2("OPC: Remove ABORTED Get File Operation [%s], status 0x%02x",
+ p_cb->p_name, status);
+ }
+ }
+
+ utl_freebuf((void**)&p_cb->p_name);
+
+ p_cb->obx_oper = OPC_OP_NONE;
+
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_ci_write
+**
+** Description Continue with the current write operation
+** (Get File processing)
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_ci_write(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_OPC_PROGRESS param;
+ UINT8 rsp_code = OBX_RSP_FAILED;
+
+ p_cb->cout_active = FALSE;
+
+ /* Process write call-in event if operation is still active */
+ if (p_cb->obx_oper == OPC_OP_PULL_OBJ)
+ {
+ if (p_data->write_evt.status == BTA_FS_CO_OK)
+ {
+ param.bytes = p_obx->offset;
+ param.obj_size = p_cb->obj_size;
+ param.operation = BTA_OP_OPER_PULL;
+ p_cb->p_cback(BTA_OPC_PROGRESS_EVT, (tBTA_OPC *)&param);
+
+ /* Send another Get request if not finished */
+ if (!p_obx->final_pkt)
+ {
+ /* Free current packet and send a new request */
+ bta_opc_send_get_req(p_cb);
+ rsp_code = OBX_RSP_CONTINUE;
+ }
+ else
+ rsp_code = OBX_RSP_OK;
+ }
+
+ if (rsp_code != OBX_RSP_CONTINUE)
+ {
+ p_data->obx_evt.rsp_code = rsp_code;
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, p_data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_ci_read
+**
+** Description Handles the response to a read call-out request.
+** This is called within the OBX get object request. The
+** operation has completed, send the OBX packet out.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_ci_read(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FS_CI_READ_EVT *p_revt = &p_data->read_evt;
+ tBTA_OPC_PROGRESS param;
+ BOOLEAN is_final;
+
+ p_cb->cout_active = FALSE;
+
+ /* Process read call-in event if operation is still active */
+ if (p_cb->obx_oper == OPC_OP_PUSH_OBJ)
+ {
+ if (p_revt->status != BTA_FS_CO_OK && p_revt->status != BTA_FS_CO_EOF)
+ {
+ p_data->obx_evt.rsp_code = OBX_RSP_FAILED;
+/* if abort added to OPC use -> bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, p_data); */
+ bta_opc_sm_execute(p_cb, BTA_OPC_API_CLOSE_EVT, p_data);
+ }
+ else
+ {
+ is_final = (p_revt->status == BTA_FS_CO_EOF) ? TRUE: FALSE;
+
+ /* Add the body header to the packet */
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_revt->num_read, is_final);
+
+ p_cb->obx.bytes_left -= p_revt->num_read;
+ p_cb->obx.offset += p_revt->num_read;
+
+ /* Send out the data */
+ OBX_PutReq(p_cb->obx_handle, is_final, p_obx->p_pkt);
+ p_obx->p_pkt = NULL;
+ p_cb->req_pending = TRUE;
+
+ /* Give application the status */
+ param.bytes = p_revt->num_read;
+ param.obj_size = p_cb->obj_size;
+ param.operation = BTA_OP_OPER_PUSH;
+ p_cb->p_cback(BTA_OPC_PROGRESS_EVT, (tBTA_OPC *)&param);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_ci_open
+**
+** Description Continue with the current file open operation
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_ci_open(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FS_CI_OPEN_EVT *p_open = &p_data->open_evt;
+ UINT8 rsp_code = OBX_RSP_FAILED;
+
+ p_cb->cout_active = FALSE;
+
+ /* if file is accessible read/write the first buffer of data */
+ if (p_open->status == BTA_FS_CO_OK)
+ {
+ p_cb->fd = p_open->fd;
+
+ if (p_cb->obx_oper == OPC_OP_PUSH_OBJ)
+ {
+ p_cb->obj_size = p_open->file_size;
+
+ rsp_code = bta_opc_send_put_req(p_cb, TRUE);
+ }
+ else if (p_cb->obx_oper == OPC_OP_PULL_OBJ)
+ {
+ rsp_code = OBX_RSP_OK;
+
+ /* Initiate the first OBX GET request */
+ p_obx->offset = 0;
+
+ /* Continue processing GET rsp */
+ bta_opc_cont_get_rsp(p_cb);
+ }
+ }
+ else
+ {
+ if (p_open->status == BTA_FS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ else /* File could not be found */
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+
+ if (rsp_code != OBX_RSP_OK)
+ {
+ p_data->obx_evt.rsp_code = rsp_code;
+ bta_opc_sm_execute(p_cb, BTA_OPC_API_CLOSE_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_obx_conn_rsp
+**
+** Description Process the OBX connect event.
+** If OPP service, get directory listing.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_obx_conn_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_EVT *p_evt = &p_data->obx_evt;
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ p_cb->peer_mtu = p_data->obx_evt.param.conn.mtu;
+
+ /* inform role manager */
+ bta_sys_conn_open( BTA_ID_OPC ,p_cb->app_id, bta_opc_cb.bd_addr);
+
+ p_cb->p_cback(BTA_OPC_OPEN_EVT, NULL);
+
+ /* start the first operation. For card exchange PUSH is done first */
+ if(p_cb->to_do & BTA_OPC_PUSH_MASK)
+ bta_opc_start_push(p_cb);
+ else
+ bta_opc_send_get_req(p_cb);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_obx_put_rsp
+**
+** Description Process the OBX file put and delete file/folder events
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_obx_put_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_OPC_OBJECT param;
+
+ p_cb->req_pending = FALSE;
+ APPL_TRACE_DEBUG1("bta_opc_obx_put_rsp to_do 0x%02x",p_cb->to_do);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ if (p_cb->obx_oper == OPC_OP_PUSH_OBJ)
+ {
+ /* If not finished with Put, start another read */
+ if (p_evt->rsp_code == OBX_RSP_CONTINUE)
+ bta_opc_send_put_req(p_cb, FALSE);
+
+ /* Start the Pull if this is card exchange */
+ else if (p_cb->to_do & BTA_OPC_PULL_MASK)
+ {
+ /* Close the current file and initiate a pull vcard */
+ bta_fs_co_close(p_cb->fd, p_cb->app_id);
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ /* If error occurred during push save it */
+ if (p_evt->rsp_code != OBX_RSP_OK)
+ p_cb->exch_status = BTA_OPC_FAIL;
+
+ /* Notify application with status of push operation */
+ param.status = p_cb->exch_status;
+ param.p_name = p_cb->p_name;
+ p_cb->p_cback(BTA_OPC_OBJECT_PSHD_EVT, (tBTA_OPC *)&param);
+
+ /* Initiate the Pull operation */
+ bta_opc_send_get_req(p_cb);
+ }
+ else /* Finished or an error occurred */
+ {
+ p_data->obx_evt.rsp_code = p_evt->rsp_code;
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, p_data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_obx_get_rsp
+**
+** Description Process the OBX file get and folder listing events
+** If the type header is not folder listing, then pulling a file.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_obx_get_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ BOOLEAN free_pkt = FALSE;
+
+ p_obx->final_pkt = (p_evt->rsp_code == OBX_RSP_OK) ? TRUE : FALSE;
+ p_obx->p_pkt = p_evt->p_pkt;
+ p_obx->rsp_code = p_evt->rsp_code;
+ p_cb->req_pending = FALSE;
+
+ if (p_cb->obx_oper == OPC_OP_PULL_OBJ)
+ {
+ /* Open file for writing */
+ if (p_cb->first_get_pkt == TRUE)
+ {
+ p_cb->first_get_pkt = FALSE;
+ free_pkt = bta_opc_proc_get_rsp(p_cb, p_data);
+ }
+ else /* Continuation of the object transfer */
+ bta_opc_cont_get_rsp(p_cb);
+ }
+ else
+ free_pkt = TRUE;
+
+ if (free_pkt) /* Release the OBX response packet */
+ utl_freebuf((void**)&p_obx->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_initialize
+**
+** Description Initialize the control block.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_initialize(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_FS_CO_STATUS status;
+
+ utl_freebuf((void**)&p_cb->obx.p_pkt);
+
+ /* Close any open files */
+ if (p_cb->fd >= 0)
+ {
+ bta_fs_co_close(p_cb->fd, p_cb->app_id);
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ /* Delete an aborted unfinished get vCard operation */
+ if (p_cb->obx_oper == OPC_OP_PULL_OBJ && p_cb->status != BTA_OPC_OK)
+ {
+ status = bta_fs_co_unlink(p_cb->p_name, p_cb->app_id);
+ APPL_TRACE_WARNING2("OPC: Remove ABORTED Get File Operation [%s], status 0x%02x",
+ p_cb->p_name, status);
+ }
+ }
+
+ utl_freebuf((void**)&p_cb->p_name);
+
+ /* Clean up control block */
+ p_cb->obx_oper = OPC_OP_NONE;
+ p_cb->req_pending = FALSE;
+ p_cb->sdp_pending = FALSE;
+ p_cb->to_do = 0;
+ p_cb->p_rcv_path = NULL;
+ p_cb->first_get_pkt = FALSE;
+
+ if (p_cb->disabling)
+ {
+ p_cb->disabling = FALSE;
+ bta_opc_sm_execute(p_cb, BTA_OPC_DISABLE_CMPL_EVT, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_stop_client
+**
+** Description Stop OBX client.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_stop_client(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ if (!p_cb->sdp_pending)
+ {
+// btla-specific ++
+#if defined (BTA_OPC_SENDING_ABORT) && (BTA_OPC_SENDING_ABORT == TRUE)
+ APPL_TRACE_WARNING3("bta_opc_stop_client p_cb->req_pending = %d, p_cb->sdp_pending = %d,handle = %d",
+ p_cb->req_pending, p_cb->sdp_pending,p_cb->obx_handle);
+ /* Abort an active request */
+ if (p_cb->req_pending)
+ OBX_AbortReq(p_cb->obx_handle, (BT_HDR *)NULL);
+#endif
+// btla-specific --
+ /* do not free p_cb->obx.p_pkt here, just in case cout_active.
+ * bta_opc_close_complete would handle it */
+ OBX_DisconnectReq(p_cb->obx_handle, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_close
+**
+** Description If not waiting for a call-in function, complete the closing
+** of the channel.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_close(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ /* finished if not waiting on a call-in function */
+ if (!p_cb->cout_active)
+ bta_opc_sm_execute(p_cb, BTA_OPC_CLOSE_CMPL_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_start_client
+**
+** Description Start an OPP operation.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_start_client(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ tOBX_STATUS status;
+ BOOLEAN srm = p_cb->srm;
+
+ /* Allocate an OBX packet */
+ if ((p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(OBX_HANDLE_NULL, OBX_MAX_MTU)) != NULL)
+ {
+ status = OBX_AllocSession (NULL, p_data->sdp_ok.scn, &p_data->sdp_ok.psm,
+ bta_opc_obx_cback, &p_cb->obx_handle);
+
+ /* set security level */
+ if (p_data->sdp_ok.scn)
+ {
+ BTM_SetSecurityLevel (TRUE, "BTA_OPC", BTM_SEC_SERVICE_OBEX,
+ p_cb->sec_mask, BT_PSM_RFCOMM,
+ BTM_SEC_PROTO_RFCOMM, p_data->sdp_ok.scn);
+ srm = 0;
+ }
+ else
+ {
+ BTM_SetSecurityLevel (TRUE, "BTA_OPC", BTM_SEC_SERVICE_OBEX,
+ p_cb->sec_mask, p_data->sdp_ok.psm, 0, 0);
+ }
+
+ if (status == OBX_SUCCESS)
+ {
+ OBX_CreateSession (p_cb->bd_addr, OBX_MAX_MTU, srm, 0,
+ p_cb->obx_handle, p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* OBX will free the memory */
+ return;
+ }
+ }
+ else
+ {
+ p_data->obx_evt.rsp_code = OBX_RSP_FAILED;
+ bta_opc_sm_execute(p_cb, BTA_OPC_CLOSE_CMPL_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_free_db
+**
+** Description Free buffer used for service discovery database.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_free_db(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ utl_freebuf((void**)&p_cb->p_db);
+ p_cb->sdp_pending = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_ignore_obx
+**
+** Description Free OBX packet for ignored OBX events.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_ignore_obx(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ utl_freebuf((void**)&p_data->obx_evt.p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_find_service
+**
+** Description Perform service discovery to find the OPP service on the
+** peer device.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_find_service(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tSDP_UUID uuid_list;
+ UINT16 attr_list[3];
+
+ if (!p_cb->to_do)
+ return;
+
+ bdcpy(p_cb->bd_addr, p_data->api_push.bd_addr);
+ if ((p_cb->p_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_OPC_DISC_SIZE)) != NULL)
+ {
+ attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+ attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+ attr_list[2] = ATTR_ID_OBX_OVR_L2CAP_PSM;
+
+ uuid_list.len = LEN_UUID_16;
+ uuid_list.uu.uuid16 = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
+ p_cb->sdp_pending = TRUE;
+ SDP_InitDiscoveryDb(p_cb->p_db, BTA_OPC_DISC_SIZE, 1, &uuid_list, 3, attr_list);
+ if(!SDP_ServiceSearchAttributeRequest(p_cb->bd_addr, p_cb->p_db, bta_opc_sdp_cback))
+ {
+ bta_opc_sm_execute(p_cb, BTA_OPC_SDP_FAIL_EVT, (tBTA_OPC_DATA *)NULL);
+ }
+ }
+ else
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, (tBTA_OPC_DATA *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_close_complete
+**
+** Description Finishes the memory cleanup after a channel is closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_close_complete(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ p_cb->cout_active = FALSE;
+ bta_opc_initialize(p_cb, p_data);
+
+ /* inform role manager */
+ bta_sys_conn_close( BTA_ID_OPC ,p_cb->app_id, bta_opc_cb.bd_addr);
+
+ p_cb->p_cback(BTA_OPC_CLOSE_EVT, (tBTA_OPC *)&p_cb->status);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_set_disable
+**
+** Description Sets flag to disable.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_set_disable(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ p_cb->disabling = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_chk_close
+**
+** Description Check if we need to stop the client now.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_chk_close(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ if (p_cb->single_op)
+ {
+ bta_opc_sm_execute(p_cb, BTA_OPC_API_CLOSE_EVT, (tBTA_OPC_DATA *)NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_do_pull
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_do_pull(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ APPL_TRACE_DEBUG1("bta_opc_do_pull to_do 0x%02x",p_cb->to_do);
+ bta_opc_send_get_req(p_cb);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_do_push
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_do_push(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ APPL_TRACE_DEBUG1("bta_opc_do_push to_do 0x%02x",p_cb->to_do);
+ bta_opc_start_push(p_cb);
+}
+
+/*****************************************************************************
+** Callback Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_opc_obx_cback
+**
+** Description OBX callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event, UINT8 rsp_code,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt)
+{
+ tBTA_OPC_OBX_EVT *p_obx_msg;
+ UINT16 event = 0;
+
+#if BTA_OPC_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("OBX Event Callback: obx_event [%s]", opc_obx_evt_code(obx_event));
+#endif
+
+ switch(obx_event)
+ {
+ case OBX_CONNECT_RSP_EVT:
+ if (rsp_code == OBX_RSP_OK)
+ {
+ event = BTA_OPC_OBX_CONN_RSP_EVT;
+ }
+ else /* Obex will disconnect underneath BTA */
+ {
+ APPL_TRACE_WARNING1("OPC_CBACK: Bad connect response 0x%02x", rsp_code);
+ if (p_pkt)
+ GKI_freebuf(p_pkt);
+ return;
+ }
+ break;
+ case OBX_PUT_RSP_EVT:
+ event = BTA_OPC_OBX_PUT_RSP_EVT;
+ break;
+ case OBX_GET_RSP_EVT:
+ event = BTA_OPC_OBX_GET_RSP_EVT;
+ break;
+ case OBX_CLOSE_IND_EVT:
+ event = BTA_OPC_OBX_CLOSE_EVT;
+ break;
+ case OBX_PASSWORD_EVT:
+ event = BTA_OPC_OBX_PASSWORD_EVT;
+ break;
+
+ default:
+/* case OBX_ABORT_RSP_EVT: */
+/* case OBX_DISCONNECT_RSP_EVT: Handled when OBX_CLOSE_IND_EVT arrives */
+ if (p_pkt)
+ GKI_freebuf(p_pkt);
+ return;
+ }
+
+ /* send event to BTA, if any */
+ if ((p_obx_msg = (tBTA_OPC_OBX_EVT *) GKI_getbuf(sizeof(tBTA_OPC_OBX_EVT))) != NULL)
+ {
+ p_obx_msg->hdr.event = event;
+ 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);
+ }
+}
+
+/******************************************************************************
+**
+** Function bta_opc_sdp_cback
+**
+** Description This is the SDP callback function used by OPC.
+** 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.
+**
+** Returns Nothing.
+**
+******************************************************************************/
+static void bta_opc_sdp_cback(UINT16 status)
+{
+ tBTA_OPC_SDP_OK_EVT *p_buf;
+ tSDP_DISC_REC *p_rec = NULL;
+ tSDP_PROTOCOL_ELEM pe;
+ UINT8 scn = 0;
+ BOOLEAN found = FALSE;
+ UINT16 version = GOEP_LEGACY_VERSION;
+ UINT16 psm = 0;
+ tSDP_DISC_ATTR *p_attr;
+
+ APPL_TRACE_DEBUG1("bta_opc_sdp_cback status:%d", status);
+
+ if ( (status == SDP_SUCCESS) || (status == SDP_DB_FULL) )
+ {
+ status = SDP_SUCCESS;
+ /* loop through all records we found */
+ do
+ {
+ /* get next record; if none found, we're done */
+ if ((p_rec = SDP_FindServiceInDb(bta_opc_cb.p_db,
+ UUID_SERVCLASS_OBEX_OBJECT_PUSH, p_rec)) == NULL)
+ break;
+
+ /* this is an optional attribute */
+ SDP_FindProfileVersionInRec (p_rec, UUID_SERVCLASS_OBEX_OBJECT_PUSH, &version);
+
+ /* get psm from proto desc list alternative; if not found, go to next record */
+ if ((p_attr = SDP_FindAttributeInRec(p_rec,
+ ATTR_ID_OBX_OVR_L2CAP_PSM)) != NULL)
+ {
+ psm = p_attr->attr_value.v.u16;
+ if ((SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 2) && L2C_IS_VALID_PSM(psm))
+ {
+ found = TRUE;
+ if (version == GOEP_LEGACY_VERSION)
+ {
+ APPL_TRACE_ERROR0("Lacking mandatory attribute/version");
+ version = GOEP_ENHANCED_VERSION;
+ }
+ break;
+ }
+ }
+
+ /* If no OBEX over L2CAP look for RFCOMM SCN */
+ if (!found)
+ {
+ /* get scn from proto desc list; if not found, go to next record */
+ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ scn = (UINT8) pe.params[0];
+
+ /* we've got everything, we're done */
+ found = TRUE;
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ } while (TRUE);
+ }
+
+ /* send result in event back to BTA */
+ if ((p_buf = (tBTA_OPC_SDP_OK_EVT *) GKI_getbuf(sizeof(tBTA_OPC_SDP_OK_EVT))) != NULL)
+ {
+ if ((status == SDP_SUCCESS) && (found == TRUE))
+ {
+ p_buf->hdr.event = BTA_OPC_SDP_OK_EVT;
+ p_buf->scn = scn;
+ p_buf->psm = psm;
+ p_buf->version = version;
+ }
+ else
+ p_buf->hdr.event = BTA_OPC_SDP_FAIL_EVT;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*****************************************************************************
+** Local OPP Event Processing Functions
+*****************************************************************************/
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_OPC_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function opc_obx_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *opc_obx_evt_code(tOBX_EVENT evt_code)
+{
+ switch(evt_code)
+ {
+ case OBX_CONNECT_RSP_EVT:
+ return "OBX_CONNECT_RSP_EVT";
+ case OBX_DISCONNECT_RSP_EVT:
+ return "OBX_DISCONNECT_RSP_EVT";
+ case OBX_PUT_RSP_EVT:
+ return "OBX_PUT_RSP_EVT";
+ case OBX_GET_RSP_EVT:
+ return "OBX_GET_RSP_EVT";
+ case OBX_SETPATH_RSP_EVT:
+ return "OBX_SETPATH_RSP_EVT";
+ case OBX_ABORT_RSP_EVT:
+ return "OBX_ABORT_RSP_EVT";
+ case OBX_CLOSE_IND_EVT:
+ return "OBX_CLOSE_IND_EVT";
+ case OBX_TIMEOUT_EVT:
+ return "OBX_TIMEOUT_EVT";
+ case OBX_PASSWORD_EVT:
+ return "OBX_PASSWORD_EVT";
+ default:
+ return "unknown OBX event code";
+ }
+}
+#endif /* Debug Functions */
diff --git a/bta/op/bta_opc_api.c b/bta/op/bta_opc_api.c
new file mode 100644
index 0000000..4440b1c
--- /dev/null
+++ b/bta/op/bta_opc_api.c
@@ -0,0 +1,214 @@
+/*****************************************************************************
+**
+** Name: bta_opc_api.c
+**
+** Description: This is the implementation of the API for the object
+** push client subsystem of BTA, Widcomm's Bluetooth
+** application layer for mobile phones.
+**
+** Copyright (c) 2003 - 2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_fs_api.h"
+#include "bta_op_api.h"
+#include "bta_opc_int.h"
+#include "bd.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_opc_reg =
+{
+ bta_opc_hdl_event,
+ BTA_OpcDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_OpcEnable
+**
+** Description Enable the object push client. This function must be
+** called before any other functions in the DG API are called.
+** When the enable operation is complete the callback function
+** will be called with a BTA_OPC_ENABLE_EVT.
+**
+** If single_op is FALSE, the connection stays open after
+** the operation finishes (until BTA_OpcClose is called).
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpcEnable(tBTA_SEC sec_mask, tBTA_OPC_CBACK *p_cback,
+ BOOLEAN single_op, BOOLEAN srm, UINT8 app_id)
+{
+ tBTA_OPC_API_ENABLE *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_OPC, &bta_opc_reg);
+ GKI_sched_unlock();
+
+ /* initialize control block */
+ memset(&bta_opc_cb, 0, sizeof(tBTA_OPC_CB));
+
+ if ((p_buf = (tBTA_OPC_API_ENABLE *) GKI_getbuf(sizeof(tBTA_OPC_API_ENABLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_OPC_API_ENABLE_EVT;
+ p_buf->p_cback = p_cback;
+ p_buf->sec_mask = sec_mask;
+ p_buf->single_op = single_op;
+ p_buf->srm = srm;
+ p_buf->app_id = app_id;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpcDisable
+**
+** Description Disable the object push client. If the client is currently
+** connected to a peer device the connection will be closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpcDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_OPC);
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_OPC_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpcPush
+**
+** Description Push an object to a peer device. p_name must point to
+** a fully qualified path and file name.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpcPush(BD_ADDR bd_addr, tBTA_OP_FMT format, char *p_name)
+{
+ tBTA_OPC_DATA *p_msg;
+
+ if ((p_msg = (tBTA_OPC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_OPC_DATA) +
+ p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ p_msg->api_push.p_name = (char *)(p_msg + 1);
+ BCM_STRNCPY_S(p_msg->api_push.p_name, p_bta_fs_cfg->max_path_len+1, p_name, p_bta_fs_cfg->max_path_len);
+ p_msg->api_push.p_name[p_bta_fs_cfg->max_path_len] = '\0';
+ p_msg->hdr.event = BTA_OPC_API_PUSH_EVT;
+ bdcpy(p_msg->api_push.bd_addr, bd_addr);
+ p_msg->api_push.format = format;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpcPullCard
+**
+** Description Pull default card from peer. p_path must point to a fully
+** qualified path specifying where to store the pulled card.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpcPullCard(BD_ADDR bd_addr, char *p_path)
+{
+ tBTA_OPC_DATA *p_msg;
+ tBTA_OPC_API_PULL *p_pull;
+
+ if ((p_msg = (tBTA_OPC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_OPC_DATA) +
+ (p_bta_fs_cfg->max_path_len + 1)))) != NULL)
+ {
+ p_pull = &p_msg->api_pull;
+ p_pull->p_path = (char *)(p_msg + 1);
+ BCM_STRNCPY_S(p_pull->p_path, p_bta_fs_cfg->max_path_len+1, p_path, p_bta_fs_cfg->max_path_len);
+ p_pull->p_path[p_bta_fs_cfg->max_path_len] = '\0';
+ bdcpy(p_pull->bd_addr, bd_addr);
+ p_pull->hdr.event = BTA_OPC_API_PULL_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpcExchCard
+**
+** Description Exchange business cards with a peer device. p_send points to
+** a fully qualified path and file name of vcard to push.
+** p_recv_path points to a fully qualified path specifying
+** where to store the pulled card.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpcExchCard(BD_ADDR bd_addr, char *p_send, char *p_recv_path)
+{
+ tBTA_OPC_DATA *p_msg;
+ tBTA_OPC_API_EXCH *p_exch;
+
+ if(!p_send || !p_recv_path)
+ return;
+
+ if ((p_msg = (tBTA_OPC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_OPC_DATA) +
+ (p_bta_fs_cfg->max_path_len + 1) * 2))) != NULL)
+ {
+ p_exch = &p_msg->api_exch;
+ p_exch->p_send = (char *)(p_msg + 1);
+ p_exch->p_rcv_path = (char *)(p_exch->p_send + p_bta_fs_cfg->max_path_len + 1);
+ BCM_STRNCPY_S(p_exch->p_send, p_bta_fs_cfg->max_path_len+1, p_send, p_bta_fs_cfg->max_path_len);
+ p_exch->p_send[p_bta_fs_cfg->max_path_len] = '\0';
+ BCM_STRNCPY_S(p_exch->p_rcv_path, p_bta_fs_cfg->max_path_len+1, p_recv_path, p_bta_fs_cfg->max_path_len);
+ p_exch->p_rcv_path[p_bta_fs_cfg->max_path_len] = '\0';
+ bdcpy(p_exch->bd_addr, bd_addr);
+ p_exch->hdr.event = BTA_OPC_API_EXCH_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpcClose
+**
+** Description Close the current connection. This function is called if
+** the phone wishes to close the connection before the object
+** push is completed. In a typical connection this function
+** does not need to be called; the connection will be closed
+** automatically when the object push is complete.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpcClose(void)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_OPC_API_CLOSE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+
diff --git a/bta/op/bta_opc_int.h b/bta/op/bta_opc_int.h
new file mode 100644
index 0000000..e26d2b5
--- /dev/null
+++ b/bta/op/bta_opc_int.h
@@ -0,0 +1,257 @@
+/*****************************************************************************
+**
+** Name: bta_opc_int.h
+**
+** Description: This is the private header file for the Object Push
+** Client (OPC).
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_OPC_INT_H
+#define BTA_OPC_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_op_api.h"
+#include "bta_fs_co.h"
+#include "bta_fs_ci.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+
+#define OPC_DEF_NAME "default_opc.vcf"
+
+/* if the pulled vCard does not have a Name Header associated with it,
+ * this is the default name used to received the file.
+ * Please make sure that this is of different file name than the local
+ * default vCard file name */
+#ifndef OPC_DEF_RCV_NAME
+#define OPC_DEF_RCV_NAME "opc_def_rcv.vcf"
+#endif
+
+/* OPC Active opp obex operation (Valid in connected state) */
+#define OPC_OP_NONE 0
+#define OPC_OP_PULL_OBJ 1
+#define OPC_OP_PUSH_OBJ 2
+
+/* Constants used for "to_do" list */
+#define BTA_OPC_PUSH_MASK 0x01
+#define BTA_OPC_PULL_MASK 0x02
+
+/* state machine events */
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_OPC_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_OPC),
+ BTA_OPC_API_DISABLE_EVT,
+ BTA_OPC_API_CLOSE_EVT, /* Close connection event */
+ BTA_OPC_API_PUSH_EVT, /* Push Object request */
+ BTA_OPC_API_PULL_EVT, /* Pull Object request */
+ BTA_OPC_API_EXCH_EVT, /* Exchange business Cards */
+ BTA_OPC_SDP_OK_EVT, /* Service search was successful */
+ BTA_OPC_SDP_FAIL_EVT, /* Service search failed */
+ BTA_OPC_CI_WRITE_EVT, /* Call-in response to Write request */
+ BTA_OPC_CI_READ_EVT, /* Call-in response to Read request */
+ BTA_OPC_CI_OPEN_EVT, /* Call-in response to File Open request */
+ BTA_OPC_OBX_CONN_RSP_EVT, /* OBX Channel Connect Request */
+ BTA_OPC_OBX_PASSWORD_EVT, /* OBX password requested */
+ BTA_OPC_OBX_CLOSE_EVT, /* OBX Channel Disconnected (Link Lost) */
+ BTA_OPC_OBX_PUT_RSP_EVT, /* Write file data or delete */
+ BTA_OPC_OBX_GET_RSP_EVT, /* Read file data or folder listing */
+ BTA_OPC_OBX_CMPL_EVT, /* operation has completed */
+ BTA_OPC_CLOSE_CMPL_EVT, /* Finish the closing of the channel */
+ BTA_OPC_DISABLE_CMPL_EVT /* Transition to disabled state */
+};
+
+typedef UINT16 tBTA_OPC_INT_EVT;
+
+typedef UINT8 tBTA_OPC_STATE;
+
+/* data type for BTA_OPC_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_OPC_CBACK *p_cback;
+ UINT8 sec_mask;
+ BOOLEAN single_op;
+ BOOLEAN srm;
+ UINT8 app_id;
+} tBTA_OPC_API_ENABLE;
+
+/* data type for BTA_OPC_API_PUSH_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ char *p_name;
+ tBTA_OP_FMT format;
+} tBTA_OPC_API_PUSH;
+
+/* data type for BTA_OPC_API_PULL_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ char *p_path;
+} tBTA_OPC_API_PULL;
+
+/* data type for BTA_OPC_API_EXCH_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ char *p_send;
+ char *p_rcv_path;
+} tBTA_OPC_API_EXCH;
+
+/* data type for BTA_OPC_SDP_OK_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 scn;
+ UINT16 psm;
+ UINT16 version;
+} tBTA_OPC_SDP_OK_EVT;
+
+/* data type for all obex events
+ hdr.event contains the OPC 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_OPC_OBX_EVT;
+
+/* union of all event data types */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_OPC_API_ENABLE api_enable;
+ tBTA_OPC_API_PUSH api_push;
+ tBTA_OPC_API_PULL api_pull;
+ tBTA_OPC_API_EXCH api_exch;
+ tBTA_OPC_SDP_OK_EVT sdp_ok;
+ tBTA_OPC_OBX_EVT obx_evt;
+ tBTA_FS_CI_OPEN_EVT open_evt;
+ tBTA_FS_CI_READ_EVT read_evt;
+ tBTA_FS_CI_WRITE_EVT write_evt;
+} tBTA_OPC_DATA;
+
+
+/* OBX Response Packet Structure - Holds current command/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 leop in Obx packet */
+ BOOLEAN final_pkt; /* (Get) Holds the final bit of the Put packet */
+ UINT8 rsp_code;
+} tBTA_OPC_OBX_PKT;
+
+/* Power management state for OPC */
+#define BTA_OPC_PM_BUSY 0
+#define BTA_OPC_PM_IDLE 1
+
+/* OPC control block */
+typedef struct
+{
+ tBTA_OPC_CBACK *p_cback; /* pointer to application callback function */
+ char *p_name; /* Holds the local path and file name of pushed item */
+ char *p_rcv_path; /* Holds the local path and file name of received item (card exch only) */
+ tSDP_DISCOVERY_DB *p_db; /* pointer to discovery database */
+ tBTA_OPC_OBX_PKT obx; /* Holds the current OBX packet information */
+ int fd; /* File Descriptor of opened file */
+ UINT32 obj_size; /* (Push/Pull) file length */
+ tOBX_HANDLE obx_handle;
+ UINT16 peer_mtu;
+ BD_ADDR bd_addr;
+ BOOLEAN single_op; /* if TRUE, close OBX connection when OP finishes */
+ UINT8 sec_mask;
+ tBTA_OPC_STATE state; /* state machine state */
+ tBTA_OP_FMT format;
+ UINT8 obx_oper; /* current active OBX operation PUT FILE or GET FILE */
+ UINT8 to_do; /* actions to be done (push,pull) */
+ UINT8 app_id;
+ tBTA_OPC_STATUS status;
+ tBTA_OPC_STATUS exch_status;
+ BOOLEAN first_get_pkt; /* TRUE if retrieving the first packet of GET object */
+ BOOLEAN cout_active; /* TRUE if call-out is currently active */
+ BOOLEAN req_pending; /* TRUE if an obx request to peer is in progress */
+ BOOLEAN disabling; /* TRUE if an disabling client */
+ BOOLEAN sdp_pending; /* TRUE when waiting for SDP to complete */
+ BOOLEAN srm; /* TRUE, to use SIngle Response Mode */
+ UINT8 pm_state;
+} tBTA_OPC_CB;
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* OPC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_OPC_CB bta_opc_cb;
+#else
+extern tBTA_OPC_CB *bta_opc_cb_ptr;
+#define bta_opc_cb (*bta_opc_cb_ptr)
+#endif
+
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+extern BOOLEAN bta_opc_hdl_event(BT_HDR *p_msg);
+extern void bta_opc_sm_execute(tBTA_OPC_CB *p_cb, UINT16 event,
+ tBTA_OPC_DATA *p_data);
+extern void bta_opc_obx_cback (tOBX_HANDLE handle, tOBX_EVENT event,
+ UINT8 rsp_code, tOBX_EVT_PARAM param,
+ BT_HDR *p_pkt);
+
+/* action functions */
+extern void bta_opc_init_close(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_init_push(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_init_pull(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_init_exch(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_send_authrsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_ci_write(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_ci_read(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_ci_open(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_obx_conn_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_obx_put_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_obx_get_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_initialize(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_trans_cmpl(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_stop_client(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_start_client(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_free_db(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_ignore_obx(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_find_service(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_close(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_close_complete(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_set_disable(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_chk_close(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_do_pull(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_do_push(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_enable(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+
+/* miscellaneous functions */
+extern UINT8 bta_opc_send_get_req(tBTA_OPC_CB *p_cb);
+extern BOOLEAN bta_opc_proc_get_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_cont_get_rsp(tBTA_OPC_CB *p_cb);
+extern UINT8 bta_opc_send_put_req(tBTA_OPC_CB *p_cb, BOOLEAN first_pkt);
+extern void bta_opc_start_push(tBTA_OPC_CB *p_cb);
+extern void bta_opc_listing_err(BT_HDR **p_pkt, tBTA_OPC_STATUS status);
+
+extern tBTA_OPC_STATUS bta_opc_convert_obx_to_opc_status(tOBX_STATUS obx_status);
+
+#endif /* BTA_OPC_INT_H */
diff --git a/bta/op/bta_opc_main.c b/bta/op/bta_opc_main.c
new file mode 100644
index 0000000..cf76143
--- /dev/null
+++ b/bta/op/bta_opc_main.c
@@ -0,0 +1,425 @@
+/*****************************************************************************
+**
+** Name: bta_opc_main.c
+**
+** Description: This file contains the file transfer client main functions
+** and state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#include <string.h>
+
+#include "bta_opc_int.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* state machine states */
+enum
+{
+ BTA_OPC_DISABLED_ST = 0, /* Disabled */
+ BTA_OPC_IDLE_ST, /* Idle */
+ BTA_OPC_W4_CONN_ST, /* Waiting for an Obex connect response */
+ BTA_OPC_CONN_ST, /* Connected - OPP Session is active */
+ BTA_OPC_CLOSING_ST /* Closing is in progress */
+};
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_OPC_START_CLIENT,
+ BTA_OPC_STOP_CLIENT,
+ BTA_OPC_INIT_PULL,
+ BTA_OPC_INIT_PUSH,
+ BTA_OPC_INIT_EXCH,
+ BTA_OPC_CI_WRITE,
+ BTA_OPC_CI_READ,
+ BTA_OPC_CI_OPEN,
+ BTA_OPC_OBX_CONN_RSP,
+ BTA_OPC_CLOSE,
+ BTA_OPC_OBX_PUT_RSP,
+ BTA_OPC_OBX_GET_RSP,
+ BTA_OPC_TRANS_CMPL,
+ BTA_OPC_FREE_DB,
+ BTA_OPC_IGNORE_OBX,
+ BTA_OPC_FIND_SERVICE,
+ BTA_OPC_INITIALIZE,
+ BTA_OPC_CLOSE_COMPLETE,
+ BTA_OPC_SET_DISABLE,
+ BTA_OPC_CHK_CLOSE,
+ BTA_OPC_DO_PUSH,
+ BTA_OPC_DO_PULL,
+ BTA_OPC_ENABLE,
+ BTA_OPC_IGNORE
+};
+
+/* type for action functions */
+typedef void (*tBTA_OPC_ACTION)(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+
+/* action function list */
+const tBTA_OPC_ACTION bta_opc_action[] =
+{
+ bta_opc_start_client,
+ bta_opc_stop_client,
+ bta_opc_init_pull,
+ bta_opc_init_push,
+ bta_opc_init_exch,
+ bta_opc_ci_write,
+ bta_opc_ci_read,
+ bta_opc_ci_open,
+ bta_opc_obx_conn_rsp,
+ bta_opc_close,
+ bta_opc_obx_put_rsp,
+ bta_opc_obx_get_rsp,
+ bta_opc_trans_cmpl,
+ bta_opc_free_db,
+ bta_opc_ignore_obx,
+ bta_opc_find_service,
+ bta_opc_initialize,
+ bta_opc_close_complete,
+ bta_opc_set_disable,
+ bta_opc_chk_close,
+ bta_opc_do_push,
+ bta_opc_do_pull,
+ bta_opc_enable
+};
+
+
+/* state table information */
+#define BTA_OPC_ACTIONS 2 /* number of actions */
+#define BTA_OPC_NEXT_STATE 2 /* position of next state */
+#define BTA_OPC_NUM_COLS 3 /* number of columns in state tables */
+
+/* state table for disabled state (enable is handled*/
+static const UINT8 bta_opc_st_disabled[][BTA_OPC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_OPC_API_ENABLE_EVT */ {BTA_OPC_ENABLE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_API_DISABLE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST},
+/* BTA_OPC_API_DISABLE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST},
+/* BTA_OPC_API_CLOSE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST},
+/* BTA_OPC_API_PUSH_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST},
+/* BTA_OPC_API_PULL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST},
+/* BTA_OPC_API_EXCH_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST}
+};
+
+/* state table for idle state */
+static const UINT8 bta_opc_st_idle[][BTA_OPC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_OPC_API_ENABLE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_API_DISABLE_EVT */ {BTA_OPC_INITIALIZE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST},
+/* BTA_OPC_API_CLOSE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_API_PUSH_EVT */ {BTA_OPC_INIT_PUSH, BTA_OPC_FIND_SERVICE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_API_PULL_EVT */ {BTA_OPC_INIT_PULL, BTA_OPC_FIND_SERVICE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_API_EXCH_EVT */ {BTA_OPC_INIT_EXCH, BTA_OPC_FIND_SERVICE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_SDP_OK_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_SDP_FAIL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CI_WRITE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CI_READ_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CI_OPEN_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_CONN_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_PASSWORD_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_CLOSE_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_PUT_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_GET_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CLOSE_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_DISABLE_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST}
+};
+
+/* state table for wait for authentication response state */
+static const UINT8 bta_opc_st_w4_conn[][BTA_OPC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_OPC_API_ENABLE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_API_DISABLE_EVT */ {BTA_OPC_SET_DISABLE, BTA_OPC_STOP_CLIENT, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_CLOSE_EVT */ {BTA_OPC_STOP_CLIENT, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_PUSH_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_API_PULL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_API_EXCH_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_SDP_OK_EVT */ {BTA_OPC_FREE_DB, BTA_OPC_START_CLIENT, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_SDP_FAIL_EVT */ {BTA_OPC_FREE_DB, BTA_OPC_CLOSE_COMPLETE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CI_WRITE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_CI_READ_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_CI_OPEN_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_OBX_CONN_RSP_EVT */ {BTA_OPC_OBX_CONN_RSP, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_OBX_PASSWORD_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_STOP_CLIENT, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_OBX_CLOSE_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_CLOSE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_PUT_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_OBX_GET_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_OBX_CMPL_EVT */ {BTA_OPC_TRANS_CMPL, BTA_OPC_STOP_CLIENT, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_CLOSE_CMPL_EVT */ {BTA_OPC_CLOSE_COMPLETE,BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_DISABLE_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_opc_st_connected[][BTA_OPC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_OPC_API_ENABLE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_API_DISABLE_EVT */ {BTA_OPC_SET_DISABLE, BTA_OPC_STOP_CLIENT, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_CLOSE_EVT */ {BTA_OPC_STOP_CLIENT, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_PUSH_EVT */ {BTA_OPC_INIT_PUSH, BTA_OPC_DO_PUSH, BTA_OPC_CONN_ST},
+/* BTA_OPC_API_PULL_EVT */ {BTA_OPC_INIT_PULL, BTA_OPC_DO_PULL, BTA_OPC_CONN_ST},
+/* BTA_OPC_API_EXCH_EVT */ {BTA_OPC_INIT_EXCH, BTA_OPC_DO_PUSH, BTA_OPC_CONN_ST},
+/* BTA_OPC_SDP_OK_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_SDP_FAIL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_CI_WRITE_EVT */ {BTA_OPC_CI_WRITE, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_CI_READ_EVT */ {BTA_OPC_CI_READ, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_CI_OPEN_EVT */ {BTA_OPC_CI_OPEN, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_OBX_CONN_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_OBX_PASSWORD_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_STOP_CLIENT, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_CLOSE_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_CLOSE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_PUT_RSP_EVT */ {BTA_OPC_OBX_PUT_RSP, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_OBX_GET_RSP_EVT */ {BTA_OPC_OBX_GET_RSP, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_OBX_CMPL_EVT */ {BTA_OPC_TRANS_CMPL, BTA_OPC_CHK_CLOSE, BTA_OPC_CONN_ST},
+/* BTA_OPC_CLOSE_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_DISABLE_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST}
+};
+
+/* state table for closing state */
+static const UINT8 bta_opc_st_closing[][BTA_OPC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_OPC_API_ENABLE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_DISABLE_EVT */ {BTA_OPC_SET_DISABLE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_CLOSE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_PUSH_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_PULL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_EXCH_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_SDP_OK_EVT */ {BTA_OPC_FREE_DB, BTA_OPC_CLOSE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_SDP_FAIL_EVT */ {BTA_OPC_FREE_DB, BTA_OPC_CLOSE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_CI_WRITE_EVT */ {BTA_OPC_CLOSE_COMPLETE,BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CI_READ_EVT */ {BTA_OPC_CLOSE_COMPLETE,BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CI_OPEN_EVT */ {BTA_OPC_CLOSE_COMPLETE,BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_CONN_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_STOP_CLIENT, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_PASSWORD_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_CLOSE_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_CLOSE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_PUT_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_GET_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_CLOSE_CMPL_EVT */ {BTA_OPC_CLOSE_COMPLETE,BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_DISABLE_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_OPC_ST_TBL)[BTA_OPC_NUM_COLS];
+
+/* state table */
+const tBTA_OPC_ST_TBL bta_opc_st_tbl[] =
+{
+ bta_opc_st_disabled,
+ bta_opc_st_idle,
+ bta_opc_st_w4_conn,
+ bta_opc_st_connected,
+ bta_opc_st_closing
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* OPC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_OPC_CB bta_opc_cb;
+#endif
+
+#if BTA_OPC_DEBUG == TRUE
+static char *opc_evt_code(tBTA_OPC_INT_EVT evt_code);
+static char *opc_state_code(tBTA_OPC_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function bta_opc_sm_execute
+**
+** Description State machine event handling function for OPC
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_sm_execute(tBTA_OPC_CB *p_cb, UINT16 event, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_ST_TBL state_table;
+ UINT8 action;
+ int i;
+
+ /* look up the state table for the current state */
+ state_table = bta_opc_st_tbl[p_cb->state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_cb->state = state_table[event][BTA_OPC_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_OPC_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_OPC_IGNORE)
+ {
+ (*bta_opc_action[action])(p_cb, p_data);
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_hdl_event
+**
+** Description File transfer server main event handling function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_opc_hdl_event(BT_HDR *p_msg)
+{
+ tBTA_OPC_CB *p_cb = &bta_opc_cb;
+
+#if BTA_OPC_DEBUG == TRUE
+ tBTA_OPC_STATE in_state = p_cb->state;
+ APPL_TRACE_DEBUG3("OPC Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ opc_state_code(in_state),
+ opc_evt_code(p_msg->event));
+#endif
+
+ bta_opc_sm_execute(p_cb, p_msg->event, (tBTA_OPC_DATA *) p_msg);
+
+ if ( p_cb->state == BTA_OPC_CONN_ST )
+ {
+ if (( p_cb->pm_state == BTA_OPC_PM_IDLE )
+ &&( p_cb->obx_oper != OPC_OP_NONE ))
+ {
+ /* inform power manager */
+ APPL_TRACE_DEBUG0("BTA OPC informs DM/PM busy state");
+ bta_sys_busy( BTA_ID_OPC, p_cb->app_id, p_cb->bd_addr );
+ p_cb->pm_state = BTA_OPC_PM_BUSY;
+ }
+ else if (( p_cb->pm_state == BTA_OPC_PM_BUSY )
+ &&( p_cb->obx_oper == OPC_OP_NONE ))
+ {
+ /* inform power manager */
+ APPL_TRACE_DEBUG0("BTA OPC informs DM/PM idle state");
+ bta_sys_idle( BTA_ID_OPC ,p_cb->app_id, p_cb->bd_addr);
+ p_cb->pm_state = BTA_OPC_PM_IDLE;
+ }
+ }
+ else if ( p_cb->state == BTA_OPC_IDLE_ST )
+ {
+ /* initialize power management state */
+ p_cb->pm_state = BTA_OPC_PM_BUSY;
+ }
+
+#if BTA_OPC_DEBUG == TRUE
+ if (in_state != p_cb->state)
+ {
+ APPL_TRACE_DEBUG3("OPC State Change: [%s] -> [%s] after Event [%s]",
+ opc_state_code(in_state),
+ opc_state_code(p_cb->state),
+ opc_evt_code(p_msg->event));
+ }
+#endif
+
+ return (TRUE);
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_OPC_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function opc_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *opc_evt_code(tBTA_OPC_INT_EVT evt_code)
+{
+ switch(evt_code)
+ {
+ case BTA_OPC_API_ENABLE_EVT:
+ return "BTA_OPC_API_ENABLE_EVT";
+ case BTA_OPC_API_DISABLE_EVT:
+ return "BTA_OPC_API_DISABLE_EVT";
+ case BTA_OPC_API_CLOSE_EVT:
+ return "BTA_OPC_API_CLOSE_EVT";
+ case BTA_OPC_API_PUSH_EVT:
+ return "BTA_OPC_API_PUSH_EVT";
+ case BTA_OPC_API_PULL_EVT:
+ return "BTA_OPC_API_PULL_EVT";
+ case BTA_OPC_API_EXCH_EVT:
+ return "BTA_OPC_API_EXCH_EVT";
+ case BTA_OPC_SDP_OK_EVT:
+ return "BTA_OPC_SDP_OK_EVT";
+ case BTA_OPC_SDP_FAIL_EVT:
+ return "BTA_OPC_SDP_FAIL_EVT";
+ case BTA_OPC_CI_WRITE_EVT:
+ return "BTA_OPC_CI_WRITE_EVT";
+ case BTA_OPC_CI_READ_EVT:
+ return "BTA_OPC_CI_READ_EVT";
+ case BTA_OPC_CI_OPEN_EVT:
+ return "BTA_OPC_CI_OPEN_EVT";
+ case BTA_OPC_OBX_CONN_RSP_EVT:
+ return "BTA_OPC_OBX_CONN_RSP_EVT";
+ case BTA_OPC_OBX_PASSWORD_EVT:
+ return "BTA_OPC_OBX_PASSWORD_EVT";
+ case BTA_OPC_OBX_CLOSE_EVT:
+ return "BTA_OPC_OBX_CLOSE_EVT";
+ case BTA_OPC_OBX_PUT_RSP_EVT:
+ return "BTA_OPC_OBX_PUT_RSP_EVT";
+ case BTA_OPC_OBX_GET_RSP_EVT:
+ return "BTA_OPC_OBX_GET_RSP_EVT";
+ case BTA_OPC_OBX_CMPL_EVT:
+ return "BTA_OPC_OBX_CMPL_EVT";
+ case BTA_OPC_CLOSE_CMPL_EVT:
+ return "BTA_OPC_CLOSE_CMPL_EVT";
+ case BTA_OPC_DISABLE_CMPL_EVT:
+ return "BTA_OPC_DISABLE_CMPL_EVT";
+ default:
+ return "unknown OPC event code";
+ }
+}
+
+/*******************************************************************************
+**
+** Function opc_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *opc_state_code(tBTA_OPC_STATE state_code)
+{
+ switch(state_code)
+ {
+ case BTA_OPC_DISABLED_ST:
+ return "BTA_OPC_DISABLED_ST";
+ case BTA_OPC_IDLE_ST:
+ return "BTA_OPC_IDLE_ST";
+ case BTA_OPC_W4_CONN_ST:
+ return "BTA_OPC_W4_CONN_ST";
+ case BTA_OPC_CONN_ST:
+ return "BTA_OPC_CONN_ST";
+ case BTA_OPC_CLOSING_ST:
+ return "BTA_OPC_CLOSING_ST";
+ default:
+ return "unknown OPC state code";
+ }
+}
+
+#endif /* Debug Functions */
diff --git a/bta/op/bta_opc_utils.c b/bta/op/bta_opc_utils.c
new file mode 100644
index 0000000..82e626c
--- /dev/null
+++ b/bta/op/bta_opc_utils.c
@@ -0,0 +1,322 @@
+/*****************************************************************************
+**
+** Name: bta_opc_utils.c
+**
+** Description: This file implements object store functions for the
+** file transfer server.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "bta_opc_int.h"
+#include "bta_fs_api.h"
+#include "bta_fs_co.h"
+#include "gki.h"
+#include "utl.h"
+
+/*******************************************************************************
+** Constants
+*******************************************************************************/
+
+/*******************************************************************************
+** Local Function Prototypes
+*******************************************************************************/
+
+/*******************************************************************************
+* Macros for OPC
+*******************************************************************************/
+
+/*******************************************************************************
+* Exported Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function bta_opc_send_get_req
+**
+** Description Processes a Get File Operation.
+**
+** Parameters p_cb - Pointer to the OPC control block
+**
+** Returns (UINT8) OBX response code
+**
+*******************************************************************************/
+UINT8 bta_opc_send_get_req(tBTA_OPC_CB *p_cb)
+{
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 rsp_code = OBX_RSP_FAILED;
+
+ utl_freebuf((void**)&p_obx->p_pkt);
+ if ((p_obx->p_pkt = OBX_HdrInit(p_cb->obx_handle, p_cb->peer_mtu)) != NULL)
+ {
+ /* If first request add the Type Header to the request */
+ if (p_cb->first_get_pkt == TRUE)
+ {
+ p_cb->obx_oper = OPC_OP_PULL_OBJ;
+ p_cb->to_do &= ~BTA_OPC_PULL_MASK;
+ OBX_AddTypeHdr(p_obx->p_pkt, "text/x-vcard");
+ }
+
+ if ((OBX_GetReq(p_cb->obx_handle, TRUE, p_obx->p_pkt)) == OBX_SUCCESS)
+ {
+ rsp_code = OBX_RSP_OK;
+ p_obx->p_pkt = NULL;
+ p_cb->req_pending = TRUE;
+ }
+ }
+
+ return (rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_cont_get_rsp
+**
+** Description Continues an obex get response packet.
+** This function is called upon completion of a file open or
+** a file write event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_cont_get_rsp(tBTA_OPC_CB *p_cb)
+{
+ tBTA_OPC_OBX_EVT obx_evt;
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ UINT16 body_size;
+ BOOLEAN end;
+
+ /* Read the body header from the obx packet if it exists */
+ if (OBX_ReadBodyHdr(p_obx->p_pkt, &p_obx->p_start, &body_size, &end))
+ {
+ p_obx->final_pkt = end;
+ if (body_size)
+ {
+ /* Data to be written */
+ p_obx->offset = body_size; /* Save write size for comparison */
+ p_cb->cout_active = TRUE;
+ bta_fs_co_write(p_cb->fd, p_obx->p_start, body_size,
+ BTA_OPC_CI_WRITE_EVT, 0, p_cb->app_id);
+ return;
+ }
+ }
+
+ /* Empty Body; send next request or finished */
+ if (!p_obx->final_pkt)
+ {
+ bta_opc_send_get_req(p_cb);
+ }
+ else /* Done getting object */
+ {
+ memset(&obx_evt, 0, sizeof(tBTA_OPC_OBX_EVT));
+ obx_evt.rsp_code = OBX_RSP_OK;
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, (tBTA_OPC_DATA *) &obx_evt);
+ utl_freebuf((void**)&p_obx->p_pkt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_proc_get_rsp
+**
+** Description Processes an obex get response packet.
+** Initiates a file open if no errors.
+**
+**
+** Returns BOOLEAN - TRUE if obex packet is to be freed
+**
+*******************************************************************************/
+BOOLEAN bta_opc_proc_get_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ char *p_filename;
+
+ if (p_evt->rsp_code == OBX_RSP_OK || p_evt->rsp_code == OBX_RSP_CONTINUE)
+ {
+ /* The get the file name */
+ if (!OBX_ReadUtf8NameHdr(p_obx->p_pkt, (UINT8 *) p_cb->p_name,
+ p_bta_fs_cfg->max_file_len))
+ BCM_STRNCPY_S(p_cb->p_name, p_bta_fs_cfg->max_path_len+1, OPC_DEF_RCV_NAME, sizeof(OPC_DEF_RCV_NAME)+1);
+
+ /* If length header exists, save the file length */
+ if (!OBX_ReadLengthHdr(p_obx->p_pkt, &p_cb->obj_size))
+ p_cb->obj_size = BTA_FS_LEN_UNKNOWN;
+
+ /* Build the file name with a fully qualified path */
+ if ((p_filename = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ sprintf(p_filename, "%s%c%s", p_cb->p_rcv_path,
+ p_bta_fs_cfg->path_separator,
+ p_cb->p_name);
+
+ p_cb->cout_active = TRUE;
+ bta_fs_co_open(p_filename,
+ (BTA_FS_O_RDWR | BTA_FS_O_CREAT | BTA_FS_O_TRUNC),
+ p_cb->obj_size, BTA_OPC_CI_OPEN_EVT, p_cb->app_id);
+
+ GKI_freebuf(p_filename);
+ return FALSE; /* Do not free the obex packet until data is written */
+ }
+ else
+ p_evt->rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+
+ /* Server returned an error or out of memory to process request */
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, p_data);
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_send_put_req
+**
+** Description Initiates/Continues a Put Object Operation.
+** Builds a new OBX packet, and initiates a read operation.
+**
+** Parameters p_cb - pointer to the client's control block.
+** first_pkt - TRUE if initial PUT request to server.
+**
+**
+** Returns UINT8 OBX response code
+**
+*******************************************************************************/
+UINT8 bta_opc_send_put_req(tBTA_OPC_CB *p_cb, BOOLEAN first_pkt)
+{
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 rsp_code = OBX_RSP_FAILED;
+ char *p_ch;
+
+ utl_freebuf((void**)&p_obx->p_pkt);
+ if ((p_obx->p_pkt = OBX_HdrInit(p_cb->obx_handle, OBX_LRG_DATA_POOL_SIZE)) != NULL)
+ {
+ /* Add length header if it exists; No body in first packet */
+ if (first_pkt)
+ {
+ /* Add the Name Header to the request */
+ /* Find the beginning of the name (excluding the path) */
+ p_ch = strrchr(p_cb->p_name, (int) p_bta_fs_cfg->path_separator);
+ if (p_ch == NULL)
+ p_ch = p_cb->p_name;
+
+ if (p_ch && p_ch[1] != '\0')
+ {
+ OBX_AddUtf8NameHdr(p_obx->p_pkt, (UINT8 *) (&p_ch[1]));
+
+ /* Add the length header if known */
+ if (p_cb->obj_size != BTA_FS_LEN_UNKNOWN)
+ {
+ OBX_AddLengthHdr(p_obx->p_pkt, p_cb->obj_size);
+ }
+
+ /* Add the type header if known */
+ switch (p_cb->format)
+ {
+ case BTA_OP_VCARD30_FMT:
+ case BTA_OP_VCARD21_FMT:
+ OBX_AddTypeHdr(p_obx->p_pkt, "text/x-vcard");
+ break;
+ case BTA_OP_VCAL_FMT:
+ case BTA_OP_ICAL_FMT:
+ OBX_AddTypeHdr(p_obx->p_pkt, "text/x-vcalendar");
+ break;
+ case BTA_OP_VNOTE_FMT:
+ OBX_AddTypeHdr(p_obx->p_pkt, "text/x-vnote");
+ break;
+ case BTA_OP_VMSG_FMT:
+ OBX_AddTypeHdr(p_obx->p_pkt, "text/x-vmessage");
+ break;
+ }
+
+ OBX_PutReq(p_cb->obx_handle, FALSE, p_obx->p_pkt);
+ p_obx->p_pkt = NULL;
+ p_cb->req_pending = TRUE;
+ rsp_code = OBX_RSP_OK;
+ }
+ else
+ APPL_TRACE_ERROR1("Invalid file name [%s] feed, PutReq NOT sent.", p_cb->p_name);
+
+ }
+ else /* A continuation packet so read object data */
+ {
+ /* 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);
+
+ /* Read in the first packet's worth of data */
+ p_cb->cout_active = TRUE;
+ bta_fs_co_read(p_cb->fd, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left, BTA_OPC_CI_READ_EVT, 0, p_cb->app_id);
+ rsp_code = OBX_RSP_OK;
+ }
+ }
+
+ return (rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_start_push
+**
+** Description Push an object to connected server.
+** Opens the object to be transferred to the server.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_start_push(tBTA_OPC_CB *p_cb)
+{
+ p_cb->to_do &= ~BTA_OPC_PUSH_MASK;
+ p_cb->obx_oper = OPC_OP_PUSH_OBJ;
+ p_cb->cout_active = TRUE;
+
+ bta_fs_co_open(p_cb->p_name, BTA_FS_O_RDONLY, 0, BTA_OPC_CI_OPEN_EVT,
+ p_cb->app_id);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_convert_obx_to_opc_status
+**
+** Description Convert OBX response code into BTA OPC status code.
+**
+** Returns void
+**
+*******************************************************************************/
+tBTA_OPC_STATUS bta_opc_convert_obx_to_opc_status(tOBX_STATUS obx_status)
+{
+ tBTA_OPC_STATUS status;
+
+ switch (obx_status)
+ {
+ case OBX_RSP_OK:
+ case OBX_RSP_CONTINUE:
+ status = BTA_OPC_OK;
+ break;
+ case OBX_RSP_UNAUTHORIZED:
+ status = BTA_OPC_NO_PERMISSION;
+ break;
+ case OBX_RSP_NOT_FOUND:
+ status = BTA_OPC_NOT_FOUND;
+ break;
+ case OBX_RSP_SERVICE_UNAVL:
+ status = BTA_OPC_SRV_UNAVAIL;
+ break;
+ case OBX_RSP_FORBIDDEN:
+ status = BTA_OPC_RSP_FORBIDDEN;
+ break;
+ case OBX_RSP_NOT_ACCEPTABLE:
+ status = BTA_OPC_RSP_NOT_ACCEPTABLE;
+ break;
+ default:
+ status = BTA_OPC_FAIL;
+ }
+
+ return (status);
+}
diff --git a/bta/op/bta_ops_act.c b/bta/op/bta_ops_act.c
new file mode 100644
index 0000000..5409cf1
--- /dev/null
+++ b/bta/op/bta_ops_act.c
@@ -0,0 +1,793 @@
+/*****************************************************************************
+**
+** Name: bta_ops_act.c
+**
+** Description: This file contains the object transfer 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_OP_INCLUDED) && (BTA_OP_INCLUDED)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_op_api.h"
+#include "bta_ops_int.h"
+#include "bta_fs_api.h"
+#include "bta_fs_co.h"
+#include "bta_fs_ci.h"
+#include "rfcdefs.h" /* BT_PSM_RFCOMM */
+#include "btm_api.h"
+#include "utl.h"
+#include "goep_util.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#define BTA_OPS_NUM_FMTS 7
+#define BTA_OPS_PROTOCOL_COUNT 3
+
+/* object format lookup table */
+const tBTA_OP_FMT bta_ops_obj_fmt[] =
+{
+ BTA_OP_VCARD21_FMT,
+ BTA_OP_VCARD30_FMT,
+ BTA_OP_VCAL_FMT,
+ BTA_OP_ICAL_FMT,
+ BTA_OP_VNOTE_FMT,
+ BTA_OP_VMSG_FMT,
+ BTA_OP_OTHER_FMT
+};
+
+/*****************************************************************************
+** Local Function prototypes
+*****************************************************************************/
+#if BTA_OPS_DEBUG == TRUE
+static char *ops_obx_evt_code(tOBX_EVENT evt_code);
+#endif
+
+/*****************************************************************************
+** Action Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_ops_enable
+**
+** Description Perform necessary operations to enable object push.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_enable(tBTA_OPS_CB *p_cb, tBTA_OPS_API_ENABLE *p_data)
+{
+ tOBX_StartParams start_params;
+ UINT16 servclass = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
+ int i, j;
+ tBTA_UTL_COD cod;
+ tOBX_STATUS status;
+ UINT8 desc_type[BTA_OPS_NUM_FMTS];
+ UINT8 type_len[BTA_OPS_NUM_FMTS];
+ UINT8 *type_value[BTA_OPS_NUM_FMTS];
+ UINT16 mtu = OBX_MAX_MTU;
+ UINT8 temp[4], *p;
+ UINT16 version = GOEP_ENHANCED_VERSION;
+
+ /* allocate scn for opp */
+ p_cb->scn = BTM_AllocateSCN();
+ p_cb->app_id = p_data->app_id;
+
+ /* set security level */
+ BTM_SetSecurityLevel (FALSE, (char *) "", BTM_SEC_SERVICE_OBEX,
+ p_data->sec_mask, BT_PSM_RFCOMM,
+ BTM_SEC_PROTO_RFCOMM, p_cb->scn);
+
+ p_cb->psm = L2CA_AllocatePSM();
+ BTM_SetSecurityLevel (FALSE, (char *) "", BTM_SEC_SERVICE_OBEX,
+ p_data->sec_mask, p_cb->psm, 0, 0);
+
+ memset (&start_params, 0, sizeof(tOBX_StartParams));
+ start_params.p_target = NULL;
+ start_params.p_cback = &bta_ops_obx_cback;
+ start_params.mtu = mtu;
+ start_params.scn = p_cb->scn;
+ start_params.psm = p_cb->psm;
+ start_params.srm = p_cb->srm;
+ start_params.nonce = 0;
+ start_params.authenticate = FALSE;
+ start_params.auth_option = OBX_AO_NONE;
+ start_params.realm_charset = OBX_RCS_ASCII;
+ start_params.p_realm = NULL;
+ start_params.realm_len = 0;
+
+ if ((status = OBX_StartServer (&start_params, &p_cb->obx_handle)) == OBX_SUCCESS)
+ {
+ status = GOEP_Register (p_data->name, &p_cb->sdp_handle, p_cb->scn, 1, &servclass,
+ servclass, version);
+
+ /* add the psm */
+ p = temp;
+ UINT16_TO_BE_STREAM(p, p_cb->psm);
+ SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_OBX_OVR_L2CAP_PSM, UINT_DESC_TYPE,
+ (UINT32)2, (UINT8*)temp);
+
+ /* add sequence for supported types */
+ for (i = 0, j = 0; i < BTA_OPS_NUM_FMTS; i++)
+ {
+ if ((p_data->formats >> i) & 1)
+ {
+ type_value[j] = (UINT8 *) &bta_ops_obj_fmt[i];
+ desc_type[j] = UINT_DESC_TYPE;
+ type_len[j++] = 1;
+ }
+ }
+
+ SDP_AddSequence(p_cb->sdp_handle, (UINT16) ATTR_ID_SUPPORTED_FORMATS_LIST,
+ (UINT8) j, desc_type, type_len, type_value);
+
+ /* set class of device */
+ cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
+ utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
+
+ /* store formats value */
+ p_cb->formats = p_data->formats;
+ }
+ bta_sys_add_uuid(servclass); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */
+
+ p_cb->p_cback(BTA_OPS_ENABLE_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_api_disable
+**
+** Description Perform necessary operations to disable object push.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_api_disable(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ /* Free any outstanding headers and control block memory */
+ bta_ops_clean_getput(p_cb, TRUE);
+
+ /* Stop the OBEX server */
+ OBX_StopServer(p_cb->obx_handle);
+
+ /* Remove the OPP service from the SDP database */
+ SDP_DeleteRecord(p_cb->sdp_handle);
+ bta_sys_remove_uuid(UUID_SERVCLASS_OBEX_OBJECT_PUSH);
+
+ /* Free the allocated server channel number */
+ BTM_FreeSCN(p_cb->scn);
+ BTM_SecClrService(BTM_SEC_SERVICE_OBEX);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_api_accessrsp
+**
+** Description Process the access API event.
+** If permission had been granted, continue the push or pull
+** operation.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_api_accessrsp(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ UINT8 rsp_code;
+
+ /* Process the currently active access response */
+ switch (p_cb->acc_active)
+ {
+ case BTA_OP_OPER_PUSH:
+ if (p_data->api_access.oper == BTA_OP_OPER_PUSH)
+ {
+ if (p_data->api_access.flag == BTA_OP_ACCESS_ALLOW)
+ {
+ /* Save the file name with path prepended */
+ BCM_STRCPY_S(p_cb->p_path, p_bta_fs_cfg->max_path_len+1, p_data->api_access.p_name);
+
+ APPL_TRACE_DEBUG2("OPS PUSH OBJ: Name [%s], Length = 0x%0x (0 = n/a)",
+ p_cb->p_path, p_cb->file_length);
+
+ p_cb->cout_active = TRUE;
+ bta_fs_co_open (p_cb->p_path,
+ (BTA_FS_O_CREAT | BTA_FS_O_TRUNC | BTA_FS_O_RDWR),
+ p_cb->file_length, BTA_OPS_CI_OPEN_EVT,
+ p_cb->app_id);
+ }
+ else /* Access denied or Unsupported */
+ {
+ rsp_code = (p_data->api_access.flag == BTA_OP_ACCESS_NONSUP)
+ ? OBX_RSP_UNSUPTD_TYPE : OBX_RSP_UNAUTHORIZED;
+ bta_ops_clean_getput(p_cb, TRUE);
+ OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ }
+ p_cb->acc_active = 0;
+ }
+
+ break;
+
+ case BTA_OP_OPER_PULL:
+ if (p_data->api_access.oper == BTA_OP_OPER_PULL)
+ {
+ if (p_data->api_access.flag == BTA_OP_ACCESS_ALLOW)
+ {
+ /* Save the file name with path prepended */
+ BCM_STRCPY_S(p_cb->p_path, p_bta_fs_cfg->max_path_len+1, p_data->api_access.p_name);
+
+ APPL_TRACE_DEBUG1("OPS PULL VCARD: Name [%s]", p_cb->p_path);
+
+ p_cb->cout_active = TRUE;
+ bta_fs_co_open (p_cb->p_path, BTA_FS_O_RDONLY, 0,
+ BTA_OPS_CI_OPEN_EVT, p_cb->app_id);
+ }
+ else /* Denied */
+ bta_ops_get_obj_rsp(OBX_RSP_UNAUTHORIZED, 0);
+
+ p_cb->acc_active = 0;
+ }
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("OPS ACCRSP: Unknown tBTA_OP_OPER value (%d)",
+ p_cb->acc_active);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_api_close
+**
+** Description Handle an api close event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_api_close(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ /* resources will be freed at BTA_OPS_OBX_CLOSE_EVT */
+ OBX_DisconnectRsp(p_cb->obx_handle, OBX_RSP_SERVICE_UNAVL, NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_ci_write
+**
+** Description Continue with the current write operation
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_ci_write(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ UINT8 rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ p_cb->cout_active = FALSE;
+
+ if (!p_cb->aborting)
+ {
+ /* Process write call-in event if operation is still active */
+ if (p_cb->obx_oper == OPS_OP_PUSH_OBJ)
+ {
+ if (p_data->write_evt.status == BTA_FS_CO_OK)
+ rsp_code = OBX_RSP_OK;
+ else
+ {
+ if (p_data->write_evt.status == BTA_FS_CO_ENOSPACE)
+ rsp_code = OBX_RSP_DATABASE_FULL;
+ bta_ops_clean_getput(p_cb, TRUE);
+ }
+
+ /* Process response to OBX client */
+ bta_ops_put_obj_rsp(rsp_code);
+ }
+ }
+ else /* Finish aborting */
+ {
+ bta_ops_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_OK, (BT_HDR *)NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_ci_read
+**
+** Description Handles the response to a read call-out request.
+** This is called within the OBX get file request. If the
+** operation has completed, the OBX response is sent out;
+** otherwise a read for additional data is made.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_ci_read(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_FS_CI_READ_EVT *p_revt = &p_data->read_evt;
+ UINT8 rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ p_cb->cout_active = FALSE;
+
+ if (!p_cb->aborting)
+ {
+ /* Process read call-in event if operation is still active */
+ if (p_cb->obx_oper == OPS_OP_PULL_OBJ && p_revt->fd == p_cb->fd)
+ {
+ /* Read was successful, not finished yet */
+ if (p_revt->status == BTA_FS_CO_OK)
+ rsp_code = OBX_RSP_CONTINUE;
+
+ /* Read was successful, end of file has been detected */
+ else if (p_revt->status == BTA_FS_CO_EOF)
+ rsp_code = OBX_RSP_OK;
+
+ /* Process response to OBX client */
+ bta_ops_get_obj_rsp(rsp_code, p_revt->num_read);
+ }
+ }
+ else /* Finish aborting */
+ {
+ bta_ops_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_OK, (BT_HDR *)NULL);
+ APPL_TRACE_ERROR0("OPS PUSH OBJ: Finished ABORTING!!!");
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_ci_open
+**
+** Description Continue with the current file open operation
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_ci_open(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FS_CI_OPEN_EVT *p_open = &p_data->open_evt;
+ UINT8 rsp_code = OBX_RSP_OK;
+ UINT8 num_hdrs;
+ BOOLEAN endpkt;
+ char *p_name;
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->aborting)
+ {
+ bta_ops_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_OK, (BT_HDR *)NULL);
+ return;
+ }
+
+ /* Only process file get or put operations */
+ if (p_cb->obx_oper == OPS_OP_PULL_OBJ)
+ {
+ /* if file is accessible read/write the first buffer of data */
+ if (p_open->status == BTA_FS_CO_OK)
+ {
+ p_cb->fd = p_open->fd;
+ p_cb->file_length = p_open->file_size;
+
+ /* Add the name and length headers */
+ p_name = strrchr(p_cb->p_path, (int)p_bta_fs_cfg->path_separator);
+ if (p_name == NULL)
+ p_name = p_cb->p_path;
+ else
+ p_name++; /* increment past the file separator */
+
+ OBX_AddUtf8NameHdr(p_obx->p_pkt, (UINT8 *)p_name);
+
+ if (p_cb->file_length != BTA_FS_LEN_UNKNOWN)
+ {
+ OBX_AddLengthHdr(p_obx->p_pkt, p_cb->file_length);
+ if (p_cb->file_length > 0)
+ {
+ rsp_code = OBX_RSP_CONTINUE;
+ }
+ }
+
+ /* Send continuation response with the length of the file and no body */
+ 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
+ {
+ if (p_open->status == BTA_FS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ else /* File could not be found */
+ rsp_code = OBX_RSP_NOT_FOUND;
+
+ /* Send OBX response if an error occurred */
+ bta_ops_get_obj_rsp(rsp_code, 0);
+ }
+ }
+ else if (p_cb->obx_oper == OPS_OP_PUSH_OBJ)
+ {
+ /* if file is accessible read/write the first buffer of data */
+ if (p_open->status == BTA_FS_CO_OK)
+ {
+ p_cb->fd = p_open->fd;
+
+ /* Read in start of body if there is a body header */
+ num_hdrs = OBX_ReadBodyHdr(p_obx->p_pkt, &p_obx->p_start,
+ &p_obx->bytes_left, &endpkt);
+ if (num_hdrs == 1)
+ {
+ rsp_code = OBX_RSP_PART_CONTENT; /* Do not send OBX response yet */
+
+ /* Initiate the writing out of the data */
+ p_cb->cout_active = TRUE;
+ bta_fs_co_write(p_cb->fd, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left, BTA_OPS_CI_WRITE_EVT,
+ 0, p_cb->app_id);
+ }
+ else if (num_hdrs > 1) /* Too many body headers to handle */
+ {
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ bta_ops_clean_getput(p_cb, TRUE);
+ }
+ else /* No body: respond with an OK so client can start sending the data */
+ p_obx->bytes_left = 0;
+ }
+ else
+ {
+ if (p_open->status == BTA_FS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ else if (p_open->status == BTA_FS_CO_ENOSPACE)
+ rsp_code = OBX_RSP_DATABASE_FULL;
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+
+ /* Send OBX response now if an error occurred or no body */
+ if (rsp_code != OBX_RSP_PART_CONTENT)
+ bta_ops_put_obj_rsp(rsp_code);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_obx_connect
+**
+** Description Process the OBX connect event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_connect(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_OBX_EVENT *p_evt = &p_data->obx_evt;
+
+ p_cb->peer_mtu = p_evt->param.conn.mtu;
+ memcpy(p_cb->bd_addr, p_evt->param.conn.peer_addr, BD_ADDR_LEN);
+ APPL_TRACE_EVENT1("OPS Connect: peer mtu 0x%04x", p_cb->peer_mtu);
+
+ /* done with obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ OBX_ConnectRsp(p_evt->handle, OBX_RSP_OK, (BT_HDR *)NULL);
+
+ /* inform role manager */
+ bta_sys_conn_open( BTA_ID_OPS ,p_cb->app_id, bta_ops_cb.bd_addr);
+
+ /* Notify the MMI that a connection has been opened */
+ p_cb->p_cback(BTA_OPS_OPEN_EVT, (tBTA_OPS*)bta_ops_cb.bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_obx_disc
+**
+** Description Process the OBX disconnect event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_disc(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code;
+
+ rsp_code = (p_evt->obx_event == OBX_DISCONNECT_REQ_EVT) ? OBX_RSP_OK
+ : OBX_RSP_BAD_REQUEST;
+
+ /* Action operation is not supported in OPP, send reject rsp and free data */
+ if(p_evt->obx_event == OBX_ACTION_REQ_EVT)
+ {
+ OBX_ActionRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ }
+
+ OBX_DisconnectRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_obx_close
+**
+** Description Process the OBX link lost event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_close(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ /* finished if not waiting on a call-in function */
+ if (!p_cb->cout_active)
+ bta_ops_sm_execute(p_cb, BTA_OPS_CLOSE_CMPL_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_obx_abort
+**
+** Description Process the OBX abort event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_abort(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_OK;
+
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ if (!p_cb->cout_active)
+ {
+ bta_ops_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ }
+ else /* Delay the response if a call-out function is active */
+ p_cb->aborting = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_obx_put
+**
+** Description Process the OBX push object put event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_put(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_CONTINUE;
+
+ p_cb->obx.final_pkt = p_evt->param.put.final;
+
+ /* If currently processing a push, use the current name */
+ if (bta_ops_cb.obx_oper == OPS_OP_PUSH_OBJ)
+ {
+ bta_ops_proc_put_obj(p_evt->p_pkt);
+ }
+
+ /* This is a new request; allocate enough memory to hold the path (including file name) */
+ else if ((p_cb->p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len
+ + p_bta_fs_cfg->max_file_len + 2))) != NULL)
+ {
+ p_cb->p_name = (p_cb->p_path + p_bta_fs_cfg->max_path_len + 1);
+ p_cb->p_name[p_bta_fs_cfg->max_file_len] = '\0';
+ p_cb->p_path[p_bta_fs_cfg->max_path_len] = '\0';
+
+ /* read the name header if it exists */
+ if (OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->p_name, p_bta_fs_cfg->max_file_len))
+ {
+ /* get file type from file name; check if supported */
+ if ((p_cb->obj_fmt = bta_ops_fmt_supported(p_cb->p_name,
+ p_cb->formats)) != 0)
+ {
+ if(!(OBX_ReadLengthHdr(p_evt->p_pkt, &p_cb->file_length)))
+ p_cb->file_length = BTA_FS_LEN_UNKNOWN;
+
+ p_cb->obx.p_pkt = p_evt->p_pkt; /* save the packet for later use */
+ p_cb->obx.offset = 0; /* Initial offset into OBX data */
+ p_cb->obx_oper = OPS_OP_PUSH_OBJ;
+
+ /* request access from the app */
+ bta_ops_req_app_access (BTA_OP_OPER_PUSH, p_cb);
+ }
+ else
+ rsp_code = OBX_RSP_UNSUPTD_TYPE;
+ }
+ else
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ /* Error has been detected; respond with error code */
+ if (rsp_code != OBX_RSP_CONTINUE)
+ {
+ utl_freebuf((void**)&p_evt->p_pkt); /* done with obex packet */
+ utl_freebuf((void**)&p_cb->p_path);
+ p_cb->p_name = NULL;
+ OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_obx_get
+**
+** Description Process the OBX pull vCard object.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_get(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ /* this is a new request; validate it */
+ if (bta_ops_cb.obx_oper != OPS_OP_PULL_OBJ)
+ bta_ops_init_get_obj(p_cb, p_data);
+ else /* this is a continuation request */
+ bta_ops_proc_get_obj(p_cb);
+
+ /* done with Obex packet */
+ utl_freebuf((void**)&p_data->obx_evt.p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_close_complete
+**
+** Description Finishes the memory cleanup after a channel is closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_close_complete(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+
+ /* inform role manager */
+ bta_sys_conn_close( BTA_ID_OPS ,p_cb->app_id, bta_ops_cb.bd_addr);
+
+ p_cb->cout_active = FALSE;
+
+ bta_ops_clean_getput(p_cb, TRUE);
+
+ /* Notify the MMI that a connection has been closed */
+ p_cb->p_cback(BTA_OPS_CLOSE_EVT, (tBTA_OPS*)p_cb->bd_addr);
+ memset(p_cb->bd_addr, 0, BD_ADDR_LEN);
+
+ if (p_data->obx_evt.p_pkt)
+ APPL_TRACE_WARNING0("OPS: OBX CLOSE CALLED WITH non-NULL Packet!!!");
+}
+
+/*****************************************************************************
+** Callback Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_ops_obx_cback
+**
+** Description OBX callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt)
+{
+ tBTA_OPS_OBX_EVENT *p_obx_msg;
+ UINT16 event = 0;
+
+#if BTA_OPS_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("OBX Event Callback: ops_obx_event[%s]", ops_obx_evt_code(obx_event));
+#endif
+
+ switch(obx_event)
+ {
+ case OBX_CONNECT_REQ_EVT:
+ event = BTA_OPS_OBX_CONN_EVT;
+ break;
+ case OBX_DISCONNECT_REQ_EVT:
+ event = BTA_OPS_OBX_DISC_EVT;
+ break;
+ case OBX_PUT_REQ_EVT:
+ event = BTA_OPS_OBX_PUT_EVT;
+ break;
+ case OBX_GET_REQ_EVT:
+ event = BTA_OPS_OBX_GET_EVT;
+ break;
+ case OBX_ABORT_REQ_EVT:
+ event = BTA_OPS_OBX_ABORT_EVT;
+ break;
+ case OBX_CLOSE_IND_EVT:
+ event = BTA_OPS_OBX_CLOSE_EVT;
+ break;
+ case OBX_TIMEOUT_EVT:
+ break;
+ default:
+ /* Unrecognized packet; disconnect the session */
+ if (p_pkt)
+ event = BTA_OPS_OBX_DISC_EVT;
+ }
+
+ /* send event to BTA, if any */
+ if (event && (p_obx_msg =
+ (tBTA_OPS_OBX_EVENT *) GKI_getbuf(sizeof(tBTA_OPS_OBX_EVENT))) != NULL)
+ {
+ p_obx_msg->hdr.event = event;
+ p_obx_msg->obx_event = obx_event;
+ p_obx_msg->handle = handle;
+ p_obx_msg->param = param;
+ p_obx_msg->p_pkt = p_pkt;
+
+ bta_sys_sendmsg(p_obx_msg);
+ }
+}
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_OPS_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function ops_obx_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *ops_obx_evt_code(tOBX_EVENT evt_code)
+{
+ switch(evt_code)
+ {
+ case OBX_CONNECT_REQ_EVT:
+ return "OBX_CONNECT_REQ_EVT";
+ case OBX_DISCONNECT_REQ_EVT:
+ return "OBX_DISCONNECT_REQ_EVT";
+ case OBX_PUT_REQ_EVT:
+ return "OBX_PUT_REQ_EVT";
+ case OBX_GET_REQ_EVT:
+ return "OBX_GET_REQ_EVT";
+ case OBX_SETPATH_REQ_EVT:
+ return "OBX_SETPATH_REQ_EVT";
+ case OBX_ABORT_REQ_EVT:
+ return "OBX_ABORT_REQ_EVT";
+ case OBX_CLOSE_IND_EVT:
+ return "OBX_CLOSE_IND_EVT";
+ case OBX_TIMEOUT_EVT:
+ return "OBX_TIMEOUT_EVT";
+ case OBX_PASSWORD_EVT:
+ return "OBX_PASSWORD_EVT";
+ case OBX_SESSION_REQ_EVT:
+ return "OBX_SESSION_REQ_EVT";
+ case OBX_ACTION_REQ_EVT:
+ return "OBX_ACTION_REQ_EVT";
+ default:
+ return "unknown OBX event code";
+ }
+}
+#endif /* Debug Functions */
+#endif /* BTA_OP_INCLUDED */
diff --git a/bta/op/bta_ops_api.c b/bta/op/bta_ops_api.c
new file mode 100644
index 0000000..1c09094
--- /dev/null
+++ b/bta/op/bta_ops_api.c
@@ -0,0 +1,153 @@
+/*****************************************************************************
+**
+** Name: bta_ops_api.c
+**
+** Description: This is the implementation of the API for the object
+** push server subsystem of BTA, Widcomm's Bluetooth
+** application layer for mobile phones.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_OP_INCLUDED) && (BTA_OP_INCLUDED)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_fs_api.h"
+#include "bta_op_api.h"
+#include "bta_ops_int.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_ops_reg =
+{
+ bta_ops_hdl_event,
+ BTA_OpsDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_OpsEnable
+**
+** Description Enable the object push server. This function must be
+** called before any other functions in the OPS API are called.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpsEnable(tBTA_SEC sec_mask, tBTA_OP_FMT_MASK formats,
+ char *p_service_name, tBTA_OPS_CBACK *p_cback, BOOLEAN srm, UINT8 app_id)
+{
+ tBTA_OPS_API_ENABLE *p_buf;
+
+ GKI_sched_lock();
+ /* register with BTA system manager */
+ bta_sys_register(BTA_ID_OPS, &bta_ops_reg);
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_OPS_API_ENABLE *) GKI_getbuf(sizeof(tBTA_OPS_API_ENABLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_OPS_API_ENABLE_EVT;
+ BCM_STRNCPY_S(p_buf->name, sizeof(p_buf->name), p_service_name, BTA_SERVICE_NAME_LEN);
+ p_buf->name[BTA_SERVICE_NAME_LEN] = '\0';
+ p_buf->p_cback = p_cback;
+ p_buf->app_id = app_id;
+ p_buf->formats = formats;
+ p_buf->sec_mask = sec_mask;
+ p_buf->srm = srm;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpsDisable
+**
+** Description Disable the object push server. If the server is currently
+** connected to a peer device the connection will be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpsDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_OPS);
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_OPS_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpsClose
+**
+** Description Close the current connection. This function is called if
+** the phone wishes to close the connection before the object
+** push is completed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpsClose(void)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_OPS_API_CLOSE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpsAccessRsp
+**
+** Description Sends a reply to an access request event (BTA_OPS_ACCESS_EVT).
+** This call MUST be made whenever the event occurs.
+**
+** Parameters oper - operation being accessed.
+** access - BTA_OP_ACCESS_ALLOW, BTA_OP_ACCESS_FORBID, or
+** BTA_OP_ACCESS_NONSUP.
+** p_name - Full path of file to read from (pull) or write to
+** (push).
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpsAccessRsp(tBTA_OP_OPER oper, tBTA_OP_ACCESS access, char *p_name)
+{
+ tBTA_OPS_API_ACCESSRSP *p_buf;
+
+ if ((p_buf = (tBTA_OPS_API_ACCESSRSP *)GKI_getbuf((UINT16)(sizeof(tBTA_OPS_API_ACCESSRSP)
+ + p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ p_buf->flag = access;
+ p_buf->oper = oper;
+ p_buf->p_name = (char *)(p_buf + 1);
+ if (p_name)
+ {
+ BCM_STRNCPY_S(p_buf->p_name, p_bta_fs_cfg->max_path_len+1, p_name, p_bta_fs_cfg->max_path_len);
+ p_buf->p_name[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+ else
+ *p_buf->p_name = '\0';
+
+ p_buf->hdr.event = BTA_OPS_API_ACCESSRSP_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+#endif /* BTA_OP_INCLUDED */
diff --git a/bta/op/bta_ops_int.h b/bta/op/bta_ops_int.h
new file mode 100644
index 0000000..733b9ae
--- /dev/null
+++ b/bta/op/bta_ops_int.h
@@ -0,0 +1,198 @@
+/*****************************************************************************
+**
+** Name: bta_ops_int.h
+**
+** Description: This is the private file for the object transfer
+** server (OPS).
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_OPS_INT_H
+#define BTA_OPS_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_op_api.h"
+#include "bta_fs_co.h"
+#include "bta_fs_ci.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+
+/* OPS active obex operation (Valid in connected state) */
+#define OPS_OP_NONE 0
+#define OPS_OP_PULL_OBJ 1
+#define OPS_OP_PUSH_OBJ 2
+
+/* state machine events */
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_OPS_API_DISABLE_EVT = BTA_SYS_EVT_START(BTA_ID_OPS),
+
+ BTA_OPS_API_ACCESSRSP_EVT, /* Response to an access request */
+ BTA_OPS_API_CLOSE_EVT, /* Close API */
+ BTA_OPS_CI_OPEN_EVT, /* Response to File Open request */
+ BTA_OPS_CI_WRITE_EVT, /* Response to Write request */
+ BTA_OPS_CI_READ_EVT, /* Response to Read request */
+ BTA_OPS_OBX_CONN_EVT, /* OBX Channel Connect Request */
+ BTA_OPS_OBX_DISC_EVT, /* OBX Channel Disconnect */
+ BTA_OPS_OBX_ABORT_EVT, /* OBX_operation aborted */
+ BTA_OPS_OBX_CLOSE_EVT, /* OBX Channel Disconnected (Link Lost) */
+ BTA_OPS_OBX_PUT_EVT, /* Write file data or delete */
+ BTA_OPS_OBX_GET_EVT, /* Read file data or folder listing */
+ BTA_OPS_CLOSE_CMPL_EVT, /* Finished closing channel */
+
+ /* these events are handled outside the state machine */
+ BTA_OPS_API_ENABLE_EVT
+};
+
+typedef UINT16 tBTA_OPS_INT_EVT;
+
+typedef UINT8 tBTA_OPS_STATE;
+
+/* data type for BTA_OPS_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char name[BTA_SERVICE_NAME_LEN + 1];
+ tBTA_OPS_CBACK *p_cback;
+ tBTA_OP_FMT_MASK formats;
+ UINT8 sec_mask;
+ BOOLEAN srm;
+ UINT8 app_id;
+} tBTA_OPS_API_ENABLE;
+
+/* data type for BTA_OPS_API_ACCESSRSP_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char *p_name;
+ tBTA_OP_OPER oper;
+ tBTA_OP_ACCESS flag;
+} tBTA_OPS_API_ACCESSRSP;
+
+/* data type for all obex events
+ hdr.event contains the OPS 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_OPS_OBX_EVENT;
+
+/* union of all event data types */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_OPS_API_ENABLE api_enable;
+ tBTA_OPS_API_ACCESSRSP api_access;
+ tBTA_OPS_OBX_EVENT obx_evt;
+ tBTA_FS_CI_OPEN_EVT open_evt;
+ tBTA_FS_CI_READ_EVT read_evt;
+ tBTA_FS_CI_WRITE_EVT write_evt;
+} tBTA_OPS_DATA;
+
+/* OBX Response Packet Structure - Holds current response packet info */
+typedef struct
+{
+ BT_HDR *p_pkt; /* (Pull/Push) Holds the current OBX hdr for Push or Pull */
+ UINT8 *p_start; /* (Pull/Push) Start of the Body of the packet */
+ UINT16 offset; /* (Pull/Push) Contains the current offset into the Body (p_start) */
+ UINT16 bytes_left; /* (Pull/Push) Holds bytes available left in Obx packet */
+ BOOLEAN final_pkt; /* (Push) Holds the final bit of the Push packet */
+} tBTA_OPS_OBX_PKT;
+
+/* Power management state for OPS */
+#define BTA_OPS_PM_BUSY 0
+#define BTA_OPS_PM_IDLE 1
+
+/* OPS control block */
+typedef struct
+{
+ tBTA_OPS_CBACK *p_cback; /* pointer to application callback function */
+ char *p_name; /* Holds name of current operation */
+ char *p_path; /* Holds path of current operation */
+ tBTA_OPS_OBX_PKT obx; /* Holds the current OBX packet information */
+ UINT32 sdp_handle; /* SDP record handle */
+ UINT32 file_length; /* length of file being Push/Pull */
+ int fd; /* File Descriptor of opened file */
+ BD_ADDR bd_addr; /* Device currently connected to */
+ tOBX_HANDLE obx_handle;
+ UINT16 peer_mtu;
+ UINT16 psm; /* PSM for Obex Over L2CAP */
+ BOOLEAN srm; /* TRUE, to use SIngle Response Mode */
+ UINT8 scn; /* SCN of the OPP server */
+ tBTA_OP_FMT_MASK formats; /* supported object formats */
+ tBTA_OPS_STATE state; /* state machine state */
+ tBTA_OP_FMT obj_fmt; /* file format of received object */
+ UINT8 obx_oper; /* current active OBX operation PUSH OBJ, or PULL OBJ */
+ UINT8 app_id;
+ tBTA_OP_OPER acc_active; /* op code when waiting for an access rsp (API) (0 not active) */
+ BOOLEAN cout_active; /* TRUE when waiting for a call-in function */
+ BOOLEAN aborting; /* TRUE when waiting for a call-in function */
+ UINT8 pm_state;
+} tBTA_OPS_CB;
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* OPS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_OPS_CB bta_ops_cb;
+#else
+extern tBTA_OPS_CB *bta_ops_cb_ptr;
+#define bta_ops_cb (*bta_ops_cb_ptr)
+#endif
+
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+extern BOOLEAN bta_ops_hdl_event(BT_HDR *p_msg);
+extern void bta_ops_sm_execute(tBTA_OPS_CB *p_cb, UINT16 event, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_cback (tOBX_HANDLE handle, tOBX_EVENT event,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt);
+
+/* action functions */
+extern void bta_ops_api_disable(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_api_accessrsp(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_api_close(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_ci_write(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_ci_read(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_ci_open(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_connect(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_disc(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_close(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_abort(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_put(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_get(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_gasp_err_rsp(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_close_complete(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+
+/* object store */
+extern void bta_ops_init_get_obj(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_proc_get_obj(tBTA_OPS_CB *p_cb);
+extern void bta_ops_proc_put_obj(BT_HDR *p_pkt);
+
+/* miscellaneous functions */
+extern void bta_ops_enable(tBTA_OPS_CB *p_cb, tBTA_OPS_API_ENABLE *p_data);
+extern void bta_ops_get_obj_rsp(UINT8 rsp_code, UINT16 num_read);
+extern void bta_ops_put_obj_rsp(UINT8 rsp_code);
+extern void bta_ops_clean_getput(tBTA_OPS_CB *p_cb, BOOLEAN is_aborted);
+extern void bta_ops_discard_data(UINT16 event, tBTA_OPS_DATA *p_data);
+extern void bta_ops_req_app_access (tBTA_OP_OPER oper, tBTA_OPS_CB *p_cb);
+extern tBTA_OP_FMT bta_ops_fmt_supported(char *p, tBTA_OP_FMT_MASK fmt_mask);
+
+#endif /* BTA_OPS_INT_H */
diff --git a/bta/op/bta_ops_main.c b/bta/op/bta_ops_main.c
new file mode 100644
index 0000000..f98b43b
--- /dev/null
+++ b/bta/op/bta_ops_main.c
@@ -0,0 +1,412 @@
+/*****************************************************************************
+**
+** Name: bta_ops_main.c
+**
+** Description: This file contains the file transfer server main functions
+** and state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_OP_INCLUDED) && (BTA_OP_INCLUDED)
+
+#include <string.h>
+
+#include "bta_fs_api.h"
+#include "bta_ops_int.h"
+#include "gki.h"
+#include "obx_api.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* state machine states */
+enum
+{
+ BTA_OPS_IDLE_ST = 0, /* Idle */
+ BTA_OPS_LISTEN_ST, /* Listen - waiting for OBX/RFC connection */
+ BTA_OPS_CONN_ST, /* Connected - OPP Session is active */
+ BTA_OPS_CLOSING_ST /* Closing is in progress */
+};
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_OPS_API_DISABLE,
+ BTA_OPS_API_ACCESSRSP,
+ BTA_OPS_API_CLOSE,
+ BTA_OPS_CI_WRITE,
+ BTA_OPS_CI_READ,
+ BTA_OPS_CI_OPEN,
+ BTA_OPS_OBX_CONNECT,
+ BTA_OPS_OBX_DISC,
+ BTA_OPS_OBX_CLOSE,
+ BTA_OPS_OBX_ABORT,
+ BTA_OPS_OBX_PUT,
+ BTA_OPS_OBX_GET,
+ BTA_OPS_CLOSE_COMPLETE,
+ BTA_OPS_IGNORE
+};
+
+/* type for action functions */
+typedef void (*tBTA_OPS_ACTION)(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+
+/* action function list */
+const tBTA_OPS_ACTION bta_ops_action[] =
+{
+ bta_ops_api_disable,
+ bta_ops_api_accessrsp,
+ bta_ops_api_close,
+ bta_ops_ci_write,
+ bta_ops_ci_read,
+ bta_ops_ci_open,
+ bta_ops_obx_connect,
+ bta_ops_obx_disc,
+ bta_ops_obx_close,
+ bta_ops_obx_abort,
+ bta_ops_obx_put,
+ bta_ops_obx_get,
+ bta_ops_close_complete
+};
+
+
+/* state table information */
+#define BTA_OPS_ACTIONS 1 /* number of actions */
+#define BTA_OPS_NEXT_STATE 1 /* position of next state */
+#define BTA_OPS_NUM_COLS 2 /* number of columns in state tables */
+
+/* state table for idle state */
+static const UINT8 bta_ops_st_idle[][BTA_OPS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_OPS_API_DISABLE_EVT */ {BTA_OPS_IGNORE, BTA_OPS_IDLE_ST},
+/* BTA_OPS_API_ACCESSRSP_EVT */ {BTA_OPS_IGNORE, BTA_OPS_IDLE_ST},
+/* BTA_OPS_API_CLOSE_EVT */ {BTA_OPS_IGNORE, BTA_OPS_IDLE_ST},
+};
+
+/* state table for obex/rfcomm connection state */
+static const UINT8 bta_ops_st_listen[][BTA_OPS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_OPS_API_DISABLE_EVT */ {BTA_OPS_API_DISABLE, BTA_OPS_IDLE_ST},
+/* BTA_OPS_API_ACCESSRSP_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_API_CLOSE_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_CI_OPEN_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_CI_WRITE_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_CI_READ_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_OBX_CONN_EVT */ {BTA_OPS_OBX_CONNECT, BTA_OPS_CONN_ST},
+/* BTA_OPS_OBX_DISC_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_OBX_ABORT_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_OBX_CLOSE_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_OBX_PUT_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_OBX_GET_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_CLOSE_CMPL_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_ops_st_connected[][BTA_OPS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_OPS_API_DISABLE_EVT */ {BTA_OPS_API_DISABLE, BTA_OPS_IDLE_ST},
+/* BTA_OPS_API_ACCESSRSP_EVT */ {BTA_OPS_API_ACCESSRSP, BTA_OPS_CONN_ST},
+/* BTA_OPS_API_CLOSE_EVT */ {BTA_OPS_API_CLOSE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_CI_OPEN_EVT */ {BTA_OPS_CI_OPEN, BTA_OPS_CONN_ST},
+/* BTA_OPS_CI_WRITE_EVT */ {BTA_OPS_CI_WRITE, BTA_OPS_CONN_ST},
+/* BTA_OPS_CI_READ_EVT */ {BTA_OPS_CI_READ, BTA_OPS_CONN_ST},
+/* BTA_OPS_OBX_CONN_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CONN_ST},
+/* BTA_OPS_OBX_DISC_EVT */ {BTA_OPS_OBX_DISC, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_ABORT_EVT */ {BTA_OPS_OBX_ABORT, BTA_OPS_CONN_ST},
+/* BTA_OPS_OBX_CLOSE_EVT */ {BTA_OPS_OBX_CLOSE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_PUT_EVT */ {BTA_OPS_OBX_PUT, BTA_OPS_CONN_ST},
+/* BTA_OPS_OBX_GET_EVT */ {BTA_OPS_OBX_GET, BTA_OPS_CONN_ST},
+/* BTA_OPS_CLOSE_CMPL_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CONN_ST}
+};
+
+/* state table for closing state */
+static const UINT8 bta_ops_st_closing[][BTA_OPS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_OPS_API_DISABLE_EVT */ {BTA_OPS_API_DISABLE, BTA_OPS_IDLE_ST},
+/* BTA_OPS_API_ACCESSRSP_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_API_CLOSE_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_CI_OPEN_EVT */ {BTA_OPS_CLOSE_COMPLETE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_CI_WRITE_EVT */ {BTA_OPS_CLOSE_COMPLETE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_CI_READ_EVT */ {BTA_OPS_CLOSE_COMPLETE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_OBX_CONN_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_DISC_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_ABORT_EVT */ {BTA_OPS_OBX_ABORT, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_CLOSE_EVT */ {BTA_OPS_OBX_CLOSE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_PUT_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_GET_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_CLOSE_CMPL_EVT */ {BTA_OPS_CLOSE_COMPLETE, BTA_OPS_LISTEN_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_OPS_ST_TBL)[BTA_OPS_NUM_COLS];
+
+/* state table */
+const tBTA_OPS_ST_TBL bta_ops_st_tbl[] =
+{
+ bta_ops_st_idle,
+ bta_ops_st_listen,
+ bta_ops_st_connected,
+ bta_ops_st_closing
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* OPS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_OPS_CB bta_ops_cb;
+#endif
+
+#if BTA_OPS_DEBUG == TRUE
+static char *ops_evt_code(tBTA_OPS_INT_EVT evt_code);
+static char *ops_state_code(tBTA_OPS_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function bta_ops_sm_execute
+**
+** Description State machine event handling function for OPS
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_sm_execute(tBTA_OPS_CB *p_cb, UINT16 event, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_ST_TBL state_table;
+ UINT8 action;
+ int i;
+#if BTA_OPS_DEBUG == TRUE
+ tBTA_OPS_STATE in_state = bta_ops_cb.state;
+ UINT16 in_event = event;
+ APPL_TRACE_EVENT3("OPS Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ ops_state_code(in_state),
+ ops_evt_code(event));
+#endif
+
+ /* look up the state table for the current state */
+ state_table = bta_ops_st_tbl[p_cb->state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_cb->state = state_table[event][BTA_OPS_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_OPS_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_OPS_IGNORE)
+ {
+ (*bta_ops_action[action])(p_cb, p_data);
+ }
+ else
+ {
+ /* discard ops data */
+ bta_ops_discard_data(p_data->hdr.event, p_data);
+ break;
+ }
+ }
+
+#if BTA_OPS_DEBUG == TRUE
+ if (in_state != bta_ops_cb.state)
+ {
+ APPL_TRACE_DEBUG3("OPS State Change: [%s] -> [%s] after Event [%s]",
+ ops_state_code(in_state),
+ ops_state_code(bta_ops_cb.state),
+ ops_evt_code(in_event));
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_api_enable
+**
+** Description Handle an api enable event. This function enables the OP
+** Server by opening an Obex/Rfcomm channel and placing it into
+** listen mode.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ops_api_enable(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_API_ENABLE *p_enable = &p_data->api_enable;
+
+ /* initialize control block */
+ memset(p_cb, 0, sizeof(tBTA_OPS_CB));
+ p_cb->p_cback = p_enable->p_cback;
+ p_cb->app_id = p_enable->app_id;
+ p_cb->srm = p_enable->srm;
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ bta_ops_cb.state = BTA_OPS_LISTEN_ST;
+
+ /* call enable action function */
+ bta_ops_enable(p_cb, p_enable);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_hdl_event
+**
+** Description File transfer server main event handling function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_ops_hdl_event(BT_HDR *p_msg)
+{
+#if BTA_OPS_DEBUG == TRUE
+ tBTA_OPS_STATE in_state = bta_ops_cb.state;
+#endif
+
+ switch (p_msg->event)
+ {
+ case BTA_OPS_API_ENABLE_EVT:
+#if BTA_OPS_DEBUG == TRUE
+ APPL_TRACE_EVENT3("OPS Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ ops_state_code(in_state),
+ ops_evt_code(p_msg->event));
+#endif
+ bta_ops_api_enable(&bta_ops_cb, (tBTA_OPS_DATA *) p_msg);
+
+#if BTA_OPS_DEBUG == TRUE
+ if (in_state != bta_ops_cb.state)
+ {
+ APPL_TRACE_DEBUG3("OPS State Change: [%s] -> [%s] after Event [%s]",
+ ops_state_code(in_state),
+ ops_state_code(bta_ops_cb.state),
+ ops_evt_code(p_msg->event));
+ }
+#endif
+ break;
+
+ default:
+
+ bta_ops_sm_execute(&bta_ops_cb, p_msg->event, (tBTA_OPS_DATA *) p_msg);
+
+ if ( bta_ops_cb.state == BTA_OPS_CONN_ST )
+ {
+ if (( bta_ops_cb.pm_state == BTA_OPS_PM_IDLE )
+ &&( bta_ops_cb.obx_oper != OPS_OP_NONE ))
+ {
+ /* inform power manager */
+ APPL_TRACE_DEBUG0("BTA OPS informs DM/PM busy state");
+ bta_sys_busy( BTA_ID_OPS ,bta_ops_cb.app_id, bta_ops_cb.bd_addr);
+ bta_ops_cb.pm_state = BTA_OPS_PM_BUSY;
+ }
+ else if (( bta_ops_cb.pm_state == BTA_OPS_PM_BUSY )
+ &&( bta_ops_cb.obx_oper == OPS_OP_NONE ))
+ {
+ /* inform power manager */
+ APPL_TRACE_DEBUG0("BTA OPS informs DM/PM idle state");
+ bta_sys_idle( BTA_ID_OPS ,bta_ops_cb.app_id, bta_ops_cb.bd_addr);
+ bta_ops_cb.pm_state = BTA_OPS_PM_IDLE;
+ }
+ }
+ else if ( bta_ops_cb.state == BTA_OPS_LISTEN_ST )
+ {
+ /* initialize power management state */
+ bta_ops_cb.pm_state = BTA_OPS_PM_BUSY;
+ }
+
+ break;
+ }
+
+ return (TRUE);
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_OPS_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function ops_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *ops_evt_code(tBTA_OPS_INT_EVT evt_code)
+{
+ switch(evt_code)
+ {
+ case BTA_OPS_API_DISABLE_EVT:
+ return "BTA_OPS_API_DISABLE_EVT";
+ case BTA_OPS_API_ACCESSRSP_EVT:
+ return "BTA_OPS_API_ACCESSRSP_EVT";
+ case BTA_OPS_API_CLOSE_EVT:
+ return "BTA_OPS_API_CLOSE_EVT";
+ case BTA_OPS_CI_OPEN_EVT:
+ return "BTA_OPS_CI_OPEN_EVT";
+ case BTA_OPS_CI_WRITE_EVT:
+ return "BTA_OPS_CI_WRITE_EVT";
+ case BTA_OPS_CI_READ_EVT:
+ return "BTA_OPS_CI_READ_EVT";
+ case BTA_OPS_OBX_CONN_EVT:
+ return "BTA_OPS_OBX_CONN_EVT";
+ case BTA_OPS_OBX_DISC_EVT:
+ return "BTA_OPS_OBX_DISC_EVT";
+ case BTA_OPS_OBX_ABORT_EVT:
+ return "BTA_OPS_OBX_ABORT_EVT";
+ case BTA_OPS_OBX_CLOSE_EVT:
+ return "BTA_OPS_OBX_CLOSE_EVT";
+ case BTA_OPS_OBX_PUT_EVT:
+ return "BTA_OPS_OBX_PUT_EVT";
+ case BTA_OPS_OBX_GET_EVT:
+ return "BTA_OPS_OBX_GET_EVT";
+ case BTA_OPS_CLOSE_CMPL_EVT:
+ return "BTA_OPS_CLOSE_CMPL_EVT";
+ case BTA_OPS_API_ENABLE_EVT:
+ return "BTA_OPS_API_ENABLE_EVT";
+ default:
+ return "unknown OPS event code";
+ }
+}
+
+/*******************************************************************************
+**
+** Function ops_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *ops_state_code(tBTA_OPS_STATE state_code)
+{
+ switch(state_code)
+ {
+ case BTA_OPS_IDLE_ST:
+ return "BTA_OPS_IDLE_ST";
+ case BTA_OPS_LISTEN_ST:
+ return "BTA_OPS_LISTEN_ST";
+ case BTA_OPS_CONN_ST:
+ return "BTA_OPS_CONN_ST";
+ case BTA_OPS_CLOSING_ST:
+ return "BTA_OPS_CLOSING_ST";
+ default:
+ return "unknown OPS state code";
+ }
+}
+
+#endif /* Debug Functions */
+#endif /* BTA_OP_INCLUDED */
diff --git a/bta/op/bta_ops_utils.c b/bta/op/bta_ops_utils.c
new file mode 100644
index 0000000..eccc1e7
--- /dev/null
+++ b/bta/op/bta_ops_utils.c
@@ -0,0 +1,487 @@
+/*****************************************************************************
+**
+** Name: bta_ops_utils.c
+**
+** Description: This file implements object store functions for the
+** object transfer server.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_OP_INCLUDED) && (BTA_OP_INCLUDED)
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "bta_fs_api.h"
+#include "bta_ops_int.h"
+#include "bta_fs_co.h"
+#include "gki.h"
+#include "utl.h"
+#include "bd.h"
+
+/*******************************************************************************
+** Constants
+*******************************************************************************/
+
+/*******************************************************************************
+** Local Function Prototypes
+*******************************************************************************/
+static int bta_ops_stricmp (const char *p_str1, const char *p_str2);
+
+/*******************************************************************************
+* Exported Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function bta_ops_init_get_obj
+**
+** Description Processes a begin object pull request.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_init_get_obj(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_FORBIDDEN;
+ UINT16 len;
+ UINT8 *p_type;
+ UINT16 name_len;
+
+ /* Type Hdr must be present */
+ if (OBX_ReadTypeHdr(p_evt->p_pkt, &p_type, &len))
+ {
+ /* Type Hdr must be correct */
+ if (!bta_ops_stricmp((const char *)p_type, "text/x-vcard"))
+ {
+ /* Erratum 385 - original OPP spec says "Name Header must not be used."
+ * errara says "Name Header must be empty"
+ * Be a forgiving OPP server, allow either way */
+ name_len = OBX_ReadHdrLen(p_evt->p_pkt, OBX_HI_NAME);
+ if((name_len == OBX_INVALID_HDR_LEN) ||/* no name header */
+ (name_len == 3) /* name header is empty */ )
+ {
+ p_cb->obx.p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /*p_cb->peer_mtu*/OBX_CMD_POOL_SIZE);
+ p_cb->p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1));
+
+ if (p_cb->p_path && p_cb->obx.p_pkt)
+ {
+ p_cb->p_path[0] = '\0';
+ p_cb->p_name = p_cb->p_path;
+ p_cb->obx_oper = OPS_OP_PULL_OBJ;
+ p_cb->obj_fmt = BTA_OP_VCARD21_FMT;
+ p_cb->file_length = BTA_FS_LEN_UNKNOWN;
+
+ /* Notify the appl that a pull default card has been requested */
+ bta_ops_req_app_access (BTA_OP_OPER_PULL, p_cb);
+ rsp_code = OBX_RSP_CONTINUE;
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ }
+ }
+
+ /* Error has been detected; respond with error code */
+ if (rsp_code != OBX_RSP_CONTINUE)
+ {
+ utl_freebuf((void**)&p_cb->obx.p_pkt);
+ utl_freebuf((void**)&p_cb->p_path);
+ p_cb->p_name = NULL;
+ OBX_GetRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_proc_get_obj
+**
+** Description Processes a continuation packet for pulling a vcard.
+** Builds a response packet and initiates a read into it.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_proc_get_obj(tBTA_OPS_CB *p_cb)
+{
+ tBTA_OPS_OBX_PKT *p_obx = &p_cb->obx;
+
+ /* Allocate a new OBX packet */
+ if ((p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /*p_cb->peer_mtu*/OBX_LRG_DATA_POOL_SIZE)) != NULL)
+ {
+ /* 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_fs_co_read(p_cb->fd, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left, BTA_OPS_CI_READ_EVT, 0, p_cb->app_id);
+ }
+ else
+ bta_ops_get_obj_rsp(OBX_RSP_INTRNL_SRVR_ERR, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_proc_put_obj
+**
+** Description Processes a Push Object Operation.
+** Initiates the opening of an object for writing, or continues
+** with a new Obx packet of data (continuation).
+**
+** Parameters p_pkt - Pointer to the OBX Put request
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_proc_put_obj(BT_HDR *p_pkt)
+{
+ tBTA_OPS_CB *p_cb = &bta_ops_cb;
+ tBTA_OPS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 num_hdrs;
+ BOOLEAN endpkt;
+
+ p_obx->p_pkt = p_pkt;
+
+ p_obx->offset = 0; /* Initial offset into OBX data */
+ /* Read in start of body if there is a body header */
+ num_hdrs = OBX_ReadBodyHdr(p_obx->p_pkt, &p_obx->p_start, &p_obx->bytes_left,
+ &endpkt);
+ if (num_hdrs == 1)
+ {
+ p_cb->cout_active = TRUE;
+ bta_fs_co_write(p_cb->fd, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left, BTA_OPS_CI_WRITE_EVT, 0, p_cb->app_id);
+ }
+ else
+ {
+ bta_ops_clean_getput(p_cb, TRUE);
+ bta_ops_put_obj_rsp(OBX_RSP_BAD_REQUEST);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_get_obj_rsp
+**
+** Description Finishes up the end body of the object get, and sends out the
+** OBX response
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_get_obj_rsp(UINT8 rsp_code, UINT16 num_read)
+{
+ tBTA_OPS_CB *p_cb = &bta_ops_cb;
+ tBTA_OPS_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_OPS_PROGRESS param;
+ BOOLEAN done = TRUE;
+
+ /* Send the response packet if successful operation */
+ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE)
+ {
+ p_obx->offset += num_read;
+
+ /* More to be sent */
+ if (rsp_code == OBX_RSP_CONTINUE)
+ {
+ if (p_obx->bytes_left != num_read)
+ APPL_TRACE_WARNING2("OPS Read: Requested (0x%04x), Read In (0x%04x)",
+ p_obx->bytes_left, num_read);
+ done = FALSE;
+ }
+
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, done);
+
+ /* Notify application with progress */
+ if (num_read)
+ {
+ param.bytes = num_read;
+ param.obj_size = p_cb->file_length;
+ param.operation = BTA_OP_OPER_PULL;
+ p_cb->p_cback(BTA_OPS_PROGRESS_EVT, (tBTA_OPS *)&param);
+ }
+ }
+ else
+ p_cb->obx_oper = OPS_OP_NONE;
+
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+
+ /* Final response packet sent out */
+ if (done)
+ bta_ops_clean_getput(p_cb, FALSE);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_put_obj_rsp
+**
+** Description Responds to a put request, and closes the object if finished
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_put_obj_rsp(UINT8 rsp_code)
+{
+ tBTA_OPS_CB *p_cb = &bta_ops_cb;
+ tBTA_OPS_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_OPS_PROGRESS param;
+ tBTA_OPS_OBJECT object;
+
+ /* Finished with input packet */
+ utl_freebuf((void**)&p_obx->p_pkt);
+
+ if (rsp_code == OBX_RSP_OK)
+ {
+ /* Update application if object data was transferred */
+ if (p_obx->bytes_left)
+ {
+ param.bytes = p_obx->bytes_left;
+ param.obj_size = p_cb->file_length;
+ param.operation = BTA_OP_OPER_PUSH;
+ p_cb->p_cback(BTA_OPS_PROGRESS_EVT, (tBTA_OPS *)&param);
+ }
+
+ /* If not end of object put, set the continue response */
+ if (!p_obx->final_pkt)
+ rsp_code = OBX_RSP_CONTINUE;
+ else /* Done - free the allocated memory */
+ {
+ /* callback to app with object */
+ object.format = p_cb->obj_fmt;
+ object.p_name = p_cb->p_name;
+
+ bta_ops_clean_getput(p_cb, FALSE);
+ p_cb->p_cback(BTA_OPS_OBJECT_EVT, (tBTA_OPS *) &object);
+
+ }
+ }
+ else
+ p_cb->obx_oper = OPS_OP_NONE;
+
+ OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_req_app_access
+**
+** Description Sends an access request event to the application.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_req_app_access (tBTA_OP_OPER oper, tBTA_OPS_CB *p_cb)
+{
+ tBTA_OPS_ACCESS *p_acc_evt;
+ char *p_devname;
+ UINT16 len;
+
+ /* Notify the application that a put or get file has been requested */
+ if ((p_acc_evt = (tBTA_OPS_ACCESS *)GKI_getbuf(sizeof(tBTA_OPS_ACCESS))) != NULL)
+ {
+ memset(p_acc_evt, 0, sizeof(tBTA_OPS_ACCESS));
+ p_acc_evt->p_name = p_cb->p_name;
+ p_acc_evt->size = p_cb->file_length;
+ p_acc_evt->oper = p_cb->acc_active = oper;
+ p_acc_evt->format = p_cb->obj_fmt;
+ bdcpy(p_acc_evt->bd_addr, p_cb->bd_addr);
+
+ if ((p_devname = BTM_SecReadDevName(p_cb->bd_addr)) != NULL)
+ BCM_STRNCPY_S((char *)p_acc_evt->dev_name, sizeof(tBTM_BD_NAME), p_devname, BTM_MAX_REM_BD_NAME_LEN);
+
+ /* Only pass the object type if Push operation */
+ if (oper == BTA_OP_OPER_PUSH)
+ {
+ if (!OBX_ReadTypeHdr(p_cb->obx.p_pkt, (UINT8 **)&p_acc_evt->p_type, &len))
+ p_acc_evt->p_type = NULL;
+ }
+
+ if (p_acc_evt->p_type)
+ {
+ APPL_TRACE_EVENT3("OPS Access Request...Name [%s], Oper [%d], Type [%s]",
+ p_cb->p_name, oper, p_acc_evt->p_type);
+ }
+ else
+ {
+ APPL_TRACE_EVENT2("OPS Access Request...Name [%s], Oper [%d]",
+ p_cb->p_name, oper);
+ }
+
+ p_cb->p_cback(BTA_OPS_ACCESS_EVT, (tBTA_OPS *)p_acc_evt);
+ GKI_freebuf(p_acc_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_clean_getput
+**
+** Description Cleans up the get/put resources and control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_clean_getput(tBTA_OPS_CB *p_cb, BOOLEAN is_aborted)
+{
+ tBTA_FS_CO_STATUS status;
+
+ /* Clean up control block */
+ utl_freebuf((void**)&p_cb->obx.p_pkt);
+
+ /* Close any open files */
+ if (p_cb->fd >= 0)
+ {
+ bta_fs_co_close(p_cb->fd, p_cb->app_id);
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ /* Delete an aborted unfinished push file operation */
+ if (is_aborted && p_cb->obx_oper == OPS_OP_PUSH_OBJ)
+ {
+ status = bta_fs_co_unlink(p_cb->p_path, p_cb->app_id);
+ APPL_TRACE_WARNING2("OPS: Remove ABORTED Push File Operation [%s], status 0x%02x", p_cb->p_path, status);
+ }
+ }
+
+ utl_freebuf((void**)&p_cb->p_path);
+ p_cb->p_name = NULL;
+
+ p_cb->obx_oper = OPS_OP_NONE;
+ p_cb->obx.bytes_left = 0;
+ p_cb->file_length = BTA_FS_LEN_UNKNOWN;
+ p_cb->acc_active = 0;
+ p_cb->aborting = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_fmt_supported
+**
+** Description This function determines the file type from a file name
+** and checks if the file type is supported.
+**
+**
+** Returns Format type value or zero if format unsupported.
+**
+*******************************************************************************/
+tBTA_OP_FMT bta_ops_fmt_supported(char *p, tBTA_OP_FMT_MASK fmt_mask)
+{
+ char *p_suffix;
+ tBTA_OP_FMT fmt = BTA_OP_OTHER_FMT;
+
+ /* scan to find file suffix */
+ if ((p_suffix = strrchr(p, '.')) != NULL)
+ {
+ p_suffix++;
+ if (bta_ops_stricmp (p_suffix, "vcf") == 0)
+ {
+ fmt = BTA_OP_VCARD21_FMT;
+ }
+ else if (bta_ops_stricmp (p_suffix, "vcd") == 0)
+ {
+ fmt = BTA_OP_VCARD30_FMT;
+ }
+ else if (bta_ops_stricmp (p_suffix, "vcs") == 0)
+ {
+ fmt = BTA_OP_VCAL_FMT;
+ }
+ else if (bta_ops_stricmp (p_suffix, "ics") == 0)
+ {
+ fmt = BTA_OP_ICAL_FMT;
+ }
+ else if (bta_ops_stricmp (p_suffix, "vmg") == 0)
+ {
+ fmt = BTA_OP_VMSG_FMT;
+ }
+ else if (bta_ops_stricmp (p_suffix, "vnt") == 0)
+ {
+ fmt = BTA_OP_VNOTE_FMT;
+ }
+ }
+
+ /* see if supported */
+ if (fmt == BTA_OP_OTHER_FMT)
+ {
+ if (!(fmt_mask & BTA_OP_ANY_MASK))
+ fmt = 0; /* Other types not supported */
+ }
+ else
+ {
+ if (!((1 << (fmt - 1)) & fmt_mask))
+ fmt = 0;
+ }
+
+ return fmt;
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_discard_data
+**
+** Description frees the data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_discard_data(UINT16 event, tBTA_OPS_DATA *p_data)
+{
+ switch(event)
+ {
+ case BTA_OPS_OBX_CONN_EVT:
+ case BTA_OPS_OBX_DISC_EVT:
+ case BTA_OPS_OBX_ABORT_EVT:
+ case BTA_OPS_OBX_CLOSE_EVT:
+ case BTA_OPS_OBX_PUT_EVT:
+ case BTA_OPS_OBX_GET_EVT:
+ utl_freebuf((void**)&p_data->obx_evt.p_pkt);
+ break;
+
+ default:
+ /*Nothing to free*/
+ break;
+ }
+}
+
+/*******************************************************************************
+* Static Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function bta_ops_stricmp
+**
+** Description Used to compare type header
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static int bta_ops_stricmp (const char *p_str1, const char *p_str2)
+{
+ UINT16 i;
+ UINT16 cmplen;
+
+ if (!p_str1 || !p_str2)
+ return (1);
+
+ cmplen = strlen(p_str1);
+ if (cmplen != strlen(p_str2))
+ return (1);
+
+ for (i = 0; i < cmplen; i++)
+ {
+ if (toupper(p_str1[i]) != toupper(p_str2[i]))
+ return (i+1);
+ }
+
+ return 0;
+}
+#endif /* BTA_OP_INCLUDED */