OSDN Git Service

DO NOT MERGE Blacklist devices for absolute volume control
authorAndre Eisenbach <eisenbach@google.com>
Wed, 2 Mar 2016 03:19:55 +0000 (03:19 +0000)
committerandroid-build-merger <android-build-merger@google.com>
Wed, 2 Mar 2016 03:19:55 +0000 (03:19 +0000)
am: 8fe9b6c9f7

* commit '8fe9b6c9f7538de91c1a3aded53518ca8c6d2fc0':
  DO NOT MERGE Blacklist devices for absolute volume control

69 files changed:
audio_a2dp_hw/audio_a2dp_hw.h
bta/Android.mk
bta/av/bta_av_aact.c
bta/av/bta_av_act.c
bta/av/bta_av_api.c
bta/av/bta_av_int.h
bta/av/bta_av_ssm.c
bta/hf_client/bta_hf_client_at.c
bta/hf_client/bta_hf_client_main.c
bta/include/bta_api.h
bta/include/bta_av_api.h
btif/include/btif_av.h
btif/include/btif_config.h
btif/include/btif_debug_btsnoop.h
btif/include/btif_media.h
btif/src/bluetooth.c
btif/src/btif_av.c
btif/src/btif_config.c
btif/src/btif_debug_btsnoop.c
btif/src/btif_dm.c
btif/src/btif_hf.c
btif/src/btif_media_task.c
btif/src/btif_rc.c
gki/common/gki_buffer.c
hci/Android.mk
hci/EventLogTags.logtags [new file with mode: 0644]
hci/include/bt_vendor_lib.h
hci/include/vendor.h
hci/src/btsnoop_mem.c
hci/src/hci_layer.c
hci/src/vendor.c
include/bt_target.h
osi/Android.mk
osi/src/alarm.c
osi/src/config.c
stack/Android.mk
stack/avdt/avdt_l2c.c
stack/btm/btm_ble.c
stack/btm/btm_dev.c
stack/include/l2c_api.h
stack/include/uipc_msg.h [deleted file]
stack/l2cap/l2c_api.c
stack/l2cap/l2c_ble.c
stack/rfcomm/rfc_mx_fsm.c
test/suite/Android.mk
test/suite/BUILD.gn [new file with mode: 0644]
test/suite/base.h
test/suite/cases/adapter.c
test/suite/cases/cases.c
test/suite/cases/cases.h
test/suite/cases/gatt.c
test/suite/cases/pan.c
test/suite/cases/rfcomm.c
test/suite/main.c [deleted file]
test/suite/main.cpp [new file with mode: 0644]
test/suite/support/adapter.c
test/suite/support/adapter.h
test/suite/support/callbacks.c
test/suite/support/callbacks.h
test/suite/support/gatt.c
test/suite/support/gatt.h
test/suite/support/hal.c
test/suite/support/hal.h
test/suite/support/pan.c
test/suite/support/pan.h
test/suite/support/rfcomm.c
test/suite/support/rfcomm.h
tools/hci/main.c
tools/scripts/btsnooz.py [new file with mode: 0755]

index 1e9464c..901fafb 100644 (file)
@@ -48,12 +48,14 @@ typedef enum {
     A2DP_CTRL_CMD_STOP,
     A2DP_CTRL_CMD_SUSPEND,
     A2DP_CTRL_GET_AUDIO_CONFIG,
+    A2DP_CTRL_CMD_OFFLOAD_START,
 } tA2DP_CTRL_CMD;
 
 typedef enum {
     A2DP_CTRL_ACK_SUCCESS,
     A2DP_CTRL_ACK_FAILURE,
-    A2DP_CTRL_ACK_INCALL_FAILURE /* Failure when in Call*/
+    A2DP_CTRL_ACK_INCALL_FAILURE, /* Failure when in Call*/
+    A2DP_CTRL_ACK_UNSUPPORTED
 } tA2DP_CTRL_ACK;
 
 
index 9f3de3a..be98795 100644 (file)
@@ -2,10 +2,6 @@ LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
 
-ifeq ($(BOARD_HAVE_BLUETOOTH_BCM),true)
-LOCAL_CFLAGS += \
-       -DBOARD_HAVE_BLUETOOTH_BCM
-endif
 LOCAL_CFLAGS += -DBUILDCFG $(bdroid_CFLAGS) -std=c99
 LOCAL_CLANG_CFLAGS += -Wno-error=gnu-variable-sized-type-not-at-end
 
index 73fe923..0748b98 100644 (file)
@@ -37,6 +37,9 @@
 #include "utl.h"
 #include "l2c_api.h"
 #include "l2cdefs.h"
+#include "bt_utils.h"
+#include "vendor.h"
+
 #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
 #include "bta_ar_api.h"
 #endif
@@ -60,6 +63,9 @@
 #define BTA_AV_RECONFIG_RETRY       6
 #endif
 
+/* ACL quota we are letting FW use for A2DP Offload Tx. */
+#define BTA_AV_A2DP_OFFLOAD_XMIT_QUOTA      4
+
 static void bta_av_st_rc_timer(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
 
 /* state machine states */
@@ -140,6 +146,8 @@ const tBTA_AV_SACT bta_av_a2d_action[] =
     bta_av_role_res,        /* BTA_AV_ROLE_RES */
     bta_av_delay_co,        /* BTA_AV_DELAY_CO */
     bta_av_open_at_inc,     /* BTA_AV_OPEN_AT_INC */
+    bta_av_offload_req,     /* BTA_AV_OFFLOAD_REQ */
+    bta_av_offload_rsp,     /* BTA_AV_OFFLOAD_RSP */
     NULL
 };
 
@@ -1076,6 +1084,14 @@ void bta_av_cleanup(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     p_scb->wait = 0;
     p_scb->num_disc_snks = 0;
     bta_sys_stop_timer(&p_scb->timer);
+
+    vendor_get_interface()->send_command(BT_VND_OP_A2DP_OFFLOAD_STOP, (void*)&p_scb->l2c_cid);
+    if (p_scb->offload_start_pending) {
+        tBTA_AV_STATUS status = BTA_AV_FAIL_STREAM;
+        (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, (tBTA_AV *)&status);
+    }
+    p_scb->offload_start_pending = FALSE;
+
     if (p_scb->deregistring)
     {
         /* remove stream */
@@ -1381,6 +1397,7 @@ void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     bta_av_conn_chg((tBTA_AV_DATA *) &msg);
     /* set the congestion flag, so AV would not send media packets by accident */
     p_scb->cong = TRUE;
+    p_scb->offload_start_pending = FALSE;
 
 
     p_scb->stream_mtu = p_data->str_msg.msg.open_ind.peer_mtu - AVDT_MEDIA_HDR_SIZE;
@@ -2061,6 +2078,13 @@ void bta_av_str_stopped (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 
     if (p_scb->co_started)
     {
+        vendor_get_interface()->send_command(BT_VND_OP_A2DP_OFFLOAD_STOP, (void*)&p_scb->l2c_cid);
+        if (p_scb->offload_start_pending) {
+            tBTA_AV_STATUS status = BTA_AV_FAIL_STREAM;
+            (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, (tBTA_AV *)&status);
+        }
+        p_scb->offload_start_pending = FALSE;
+
         bta_av_stream_chg(p_scb, FALSE);
         p_scb->co_started = FALSE;
 
@@ -2653,6 +2677,13 @@ void bta_av_suspend_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     /* in case that we received suspend_ind, we may need to call co_stop here */
     if(p_scb->co_started)
     {
+        vendor_get_interface()->send_command(BT_VND_OP_A2DP_OFFLOAD_STOP, (void*)&p_scb->l2c_cid);
+        if (p_scb->offload_start_pending) {
+            tBTA_AV_STATUS status = BTA_AV_FAIL_STREAM;
+            (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, (tBTA_AV *)&status);
+        }
+        p_scb->offload_start_pending = FALSE;
+
         bta_av_stream_chg(p_scb, FALSE);
 
         {
@@ -3101,4 +3132,88 @@ void bta_av_open_at_inc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     }
 }
 
+/*******************************************************************************
+**
+** Function         bta_av_offload_req
+**
+** Description      This function is called if application requests offload of
+**                  a2dp audio.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_offload_req(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_STATUS status = BTA_AV_FAIL_RESOURCES;
+    UINT16 mtu = bta_av_chk_mtu(p_scb, p_scb->stream_mtu);
+
+    APPL_TRACE_DEBUG("%s stream %s, audio channels open %d", __func__,
+                     p_scb->started ? "STARTED" : "STOPPED", bta_av_cb.audio_open_cnt);
+
+    /* Check if stream has already been started. */
+    /* Support offload if only one audio source stream is open. */
+    if (p_scb->started != TRUE) {
+        status = BTA_AV_FAIL_STREAM;
+
+    } else if (bta_av_cb.audio_open_cnt == 1 &&
+               p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC &&
+               p_scb->chnl == BTA_AV_CHNL_AUDIO) {
+
+        bt_vendor_op_a2dp_offload_t a2dp_offload_start;
+
+        if (L2CA_GetConnectionConfig(p_scb->l2c_cid, &a2dp_offload_start.acl_data_size,
+                                     &a2dp_offload_start.remote_cid, &a2dp_offload_start.lm_handle)) {
+
+            APPL_TRACE_DEBUG("%s l2cmtu %d lcid 0x%02X rcid 0x%02X lm_handle 0x%02X", __func__,
+                             a2dp_offload_start.acl_data_size, p_scb->l2c_cid,
+                             a2dp_offload_start.remote_cid, a2dp_offload_start.lm_handle);
+
+            a2dp_offload_start.bta_av_handle = p_scb->hndl;
+            a2dp_offload_start.xmit_quota = BTA_AV_A2DP_OFFLOAD_XMIT_QUOTA;
+            a2dp_offload_start.stream_mtu = (mtu < p_scb->stream_mtu) ? mtu : p_scb->stream_mtu;
+            a2dp_offload_start.local_cid = p_scb->l2c_cid;
+            a2dp_offload_start.is_flushable = TRUE;
+            a2dp_offload_start.stream_source = ((UINT32)(p_scb->cfg.codec_info[1] | p_scb->cfg.codec_info[2]));
+
+            memcpy(a2dp_offload_start.codec_info, p_scb->cfg.codec_info,
+                   sizeof(a2dp_offload_start.codec_info));
+
+            if (!vendor_get_interface()->send_command(BT_VND_OP_A2DP_OFFLOAD_START, &a2dp_offload_start)) {
+                status = BTA_AV_SUCCESS;
+                p_scb->offload_start_pending = TRUE;
+            }
+        }
+    }
+
+    if (status != BTA_AV_SUCCESS)
+        (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, (tBTA_AV *)&status);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_offload_rsp
+**
+** Description      This function is called when the vendor lib responds to
+**                  BT_VND_OP_A2DP_OFFLOAD_START.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_offload_rsp(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_STATUS status = p_data->api_status_rsp.status;
+
+    APPL_TRACE_DEBUG("%s stream %s status %s", __func__,
+                     p_scb->started ? "STARTED" : "STOPPED",
+                     status ? "FAIL" : "SUCCESS");
+
+    /* Check if stream has already been started. */
+    if (status == BTA_AV_SUCCESS && p_scb->started != TRUE) {
+        status = BTA_AV_FAIL_STREAM;
+    }
+
+    p_scb->offload_start_pending = FALSE;
+    (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, (tBTA_AV *)&status);
+}
+
 #endif /* BTA_AV_INCLUDED */
index 75e0900..aa95c45 100644 (file)
@@ -1434,7 +1434,18 @@ void bta_av_sig_chg(tBTA_AV_DATA *p_data)
             {
                 mask = 1 << xx;
                 APPL_TRACE_DEBUG("conn_lcb: 0x%x", p_cb->conn_lcb);
-
+                tBTA_AV_SCB *p_scb = p_cb->p_scb[xx];
+                if (p_scb != NULL)
+                {
+                    UINT8 avdt_tsep_type = p_scb->seps[p_scb->sep_idx].tsep;
+                    /* If the device is a A2DP source, disconnect the AVDT connection */
+                    if ((avdt_tsep_type == AVDT_TSEP_SRC) && (p_data->hdr.offset == AVDT_ACP))
+                    {
+                        LOG_INFO("%s disconnecting invalid A2DP source to A2DP source connection.", __func__);
+                        AVDT_DisconnectReq(p_data->str_msg.bd_addr, NULL);
+                        return;
+                    }
+                }
                 /* look for a p_lcb with its p_scb registered */
                 if((!(mask & p_cb->conn_lcb)) && (p_cb->p_scb[xx] != NULL))
                 {
index ecc05e1..417e976 100644 (file)
@@ -246,6 +246,47 @@ void BTA_AvStart(void)
 
 /*******************************************************************************
 **
+** Function         BTA_AvOffloadStart
+**
+** Description      Start a2dp audio offloading.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvOffloadStart(tBTA_AV_HNDL hndl)
+{
+    BT_HDR  *p_buf;
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_AV_API_OFFLOAD_START_EVT;
+        p_buf->layer_specific = hndl;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvOffloadStartRsp
+**
+** Description      Response from vendor lib for A2DP Offload Start request.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvOffloadStartRsp(tBTA_AV_HNDL hndl, tBTA_AV_STATUS status)
+{
+    tBTA_AV_API_STATUS_RSP *p_buf;
+    if ((p_buf = (tBTA_AV_API_STATUS_RSP *) GKI_getbuf(sizeof(tBTA_AV_API_STATUS_RSP))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_API_OFFLOAD_START_RSP_EVT;
+        p_buf->hdr.layer_specific = hndl;
+        p_buf->status = status;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         BTA_AvEnable_Sink
 **
 ** Description      Enable/Disable A2DP Sink..
index 6764e94..bc3240c 100644 (file)
@@ -84,6 +84,8 @@ enum
     BTA_AV_ROLE_CHANGE_EVT,
     BTA_AV_AVDT_DELAY_RPT_EVT,
     BTA_AV_ACP_CONNECT_EVT,
+    BTA_AV_API_OFFLOAD_START_EVT,
+    BTA_AV_API_OFFLOAD_START_RSP_EVT,
 
     /* these events are handled outside of the state machine */
     BTA_AV_API_ENABLE_EVT,
@@ -379,6 +381,14 @@ typedef struct
     UINT16              avdt_version;   /* AVDTP protocol version */
 } tBTA_AV_SDP_RES;
 
+/* data type for BTA_AV_API_OFFLOAD_RSP_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_AV_STATUS      status;
+} tBTA_AV_API_STATUS_RSP;
+
+
 /* type for SEP control block */
 typedef struct
 {
@@ -422,6 +432,7 @@ typedef union
     tBTA_AV_ROLE_RES        role_res;
     tBTA_AV_SDP_RES         sdp_res;
     tBTA_AV_API_META_RSP    api_meta_rsp;
+    tBTA_AV_API_STATUS_RSP  api_status_rsp;
 } tBTA_AV_DATA;
 
 typedef void (tBTA_AV_VDP_DATA_ACT)(void *p_scb);
@@ -515,6 +526,7 @@ typedef struct
     UINT8               q_tag;          /* identify the associated q_info union member */
     BOOLEAN             no_rtp_hdr;     /* TRUE if add no RTP header*/
     UINT16              uuid_int;       /*intended UUID of Initiator to connect to */
+    BOOLEAN             offload_start_pending;
 } tBTA_AV_SCB;
 
 #define BTA_AV_RC_ROLE_MASK     0x10
@@ -723,6 +735,9 @@ extern void bta_av_switch_role (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
 extern void bta_av_role_res (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
 extern void bta_av_delay_co (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
 extern void bta_av_open_at_inc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_offload_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_offload_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+
 
 /* ssm action functions - vdp specific */
 extern void bta_av_do_disc_vdp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
index 64ee42a..0ca7948 100644 (file)
@@ -96,6 +96,8 @@ enum
     BTA_AV_ROLE_RES,
     BTA_AV_DELAY_CO,
     BTA_AV_OPEN_AT_INC,
+    BTA_AV_OFFLOAD_REQ,
+    BTA_AV_OFFLOAD_RSP,
     BTA_AV_NUM_SACTIONS
 };
 
@@ -145,7 +147,9 @@ static const UINT8 bta_av_sst_init[][BTA_AV_NUM_COLS] =
 /* AVDT_DISCONNECT_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
 /* ROLE_CHANGE_EVT*/        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
 /* AVDT_DELAY_RPT_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
-/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST }
+/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* API_OFFLOAD_START_EVT */{BTA_AV_OFFLOAD_REQ,    BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* API_OFFLOAD_START_RSP_EVT */{BTA_AV_OFFLOAD_RSP,    BTA_AV_SIGNORE,        BTA_AV_INIT_SST }
 };
 
 /* state table for incoming state */
@@ -185,7 +189,9 @@ static const UINT8 bta_av_sst_incoming[][BTA_AV_NUM_COLS] =
 /* AVDT_DISCONNECT_EVT */   {BTA_AV_CCO_CLOSE,      BTA_AV_CLEANUP,        BTA_AV_INIT_SST },
 /* ROLE_CHANGE_EVT*/        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* AVDT_DELAY_RPT_EVT */    {BTA_AV_DELAY_CO,       BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
-/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST }
+/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* API_OFFLOAD_START_EVT */{BTA_AV_OFFLOAD_REQ,    BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* API_OFFLOAD_START_RSP_EVT */{BTA_AV_OFFLOAD_RSP,    BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST }
 };
 
 /* state table for opening state */
@@ -225,7 +231,9 @@ static const UINT8 bta_av_sst_opening[][BTA_AV_NUM_COLS] =
 /* AVDT_DISCONNECT_EVT */   {BTA_AV_CONN_FAILED,    BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
 /* ROLE_CHANGE_EVT*/        {BTA_AV_ROLE_RES,       BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
 /* AVDT_DELAY_RPT_EVT */    {BTA_AV_DELAY_CO,       BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
-/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST }
+/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* API_OFFLOAD_START_EVT */{BTA_AV_OFFLOAD_REQ,    BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* API_OFFLOAD_START_RSP_EVT */{BTA_AV_OFFLOAD_RSP,    BTA_AV_SIGNORE,        BTA_AV_OPENING_SST }
 };
 
 /* state table for open state */
@@ -265,7 +273,9 @@ static const UINT8 bta_av_sst_open[][BTA_AV_NUM_COLS] =
 /* AVDT_DISCONNECT_EVT */   {BTA_AV_STR_CLOSED,     BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
 /* ROLE_CHANGE_EVT*/        {BTA_AV_ROLE_RES,       BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
 /* AVDT_DELAY_RPT_EVT */    {BTA_AV_DELAY_CO,       BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
-/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPEN_SST }
+/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* API_OFFLOAD_START_EVT */{BTA_AV_OFFLOAD_REQ,    BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* API_OFFLOAD_START_RSP_EVT */{BTA_AV_OFFLOAD_RSP,    BTA_AV_SIGNORE,        BTA_AV_OPEN_SST }
 };
 
 /* state table for reconfig state */
@@ -298,14 +308,16 @@ static const UINT8 bta_av_sst_rcfg[][BTA_AV_NUM_COLS] =
 /* STR_SECURITY_IND_EVT */  {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
 /* STR_SECURITY_CFM_EVT */  {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
 /* STR_WRITE_CFM_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
-/* STR_SUSPEND_CFM_EVT */   {BTA_AV_SUSPEND_CONT,   BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* STR_SUSPEND_CFM_EVT */   {BTA_AV_SUSPEND_CFM,    BTA_AV_SUSPEND_CONT,   BTA_AV_RCFG_SST },
 /* STR_RECONFIG_CFM_EVT */  {BTA_AV_RCFG_CFM,       BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
 /* AVRC_TIMER_EVT */        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
 /* AVDT_CONNECT_EVT */      {BTA_AV_RCFG_OPEN,      BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
 /* AVDT_DISCONNECT_EVT */   {BTA_AV_RCFG_DISCNTD,   BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
 /* ROLE_CHANGE_EVT*/        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
 /* AVDT_DELAY_RPT_EVT */    {BTA_AV_DELAY_CO,       BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
-/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST }
+/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* API_OFFLOAD_START_EVT */{BTA_AV_OFFLOAD_REQ,    BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* API_OFFLOAD_START_RSP_EVT */{BTA_AV_OFFLOAD_RSP,    BTA_AV_SIGNORE,        BTA_AV_RCFG_SST }
 };
 
 /* state table for closing state */
@@ -345,7 +357,9 @@ static const UINT8 bta_av_sst_closing[][BTA_AV_NUM_COLS] =
 /* AVDT_DISCONNECT_EVT */   {BTA_AV_STR_CLOSED,     BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
 /* ROLE_CHANGE_EVT*/        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
 /* AVDT_DELAY_RPT_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
-/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST }
+/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* API_OFFLOAD_START_EVT */{BTA_AV_OFFLOAD_REQ,    BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* API_OFFLOAD_START_RSP_EVT */{BTA_AV_OFFLOAD_RSP,    BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST }
 };
 
 /* type for state table */
index 5674b91..755c5d6 100644 (file)
  *  limitations under the License.
  *
  ******************************************************************************/
+
+#define LOG_TAG "bt_hf_client"
+
 #include <errno.h>
 #include <string.h>
 #include <stdio.h>
 
 #include "bta_hf_client_api.h"
 #include "bta_hf_client_int.h"
+#include "osi/include/log.h"
 #include "port_api.h"
 
 /* Uncomment to enable AT traffic dumping */
@@ -145,9 +149,13 @@ static void bta_hf_client_at_resp_timer_cback (TIMER_LIST_ENT *p_tle)
     {
         bta_hf_client_cb.scb.at_cb.resp_timer_on = FALSE;
 
-        APPL_TRACE_ERROR("HFPClient: AT response timeout, disconnecting");
-
-        bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL);
+        if (bta_hf_client_cb.scb.at_cb.current_cmd == BTA_HF_CLIENT_AT_CNUM) {
+          LOG_INFO("%s timed out waiting for AT+CNUM response; spoofing OK.", __func__);
+          bta_hf_client_handle_ok();
+        } else {
+          APPL_TRACE_ERROR("HFPClient: AT response timeout, disconnecting");
+          bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL);
+        }
     }
 }
 
@@ -965,7 +973,7 @@ static char *bta_hf_client_parse_cops(char *buffer)
     /* spec forces 16 chars max, plus \0 here */
     char opstr[17];
     int res;
-    int offset;
+    int offset = 0;
 
     AT_CHECK_EVENT(buffer, "+COPS:");
 
index 27c00cb..577c78a 100644 (file)
@@ -571,7 +571,8 @@ void bta_hf_client_slc_seq(BOOLEAN error)
         break;
 
     case BTA_HF_CLIENT_AT_BRSF:
-        if (bta_hf_client_cb.scb.peer_features & BTA_HF_CLIENT_PEER_CODEC)
+        if ((bta_hf_client_cb.scb.features & BTA_HF_CLIENT_FEAT_CODEC)
+                && (bta_hf_client_cb.scb.peer_features & BTA_HF_CLIENT_PEER_CODEC))
         {
             bta_hf_client_send_at_bac();
             break;
@@ -593,7 +594,8 @@ void bta_hf_client_slc_seq(BOOLEAN error)
         break;
 
     case BTA_HF_CLIENT_AT_CMER:
-        if (bta_hf_client_cb.scb.peer_features & BTA_HF_CLIENT_PEER_FEAT_3WAY)
+        if (bta_hf_client_cb.scb.peer_features & BTA_HF_CLIENT_PEER_FEAT_3WAY
+               && bta_hf_client_cb.scb.features & BTA_HF_CLIENT_FEAT_3WAY)
         {
             bta_hf_client_send_at_chld('?', 0);
         }
index 648d118..298bc94 100644 (file)
@@ -28,7 +28,6 @@
 #include "bt_target.h"
 #include "bt_types.h"
 #include "btm_api.h"
-#include "uipc_msg.h"
 
 #if BLE_INCLUDED == TRUE
 #include "btm_ble_api.h"
index e0e356f..8b92d30 100644 (file)
@@ -249,10 +249,11 @@ typedef UINT8 tBTA_AV_ERR;
 #define BTA_AV_META_MSG_EVT     17      /* metadata messages */
 #define BTA_AV_REJECT_EVT       18      /* incoming connection rejected */
 #define BTA_AV_RC_FEAT_EVT      19      /* remote control channel peer supported features update */
-#define BTA_AV_MEDIA_SINK_CFG_EVT    20      /* command to configure codec */
+#define BTA_AV_MEDIA_SINK_CFG_EVT    20 /* command to configure codec */
 #define BTA_AV_MEDIA_DATA_EVT   21      /* sending data to Media Task */
+#define BTA_AV_OFFLOAD_START_RSP_EVT 22 /* a2dp offload start response */
 /* Max BTA event */
-#define BTA_AV_MAX_EVT          22
+#define BTA_AV_MAX_EVT          23
 
 
 typedef UINT8 tBTA_AV_EVT;
@@ -448,6 +449,7 @@ typedef union
     tBTA_AV_META_MSG    meta_msg;
     tBTA_AV_REJECT      reject;
     tBTA_AV_RC_FEAT     rc_feat;
+    tBTA_AV_STATUS      status;
 } tBTA_AV;
 
 /* union of data associated with AV Media callback */
@@ -784,6 +786,32 @@ void BTA_AvMetaRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code,
 *******************************************************************************/
 void BTA_AvMetaCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CMD cmd_code, BT_HDR *p_pkt);
 
+/*******************************************************************************
+**
+** Function         BTA_AvOffloadStart
+**
+** Description      Request Starting of A2DP Offload.
+**                  This function is used to start A2DP offload if vendor lib has
+**                  the feature enabled.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvOffloadStart(tBTA_AV_HNDL hndl);
+
+/*******************************************************************************
+**
+** Function         BTA_AvOffloadStartRsp
+**
+** Description      Response from vendor library indicating response for
+**                  OffloadStart.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvOffloadStartRsp(tBTA_AV_HNDL hndl, tBTA_AV_STATUS status);
+
+
 #ifdef __cplusplus
 }
 #endif
index cedc1b7..4b116ee 100644 (file)
@@ -45,6 +45,7 @@ typedef enum {
     BTIF_AV_STOP_STREAM_REQ_EVT,
     BTIF_AV_SUSPEND_STREAM_REQ_EVT,
     BTIF_AV_SINK_CONFIG_REQ_EVT,
+    BTIF_AV_OFFLOAD_START_REQ_EVT,
 } btif_av_sm_event_t;
 
 
index 4dc897a..15b7479 100644 (file)
@@ -46,7 +46,7 @@ const char *btif_config_section_name(const btif_config_section_iter_t *section);
 
 void btif_config_save(void);
 void btif_config_flush(void);
-int btif_config_clear(void);
+bool btif_config_clear(void);
 
 // TODO(zachoverflow): Eww...we need to move these out. These are peer specific, not config general.
 bool btif_get_address_type(const BD_ADDR bd_addr, int *p_addr_type);
index 8c8ef0f..e82421a 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <stdint.h>
 
-#define BTSNOOZ_CURRENT_VERSION 0x01
+#define BTSNOOZ_CURRENT_VERSION 0x02
 
 // The preamble is stored un-encrypted as the first part
 // of the file.
@@ -32,6 +32,7 @@ typedef struct btsnooz_preamble_t {
 // One header for each HCI packet
 typedef struct btsnooz_header_t {
   uint16_t length;
+  uint16_t packet_length;
   uint32_t delta_time_ms;
   uint8_t type;
 } __attribute__((__packed__)) btsnooz_header_t;
index 2ec19cb..01fdf73 100644 (file)
@@ -274,6 +274,8 @@ void btif_a2dp_set_tx_flush(BOOLEAN enable);
 void btif_a2dp_set_rx_flush(BOOLEAN enable);
 void btif_media_check_iop_exceptions(UINT8 *peer_bda);
 void btif_reset_decoder(UINT8 *p_av);
+void btif_a2dp_on_offload_started(tBTA_AV_STATUS status);
+
 
 int btif_a2dp_get_track_frequency(UINT8 frequency);
 int btif_a2dp_get_track_channel_count(UINT8 channeltype);
index 8863f75..23b3db6 100644 (file)
@@ -420,7 +420,7 @@ static int set_os_callouts(bt_os_callouts_t *callouts) {
 
 static int config_clear(void) {
     LOG_INFO("%s", __func__);
-    return btif_config_clear();
+    return btif_config_clear() ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
 }
 
 static const bt_interface_t bluetoothInterface = {
index 5715748..0d87c57 100644 (file)
@@ -194,6 +194,7 @@ const char *dump_av_sm_event_name(btif_av_sm_event_t event)
         CASE_RETURN_STR(BTA_AV_META_MSG_EVT)
         CASE_RETURN_STR(BTA_AV_REJECT_EVT)
         CASE_RETURN_STR(BTA_AV_RC_FEAT_EVT)
+        CASE_RETURN_STR(BTA_AV_OFFLOAD_START_RSP_EVT)
         CASE_RETURN_STR(BTIF_SM_ENTER_EVT)
         CASE_RETURN_STR(BTIF_SM_EXIT_EVT)
         CASE_RETURN_STR(BTIF_AV_CONNECT_REQ_EVT)
@@ -202,6 +203,7 @@ const char *dump_av_sm_event_name(btif_av_sm_event_t event)
         CASE_RETURN_STR(BTIF_AV_STOP_STREAM_REQ_EVT)
         CASE_RETURN_STR(BTIF_AV_SUSPEND_STREAM_REQ_EVT)
         CASE_RETURN_STR(BTIF_AV_SINK_CONFIG_REQ_EVT)
+        CASE_RETURN_STR(BTIF_AV_OFFLOAD_START_REQ_EVT)
         default: return "UNKNOWN_EVENT";
    }
 }
@@ -351,6 +353,11 @@ static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data)
             btif_rc_handler(event, p_data);
             break;
 
+        case BTIF_AV_OFFLOAD_START_REQ_EVT:
+            BTIF_TRACE_ERROR("BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started IDLE");
+            btif_a2dp_on_offload_started(BTA_AV_FAIL);
+            break;
+
         default:
             BTIF_TRACE_WARNING("%s : unhandled event:%s", __FUNCTION__,
                                 dump_av_sm_event_name(event));
@@ -483,6 +490,11 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
                 break;
             }
 
+        case BTIF_AV_OFFLOAD_START_REQ_EVT:
+            btif_a2dp_on_offload_started(BTA_AV_FAIL);
+            BTIF_TRACE_ERROR("BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started OPENING");
+            break;
+
         CHECK_RC_EVENT(event, p_data);
 
         default:
@@ -557,6 +569,11 @@ static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data
             btif_rc_handler(event, (tBTA_AV*)p_data);
             break;
 
+        case BTIF_AV_OFFLOAD_START_REQ_EVT:
+            btif_a2dp_on_offload_started(BTA_AV_FAIL);
+            BTIF_TRACE_ERROR("BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started Closing");
+            break;
+
         default:
             BTIF_TRACE_WARNING("%s : unhandled event:%s", __FUNCTION__,
                                 dump_av_sm_event_name(event));
@@ -713,6 +730,11 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
             btif_queue_advance();
             break;
 
+        case BTIF_AV_OFFLOAD_START_REQ_EVT:
+            btif_a2dp_on_offload_started(BTA_AV_FAIL);
+            BTIF_TRACE_ERROR("BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started Opened");
+            break;
+
         CHECK_RC_EVENT(event, p_data);
 
         default:
@@ -879,6 +901,15 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data
             btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
             break;
 
+        case BTIF_AV_OFFLOAD_START_REQ_EVT:
+            BTA_AvOffloadStart(btif_av_cb.bta_handle);
+            break;
+
+        case BTA_AV_OFFLOAD_START_RSP_EVT:
+
+            btif_a2dp_on_offload_started(p_av->status);
+            break;
+
         CHECK_RC_EVENT(event, p_data);
 
         default:
index dfd308e..d699809 100644 (file)
@@ -23,6 +23,7 @@
 #include <pthread.h>
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "osi/include/alarm.h"
 #include "osi/include/allocator.h"
 
 #include "bt_types.h"
 
+// TODO(armansito): Find a better way than searching by a hardcoded path.
+#if defined(OS_GENERIC)
+static const char *CONFIG_FILE_PATH = "bt_config.conf";
+static const char *CONFIG_BACKUP_PATH = "bt_config.bak";
+#else  // !defined(OS_GENERIC)
 static const char *CONFIG_FILE_PATH = "/data/misc/bluedroid/bt_config.conf";
-static const char *LEGACY_CONFIG_FILE_PATH = "/data/misc/bluedroid/bt_config.xml";
+static const char *CONFIG_BACKUP_PATH = "/data/misc/bluedroid/bt_config.bak";
+#endif  // defined(OS_GENERIC)
 static const period_ms_t CONFIG_SETTLE_PERIOD_MS = 3000;
 
 static void timer_config_save_cb(void *data);
@@ -94,19 +101,17 @@ static future_t *init(void) {
   pthread_mutex_init(&lock, NULL);
   config = config_new(CONFIG_FILE_PATH);
   if (!config) {
-    LOG_WARN("%s unable to load config file; attempting to transcode legacy file.", __func__);
-    config = btif_config_transcode(LEGACY_CONFIG_FILE_PATH);
+    LOG_WARN("%s unable to load config file: %s; using backup.",
+              __func__, CONFIG_FILE_PATH);
+    config = config_new(CONFIG_BACKUP_PATH);
     if (!config) {
-      LOG_WARN("%s unable to transcode legacy file, starting unconfigured.", __func__);
+      LOG_ERROR("%s unable to load backup; creating empty config.", __func__);
       config = config_new_empty();
       if (!config) {
         LOG_ERROR("%s unable to allocate a config object.", __func__);
         goto error;
       }
     }
-
-    if (config_save(config, CONFIG_FILE_PATH))
-      unlink(LEGACY_CONFIG_FILE_PATH);
   }
 
   btif_config_devcache_cleanup();
@@ -362,7 +367,7 @@ void btif_config_flush(void) {
   btif_config_write();
 }
 
-int btif_config_clear(void){
+bool btif_config_clear(void){
   assert(config != NULL);
   assert(alarm_timer != NULL);
 
@@ -377,7 +382,7 @@ int btif_config_clear(void){
     return false;
   }
 
-  int ret = config_save(config, CONFIG_FILE_PATH);
+  bool ret = config_save(config, CONFIG_FILE_PATH);
   pthread_mutex_unlock(&lock);
   return ret;
 }
@@ -393,6 +398,8 @@ static void btif_config_write(void) {
   btif_config_devcache_cleanup();
 
   pthread_mutex_lock(&lock);
+  rename(CONFIG_FILE_PATH, CONFIG_BACKUP_PATH);
+  sync();
   config_save(config, CONFIG_FILE_PATH);
   pthread_mutex_unlock(&lock);
 }
index 1deda9c..7916fdf 100644 (file)
@@ -30,7 +30,7 @@
 
 // Total btsnoop memory log buffer size
 #ifndef BTSNOOP_MEM_BUFFER_SIZE
-static const size_t BTSNOOP_MEM_BUFFER_SIZE = (128 * 1024);
+static const size_t BTSNOOP_MEM_BUFFER_SIZE = (172 * 1024);
 #endif
 
 // Block size for copying buffers (for compression/encoding etc.)
@@ -45,9 +45,28 @@ static uint64_t last_timestamp_ms = 0;
 static void btsnoop_cb(const uint16_t type, const uint8_t *data, const size_t length) {
   btsnooz_header_t header;
 
+  // Only log packet content for HCI commands and events (privacy).
+  size_t included_length = 0;
+  switch (type) {
+    case BT_EVT_TO_LM_HCI_CMD:
+      included_length = length;
+      break;
+    case BT_EVT_TO_BTU_HCI_EVT:
+      included_length = length;
+      break;
+    case BT_EVT_TO_LM_HCI_ACL:
+    case BT_EVT_TO_BTU_HCI_ACL:
+      included_length = 4;
+      break;
+    case BT_EVT_TO_LM_HCI_SCO:
+    case BT_EVT_TO_BTU_HCI_SCO:
+      included_length = 2;
+      break;
+  }
+
   // Make room in the ring buffer
 
-  while (ringbuffer_available(buffer) < (length + sizeof(btsnooz_header_t))) {
+  while (ringbuffer_available(buffer) < (included_length + sizeof(btsnooz_header_t))) {
     ringbuffer_pop(buffer, (uint8_t *)&header, sizeof(btsnooz_header_t));
     ringbuffer_delete(buffer, header.length - 1);
   }
@@ -57,12 +76,13 @@ static void btsnoop_cb(const uint16_t type, const uint8_t *data, const size_t le
   const uint64_t now = btif_debug_ts();
 
   header.type = REDUCE_HCI_TYPE_TO_SIGNIFICANT_BITS(type);
-  header.length = length;
+  header.length = included_length + 1;  // +1 for type byte.
+  header.packet_length = length + 1;  // +1 for type byte.
   header.delta_time_ms = last_timestamp_ms ? now - last_timestamp_ms : 0;
   last_timestamp_ms = now;
 
   ringbuffer_insert(buffer, (uint8_t *)&header, sizeof(btsnooz_header_t));
-  ringbuffer_insert(buffer, data, length - 1);
+  ringbuffer_insert(buffer, data, included_length);
 }
 
 static bool btsnoop_compress(ringbuffer_t *rb_dst, ringbuffer_t *rb_src) {
index 425af22..3996153 100644 (file)
@@ -1089,6 +1089,16 @@ static void btif_dm_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl)
         }
     }
 
+    // We could have received a new link key without going through the pairing flow.
+    // If so, we don't want to perform SDP or any other operations on the authenticated
+    // device.
+    if (!bdaddr_equals(p_auth_cmpl->bd_addr, pairing_cb.bd_addr)) {
+      char address[32];
+      bdaddr_to_string(&p_auth_cmpl->bd_addr, address, sizeof(address));
+      LOG_INFO("%s skipping SDP since we did not initiate pairing to %s.", __func__, address);
+      return;
+    }
+
     // Skip SDP for certain  HID Devices
     if (p_auth_cmpl->success)
     {
index d5470d7..3ce6e07 100644 (file)
@@ -1053,7 +1053,7 @@ static bt_status_t cops_response(const char *cops, bt_bdaddr_t *bd_addr)
         tBTA_AG_RES_DATA    ag_res;
 
         /* Format the response */
-        sprintf (ag_res.str, "0,0,\"%s\"", cops);
+        sprintf (ag_res.str, "0,0,\"%.16s\"", cops);
         ag_res.ok_flag = BTA_AG_OK_DONE;
 
         BTA_AgResult (btif_hf_cb[idx].handle, BTA_AG_COPS_RES, &ag_res);
index b6f3f0c..272a033 100644 (file)
@@ -40,6 +40,8 @@
 #include <sys/time.h>
 #include <errno.h>
 
+#define LOG_TAG "BTIF-MEDIA"
+
 #include "bt_target.h"
 #include "osi/include/fixed_queue.h"
 #include "gki.h"
@@ -151,8 +153,10 @@ enum {
 #define BTIF_MEDIA_BITRATE_STEP 5
 #endif
 
-/* Middle quality quality setting @ 44.1 khz */
-#define DEFAULT_SBC_BITRATE 328
+#ifndef BTIF_A2DP_DEFAULT_BITRATE
+/* High quality quality setting @ 44.1 khz */
+#define BTIF_A2DP_DEFAULT_BITRATE 328
+#endif
 
 #ifndef BTIF_A2DP_NON_EDR_MAX_RATE
 #define BTIF_A2DP_NON_EDR_MAX_RATE 229
@@ -372,6 +376,8 @@ static const char* dump_a2dp_ctrl_event(UINT8 event)
         CASE_RETURN_STR(A2DP_CTRL_CMD_START)
         CASE_RETURN_STR(A2DP_CTRL_CMD_STOP)
         CASE_RETURN_STR(A2DP_CTRL_CMD_SUSPEND)
+        CASE_RETURN_STR(A2DP_CTRL_CMD_OFFLOAD_START)
+
         default:
             return "UNKNOWN MSG ID";
     }
@@ -531,6 +537,10 @@ static void btif_recv_ctrl_data(void)
             break;
         }
 
+        case A2DP_CTRL_CMD_OFFLOAD_START:
+                btif_dispatch_sm_event(BTIF_AV_OFFLOAD_START_REQ_EVT, NULL, 0);
+            break;
+
         default:
             APPL_TRACE_ERROR("UNSUPPORTED CMD (%d)", cmd);
             a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
@@ -615,7 +625,7 @@ static void btif_a2dp_data_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event)
 
 static UINT16 btif_media_task_get_sbc_rate(void)
 {
-    UINT16 rate = DEFAULT_SBC_BITRATE;
+    UINT16 rate = BTIF_A2DP_DEFAULT_BITRATE;
 
     /* restrict bitrate if a2dp link is non-edr */
     if (!btif_av_is_peer_edr())
@@ -801,9 +811,9 @@ void btif_a2dp_setup_codec(void)
     GKI_disable();
 
     /* for now hardcode 44.1 khz 16 bit stereo PCM format */
-    media_feeding.cfg.pcm.sampling_freq = 44100;
-    media_feeding.cfg.pcm.bit_per_sample = 16;
-    media_feeding.cfg.pcm.num_channel = 2;
+    media_feeding.cfg.pcm.sampling_freq = BTIF_A2DP_SRC_SAMPLING_RATE;
+    media_feeding.cfg.pcm.bit_per_sample = BTIF_A2DP_SRC_BIT_DEPTH;
+    media_feeding.cfg.pcm.num_channel = BTIF_A2DP_SRC_NUM_CHANNELS;
     media_feeding.format = BTIF_AV_CODEC_PCM;
 
     if (bta_av_co_audio_set_codec(&media_feeding, &status))
@@ -1080,6 +1090,38 @@ void btif_a2dp_on_suspended(tBTA_AV_SUSPEND *p_av)
     btif_media_task_stop_aa_req();
 }
 
+
+/*****************************************************************************
+**
+** Function        btif_a2dp_on_offload_started
+**
+** Description
+**
+** Returns
+**
+*******************************************************************************/
+void btif_a2dp_on_offload_started(tBTA_AV_STATUS status)
+{
+    tA2DP_CTRL_ACK ack;
+    APPL_TRACE_EVENT("%s status %d", __func__, status);
+
+    switch (status) {
+        case BTA_AV_SUCCESS:
+            ack = A2DP_CTRL_ACK_SUCCESS;
+            break;
+
+        case BTA_AV_FAIL_RESOURCES:
+            APPL_TRACE_ERROR("%s FAILED UNSUPPORTED", __func__);
+            ack = A2DP_CTRL_ACK_UNSUPPORTED;
+            break;
+        default:
+            APPL_TRACE_ERROR("%s FAILED", __func__);
+            ack = A2DP_CTRL_ACK_FAILURE;
+            break;
+    }
+    a2dp_cmd_acknowledge(ack);
+}
+
 /* when true media task discards any rx frames */
 void btif_a2dp_set_rx_flush(BOOLEAN enable)
 {
index 15fc9cf..6a7bc6a 100644 (file)
@@ -333,11 +333,13 @@ void handle_rc_features()
         rc_features |= BTRC_FEAT_BROWSE;
     }
 
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
     if ( (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL) &&
          (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG))
     {
         rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
     }
+#endif
 
     if (btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)
     {
index 633b222..0a02b36 100644 (file)
@@ -243,7 +243,8 @@ void *GKI_getpoolbuf (UINT8 pool_id)
 *******************************************************************************/
 void GKI_freebuf (void *p_buf)
 {
-  osi_free((BUFFER_HDR_T *)p_buf - 1);
+  if (p_buf)
+    osi_free((BUFFER_HDR_T *)p_buf - 1);
 }
 
 
index af87285..8397056 100644 (file)
@@ -17,7 +17,8 @@ LOCAL_SRC_FILES := \
     src/hci_packet_parser.c \
     src/low_power_manager.c \
     src/packet_fragmenter.c \
-    src/vendor.c
+    src/vendor.c \
+    EventLogTags.logtags
 
 ifeq ($(BLUETOOTH_HCI_USE_MCT),true)
 LOCAL_CFLAGS += -DHCI_USE_MCT
@@ -35,6 +36,7 @@ LOCAL_C_INCLUDES += \
     $(LOCAL_PATH)/../osi/include \
     $(LOCAL_PATH)/../stack/include \
     $(LOCAL_PATH)/../utils/include \
+    $(LOCAL_PATH)/../bta/include \
     $(bdroid_C_INCLUDES)
 
 LOCAL_MODULE := libbt-hci
@@ -74,7 +76,7 @@ LOCAL_SRC_FILES := \
 LOCAL_CFLAGS := -Wall -Werror $(bdroid_CFLAGS)
 LOCAL_MODULE := net_test_hci
 LOCAL_MODULE_TAGS := tests
-LOCAL_SHARED_LIBRARIES := liblog libdl
+LOCAL_SHARED_LIBRARIES := liblog libdl libpower
 LOCAL_STATIC_LIBRARIES := libbt-hci libosi libcutils libbtcore
 
 include $(BUILD_NATIVE_TEST)
diff --git a/hci/EventLogTags.logtags b/hci/EventLogTags.logtags
new file mode 100644 (file)
index 0000000..fb8b83e
--- /dev/null
@@ -0,0 +1,36 @@
+# The entries in this file map a sparse set of log tag numbers to tag names.
+# This is installed on the device, in /system/etc, and parsed by logcat.
+#
+# Tag numbers are decimal integers, from 0 to 2^31.  (Let's leave the
+# negative values alone for now.)
+#
+# Tag names are one or more ASCII letters and numbers or underscores, i.e.
+# "[A-Z][a-z][0-9]_".  Do not include spaces or punctuation (the former
+# impacts log readability, the latter makes regex searches more annoying).
+#
+# Tag numbers and names are separated by whitespace.  Blank lines and lines
+# starting with '#' are ignored.
+#
+# Optionally, after the tag names can be put a description for the value(s)
+# of the tag. Description are in the format
+#    (<name>|data type[|data unit])
+# Multiple values are separated by commas.
+#
+# The data type is a number from the following values:
+# 1: int
+# 2: long
+# 3: string
+# 4: list
+#
+# The data unit is a number taken from the following list:
+# 1: Number of objects
+# 2: Number of bytes
+# 3: Number of milliseconds
+# 4: Number of allocations
+# 5: Id
+# 6: Percent
+# Default value for data of type int/long is 2 (bytes).
+#
+# TODO: generate ".java" and ".h" files with integer constants from this file.
+
+1010000 bt_hci_timeout (opcode|1)
index 65d448b..b4396ea 100644 (file)
@@ -167,6 +167,35 @@ typedef enum {
  *      specific epilog process once it has been done.
  */
     BT_VND_OP_EPILOG,
+
+/*  [operation]
+ *      Call to the vendor module so that it can perform all vendor-specific
+ *      operations to start offloading a2dp media encode & tx.
+ *  [input param]
+ *      pointer to bt_vendor_op_a2dp_offload_start_t containing elements
+ *      required for VND FW to setup a2dp offload.
+ *  [return]
+ *      0  - default, dont care.
+ *  [callback]
+ *      Must call a2dp_offload_start_cb to notify the stack of the
+ *      completion of vendor specific setup process once it has been done.
+ */
+    BT_VND_OP_A2DP_OFFLOAD_START,
+
+/*  [operation]
+ *      Call to the vendor module so that it can perform all vendor-specific
+ *      operations to suspend offloading a2dp media encode & tx.
+ *  [input param]
+ *      pointer to bt_vendor_op_a2dp_offload_t containing elements
+ *      required for VND FW to setup a2dp offload.
+ *  [return]
+ *      0  - default, dont care.
+ *  [callback]
+ *      Must call a2dp_offload_cb to notify the stack of the
+ *      completion of vendor specific setup process once it has been done.
+ */
+    BT_VND_OP_A2DP_OFFLOAD_STOP,
+
 } bt_vendor_opcode_t;
 
 /** Power on/off control states */
@@ -287,6 +316,8 @@ typedef void (*tINT_CMD_CBACK)(void *p_mem);
  */
 typedef uint8_t (*cmd_xmit_cb)(uint16_t opcode, void *p_buf, tINT_CMD_CBACK p_cback);
 
+typedef void (*cfg_a2dp_cb)(bt_vendor_op_result_t result, bt_vendor_opcode_t op, uint8_t bta_av_handle);
+
 typedef struct {
     /** set to sizeof(bt_vendor_callbacks_t) */
     size_t         size;
@@ -319,8 +350,25 @@ typedef struct {
 
     /* notifies caller completion of epilog process */
     cfg_result_cb epilog_cb;
+
+    /* notifies status of a2dp offload cmd's */
+    cfg_a2dp_cb a2dp_offload_cb;
 } bt_vendor_callbacks_t;
 
+/** A2DP offload request */
+typedef struct {
+    uint8_t   bta_av_handle;                 /* BTA_AV Handle for callbacks */
+    uint16_t  xmit_quota;                    /* Total ACL quota for light stack */
+    uint16_t  acl_data_size;                 /* Max ACL data size across HCI transport */
+    uint16_t  stream_mtu;
+    uint16_t  local_cid;
+    uint16_t  remote_cid;
+    uint16_t  lm_handle;
+    uint8_t   is_flushable;                  /* TRUE if flushable channel */
+    uint32_t  stream_source;
+    uint8_t   codec_info[10];                /* Codec capabilities array */
+} bt_vendor_op_a2dp_offload_t;
+
 /*
  * Bluetooth Host/Controller VENDOR Interface
  */
index 3181e62..e147b23 100644 (file)
@@ -39,7 +39,10 @@ typedef enum {
   VENDOR_CONFIGURE_FIRMWARE   = BT_VND_OP_FW_CFG,
   VENDOR_CONFIGURE_SCO        = BT_VND_OP_SCO_CFG,
   VENDOR_SET_LPM_MODE         = BT_VND_OP_LPM_SET_MODE,
-  VENDOR_DO_EPILOG            = BT_VND_OP_EPILOG
+  VENDOR_DO_EPILOG            = BT_VND_OP_EPILOG,
+  VENDOR_A2DP_OFFLOAD_START   = BT_VND_OP_A2DP_OFFLOAD_START,
+  VENDOR_A2DP_OFFLOAD_STOP    = BT_VND_OP_A2DP_OFFLOAD_STOP,
+  VENDOR_LAST_OP
 } vendor_async_opcode_t;
 
 typedef void (*vendor_cb)(bool success);
index 55efc1b..6b5d6c5 100644 (file)
@@ -40,19 +40,24 @@ void btsnoop_mem_capture(const BT_HDR *packet) {
   switch (type) {
     case BT_EVT_TO_LM_HCI_CMD:
       if (packet->len > 2)
-        length = data[2] + 4;
+        length = data[2] + 3;
       break;
 
     case BT_EVT_TO_BTU_HCI_EVT:
       if (packet->len > 1)
-        length = data[1] + 3;
+        length = data[1] + 2;
       break;
 
-    // Ignore data for privacy
     case BT_EVT_TO_LM_HCI_ACL:
-    case BT_EVT_TO_LM_HCI_SCO:
     case BT_EVT_TO_BTU_HCI_ACL:
+      if (packet->len > 3)
+        length = (data[2] | (data[3] << 8)) + 4;
+      break;
+
+    case BT_EVT_TO_LM_HCI_SCO:
     case BT_EVT_TO_BTU_HCI_SCO:
+      if (packet->len > 2)
+        length = data[2] + 3;
       break;
   }
 
index 5138ce6..ef9f74f 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <assert.h>
 #include <cutils/properties.h>
+#include <hardware_legacy/power.h>
 #include <string.h>
 #include <signal.h>
 #include <string.h>
@@ -56,6 +57,8 @@ bt_bdaddr_t btif_local_bd_addr;
 #define PREAMBLE_BUFFER_SIZE 4 // max preamble size, ACL
 #define RETRIEVE_ACL_LENGTH(preamble) ((((preamble)[3]) << 8) | (preamble)[2])
 
+#define BT_HCI_TIMEOUT_TAG_NUM 1010000
+
 static const uint8_t preamble_sizes[] = {
   HCI_COMMAND_PREAMBLE_SIZE,
   HCI_ACL_PREAMBLE_SIZE,
@@ -139,6 +142,9 @@ static packet_receive_data_t incoming_packets[INBOUND_PACKET_TYPE_COUNT];
 // The hand-off point for data going to a higher layer, set by the higher layer
 static fixed_queue_t *upwards_data_queue;
 
+// Wake lock to prevent sleep mode during bt adapter initialization.
+static const char *WAKE_LOCK_ID = "bt_adapter_init_wakelock";
+
 static future_t *shut_down();
 
 static void event_finish_startup(void *context);
@@ -188,6 +194,12 @@ static future_t *start_up(void) {
     goto error;
   }
 
+  // Prevent system from entering suspend mode during bt adapter initialization.
+  int status = acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
+  if (status != (int) strlen(WAKE_LOCK_ID)) {
+    LOG_ERROR("%s unable to acquire wake lock: %d", __func__, status);
+    goto error;
+  }
   // Make sure we run in a bounded amount of time
   non_repeating_timer_restart(startup_timer);
 
@@ -274,6 +286,8 @@ error:;
 static future_t *shut_down() {
   LOG_INFO("%s", __func__);
 
+  release_wake_lock(WAKE_LOCK_ID);
+
   hci_inject->close();
 
   if (thread) {
@@ -407,12 +421,17 @@ static void firmware_config_callback(UNUSED_ATTR bool success) {
   firmware_is_configured = true;
   non_repeating_timer_cancel(startup_timer);
 
+  release_wake_lock(WAKE_LOCK_ID);
+
   future_ready(startup_future, FUTURE_SUCCESS);
   startup_future = NULL;
 }
 
 static void startup_timer_expired(UNUSED_ATTR void *context) {
   LOG_ERROR("%s", __func__);
+
+  release_wake_lock(WAKE_LOCK_ID);
+
   future_ready(startup_future, FUTURE_FAIL);
   startup_future = NULL;
 }
@@ -514,6 +533,7 @@ static void command_timed_out(UNUSED_ATTR void *context) {
     // We shouldn't try to recover the stack from this command timeout.
     // If it's caused by a software bug, fix it. If it's a hardware bug, fix it.
     LOG_ERROR("%s hci layer timeout waiting for response to a command. opcode: 0x%x", __func__, wait_entry->opcode);
+    LOG_EVENT_INT(BT_HCI_TIMEOUT_TAG_NUM, wait_entry->opcode);
   }
 
   LOG_ERROR("%s restarting the bluetooth process.", __func__);
index 2e220e4..21153c0 100644 (file)
 
 #include "buffer_allocator.h"
 #include "bt_vendor_lib.h"
+#include "bta_av_api.h"
 #include "osi/include/osi.h"
 #include "osi/include/log.h"
 #include "vendor.h"
 
-#define LAST_VENDOR_OPCODE_VALUE VENDOR_DO_EPILOG
 
 static const char *VENDOR_LIBRARY_NAME = "libbt-vendor.so";
 static const char *VENDOR_LIBRARY_SYMBOL_NAME = "BLUETOOTH_VENDOR_LIB_INTERFACE";
@@ -35,7 +35,7 @@ static const char *VENDOR_LIBRARY_SYMBOL_NAME = "BLUETOOTH_VENDOR_LIB_INTERFACE"
 static const vendor_t interface;
 static const allocator_t *buffer_allocator;
 static const hci_t *hci;
-static vendor_cb callbacks[LAST_VENDOR_OPCODE_VALUE + 1];
+static vendor_cb callbacks[VENDOR_LAST_OP];
 
 static void *lib_handle;
 static bt_vendor_interface_t *lib_interface;
@@ -186,6 +186,16 @@ static void epilog_cb(bt_vendor_op_result_t result) {
   callback(result == BT_VND_OP_RESULT_SUCCESS);
 }
 
+// Called back from vendor library when the a2dp offload machine has to report status of
+// an a2dp offload command.
+static void a2dp_offload_cb(bt_vendor_op_result_t result, bt_vendor_opcode_t op, uint8_t bta_av_handle) {
+  tBTA_AV_STATUS status = (result == BT_VND_OP_RESULT_SUCCESS) ? BTA_AV_SUCCESS : BTA_AV_FAIL_RESOURCES;
+
+  if (op == BT_VND_OP_A2DP_OFFLOAD_START) {
+      BTA_AvOffloadStartRsp(bta_av_handle, status);
+  }
+}
+
 static const bt_vendor_callbacks_t lib_callbacks = {
   sizeof(lib_callbacks),
   firmware_config_cb,
@@ -195,7 +205,8 @@ static const bt_vendor_callbacks_t lib_callbacks = {
   buffer_alloc_cb,
   buffer_free_cb,
   transmit_cb,
-  epilog_cb
+  epilog_cb,
+  a2dp_offload_cb
 };
 
 static const vendor_t interface = {
index 16605c6..e1f6f55 100644 (file)
 #define BTA_AV_CO_CP_SCMS_T  FALSE
 #endif
 
+#ifndef BTIF_A2DP_SRC_SAMPLING_RATE
+#define BTIF_A2DP_SRC_SAMPLING_RATE 44100
+#endif
+
+#ifndef BTIF_A2DP_SRC_BIT_DEPTH
+#define BTIF_A2DP_SRC_BIT_DEPTH 16
+#endif
+
+#ifndef BTIF_A2DP_SRC_NUM_CHANNELS
+#define BTIF_A2DP_SRC_NUM_CHANNELS 2
+#endif
+
 /* This feature is used to eanble interleaved scan*/
 #ifndef BTA_HOST_INTERLEAVE_SEARCH
 #define BTA_HOST_INTERLEAVE_SEARCH FALSE
index 52dc2cf..724ed1f 100644 (file)
@@ -89,7 +89,7 @@ LOCAL_SRC_FILES := \
 LOCAL_CFLAGS := -Wall -UNDEBUG
 LOCAL_MODULE := net_test_osi
 LOCAL_MODULE_TAGS := tests
-LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SHARED_LIBRARIES := liblog libpower
 LOCAL_STATIC_LIBRARIES := libosi
 
 include $(BUILD_NATIVE_TEST)
index aa1672d..697cbb3 100644 (file)
@@ -21,6 +21,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <hardware/bluetooth.h>
+#include <hardware_legacy/power.h>
 #include <inttypes.h>
 #include <malloc.h>
 #include <string.h>
@@ -65,6 +66,7 @@ extern bt_os_callouts_t *bt_os_callouts;
 // unit tests to run faster. It should not be modified by production code.
 int64_t TIMER_INTERVAL_FOR_WAKELOCK_IN_MS = 3000;
 static const clockid_t CLOCK_ID = CLOCK_BOOTTIME;
+static const clockid_t CLOCK_ID_ALARM = CLOCK_BOOTTIME_ALARM;
 static const char *WAKE_LOCK_ID = "bluedroid_timer";
 
 // This mutex ensures that the |alarm_set|, |alarm_cancel|, and alarm callback
@@ -73,6 +75,7 @@ static const char *WAKE_LOCK_ID = "bluedroid_timer";
 static pthread_mutex_t monitor;
 static list_t *alarms;
 static timer_t timer;
+static timer_t wakeup_timer;
 static bool timer_set;
 
 // All alarm callbacks are dispatched from |callback_thread|
@@ -87,6 +90,7 @@ static void schedule_next_instance(alarm_t *alarm, bool force_reschedule);
 static void reschedule_root_alarm(void);
 static void timer_callback(void *data);
 static void callback_dispatch(void *context);
+static bool timer_create_internal(const clockid_t clock_id, timer_t *timer);
 
 alarm_t *alarm_new(void) {
   // Make sure we have a list we can insert alarms into.
@@ -218,39 +222,65 @@ void alarm_cleanup(void) {
 static bool lazy_initialize(void) {
   assert(alarms == NULL);
 
+  // timer_t doesn't have an invalid value so we must track whether
+  // the |timer| variable is valid ourselves.
+  bool timer_initialized = false;
+  bool wakeup_timer_initialized = false;
+
   pthread_mutex_init(&monitor, NULL);
 
   alarms = list_new(NULL);
   if (!alarms) {
     LOG_ERROR("%s unable to allocate alarm list.", __func__);
-    return false;
+    goto error;
   }
 
-  struct sigevent sigevent;
-  memset(&sigevent, 0, sizeof(sigevent));
-  sigevent.sigev_notify = SIGEV_THREAD;
-  sigevent.sigev_notify_function = (void (*)(union sigval))timer_callback;
-  if (timer_create(CLOCK_ID, &sigevent, &timer) == -1) {
-    LOG_ERROR("%s unable to create timer: %s", __func__, strerror(errno));
-    return false;
-  }
+  if (!timer_create_internal(CLOCK_ID, &timer))
+    goto error;
+  timer_initialized = true;
+
+  if (!timer_create_internal(CLOCK_ID_ALARM, &wakeup_timer))
+    goto error;
+  wakeup_timer_initialized = true;
 
   alarm_expired = semaphore_new(0);
   if (!alarm_expired) {
     LOG_ERROR("%s unable to create alarm expired semaphore", __func__);
-    return false;
+    goto error;
   }
 
   callback_thread_active = true;
   callback_thread = thread_new("alarm_callbacks");
   if (!callback_thread) {
     LOG_ERROR("%s unable to create alarm callback thread.", __func__);
-    return false;
+    goto error;
   }
 
   thread_set_priority(callback_thread, CALLBACK_THREAD_PRIORITY_HIGH);
   thread_post(callback_thread, callback_dispatch, NULL);
   return true;
+
+error:
+  thread_free(callback_thread);
+  callback_thread = NULL;
+
+  callback_thread_active = false;
+
+  semaphore_free(alarm_expired);
+  alarm_expired = NULL;
+
+  if (wakeup_timer_initialized)
+    timer_delete(wakeup_timer);
+
+  if (timer_initialized)
+    timer_delete(timer);
+
+  list_free(alarms);
+  alarms = NULL;
+
+  pthread_mutex_destroy(&monitor);
+
+  return false;
 }
 
 static period_ms_t now(void) {
@@ -297,41 +327,65 @@ static void schedule_next_instance(alarm_t *alarm, bool force_reschedule) {
 
 // NOTE: must be called with monitor lock.
 static void reschedule_root_alarm(void) {
-  bool timer_was_set = timer_set;
   assert(alarms != NULL);
 
-  // If used in a zeroed state, disarms the timer
-  struct itimerspec wakeup_time;
-  memset(&wakeup_time, 0, sizeof(wakeup_time));
+  const bool timer_was_set = timer_set;
+
+  // If used in a zeroed state, disarms the timer.
+  struct itimerspec timer_time;
+  memset(&timer_time, 0, sizeof(timer_time));
 
   if (list_is_empty(alarms))
     goto done;
 
-  alarm_t *next = list_front(alarms);
-  int64_t next_expiration = next->deadline - now();
+  const alarm_t *next = list_front(alarms);
+  const int64_t next_expiration = next->deadline - now();
   if (next_expiration < TIMER_INTERVAL_FOR_WAKELOCK_IN_MS) {
     if (!timer_set) {
-      int status = bt_os_callouts->acquire_wake_lock(WAKE_LOCK_ID);
-      if (status != BT_STATUS_SUCCESS) {
+      int status = acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
+      if (status != (int) strlen(WAKE_LOCK_ID)) {
         LOG_ERROR("%s unable to acquire wake lock: %d", __func__, status);
         goto done;
       }
     }
 
+    timer_time.it_value.tv_sec = (next->deadline / 1000);
+    timer_time.it_value.tv_nsec = (next->deadline % 1000) * 1000000LL;
+
+    // It is entirely unsafe to call timer_settime(2) with a zeroed timerspec for
+    // timers with *_ALARM clock IDs. Although the man page states that the timer
+    // would be canceled, the current behavior (as of Linux kernel 3.17) is that
+    // the callback is issued immediately. The only way to cancel an *_ALARM timer
+    // is to delete the timer. But unfortunately, deleting and re-creating a timer
+    // is rather expensive; every timer_create(2) spawns a new thread. So we simply
+    // set the timer to fire at the largest possible time.
+    //
+    // If we've reached this code path, we're going to grab a wake lock and wait for
+    // the next timer to fire. In that case, there's no reason to have a pending wakeup
+    // timer so we simply cancel it.
+    struct itimerspec end_of_time;
+    memset(&end_of_time, 0, sizeof(end_of_time));
+    end_of_time.it_value.tv_sec = (time_t)((1LL << (sizeof(time_t) * 8 - 1)) - 1);
+    timer_settime(wakeup_timer, TIMER_ABSTIME, &end_of_time, NULL);
+  } else {
+    // WARNING: do not attempt to use relative timers with *_ALARM clock IDs
+    // in kernels before 3.17 unless you have the following patch:
+    // https://lkml.org/lkml/2014/7/7/576
+    struct itimerspec wakeup_time;
+    memset(&wakeup_time, 0, sizeof(wakeup_time));
     wakeup_time.it_value.tv_sec = (next->deadline / 1000);
     wakeup_time.it_value.tv_nsec = (next->deadline % 1000) * 1000000LL;
-  } else {
-    if (!bt_os_callouts->set_wake_alarm(next_expiration, true, timer_callback, NULL))
-      LOG_ERROR("%s unable to set wake alarm for %" PRId64 "ms.", __func__, next_expiration);
+    if (timer_settime(wakeup_timer, TIMER_ABSTIME, &wakeup_time, NULL) == -1)
+      LOG_ERROR("%s unable to set wakeup timer: %s", __func__, strerror(errno));
   }
 
 done:
-  timer_set = wakeup_time.it_value.tv_sec != 0 || wakeup_time.it_value.tv_nsec != 0;
+  timer_set = timer_time.it_value.tv_sec != 0 || timer_time.it_value.tv_nsec != 0;
   if (timer_was_set && !timer_set) {
-    bt_os_callouts->release_wake_lock(WAKE_LOCK_ID);
+    release_wake_lock(WAKE_LOCK_ID);
   }
 
-  if (timer_settime(timer, TIMER_ABSTIME, &wakeup_time, NULL) == -1)
+  if (timer_settime(timer, TIMER_ABSTIME, &timer_time, NULL) == -1)
     LOG_ERROR("%s unable to set timer: %s", __func__, strerror(errno));
 
   // If next expiration was in the past (e.g. short timer that got context switched)
@@ -405,3 +459,18 @@ static void callback_dispatch(UNUSED_ATTR void *context) {
 
   LOG_DEBUG("%s Callback thread exited", __func__);
 }
+
+static bool timer_create_internal(const clockid_t clock_id, timer_t *timer) {
+  assert(timer != NULL);
+
+  struct sigevent sigevent;
+  memset(&sigevent, 0, sizeof(sigevent));
+  sigevent.sigev_notify = SIGEV_THREAD;
+  sigevent.sigev_notify_function = (void (*)(union sigval))timer_callback;
+  if (timer_create(clock_id, &sigevent, timer) == -1) {
+    LOG_ERROR("%s unable to create timer with clock %d: %s", __func__, clock_id, strerror(errno));
+    return false;
+  }
+
+  return true;
+}
index 11a5baf..4dd9c19 100644 (file)
@@ -268,20 +268,34 @@ bool config_save(const config_t *config, const char *filename) {
 
   for (const list_node_t *node = list_begin(config->sections); node != list_end(config->sections); node = list_next(node)) {
     const section_t *section = (const section_t *)list_node(node);
-    fprintf(fp, "[%s]\n", section->name);
+    if (fprintf(fp, "[%s]\n", section->name) < 0) {
+      LOG_ERROR("%s unable to write to file '%s': %s", __func__, temp_filename, strerror(errno));
+      goto error;
+    }
 
     for (const list_node_t *enode = list_begin(section->entries); enode != list_end(section->entries); enode = list_next(enode)) {
       const entry_t *entry = (const entry_t *)list_node(enode);
-      fprintf(fp, "%s = %s\n", entry->key, entry->value);
+      if (fprintf(fp, "%s = %s\n", entry->key, entry->value) < 0) {
+        LOG_ERROR("%s unable to write to file '%s': %s", __func__, temp_filename, strerror(errno));
+        goto error;
+      }
     }
 
     // Only add a separating newline if there are more sections.
-    if (list_next(node) != list_end(config->sections))
-      fputc('\n', fp);
+    if (list_next(node) != list_end(config->sections)) {
+      if (fputc('\n', fp) == EOF) {
+        LOG_ERROR("%s unable to write to file '%s': %s", __func__, temp_filename, strerror(errno));
+        goto error;
+      }
+    }
   }
 
-  fflush(fp);
-  fclose(fp);
+  if (fclose(fp) == EOF) {
+    LOG_ERROR("%s unable to close file '%s': %s", __func__, temp_filename, strerror(errno));
+    fp = NULL;
+    goto error;
+  }
+  fp = NULL;
 
   // Change the file's permissions to Read/Write by User and Group
   if (chmod(temp_filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1) {
@@ -298,6 +312,8 @@ bool config_save(const config_t *config, const char *filename) {
   return true;
 
 error:;
+  if (fp != NULL)
+    fclose(fp);
   unlink(temp_filename);
   osi_free(temp_filename);
   return false;
index ccb5dc6..09d0be5 100644 (file)
@@ -38,11 +38,6 @@ LOCAL_C_INCLUDES:= . \
 
 LOCAL_CFLAGS += $(bdroid_CFLAGS) -std=c99
 
-ifeq ($(BOARD_HAVE_BLUETOOTH_BCM),true)
-LOCAL_CFLAGS += \
-       -DBOARD_HAVE_BLUETOOTH_BCM
-endif
-
 LOCAL_SRC_FILES:= \
     ./a2dp/a2d_api.c \
     ./a2dp/a2d_sbc.c \
index dbdfc08..b1177bf 100644 (file)
@@ -179,6 +179,9 @@ void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8
     UINT16          result;
     tL2CAP_CFG_INFO cfg;
     tBTM_STATUS rc;
+#if defined(AVDT_DISABLE_3DH) && (AVDT_DISABLE_3DH == TRUE)
+    tACL_CONN *p_acl_cb;
+#endif
     UNUSED(psm);
 
     /* do we already have a control channel for this peer? */
@@ -202,6 +205,14 @@ void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8
             p_tbl->state = AVDT_AD_ST_SEC_ACP;
             p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_ACP;
 
+#if defined(AVDT_DISABLE_3DH) && (AVDT_DISABLE_3DH == TRUE)
+            p_acl_cb = btm_bda_to_acl(bd_addr, BT_TRANSPORT_BR_EDR);
+            btm_set_packet_types (p_acl_cb, (btm_cb.btm_acl_pkt_types_supported |
+                                             HCI_PKT_TYPES_MASK_NO_3_DH1 |
+                                             HCI_PKT_TYPES_MASK_NO_3_DH3 |
+                                             HCI_PKT_TYPES_MASK_NO_3_DH5));
+#endif
+
             /* Check the security */
             rc = btm_sec_mx_access_request (bd_addr, AVDT_PSM,
                 FALSE, BTM_SEC_PROTO_AVDT,
@@ -282,6 +293,9 @@ void avdt_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result)
     tAVDT_TC_TBL    *p_tbl;
     tL2CAP_CFG_INFO cfg;
     tAVDT_CCB *p_ccb;
+#if defined(AVDT_DISABLE_3DH) && (AVDT_DISABLE_3DH == TRUE)
+    tACL_CONN *p_acl_cb;
+#endif
 
     AVDT_TRACE_DEBUG("avdt_l2c_connect_cfm_cback lcid: %d, result: %d",
         lcid, result);
@@ -321,6 +335,15 @@ void avdt_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result)
                         p_tbl->lcid = lcid;
                         p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_INT;
 
+#if defined(AVDT_DISABLE_3DH) && (AVDT_DISABLE_3DH == TRUE)
+                        p_acl_cb = btm_bda_to_acl(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR);
+                        btm_set_packet_types (p_acl_cb,
+                                              (btm_cb.btm_acl_pkt_types_supported |
+                                               HCI_PKT_TYPES_MASK_NO_3_DH1 |
+                                               HCI_PKT_TYPES_MASK_NO_3_DH3 |
+                                               HCI_PKT_TYPES_MASK_NO_3_DH5));
+#endif
+
                         /* Check the security */
                         btm_sec_mx_access_request (p_ccb->peer_addr, AVDT_PSM,
                             TRUE, BTM_SEC_PROTO_AVDT,
index eb9e864..06694a2 100644 (file)
@@ -1847,9 +1847,9 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced)
             STREAM_TO_BDADDR   (peer_rpa, p);
         }
 
-        /* possiblly receive connection complete with resolvable random on
-           slave role while the device has been paired */
-        if (!match && role == HCI_ROLE_SLAVE && BTM_BLE_IS_RESOLVE_BDA(bda))
+        /* possiblly receive connection complete with resolvable random while
+           the device has been paired */
+        if (!match && BTM_BLE_IS_RESOLVE_BDA(bda))
         {
             btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_on_conn_cmpl, p_data);
         }
index 0189bda..46a15d0 100644 (file)
@@ -152,9 +152,9 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
         if (pin_length >= 16 ||
             key_type == BTM_LKEY_TYPE_AUTH_COMB ||
             key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256) {
-            // Set the fiag if the link key was made by using either a 16 digit
+            // Set the flag if the link key was made by using either a 16 digit
             // pin or MITM.
-            p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED;
+            p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED | BTM_SEC_LINK_KEY_AUTHED;
         }
     }
 
index 837dbc8..fc34f3f 100644 (file)
@@ -1067,6 +1067,18 @@ extern BOOLEAN L2CA_GetCurrentConfig (UINT16 lcid,
                                       tL2CAP_CFG_INFO **pp_our_cfg,  tL2CAP_CH_CFG_BITS *p_our_cfg_bits,
                                       tL2CAP_CFG_INFO **pp_peer_cfg, tL2CAP_CH_CFG_BITS *p_peer_cfg_bits);
 
+/*******************************************************************************
+**
+** Function     L2CA_GetConnectionConfig
+**
+** Description  This function polulates the mtu, remote cid & lm_handle for
+**              a given local L2CAP channel
+**
+** Returns      TRUE if successful
+**
+*******************************************************************************/
+extern BOOLEAN L2CA_GetConnectionConfig(UINT16 lcid, UINT16 *mtu, UINT16 *rcid, UINT16 *handle);
+
 #if (BLE_INCLUDED == TRUE)
 /*******************************************************************************
 **
diff --git a/stack/include/uipc_msg.h b/stack/include/uipc_msg.h
deleted file mode 100644 (file)
index 53cdccf..0000000
+++ /dev/null
@@ -1,568 +0,0 @@
-/******************************************************************************
- *
- *  Copyright (C) 1999-2012 Broadcom Corporation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at:
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This file contains sync message over UIPC
- *
- ******************************************************************************/
-
-#ifndef UIPC_MSG_H
-#define UIPC_MSG_H
-
-#include "bt_types.h"
-
-/****************************************************************************/
-/*                            UIPC version number: 1.0                      */
-/****************************************************************************/
-#define UIPC_VERSION_MAJOR  0x0001
-#define UIPC_VERSION_MINOR  0x0000
-
-
-/********************************
-
-    UIPC Management Messages
-
-********************************/
-
-/* tUIPC_STATUS codes*/
-enum
-{
-    UIPC_STATUS_SUCCESS,
-    UIPC_STATUS_FAIL
-};
-typedef UINT8 tUIPC_STATUS;
-
-/* op_code */
-#define UIPC_OPEN_REQ                   0x00
-#define UIPC_OPEN_RSP                   0x01
-#define UIPC_CLOSE_REQ                  0x02
-#define UIPC_CLOSE_RSP                  0x03
-
-/* Structure of UIPC_OPEN_REQ message */
-typedef struct
-{
-    UINT8               opcode;         /* UIPC_OPEN_REQ */
-} tUIPC_OPEN_REQ;
-#define UIPC_OPEN_REQ_MSGLEN        (1)
-
-/* Structure of UIPC_OPEN_RSP message */
-typedef struct
-{
-    UINT8               opcode;         /* UIPC_OPEN_RESP */
-    tUIPC_STATUS        status;         /* UIPC_STATUS */
-    UINT16              version_major;  /* UIPC_VERSION_MAJOR */
-    UINT16              version_minor;  /* UIPC_VERSION_MINOR */
-    UINT8               num_streams;    /* Number of simultaneous streams supported by the light stack */
-} tUIPC_OPEN_RSP;
-#define UIPC_OPEN_RSP_MSGLEN        (7)
-
-/* Structure of UIPC_CLOSE_REQ message */
-typedef struct t_uipc_close_req
-{
-    UINT8               opcode;         /* UIPC_CLOSE_REQ */
-} tUIPC_CLOSE_REQ;
-#define UIPC_CLOSE_REQ_MSGLEN       (1)
-
-/* Structure of UIPC_CLOSE_RSP message, only for BTC, full stack may ignore it */
-typedef struct t_uipc_close_rsp
-{
-    UINT8               opcode;         /* UIPC_CLOSE_RSP */
-} tUIPC_CLOSE_RSP;
-#define UIPC_CLOSE_RSP_MSGLEN       (1)
-
-/* UIPC management message structures */
-typedef union
-{
-    UINT8               opcode;
-    tUIPC_OPEN_REQ      open_req;
-    tUIPC_OPEN_RSP      open_resp;
-    tUIPC_CLOSE_REQ     close_req;
-} tUIPC_MSG;
-
-#define UIPC_MGMT_MSG_MAXLEN    (sizeof(tUIPC_MSG))
-
-#define IPC_LOG_MSG_LEN  100
-typedef struct t_uipc_log_msg
-{
-    UINT32              trace_set_mask;
-    UINT8               msg[IPC_LOG_MSG_LEN];
-} tUIPC_LOG_MSG;
-#define UIPC_LOG_MSGLEN       (IPC_LOG_MSG_LEN + 4)
-
-typedef struct
-{
-    UINT8   opcode;     /* A2DP_START_REQ */
-    UINT16  lcid;
-    UINT16  curr_mtu;
-}tA2DP_START_REQ;
-
-typedef struct
-{
-    UINT8   opcode;     /* A2DP_STOP_REQ */
-    UINT16  lcid;
-}tA2DP_STOP_REQ;
-
-typedef struct
-{
-    UINT8   opcode;     /* A2DP_SUSPEND_REQ */
-    UINT16  lcid;
-}tA2DP_SUSPEND_REQ;
-
-typedef struct
-{
-    UINT8   opcode;     /* A2DP_CLEANUP_REQ */
-    UINT16  lcid;
-    UINT16  curr_mtu;
-} tA2DP_CLEANUP_REQ;
-
-typedef struct
-{
-    UINT8   opcode;     /* A2DP_START_RESP, A2DP_STOP_RESP, A2DP_CLEANUP_RESP, A2DP_SUSPEND_RESP */
-    UINT16  lcid;
-}tA2DP_GENERIC_RESP;
-
-#define AUDIO_CODEC_NONE            0x0000
-#define AUDIO_CODEC_SBC_ENC         0x0001
-#define AUDIO_CODEC_SBC_DEC         0x0002
-#define AUDIO_CODEC_MP3_ENC         0x0004
-#define AUDIO_CODEC_MP3_DEC         0x0008
-#define AUDIO_CODEC_AAC_ENC         0x0010
-#define AUDIO_CODEC_AAC_DEC         0x0020
-#define AUDIO_CODEC_AAC_PLUS_ENC    0x0040
-#define AUDIO_CODEC_AAC_PLUS_DEC    0x0080
-#define AUDIO_CODEC_MP2_ENC         0x0100
-#define AUDIO_CODEC_MP2_DEC         0x0200
-#define AUDIO_CODEC_MP2_5_ENC       0x0400
-#define AUDIO_CODEC_MP2_5_DEC       0x0800
-
-typedef UINT16 tAUDIO_CODEC_TYPE;
-
-/* SBC CODEC Parameters */
-
-#define CODEC_INFO_SBC_SF_16K       0x00
-#define CODEC_INFO_SBC_SF_32K       0x01
-#define CODEC_INFO_SBC_SF_44K       0x02
-#define CODEC_INFO_SBC_SF_48K       0x03
-
-#define CODEC_INFO_SBC_BLOCK_4      0x00
-#define CODEC_INFO_SBC_BLOCK_8      0x01
-#define CODEC_INFO_SBC_BLOCK_12     0x02
-#define CODEC_INFO_SBC_BLOCK_16     0x03
-
-#define CODEC_INFO_SBC_CH_MONO      0x00
-#define CODEC_INFO_SBC_CH_DUAL      0x01
-#define CODEC_INFO_SBC_CH_STEREO    0x02
-#define CODEC_INFO_SBC_CH_JS        0x03
-
-#define CODEC_INFO_SBC_ALLOC_LOUDNESS   0x00
-#define CODEC_INFO_SBC_ALLOC_SNR        0x01
-
-#define CODEC_INFO_SBC_SUBBAND_4    0x00
-#define CODEC_INFO_SBC_SUBBAND_8    0x01
-
-/* MPEG audio version ID */
-#define CODEC_INFO_MP25_ID              0x00
-#define CODEC_INFO_RESERVE              0x01
-#define CODEC_INFO_MP2_ID               0x02
-#define CODEC_INFO_MP3_ID               0x03
-
-#define CODEC_INFO_MP3_PROTECTION_ON    0x00
-#define CODEC_INFO_MP3_PROTECTION_OFF   0x01
-
-#define CODEC_INFO_MP3_BR_IDX_FREE      0x00
-#define CODEC_INFO_MP3_BR_IDX_32K       0x01
-#define CODEC_INFO_MP3_BR_IDX_40K       0x02
-#define CODEC_INFO_MP3_BR_IDX_48K       0x03
-#define CODEC_INFO_MP3_BR_IDX_56K       0x04
-#define CODEC_INFO_MP3_BR_IDX_64K       0x05
-#define CODEC_INFO_MP3_BR_IDX_80K       0x06
-#define CODEC_INFO_MP3_BR_IDX_96K       0x07
-#define CODEC_INFO_MP3_BR_IDX_112K      0x08
-#define CODEC_INFO_MP3_BR_IDX_128K      0x09
-#define CODEC_INFO_MP3_BR_IDX_160K      0x0A
-#define CODEC_INFO_MP3_BR_IDX_192K      0x0B
-#define CODEC_INFO_MP3_BR_IDX_224K      0x0C
-#define CODEC_INFO_MP3_BR_IDX_256K      0x0D
-#define CODEC_INFO_MP3_BR_IDX_320K      0x0E
-
-#define CODEC_INFO_MP3_SF_44K           0x00
-#define CODEC_INFO_MP3_SF_48K           0x01
-#define CODEC_INFO_MP3_SF_32K           0x02
-
-#define CODEC_INFO_MP3_MODE_STEREO      0x00
-#define CODEC_INFO_MP3_MODE_JS          0x01
-#define CODEC_INFO_MP3_MODE_DUAL        0x02
-#define CODEC_INFO_MP3_MODE_SINGLE      0x03
-
-/* layer 3, type of joint stereo coding method (intensity and ms) */
-#define CODEC_INFO_MP3_MODE_EXT_OFF_OFF 0x00
-#define CODEC_INFO_MP3_MODE_EXT_ON_OFF  0x01
-#define CODEC_INFO_MP3_MODE_EXT_OFF_ON  0x02
-#define CODEC_INFO_MP3_MODE_EXT_ON_ON   0x03
-
-
-#define CODEC_INFO_MP2_PROTECTION_ON    0x00
-#define CODEC_INFO_MP2_PROTECTION_OFF   0x01
-
-#define CODEC_INFO_MP2_BR_IDX_FREE      0x00
-#define CODEC_INFO_MP2_BR_IDX_8K        0x01
-#define CODEC_INFO_MP2_BR_IDX_16K       0x02
-#define CODEC_INFO_MP2_BR_IDX_24K       0x03
-#define CODEC_INFO_MP2_BR_IDX_32K       0x04
-#define CODEC_INFO_MP2_BR_IDX_40K       0x05
-#define CODEC_INFO_MP2_BR_IDX_48K       0x06
-#define CODEC_INFO_MP2_BR_IDX_56K       0x07
-#define CODEC_INFO_MP2_BR_IDX_64K       0x08
-#define CODEC_INFO_MP2_BR_IDX_80K       0x09
-#define CODEC_INFO_MP2_BR_IDX_96K       0x0A
-#define CODEC_INFO_MP2_BR_IDX_112K      0x0B
-#define CODEC_INFO_MP2_BR_IDX_128K      0x0C
-#define CODEC_INFO_MP2_BR_IDX_144K      0x0D
-#define CODEC_INFO_MP2_BR_IDX_160K      0x0E
-
-#define CODEC_INFO_MP2_SF_22K           0x00
-#define CODEC_INFO_MP2_SF_24K           0x01
-#define CODEC_INFO_MP2_SF_16K           0x02
-
-#define CODEC_INFO_MP2_MODE_STEREO      0x00
-#define CODEC_INFO_MP2_MODE_JS          0x01
-#define CODEC_INFO_MP2_MODE_DUAL        0x02
-#define CODEC_INFO_MP2_MODE_SINGLE      0x03
-
-/* layer 3, type of joint stereo coding method (intensity and ms) */
-#define CODEC_INFO_MP2_MODE_EXT_OFF_OFF 0x00
-#define CODEC_INFO_MP2_MODE_EXT_ON_OFF  0x01
-#define CODEC_INFO_MP2_MODE_EXT_OFF_ON  0x02
-#define CODEC_INFO_MP2_MODE_EXT_ON_ON   0x03
-
-#define CODEC_INFO_MP2_SAMPLE_PER_FRAME     576
-
-/* mpeg 2.5 layer 3 decoder */
-
-#define CODEC_INFO_MP25_PROTECTION_ON   0x00
-#define CODEC_INFO_MP25_PROTECTION_OFF  0x01
-
-#define CODEC_INFO_MP25_BR_IDX_FREE     0x00
-#define CODEC_INFO_MP25_BR_IDX_8K       0x01
-#define CODEC_INFO_MP25_BR_IDX_16K      0x02
-#define CODEC_INFO_MP25_BR_IDX_24K      0x03
-#define CODEC_INFO_MP25_BR_IDX_32K      0x04
-#define CODEC_INFO_MP25_BR_IDX_40K      0x05
-#define CODEC_INFO_MP25_BR_IDX_48K      0x06
-#define CODEC_INFO_MP25_BR_IDX_56K      0x07
-#define CODEC_INFO_MP25_BR_IDX_64K      0x08
-#define CODEC_INFO_MP25_BR_IDX_80K      0x09
-#define CODEC_INFO_MP25_BR_IDX_96K      0x0A
-#define CODEC_INFO_MP25_BR_IDX_112K     0x0B
-#define CODEC_INFO_MP25_BR_IDX_128K     0x0C
-#define CODEC_INFO_MP25_BR_IDX_144K     0x0D
-#define CODEC_INFO_MP25_BR_IDX_160K     0x0E
-
-#define CODEC_INFO_MP25_SF_11K          0x00
-#define CODEC_INFO_MP25_SF_12K          0x01
-#define CODEC_INFO_MP25_SF_8K           0x02
-
-#define CODEC_INFO_MP25_MODE_STEREO     0x00
-#define CODEC_INFO_MP25_MODE_JS         0x01
-#define CODEC_INFO_MP25_MODE_DUAL       0x02
-#define CODEC_INFO_MP25_MODE_SINGLE     0x03
-
-/* layer 3, type of joint stereo coding method (intensity and ms) */
-#define CODEC_INFO_MP25_MODE_EXT_OFF_OFF 0x00
-#define CODEC_INFO_MP25_MODE_EXT_ON_OFF  0x01
-#define CODEC_INFO_MP25_MODE_EXT_OFF_ON  0x02
-#define CODEC_INFO_MP25_MODE_EXT_ON_ON   0x03
-
-#define CODEC_INFO_MP25_SAMPLE_PER_FRAME    576
-
-/* AAC/AAC+ CODEC Parameters */
-#define CODEC_INFO_AAC_SF_IDX_96K   0x0
-#define CODEC_INFO_AAC_SF_IDX_88K   0x1
-#define CODEC_INFO_AAC_SF_IDX_64K   0x2
-#define CODEC_INFO_AAC_SF_IDX_48K   0x3
-#define CODEC_INFO_AAC_SF_IDX_44K   0x4
-#define CODEC_INFO_AAC_SF_IDX_32K   0x5
-#define CODEC_INFO_AAC_SF_IDX_24K   0x6
-#define CODEC_INFO_AAC_SF_IDX_22K   0x7
-#define CODEC_INFO_AAC_SF_IDX_16K   0x8
-#define CODEC_INFO_AAC_SF_IDX_12K   0x9
-#define CODEC_INFO_AAC_SF_IDX_11K   0xA
-#define CODEC_INFO_AAC_SF_IDX_08K   0xB
-#define CODEC_INFO_AAC_SF_IDX_RESERVE   0xC
-
-#define CODEC_INFO_AAC_BR_RATE_48K  288000
-#define CODEC_INFO_AAC_BR_RATE_44K  264600
-#define CODEC_INFO_AAC_BR_RATE_32K  192000
-
-
-#define CODEC_INFO_AAC_1_CH           1         /*center front speaker */
-#define CODEC_INFO_AAC_2_CH           2         /*left, right front speaker */
-#define CODEC_INFO_AAC_3_CH           3         /*center front speaker, left right front speaker */
-#define CODEC_INFO_AAC_4_CH           4         /*center/rear front speaker, left/right front speaker */
-#define CODEC_INFO_AAC_5_CH           5         /*center, left, right front speaker, left/right surround */
-#define CODEC_INFO_AAC_6_CH           6         /*center, left, right front speaker, left/right surround, LFE */
-#define CODEC_INFO_AAC_7_CH           7         /*(left, right)center/left,right front speaker, left/right surround, LFE */
-
-
-typedef struct
-{
-    UINT8   sampling_freq;
-    UINT8   channel_mode;
-    UINT8   block_length;
-    UINT8   num_subbands;
-    UINT8   alloc_method;
-    UINT8   bitpool_size;   /* 2 - 250 */
-} tCODEC_INFO_SBC;
-
-typedef struct
-{
-    UINT8   ch_mode;
-    UINT8   sampling_freq;
-    UINT8   bitrate_index;  /* 0 - 14 */
-} tCODEC_INFO_MP3;
-
-typedef struct
-{
-    UINT8   ch_mode;
-    UINT8   sampling_freq;
-    UINT8   bitrate_index;  /* 0 - 14 */
-} tCODEC_INFO_MP2;
-
-
-typedef struct
-{
-    UINT8   ch_mode;
-    UINT8   sampling_freq;
-    UINT8   bitrate_index;  /* 0 - 14 */
-} tCODEC_INFO_MP2_5;
-
-typedef struct
-{
-    UINT16  sampling_freq;
-    UINT8   channel_mode;   /* 0x02:mono, 0x01:dual */
-    UINT32  bitrate;        /* 0 - 320K */
-    UINT32  sbr_profile;        /* 1: ON, 0: OFF */
-} tCODEC_INFO_AAC;
-
-typedef union
-{
-    tCODEC_INFO_SBC     sbc;
-    tCODEC_INFO_MP3     mp3;
-    tCODEC_INFO_MP2     mp2;
-    tCODEC_INFO_MP2_5   mp2_5;
-    tCODEC_INFO_AAC     aac;
-} tCODEC_INFO;
-
-typedef struct
-{
-    UINT8               opcode;     /* AUDIO_CODEC_CONFIG_REQ */
-    tAUDIO_CODEC_TYPE   codec_type;
-    tCODEC_INFO         codec_info;
-} tAUDIO_CODEC_CONFIG_REQ;
-
-#define AUDIO_CONFIG_SUCCESS            0x00
-#define AUDIO_CONFIG_NOT_SUPPORTED      0x01
-#define AUDIO_CONFIG_FAIL_OUT_OF_MEMORY 0x02
-#define AUDIO_CONFIG_FAIL_CODEC_USED    0x03
-#define AUDIO_CONFIG_FAIL_ROUTE         0x04
-typedef UINT8 tAUDIO_CONFIG_STATUS;
-
-typedef struct
-{
-    UINT8                   opcode; /* AUDIO_CODEC_CONFIG_RESP */
-    tAUDIO_CONFIG_STATUS    status;
-} tAUDIO_CODEC_CONFIG_RESP;
-
-typedef struct
-{
-    UINT8               opcode;     /* AUDIO_CODEC_SET_BITRATE_REQ */
-    tAUDIO_CODEC_TYPE   codec_type;
-    union
-    {
-        UINT8   sbc;
-        UINT8   mp3;
-        UINT32  aac;
-    } codec_bitrate;
-} tAUDIO_CODEC_SET_BITRATE_REQ;
-
-#define AUDIO_ROUTE_SRC_FMRX        0x00
-#define AUDIO_ROUTE_SRC_I2S         0x01
-#define AUDIO_ROUTE_SRC_ADC         0x02
-#define AUDIO_ROUTE_SRC_HOST        0x03
-#define AUDIO_ROUTE_SRC_PTU         0x04
-#define AUDIO_ROUTE_SRC_BTSNK       0x05
-#define AUDIO_ROUTE_SRC_NONE        0x80
-#define MAX_AUDIO_ROUTE_SRC         6
-typedef UINT8 tAUDIO_ROUTE_SRC;
-
-#define AUDIO_ROUTE_MIX_NONE        0x00
-#define AUDIO_ROUTE_MIX_HOST        0x01
-#define AUDIO_ROUTE_MIX_PCM         0x02
-#define AUDIO_ROUTE_MIX_CHIRP       0x03
-#define AUDIO_ROUTE_MIX_I2S         0x04
-#define AUDIO_ROUTE_MIX_ADC         0x05
-#define AUDIO_ROUTE_MIX_RESERVED    0x06
-#define MAX_AUDIO_ROUTE_MIX         7
-typedef UINT8 tAUDIO_ROUTE_MIX;
-
-#define AUDIO_ROUTE_OUT_NONE        0x0000
-#define AUDIO_ROUTE_OUT_BTA2DP      0x0001
-#define AUDIO_ROUTE_OUT_FMTX        0x0002
-#define AUDIO_ROUTE_OUT_BTSCO       0x0004
-#define AUDIO_ROUTE_OUT_HOST        0x0008
-#define AUDIO_ROUTE_OUT_DAC         0x0010
-#define AUDIO_ROUTE_OUT_I2S         0x0020
-#define AUDIO_ROUTE_OUT_BTA2DP_DAC  0x0040
-#define AUDIO_ROUTE_OUT_BTA2DP_I2S  0x0080
-#define AUDIO_ROUTE_OUT_BTSCO_DAC   0x0100
-#define AUDIO_ROUTE_OUT_BTSCO_I2S   0x0200
-#define AUDIO_ROUTE_OUT_HOST_BTA2DP 0x0400
-#define AUDIO_ROUTE_OUT_HOST_BTSCO  0x0800
-#define AUDIO_ROUTE_OUT_HOST_DAC    0x1000
-#define AUDIO_ROUTE_OUT_HOST_I2S    0x2000
-#define AUDIO_ROUTE_OUT_DAC_I2S     0x4000
-#define AUDIO_ROUTE_OUT_RESERVED_2  0x8000
-
-#define MAX_AUDIO_SINGLE_ROUTE_OUT  6
-#define MAX_AUDIO_MULTI_ROUTE_OUT   16
-typedef UINT16 tAUDIO_MULTI_ROUTE_OUT;
-typedef UINT8  tAUDIO_ROUTE_OUT;
-
-#define AUDIO_ROUTE_SF_8K           0x00
-#define AUDIO_ROUTE_SF_16K          0x01
-#define AUDIO_ROUTE_SF_32K          0x02
-#define AUDIO_ROUTE_SF_44_1K        0x03
-#define AUDIO_ROUTE_SF_48K          0x04
-#define AUDIO_ROUTE_SF_11K          0x05
-#define AUDIO_ROUTE_SF_12K          0x06
-#define AUDIO_ROUTE_SF_22K          0x07
-#define AUDIO_ROUTE_SF_24K          0x08
-#define AUDIO_ROUTE_SF_NA           0xFF
-typedef UINT8 tAUDIO_ROUTE_SF;
-
-#define AUDIO_ROUTE_EQ_BASS_BOOST   0x00
-#define AUDIO_ROUTE_EQ_CLASSIC      0x01
-#define AUDIO_ROUTE_EQ_JAZZ         0x02
-#define AUDIO_ROUTE_EQ_LIVE         0x03
-#define AUDIO_ROUTE_EQ_NORMAL       0x04
-#define AUDIO_ROUTE_EQ_ROCK         0x05
-#define AUDIO_ROUTE_EQ_BYPASS       0x06
-
-#define AUDIO_ROUTE_DIGITAL_VOLUME_CONTROL  0x07
-
-#define AUDIO_ROUTE_EQ_CONFIG_GAIN  0xFF    /* Custion Gain Config */
-typedef UINT8 tAUDIO_ROUTE_EQ;
-
-typedef struct
-{
-    UINT8               opcode;     /* AUDIO_ROUTE_CONFIG_REQ */
-    tAUDIO_ROUTE_SRC    src;
-    tAUDIO_ROUTE_SF     src_sf;
-    tAUDIO_ROUTE_OUT    out;
-    tAUDIO_ROUTE_SF     out_codec_sf;
-    tAUDIO_ROUTE_SF     out_i2s_sf;
-    tAUDIO_ROUTE_EQ     eq_mode;
-} tAUDIO_ROUTE_CONFIG_REQ;
-
-typedef struct
-{
-    UINT8                   opcode; /* AUDIO_ROUTE_CONFIG_RESP */
-    tAUDIO_CONFIG_STATUS    status;
-} tAUDIO_ROUTE_CONFIG_RESP;
-
-typedef struct
-{
-    UINT16  amp[2];                 /* left/right 15 bit amplitude value        */
-    UINT16  tone[2];                /* left/right 12 bit frequency 0 - 4096Hz   */
-    UINT16  mark[2];                /* left/right 16 bit mark time 0 - 65535ms  */
-    UINT16  space[2];               /* left/right 16 bit space time 0 - 65535ms */
-} tCHIRP_CONFIG;
-
-typedef struct
-{
-    UINT8   pri_l;                  /* Primary Left scale : 0 ~ 255     */
-    UINT8   mix_l;                  /* Mixing Left scale : 0 ~ 255      */
-    UINT8   pri_r;                  /* Primary Right scale : 0 ~ 255    */
-    UINT8   mix_r;                  /* Mixing Right scale : 0 ~ 255     */
-} tMIX_SCALE_CONFIG;
-
-/* For custon equalizer gain configuration */
-typedef struct
-{
-    UINT32  audio_l_g0;         /* IIR biquad filter left ch gain 0 */
-    UINT32  audio_l_g1;         /* IIR biquad filter left ch gain 1 */
-    UINT32  audio_l_g2;         /* IIR biquad filter left ch gain 2 */
-    UINT32  audio_l_g3;         /* IIR biquad filter left ch gain 3 */
-    UINT32  audio_l_g4;         /* IIR biquad filter left ch gain 4 */
-    UINT32  audio_l_gl;         /* IIR biquad filter left ch global gain  */
-    UINT32  audio_r_g0;         /* IIR biquad filter left ch gain 0 */
-    UINT32  audio_r_g1;         /* IIR biquad filter left ch gain 1 */
-    UINT32  audio_r_g2;         /* IIR biquad filter left ch gain 2 */
-    UINT32  audio_r_g3;         /* IIR biquad filter left ch gain 3 */
-    UINT32  audio_r_g4;         /* IIR biquad filter left ch gain 4 */
-    UINT32  audio_r_gl;         /* IIR biquad filter left ch global gain */
-} tEQ_GAIN_CONFIG;
-
-typedef struct
-{
-    UINT8               opcode;     /* AUDIO_MIX_CONFIG_REQ */
-    tAUDIO_ROUTE_MIX    mix_src;
-    tAUDIO_ROUTE_SF     mix_src_sf;
-    tMIX_SCALE_CONFIG   mix_scale;
-    tCHIRP_CONFIG       chirp_config;
-} tAUDIO_MIX_CONFIG_REQ;
-
-typedef struct
-{
-    UINT8                   opcode; /* AUDIO_MIX_CONFIG_RESP */
-    tAUDIO_CONFIG_STATUS    status;
-} tAUDIO_MIX_CONFIG_RESP;
-
-
-typedef struct
-{
-    UINT8   opcode;                 /* AUDIO_BURST_FRAMES_IND */
-    UINT32  burst_size;             /* in bytes */
-} tAUDIO_BURST_FRAMES_IND;
-
-typedef struct
-{
-    UINT8   opcode;                 /* AUDIO_BURST_END_IND */
-} tAUDIO_BURST_END_IND;
-
-typedef struct
-{
-    UINT8   opcode;                 /* AUDIO_CODEC_FLUSH_REQ */
-} tAUDIO_CODEC_FLUSH_REQ;
-
-typedef struct
-{
-    UINT8               opcode;     /* AUDIO_EQ_MODE_CONFIG_REQ */
-    tAUDIO_ROUTE_EQ     eq_mode;
-    tEQ_GAIN_CONFIG     filter_gain;    /* Valid only when eq_mode is 0xFF */
-} tAUDIO_EQ_MODE_CONFIG_REQ;
-
-typedef struct
-{
-    UINT8               opcode;     /* AUDIO_SCALE_CONFIG_REQ */
-    tMIX_SCALE_CONFIG   mix_scale;
-} tAUDIO_SCALE_CONFIG_REQ;
-
-#endif /* UIPC_MSG_H */
-
index e01a261..c1ca120 100644 (file)
@@ -1772,6 +1772,37 @@ BOOLEAN L2CA_GetCurrentConfig (UINT16 lcid,
 
 /*******************************************************************************
 **
+** Function      L2CA_GetConnectionConfig
+**
+** Description  This function returns configurations of L2CAP channel
+**              pp_l2c_ccb : pointer to this channels L2CAP ccb data.
+**
+** Returns      TRUE if successful
+**
+*******************************************************************************/
+BOOLEAN L2CA_GetConnectionConfig(UINT16 lcid, UINT16 *mtu, UINT16 *rcid, UINT16 *handle)
+{
+    tL2C_CCB *p_ccb = l2cu_find_ccb_by_cid(NULL, lcid);;
+
+    L2CAP_TRACE_API ("%s CID: 0x%04x", __func__, lcid);
+
+    if (p_ccb)
+    {
+        *mtu = L2CAP_MTU_SIZE;
+        if (p_ccb->our_cfg.mtu_present)
+            *mtu = p_ccb->our_cfg.mtu;
+
+        *rcid  = p_ccb->remote_cid;
+        *handle= p_ccb->p_lcb->handle;
+        return TRUE;
+    }
+
+    L2CAP_TRACE_ERROR ("%s No CCB for CID:0x%04x", __func__, lcid);
+    return FALSE;
+}
+
+/*******************************************************************************
+**
 ** Function         L2CA_RegForNoCPEvt
 **
 ** Description      Register callback for Number of Completed Packets event.
index a5cfb4d..9aff917 100644 (file)
@@ -714,9 +714,14 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
 
         btm_ble_enable_resolving_list(BTM_BLE_RL_INIT);
         btm_random_pseudo_to_identity_addr(peer_addr, &peer_addr_type);
-    }
-    else
+    } else {
         btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, TRUE);
+
+        // If we have a current RPA, use that instead.
+        if (!bdaddr_is_empty((const bt_bdaddr_t *)p_dev_rec->ble.cur_rand_addr)) {
+            memcpy(peer_addr, p_dev_rec->ble.cur_rand_addr, BD_ADDR_LEN);
+        }
+    }
 #endif
 
     if (!btm_ble_topology_check(BTM_BLE_STATE_INIT))
index a7ffca5..0567c6a 100644 (file)
@@ -411,6 +411,7 @@ void rfc_mx_sm_state_wait_sabme (tRFC_MCB *p_mcb, UINT16 event, void *p_data)
 
             p_mcb->state      = RFC_MX_STATE_CONNECTED;
             p_mcb->peer_ready = TRUE;
+            PORT_StartCnf (p_mcb, RFCOMM_SUCCESS);
         }
         return;
 
index 3caec79..960043b 100644 (file)
@@ -1,5 +1,5 @@
 #
-#  Copyright (C) 2014 Google, Inc.
+#  Copyright (C) 2015 Google, Inc.
 #
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := net_test_bluedroid
+LOCAL_MODULE := net_test_bluetooth
 
 LOCAL_C_INCLUDES += \
     $(LOCAL_PATH)/../../
@@ -36,7 +36,7 @@ LOCAL_SRC_FILES := \
     support/hal.c \
     support/pan.c \
     support/rfcomm.c \
-    main.c
+    main.cpp
 
 LOCAL_SHARED_LIBRARIES += \
     liblog \
@@ -48,8 +48,8 @@ LOCAL_STATIC_LIBRARIES += \
   libbtcore \
   libosi
 
-LOCAL_CFLAGS += -std=c99 -Wall -Wno-unused-parameter -Wno-missing-field-initializers -Werror
+LOCAL_CFLAGS += -Wall -Wno-unused-parameter -Wno-missing-field-initializers -Werror
 
 LOCAL_MULTILIB := 32
 
-include $(BUILD_EXECUTABLE)
+include $(BUILD_NATIVE_TEST)
diff --git a/test/suite/BUILD.gn b/test/suite/BUILD.gn
new file mode 100644 (file)
index 0000000..74d6b75
--- /dev/null
@@ -0,0 +1,48 @@
+#
+#  Copyright (C) 2015 Google, Inc.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at:
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+
+executable("net_test_bluetooth") {
+  testonly = true
+  sources = [
+    "cases/adapter.c",
+    "cases/cases.c",
+    "cases/gatt.c",
+    "cases/pan.c",
+    "cases/rfcomm.c",
+    "support/adapter.c",
+    "support/callbacks.c",
+    "support/gatt.c",
+    "support/hal.c",
+    "support/pan.c",
+    "support/rfcomm.c",
+    "main.cpp",
+  ]
+
+  include_dirs = [
+    "//",
+    "//test/suite",
+  ]
+
+  deps = [
+    "//btcore",
+    "//main:bluetooth.default",
+    "//osi",
+    "//third_party/gtest:gtest_main",
+  ]
+
+  libs = [ "-lpthread", "-lrt", "-ldl" ]
+
+}
index 935ff17..7f33867 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index 280cfc6..2d20084 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -36,7 +36,8 @@ bool adapter_enable_disable() {
 }
 
 bool adapter_repeated_enable_disable() {
-  for (int i = 0; i < 10; ++i) {
+  int i;
+  for (i = 0; i < 10; ++i) {
     if (!adapter_enable_disable()) {
       return false;
     }
index 476a3a1..99fd348 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index b20950b..9606b20 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index 02c2ae5..a38f7d6 100644 (file)
@@ -1,3 +1,21 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2015 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
 #include <stdlib.h>
 #include <time.h>
 #include <unistd.h>
@@ -10,7 +28,8 @@
 
 static void create_random_uuid(bt_uuid_t *uuid, int seed) {
   srand(seed < 0 ? time(NULL) : seed);
-  for (int i = 0; i < 16; ++i) {
+  int i;
+  for (i = 0; i < 16; ++i) {
     uuid->uu[i] = (uint8_t) (rand() % 256);
   }
 }
index b903b90..157bd81 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index feea4c1..6cb2793 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -67,7 +67,8 @@ bool rfcomm_connect() {
 bool rfcomm_repeated_connect() {
   static const int max_iterations = 128;
 
-  for (int i = 0; i < max_iterations; ++i) {
+  int i;
+  for (i = 0; i < max_iterations; ++i) {
     TASSERT(rfcomm_connect(), "Connection failed on attempt %d/%d", i, max_iterations);
   }
 
diff --git a/test/suite/main.c b/test/suite/main.c
deleted file mode 100644 (file)
index 24cb862..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-/******************************************************************************
- *
- *  Copyright (C) 2014 Google, Inc.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at:
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- ******************************************************************************/
-
-#include <cutils/properties.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "base.h"
-#include "btcore/include/bdaddr.h"
-#include "cases/cases.h"
-#include "osi/include/config.h"
-#include "support/callbacks.h"
-#include "support/hal.h"
-#include "support/gatt.h"
-#include "support/pan.h"
-#include "support/rfcomm.h"
-
-// How long the watchdog thread should wait before checking if a test has completed.
-// Any individual test will have at least WATCHDOG_PERIOD_SEC and at most
-// 2 * WATCHDOG_PERIOD_SEC seconds to complete.
-static const int WATCHDOG_PERIOD_SEC = 1 * 60;
-static const char *CONFIG_FILE_PATH = "/data/misc/bluedroid/bt_config.conf";
-
-const bt_interface_t *bt_interface;
-bt_bdaddr_t bt_remote_bdaddr;
-
-static pthread_t watchdog_thread;
-static int watchdog_id;
-static bool watchdog_running;
-
-static void *watchdog_fn(void *arg) {
-  int current_id = 0;
-  for (;;) {
-    // Check every second whether this thread should exit and check
-    // every WATCHDOG_PERIOD_SEC whether we should terminate the process.
-    for (int i = 0; watchdog_running && i < WATCHDOG_PERIOD_SEC; ++i) {
-      sleep(1);
-    }
-
-    if (!watchdog_running)
-      break;
-
-    if (current_id == watchdog_id) {
-      printf("Watchdog detected hanging test suite, aborting...\n");
-      exit(-1);
-    }
-    current_id = watchdog_id;
-  }
-  return NULL;
-}
-
-static bool is_shell_running(void) {
-  char property_str[100];
-  property_get("init.svc.zygote", property_str, NULL);
-  if (!strcmp("running", property_str)) {
-    return true;
-  }
-  return false;
-}
-
-static void print_usage(const char *program_name) {
-  printf("Usage: %s [options] [test name]\n", program_name);
-  printf("\n");
-  printf("Options:\n");
-  printf("  %-20sdisplay this help text.\n", "--help");
-  printf("  %-20sdo not run sanity suite.\n", "--insanity");
-  printf("\n");
-  printf("Valid test names are:\n");
-  for (size_t i = 0; i < sanity_suite_size; ++i) {
-    printf("  %s\n", sanity_suite[i].function_name);
-  }
-  for (size_t i = 0; i < test_suite_size; ++i) {
-    printf("  %s\n", test_suite[i].function_name);
-  }
-}
-
-static bool is_valid(const char *test_name) {
-  for (size_t i = 0; i < sanity_suite_size; ++i) {
-    if (!strcmp(test_name, sanity_suite[i].function_name)) {
-      return true;
-    }
-  }
-  for (size_t i = 0; i < test_suite_size; ++i) {
-    if (!strcmp(test_name, test_suite[i].function_name)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-int main(int argc, char **argv) {
-  const char *test_name = NULL;
-  bool skip_sanity_suite = false;
-
-  for (int i = 1; i < argc; ++i) {
-    if (!strcmp("--help", argv[i])) {
-      print_usage(argv[0]);
-      return 0;
-    }
-
-    if (!strcmp("--insanity", argv[i])) {
-      skip_sanity_suite = true;
-      continue;
-    }
-
-    if (!is_valid(argv[i])) {
-      printf("Error: invalid test name.\n");
-      print_usage(argv[0]);
-      return -1;
-    }
-
-    if (test_name != NULL) {
-      printf("Error: invalid arguments.\n");
-      print_usage(argv[0]);
-      return -1;
-    }
-
-    test_name = argv[i];
-  }
-
-  if (is_shell_running()) {
-    printf("Run 'adb shell stop' before running %s.\n", argv[0]);
-    return -1;
-  }
-
-  config_t *config = config_new(CONFIG_FILE_PATH);
-  if (!config) {
-    printf("Error: unable to open stack config file.\n");
-    print_usage(argv[0]);
-    return -1;
-  }
-
-  for (const config_section_node_t *node = config_section_begin(config); node != config_section_end(config); node = config_section_next(node)) {
-    const char *name = config_section_name(node);
-    if (config_has_key(config, name, "LinkKey") && string_to_bdaddr(name, &bt_remote_bdaddr)) {
-      break;
-    }
-  }
-
-  config_free(config);
-
-  if (bdaddr_is_empty(&bt_remote_bdaddr)) {
-    printf("Error: unable to find paired device in config file.\n");
-    print_usage(argv[0]);
-    return -1;
-  }
-
-  if (!hal_open(callbacks_get_adapter_struct())) {
-    printf("Unable to open Bluetooth HAL.\n");
-    return 1;
-  }
-
-  if (!btsocket_init()) {
-    printf("Unable to initialize Bluetooth sockets.\n");
-    return 2;
-  }
-
-  if (!pan_init()) {
-    printf("Unable to initialize PAN.\n");
-    return 3;
-  }
-
-  if (!gatt_init()) {
-    printf("Unable to initialize GATT.\n");
-    return 4;
-  }
-
-  watchdog_running = true;
-  pthread_create(&watchdog_thread, NULL, watchdog_fn, NULL);
-
-  static const char *DEFAULT  = "\x1b[0m";
-  static const char *GREEN = "\x1b[0;32m";
-  static const char *RED   = "\x1b[0;31m";
-
-  // If the output is not a TTY device, don't colorize output.
-  if (!isatty(fileno(stdout))) {
-    DEFAULT = GREEN = RED = "";
-  }
-
-  int pass = 0;
-  int fail = 0;
-  int case_num = 0;
-
-  // If test name is specified, run that specific test.
-  // Otherwise run through the sanity suite.
-  if (!skip_sanity_suite) {
-    for (size_t i = 0; i < sanity_suite_size; ++i) {
-      if (!test_name || !strcmp(test_name, sanity_suite[i].function_name)) {
-        callbacks_init();
-        if (sanity_suite[i].function()) {
-          printf("[%4d] %-64s [%sPASS%s]\n", ++case_num, sanity_suite[i].function_name, GREEN, DEFAULT);
-          ++pass;
-        } else {
-          printf("[%4d] %-64s [%sFAIL%s]\n", ++case_num, sanity_suite[i].function_name, RED, DEFAULT);
-          ++fail;
-        }
-        callbacks_cleanup();
-        ++watchdog_id;
-      }
-    }
-  }
-
-  // If there was a failure in the sanity suite, don't bother running the rest of the tests.
-  if (fail) {
-    printf("\n%sSanity suite failed with %d errors.%s\n", RED, fail, DEFAULT);
-    hal_close();
-    return 4;
-  }
-
-  // If test name is specified, run that specific test.
-  // Otherwise run through the full test suite.
-  for (size_t i = 0; i < test_suite_size; ++i) {
-    if (!test_name || !strcmp(test_name, test_suite[i].function_name)) {
-      callbacks_init();
-      CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
-      if (test_suite[i].function()) {
-        printf("[%4d] %-64s [%sPASS%s]\n", ++case_num, test_suite[i].function_name, GREEN, DEFAULT);
-        ++pass;
-      } else {
-        printf("[%4d] %-64s [%sFAIL%s]\n", ++case_num, test_suite[i].function_name, RED, DEFAULT);
-        ++fail;
-      }
-      CALL_AND_WAIT(bt_interface->disable(), adapter_state_changed);
-      callbacks_cleanup();
-      ++watchdog_id;
-    }
-  }
-
-  printf("\n");
-
-  if (fail) {
-    printf("%d/%d tests failed. See above for failed test cases.\n", fail, sanity_suite_size + test_suite_size);
-  } else {
-    printf("All tests passed!\n");
-  }
-
-  watchdog_running = false;
-  pthread_join(watchdog_thread, NULL);
-
-  hal_close();
-
-  return 0;
-}
diff --git a/test/suite/main.cpp b/test/suite/main.cpp
new file mode 100644 (file)
index 0000000..3de1420
--- /dev/null
@@ -0,0 +1,186 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2015 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <cutils/properties.h>
+#include <gtest/gtest.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+extern "C" {
+  #include "base.h"
+  #include "btcore/include/bdaddr.h"
+  #include "cases/cases.h"
+  #include "osi/include/config.h"
+  #include "support/callbacks.h"
+  #include "support/hal.h"
+  #include "support/gatt.h"
+  #include "support/pan.h"
+  #include "support/rfcomm.h"
+}
+
+static const char *CONFIG_FILE_PATH = "/data/misc/bluedroid/bt_config.conf";
+
+const bt_interface_t *bt_interface;
+bt_bdaddr_t bt_remote_bdaddr;
+
+class CommsTest : public ::testing::Test {
+    protected : CommsTest() { }
+    ~CommsTest() { }
+    virtual void SetUp() {
+        callbacks_init();
+    }
+    virtual void TearDown() {
+        callbacks_cleanup();
+    }
+};
+
+void first_time_setup() {
+    config_t *config = config_new(CONFIG_FILE_PATH);
+    if (!config) {
+        printf("Error: unable to open stack config file.\n");
+        FAIL();
+    }
+    for (const config_section_node_t *node = config_section_begin(config); node != config_section_end(config); node = config_section_next(node)) {
+        const char *name = config_section_name(node);
+        if (config_has_key(config, name, "LinkKey") && string_to_bdaddr(name, &bt_remote_bdaddr)) {
+            break;
+        }
+    }
+    config_free(config);
+    if (bdaddr_is_empty(&bt_remote_bdaddr)) {
+        printf("Error: unable to find paired device in config file.\n");
+        FAIL();
+    } else if (!hal_open(callbacks_get_adapter_struct())) {
+        printf("Unable to open Bluetooth HAL.\n");
+        FAIL();
+    } else if (!btsocket_init()) {
+        printf("Unable to initialize Bluetooth sockets.\n");
+        FAIL();
+    } else if (!pan_init()) {
+        printf("Unable to initialize PAN.\n");
+        FAIL();
+    } else if (!gatt_init()) {
+        printf("Unable to initialize GATT.\n");
+        FAIL();
+    }
+}
+
+void setup() {
+    CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
+}
+
+void cleanup() {
+    CALL_AND_WAIT(bt_interface->disable(), adapter_state_changed);
+}
+
+TEST_F(CommsTest, initial_setup) {
+    first_time_setup();
+}
+
+TEST_F(CommsTest, adapter_enable_disable) {
+    EXPECT_TRUE(sanity_suite[0].function());
+}
+
+TEST_F(CommsTest, adapter_repeated_enable_disable) {
+    EXPECT_TRUE(sanity_suite[1].function());
+}
+
+TEST_F(CommsTest, adapter_set_name) {
+    setup();
+    EXPECT_TRUE(test_suite[0].function());
+    cleanup();
+}
+
+TEST_F(CommsTest, adapter_get_name) {
+    setup();
+    EXPECT_TRUE(test_suite[1].function());
+    cleanup();
+}
+
+TEST_F(CommsTest, adapter_start_discovery) {
+    setup();
+    EXPECT_TRUE(test_suite[2].function());
+    cleanup();
+}
+
+TEST_F(CommsTest, adapter_cancel_discovery) {
+    setup();
+    EXPECT_TRUE(test_suite[3].function());
+    cleanup();
+}
+
+TEST_F(CommsTest, rfcomm_connect) {
+    setup();
+    EXPECT_TRUE(test_suite[4].function());
+    cleanup();
+}
+
+TEST_F(CommsTest, rfcomm_repeated_connect) {
+    setup();
+    EXPECT_TRUE(test_suite[5].function());
+    cleanup();
+}
+
+TEST_F(CommsTest, pan_enable) {
+    setup();
+    EXPECT_TRUE(test_suite[6].function());
+    cleanup();
+}
+
+TEST_F(CommsTest, pan_connect) {
+    setup();
+    EXPECT_TRUE(test_suite[7].function());
+    cleanup();
+}
+
+TEST_F(CommsTest, pan_disconnect) {
+    setup();
+    EXPECT_TRUE(test_suite[8].function());
+    cleanup();
+}
+
+TEST_F(CommsTest, gatt_client_register) {
+    setup();
+    EXPECT_TRUE(test_suite[9].function());
+    cleanup();
+}
+
+TEST_F(CommsTest, gatt_client_scan) {
+    setup();
+    EXPECT_TRUE(test_suite[10].function());
+    cleanup();
+}
+
+TEST_F(CommsTest, gatt_client_advertise) {
+    setup();
+    EXPECT_TRUE(test_suite[11].function());
+    cleanup();
+}
+
+TEST_F(CommsTest, gatt_server_register) {
+    setup();
+    EXPECT_TRUE(test_suite[12].function());
+    cleanup();
+}
+
+TEST_F(CommsTest, gatt_server_build) {
+    setup();
+    EXPECT_TRUE(test_suite[13].function());
+    cleanup();
+}
index d6b8ab3..34ce107 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -38,7 +38,8 @@ int adapter_get_property_count() {
 }
 
 bt_property_t *adapter_get_property(bt_property_type_t type) {
-  for (int i = 0; i < property_count; ++i) {
+  int i;
+  for (i = 0; i < property_count; ++i) {
     if (properties[i].type == type) {
       return &properties[i];
     }
index 0f5883f..cae90da 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index bbec5d2..4ad3bf6 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -208,13 +208,15 @@ static btgatt_callbacks_t gatt_callbacks = {
 };
 
 void callbacks_init() {
-  for (size_t i = 0; i < ARRAY_SIZE(callback_data); ++i) {
+  size_t i;
+  for (i = 0; i < ARRAY_SIZE(callback_data); ++i) {
     sem_init(&callback_data[i].semaphore, 0, 0);
   }
 }
 
 void callbacks_cleanup() {
-  for (size_t i = 0; i < ARRAY_SIZE(callback_data); ++i) {
+  size_t i;
+  for (i = 0; i < ARRAY_SIZE(callback_data); ++i) {
     sem_destroy(&callback_data[i].semaphore);
   }
 }
@@ -232,7 +234,8 @@ btgatt_callbacks_t *callbacks_get_gatt_struct() {
 }
 
 sem_t *callbacks_get_semaphore(const char *name) {
-  for (size_t i = 0; i < ARRAY_SIZE(callback_data); ++i) {
+  size_t i;
+  for (i = 0; i < ARRAY_SIZE(callback_data); ++i) {
     if (callback_data[i].name && !strcmp(name, callback_data[i].name)) {
       return &callback_data[i].semaphore;
     }
index e01de39..de92f15 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index 9896afd..31a28f2 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -155,7 +155,8 @@ void btgatts_register_app_cb(int status, int server_if, bt_uuid_t *uuid) {
 
 void btgatts_connection_cb(int conn_id, int server_if, int connected, bt_bdaddr_t *bda) {
   gatt_connection_id = conn_id;
-  for (int i = 0; i < 6; ++i) {
+  int i;
+  for (i = 0; i < 6; ++i) {
     remote_bd_addr.address[i] = bda->address[i];
   }
   CALLBACK_RET();
@@ -227,4 +228,4 @@ void btgatts_request_exec_write_cb(int conn_id, int trans_id, bt_bdaddr_t *bda,
 
 void btgatts_response_confirmation_cb(int status, int handle) {
   CALLBACK_RET();
-}
\ No newline at end of file
+}
index d438cdf..2ef5433 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index 3ebcf74..89f609b 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index 11fa9f9..ccf6267 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index df4c516..e2ef8c7 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -55,7 +55,7 @@ bt_status_t pan_get_error() {
 }
 
 // callback
-void pan_control_state_changed(btpan_control_state_t state, bt_status_t error, int local_role, const char *ifname) {
+void pan_control_state_changed(btpan_control_state_t state, int local_role, bt_status_t error, const char *ifname) {
   free(pan_ifname);
 
   pan_control_state = state;
index f43eb24..69dd4a9 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index 8bb8b4d..c9d15e4 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index 6b861d1..1c2de7b 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2014 Google, Inc.
+ *  Copyright (C) 2015 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
index fc433bc..ae06400 100644 (file)
@@ -27,6 +27,7 @@ static int help(int argc, char **argv);
 static int set_discoverable(int argc, char **argv);
 static int set_name(int argc, char **argv);
 static int set_pcm_loopback(int argc, char **argv);
+static int set_sco_route(int argc, char **argv);
 
 static bool write_hci_command(hci_packet_t type, const void *packet, size_t length);
 static const command_t *find_command(const char *name);
@@ -37,6 +38,7 @@ static const command_t commands[] = {
   { "setDiscoverable", "(true|false) - whether the controller should be discoverable.", set_discoverable },
   { "setName", "<name> - sets the device's Bluetooth name to <name>.", set_name },
   { "setPcmLoopback", "(true|false) - enables or disables PCM loopback on the controller.", set_pcm_loopback },
+  { "setScoRoute", "(pcm|i2s|uart) - sets the SCO packet route to one of the specified buses.", set_sco_route },
 };
 
 static int help(int argc, char **argv) {
@@ -120,6 +122,31 @@ static int set_pcm_loopback(int argc, char **argv) {
   return !write_hci_command(HCI_PACKET_COMMAND, packet, ARRAY_SIZE(packet));
 }
 
+static int set_sco_route(int argc, char **argv) {
+  if (argc != 1) {
+    printf("SCO route parameter must be specified.\n");
+    return 1;
+  }
+
+  uint8_t route = 0xFF;
+  if (!strcmp(argv[0], "pcm"))
+    route = 0;
+  else if (!strcmp(argv[0], "i2s"))
+    route = 3;
+  else if (!strcmp(argv[0], "uart"))
+    route = 1;
+
+  if (route == 0xFF) {
+    printf("Invalid SCO route specified: %s\n", argv[0]);
+    return 2;
+  }
+
+  uint8_t packet[] = { 0x1C, 0xFC, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00 };
+  packet[3] = route;
+
+  return !write_hci_command(HCI_PACKET_COMMAND, packet, ARRAY_SIZE(packet));
+}
+
 int main(int argc, char **argv) {
   if (argc < 2) {
     usage(argv[0]);
diff --git a/tools/scripts/btsnooz.py b/tools/scripts/btsnooz.py
new file mode 100755 (executable)
index 0000000..af4708d
--- /dev/null
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+"""
+This script extracts btsnooz content from bugreports and generates
+a valid btsnoop log file which can be viewed using standard tools
+like Wireshark.
+
+btsnooz is a custom format designed to be included in bugreports.
+It can be described as:
+
+base64 {
+  file_header
+  deflate {
+    repeated {
+      record_header
+      record_data
+    }
+  }
+}
+
+where the file_header and record_header are modified versions of
+the btsnoop headers.
+"""
+
+
+import base64
+import fileinput
+import struct
+import sys
+import zlib
+
+
+# Enumeration of the values the 'type' field can take in a btsnooz
+# header. These values come from the Bluetooth stack's internal
+# representation of packet types.
+TYPE_IN_EVT = 0x10
+TYPE_IN_ACL = 0x11
+TYPE_IN_SCO = 0x12
+TYPE_OUT_CMD = 0x20
+TYPE_OUT_ACL = 0x21
+TYPE_OUT_SCO = 0x22
+
+
+def type_to_direction(type):
+  """
+  Returns the inbound/outbound direction of a packet given its type.
+  0 = sent packet
+  1 = received packet
+  """
+  if type in [TYPE_IN_EVT, TYPE_IN_ACL, TYPE_IN_SCO]:
+    return 1
+  return 0
+
+
+def type_to_hci(type):
+  """
+  Returns the HCI type of a packet given its btsnooz type.
+  """
+  if type == TYPE_OUT_CMD:
+    return '\x01'
+  if type == TYPE_IN_ACL or type == TYPE_OUT_ACL:
+    return '\x02'
+  if type == TYPE_IN_SCO or type == TYPE_OUT_SCO:
+    return '\x03'
+  if type == TYPE_IN_EVT:
+    return '\x04'
+
+
+def decode_snooz(snooz):
+  """
+  Decodes all known versions of a btsnooz file into a btsnoop file.
+  """
+  version, last_timestamp_ms = struct.unpack_from('=bQ', snooz)
+
+  if version != 1 and version != 2:
+    sys.stderr.write('Unsupported btsnooz version: %s\n' % version)
+    exit(1)
+
+  # Oddly, the file header (9 bytes) is not compressed, but the rest is.
+  decompressed = zlib.decompress(snooz[9:])
+
+  sys.stdout.write('btsnoop\x00\x00\x00\x00\x01\x00\x00\x03\xea')
+
+  if version == 1:
+    decode_snooz_v1(decompressed, last_timestamp_ms)
+  elif version == 2:
+    decode_snooz_v2(decompressed, last_timestamp_ms)
+
+
+def decode_snooz_v1(decompressed, last_timestamp_ms):
+  """
+  Decodes btsnooz v1 files into a btsnoop file.
+  """
+  # An unfortunate consequence of the file format design: we have to do a
+  # pass of the entire file to determine the timestamp of the first packet.
+  first_timestamp_ms = last_timestamp_ms + 0x00dcddb30f2f8000
+  offset = 0
+  while offset < len(decompressed):
+    length, delta_time_ms, type = struct.unpack_from('=HIb', decompressed, offset)
+    offset += 7 + length - 1
+    first_timestamp_ms -= delta_time_ms
+
+  # Second pass does the actual writing out to stdout.
+  offset = 0
+  while offset < len(decompressed):
+    length, delta_time_ms, type = struct.unpack_from('=HIb', decompressed, offset)
+    first_timestamp_ms += delta_time_ms
+    offset += 7
+    sys.stdout.write(struct.pack('>II', length, length))
+    sys.stdout.write(struct.pack('>II', type_to_direction(type), 0))
+    sys.stdout.write(struct.pack('>II', (first_timestamp_ms >> 32), (first_timestamp_ms & 0xFFFFFFFF)))
+    sys.stdout.write(type_to_hci(type))
+    sys.stdout.write(decompressed[offset : offset + length - 1])
+    offset += length - 1
+
+
+def decode_snooz_v2(decompressed, last_timestamp_ms):
+  """
+  Decodes btsnooz v2 files into a btsnoop file.
+  """
+  # An unfortunate consequence of the file format design: we have to do a
+  # pass of the entire file to determine the timestamp of the first packet.
+  first_timestamp_ms = last_timestamp_ms + 0x00dcddb30f2f8000
+  offset = 0
+  while offset < len(decompressed):
+    length, packet_length, delta_time_ms, snooz_type = struct.unpack_from('=HHIb', decompressed, offset)
+    offset += 9 + length - 1
+    first_timestamp_ms -= delta_time_ms
+
+  # Second pass does the actual writing out to stdout.
+  offset = 0
+  while offset < len(decompressed):
+    length, packet_length, delta_time_ms, snooz_type = struct.unpack_from('=HHIb', decompressed, offset)
+    first_timestamp_ms += delta_time_ms
+    offset += 9
+    sys.stdout.write(struct.pack('>II', packet_length, length))
+    sys.stdout.write(struct.pack('>II', type_to_direction(snooz_type), 0))
+    sys.stdout.write(struct.pack('>II', (first_timestamp_ms >> 32), (first_timestamp_ms & 0xFFFFFFFF)))
+    sys.stdout.write(type_to_hci(snooz_type))
+    sys.stdout.write(decompressed[offset : offset + length - 1])
+    offset += length - 1
+
+
+def main():
+  if len(sys.argv) > 2:
+    sys.stderr.write('Usage: %s [bugreport]\n' % sys.argv[0])
+    exit(1)
+
+  iterator = fileinput.input()
+  for line in iterator:
+    if line.startswith('--- BEGIN:BTSNOOP_LOG_SUMMARY'):
+      decode_snooz(base64.standard_b64decode(iterator.next()))
+      sys.exit(0)
+  sys.stderr.write('No btsnooz section found in bugreport.\n');
+
+
+if __name__ == '__main__':
+  main()