OSDN Git Service

[automerger] Fix out of bounds read in l2c_rcv_acl_data am: 32b472675b am: 7b75ed3034
authorAndroid Build Merger (Role) <noreply-android-build-merger@google.com>
Fri, 13 Jul 2018 09:40:33 +0000 (09:40 +0000)
committerAndroid Build Merger (Role) <noreply-android-build-merger@google.com>
Fri, 13 Jul 2018 09:40:33 +0000 (09:40 +0000)
Change-Id: I82e38c97577588ebe8738858011ec77ebba0d1ae

21 files changed:
EventLogTags.logtags
bta/ag/bta_ag_at.c
bta/ag/bta_ag_at.h
bta/ag/bta_ag_cmd.c
bta/ag/bta_ag_int.h
bta/dm/bta_dm_act.c
bta/gatt/bta_gattc_act.c
bta/hh/bta_hh_le.c
bta/include/bta_ag_api.h
btif/src/btif_dm.c
btif/src/btif_gatt_client.c
doc/supported_features.md
hci/src/hci_hal_h4.c
hci/test/hci_hal_h4_test.cpp
stack/btm/btm_ble.c
stack/btm/btm_ble_batchscan.c
stack/btm/btm_dev.c
stack/btm/btm_int.h
stack/include/btm_api.h
stack/l2cap/l2c_ble.c
stack/smp/smp_act.c

index 32493d8..dc1d239 100644 (file)
@@ -35,3 +35,4 @@
 
 1010000 bt_hci_timeout (opcode|1)
 1010001 bt_config_source (opcode|1)
+1010002 bt_hci_unknown_type (hci_type|1)
index 8201e86..3606175 100644 (file)
@@ -149,12 +149,16 @@ void bta_ag_process_at(tBTA_AG_AT_CB *p_cb)
                 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, 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, int_arg);
             }
         }
         /* else error */
index 90d7b0f..4b78a33 100644 (file)
@@ -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,7 +55,7 @@ typedef struct
 } 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,
+typedef void (tBTA_AG_AT_CMD_CBACK)(void *p_user, UINT16 command_id, UINT8 arg_type,
                                     char *p_arg, INT16 int_arg);
 
 /* callback function executed to send "ERROR" result code */
index 110b531..ce22f87 100644 (file)
  *
  ******************************************************************************/
 
-/******************************************************************************
- *
- *  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>
@@ -33,6 +30,7 @@
 #include "bta_api.h"
 #include "bta_sys.h"
 #include "bt_common.h"
+#include "osi/include/log.h"
 #include "port_api.h"
 #include "utl.h"
 
 #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;}
-
-/* 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 */
-enum
-{
-    BTA_AG_HS_CMD_CKPD,
-    BTA_AG_HS_CMD_VGS,
-    BTA_AG_HS_CMD_VGM
-};
+#define COLON_IDX_4_VGSVGM    4
 
-/* enumeration of HFP AT commands matches HFP command interpreter table */
+/* Local events which will not trigger a higher layer callback */
 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,162 +130,88 @@ enum
     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[] =
-{
-    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[] =
+typedef struct
 {
-    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 */
-};
+    size_t result_code;
+    size_t indicator;
+} tBTA_AG_INDICATOR_MAP;
 
-/* translation of API result code values to internal values */
-const UINT8 bta_ag_trans_result[] =
+/* callsetup indicator value lookup table */
+const tBTA_AG_INDICATOR_MAP callsetup_indicator_map[] =
 {
-    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 */
+    {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}
 };
 
-/* callsetup indicator value lookup table */
-const UINT8 bta_ag_callsetup_ind_tbl[] =
+static size_t bta_ag_indicator_by_result_code(size_t code)
 {
-    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 */
-};
+    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;
+}
 
 /*******************************************************************************
 **
@@ -342,49 +223,50 @@ const UINT8 bta_ag_callsetup_ind_tbl[] =
 ** 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;
+    }
+
+    char buf[BTA_AG_AT_MAX_LEN + 16];
+    char *p = buf;
+    memset(buf, 0, sizeof(buf));
 
-#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
-    memset(buf, NULL, sizeof(buf));
-#endif
     /* 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 +276,11 @@ static void bta_ag_send_result(tBTA_AG_SCB *p_scb, UINT8 code, char *p_arg,
     *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 +293,7 @@ static void bta_ag_send_multi_result(tBTA_AG_SCB *p_scb, tBTA_AG_MULTI_RESULT_CB
 *******************************************************************************/
 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 +311,9 @@ static void bta_ag_send_error(tBTA_AG_SCB *p_scb, INT16 errcode)
 {
     /* 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 +398,7 @@ static void bta_ag_send_ind(tBTA_AG_SCB *p_scb, UINT16 id, UINT16 value, BOOLEAN
         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);
     }
 }
 
@@ -812,10 +626,9 @@ BOOLEAN bta_ag_inband_enabled(tBTA_AG_SCB *p_scb)
 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 +659,22 @@ void bta_ag_send_call_inds(tBTA_AG_SCB *p_scb, tBTA_AG_RES result)
 ** Returns          void
 **
 *******************************************************************************/
-void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
+void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 command_id, UINT8 arg_type,
                                 char *p_arg, 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);
 
     /* 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 +791,7 @@ static void bta_ag_bind_response(tBTA_AG_SCB *p_scb, uint8_t arg_type)
 
         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 +823,7 @@ static void bta_ag_bind_response(tBTA_AG_SCB *p_scb, uint8_t arg_type)
                 *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;
@@ -1096,7 +907,6 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
                                 char *p_arg, INT16 int_arg)
 {
     tBTA_AG_VAL     val;
-    tBTA_AG_EVT   event;
     tBTA_AG_SCB     *ag_scb;
     UINT32          i, ind_id;
     UINT32          bia_masked_out;
@@ -1120,25 +930,33 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
     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];
+    /**
+     * 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 +990,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             }
             break;
 
-        case BTA_AG_HF_CMD_CCWA:
+        case BTA_AG_LOCAL_EVT_CCWA:
             /* store setting */
             p_scb->ccwa_enabled = (BOOLEAN) int_arg;
 
@@ -1180,7 +998,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             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 +1009,17 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
                 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 +1063,8 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             }
             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 +1083,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             }
             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,25 +1094,25 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             }
             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))
             {
@@ -1314,7 +1133,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             }
             break;
 
-        case BTA_AG_HF_CMD_VTS:
+        case BTA_AG_AT_VTS_EVT:
             /* check argument */
             if (strlen(p_arg) == 1)
             {
@@ -1327,7 +1146,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             }
             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 +1155,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             }
             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 +1164,27 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             }
             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 +1197,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             }
             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 +1208,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
                     {
                         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 +1225,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             }
             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 +1236,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             }
             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 +1253,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             event = 0;
             break;
 
-        case BTA_AG_HF_CMD_BIA:
+        case BTA_AG_LOCAL_EVT_BIA:
             /* don't call callback */
             event = 0;
 
@@ -1461,9 +1285,10 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
                 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,7 +1297,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             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 */
@@ -1508,7 +1333,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             }
             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 +1361,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
             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 +1428,13 @@ void bta_ag_at_err_cback(tBTA_AG_SCB *p_scb, BOOLEAN unknown, char *p_arg)
 *******************************************************************************/
 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 +1508,7 @@ void bta_ag_hsp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
             {
                 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 +1538,13 @@ void bta_ag_hsp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
 *******************************************************************************/
 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 +1701,7 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
         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 +1715,7 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
             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 +1727,7 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
             {
                 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 +1747,7 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
                 {
                     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 +1762,7 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
         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 +1772,7 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
             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 +1781,7 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
                 /* 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 +1827,7 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
                     *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 +1897,7 @@ void bta_ag_send_bcs(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
 
     /* 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 +1916,14 @@ void bta_ag_send_ring(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
 {
     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));
index b721ac0..c1e685f 100644 (file)
 #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
 *****************************************************************************/
index f1e3432..3bf6c06 100644 (file)
@@ -3510,24 +3510,19 @@ static void bta_dm_reset_sec_dev_pending(BD_ADDR remote_bd_addr)
 *******************************************************************************/
 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
index 01b06b8..3390b94 100644 (file)
@@ -715,6 +715,7 @@ void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
             {
                 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;
index 92b3c40..b538470 100644 (file)
@@ -164,34 +164,27 @@ static void gatt_execute_next_op(UINT16 conn_id) {
     }
 
     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 @@ void bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
 
     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 @@ void bta_hh_w4_le_read_char_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
     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 @@ void bta_hh_le_read_char_cmpl (tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
 
     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 @@ void bta_hh_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
     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 @@ void bta_hh_w4_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf)
         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;
index fa76a57..e281fb1 100644 (file)
 #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 */
 #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 */
index 49fa274..f70e4fa 100644 (file)
@@ -1554,6 +1554,10 @@ static void btif_dm_search_services_evt(UINT16 event, char *p_param)
             /* 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__,
index c70fa49..7ad4f08 100644 (file)
@@ -497,6 +497,12 @@ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
             break;
         }
 
+        case BTA_GATTC_SEARCH_RES_EVT:
+        {
+            /* Do nothing */
+            break;
+        }
+
         case BTA_GATTC_READ_DESCR_EVT:
         {
             btgatt_read_params_t data;
index 27fdaa6..60580e2 100644 (file)
@@ -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
 -------------------+---------+-------
index 062b6c0..9c7afe5 100644 (file)
@@ -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 @@ static void event_uart_has_bytes(eager_reader_t *reader, UNUSED_ATTR void *conte
       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;
     }
 
index bf62405..1b861a0 100644 (file)
@@ -192,17 +192,18 @@ static void expect_socket_data(int fd, char first_byte, char *data) {
   }
 }
 
-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_transmit) {
 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 @@ TEST_F(HciHalH4Test, test_read_async_reentry) {
   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);
index d612a85..d6d8d60 100644 (file)
@@ -50,6 +50,7 @@ extern void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable);
 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 @@ BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE d
                              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);
index 95609de..2b329b5 100644 (file)
@@ -123,6 +123,10 @@ void btm_ble_batchscan_filter_track_adv_vse_cback(UINT8 len, UINT8 *p)
 
         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;
     }
index c6def65..25072c5 100644 (file)
@@ -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 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
                           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,11 +76,19 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
         /* 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++;
+
+        /* 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;
     }
 
-    p_dev_rec->bond_type = BOND_TYPE_UNKNOWN;           /* Default value */
-    p_dev_rec->timestamp = btm_cb.dev_rec_count++;
-
     if (dev_class)
         memcpy (p_dev_rec->dev_class, dev_class, DEV_CLASS_LEN);
 
@@ -108,26 +104,23 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
     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_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
  */
 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 @@ BOOLEAN BTM_SecDeleteDevice (BD_ADDR bd_addr)
         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 @@ 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)
+{
+    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 @@ bool is_bd_addr_equal(void *data, void *context)
 *******************************************************************************/
 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 @@ tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr)
     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 @@ tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr)
 *******************************************************************************/
 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 @@ void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec)
 
             /* 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 @@ void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec)
 
                 /* 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 @@ tBTM_SEC_DEV_REC *btm_find_or_alloc_dev (BD_ADDR bd_addr)
 
 /*******************************************************************************
 **
-** 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;
+            }
+        } else {
+            // Paired device
+            if (p_dev_rec->timestamp < ts_oldest_paired) {
+                p_oldest_paired = p_dev_rec;
+                ts_oldest_paired = p_dev_rec->timestamp;
             }
-            continue;
         }
+    }
 
-        if (p_dev_rec->timestamp < ot_paired) {
-            p_oldest_paired = p_dev_rec;
-            ot_paired       = p_dev_rec->timestamp;
-        }
+    // If we did not find any non-paired devices, use the oldest paired one...
+    if (ts_oldest == 0xFFFFFFFF)
+        p_oldest = 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);
     }
 
-    /* if non-paired device return oldest */
-    if (ot != 0xFFFFFFFF)
-        return(p_oldest);
+    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++;
 
-    /* only paired devices present, return oldest */
-    return p_oldest_paired;
+    return p_dev_rec;
 }
 
 /*******************************************************************************
index 4bbc656..88e20ab 100644 (file)
@@ -1057,6 +1057,7 @@ extern void btm_report_device_status (tBTM_DEV_STATUS status);
 */
 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);
index 5df4ce2..a0dc70b 100644 (file)
@@ -3325,6 +3325,15 @@ extern BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class,
  */
 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);
 
 /*******************************************************************************
 **
index 4c5af64..aa855cc 100644 (file)
@@ -77,7 +77,7 @@ BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda)
         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 @@ void l2cble_notify_le_connection (BD_ADDR bda)
         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);
index 4c6cd59..688d967 100644 (file)
@@ -1515,8 +1515,6 @@ void smp_pairing_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     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);
     }
@@ -1555,8 +1553,11 @@ void smp_idle_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 *******************************************************************************/
 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);
 }
 
 /*******************************************************************************