1010000 bt_hci_timeout (opcode|1)
1010001 bt_config_source (opcode|1)
1010002 bt_hci_unknown_type (hci_type|1)
+1010003 bt_conn_param_update_status (status|1)
bta_sys_sendmsg(p_buf);
}
+
+void BTA_AgSetScoAllowed(bool value)
+{
+ tBTA_AG_API_SET_SCO_ALLOWED *p_buf =
+ (tBTA_AG_API_SET_SCO_ALLOWED *)osi_malloc(sizeof(tBTA_AG_API_SET_SCO_ALLOWED));
+
+ p_buf->hdr.event = BTA_AG_API_SET_SCO_ALLOWED_EVT;
+ p_buf->value = value;
+
+ bta_sys_sendmsg(p_buf);
+}
APPL_TRACE_DEBUG("HFP AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
int_arg, p_arg);
+ memset(&val, 0, sizeof(tBTA_AG_VAL));
val.hdr.handle = bta_ag_scb_to_idx(p_scb);
val.hdr.app_id = p_scb->app_id;
val.hdr.status = BTA_AG_SUCCESS;
/* these events are handled outside of the state machine */
BTA_AG_API_ENABLE_EVT,
- BTA_AG_API_DISABLE_EVT
+ BTA_AG_API_DISABLE_EVT,
+ BTA_AG_API_SET_SCO_ALLOWED_EVT
};
/* Actions to perform after a SCO event */
tBTA_AG_PEER_CODEC codec;
} tBTA_AG_API_SETCODEC;
+/* data type for BTA_AG_API_SET_SCO_ALLOWED_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ bool value;
+} tBTA_AG_API_SET_SCO_ALLOWED;
+
/* data type for BTA_AG_DISC_RESULT_EVT */
typedef struct
{
extern void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param);
extern void bta_ag_ci_rx_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
extern void bta_ag_rcvd_slc_ready(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_set_sco_allowed(tBTA_AG_DATA *p_data);
#endif /* BTA_AG_INT_H */
bta_ag_api_result((tBTA_AG_DATA *) p_msg);
break;
+ case BTA_AG_API_SET_SCO_ALLOWED_EVT:
+ bta_ag_set_sco_allowed((tBTA_AG_DATA *) p_msg);
+ break;
+
/* all others reference scb by handle */
default:
if ((p_scb = bta_ag_scb_by_idx(p_msg->layer_specific)) != NULL)
static char *bta_ag_sco_state_str(UINT8 state);
#endif
+static bool sco_allowed = true;
+
#define BTA_AG_NO_EDR_ESCO (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \
BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
UINT8 event;
UNUSED(p_data);
+ if (!sco_allowed)
+ {
+ APPL_TRACE_DEBUG("%s not opening sco, by policy", __func__);
+ return;
+ }
+
/* if another scb using sco, this is a transfer */
if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb != p_scb)
{
}
}
+void bta_ag_set_sco_allowed(tBTA_AG_DATA *p_data)
+{
+ sco_allowed = ((tBTA_AG_API_SET_SCO_ALLOWED *) p_data)->value;
+ APPL_TRACE_DEBUG(sco_allowed ? "sco now allowed" : "sco now not allowed");
+}
+
/*******************************************************************************
** Debugging functions
*******************************************************************************/
void bta_dm_ble_update_conn_params (tBTA_DM_MSG *p_data)
{
if (!L2CA_UpdateBleConnParams(p_data->ble_update_conn_params.bd_addr,
- p_data->ble_update_conn_params.min_int,
- p_data->ble_update_conn_params.max_int,
- p_data->ble_update_conn_params.latency,
- p_data->ble_update_conn_params.timeout))
+ p_data->ble_update_conn_params.min_int,
+ p_data->ble_update_conn_params.max_int,
+ p_data->ble_update_conn_params.latency,
+ p_data->ble_update_conn_params.timeout,
+ p_data->ble_update_conn_params.p_conn_param_update_cback))
{
APPL_TRACE_ERROR("Update connection parameters failed!");
}
UNUSED(p_cback);
#endif
}
-/*******************************************************************************
-**
-** Function BTA_DmBleUpdateConnectionParam
-**
-** Description Update connection parameters, can only be used when connection is up.
-**
-** Parameters: bd_addr - BD address of the peer
-** min_int - minimum connection interval, [0x0004~ 0x4000]
-** max_int - maximum connection interval, [0x0004~ 0x4000]
-** latency - slave latency [0 ~ 500]
-** timeout - supervision timeout [0x000a ~ 0xc80]
-**
-** Returns void
-**
-*******************************************************************************/
-void BTA_DmBleUpdateConnectionParam(BD_ADDR bd_addr, UINT16 min_int,
- UINT16 max_int, UINT16 latency,
- UINT16 timeout)
-{
-#if BLE_INCLUDED == TRUE
- tBTA_DM_API_UPDATE_CONN_PARAM *p_msg =
- (tBTA_DM_API_UPDATE_CONN_PARAM *)osi_calloc(sizeof(tBTA_DM_API_UPDATE_CONN_PARAM));
-
- p_msg->hdr.event = BTA_DM_API_UPDATE_CONN_PARAM_EVT;
- bdcpy(p_msg->bd_addr, bd_addr);
- p_msg->min_int = min_int;
- p_msg->max_int = max_int;
- p_msg->latency = latency;
- p_msg->timeout = timeout;
-
- bta_sys_sendmsg(p_msg);
-#endif
-}
/*******************************************************************************
**
**
** Description Update connection parameters, can only be used when connection is up.
**
-** Parameters: bd_addr - BD address of the peer
+** Parameters: bd_addr - BD address of the peer
** min_int - minimum connection interval, [0x0004~ 0x4000]
** max_int - maximum connection interval, [0x0004~ 0x4000]
** latency - slave latency [0 ~ 500]
** timeout - supervision timeout [0x000a ~ 0xc80]
+ p_cback - callback on connection parameters updated
**
** Returns void
**
*******************************************************************************/
-void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int, UINT16 max_int,
- UINT16 latency, UINT16 timeout)
+void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int,
+ UINT16 max_int, UINT16 latency, UINT16 timeout,
+ tBTA_DM_BLE_CONN_PARAM_CBACK *p_cback)
{
tBTA_DM_API_UPDATE_CONN_PARAM *p_msg =
(tBTA_DM_API_UPDATE_CONN_PARAM *)osi_calloc(sizeof(tBTA_DM_API_UPDATE_CONN_PARAM));
p_msg->max_int = max_int;
p_msg->latency = latency;
p_msg->timeout = timeout;
+ p_msg->p_conn_param_update_cback = p_cback;
bta_sys_sendmsg(p_msg);
}
UINT16 conn_int_max;
UINT16 supervision_tout;
UINT16 slave_latency;
-
}tBTA_DM_API_BLE_CONN_PARAMS;
typedef struct
tBTA_DM_LINK_TYPE link_type;
} tBTA_DM_API_REMOVE_ALL_ACL;
+
+/* data type for BTA_DM_API_UPDATE_CONN_PARAM_EVT */
typedef struct
{
BT_HDR hdr;
UINT16 max_int;
UINT16 latency;
UINT16 timeout;
-}tBTA_DM_API_UPDATE_CONN_PARAM;
+ tBTA_DM_BLE_CONN_PARAM_CBACK *p_conn_param_update_cback;
+} tBTA_DM_API_UPDATE_CONN_PARAM;
#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
typedef struct
return;
}
- /* discard responses if service change indication is received before operation completed */
- if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING && p_clcb->p_srcb->srvc_hdl_chg)
+ /* Except for MTU configuration, discard responses if service change indication is
+ * received before operation completed */
+ if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING && p_clcb->p_srcb->srvc_hdl_chg &&
+ op != GATTC_OPTYPE_CONFIG)
{
APPL_TRACE_DEBUG("Discard all responses when service change indication is received.");
p_data->op_cmpl.status = GATT_ERROR;
*******************************************************************************/
bool bta_gattc_cache_load(tBTA_GATTC_CLCB *p_clcb)
{
+
+#if (defined WEAR_DISABLE_GATT_CACHE && WEAR_DISABLE_GATT_CACHE == TRUE)
+ LOG_WARN(LOG_TAG, "%s GATT cache not used.", __func__);
+ return false;
+#endif
+
char fname[255] = {0};
bta_gattc_generate_cache_file_name(fname, p_clcb->p_srcb->server_bda);
/* no match found; disconnect sco, init sco variables */
else
{
- bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
+ /* should not force the sco state to shutdown state here */
BTM_RemoveSco(sco_idx);
}
}
if (tout < BTM_BLE_CONN_TIMEOUT_MIN_DEF)
tout = BTM_BLE_CONN_TIMEOUT_MIN_DEF;
- BTM_BleSetPrefConnParams (p_dev_cb->addr, min, max, latency, tout);
- L2CA_UpdateBleConnParams(p_dev_cb->addr, min, max, latency, tout);
+ BTM_BleSetPrefConnParams(p_dev_cb->addr, min, max, latency, tout);
+ L2CA_UpdateBleConnParams(p_dev_cb->addr, min, max, latency, tout, NULL);
}
else
{
*******************************************************************************/
void BTA_AgSetCodec(UINT16 handle, tBTA_AG_PEER_CODEC codec);
+void BTA_AgSetScoAllowed(bool value);
+
#ifdef __cplusplus
}
#endif
typedef void (tBTA_DM_BLE_PF_STATUS_CBACK) (UINT8 action, tBTA_STATUS status,
tBTA_DM_BLE_REF_VALUE ref_value);
+/* Connection update callback */
+typedef void (tBTA_DM_BLE_CONN_PARAM_CBACK) (BD_ADDR bd_addr, UINT16 interval, UINT16 latency,
+ UINT16 timeout, tBTA_STATUS status);
#define BTA_DM_BLE_PF_BRDCAST_ADDR_FILT 1
#define BTA_DM_BLE_PF_SERV_DATA_CHG_FILT 2
**
** Description Update connection parameters, can only be used when connection is up.
**
-** Parameters: bd_addr - BD address of the peer
+** Parameters: bd_addr - BD address of the peer
** min_int - minimum connection interval, [0x0004~ 0x4000]
** max_int - maximum connection interval, [0x0004~ 0x4000]
** latency - slave latency [0 ~ 500]
** Returns void
**
*******************************************************************************/
-extern void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int,
- UINT16 max_int, UINT16 latency, UINT16 timeout);
+extern void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int, UINT16 max_int,
+ UINT16 latency, UINT16 timeout,
+ tBTA_DM_BLE_CONN_PARAM_CBACK p_cback);
/*******************************************************************************
**
#define BTA_GATTC_SCAN_FLT_PARAM_EVT 32 /* Param filter event */
#define BTA_GATTC_SCAN_FLT_STATUS_EVT 33 /* Filter status event */
#define BTA_GATTC_ADV_VSC_EVT 34 /* ADV VSC event */
+#define BTA_GATTC_CONN_PARAM_UPD_EVT 35 /* Connection parameter update event */
typedef UINT8 tBTA_GATTC_EVT;
src/btif_debug.c \
src/btif_debug_btsnoop.c \
src/btif_debug_conn.c \
+ src/btif_debug_l2c.c \
src/btif_dm.c \
src/btif_gatt.c \
src/btif_gatt_client.c \
#include "bta_dm_ci.h"
#include "bt_utils.h"
#include "btif_dm.h"
+#if (defined WEAR_LE_IO_CAP_OVERRIDE && WEAR_LE_IO_CAP_OVERRIDE == TRUE)
+#include "btif_storage.h"
+#endif
#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
#include "bte_appl.h"
tBTA_LE_KEY_TYPE *p_resp_key )
{
UNUSED(bd_addr);
- /* Retrieve the properties from file system if possible */
+
+
+#if (defined WEAR_LE_IO_CAP_OVERRIDE && WEAR_LE_IO_CAP_OVERRIDE == TRUE)
+ /*
+ * Note: This is a Wear-specific feature for iOS pairing.
+ *
+ * Set WearLeIoCap config to force local IO capability to be BTM_IO_CAP_NONE
+ * (No input, no output) for the first bond creation, that indirectly
+ * triggers Just Works pairing.
+ */
+ if (btif_storage_get_num_bonded_devices() == 0)
+ bte_appl_cfg.ble_io_cap = BTM_IO_CAP_NONE;
+#endif
+
+ /* For certification testing purpose, LE IO capability can also be specified with
+ * "PTS_SmpOptions" in the BT stack configuration file (i.e. bt_stack.conf).
+ * Note that if "PTS_SmpOptions" is set, it could override IO capability set above.
+ */
tBTE_APPL_CFG nv_config;
if(btif_dm_get_smp_config(&nv_config))
bte_appl_cfg = nv_config;
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2016 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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <stdint.h>
+
+#include <hardware/bluetooth.h>
+
+// Captures a BLE connection parameter update request (Section 4.20 of
+// Bluetooth Core V4.2 specification):
+//
+// |min_interval| and |max_interval| define the minimum and maximum values for
+// the connection event interval (in units of 1.25ms and should be in the
+// [6, 3200] range).
+// |slave_latency_param| is the slave latency parameter for the connection in
+// number of connection events (unitless and should be less than 500).
+// |timeout_multiplier| is the connection timeout parameter (in units of 10ms
+// and should be in the [10, 3200] range).
+void btif_debug_ble_connection_update_request(bt_bdaddr_t bda,
+ uint16_t min_interval, uint16_t max_interval, uint16_t slave_latency_param,
+ uint16_t timeout_multiplier);
+
+// Captures a BLE connection parameter update response ((Section 4.21 of
+// Bluetooth Core V4.2 specification):
+//
+// |interval| defines the minimum and maximum values for the
+// connection event interval (in units of 1.25ms and should be in the
+// [6, 3200] range).
+// |slave_latency_param| is the slave latency parameter for the connection in
+// number of connection events (unitless and should be less than 500).
+// |timeout_multiplier| is the connection timeout parameter (in units of 10ms
+// and should be in the [10, 3200] range).
+void btif_debug_ble_connection_update_response(bt_bdaddr_t bda, uint8_t status,
+ uint16_t interval, uint16_t slave_latency_param,
+ uint16_t timeout_multiplier);
+
+// Dumps captured L2C information.
+void btif_debug_l2c_dump(int fd);
*******************************************************************************/
BOOLEAN btif_storage_is_restricted_device(const bt_bdaddr_t *remote_bd_addr);
+/*******************************************************************************
+**
+** Function btif_storage_get_num_bonded_devices
+**
+** Description BTIF storage API - Gets the number of bonded devices
+**
+** Returns the number of bonded devices
+**
+*******************************************************************************/
+int btif_storage_get_num_bonded_devices(void);
#if (BLE_INCLUDED == TRUE)
bt_status_t btif_storage_add_ble_bonding_key( bt_bdaddr_t *remote_bd_addr,
char *key,
#include "btif_storage.h"
#include "btif/include/btif_debug_btsnoop.h"
#include "btif/include/btif_debug_conn.h"
+#include "btif/include/btif_debug_l2c.h"
#include "btif/include/btif_media.h"
/************************************************************************************
btif_debug_conn_dump(fd);
btif_debug_bond_event_dump(fd);
btif_debug_a2dp_dump(fd);
+ btif_debug_l2c_dump(fd);
btif_debug_config_dump(fd);
wakelock_debug_dump(fd);
alarm_debug_dump(fd);
uint32_t disc_timeout;
bt_bdaddr_t bonded_devices[BTM_SEC_MAX_DEVICE_RECORDS];
bt_uuid_t local_uuids[BT_MAX_NUM_UUIDS];
+ bt_status_t status;
num_props = 0;
/* BD_ADDR */
BTIF_STORAGE_FILL_PROPERTY(&properties[num_props], BT_PROPERTY_BDADDR,
sizeof(addr), &addr);
- btif_storage_get_adapter_property(&properties[num_props]);
- num_props++;
+ status = btif_storage_get_adapter_property(&properties[num_props]);
+ // Add BT_PROPERTY_BDADDR property into list only when successful.
+ // Otherwise, skip this property entry.
+ if (status == BT_STATUS_SUCCESS) {
+ num_props++;
+ }
/* BD_NAME */
BTIF_STORAGE_FILL_PROPERTY(&properties[num_props], BT_PROPERTY_BDNAME,
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2016 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 <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+
+#include "btcore/include/bdaddr.h"
+#include "btif/include/btif_debug.h"
+#include "btif/include/btif_debug_l2c.h"
+
+#define NUM_UPDATE_REQUESTS 5
+#define NUM_UPDATE_RESPONSES 5
+
+#define INTERVAL_1_25_MS_MULTIPLIER 1.25f
+#define TIMEOUT_10_MS_MULTIPLIER 10
+
+typedef enum {
+ BTIF_DEBUG_CONNECTION_UPDATE_REQUEST,
+ BTIF_DEBUG_CONNECTION_UPDATE_RESPONSE,
+} btif_debug_ble_conn_update_t;
+
+/* Shared Connection update record for both request and response. */
+typedef struct ble_conn_update_t {
+ uint64_t timestamp_ms;
+ bt_bdaddr_t bda;
+ btif_debug_ble_conn_update_t type;
+ uint8_t status; /* Not populated for request. */
+ uint16_t min_interval; /* Not populated for response. */
+ uint16_t max_interval;
+ uint16_t latency;
+ uint16_t timeout;
+} ble_conn_update_t;
+
+static int update_request_index;
+static int update_response_index;
+static ble_conn_update_t last_ble_conn_update_requests[NUM_UPDATE_REQUESTS];
+static ble_conn_update_t last_ble_conn_update_responses[NUM_UPDATE_RESPONSES];
+
+static int dump_connection_update(int fd, const ble_conn_update_t *update) {
+ if (!update || update->timestamp_ms == 0) {
+ return -1;
+ }
+
+ /* Format timestamp */
+ const uint64_t msecs = update->timestamp_ms / 1000;
+ const time_t secs = msecs / 1000;
+ struct tm *ptm = localtime(&secs);
+ char time_buf[20] = {0};
+ strftime(time_buf, sizeof(time_buf), "%m-%d %H:%M:%S", ptm);
+ snprintf(time_buf, sizeof(time_buf), "%s.%03u", time_buf,
+ (uint16_t)(msecs % 1000));
+
+ /* Format address */
+ char addr_buf[18] = {0};
+ bdaddr_to_string(&update->bda, addr_buf, sizeof(addr_buf));
+
+ if (update->type == BTIF_DEBUG_CONNECTION_UPDATE_REQUEST) {
+ dprintf(fd,
+ " %s %s min interval=%d (%.2fms) max interval=%d (%.2fms) "
+ "latency parameter=%d timeout multiplier=%d (%dms)\n",
+ time_buf, addr_buf, update->min_interval,
+ (float)update->min_interval * INTERVAL_1_25_MS_MULTIPLIER,
+ update->max_interval,
+ (float)update->max_interval * INTERVAL_1_25_MS_MULTIPLIER,
+ update->latency, update->timeout,
+ update->timeout * TIMEOUT_10_MS_MULTIPLIER);
+ } else {
+ dprintf(fd,
+ " %s %s status=%d interval=%d (%.2fms) latency parameter=%d "
+ "timeout multiplier=%d (%dms)\n", time_buf,
+ addr_buf, update->status, update->max_interval,
+ (float)update->max_interval * INTERVAL_1_25_MS_MULTIPLIER,
+ update->latency, update->timeout,
+ update->timeout * TIMEOUT_10_MS_MULTIPLIER);
+ }
+
+ return 0;
+}
+
+static void record_connection_update(bt_bdaddr_t bda, uint8_t status,
+ uint16_t min_interval, uint16_t max_interval, uint16_t latency,
+ uint16_t timeout, btif_debug_ble_conn_update_t type,
+ ble_conn_update_t* update) {
+
+ memcpy(&update->bda, &bda, sizeof(bt_bdaddr_t));
+ update->type = type;
+ update->timestamp_ms = btif_debug_ts();
+ update->min_interval = min_interval;
+ update->max_interval = max_interval;
+ update->latency = latency;
+ update->timeout = timeout;
+ update->status = 0;
+}
+
+void btif_debug_ble_connection_update_request(bt_bdaddr_t bda,
+ uint16_t min_interval, uint16_t max_interval, uint16_t slave_latency_param,
+ uint16_t timeout_multiplier) {
+ ble_conn_update_t *request =
+ &last_ble_conn_update_requests[update_request_index];
+
+ record_connection_update(bda, 0, min_interval, max_interval, slave_latency_param,
+ timeout_multiplier, BTIF_DEBUG_CONNECTION_UPDATE_REQUEST, request);
+
+ update_request_index = (update_request_index == NUM_UPDATE_REQUESTS - 1) ?
+ 0 : update_request_index + 1;
+}
+
+void btif_debug_ble_connection_update_response(bt_bdaddr_t bda, uint8_t status,
+ uint16_t interval, uint16_t slave_latency_param,
+ uint16_t timeout_multiplier) {
+ ble_conn_update_t *response =
+ &last_ble_conn_update_responses[update_response_index];
+
+ record_connection_update(bda, status, 0, interval, slave_latency_param,
+ timeout_multiplier, BTIF_DEBUG_CONNECTION_UPDATE_RESPONSE, response);
+
+ update_response_index = (update_response_index == NUM_UPDATE_RESPONSES - 1) ?
+ 0 : update_response_index + 1;
+}
+
+void btif_debug_l2c_dump(int fd) {
+ dprintf(fd, "\nLE Connection Parameter Updates:\n");
+
+ int i;
+ dprintf(fd, " Last %d Request(s):\n", NUM_UPDATE_REQUESTS);
+ for (i = 0; i < NUM_UPDATE_REQUESTS; ++i) {
+ if (dump_connection_update(fd, &last_ble_conn_update_requests[i]) < 0 &&
+ i == 0) {
+ dprintf(fd, " None\n");
+ break;
+ }
+ }
+
+ dprintf(fd, "\n Last %d Response(s):\n", NUM_UPDATE_RESPONSES);
+ for (i = 0; i < NUM_UPDATE_RESPONSES; ++i) {
+ if (dump_connection_update(fd, &last_ble_conn_update_responses[i]) < 0 &&
+ i == 0) {
+ dprintf(fd, " None\n");
+ break;
+ }
+ }
+}
btif_storage_remove_bonded_device(&bdaddr);
state = BT_BOND_STATE_NONE;
} else {
+ /*
+ * Note: This is a Wear-specific feature for iOS pairing.
+ * Store the address of the first bonded device that is also of type LE to
+ * enable auto connection parameter update.
+ */
+#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
+ if (btif_storage_get_num_bonded_devices() == 0) {
+ bdstr_t bdstr;
+ bdaddr_to_string(&bdaddr, bdstr, sizeof(bdstr));
+ btif_config_set_str("Adapter", "AutoConnParamUpdateAddr", bdstr);
+ }
+#endif
btif_dm_save_ble_bonding_keys();
BTA_GATTC_Refresh(bd_addr.address);
btif_dm_get_remote_services_by_transport(&bd_addr, BTA_GATT_TRANSPORT_LE);
#include "btif_gatt_multi_adv_util.h"
#include "btif_gatt_util.h"
#include "btif_storage.h"
-#include "btif_storage.h"
#include "osi/include/log.h"
+#include "osi/include/alarm.h"
+#include "stack/include/gatt_api.h"
#include "vendor_api.h"
/*******************************************************************************
#define BLE_RESOLVE_ADDR_MSB 0x40 /* bit7, bit6 is 01 to be resolvable random */
#define BLE_RESOLVE_ADDR_MASK 0xc0 /* bit 6, and bit7 */
#define BTM_BLE_IS_RESOLVE_BDA(x) ((x[0] & BLE_RESOLVE_ADDR_MASK) == BLE_RESOLVE_ADDR_MSB)
+#define BT_CONN_PARAM_UPDATE_STATUS 1010003
typedef enum {
BTIF_GATTC_REGISTER_APP = 1000,
typedef struct
{
+ uint8_t client_if;
bt_bdaddr_t bd_addr;
- uint16_t min_interval;
- uint16_t max_interval;
+ uint16_t requested_min_interval;
+ uint16_t requested_max_interval;
+ uint16_t configured_interval;
uint16_t timeout;
uint16_t latency;
-} btif_conn_param_cb_t;
+ uint8_t status;
+}__attribute__((packed)) btif_conn_param_cb_t;
typedef struct
{
static uint8_t rssi_request_client_if;
/*******************************************************************************
+** Auto Connection Parameter Update
+**
+** Feature is enabled when WEAR_AUTO_CONN_PARAM_UPDATE build config is set to
+** TRUE. It looks for a whitelisted address in the configuration file and
+** automatically applies a connection interval parameter update
+** (WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS) when the connection is idle for a
+** specific period of time (WEAR_AUTO_CONN_IDLE_TIMEOUT_MS).
+********************************************************************************/
+#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
+typedef struct
+{
+ bt_bdaddr_t device_address;
+ uint16_t min_interval;
+ uint16_t max_interval;
+ uint16_t timeout;
+ uint16_t latency;
+ bool is_auto_update_address_known;
+ bool is_auto_update_enabled;
+ bool is_updating;
+ alarm_t *check_idle_alarm;
+} btgatt_auto_connection_param_update_cb_t;
+
+static btgatt_auto_connection_param_update_cb_t auto_conn_param_update_cb;
+
+static bt_status_t btif_gattc_conn_parameter_update_internal(const bt_bdaddr_t *bd_addr, int min_interval,
+ int max_interval, int latency, int timeout);
+
+static void auto_connection_param_update_idle_cb(UNUSED_ATTR void *data)
+{
+ btgatt_auto_connection_param_update_cb_t *auto_update_cb =
+ (btgatt_auto_connection_param_update_cb_t *)data;
+
+ if (auto_conn_param_update_cb.is_updating)
+ {
+ LOG_WARN(LOG_TAG, "%s another connection update in progress", __FUNCTION__);
+ return;
+ }
+
+ btif_gattc_conn_parameter_update_internal(&auto_update_cb->device_address,
+ WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS, WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS, 0, 2000);
+ LOG_INFO(LOG_TAG, "%s auto adjust connection interval to %dms", __FUNCTION__,
+ (int)(WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS * 1.25f));
+}
+
+static void maybe_set_connection_param_update_in_progress(const bt_bdaddr_t *bd_addr, bool in_progress)
+{
+ if (auto_conn_param_update_cb.is_auto_update_enabled &&
+ bdcmp(auto_conn_param_update_cb.device_address.address, bd_addr->address) == 0)
+ {
+ auto_conn_param_update_cb.is_updating = in_progress;
+ }
+}
+
+static void maybe_enable_auto_connection_param_update(const bt_bdaddr_t *bd_addr, int min_interval,
+ int max_interval, int latency, int timeout)
+{
+ /* First check if there is a whitelisted address to enable auto connection param update */
+ if (!auto_conn_param_update_cb.is_auto_update_address_known)
+ {
+ bdstr_t bdstr;
+ int bdstr_size = sizeof(bdstr);
+ /*
+ * If AutoConnParamUpdateAddr is not set from bonding, infer the first LE address performing
+ * connection parameter update as the companion.
+ */
+ if (!btif_config_get_str("Adapter", "AutoConnParamUpdateAddr", bdstr, &bdstr_size)) {
+ bdaddr_to_string(bd_addr, bdstr, bdstr_size);
+ btif_config_set_str("Adapter", "AutoConnParamUpdateAddr", bdstr);
+ LOG_INFO(LOG_TAG, "%s force set AutoConnParamUpdateAddr: %s", __FUNCTION__, bdstr);
+ }
+
+ bdcpy(auto_conn_param_update_cb.device_address.address, bd_addr->address);
+ auto_conn_param_update_cb.is_auto_update_address_known = true;
+ LOG_INFO(LOG_TAG, "%s auto connection param update for address: %s", __FUNCTION__, bdstr);
+ }
+
+ /* If the address matches the auto update address, store the connection parameter value */
+ if (bdcmp(auto_conn_param_update_cb.device_address.address, bd_addr->address) == 0)
+ {
+ auto_conn_param_update_cb.min_interval = min_interval;
+ auto_conn_param_update_cb.max_interval = max_interval;
+ auto_conn_param_update_cb.timeout = timeout;
+ auto_conn_param_update_cb.latency = latency;
+ auto_conn_param_update_cb.is_auto_update_enabled = true;
+ }
+}
+
+static void maybe_restore_connection_parameters(BD_ADDR address) {
+ /*
+ * Will not perform auto connection parameter update if:
+ *
+ * - feature not enabled (yet)
+ * - address doesn't match auto update address
+ * - connection parameter update is in progress
+ */
+ if (!auto_conn_param_update_cb.is_auto_update_enabled ||
+ (bdcmp(auto_conn_param_update_cb.device_address.address, address) != 0) ||
+ auto_conn_param_update_cb.is_updating)
+ {
+ return;
+ }
+
+ if (alarm_is_scheduled(auto_conn_param_update_cb.check_idle_alarm))
+ {
+ /* Idle alarm is scheduled, reschedule it */
+ alarm_cancel(auto_conn_param_update_cb.check_idle_alarm);
+ }
+ else
+ {
+ /* No idle alarm and no update in progress, restore specified connection parameters */
+ btif_gattc_conn_parameter_update_internal(&auto_conn_param_update_cb.device_address,
+ auto_conn_param_update_cb.min_interval,
+ auto_conn_param_update_cb.max_interval,
+ auto_conn_param_update_cb.latency,
+ auto_conn_param_update_cb.timeout);
+ LOG_VERBOSE(LOG_TAG, "%s restore connection parameters", __FUNCTION__);
+ }
+
+ /* Schedule idle alarm */
+ if (!auto_conn_param_update_cb.check_idle_alarm)
+ {
+ auto_conn_param_update_cb.check_idle_alarm =
+ alarm_new("gatt_client.auto_conn_param_update_idle_alarm");
+ }
+ alarm_set(auto_conn_param_update_cb.check_idle_alarm, WEAR_AUTO_CONN_IDLE_TIMEOUT_MS,
+ auto_connection_param_update_idle_cb, &auto_conn_param_update_cb);
+
+ return;
+}
+#endif
+
+/*******************************************************************************
** Static functions
********************************************************************************/
if (p_data->notify.is_notify == FALSE)
BTA_GATTC_SendIndConfirm(p_data->notify.conn_id, p_data->notify.handle);
+#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
+ maybe_restore_connection_parameters(data.bda.address);
+#endif
+
break;
}
break;
}
+ case BTA_GATTC_CONN_PARAM_UPD_EVT:
+ {
+ btif_conn_param_cb_t *p_btif_cb = (btif_conn_param_cb_t *)p_param;
+#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
+ maybe_set_connection_param_update_in_progress(&p_btif_cb->bd_addr, false);
+#endif
+ /* Log update failures */
+ if (p_btif_cb->status != 0)
+ {
+ LOG_EVENT_INT(BT_CONN_PARAM_UPDATE_STATUS, p_btif_cb->status);
+ }
+ break;
+ }
+
case BTIF_GATTC_SCAN_PARAM_EVT:
{
btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t *)p_param;
(char*) &btif_cb, sizeof(btgatt_adv_filter_cb_t), NULL);
}
+static void bta_gattc_conn_param_update_cback(BD_ADDR bd_addr, UINT16 interval,
+ UINT16 latency, UINT16 timeout, tBTA_STATUS status)
+{
+ btif_conn_param_cb_t btif_cb;
+
+ bdcpy(btif_cb.bd_addr.address, bd_addr);
+ btif_cb.configured_interval = interval;
+ btif_cb.latency = latency;
+ btif_cb.timeout = timeout;
+ btif_cb.status = status;
+ btif_transfer_context(btif_gattc_upstreams_evt, BTA_GATTC_CONN_PARAM_UPD_EVT,
+ (char*) &btif_cb, sizeof(btif_conn_param_cb_t), NULL);
+}
+
static void btgattc_free_event_data(UINT16 event, char *event_data)
{
switch (event)
break;
case BTIF_GATTC_WRITE_CHAR:
+ {
+#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
+ /* TODO(jackyc): find a cleaner way to get address from connection id */
+ tGATT_IF gatt_if;
+ BD_ADDR bd_addr;
+ tBT_TRANSPORT transport;
+ if (GATT_GetConnectionInfor(p_cb->conn_id, &gatt_if, bd_addr, &transport) == TRUE)
+ {
+ maybe_restore_connection_parameters(bd_addr);
+ }
+#endif
BTA_GATTC_WriteCharValue(p_cb->conn_id, p_cb->handle, p_cb->write_type,
p_cb->len, p_cb->value, p_cb->auth_req);
break;
+ }
case BTIF_GATTC_WRITE_CHAR_DESCR:
descr_val.len = p_cb->len;
if (BTA_DmGetConnectionState(p_conn_param_cb->bd_addr.address))
{
BTA_DmBleUpdateConnectionParams(p_conn_param_cb->bd_addr.address,
- p_conn_param_cb->min_interval, p_conn_param_cb->max_interval,
- p_conn_param_cb->latency, p_conn_param_cb->timeout);
+ p_conn_param_cb->requested_min_interval,
+ p_conn_param_cb->requested_max_interval,
+ p_conn_param_cb->latency, p_conn_param_cb->timeout,
+ bta_gattc_conn_param_update_cback);
} else {
BTA_DmSetBlePrefConnParams(p_conn_param_cb->bd_addr.address,
- p_conn_param_cb->min_interval, p_conn_param_cb->max_interval,
+ p_conn_param_cb->requested_min_interval,
+ p_conn_param_cb->requested_max_interval,
p_conn_param_cb->latency, p_conn_param_cb->timeout);
}
break;
(char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
}
-static bt_status_t btif_gattc_conn_parameter_update(const bt_bdaddr_t *bd_addr, int min_interval,
- int max_interval, int latency, int timeout)
+static bt_status_t btif_gattc_conn_parameter_update_internal(const bt_bdaddr_t *bd_addr, int min_interval,
+ int max_interval, int latency, int timeout)
{
CHECK_BTGATT_INIT();
+#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
+ maybe_set_connection_param_update_in_progress(bd_addr, true);
+#endif
btif_conn_param_cb_t btif_cb;
- btif_cb.min_interval = min_interval;
- btif_cb.max_interval = max_interval;
+ btif_cb.requested_min_interval = min_interval;
+ btif_cb.requested_max_interval = max_interval;
btif_cb.latency = latency;
btif_cb.timeout = timeout;
bdcpy(btif_cb.bd_addr.address, bd_addr->address);
(char*) &btif_cb, sizeof(btif_conn_param_cb_t), NULL);
}
+static bt_status_t btif_gattc_conn_parameter_update(const bt_bdaddr_t *bd_addr, int min_interval,
+ int max_interval, int latency, int timeout)
+{
+#if (defined(WEAR_AUTO_CONN_PARAM_UPDATE) && (WEAR_AUTO_CONN_PARAM_UPDATE == TRUE))
+ maybe_enable_auto_connection_param_update(bd_addr, min_interval, max_interval, latency, timeout);
+#endif
+
+ return btif_gattc_conn_parameter_update_internal(bd_addr, min_interval, max_interval, latency, timeout);
+}
+
static bt_status_t btif_gattc_scan_filter_param_setup(btgatt_filt_param_setup_t
filt_param)
{
return BT_STATUS_SUCCESS;
}
+static bt_status_t set_sco_allowed(bool value)
+{
+ CHECK_BTHF_INIT();
+
+ BTA_AgSetScoAllowed(value);
+ return BT_STATUS_SUCCESS;
+}
+
/*******************************************************************************
**
** Function formatted_at_response
cleanup,
configure_wbs,
bind_response,
+ set_sco_allowed,
};
/*******************************************************************************
static void btm_read_rssi_cb(void *data)
{
- assert(data);
+ if (data == NULL)
+ {
+ LOG_ERROR(LOG_TAG, "%s RSSI request timed out", __func__);
+ return;
+ }
tBTM_RSSI_RESULTS *result = (tBTM_RSSI_RESULTS*)data;
if (result->status != BTM_SUCCESS)
#include "osi/include/log.h"
#include "osi/include/osi.h"
+#include "device/include/controller.h"
+
/************************************************************************************
** Constants & Macros
************************************************************************************/
/* This is a local property to add a device found */
#define BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP 0xFF
-#define BTIF_STORAGE_GET_ADAPTER_PROP(t,v,l,p) \
- {p.type=t;p.val=v;p.len=l; btif_storage_get_adapter_property(&p);}
+// TODO: This macro should be converted to a function
+#define BTIF_STORAGE_GET_ADAPTER_PROP(s, t,v,l,p) \
+ {p.type=t;p.val=v;p.len=l; s = btif_storage_get_adapter_property(&p);}
+// TODO: This macro should be converted to a function
#define BTIF_STORAGE_GET_REMOTE_PROP(b,t,v,l,p) \
{p.type=t;p.val=v;p.len=l;btif_storage_get_remote_device_property(b,&p);}
if (property->type == BT_PROPERTY_BDADDR)
{
bt_bdaddr_t *bd_addr = (bt_bdaddr_t*)property->val;
- /* This has been cached in btif. Just fetch it from there */
- memcpy(bd_addr, &btif_local_bd_addr, sizeof(bt_bdaddr_t));
+ /* Fetch the local BD ADDR */
+ const controller_t* controller = controller_get_interface();
+ if (controller->get_is_ready() == false) {
+ BTIF_TRACE_DEBUG("%s: Controller not ready! Unable to return Bluetooth Address",
+ __FUNCTION__);
+ memset(bd_addr, 0, sizeof(bt_bdaddr_t));
+ return BT_STATUS_FAIL;
+ } else {
+ BTIF_TRACE_DEBUG("%s: Controller ready!", __FUNCTION__);
+ memcpy(bd_addr, controller->get_address(), sizeof(bt_bdaddr_t));
+ }
property->len = sizeof(bt_bdaddr_t);
return BT_STATUS_SUCCESS;
}
uint32_t disc_timeout;
bt_uuid_t local_uuids[BT_MAX_NUM_UUIDS];
bt_uuid_t remote_uuids[BT_MAX_NUM_UUIDS];
+ bt_status_t status;
btif_in_fetch_bonded_devices(&bonded_devices, 1);
memset(adapter_props, 0, sizeof(adapter_props));
/* BD_ADDR */
- BTIF_STORAGE_GET_ADAPTER_PROP(BT_PROPERTY_BDADDR, &addr, sizeof(addr),
+ BTIF_STORAGE_GET_ADAPTER_PROP(status, BT_PROPERTY_BDADDR, &addr, sizeof(addr),
adapter_props[num_props]);
- num_props++;
+ // Add BT_PROPERTY_BDADDR property into list only when successful.
+ // Otherwise, skip this property entry.
+ if (status == BT_STATUS_SUCCESS) {
+ num_props++;
+ }
/* BD_NAME */
- BTIF_STORAGE_GET_ADAPTER_PROP(BT_PROPERTY_BDNAME, &name, sizeof(name),
+ BTIF_STORAGE_GET_ADAPTER_PROP(status, BT_PROPERTY_BDNAME, &name, sizeof(name),
adapter_props[num_props]);
num_props++;
num_props++;
/* DISC_TIMEOUT */
- BTIF_STORAGE_GET_ADAPTER_PROP(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
+ BTIF_STORAGE_GET_ADAPTER_PROP(status, BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
&disc_timeout, sizeof(disc_timeout),
adapter_props[num_props]);
num_props++;
num_props++;
/* LOCAL UUIDs */
- BTIF_STORAGE_GET_ADAPTER_PROP(BT_PROPERTY_UUIDS,
+ BTIF_STORAGE_GET_ADAPTER_PROP(status, BT_PROPERTY_UUIDS,
local_uuids, sizeof(local_uuids),
adapter_props[num_props]);
num_props++;
/*******************************************************************************
**
+** Function btif_storage_get_num_bonded_devices
+**
+** Description BTIF storage API - Gets the number of bonded devices
+**
+** Returns the number of bonded devices
+**
+*******************************************************************************/
+int btif_storage_get_num_bonded_devices(void) {
+ btif_bonded_devices_t bonded_devices;
+ btif_in_fetch_bonded_devices(&bonded_devices, 0);
+ return bonded_devices.num_devices;
+}
+
+/*******************************************************************************
+**
** Function btif_storage_read_hl_apps_cb
**
** Description BTIF storage API - Read HL application control block from NVRAM
module_shut_down(get_module(CONTROLLER_MODULE)); // Doesn't do any work, just puts it in a restartable state
LOG_INFO(LOG_TAG, "%s finished", __func__);
+ hack_future = future_new();
btif_thread_post(event_signal_stack_down, NULL);
+ future_await(hack_future);
}
static void ensure_stack_is_not_running(void) {
static void event_signal_stack_down(UNUSED_ATTR void *context) {
HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_OFF);
+ future_ready(stack_manager_get_hack_future(), FUTURE_SUCCESS);
}
static void ensure_manager_initialized(void) {
// Keyboards should use a variable pin at all times. However, some keyboards
// require a fixed pin of all 0000. This workaround enables auto pairing for
// those keyboards.
- INTEROP_KEYBOARD_REQUIRES_FIXED_PIN,
-
- // Some headsets have audio jitter issues because of increased re-transmissions as the
- // 3 Mbps packets have a lower link margin, and are more prone to interference. We can
- // disable 3DH packets (use only 2DH packets) for the ACL link to improve sensitivity
- // when streaming A2DP audio to the headset. Air sniffer logs show reduced
- // re-transmissions after switching to 2DH packets.
- //
- // Disable 3Mbps packets and use only 2Mbps packets for ACL links when streaming audio.
- INTEROP_2MBPS_LINK_ONLY
+ INTEROP_KEYBOARD_REQUIRES_FIXED_PIN
} interop_feature_t;
// Check if a given |addr| matches a known interoperability workaround as identified
{{{0x44, 0x5e, 0xf3, 0,0,0}}, 3, INTEROP_DISABLE_ABSOLUTE_VOLUME},
{{{0xd4, 0x9c, 0x28, 0,0,0}}, 3, INTEROP_DISABLE_ABSOLUTE_VOLUME},
- // JayBird Family
- {{{0x00, 0x18, 0x91, 0,0,0}}, 3, INTEROP_2MBPS_LINK_ONLY},
-
// LG Tone HBS-730 - unacceptably loud volume
{{{0x00, 0x18, 0x6b, 0,0,0}}, 3, INTEROP_DISABLE_ABSOLUTE_VOLUME},
{{{0xb8, 0xad, 0x3e, 0,0,0}}, 3, INTEROP_DISABLE_ABSOLUTE_VOLUME},
CASE_RETURN_STR(INTEROP_DISABLE_ABSOLUTE_VOLUME)
CASE_RETURN_STR(INTEROP_DISABLE_AUTO_PAIRING)
CASE_RETURN_STR(INTEROP_KEYBOARD_REQUIRES_FIXED_PIN)
- CASE_RETURN_STR(INTEROP_2MBPS_LINK_ONLY)
}
return "UNKNOWN";
gettimeofday(&tv, NULL);
// Timestamp is in microseconds.
- uint64_t timestamp = tv.tv_sec * 1000 * 1000LL;
+ uint64_t timestamp = tv.tv_sec;
+ timestamp *= (uint64_t)1000000ULL;
timestamp += tv.tv_usec;
timestamp += BTSNOOP_EPOCH_DELTA;
return timestamp;
#include "bt_trace.h"
+/******************************************************************************
+**
+** Wear
+**
+******************************************************************************/
+
+/* Enable/disable LE IO capability overriding to no-input-no-output on first bond */
+#ifndef WEAR_LE_IO_CAP_OVERRIDE
+#define WEAR_LE_IO_CAP_OVERRIDE FALSE
+#endif
+
+/*
+ * Enable/disable LE auto connection parameter update.
+ * When enabled, the first bonded device that is also of type LE will be whitelisted
+ * to use auto connection parameter update.
+ */
+#ifndef WEAR_AUTO_CONN_PARAM_UPDATE
+#define WEAR_AUTO_CONN_PARAM_UPDATE FALSE
+#endif
+
+/*
+ * Idle timeout period in milliseconds for auto connection parameter update.
+ * Only used when WEAR_AUTO_CONN_PARAM_UPDATE is enabled.
+ */
+#ifndef WEAR_AUTO_CONN_IDLE_TIMEOUT_MS
+#define WEAR_AUTO_CONN_IDLE_TIMEOUT_MS 10000
+#endif
+
+/*
+ * Connection interval parameter applied when the connection is detected to be idle for
+ * WEAR_AUTO_CONN_IDLE_TIMEOUT_MS of time.
+ * Only used when WEAR_AUTO_CONN_PARAM_UPDATE is enabled.
+ */
+#ifndef WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS
+#define WEAR_AUTO_CONN_IDLE_INTERVAL_1_25_MS 72
+#endif
+
+/*
+ * Disable the use of local GATT cache. This forces service discovery on connection
+ * establishment.
+ */
+#ifndef WEAR_DISABLE_GATT_CACHE
+#define WEAR_DISABLE_GATT_CACHE TRUE
+#endif
+
#endif /* BT_TARGET_H */
#include "l2cdefs.h"
#include "btm_api.h"
#include "btm_int.h"
-#include "device/include/interop.h"
+
/* callback function declarations */
void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
p_tbl->state = AVDT_AD_ST_SEC_ACP;
p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_ACP;
- if (interop_match_addr(INTEROP_2MBPS_LINK_ONLY, (const bt_bdaddr_t *)&bd_addr)) {
- // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
- tACL_CONN *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));
- }
+ // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
+ tACL_CONN *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));
/* Check the security */
rc = btm_sec_mx_access_request (bd_addr, AVDT_PSM,
p_tbl->lcid = lcid;
p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_INT;
- if (interop_match_addr(INTEROP_2MBPS_LINK_ONLY, (const bt_bdaddr_t *) &p_ccb->peer_addr)) {
- // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
- tACL_CONN *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));
- }
+ // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
+ tACL_CONN *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));
/* Check the security */
btm_sec_mx_access_request (p_ccb->peer_addr, AVDT_PSM,
if (ret)
{
if (!opportunistic)
- gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, FALSE);
+ gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, TRUE);
else
GATT_TRACE_DEBUG("%s: connection is opportunistic, not updating app usage",
__func__);
#include "bt_target.h"
#include "l2cdefs.h"
#include "hcidefs.h"
+#include "bta_api.h"
/*****************************************************************************
** Constants
** Return value: TRUE if update started
**
*******************************************************************************/
-extern BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bdRa, UINT16 min_int,
- UINT16 max_int, UINT16 latency, UINT16 timeout);
+extern BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bdRa, UINT16 min_int, UINT16 max_int,
+ UINT16 latency, UINT16 timeout,
+ tBTA_DM_BLE_CONN_PARAM_CBACK *p_cback);
/*******************************************************************************
**
#include "hcimsgs.h"
#include "device/include/controller.h"
#include "stack_config.h"
+#include "btif_debug_l2c.h"
#include "log/log.h"
#if (BLE_INCLUDED == TRUE)
** Return value: TRUE if update started
**
*******************************************************************************/
-BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_int,
- UINT16 latency, UINT16 timeout)
+BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int,
+ UINT16 max_int, UINT16 latency, UINT16 timeout,
+ tBTA_DM_BLE_CONN_PARAM_CBACK *p_callback)
{
tL2C_LCB *p_lcb;
tACL_CONN *p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE);
p_lcb->latency = latency;
p_lcb->timeout = timeout;
p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
+ p_lcb->p_conn_param_update_cb = p_callback;
l2cble_start_conn_update(p_lcb);
*******************************************************************************/
static void l2cble_start_conn_update (tL2C_LCB *p_lcb)
{
- UINT16 min_conn_int, max_conn_int, slave_latency, supervision_tout;
tACL_CONN *p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE);
// TODO(armansito): The return value of this call wasn't being used but the
if (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE)
{
+ UINT16 min_conn_int, max_conn_int, slave_latency, supervision_tout;
/* application requests to disable parameters update.
If parameters are already updated, lets set them
up to what has been requested during connection establishement */
btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->min_interval,
p_lcb->max_interval, p_lcb->latency, p_lcb->timeout, 0, 0);
p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
+
+ /* Record the BLE connection update request if the role is master device */
+ bt_bdaddr_t bd_addr;
+ bdcpy(bd_addr.address, p_lcb->remote_bd_addr);
+ btif_debug_ble_connection_update_request(bd_addr, p_lcb->min_interval, p_lcb->max_interval,
+ p_lcb->latency, p_lcb->timeout);
}
else
{
}
p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM;
p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM;
- }
+
+ }
}
+
}
/*******************************************************************************
l2cble_start_conn_update(p_lcb);
+ /* Callback to upper layer */
+ if (p_lcb->p_conn_param_update_cb) {
+ p_lcb->p_conn_param_update_cb(p_lcb->remote_bd_addr, interval, latency,
+ timeout, status);
+ }
+
+ /* Record the BLE connection update response. */
+ bt_bdaddr_t bd_addr;
+ bdcpy(bd_addr.address, p_lcb->remote_bd_addr);
+ btif_debug_ble_connection_update_response(bd_addr, status, interval,
+ latency, timeout);
+
L2CAP_TRACE_DEBUG("%s: conn_update_mask=%d", __func__, p_lcb->conn_update_mask);
}
break;
case L2CAP_CMD_DISC_REQ:
- if (p + 4 >= p_pkt_end) {
- android_errorWriteLog(0x534e4554, "63146237");
- return;
- }
STREAM_TO_UINT16 (lcid, p);
STREAM_TO_UINT16 (rcid, p);
UINT16 latency;
UINT16 timeout;
+ tBTA_DM_BLE_CONN_PARAM_CBACK *p_conn_param_update_cb;
#endif
#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
extern BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport);
extern BOOLEAN l2cu_create_conn_after_switch (tL2C_LCB *p_lcb);
-extern BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb);
+extern BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb, UINT16 *fixed_cid);
extern void l2cu_resubmit_pending_sec_req (BD_ADDR p_bda);
extern void l2cu_initialize_amp_ccb (tL2C_LCB *p_lcb);
extern void l2cu_adjust_out_mps (tL2C_CCB *p_ccb);
extern fixed_queue_t *btu_general_alarm_queue;
-static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf);
+static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf, UINT16 fixed_cid);
/*******************************************************************************
**
{
int xx;
BOOLEAN single_write = FALSE;
+ UINT16 fixed_cid;
/* Save the channel ID for faster counting */
if (p_buf)
/* Loop through, starting at the next */
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++)
{
+ /* Check for wraparound */
+ if (p_lcb == &l2cb.lcb_pool[MAX_L2CAP_LINKS])
+ p_lcb = &l2cb.lcb_pool[0];
+
/* If controller window is full, nothing to do */
- if (((l2cb.controller_xmit_window == 0 ||
- (l2cb.round_robin_unacked >= l2cb.round_robin_quota))
+ if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
+ (l2cb.controller_xmit_window == 0 ||
+ l2cb.round_robin_unacked >= l2cb.round_robin_quota))
+ {
#if (BLE_INCLUDED == TRUE)
- && (p_lcb->transport == BT_TRANSPORT_BR_EDR)
- )
- || (p_lcb->transport == BT_TRANSPORT_LE &&
- (l2cb.ble_round_robin_unacked >= l2cb.ble_round_robin_quota ||
- l2cb.controller_le_xmit_window == 0 )))
+ continue;
#else
- ))
+ /* No more quota and only BR/EDR supported, so nothing more to do*/
+ break;
#endif
- break;
-
+ }
- /* Check for wraparound */
- if (p_lcb == &l2cb.lcb_pool[MAX_L2CAP_LINKS])
- p_lcb = &l2cb.lcb_pool[0];
+#if (BLE_INCLUDED == TRUE)
+ if (p_lcb->transport == BT_TRANSPORT_LE &&
+ (l2cb.controller_le_xmit_window == 0 ||
+ l2cb.ble_round_robin_unacked >= l2cb.ble_round_robin_quota))
+ {
+ continue;
+ }
+#endif
if ( (!p_lcb->in_use)
|| (p_lcb->partial_segment_being_sent)
if (!list_is_empty(p_lcb->link_xmit_data_q)) {
p_buf = (BT_HDR *)list_front(p_lcb->link_xmit_data_q);
list_remove(p_lcb->link_xmit_data_q, p_buf);
- l2c_link_send_to_lower (p_lcb, p_buf);
+ l2c_link_send_to_lower (p_lcb, p_buf, 0);
}
else if (single_write)
{
break;
}
/* If nothing on the link queue, check the channel queue */
- else if ((p_buf = l2cu_get_next_buffer_to_send (p_lcb)) != NULL)
+ else if ((p_buf = l2cu_get_next_buffer_to_send (p_lcb, &fixed_cid)) != NULL)
{
- l2c_link_send_to_lower (p_lcb, p_buf);
+ l2c_link_send_to_lower (p_lcb, p_buf, fixed_cid);
}
}
p_buf = (BT_HDR *)list_front(p_lcb->link_xmit_data_q);
list_remove(p_lcb->link_xmit_data_q, p_buf);
- if (!l2c_link_send_to_lower (p_lcb, p_buf))
+ if (!l2c_link_send_to_lower (p_lcb, p_buf, 0))
break;
}
while ((l2cb.controller_xmit_window != 0) && (p_lcb->sent_not_acked < p_lcb->link_xmit_quota))
#endif
{
- if ((p_buf = l2cu_get_next_buffer_to_send (p_lcb)) == NULL)
+ if ((p_buf = l2cu_get_next_buffer_to_send (p_lcb, &fixed_cid)) == NULL)
break;
- if (!l2c_link_send_to_lower (p_lcb, p_buf))
+ if (!l2c_link_send_to_lower (p_lcb, p_buf, fixed_cid))
break;
}
}
** Returns TRUE for success, FALSE for fail
**
*******************************************************************************/
-static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf)
+static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf, UINT16 fixed_cid)
{
UINT16 num_segs;
UINT16 xmit_window, acl_data_size;
}
#endif
+ if (fixed_cid != 0)
+ {
+ L2CAP_TRACE_DEBUG("%s: fixed_cid = %d, send tx complete", __func__, fixed_cid);
+ /* send tx complete */
+ if (l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedTxComplete_Cb)
+ {
+ (*l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedTxComplete_Cb)(fixed_cid, 1);
+ }
+ }
return TRUE;
}
{
if (!p_lcb->ccb_queue.p_first_ccb)
{
+ // Closing a security channel on LE device should not start connection
+ // timeout
+ if (p_lcb->transport == BT_TRANSPORT_LE &&
+ p_ccb->local_cid == L2CAP_SMP_CID)
+ return;
+
l2cu_no_dynamic_ccbs (p_lcb);
}
else
** Returns pointer to buffer or NULL
**
*******************************************************************************/
-BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb)
+BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb, UINT16 *fixed_cid)
{
tL2C_CCB *p_ccb;
BT_HDR *p_buf;
#if (L2CAP_NUM_FIXED_CHNLS > 0)
int xx;
+ *fixed_cid = 0;
for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
{
if ((p_ccb = p_lcb->p_fixed_ccbs[xx]) == NULL)
L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send: No data to be sent");
return (NULL);
}
- /* send tx complete */
- if (l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)
- (*l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)(p_ccb->local_cid, 1);
+ if (fixed_cid != NULL)
+ {
+ *fixed_cid = p_ccb->local_cid;
+ L2CAP_TRACE_DEBUG("l2cu_get_buffer_to_send: fixed_cid = %d", *fixed_cid);
+ }
l2cu_check_channel_congestion (p_ccb);
l2cu_set_acl_hci_header (p_buf, p_ccb);