[automerger] Fix buffer overflow in btif_dm_data_copy am: d117975904 am: 12d8535d0f
Change-Id: I22ea297e564616790fd7e916747cdcea25d2b068
diff --git a/EventLogTags.logtags b/EventLogTags.logtags
index 32493d8..dc1d239 100644
--- a/EventLogTags.logtags
+++ b/EventLogTags.logtags
@@ -35,3 +35,4 @@
1010000 bt_hci_timeout (opcode|1)
1010001 bt_config_source (opcode|1)
+1010002 bt_hci_unknown_type (hci_type|1)
diff --git a/bta/ag/bta_ag_act.c b/bta/ag/bta_ag_act.c
index 285a967..e93acb2 100644
--- a/bta/ag/bta_ag_act.c
+++ b/bta/ag/bta_ag_act.c
@@ -68,7 +68,7 @@
};
typedef void (*tBTA_AG_ATCMD_CBACK)(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
- char *p_arg, INT16 int_arg);
+ char *p_arg, char *p_end, INT16 int_arg);
const tBTA_AG_ATCMD_CBACK bta_ag_at_cback_tbl[BTA_AG_NUM_IDX] =
{
diff --git a/bta/ag/bta_ag_at.c b/bta/ag/bta_ag_at.c
index 8201e86..952f1f8 100644
--- a/bta/ag/bta_ag_at.c
+++ b/bta/ag/bta_ag_at.c
@@ -25,6 +25,7 @@
#include <string.h>
#include "bt_common.h"
#include "bta_ag_at.h"
+#include "log/log.h"
#include "utl.h"
/*****************************************************************************
@@ -77,7 +78,7 @@
** Returns void
**
******************************************************************************/
-void bta_ag_process_at(tBTA_AG_AT_CB *p_cb)
+void bta_ag_process_at(tBTA_AG_AT_CB *p_cb, char *p_end)
{
UINT16 idx;
UINT8 arg_type;
@@ -97,6 +98,11 @@
{
/* start of argument is p + strlen matching command */
p_arg = p_cb->p_cmd_buf + strlen(p_cb->p_at_tbl[idx].p_cmd);
+ if (p_arg > p_end) {
+ (*p_cb->p_err_cback)(p_cb->p_user, FALSE, NULL);
+ android_errorWriteLog(0x534e4554, "112860487");
+ return;
+ }
/* if no argument */
if (p_arg[0] == 0)
@@ -149,12 +155,16 @@
else
{
- (*p_cb->p_cmd_cback)(p_cb->p_user, idx, arg_type, p_arg, int_arg);
+ (*p_cb->p_cmd_cback)(p_cb->p_user,
+ p_cb->p_at_tbl[idx].command_id,
+ arg_type, p_arg, p_end, int_arg);
}
}
else
{
- (*p_cb->p_cmd_cback)(p_cb->p_user, idx, arg_type, p_arg, int_arg);
+ (*p_cb->p_cmd_cback)(p_cb->p_user,
+ p_cb->p_at_tbl[idx].command_id,
+ arg_type, p_arg, p_end, int_arg);
}
}
/* else error */
@@ -212,8 +222,9 @@
(p_cb->p_cmd_buf[1] == 'T' || p_cb->p_cmd_buf[1] == 't'))
{
p_save = p_cb->p_cmd_buf;
+ char *p_end = p_cb->p_cmd_buf + p_cb->cmd_pos;
p_cb->p_cmd_buf += 2;
- bta_ag_process_at(p_cb);
+ bta_ag_process_at(p_cb, p_end);
p_cb->p_cmd_buf = p_save;
}
diff --git a/bta/ag/bta_ag_at.h b/bta/ag/bta_ag_at.h
index 90d7b0f..b2dae6e 100644
--- a/bta/ag/bta_ag_at.h
+++ b/bta/ag/bta_ag_at.h
@@ -47,6 +47,7 @@
typedef struct
{
const char *p_cmd; /* AT command string */
+ size_t command_id; /* passed to the callback on p_cmd match */
UINT8 arg_type; /* allowable argument type syntax */
UINT8 fmt; /* whether arg is int or string */
UINT8 min; /* minimum value for int arg */
@@ -54,8 +55,8 @@
} tBTA_AG_AT_CMD;
/* callback function executed when command is parsed */
-typedef void (tBTA_AG_AT_CMD_CBACK)(void *p_user, UINT16 cmd, UINT8 arg_type,
- char *p_arg, INT16 int_arg);
+typedef void (tBTA_AG_AT_CMD_CBACK)(void *p_user, UINT16 command_id, UINT8 arg_type,
+ char *p_arg, char *p_end, INT16 int_arg);
/* callback function executed to send "ERROR" result code */
typedef void (tBTA_AG_AT_ERR_CBACK)(void *p_user, BOOLEAN unknown, char *p_arg);
diff --git a/bta/ag/bta_ag_cmd.c b/bta/ag/bta_ag_cmd.c
index 110b531..6101e36 100644
--- a/bta/ag/bta_ag_cmd.c
+++ b/bta/ag/bta_ag_cmd.c
@@ -16,11 +16,8 @@
*
******************************************************************************/
-/******************************************************************************
- *
- * This file contains functions for processing AT commands and results.
- *
- ******************************************************************************/
+#define LOG_TAG "bta_ag_cmd"
+
#include <ctype.h>
#include <stdio.h>
#include <string.h>
@@ -32,7 +29,9 @@
#include "bta_ag_int.h"
#include "bta_api.h"
#include "bta_sys.h"
+#include "log/log.h"
#include "bt_common.h"
+#include "osi/include/log.h"
#include "port_api.h"
#include "utl.h"
@@ -55,116 +54,73 @@
#define BTA_AG_CLIP_TYPE_DEFAULT 129
#define BTA_AG_CLIP_TYPE_VOIP 255
-#if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
-#define BTA_AG_AT_MULTI_LEN 2
-#define AT_SET_RES_CB(res_cb, c, p, i) {res_cb.code = c; res_cb.p_arg = p; res_cb.int_arg = i;}
+#define COLON_IDX_4_VGSVGM 4
-/* type for AT result code block */
-typedef struct
-{
- UINT8 code;
- char *p_arg;
- INT16 int_arg;
-} tBTA_AG_RESULT_CB;
-
-/* type for multiple AT result codes block */
-typedef struct
-{
- UINT8 num_result;
- tBTA_AG_RESULT_CB res_cb[BTA_AG_AT_MULTI_LEN];
-} tBTA_AG_MULTI_RESULT_CB;
-#endif
-
-/* enumeration of HSP AT commands matches HSP command interpreter table */
+/* Local events which will not trigger a higher layer callback */
enum
{
- BTA_AG_HS_CMD_CKPD,
- BTA_AG_HS_CMD_VGS,
- BTA_AG_HS_CMD_VGM
-};
-
-/* enumeration of HFP AT commands matches HFP command interpreter table */
-enum
-{
- BTA_AG_HF_CMD_A,
- BTA_AG_HF_CMD_D,
- BTA_AG_HF_CMD_VGS,
- BTA_AG_HF_CMD_VGM,
- BTA_AG_HF_CMD_CCWA,
- BTA_AG_HF_CMD_CHLD,
- BTA_AG_HF_CMD_CHUP,
- BTA_AG_HF_CMD_CIND,
- BTA_AG_HF_CMD_CLIP,
- BTA_AG_HF_CMD_CMER,
- BTA_AG_HF_CMD_VTS,
- BTA_AG_HF_CMD_BINP,
- BTA_AG_HF_CMD_BLDN,
- BTA_AG_HF_CMD_BVRA,
- BTA_AG_HF_CMD_BRSF,
- BTA_AG_HF_CMD_NREC,
- BTA_AG_HF_CMD_CNUM,
- BTA_AG_HF_CMD_BTRH,
- BTA_AG_HF_CMD_CLCC,
- BTA_AG_HF_CMD_COPS,
- BTA_AG_HF_CMD_CMEE,
- BTA_AG_HF_CMD_BIA,
- BTA_AG_HF_CMD_CBC,
- BTA_AG_HF_CMD_BCC,
- BTA_AG_HF_CMD_BCS,
- BTA_AG_HF_CMD_BIND,
- BTA_AG_HF_CMD_BIEV,
- BTA_AG_HF_CMD_BAC
+ BTA_AG_LOCAL_EVT_FIRST = 0x100,
+ BTA_AG_LOCAL_EVT_CCWA,
+ BTA_AG_LOCAL_EVT_CLIP,
+ BTA_AG_LOCAL_EVT_CMER,
+ BTA_AG_LOCAL_EVT_BRSF,
+ BTA_AG_LOCAL_EVT_CMEE,
+ BTA_AG_LOCAL_EVT_BIA,
+ BTA_AG_LOCAL_EVT_BCC,
};
/* AT command interpreter table for HSP */
const tBTA_AG_AT_CMD bta_ag_hsp_cmd[] =
{
- {"+CKPD", BTA_AG_AT_SET, BTA_AG_AT_INT, 200, 200},
- {"+VGS", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
- {"+VGM", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
- {"", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0}
+ {"+CKPD", BTA_AG_AT_CKPD_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 200, 200},
+ {"+VGS", BTA_AG_SPK_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
+ {"+VGM", BTA_AG_MIC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
+ /* End-of-table marker used to stop lookup iteration */
+ {"", 0, 0, 0, 0, 0}
};
/* AT command interpreter table for HFP */
const tBTA_AG_AT_CMD bta_ag_hfp_cmd[] =
{
- {"A", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
- {"D", (BTA_AG_AT_NONE | BTA_AG_AT_FREE), BTA_AG_AT_STR, 0, 0},
- {"+VGS", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
- {"+VGM", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
- {"+CCWA", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
+ {"A", BTA_AG_AT_A_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
+ {"D", BTA_AG_AT_D_EVT, BTA_AG_AT_NONE | BTA_AG_AT_FREE, BTA_AG_AT_STR, 0, 0},
+ {"+VGS", BTA_AG_SPK_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
+ {"+VGM", BTA_AG_MIC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
+ {"+CCWA", BTA_AG_LOCAL_EVT_CCWA, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
/* Consider CHLD as str to take care of indexes for ECC */
- {"+CHLD", (BTA_AG_AT_SET | BTA_AG_AT_TEST), BTA_AG_AT_STR, 0, 4},
- {"+CHUP", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
- {"+CIND", (BTA_AG_AT_READ | BTA_AG_AT_TEST), BTA_AG_AT_STR, 0, 0},
- {"+CLIP", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
- {"+CMER", BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
- {"+VTS", BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
- {"+BINP", BTA_AG_AT_SET, BTA_AG_AT_INT, 1, 1},
- {"+BLDN", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
- {"+BVRA", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
- {"+BRSF", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, BTA_AG_CMD_MAX_VAL},
- {"+NREC", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 0},
- {"+CNUM", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
- {"+BTRH", (BTA_AG_AT_READ | BTA_AG_AT_SET), BTA_AG_AT_INT, 0, 2},
- {"+CLCC", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
- {"+COPS", (BTA_AG_AT_READ | BTA_AG_AT_SET), BTA_AG_AT_STR, 0, 0},
- {"+CMEE", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
- {"+BIA", BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 20},
- {"+CBC", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 100},
- {"+BCC", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
- {"+BCS", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, BTA_AG_CMD_MAX_VAL},
- {"+BIND", BTA_AG_AT_SET | BTA_AG_AT_READ | BTA_AG_AT_TEST , BTA_AG_AT_STR, 0, 0},
- {"+BIEV", BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
- {"+BAC", BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
- {"", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0}
+ {"+CHLD", BTA_AG_AT_CHLD_EVT, BTA_AG_AT_SET | BTA_AG_AT_TEST, BTA_AG_AT_STR, 0, 4},
+ {"+CHUP", BTA_AG_AT_CHUP_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
+ {"+CIND", BTA_AG_AT_CIND_EVT, BTA_AG_AT_READ | BTA_AG_AT_TEST, BTA_AG_AT_STR, 0, 0},
+ {"+CLIP", BTA_AG_LOCAL_EVT_CLIP, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
+ {"+CMER", BTA_AG_LOCAL_EVT_CMER, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
+ {"+VTS", BTA_AG_AT_VTS_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
+ {"+BINP", BTA_AG_AT_BINP_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 1, 1},
+ {"+BLDN", BTA_AG_AT_BLDN_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
+ {"+BVRA", BTA_AG_AT_BVRA_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
+ {"+BRSF", BTA_AG_LOCAL_EVT_BRSF, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, BTA_AG_CMD_MAX_VAL},
+ {"+NREC", BTA_AG_AT_NREC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 0},
+ {"+CNUM", BTA_AG_AT_CNUM_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
+ {"+BTRH", BTA_AG_AT_BTRH_EVT, BTA_AG_AT_READ | BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 2},
+ {"+CLCC", BTA_AG_AT_CLCC_EVT, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
+ {"+COPS", BTA_AG_AT_COPS_EVT, BTA_AG_AT_READ | BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
+ {"+CMEE", BTA_AG_LOCAL_EVT_CMEE, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
+ {"+BIA", BTA_AG_LOCAL_EVT_BIA, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 20},
+ {"+CBC", BTA_AG_AT_CBC_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 100},
+ {"+BCC", BTA_AG_LOCAL_EVT_BCC, BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
+ {"+BCS", BTA_AG_AT_BCS_EVT, BTA_AG_AT_SET, BTA_AG_AT_INT, 0, BTA_AG_CMD_MAX_VAL},
+ {"+BIND", BTA_AG_AT_BIND_EVT, BTA_AG_AT_SET | BTA_AG_AT_READ | BTA_AG_AT_TEST, BTA_AG_AT_STR, 0, 0},
+ {"+BIEV", BTA_AG_AT_BIEV_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
+ {"+BAC", BTA_AG_AT_BAC_EVT, BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
+ /* End-of-table marker used to stop lookup iteration */
+ {"", 0, 0, 0, 0, 0}
};
/* AT result code table element */
typedef struct
{
- const char *p_res; /* AT result string */
- UINT8 fmt; /* whether argument is int or string */
+ const char *result_string; /* AT result string */
+ size_t result_id; /* Local or BTA result id */
+ UINT8 arg_type; /* whether argument is int or string */
} tBTA_AG_RESULT;
/* AT result code argument types */
@@ -175,163 +131,89 @@
BTA_AG_RES_FMT_STR /* string argument */
};
-/* enumeration of AT result codes, matches constant table */
+/* Local AT command result codes not defined in bta_ag_api.h */
enum
{
- BTA_AG_RES_OK,
- BTA_AG_RES_ERROR,
- BTA_AG_RES_RING,
- BTA_AG_RES_VGS,
- BTA_AG_RES_VGM,
- BTA_AG_RES_CCWA,
- BTA_AG_RES_CHLD,
- BTA_AG_RES_CIND,
- BTA_AG_RES_CLIP,
- BTA_AG_RES_CIEV,
- BTA_AG_RES_BINP,
- BTA_AG_RES_BVRA,
- BTA_AG_RES_BRSF,
- BTA_AG_RES_BSIR,
- BTA_AG_RES_CNUM,
- BTA_AG_RES_BTRH,
- BTA_AG_RES_CLCC,
- BTA_AG_RES_COPS,
- BTA_AG_RES_CMEE,
- BTA_AG_RES_BCS,
- BTA_AG_RES_BIND,
- BTA_AG_RES_UNAT
+ BTA_AG_LOCAL_RES_FIRST = 0x0100,
+ BTA_AG_LOCAL_RES_OK,
+ BTA_AG_LOCAL_RES_ERROR,
+ BTA_AG_LOCAL_RES_RING,
+ BTA_AG_LOCAL_RES_CLIP,
+ BTA_AG_LOCAL_RES_BRSF,
+ BTA_AG_LOCAL_RES_CMEE,
+ BTA_AG_LOCAL_RES_BCS
};
-#if defined(BTA_HSP_RESULT_REPLACE_COLON) && (BTA_HSP_RESULT_REPLACE_COLON == TRUE)
-#define COLON_IDX_4_VGSVGM 4
-#endif
-/* AT result code constant table (Indexed by result code) */
+/* AT result code constant table */
const tBTA_AG_RESULT bta_ag_result_tbl[] =
{
- {"OK", BTA_AG_RES_FMT_NONE},
- {"ERROR", BTA_AG_RES_FMT_NONE},
- {"RING", BTA_AG_RES_FMT_NONE},
- {"+VGS: ", BTA_AG_RES_FMT_INT},
- {"+VGM: ", BTA_AG_RES_FMT_INT},
- {"+CCWA: ", BTA_AG_RES_FMT_STR},
- {"+CHLD: ", BTA_AG_RES_FMT_STR},
- {"+CIND: ", BTA_AG_RES_FMT_STR},
- {"+CLIP: ", BTA_AG_RES_FMT_STR},
- {"+CIEV: ", BTA_AG_RES_FMT_STR},
- {"+BINP: ", BTA_AG_RES_FMT_STR},
- {"+BVRA: ", BTA_AG_RES_FMT_INT},
- {"+BRSF: ", BTA_AG_RES_FMT_INT},
- {"+BSIR: ", BTA_AG_RES_FMT_INT},
- {"+CNUM: ", BTA_AG_RES_FMT_STR},
- {"+BTRH: ", BTA_AG_RES_FMT_INT},
- {"+CLCC: ", BTA_AG_RES_FMT_STR},
- {"+COPS: ", BTA_AG_RES_FMT_STR},
- {"+CME ERROR: ", BTA_AG_RES_FMT_INT},
- {"+BCS: ", BTA_AG_RES_FMT_INT},
- {"+BIND: ", BTA_AG_RES_FMT_STR},
- {"", BTA_AG_RES_FMT_STR}
+ {"OK", BTA_AG_LOCAL_RES_OK, BTA_AG_RES_FMT_NONE},
+ {"ERROR", BTA_AG_LOCAL_RES_ERROR, BTA_AG_RES_FMT_NONE},
+ {"RING", BTA_AG_LOCAL_RES_RING, BTA_AG_RES_FMT_NONE},
+ {"+VGS: ", BTA_AG_SPK_RES, BTA_AG_RES_FMT_INT},
+ {"+VGM: ", BTA_AG_MIC_RES, BTA_AG_RES_FMT_INT},
+ {"+CCWA: ", BTA_AG_CALL_WAIT_RES, BTA_AG_RES_FMT_STR},
+ {"+CHLD: ", BTA_AG_IN_CALL_HELD_RES,BTA_AG_RES_FMT_STR},
+ {"+CIND: ", BTA_AG_CIND_RES, BTA_AG_RES_FMT_STR},
+ {"+CLIP: ", BTA_AG_LOCAL_RES_CLIP, BTA_AG_RES_FMT_STR},
+ {"+CIEV: ", BTA_AG_IND_RES, BTA_AG_RES_FMT_STR},
+ {"+BINP: ", BTA_AG_BINP_RES, BTA_AG_RES_FMT_STR},
+ {"+BVRA: ", BTA_AG_BVRA_RES, BTA_AG_RES_FMT_INT},
+ {"+BRSF: ", BTA_AG_LOCAL_RES_BRSF, BTA_AG_RES_FMT_INT},
+ {"+BSIR: ", BTA_AG_INBAND_RING_RES, BTA_AG_RES_FMT_INT},
+ {"+CNUM: ", BTA_AG_CNUM_RES, BTA_AG_RES_FMT_STR},
+ {"+BTRH: ", BTA_AG_BTRH_RES, BTA_AG_RES_FMT_INT},
+ {"+CLCC: ", BTA_AG_CLCC_RES, BTA_AG_RES_FMT_STR},
+ {"+COPS: ", BTA_AG_COPS_RES, BTA_AG_RES_FMT_STR},
+ {"+CME ERROR: ", BTA_AG_LOCAL_RES_CMEE, BTA_AG_RES_FMT_INT},
+ {"+BCS: ", BTA_AG_LOCAL_RES_BCS, BTA_AG_RES_FMT_INT},
+ {"+BIND: ", BTA_AG_BIND_RES, BTA_AG_RES_FMT_STR},
+ {"", BTA_AG_UNAT_RES, BTA_AG_RES_FMT_STR}
};
+static const tBTA_AG_RESULT* bta_ag_result_by_code(size_t code)
+{
+ for (size_t i = 0; i != sizeof(bta_ag_result_tbl) /
+ sizeof(bta_ag_result_tbl[0]); ++i)
+ {
+ if (code == bta_ag_result_tbl[i].result_id)
+ return &bta_ag_result_tbl[i];
+ }
+ return 0;
+}
+
const tBTA_AG_AT_CMD *bta_ag_at_tbl[BTA_AG_NUM_IDX] =
{
bta_ag_hsp_cmd,
bta_ag_hfp_cmd
};
-/* callback event lookup table for HSP */
-const tBTA_AG_EVT bta_ag_hsp_cb_evt[] =
+typedef struct
{
- BTA_AG_AT_CKPD_EVT, /* BTA_AG_HS_CMD_CKPD */
- BTA_AG_SPK_EVT, /* BTA_AG_HS_CMD_VGS */
- BTA_AG_MIC_EVT /* BTA_AG_HS_CMD_VGM */
-};
-
-/* callback event lookup table for HFP (Indexed by command) */
-const tBTA_AG_EVT bta_ag_hfp_cb_evt[] =
-{
- BTA_AG_AT_A_EVT, /* BTA_AG_HF_CMD_A */
- BTA_AG_AT_D_EVT, /* BTA_AG_HF_CMD_D */
- BTA_AG_SPK_EVT, /* BTA_AG_HF_CMD_VGS */
- BTA_AG_MIC_EVT, /* BTA_AG_HF_CMD_VGM */
- 0, /* BTA_AG_HF_CMD_CCWA */
- BTA_AG_AT_CHLD_EVT, /* BTA_AG_HF_CMD_CHLD */
- BTA_AG_AT_CHUP_EVT, /* BTA_AG_HF_CMD_CHUP */
- BTA_AG_AT_CIND_EVT, /* BTA_AG_HF_CMD_CIND */
- 0, /* BTA_AG_HF_CMD_CLIP */
- 0, /* BTA_AG_HF_CMD_CMER */
- BTA_AG_AT_VTS_EVT, /* BTA_AG_HF_CMD_VTS */
- BTA_AG_AT_BINP_EVT, /* BTA_AG_HF_CMD_BINP */
- BTA_AG_AT_BLDN_EVT, /* BTA_AG_HF_CMD_BLDN */
- BTA_AG_AT_BVRA_EVT, /* BTA_AG_HF_CMD_BVRA */
- 0, /* BTA_AG_HF_CMD_BRSF */
- BTA_AG_AT_NREC_EVT, /* BTA_AG_HF_CMD_NREC */
- BTA_AG_AT_CNUM_EVT, /* BTA_AG_HF_CMD_CNUM */
- BTA_AG_AT_BTRH_EVT, /* BTA_AG_HF_CMD_BTRH */
- BTA_AG_AT_CLCC_EVT, /* BTA_AG_HF_CMD_CLCC */
- BTA_AG_AT_COPS_EVT, /* BTA_AG_HF_CMD_COPS */
- 0, /* BTA_AG_HF_CMD_CMEE */
- 0, /* BTA_AG_HF_CMD_BIA */
- BTA_AG_AT_CBC_EVT, /* BTA_AG_HF_CMD_CBC */
- 0, /* BTA_AG_HF_CMD_BCC */
- BTA_AG_AT_BCS_EVT, /* BTA_AG_HF_CMD_BCS */
- BTA_AG_AT_BIND_EVT, /* BTA_AG_HF_CMD_BIND */
- BTA_AG_AT_BIEV_EVT, /* BTA_AG_HF_CMD_BIEV */
- BTA_AG_AT_BAC_EVT /* BTA_AG_HF_CMD_BAC */
-};
-
-/* translation of API result code values to internal values */
-const UINT8 bta_ag_trans_result[] =
-{
- BTA_AG_RES_VGS, /* BTA_AG_SPK_RES */
- BTA_AG_RES_VGM, /* BTA_AG_MIC_RES */
- BTA_AG_RES_BSIR, /* BTA_AG_INBAND_RING_RES */
- BTA_AG_RES_CIND, /* BTA_AG_CIND_RES */
- BTA_AG_RES_BINP, /* BTA_AG_BINP_RES */
- BTA_AG_RES_CIEV, /* BTA_AG_IND_RES */
- BTA_AG_RES_BVRA, /* BTA_AG_BVRA_RES */
- BTA_AG_RES_CNUM, /* BTA_AG_CNUM_RES */
- BTA_AG_RES_BTRH, /* BTA_AG_BTRH_RES */
- BTA_AG_RES_CLCC, /* BTA_AG_CLCC_RES */
- BTA_AG_RES_COPS, /* BTA_AG_COPS_RES */
- 0, /* BTA_AG_IN_CALL_RES */
- 0, /* BTA_AG_IN_CALL_CONN_RES */
- BTA_AG_RES_CCWA, /* BTA_AG_CALL_WAIT_RES */
- 0, /* BTA_AG_OUT_CALL_ORIG_RES */
- 0, /* BTA_AG_OUT_CALL_ALERT_RES */
- 0, /* BTA_AG_OUT_CALL_CONN_RES */
- 0, /* BTA_AG_CALL_CANCEL_RES */
- 0, /* BTA_AG_END_CALL_RES */
- 0, /* BTA_AG_IN_CALL_HELD_RES */
- BTA_AG_RES_BIND, /* BTA_AG_BIND_RES */
- BTA_AG_RES_UNAT /* BTA_AG_UNAT_RES */
-};
+ size_t result_code;
+ size_t indicator;
+} tBTA_AG_INDICATOR_MAP;
/* callsetup indicator value lookup table */
-const UINT8 bta_ag_callsetup_ind_tbl[] =
+const tBTA_AG_INDICATOR_MAP callsetup_indicator_map[] =
{
- 0, /* BTA_AG_SPK_RES */
- 0, /* BTA_AG_MIC_RES */
- 0, /* BTA_AG_INBAND_RING_RES */
- 0, /* BTA_AG_CIND_RES */
- 0, /* BTA_AG_BINP_RES */
- 0, /* BTA_AG_IND_RES */
- 0, /* BTA_AG_BVRA_RES */
- 0, /* BTA_AG_CNUM_RES */
- 0, /* BTA_AG_BTRH_RES */
- 0, /* BTA_AG_CLCC_RES */
- 0, /* BTA_AG_COPS_RES */
- BTA_AG_CALLSETUP_INCOMING, /* BTA_AG_IN_CALL_RES */
- BTA_AG_CALLSETUP_NONE, /* BTA_AG_IN_CALL_CONN_RES */
- BTA_AG_CALLSETUP_INCOMING, /* BTA_AG_CALL_WAIT_RES */
- BTA_AG_CALLSETUP_OUTGOING, /* BTA_AG_OUT_CALL_ORIG_RES */
- BTA_AG_CALLSETUP_ALERTING, /* BTA_AG_OUT_CALL_ALERT_RES */
- BTA_AG_CALLSETUP_NONE, /* BTA_AG_OUT_CALL_CONN_RES */
- BTA_AG_CALLSETUP_NONE, /* BTA_AG_CALL_CANCEL_RES */
- BTA_AG_CALLSETUP_NONE, /* BTA_AG_END_CALL_RES */
- BTA_AG_CALLSETUP_NONE, /* BTA_AG_IN_CALL_HELD_RES */
- 0 /* BTA_AG_BIND_RES */
+ {BTA_AG_IN_CALL_RES, BTA_AG_CALLSETUP_INCOMING},
+ {BTA_AG_CALL_WAIT_RES, BTA_AG_CALLSETUP_INCOMING},
+ {BTA_AG_OUT_CALL_ORIG_RES, BTA_AG_CALLSETUP_OUTGOING},
+ {BTA_AG_OUT_CALL_ALERT_RES, BTA_AG_CALLSETUP_ALERTING}
};
+static size_t bta_ag_indicator_by_result_code(size_t code)
+{
+ for (size_t i = 0; i != sizeof(callsetup_indicator_map) /
+ sizeof(callsetup_indicator_map[0]); ++i)
+ {
+ if (code == callsetup_indicator_map[i].result_code)
+ return callsetup_indicator_map[i].indicator;
+ }
+ return BTA_AG_CALLSETUP_NONE;
+}
+
/*******************************************************************************
**
** Function bta_ag_send_result
@@ -342,49 +224,50 @@
** Returns void
**
*******************************************************************************/
-static void bta_ag_send_result(tBTA_AG_SCB *p_scb, UINT8 code, char *p_arg,
+static void bta_ag_send_result(tBTA_AG_SCB *p_scb, size_t code, char *p_arg,
INT16 int_arg)
{
- char buf[BTA_AG_AT_MAX_LEN + 16];
- char *p = buf;
- UINT16 len;
+ const tBTA_AG_RESULT *result = bta_ag_result_by_code(code);
+ if (result == 0)
+ {
+ LOG_ERROR(LOG_TAG, "%s Unable to lookup result for code %zu", __func__, code);
+ return;
+ }
-#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
- memset(buf, NULL, sizeof(buf));
-#endif
+ char buf[BTA_AG_AT_MAX_LEN + 16];
+ char *p = buf;
+ memset(buf, 0, sizeof(buf));
+
/* init with \r\n */
*p++ = '\r';
*p++ = '\n';
/* copy result code string */
- strlcpy(p, bta_ag_result_tbl[code].p_res, sizeof(buf) - 2);
-#if defined(BTA_HSP_RESULT_REPLACE_COLON) && (BTA_HSP_RESULT_REPLACE_COLON == TRUE)
- if(p_scb->conn_service == BTA_AG_HSP)
+ strlcpy(p, result->result_string, sizeof(buf) - 2);
+
+ if (p_scb->conn_service == BTA_AG_HSP)
{
/* If HSP then ":"symbol should be changed as "=" for HSP compatibility */
switch(code)
{
- case BTA_AG_RES_VGS:
- case BTA_AG_RES_VGM:
+ case BTA_AG_SPK_RES:
+ case BTA_AG_MIC_RES:
if(*(p+COLON_IDX_4_VGSVGM) == ':')
{
- #if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
- APPL_TRACE_DEBUG("[HSP] ':'symbol is changed as '=' for HSP compatibility");
- #endif
*(p+COLON_IDX_4_VGSVGM) = '=';
}
break;
}
}
-#endif
- p += strlen(bta_ag_result_tbl[code].p_res);
+
+ p += strlen(result->result_string);
/* copy argument if any */
- if (bta_ag_result_tbl[code].fmt == BTA_AG_RES_FMT_INT)
+ if (result->arg_type == BTA_AG_RES_FMT_INT)
{
p += utl_itoa((UINT16) int_arg, p);
}
- else if (bta_ag_result_tbl[code].fmt == BTA_AG_RES_FMT_STR)
+ else if (result->arg_type == BTA_AG_RES_FMT_STR)
{
strcpy(p, p_arg);
p += strlen(p_arg);
@@ -394,79 +277,11 @@
*p++ = '\r';
*p++ = '\n';
-#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
- APPL_TRACE_DEBUG("bta_ag_send_result: %s", buf);
-#endif
-
/* send to RFCOMM */
+ UINT16 len = 0;
PORT_WriteData(p_scb->conn_handle, buf, (UINT16) (p - buf), &len);
}
-#if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
-/*******************************************************************************
-**
-** Function bta_ag_send_multi_result
-**
-** Description Send multiple AT result codes.
-**
-**
-** Returns void
-**
-*******************************************************************************/
-static void bta_ag_send_multi_result(tBTA_AG_SCB *p_scb, tBTA_AG_MULTI_RESULT_CB *m_res_cb)
-{
- char buf[BTA_AG_AT_MAX_LEN * BTA_AG_AT_MULTI_LEN + 16];
- char *p = buf;
- UINT16 len;
- UINT8 res_idx = 0;
-
- if((!m_res_cb) || (m_res_cb->num_result == 0) || (m_res_cb->num_result > BTA_AG_AT_MULTI_LEN))
- {
- APPL_TRACE_DEBUG("m_res_cb is NULL or num_result is out of range.");
- return;
- }
-
-#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
- memset(buf, NULL, sizeof(buf));
-#endif
-
- while(res_idx < m_res_cb->num_result)
- {
- /* init with \r\n */
- *p++ = '\r';
- *p++ = '\n';
-
- /* copy result code string */
- strcpy(p, bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].p_res);
- p += strlen(bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].p_res);
-
- /* copy argument if any */
- if (bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].fmt == BTA_AG_RES_FMT_INT)
- {
- p += utl_itoa((UINT16) m_res_cb->res_cb[res_idx].int_arg, p);
- }
- else if (bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].fmt == BTA_AG_RES_FMT_STR)
- {
- strcpy(p, m_res_cb->res_cb[res_idx].p_arg);
- p += strlen(m_res_cb->res_cb[res_idx].p_arg);
- }
-
- /* finish with \r\n */
- *p++ = '\r';
- *p++ = '\n';
-
- res_idx++;
- }
-
-#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
- APPL_TRACE_DEBUG("send_result: %s", buf);
-#endif
-
- /* send to RFCOMM */
- PORT_WriteData(p_scb->conn_handle, buf, (UINT16) (p - buf), &len);
-}
-#endif
-
/*******************************************************************************
**
** Function bta_ag_send_ok
@@ -479,7 +294,7 @@
*******************************************************************************/
static void bta_ag_send_ok(tBTA_AG_SCB *p_scb)
{
- bta_ag_send_result(p_scb, BTA_AG_RES_OK, NULL, 0);
+ bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_OK, NULL, 0);
}
/*******************************************************************************
@@ -497,9 +312,9 @@
{
/* If HFP and extended audio gateway error codes are enabled */
if (p_scb->conn_service == BTA_AG_HFP && p_scb->cmee_enabled)
- bta_ag_send_result(p_scb, BTA_AG_RES_CMEE, NULL, errcode);
+ bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_CMEE, NULL, errcode);
else
- bta_ag_send_result(p_scb, BTA_AG_RES_ERROR, NULL, 0);
+ bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_ERROR, NULL, 0);
}
/*******************************************************************************
@@ -584,7 +399,7 @@
p += utl_itoa(id, p);
*p++ = ',';
utl_itoa(value, p);
- bta_ag_send_result(p_scb, BTA_AG_RES_CIEV, str, 0);
+ bta_ag_send_result(p_scb, BTA_AG_IND_RES, str, 0);
}
}
@@ -598,25 +413,25 @@
** Returns TRUE if parsed ok, FALSE otherwise.
**
*******************************************************************************/
-static BOOLEAN bta_ag_parse_cmer(char *p_s, BOOLEAN *p_enabled)
+static BOOLEAN bta_ag_parse_cmer(char *p_s, char *p_end, BOOLEAN *p_enabled)
{
INT16 n[4] = {-1, -1, -1, -1};
int i;
char *p;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++, p_s = p + 1)
{
/* skip to comma delimiter */
- for (p = p_s; *p != ',' && *p != 0; p++);
+ for (p = p_s; p < p_end && *p != ',' && *p != 0; p++);
/* get integer value */
+ if (p > p_end) {
+ android_errorWriteLog(0x534e4554, "112860487");
+ return FALSE;
+ }
*p = 0;
n[i] = utl_str2int(p_s);
p_s = p + 1;
- if (p_s == 0)
- {
- break;
- }
}
/* process values */
@@ -682,7 +497,8 @@
** Returns Returns bitmap of supported codecs.
**
*******************************************************************************/
-static tBTA_AG_PEER_CODEC bta_ag_parse_bac(tBTA_AG_SCB *p_scb, char *p_s)
+static tBTA_AG_PEER_CODEC bta_ag_parse_bac(tBTA_AG_SCB *p_scb, char *p_s,
+ char *p_end)
{
tBTA_AG_PEER_CODEC retval = BTA_AG_CODEC_NONE;
UINT16 uuid_codec;
@@ -692,9 +508,13 @@
while(p_s)
{
/* skip to comma delimiter */
- for(p = p_s; *p != ',' && *p != 0; p++);
+ for(p = p_s; p < p_end && *p != ',' && *p != 0; p++);
/* get integre value */
+ if (p > p_end) {
+ android_errorWriteLog(0x534e4554, "112860487");
+ break;
+ }
if (*p != 0)
{
*p = 0;
@@ -812,10 +632,9 @@
void bta_ag_send_call_inds(tBTA_AG_SCB *p_scb, tBTA_AG_RES result)
{
UINT8 call = p_scb->call_ind;
- UINT8 callsetup;
/* set new call and callsetup values based on BTA_AgResult */
- callsetup = bta_ag_callsetup_ind_tbl[result];
+ size_t callsetup = bta_ag_indicator_by_result_code(result);
if (result == BTA_AG_END_CALL_RES)
{
@@ -846,24 +665,29 @@
** Returns void
**
*******************************************************************************/
-void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
- char *p_arg, INT16 int_arg)
+void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 command_id, UINT8 arg_type,
+ char *p_arg, char *p_end, INT16 int_arg)
{
- tBTA_AG_VAL val;
-
- APPL_TRACE_DEBUG("AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
+ APPL_TRACE_DEBUG("AT cmd:%d arg_type:%d arg:%d arg:%s", command_id, arg_type,
int_arg, p_arg);
- /* send OK */
bta_ag_send_ok(p_scb);
+ tBTA_AG_VAL val;
val.hdr.handle = bta_ag_scb_to_idx(p_scb);
val.hdr.app_id = p_scb->app_id;
val.num = (UINT16) int_arg;
- strlcpy(val.str, p_arg, BTA_AG_AT_MAX_LEN);
+
+ if ((p_end - p_arg + 1) >= (long)sizeof(val.str)) {
+ APPL_TRACE_ERROR("%s: p_arg is too long, send error and return", __func__);
+ bta_ag_send_error(p_scb, BTA_AG_ERR_TEXT_TOO_LONG);
+ android_errorWriteLog(0x534e4554, "112860487");
+ return;
+ }
+ strlcpy(val.str, p_arg, sizeof(val.str));
/* call callback with event */
- (*bta_ag_cb.p_cback)(bta_ag_hsp_cb_evt[cmd], (tBTA_AG *) &val);
+ (*bta_ag_cb.p_cback)(command_id, (tBTA_AG *) &val);
}
/*******************************************************************************
@@ -980,7 +804,7 @@
buffer[index++] = ')';
- bta_ag_send_result(p_scb, BTA_AG_RES_BIND, buffer, 0);
+ bta_ag_send_result(p_scb, BTA_AG_BIND_RES, buffer, 0);
bta_ag_send_ok(p_scb);
}
else if (arg_type == BTA_AG_AT_READ)
@@ -1012,7 +836,7 @@
*p++ = ',';
p += utl_itoa((uint16_t) p_scb->local_hf_indicators[i].is_enable, p);
- bta_ag_send_result(p_scb, BTA_AG_RES_BIND, buffer, 0);
+ bta_ag_send_result(p_scb, BTA_AG_BIND_RES, buffer, 0);
memset(buffer, 0, sizeof(buffer));
p = buffer;
@@ -1093,10 +917,9 @@
**
*******************************************************************************/
void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
- char *p_arg, INT16 int_arg)
+ char *p_arg, char *p_end, INT16 int_arg)
{
tBTA_AG_VAL val;
- tBTA_AG_EVT event;
tBTA_AG_SCB *ag_scb;
UINT32 i, ind_id;
UINT32 bia_masked_out;
@@ -1118,27 +941,42 @@
val.hdr.status = BTA_AG_SUCCESS;
val.num = int_arg;
bdcpy(val.bd_addr, p_scb->peer_addr);
- strlcpy(val.str, p_arg, BTA_AG_AT_MAX_LEN);
- event = bta_ag_hfp_cb_evt[cmd];
+ if ((p_end - p_arg + 1) >= (long)sizeof(val.str)) {
+ APPL_TRACE_ERROR("%s: p_arg is too long, send error and return", __func__);
+ bta_ag_send_error(p_scb, BTA_AG_ERR_TEXT_TOO_LONG);
+ android_errorWriteLog(0x534e4554, "112860487");
+ return;
+ }
+ strlcpy(val.str, p_arg, sizeof(val.str));
+
+ /**
+ * Unless this this is a local event, by default we'll forward
+ * the event code to the application.
+ * If |event| is 0 at the end of this function, the application
+ * callback is NOT invoked.
+ */
+ tBTA_AG_EVT event = 0;
+ if (cmd < BTA_AG_LOCAL_EVT_FIRST)
+ event = cmd;
switch (cmd)
{
- case BTA_AG_HF_CMD_A:
- case BTA_AG_HF_CMD_VGS:
- case BTA_AG_HF_CMD_VGM:
- case BTA_AG_HF_CMD_CHUP:
- case BTA_AG_HF_CMD_CBC:
+ case BTA_AG_AT_A_EVT:
+ case BTA_AG_SPK_EVT:
+ case BTA_AG_MIC_EVT:
+ case BTA_AG_AT_CHUP_EVT:
+ case BTA_AG_AT_CBC_EVT:
/* send OK */
bta_ag_send_ok(p_scb);
break;
- case BTA_AG_HF_CMD_BLDN:
+ case BTA_AG_AT_BLDN_EVT:
/* Do not send OK, App will send error or OK depending on
** last dial number enabled or not */
break;
- case BTA_AG_HF_CMD_D:
+ case BTA_AG_AT_D_EVT:
/* Do not send OK for Dial cmds
** Let application decide whether to send OK or ERROR*/
@@ -1172,7 +1010,7 @@
}
break;
- case BTA_AG_HF_CMD_CCWA:
+ case BTA_AG_LOCAL_EVT_CCWA:
/* store setting */
p_scb->ccwa_enabled = (BOOLEAN) int_arg;
@@ -1180,7 +1018,7 @@
bta_ag_send_ok(p_scb);
break;
- case BTA_AG_HF_CMD_CHLD:
+ case BTA_AG_AT_CHLD_EVT:
if (arg_type == BTA_AG_AT_TEST)
{
/* don't call callback */
@@ -1191,16 +1029,17 @@
if ((p_scb->peer_version >= HFP_VERSION_1_5) &&
(p_scb->features & BTA_AG_FEAT_ECC) &&
(p_scb->peer_features & BTA_AG_PEER_FEAT_ECC))
- bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val_ecc, 0);
+ bta_ag_send_result(p_scb, BTA_AG_IN_CALL_HELD_RES,
+ p_bta_ag_cfg->chld_val_ecc, 0);
else
- bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val, 0);
+ bta_ag_send_result(p_scb, BTA_AG_IN_CALL_HELD_RES,
+ p_bta_ag_cfg->chld_val, 0);
/* send OK */
bta_ag_send_ok(p_scb);
/* if service level conn. not already open, now it's open */
bta_ag_svc_conn_open(p_scb, NULL);
-
}
else
{
@@ -1244,8 +1083,8 @@
}
break;
- case BTA_AG_HF_CMD_BIND:
- APPL_TRACE_DEBUG("%s BTA_AG_HF_CMD_BIND arg_type: %d", __func__, arg_type);
+ case BTA_AG_AT_BIND_EVT:
+ APPL_TRACE_DEBUG("%s BTA_AG_AT_BIND_EVT arg_type: %d", __func__, arg_type);
if (arg_type == BTA_AG_AT_SET)
{
if (bta_ag_parse_bind_set(p_scb, val))
@@ -1264,7 +1103,7 @@
}
break;
- case BTA_AG_HF_CMD_BIEV:
+ case BTA_AG_AT_BIEV_EVT:
if (bta_ag_parse_biev_response(p_scb, &val))
{
bta_ag_send_ok(p_scb);
@@ -1275,27 +1114,27 @@
}
break;
- case BTA_AG_HF_CMD_CIND:
+ case BTA_AG_AT_CIND_EVT:
if (arg_type == BTA_AG_AT_TEST)
{
/* don't call callback */
event = 0;
/* send CIND string, send OK */
- bta_ag_send_result(p_scb, BTA_AG_RES_CIND, p_bta_ag_cfg->cind_info, 0);
+ bta_ag_send_result(p_scb, BTA_AG_CIND_RES, p_bta_ag_cfg->cind_info, 0);
bta_ag_send_ok(p_scb);
}
break;
- case BTA_AG_HF_CMD_CLIP:
+ case BTA_AG_LOCAL_EVT_CLIP:
/* store setting, send OK */
p_scb->clip_enabled = (BOOLEAN) int_arg;
bta_ag_send_ok(p_scb);
break;
- case BTA_AG_HF_CMD_CMER:
+ case BTA_AG_LOCAL_EVT_CMER:
/* if parsed ok store setting, send OK */
- if (bta_ag_parse_cmer(p_arg, &p_scb->cmer_enabled))
+ if (bta_ag_parse_cmer(p_arg, p_end, &p_scb->cmer_enabled))
{
bta_ag_send_ok(p_scb);
@@ -1314,7 +1153,7 @@
}
break;
- case BTA_AG_HF_CMD_VTS:
+ case BTA_AG_AT_VTS_EVT:
/* check argument */
if (strlen(p_arg) == 1)
{
@@ -1327,7 +1166,7 @@
}
break;
- case BTA_AG_HF_CMD_BINP:
+ case BTA_AG_AT_BINP_EVT:
/* if feature not set don't call callback, send ERROR */
if (!(p_scb->features & BTA_AG_FEAT_VTAG))
{
@@ -1336,7 +1175,7 @@
}
break;
- case BTA_AG_HF_CMD_BVRA:
+ case BTA_AG_AT_BVRA_EVT:
/* if feature not supported don't call callback, send ERROR. App will send OK */
if (!(p_scb->features & BTA_AG_FEAT_VREC))
{
@@ -1345,22 +1184,27 @@
}
break;
- case BTA_AG_HF_CMD_BRSF:
+ case BTA_AG_LOCAL_EVT_BRSF:
+ {
/* store peer features */
p_scb->peer_features = (uint16_t) int_arg;
-#if (BTA_HFP_VERSION < HFP_VERSION_1_7 || BTA_HFP_HF_IND_SUPPORTED != true)
- p_scb->features &= ~BTA_AG_FEAT_HF_IND;
-#endif
+
+ tBTA_AG_FEAT features = p_scb->features;
+ if (p_scb->peer_version < HFP_VERSION_1_7)
+ {
+ features &= HFP_1_6_FEAT_MASK;
+ }
+
APPL_TRACE_DEBUG("%s BRSF HF: 0x%x, phone: 0x%x", __func__,
- p_scb->peer_features, p_scb->features);
+ p_scb->peer_features, features);
/* send BRSF, send OK */
- bta_ag_send_result(p_scb, BTA_AG_RES_BRSF, NULL,
- (INT16) (p_scb->features & BTA_AG_BSRF_FEAT_SPEC));
+ bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BRSF, NULL, (int16_t)features);
bta_ag_send_ok(p_scb);
break;
+ }
- case BTA_AG_HF_CMD_NREC:
+ case BTA_AG_AT_NREC_EVT:
/* if feature send OK, else don't call callback, send ERROR */
if (p_scb->features & BTA_AG_FEAT_ECNR)
{
@@ -1373,7 +1217,7 @@
}
break;
- case BTA_AG_HF_CMD_BTRH:
+ case BTA_AG_AT_BTRH_EVT:
/* if feature send BTRH, send OK:, else don't call callback, send ERROR */
if (p_scb->features & BTA_AG_FEAT_BTRH)
{
@@ -1384,7 +1228,7 @@
{
if (ag_scb->in_use)
{
- bta_ag_send_result(ag_scb, BTA_AG_RES_BTRH, NULL, int_arg);
+ bta_ag_send_result(ag_scb, BTA_AG_BTRH_RES, NULL, int_arg);
}
}
bta_ag_send_ok(p_scb);
@@ -1401,7 +1245,7 @@
}
break;
- case BTA_AG_HF_CMD_COPS:
+ case BTA_AG_AT_COPS_EVT:
if (arg_type == BTA_AG_AT_SET)
{
/* don't call callback */
@@ -1412,7 +1256,7 @@
}
break;
- case BTA_AG_HF_CMD_CMEE:
+ case BTA_AG_LOCAL_EVT_CMEE:
if (p_scb->features & BTA_AG_FEAT_EXTERR)
{
/* store setting */
@@ -1429,7 +1273,7 @@
event = 0;
break;
- case BTA_AG_HF_CMD_BIA:
+ case BTA_AG_LOCAL_EVT_BIA:
/* don't call callback */
event = 0;
@@ -1461,9 +1305,10 @@
bta_ag_send_error (p_scb, BTA_AG_ERR_INVALID_INDEX);
break;
- case BTA_AG_HF_CMD_CNUM:
+ case BTA_AG_AT_CNUM_EVT:
break;
- case BTA_AG_HF_CMD_CLCC:
+
+ case BTA_AG_AT_CLCC_EVT:
if(!(p_scb->features & BTA_AG_FEAT_ECS))
{
event = 0;
@@ -1472,13 +1317,13 @@
break;
#if (BTM_WBS_INCLUDED == TRUE )
- case BTA_AG_HF_CMD_BAC:
+ case BTA_AG_AT_BAC_EVT:
bta_ag_send_ok(p_scb);
/* store available codecs from the peer */
if((p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC) && (p_scb->features & BTA_AG_FEAT_CODEC))
{
- p_scb->peer_codecs = bta_ag_parse_bac(p_scb, p_arg);
+ p_scb->peer_codecs = bta_ag_parse_bac(p_scb, p_arg, p_end);
p_scb->codec_updated = TRUE;
if (p_scb->peer_codecs & BTA_AG_CODEC_MSBC)
@@ -1508,7 +1353,7 @@
}
break;
- case BTA_AG_HF_CMD_BCS:
+ case BTA_AG_AT_BCS_EVT:
bta_ag_send_ok(p_scb);
alarm_cancel(p_scb->codec_negotiation_timer);
@@ -1536,7 +1381,7 @@
val.num = codec_sent;
break;
- case BTA_AG_HF_CMD_BCC:
+ case BTA_AG_LOCAL_EVT_BCC:
bta_ag_send_ok(p_scb);
bta_ag_sco_open(p_scb, NULL);
break;
@@ -1603,15 +1448,13 @@
*******************************************************************************/
void bta_ag_hsp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
{
- UINT8 code = bta_ag_trans_result[p_result->result];
-
APPL_TRACE_DEBUG("bta_ag_hsp_result : res = %d", p_result->result);
switch(p_result->result)
{
case BTA_AG_SPK_RES:
case BTA_AG_MIC_RES:
- bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
+ bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.num);
break;
case BTA_AG_IN_CALL_RES:
@@ -1685,7 +1528,7 @@
{
if (p_result->data.str[0] != 0)
{
- bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+ bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
}
if (p_result->data.ok_flag == BTA_AG_OK_DONE)
@@ -1715,14 +1558,13 @@
*******************************************************************************/
void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
{
- UINT8 code = bta_ag_trans_result[p_result->result];
APPL_TRACE_DEBUG("bta_ag_hfp_result : res = %d", p_result->result);
switch(p_result->result)
{
case BTA_AG_SPK_RES:
case BTA_AG_MIC_RES:
- bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
+ bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.num);
break;
case BTA_AG_IN_CALL_RES:
@@ -1879,7 +1721,7 @@
case BTA_AG_INBAND_RING_RES:
p_scb->inband_enabled = p_result->data.state;
APPL_TRACE_DEBUG("inband_enabled set to %d", p_scb->inband_enabled);
- bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
+ bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.state);
break;
case BTA_AG_CIND_RES:
@@ -1893,7 +1735,7 @@
p_scb->callheld_ind = p_result->data.str[12] - '0';
APPL_TRACE_DEBUG("cind call:%d callsetup:%d", p_scb->call_ind, p_scb->callsetup_ind);
- bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+ bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
bta_ag_send_ok(p_scb);
break;
@@ -1905,7 +1747,7 @@
{
if (p_result->data.str[0] != 0)
{
- bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+ bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
}
if (p_result->data.ok_flag == BTA_AG_OK_DONE)
@@ -1925,7 +1767,7 @@
{
bta_ag_process_unat_res(p_result->data.str);
APPL_TRACE_DEBUG("BTA_AG_RES :%s",p_result->data.str);
- bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+ bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
}
if (p_result->data.ok_flag == BTA_AG_OK_DONE)
@@ -1940,7 +1782,7 @@
case BTA_AG_CALL_WAIT_RES:
if (p_scb->ccwa_enabled)
{
- bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+ bta_ag_send_result(p_scb, p_result->result, p_result->data.str, 0);
}
bta_ag_send_call_inds(p_scb, p_result->result);
break;
@@ -1950,7 +1792,7 @@
break;
case BTA_AG_BVRA_RES:
- bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
+ bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.state);
break;
case BTA_AG_BTRH_RES:
@@ -1959,7 +1801,7 @@
/* Don't respond to read if not in response & hold state */
if (p_result->data.num != BTA_AG_BTRH_NO_RESP)
{
- bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
+ bta_ag_send_result(p_scb, p_result->result, NULL, p_result->data.num);
}
/* In case of a response to a read request we need to send OK */
@@ -2005,7 +1847,7 @@
*p++ = ',';
p += utl_itoa(p_scb->local_hf_indicators[local_index].is_enable, p);
- bta_ag_send_result(p_scb, code, buffer, 0);
+ bta_ag_send_result(p_scb, p_result->result, buffer, 0);
} else {
APPL_TRACE_DEBUG("%s HF Indicator %d already %s", p_result->data.ind.id,
(p_result->data.ind.on_demand == true) ? "Enabled" : "Disabled");
@@ -2075,7 +1917,7 @@
/* send +BCS */
APPL_TRACE_DEBUG("send +BCS codec is %d", codec_uuid);
- bta_ag_send_result(p_scb, BTA_AG_RES_BCS, NULL, codec_uuid);
+ bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_BCS, NULL, codec_uuid);
}
#endif
@@ -2094,34 +1936,14 @@
{
UNUSED(p_data);
-#if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
- tBTA_AG_MULTI_RESULT_CB m_res_cb;
-
- if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
- {
- memset(&m_res_cb, NULL, sizeof(tBTA_AG_MULTI_RESULT_CB));
-
- m_res_cb.num_result = 2;
- AT_SET_RES_CB(m_res_cb.res_cb[0], BTA_AG_RES_RING, NULL, 0)
- AT_SET_RES_CB(m_res_cb.res_cb[1], BTA_AG_RES_CLIP, p_scb->clip, 0)
-
- bta_ag_send_multi_result(p_scb, &m_res_cb);
- }
- else
- {
- /* send RING ONLY */
- bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
- }
-#else
/* send RING */
- bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
+ bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_RING, NULL, 0);
/* if HFP and clip enabled and clip data send CLIP */
if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
{
- bta_ag_send_result(p_scb, BTA_AG_RES_CLIP, p_scb->clip, 0);
+ bta_ag_send_result(p_scb, BTA_AG_LOCAL_RES_CLIP, p_scb->clip, 0);
}
-#endif
bta_sys_start_timer(p_scb->ring_timer, BTA_AG_RING_TIMEOUT_MS,
BTA_AG_RING_TIMEOUT_EVT, bta_ag_scb_to_idx(p_scb));
diff --git a/bta/ag/bta_ag_int.h b/bta/ag/bta_ag_int.h
index b721ac0..eac98c2 100644
--- a/bta/ag/bta_ag_int.h
+++ b/bta/ag/bta_ag_int.h
@@ -29,16 +29,6 @@
#include "bta_ag_api.h"
#include "bta_ag_at.h"
-/* Send RING & CLIP in one AT cmd */
-#ifndef BTA_AG_MULTI_RESULT_INCLUDED
-#define BTA_AG_MULTI_RESULT_INCLUDED FALSE
-#endif
-
-/* Replace : in VGS and VGM for HSP */
-#ifndef BTA_HSP_RESULT_REPLACE_COLON
-#define BTA_HSP_RESULT_REPLACE_COLON TRUE
-#endif
-
/*****************************************************************************
** Constants
*****************************************************************************/
@@ -388,9 +378,9 @@
/* AT command functions */
extern void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
- char *p_arg, INT16 int_arg);
+ char *p_arg, char *p_end, INT16 int_arg);
extern void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
- char *p_arg, INT16 int_arg);
+ char *p_arg, char *p_end, INT16 int_arg);
extern void bta_ag_at_err_cback(tBTA_AG_SCB *p_scb, BOOLEAN unknown, char *p_arg);
extern BOOLEAN bta_ag_inband_enabled(tBTA_AG_SCB *p_scb);
extern void bta_ag_send_call_inds(tBTA_AG_SCB *p_scb, tBTA_AG_RES result);
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index f1e3432..3bf6c06 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -3510,24 +3510,19 @@
*******************************************************************************/
static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr)
{
- UINT16 index = 0;
if ( BTM_IsAclConnectionUp(remote_bd_addr, BT_TRANSPORT_LE) ||
BTM_IsAclConnectionUp(remote_bd_addr, BT_TRANSPORT_BR_EDR))
{
- APPL_TRACE_DEBUG("%s ACL is not down. Schedule for Dev Removal when ACL closes",
- __FUNCTION__);
- for (index = 0; index < bta_dm_cb.device_list.count; index ++)
+ APPL_TRACE_DEBUG("%s ACL is not down. Schedule for Dev Removal when ACL closes",
+ __func__);
+ BTM_SecClearSecurityFlags (remote_bd_addr);
+ for (int i = 0; i < bta_dm_cb.device_list.count; i++)
{
- if (!bdcmp( bta_dm_cb.device_list.peer_device[index].peer_bdaddr, remote_bd_addr))
+ if (!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, remote_bd_addr))
+ {
+ bta_dm_cb.device_list.peer_device[i].remove_dev_pending = TRUE;
break;
- }
- if (index != bta_dm_cb.device_list.count)
- {
- bta_dm_cb.device_list.peer_device[index].remove_dev_pending = TRUE;
- }
- else
- {
- APPL_TRACE_ERROR(" %s Device does not exist in DB", __FUNCTION__);
+ }
}
}
else
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
index 01b06b8..3390b94 100644
--- a/bta/gatt/bta_gattc_act.c
+++ b/bta/gatt/bta_gattc_act.c
@@ -715,6 +715,7 @@
{
p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD;
if (bta_gattc_cache_load(p_clcb)) {
+ p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
} else {
p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
diff --git a/bta/hh/bta_hh_le.c b/bta/hh/bta_hh_le.c
index 92b3c40..b538470 100644
--- a/bta/hh/bta_hh_le.c
+++ b/bta/hh/bta_hh_le.c
@@ -164,34 +164,27 @@
}
if (op->type == GATT_READ_CHAR) {
- const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(op->conn_id, op->handle);
-
mark_as_executing(conn_id);
- BTA_GATTC_ReadCharacteristic(op->conn_id, p_char->handle, BTA_GATT_AUTH_REQ_NONE);
+ BTA_GATTC_ReadCharacteristic(op->conn_id, op->handle, BTA_GATT_AUTH_REQ_NONE);
list_remove(gatt_op_queue, op);
} else if (op->type == GATT_READ_DESC) {
- const tBTA_GATTC_DESCRIPTOR *p_desc = BTA_GATTC_GetDescriptor(op->conn_id, op->handle);
-
mark_as_executing(conn_id);
- BTA_GATTC_ReadCharDescr(op->conn_id, p_desc->handle, BTA_GATT_AUTH_REQ_NONE);
+ BTA_GATTC_ReadCharDescr(op->conn_id, op->handle, BTA_GATT_AUTH_REQ_NONE);
list_remove(gatt_op_queue, op);
} else if (op->type == GATT_WRITE_CHAR) {
- const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(op->conn_id, op->handle);
mark_as_executing(conn_id);
- BTA_GATTC_WriteCharValue(op->conn_id, p_char->handle, op->write_type, op->len,
+ BTA_GATTC_WriteCharValue(op->conn_id, op->handle, op->write_type, op->len,
op->p_value, BTA_GATT_AUTH_REQ_NONE);
list_remove(gatt_op_queue, op);
} else if (op->type == GATT_WRITE_DESC) {
- const tBTA_GATTC_DESCRIPTOR *p_desc = BTA_GATTC_GetDescriptor(op->conn_id, op->handle);
-
tBTA_GATT_UNFMT value;
value.len = op->len;
value.p_value = op->p_value;
mark_as_executing(conn_id);
- BTA_GATTC_WriteCharDescr(op->conn_id, p_desc->handle, BTA_GATTC_TYPE_WRITE,
+ BTA_GATTC_WriteCharDescr(op->conn_id, op->handle, BTA_GATTC_TYPE_WRITE,
&value, BTA_GATT_AUTH_REQ_NONE);
list_remove(gatt_op_queue, op);
}
@@ -1774,6 +1767,11 @@
const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
p_data->handle);
+ if (p_char == NULL) {
+ APPL_TRACE_ERROR("%s: p_char is NULL %d", __func__, p_data->handle);
+ return;
+ }
+
UINT16 char_uuid = p_char->uuid.uu.uuid16;
if (char_uuid == GATT_UUID_BATTERY_LEVEL)
@@ -1783,6 +1781,12 @@
else if (char_uuid == GATT_UUID_GAP_PREF_CONN_PARAM)
{
//TODO(jpawlowski): this should be done by GAP profile, remove when GAP is fixed.
+ if (p_data->status != BTA_GATT_OK || p_data->p_value == NULL) {
+ APPL_TRACE_ERROR("%s: read pref conn params error: %d",
+ __func__, p_data->status);
+ return;
+ }
+
UINT8 *pp = p_data->p_value->p_value;
UINT16 min, max, latency, tout;
STREAM_TO_UINT16 (min, pp);
@@ -1858,6 +1862,11 @@
const tBTA_GATTC_CHARACTERISTIC *p_char = BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id,
p_data->handle);
+ if (p_char == NULL) {
+ APPL_TRACE_ERROR("%s: p_char is NULL %d", __func__, p_data->handle);
+ return;
+ }
+
UINT16 char_uuid = p_char->uuid.uu.uuid16;
switch (char_uuid)
@@ -1898,6 +1907,10 @@
UINT8 *pp;
const tBTA_GATTC_DESCRIPTOR *p_desc = BTA_GATTC_GetDescriptor(p_data->conn_id, p_data->handle);
+ if (p_desc == NULL) {
+ APPL_TRACE_ERROR("%s: p_descr is NULL %d", __func__, p_data->handle);
+ return;
+ }
/* if a report client configuration */
if (p_desc->uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG)
@@ -1934,7 +1947,6 @@
return;
const tBTA_GATTC_DESCRIPTOR *p_desc = BTA_GATTC_GetDescriptor(p_data->conn_id, p_data->handle);
-
if (p_desc == NULL) {
APPL_TRACE_ERROR("%s: p_descr is NULL %d", __func__, p_data->handle);
return;
diff --git a/bta/include/bta_ag_api.h b/bta/include/bta_ag_api.h
index fa76a57..e281fb1 100644
--- a/bta/include/bta_ag_api.h
+++ b/bta/include/bta_ag_api.h
@@ -45,10 +45,6 @@
#define BTA_HFP_VERSION HFP_VERSION_1_7
#endif
-#ifndef BTA_HFP_HF_IND_SUPPORTED
-#define BTA_HFP_HF_IND_SUPPORTED TRUE
-#endif
-
/* AG feature masks */
#define BTA_AG_FEAT_3WAY 0x00000001 /* Three-way calling */
#define BTA_AG_FEAT_ECNR 0x00000002 /* Echo cancellation and/or noise reduction */
@@ -60,9 +56,14 @@
#define BTA_AG_FEAT_ECC 0x00000080 /* Enhanced Call Control */
#define BTA_AG_FEAT_EXTERR 0x00000100 /* Extended error codes */
#define BTA_AG_FEAT_CODEC 0x00000200 /* Codec Negotiation */
+
+#define HFP_1_6_FEAT_MASK 0x000003FF /* Valid feature bit mask for HFP 1.6 (and below) */
+
+/* HFP 1.7+ */
#define BTA_AG_FEAT_HF_IND 0x00000400 /* HF Indicators */
#define BTA_AG_FEAT_ESCO 0x00000800 /* eSCO S4 (and T2) setting supported */
+
/* Proprietary features: using 31 ~ 16 bits */
#define BTA_AG_FEAT_BTRH 0x00010000 /* CCAP incoming call hold */
#define BTA_AG_FEAT_UNAT 0x00020000 /* Pass unknown AT commands to application */
diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c
index 49fa274..f70e4fa 100644
--- a/btif/src/btif_dm.c
+++ b/btif/src/btif_dm.c
@@ -1554,6 +1554,10 @@
/* fixme */
break;
+ case BTA_DM_SEARCH_CANCEL_CMPL_EVT:
+ /* no-op */
+ break;
+
#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
case BTA_DM_DISC_BLE_RES_EVT:
BTIF_TRACE_DEBUG("%s:, services 0x%x)", __FUNCTION__,
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
index c70fa49..7ad4f08 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -497,6 +497,12 @@
break;
}
+ case BTA_GATTC_SEARCH_RES_EVT:
+ {
+ /* Do nothing */
+ break;
+ }
+
case BTA_GATTC_READ_DESCR_EVT:
{
btgatt_read_params_t data;
diff --git a/doc/supported_features.md b/doc/supported_features.md
index 27fdaa6..60580e2 100644
--- a/doc/supported_features.md
+++ b/doc/supported_features.md
@@ -1,7 +1,7 @@
-# Fluoride 1.0
+# Fluoride 1.1
-Declaration ID: [D0026807](https://www.bluetooth.org/tpg/QLI_viewQDL.cfm?qid=26807)
-Qualified Design ID: 67282
+Declaration ID: [D024527](https://www.bluetooth.org/tpg/QLI_viewQDL.cfm?qid=24527)
+Qualified Design ID: 83953
Protocol / Profile | Version | Roles
-------------------+---------+-------
diff --git a/hci/src/hci_hal_h4.c b/hci/src/hci_hal_h4.c
index 062b6c0..9c7afe5 100644
--- a/hci/src/hci_hal_h4.c
+++ b/hci/src/hci_hal_h4.c
@@ -38,6 +38,8 @@
// when streaming time sensitive data (A2DP).
#define HCI_THREAD_PRIORITY -19
+#define BT_HCI_UNKNOWN_MESSAGE_TYPE_NUM 1010002
+
// Our interface and modules we import
static const hci_hal_t interface;
static const hci_hal_callbacks_t *callbacks;
@@ -233,7 +235,10 @@
return;
if (type_byte < DATA_TYPE_ACL || type_byte > DATA_TYPE_EVENT) {
- LOG_ERROR(LOG_TAG, "%s Unknown HCI message type. Dropping this byte 0x%x, min %x, max %x", __func__, type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT);
+ LOG_ERROR(LOG_TAG, "%s Unknown HCI message type 0x%x (min=0x%x max=0x%x). Aborting...",
+ __func__, type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT);
+ LOG_EVENT_INT(BT_HCI_UNKNOWN_MESSAGE_TYPE_NUM, type_byte);
+ assert(false && "Unknown HCI message type");
return;
}
diff --git a/hci/test/hci_hal_h4_test.cpp b/hci/test/hci_hal_h4_test.cpp
index bf62405..1b861a0 100644
--- a/hci/test/hci_hal_h4_test.cpp
+++ b/hci/test/hci_hal_h4_test.cpp
@@ -192,17 +192,18 @@
}
}
-static void write_packet(int fd, char first_byte, char *data) {
+static void write_packet(int fd, char first_byte, const void *data,
+ size_t datalen) {
write(fd, &first_byte, 1);
- write(fd, data, strlen(data));
+ write(fd, data, datalen);
}
-static void write_packet_reentry(int fd, char first_byte, char *data) {
+static void write_packet_reentry(int fd, char first_byte, const void *data,
+ size_t datalen) {
write(fd, &first_byte, 1);
- int length = strlen(data);
- for (int i = 0; i < length; i++) {
- write(fd, &data[i], 1);
+ for (size_t i = 0; i < datalen; i++) {
+ write(fd, static_cast<const uint8_t *>(data) + i, 1);
semaphore_wait(reentry_semaphore);
}
}
@@ -226,10 +227,11 @@
TEST_F(HciHalH4Test, test_read_synchronous) {
reset_for(read_synchronous);
- write_packet(sockfd[1], DATA_TYPE_ACL, acl_data);
- write_packet(sockfd[1], HCI_BLE_EVENT, corrupted_data);
- write_packet(sockfd[1], DATA_TYPE_SCO, sco_data);
- write_packet(sockfd[1], DATA_TYPE_EVENT, event_data);
+ write_packet(sockfd[1], DATA_TYPE_ACL, acl_data, strlen(acl_data));
+ write_packet(sockfd[1], HCI_BLE_EVENT, corrupted_data,
+ sizeof(corrupted_data));
+ write_packet(sockfd[1], DATA_TYPE_SCO, sco_data, strlen(sco_data));
+ write_packet(sockfd[1], DATA_TYPE_EVENT, event_data, strlen(event_data));
// Wait for all data to be received before calling the test good
semaphore_wait(done);
@@ -242,7 +244,8 @@
reentry_semaphore = semaphore_new(0);
reentry_i = 0;
- write_packet_reentry(sockfd[1], DATA_TYPE_ACL, sample_data3);
+ write_packet_reentry(sockfd[1], DATA_TYPE_ACL, sample_data3,
+ strlen(sample_data3));
// write_packet_reentry ensures the data has been received
semaphore_free(reentry_semaphore);
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index d612a85..d6d8d60 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -50,6 +50,7 @@
extern BOOLEAN smp_proc_ltk_request(BD_ADDR bda);
#endif
extern void gatt_notify_enc_cmpl(BD_ADDR bd_addr);
+
/*******************************************************************************/
/* External Function to be called by other modules */
/*******************************************************************************/
@@ -73,16 +74,11 @@
tBLE_ADDR_TYPE addr_type)
{
BTM_TRACE_DEBUG ("%s: dev_type=0x%x", __func__, dev_type);
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr);
- if (!p_dev_rec) {
- if (list_length(btm_cb.sec_dev_rec) > BTM_SEC_MAX_DEVICE_RECORDS) {
- BTM_TRACE_ERROR("%s: %d max devices reached!", __func__, BTM_SEC_MAX_DEVICE_RECORDS);
- return FALSE;
- }
-
- p_dev_rec = osi_calloc(sizeof(tBTM_SEC_DEV_REC));
- list_append(btm_cb.sec_dev_rec, p_dev_rec);
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr);
+ if (!p_dev_rec)
+ {
+ p_dev_rec = btm_sec_allocate_dev_rec();
memcpy(p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN);
p_dev_rec->hci_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_BR_EDR);
diff --git a/stack/btm/btm_ble_batchscan.c b/stack/btm/btm_ble_batchscan.c
index 95609de..2b329b5 100644
--- a/stack/btm/btm_ble_batchscan.c
+++ b/stack/btm/btm_ble_batchscan.c
@@ -123,6 +123,10 @@
BTM_TRACE_EVENT("track_adv_vse_cback called: %d, %d, %d", adv_data.filt_index,
adv_data.addr_type, adv_data.advertiser_state);
+
+ // Make sure the device is known
+ BTM_SecAddBleDevice(adv_data.bd_addr.address, NULL, BT_DEVICE_TYPE_BLE, adv_data.addr_type);
+
ble_advtrack_cb.p_track_cback(&adv_data);
return;
}
diff --git a/stack/btm/btm_dev.c b/stack/btm/btm_dev.c
index c6def65..25072c5 100644
--- a/stack/btm/btm_dev.c
+++ b/stack/btm/btm_dev.c
@@ -37,8 +37,6 @@
#include "hcidefs.h"
#include "l2c_api.h"
-static tBTM_SEC_DEV_REC *btm_find_oldest_dev (void);
-
/*******************************************************************************
**
** Function BTM_SecAddDevice
@@ -63,22 +61,12 @@
LINK_KEY link_key, UINT8 key_type, tBTM_IO_CAP io_cap,
UINT8 pin_length)
{
- tBTM_SEC_DEV_REC *p_dev_rec;
- int i, j;
- BOOLEAN found = FALSE;
-
BTM_TRACE_API("%s: link key type:%x", __func__, key_type);
- p_dev_rec = btm_find_dev (bd_addr);
+
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
if (!p_dev_rec)
{
- if (list_length(btm_cb.sec_dev_rec) > BTM_SEC_MAX_DEVICE_RECORDS) {
- BTM_TRACE_DEBUG("%s: Max devices reached!", __func__);
- return FALSE;
- }
-
- BTM_TRACE_DEBUG ("%s: allocate a new dev rec", __func__);
- p_dev_rec = osi_calloc(sizeof(tBTM_SEC_DEV_REC));
- list_append(btm_cb.sec_dev_rec, p_dev_rec);
+ p_dev_rec = btm_sec_allocate_dev_rec();
memcpy (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN);
p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_BR_EDR);
@@ -88,10 +76,18 @@
/* update conn params, use default value for background connection params */
memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
#endif
- }
+ } else {
+ /* "Bump" timestamp for existing record */
+ p_dev_rec->timestamp = btm_cb.dev_rec_count++;
- p_dev_rec->bond_type = BOND_TYPE_UNKNOWN; /* Default value */
- p_dev_rec->timestamp = btm_cb.dev_rec_count++;
+ /* TODO(eisenbach):
+ * Small refactor, but leaving original logic for now.
+ * On the surface, this does not make any sense at all. Why change the
+ * bond state for an existing device here? This logic should be verified
+ * as part of a larger refactor.
+ */
+ p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
+ }
if (dev_class)
memcpy (p_dev_rec->dev_class, dev_class, DEV_CLASS_LEN);
@@ -108,26 +104,23 @@
p_dev_rec->num_read_pages = 0;
if (features)
{
+ BOOLEAN found = FALSE;
memcpy (p_dev_rec->features, features, sizeof (p_dev_rec->features));
- for (i = HCI_EXT_FEATURES_PAGE_MAX; i >= 0; i--)
+ for (int i = HCI_EXT_FEATURES_PAGE_MAX; !found && i >= 0; i--)
{
- for (j = 0; j < HCI_FEATURE_BYTES_PER_PAGE; j++)
+ for (int j = 0; j < HCI_FEATURE_BYTES_PER_PAGE; j++)
{
if (p_dev_rec->features[i][j] != 0)
{
found = TRUE;
+ p_dev_rec->num_read_pages = i + 1;
break;
}
}
- if (found)
- {
- p_dev_rec->num_read_pages = i + 1;
- break;
- }
}
- }
- else
+ } else {
memset (p_dev_rec->features, 0, sizeof (p_dev_rec->features));
+ }
BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
@@ -176,8 +169,6 @@
*/
BOOLEAN BTM_SecDeleteDevice (BD_ADDR bd_addr)
{
- tBTM_SEC_DEV_REC *p_dev_rec;
-
if (BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE) ||
BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_BR_EDR))
{
@@ -185,7 +176,8 @@
return FALSE;
}
- if ((p_dev_rec = btm_find_dev(bd_addr)) != NULL)
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr);
+ if (p_dev_rec != NULL)
{
BD_ADDR bda;
memcpy(bda, bd_addr, BD_ADDR_LEN);
@@ -199,6 +191,25 @@
/*******************************************************************************
**
+** Function BTM_SecClearSecurityFlags
+**
+** Description Reset the security flags (mark as not-paired) for a given
+** remove device.
+**
+*******************************************************************************/
+extern void BTM_SecClearSecurityFlags (BD_ADDR bd_addr)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(bd_addr);
+ if (p_dev_rec == NULL)
+ return;
+
+ p_dev_rec->sec_flags = 0;
+ p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
+ p_dev_rec->sm4 = BTM_SM4_UNKNOWN;
+}
+
+/*******************************************************************************
+**
** Function BTM_SecReadDevName
**
** Description Looks for the device name in the security database for the
@@ -241,20 +252,10 @@
*******************************************************************************/
tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr)
{
- tBTM_SEC_DEV_REC *p_dev_rec = NULL;
tBTM_INQ_INFO *p_inq_info;
BTM_TRACE_EVENT ("btm_sec_alloc_dev");
- if (list_length(btm_cb.sec_dev_rec) > BTM_SEC_MAX_DEVICE_RECORDS) {
- p_dev_rec = btm_find_oldest_dev();
- } else {
- BTM_TRACE_DEBUG ("allocate a new dev rec");
- p_dev_rec = osi_calloc(sizeof(tBTM_SEC_DEV_REC));
- list_append(btm_cb.sec_dev_rec, p_dev_rec);
- }
-
- p_dev_rec->bond_type = BOND_TYPE_UNKNOWN; /* Default value */
- p_dev_rec->sec_flags = BTM_SEC_IN_USE;
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_sec_allocate_dev_rec();
/* Check with the BT manager if details about remote device are known */
/* outgoing connection */
@@ -281,7 +282,6 @@
p_dev_rec->ble_hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_LE);
#endif
p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr, BT_TRANSPORT_BR_EDR);
- p_dev_rec->timestamp = btm_cb.dev_rec_count++;
return(p_dev_rec);
}
@@ -296,17 +296,11 @@
*******************************************************************************/
void btm_sec_free_dev (tBTM_SEC_DEV_REC *p_dev_rec)
{
- p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
- p_dev_rec->sec_flags = 0;
-
#if BLE_INCLUDED == TRUE
/* Clear out any saved BLE keys */
btm_sec_clear_ble_keys (p_dev_rec);
- /* clear the ble block */
- memset(&p_dev_rec->ble, 0, sizeof(tBTM_SEC_BLE));
#endif
-
-
+ list_remove(btm_cb.sec_dev_rec, p_dev_rec);
}
/*******************************************************************************
@@ -476,8 +470,6 @@
/* remove the combined record */
list_remove(btm_cb.sec_dev_rec, p_dev_rec);
-
- p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
break;
}
@@ -491,8 +483,6 @@
/* remove the combined record */
list_remove(btm_cb.sec_dev_rec, p_dev_rec);
-
- p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
}
break;
}
@@ -525,48 +515,79 @@
/*******************************************************************************
**
-** Function btm_find_oldest_dev
+** Function btm_find_oldest_dev_rec
**
** Description Locates the oldest device in use. It first looks for
** the oldest non-paired device. If all devices are paired it
-** deletes the oldest paired device.
+** returns the oldest paired device.
**
** Returns Pointer to the record or NULL
**
*******************************************************************************/
-tBTM_SEC_DEV_REC *btm_find_oldest_dev (void)
+static tBTM_SEC_DEV_REC* btm_find_oldest_dev_rec (void)
{
tBTM_SEC_DEV_REC *p_oldest = NULL;
- UINT32 ot = 0xFFFFFFFF;
+ UINT32 ts_oldest = 0xFFFFFFFF;
tBTM_SEC_DEV_REC *p_oldest_paired = NULL;
- UINT32 ot_paired = 0xFFFFFFFF;
+ UINT32 ts_oldest_paired = 0xFFFFFFFF;
- /* First look for the non-paired devices for the oldest entry */
list_node_t *end = list_end(btm_cb.sec_dev_rec);
for (list_node_t *node = list_begin(btm_cb.sec_dev_rec); node != end; node = list_next(node)) {
tBTM_SEC_DEV_REC *p_dev_rec = list_node(node);
- /* Device is not paired */
- if ((p_dev_rec->sec_flags & (BTM_SEC_LINK_KEY_KNOWN |BTM_SEC_LE_LINK_KEY_KNOWN)) == 0) {
- if (p_dev_rec->timestamp < ot) {
+
+ if ((p_dev_rec->sec_flags & (BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LE_LINK_KEY_KNOWN)) == 0) {
+ // Device is not paired
+ if (p_dev_rec->timestamp < ts_oldest) {
p_oldest = p_dev_rec;
- ot = p_dev_rec->timestamp;
+ ts_oldest = p_dev_rec->timestamp;
}
- continue;
+ } else {
+ // Paired device
+ if (p_dev_rec->timestamp < ts_oldest_paired) {
+ p_oldest_paired = p_dev_rec;
+ ts_oldest_paired = p_dev_rec->timestamp;
+ }
}
-
- if (p_dev_rec->timestamp < ot_paired) {
- p_oldest_paired = p_dev_rec;
- ot_paired = p_dev_rec->timestamp;
- }
-
}
- /* if non-paired device return oldest */
- if (ot != 0xFFFFFFFF)
- return(p_oldest);
+ // If we did not find any non-paired devices, use the oldest paired one...
+ if (ts_oldest == 0xFFFFFFFF)
+ p_oldest = p_oldest_paired;
- /* only paired devices present, return oldest */
- return p_oldest_paired;
+ return p_oldest;
+}
+
+/*******************************************************************************
+**
+** Function btm_sec_allocate_dev_rec
+**
+** Description Attempts to allocate a new device record. If we have
+** exceeded the maximum number of allowable records to
+** allocate, the oldest record will be deleted to make room
+** for the new record.
+**
+** Returns Pointer to the newly allocated record
+**
+*******************************************************************************/
+tBTM_SEC_DEV_REC* btm_sec_allocate_dev_rec(void)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec = NULL;
+
+ if (list_length(btm_cb.sec_dev_rec) > BTM_SEC_MAX_DEVICE_RECORDS)
+ {
+ p_dev_rec = btm_find_oldest_dev_rec();
+ list_remove(btm_cb.sec_dev_rec, p_dev_rec);
+ }
+
+ p_dev_rec = osi_calloc(sizeof(tBTM_SEC_DEV_REC));
+ list_append(btm_cb.sec_dev_rec, p_dev_rec);
+
+ // Initialize defaults
+ p_dev_rec->sec_flags = BTM_SEC_IN_USE;
+ p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;
+ p_dev_rec->timestamp = btm_cb.dev_rec_count++;
+
+ return p_dev_rec;
}
/*******************************************************************************
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index 4bbc656..88e20ab 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -1057,6 +1057,7 @@
*/
extern BOOLEAN btm_dev_support_switch (BD_ADDR bd_addr);
+extern tBTM_SEC_DEV_REC *btm_sec_allocate_dev_rec(void);
extern tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr);
extern void btm_sec_free_dev (tBTM_SEC_DEV_REC *p_dev_rec);
extern tBTM_SEC_DEV_REC *btm_find_dev (BD_ADDR bd_addr);
diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h
index 5df4ce2..a0dc70b 100644
--- a/stack/include/btm_api.h
+++ b/stack/include/btm_api.h
@@ -3325,6 +3325,15 @@
*/
extern BOOLEAN BTM_SecDeleteDevice (BD_ADDR bd_addr);
+/*******************************************************************************
+**
+** Function BTM_SecClearSecurityFlags
+**
+** Description Reset the security flags (mark as not-paired) for a given
+** remove device.
+**
+*******************************************************************************/
+extern void BTM_SecClearSecurityFlags (BD_ADDR bd_addr);
/*******************************************************************************
**
diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c
index 4c5af64..aa855cc 100644
--- a/stack/l2cap/l2c_ble.c
+++ b/stack/l2cap/l2c_ble.c
@@ -77,7 +77,7 @@
p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
/* Do not remove lcb if an LE link is already up as a peripheral */
if (p_lcb != NULL &&
- !(p_lcb->link_role == HCI_ROLE_SLAVE && BTM_ACL_IS_CONNECTED(rem_bda)))
+ !(p_lcb->link_role == HCI_ROLE_SLAVE && btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE) != NULL))
{
p_lcb->disc_reason = L2CAP_CONN_CANCEL;
l2cu_release_lcb (p_lcb);
@@ -294,11 +294,13 @@
l2cu_process_fixed_chnl_resp (p_lcb);
}
- /* For all channels, send the event through their FSMs */
- for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb)
- {
- if (p_ccb->chnl_state == CST_CLOSED)
- l2c_csm_execute (p_ccb, L2CEVT_LP_CONNECT_CFM, NULL);
+ if (p_lcb != NULL) {
+ /* For all channels, send the event through their FSMs */
+ for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb)
+ {
+ if (p_ccb->chnl_state == CST_CLOSED)
+ l2c_csm_execute (p_ccb, L2CEVT_LP_CONNECT_CFM, NULL);
+ }
}
l2cble_use_preferred_conn_params(bda);
diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c
index fc370ad..a986cbd 100644
--- a/stack/smp/smp_act.c
+++ b/stack/smp/smp_act.c
@@ -1537,8 +1537,6 @@
{
if (p_cb->total_tx_unacked == 0)
{
- /* update connection parameter to remote preferred */
- L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, TRUE);
/* process the pairing complete */
smp_proc_pairing_cmpl(p_cb);
}
@@ -1577,8 +1575,11 @@
*******************************************************************************/
void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- /* disable connection parameter update */
- L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE);
+ /* Disable L2CAP connection parameter updates while bonding since
+ some peripherals are not able to revert to fast connection parameters
+ during the start of service discovery. Connection paramter updates
+ get enabled again once service discovery completes. */
+ L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, false);
}
/*******************************************************************************