summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPriti Aghera <paghera@broadcom.com>2014-12-18 13:55:48 -0800
committerAndre Eisenbach <eisenbach@google.com>2015-04-15 23:25:17 -0700
commit636d6714a4c08dd99d2147dcce05dc3892e804b4 (patch)
tree1ae16fa567a6d95b8424bc1bbec3587412e7305a
parent8a0b80ebad0cb187ff7856d14b83fa74aed51d98 (diff)
downloadandroid_system_bt-636d6714a4c08dd99d2147dcce05dc3892e804b4.tar.gz
android_system_bt-636d6714a4c08dd99d2147dcce05dc3892e804b4.tar.bz2
android_system_bt-636d6714a4c08dd99d2147dcce05dc3892e804b4.zip
LE Data Packet Extension support
Included support for LE data packet extension feature according to BT 4.2 spec. This patch checks if the controller supports LE packet extension and provides functions to set the PDU length. Bug: 20013956 Change-Id: I6a92970fede2f793ad48c9fa2e0247ad00297533
-rw-r--r--bta/dm/bta_dm_act.c18
-rw-r--r--bta/dm/bta_dm_api.c26
-rw-r--r--bta/dm/bta_dm_int.h11
-rw-r--r--bta/dm/bta_dm_main.c1
-rw-r--r--bta/include/bta_api.h11
-rw-r--r--device/include/controller.h3
-rw-r--r--device/src/controller.c25
-rw-r--r--hci/include/hci_packet_factory.h1
-rw-r--r--hci/include/hci_packet_parser.h4
-rw-r--r--hci/src/hci_packet_factory.c5
-rw-r--r--hci/src/hci_packet_parser.c13
-rw-r--r--stack/btm/btm_ble.c49
-rw-r--r--stack/btu/btu_hcif.c29
-rw-r--r--stack/gatt/gatt_cl.c2
-rw-r--r--[-rwxr-xr-x]stack/gatt/gatt_sr.c4
-rw-r--r--stack/hcic/hciblecmds.c23
-rw-r--r--stack/include/btm_ble_api.h24
-rw-r--r--stack/include/hcidefs.h11
-rw-r--r--stack/include/hcimsgs.h7
-rw-r--r--stack/l2cap/l2c_ble.c98
-rw-r--r--stack/l2cap/l2c_int.h10
-rw-r--r--stack/l2cap/l2c_utils.c1
22 files changed, 365 insertions, 11 deletions
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index 68d99d41f..1251f5d5b 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -4757,6 +4757,24 @@ void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data)
/*******************************************************************************
**
+** Function bta_dm_ble_set_data_length
+**
+** Description This function set the maximum transmission packet size
+**
+** Parameters
+**
+*******************************************************************************/
+void bta_dm_ble_set_data_length(tBTA_DM_MSG *p_data)
+{
+ if (BTM_SetBleDataLength(p_data->ble_set_data_length.remote_bda,
+ p_data->ble_set_data_length.tx_data_length) != BTM_SUCCESS)
+ {
+ APPL_TRACE_ERROR("%s failed", __FUNCTION__);
+ }
+}
+
+/*******************************************************************************
+**
** Function bta_dm_ble_broadcast
**
** Description Starts or stops LE broadcasts
diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c
index 47b948821..9ff3e98e2 100644
--- a/bta/dm/bta_dm_api.c
+++ b/bta/dm/bta_dm_api.c
@@ -1882,6 +1882,32 @@ void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int, UINT16 max
bta_sys_sendmsg(p_msg);
}
}
+
+/*******************************************************************************
+**
+** Function BTA_DmBleSetDataLength
+**
+** Description This function is to set maximum LE data packet size
+**
+** Returns void
+**
+**
+*******************************************************************************/
+void BTA_DmBleSetDataLength(BD_ADDR remote_device, UINT16 tx_data_length)
+{
+ tBTA_DM_API_BLE_SET_DATA_LENGTH *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_BLE_SET_DATA_LENGTH *)GKI_getbuf(sizeof(tBTA_DM_API_BLE_SET_DATA_LENGTH)))
+ != NULL)
+ {
+ bdcpy(p_msg->remote_bda, remote_device);
+ p_msg->hdr.event = BTA_DM_API_SET_DATA_LENGTH_EVT;
+ p_msg->tx_data_length = tx_data_length;
+
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
#endif
/*******************************************************************************
diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h
index 798a90975..cabe88eff 100644
--- a/bta/dm/bta_dm_int.h
+++ b/bta/dm/bta_dm_int.h
@@ -99,6 +99,7 @@ enum
BTA_DM_API_BLE_SET_ADV_CONFIG_EVT,
BTA_DM_API_BLE_SET_SCAN_RSP_EVT,
BTA_DM_API_BLE_BROADCAST_EVT,
+ BTA_DM_API_SET_DATA_LENGTH_EVT,
#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
BTA_DM_API_CFG_FILTER_COND_EVT,
@@ -466,6 +467,13 @@ typedef struct
tBTA_DM_SEARCH_CBACK * p_cback;
}tBTA_DM_API_BLE_OBSERVE;
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR remote_bda;
+ UINT16 tx_data_length;
+}tBTA_DM_API_BLE_SET_DATA_LENGTH;
+
/* set adv parameter for BLE advertising */
typedef struct
{
@@ -692,6 +700,8 @@ typedef union
tBTA_DM_API_ENABLE_SCAN_FILTER ble_enable_scan_filt;
#endif
tBTA_DM_API_UPDATE_CONN_PARAM ble_update_conn_params;
+ tBTA_DM_API_BLE_SET_DATA_LENGTH ble_set_data_length;
+
tBTA_DM_API_BLE_MULTI_ADV_ENB ble_multi_adv_enb;
tBTA_DM_API_BLE_MULTI_ADV_PARAM ble_multi_adv_param;
tBTA_DM_API_BLE_MULTI_ADV_DATA ble_multi_adv_data;
@@ -1057,6 +1067,7 @@ extern void bta_dm_ble_set_adv_params (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_data_length(tBTA_DM_MSG *p_data);
#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
extern void bta_dm_cfg_filter_cond (tBTA_DM_MSG *p_data);
diff --git a/bta/dm/bta_dm_main.c b/bta/dm/bta_dm_main.c
index 75de1f3b2..450151a21 100644
--- a/bta/dm/bta_dm_main.c
+++ b/bta/dm/bta_dm_main.c
@@ -96,6 +96,7 @@ const tBTA_DM_ACTION bta_dm_action[] =
bta_dm_ble_set_adv_config, /* BTA_DM_API_BLE_SET_ADV_CONFIG_EVT */
bta_dm_ble_set_scan_rsp, /* BTA_DM_API_BLE_SET_SCAN_RSP_EVT */
bta_dm_ble_broadcast, /* BTA_DM_API_BLE_BROADCAST_EVT */
+ bta_dm_ble_set_data_length, /* BTA_DM_API_SET_DATA_LENGTH_EVT */
#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE
bta_dm_cfg_filter_cond, /* BTA_DM_API_CFG_FILTER_COND_EVT */
bta_dm_scan_filter_param_setup, /* BTA_DM_API_SCAN_FILTER_SETUP_EVT */
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index e6de6bb49..9c13be45e 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -2146,6 +2146,17 @@ extern void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int,
/*******************************************************************************
**
+** Function BTA_DmBleSetDataLength
+**
+** Description This function is to set maximum LE data packet size
+**
+** Returns void
+**
+*******************************************************************************/
+extern void BTA_DmBleSetDataLength(BD_ADDR remote_device, UINT16 tx_data_length);
+
+/*******************************************************************************
+**
** Function BTA_DmBleSetStorageParams
**
** Description This function is called to set the storage parameters
diff --git a/device/include/controller.h b/device/include/controller.h
index af93e4742..2acca1bc0 100644
--- a/device/include/controller.h
+++ b/device/include/controller.h
@@ -51,6 +51,7 @@ typedef struct controller_t {
bool (*supports_master_slave_role_switch)(void);
bool (*supports_ble)(void);
+ bool (*supports_ble_packet_extension)(void);
bool (*supports_ble_connection_parameters_request)(void);
bool (*supports_ble_privacy)(void);
@@ -64,6 +65,8 @@ typedef struct controller_t {
uint16_t (*get_acl_packet_size_classic)(void);
uint16_t (*get_acl_packet_size_ble)(void);
+ uint16_t (*get_ble_default_data_packet_length)(void);
+
// Get the number of acl packets the controller can buffer.
uint16_t (*get_acl_buffer_count_classic)(void);
uint8_t (*get_acl_buffer_count_ble)(void);
diff --git a/device/src/controller.c b/device/src/controller.c
index f0d3e584d..02edc4faf 100644
--- a/device/src/controller.c
+++ b/device/src/controller.c
@@ -34,7 +34,8 @@
#include "stack/include/btm_ble_api.h"
#include "btcore/include/version.h"
-const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x00\x00\x00\x00\x3f" };
+const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x00\x00\x00\x04\x7f" };
+
#if (BLE_INCLUDED)
const bt_event_mask_t CLASSIC_EVENT_MASK = { HCI_DUMO_EVENT_MASK_EXT };
#else
@@ -69,6 +70,7 @@ static uint8_t ble_white_list_size;
static uint8_t ble_resolving_list_max_size;
static uint8_t ble_supported_states[BLE_SUPPORTED_STATES_SIZE];
static bt_device_features_t features_ble;
+static uint16_t ble_suggested_default_data_length;
static bool readable;
static bool ble_supported;
@@ -225,6 +227,13 @@ static future_t *start_up(void) {
&ble_resolving_list_max_size);
}
+ if (HCI_LE_DATA_LEN_EXT_SUPPORTED(features_ble.as_array)) {
+ response = AWAIT_COMMAND(packet_factory->make_ble_read_suggested_default_data_length());
+ packet_parser->parse_ble_read_suggested_default_data_length_response(
+ response,
+ &ble_suggested_default_data_length);
+ }
+
// Set the ble event mask next
response = AWAIT_COMMAND(packet_factory->make_ble_set_event_mask(&BLE_EVENT_MASK));
packet_parser->parse_generic_command_complete(response);
@@ -348,6 +357,12 @@ static bool supports_ble_privacy(void) {
return HCI_LE_ENHANCED_PRIVACY_SUPPORTED(features_ble.as_array);
}
+static bool supports_ble_packet_extension(void) {
+ assert(readable);
+ assert(ble_supported);
+ return HCI_LE_DATA_LEN_EXT_SUPPORTED(features_ble.as_array);
+}
+
static bool supports_ble_connection_parameters_request(void) {
assert(readable);
assert(ble_supported);
@@ -375,6 +390,12 @@ static uint16_t get_acl_packet_size_ble(void) {
return acl_data_size_ble + HCI_DATA_PREAMBLE_SIZE;
}
+static uint16_t get_ble_suggested_default_data_length(void) {
+ assert(readable);
+ assert(ble_supported);
+ return ble_suggested_default_data_length;
+}
+
static uint16_t get_acl_buffer_count_classic(void) {
assert(readable);
return acl_buffer_count_classic;
@@ -420,6 +441,7 @@ static const controller_t interface = {
supports_master_slave_role_switch,
supports_ble,
+ supports_ble_packet_extension,
supports_ble_connection_parameters_request,
supports_ble_privacy,
@@ -428,6 +450,7 @@ static const controller_t interface = {
get_acl_packet_size_classic,
get_acl_packet_size_ble,
+ get_ble_suggested_default_data_length,
get_acl_buffer_count_classic,
get_acl_buffer_count_ble,
diff --git a/hci/include/hci_packet_factory.h b/hci/include/hci_packet_factory.h
index 5a50b5199..79110e178 100644
--- a/hci/include/hci_packet_factory.h
+++ b/hci/include/hci_packet_factory.h
@@ -38,6 +38,7 @@ typedef struct {
BT_HDR *(*make_ble_read_supported_states)(void);
BT_HDR *(*make_ble_read_local_supported_features)(void);
BT_HDR *(*make_ble_read_resolving_list_size)(void);
+ BT_HDR *(*make_ble_read_suggested_default_data_length)(void);
BT_HDR *(*make_ble_set_event_mask)(const bt_event_mask_t *event_mask);
} hci_packet_factory_t;
diff --git a/hci/include/hci_packet_parser.h b/hci/include/hci_packet_parser.h
index 45b934a5d..57e5d1c25 100644
--- a/hci/include/hci_packet_parser.h
+++ b/hci/include/hci_packet_parser.h
@@ -87,6 +87,10 @@ typedef struct {
uint8_t *resolving_list_size_ptr
);
+ void (*parse_ble_read_suggested_default_data_length_response)(
+ BT_HDR *response,
+ uint16_t *ble_default_packet_length_ptr
+ );
} hci_packet_parser_t;
const hci_packet_parser_t *hci_packet_parser_get_interface();
diff --git a/hci/src/hci_packet_factory.c b/hci/src/hci_packet_factory.c
index 89b82d189..bc8fca51d 100644
--- a/hci/src/hci_packet_factory.c
+++ b/hci/src/hci_packet_factory.c
@@ -133,6 +133,10 @@ static BT_HDR *make_ble_read_resolving_list_size(void) {
return make_command_no_params(HCI_BLE_READ_RESOLVING_LIST_SIZE);
}
+static BT_HDR *make_ble_read_suggested_default_data_length(void) {
+ return make_command_no_params(HCI_BLE_READ_DEFAULT_DATA_LENGTH);
+}
+
static BT_HDR *make_ble_set_event_mask(const bt_event_mask_t *event_mask) {
uint8_t *stream;
uint8_t parameter_size = sizeof(bt_event_mask_t);
@@ -188,6 +192,7 @@ static const hci_packet_factory_t interface = {
make_ble_read_supported_states,
make_ble_read_local_supported_features,
make_ble_read_resolving_list_size,
+ make_ble_read_suggested_default_data_length,
make_ble_set_event_mask
};
diff --git a/hci/src/hci_packet_parser.c b/hci/src/hci_packet_parser.c
index e25b7c479..b9f4080cd 100644
--- a/hci/src/hci_packet_parser.c
+++ b/hci/src/hci_packet_parser.c
@@ -173,6 +173,16 @@ static void parse_ble_read_resolving_list_size_response(
buffer_allocator->free(response);
}
+static void parse_ble_read_suggested_default_data_length_response(
+ BT_HDR *response,
+ uint16_t *ble_default_packet_length_ptr) {
+
+ uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 2 /* bytes after */);
+ STREAM_TO_UINT8(*ble_default_packet_length_ptr, stream);
+
+ buffer_allocator->free(response);
+}
+
// Internal functions
static uint8_t *read_command_complete_header(
@@ -225,7 +235,8 @@ static const hci_packet_parser_t interface = {
parse_ble_read_buffer_size_response,
parse_ble_read_supported_states_response,
parse_ble_read_local_supported_features_response,
- parse_ble_read_resolving_list_size_response
+ parse_ble_read_resolving_list_size_response,
+ parse_ble_read_suggested_default_data_length_response
};
const hci_packet_parser_t *hci_packet_parser_get_interface() {
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index e492b1f3b..789cfb1e6 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -38,6 +38,7 @@
#include "gap_api.h"
#include "bt_utils.h"
#include "device/include/controller.h"
+
#define LOG_TAG "bt_btm_ble"
#include "osi/include/log.h"
@@ -759,6 +760,54 @@ BOOLEAN BTM_UseLeLink (BD_ADDR bd_addr)
}
return use_le;
}
+
+
+/*******************************************************************************
+**
+** Function BTM_SetBleDataLength
+**
+** Description This function is to set maximum BLE transmission packet size
+**
+** Returns BTM_SUCCESS if success; otherwise failed.
+**
+*******************************************************************************/
+tBTM_STATUS BTM_SetBleDataLength(BD_ADDR bd_addr, UINT16 tx_pdu_length)
+{
+ tACL_CONN *p_acl = btm_bda_to_acl(bd_addr, BT_TRANSPORT_LE);
+ BTM_TRACE_DEBUG("%s: tx_pdu_length =%d", __FUNCTION__, tx_pdu_length);
+
+ if (!controller_get_interface()->supports_ble_packet_extension())
+ {
+ BTM_TRACE_ERROR("%s failed, request not supported", __FUNCTION__);
+ return BTM_ILLEGAL_VALUE;
+ }
+
+ if (!HCI_LE_DATA_LEN_EXT_SUPPORTED(p_acl->peer_le_features))
+ {
+ BTM_TRACE_ERROR("%s failed, peer does not support request", __FUNCTION__);
+ return BTM_ILLEGAL_VALUE;
+ }
+
+ if (p_acl != NULL)
+ {
+ if (tx_pdu_length > BTM_BLE_DATA_SIZE_MAX)
+ tx_pdu_length = BTM_BLE_DATA_SIZE_MAX;
+ else if (tx_pdu_length < BTM_BLE_DATA_SIZE_MIN)
+ tx_pdu_length = BTM_BLE_DATA_SIZE_MIN;
+
+ /* always set the TxTime to be max, as controller does not care for now */
+ btsnd_hcic_ble_set_data_length(p_acl->hci_handle, tx_pdu_length,
+ BTM_BLE_DATA_TX_TIME_MAX);
+
+ return BTM_SUCCESS;
+ }
+ else
+ {
+ BTM_TRACE_ERROR("%s: Wrong mode: no LE link exist or LE not supported",__FUNCTION__);
+ return BTM_WRONG_MODE;
+ }
+}
+
/*******************************************************************************
**
** Function btm_ble_rand_enc_complete
diff --git a/stack/btu/btu_hcif.c b/stack/btu/btu_hcif.c
index e3f61398c..700577271 100644
--- a/stack/btu/btu_hcif.c
+++ b/stack/btu/btu_hcif.c
@@ -40,7 +40,8 @@
#include "btm_api.h"
#include "btm_int.h"
#include "bt_utils.h"
-#include "osi/include/osi.h"
+#include "device/include/controller.h"
+#include "osi.h"
#include "osi/include/log.h"
#include "hci_layer.h"
@@ -119,6 +120,7 @@ static void btu_ble_read_remote_feat_evt (UINT8 *p);
static void btu_ble_ll_conn_param_upd_evt (UINT8 *p, UINT16 evt_len);
static void btu_ble_proc_ltk_req (UINT8 *p);
static void btu_hcif_encryption_key_refresh_cmpl_evt (UINT8 *p);
+static void btu_ble_data_length_change_evt (UINT8 *p, UINT16 evt_len);
#if (BLE_LLT_INCLUDED == TRUE)
static void btu_ble_rc_param_req_evt(UINT8 *p);
#endif
@@ -332,7 +334,9 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
btu_ble_rc_param_req_evt(p);
break;
#endif
-
+ case HCI_BLE_DATA_LENGTH_CHANGE_EVT:
+ btu_ble_data_length_change_evt(p, hci_evt_len);
+ break;
}
break;
#endif /* BLE_INCLUDED */
@@ -1721,6 +1725,27 @@ static void btu_ble_proc_ltk_req (UINT8 *p)
#endif
/* This is empty until an upper layer cares about returning event */
}
+
+static void btu_ble_data_length_change_evt(UINT8 *p, UINT16 evt_len)
+{
+ UINT16 handle;
+ UINT16 tx_data_len;
+ UINT16 rx_data_len;
+
+ if (!controller_get_interface()->supports_ble_packet_extension())
+ {
+ HCI_TRACE_WARNING("%s, request not supported", __FUNCTION__);
+ return;
+ }
+
+ STREAM_TO_UINT16(handle, p);
+ STREAM_TO_UINT16(tx_data_len, p);
+ p += 2; /* Skip the TxTimer */
+ STREAM_TO_UINT16(rx_data_len, p);
+
+ l2cble_process_data_length_change_event(handle, tx_data_len, rx_data_len);
+}
+
/**********************************************
** End of BLE Events Handler
***********************************************/
diff --git a/stack/gatt/gatt_cl.c b/stack/gatt/gatt_cl.c
index 0578086bb..3e623bf7b 100644
--- a/stack/gatt/gatt_cl.c
+++ b/stack/gatt/gatt_cl.c
@@ -30,6 +30,7 @@
#include "bt_utils.h"
#include "gki.h"
#include "gatt_int.h"
+#include "l2c_int.h"
#define GATT_WRITE_LONG_HDR_SIZE 5 /* 1 opcode + 2 handle + 2 offset */
#define GATT_READ_CHAR_VALUE_HDL (GATT_READ_CHAR_VALUE | 0x80)
@@ -1065,6 +1066,7 @@ void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT
p_tcb->payload_size = mtu;
}
+ l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size);
gatt_end_operation(p_clcb, status, NULL);
}
/*******************************************************************************
diff --git a/stack/gatt/gatt_sr.c b/stack/gatt/gatt_sr.c
index d4323c74b..05facd606 100755..100644
--- a/stack/gatt/gatt_sr.c
+++ b/stack/gatt/gatt_sr.c
@@ -29,7 +29,7 @@
#include <string.h>
#include "gatt_int.h"
#include "l2c_api.h"
-
+#include "l2c_int.h"
#define GATT_MTU_REQ_MIN_LEN 2
@@ -935,6 +935,8 @@ static void gatts_process_mtu_req (tGATT_TCB *p_tcb, UINT16 len, UINT8 *p_data)
GATT_TRACE_ERROR("MTU request PDU with MTU size %d", p_tcb->payload_size);
+ l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size);
+
if ((p_buf = attp_build_sr_msg(p_tcb, GATT_RSP_MTU, (tGATT_SR_MSG *) &p_tcb->payload_size)) != NULL)
{
attp_send_sr_msg (p_tcb, p_buf);
diff --git a/stack/hcic/hciblecmds.c b/stack/hcic/hciblecmds.c
index 9a5e1069d..5d7d2106b 100644
--- a/stack/hcic/hciblecmds.c
+++ b/stack/hcic/hciblecmds.c
@@ -929,6 +929,29 @@ BOOLEAN btsnd_hcic_ble_set_rand_priv_addr_timeout (UINT16 rpa_timout)
return (TRUE);
}
+BOOLEAN btsnd_hcic_ble_set_data_length(UINT16 conn_handle, UINT16 tx_octets, UINT16 tx_time)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_SET_DATA_LENGTH)) == NULL)
+ return FALSE;
+
+ pp = p->data;
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_SET_DATA_LENGTH;
+ p->offset = 0;
+
+ UINT16_TO_STREAM(pp, HCI_BLE_SET_DATA_LENGTH);
+ UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_BLE_SET_DATA_LENGTH);
+
+ UINT16_TO_STREAM(pp, conn_handle);
+ UINT16_TO_STREAM(pp, tx_octets);
+ UINT16_TO_STREAM(pp, tx_time);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+ return TRUE;
+}
#endif
diff --git a/stack/include/btm_ble_api.h b/stack/include/btm_ble_api.h
index 607e6871e..df61449d9 100644
--- a/stack/include/btm_ble_api.h
+++ b/stack/include/btm_ble_api.h
@@ -327,10 +327,21 @@ typedef UINT32 tBTM_BLE_AD_MASK;
#define BTM_BLE_AD_TYPE_MANU HCI_EIR_MANUFACTURER_SPECIFIC_TYPE /* 0xff */
typedef UINT8 tBTM_BLE_AD_TYPE;
-/* security settings used with L2CAP LE COC */
+/* Security settings used with L2CAP LE COC */
#define BTM_SEC_LE_LINK_ENCRYPTED 0x01
#define BTM_SEC_LE_LINK_PAIRED_WITHOUT_MITM 0x02
#define BTM_SEC_LE_LINK_PAIRED_WITH_MITM 0x04
+
+/* Min/max Preferred number of payload octets that the local Controller
+ should include in a single Link Layer Data Channel PDU. */
+#define BTM_BLE_DATA_SIZE_MAX 0x00fb
+#define BTM_BLE_DATA_SIZE_MIN 0x001b
+
+/* Preferred maximum number of microseconds that the local Controller
+ should use to transmit a single Link Layer Data Channel PDU. */
+#define BTM_BLE_DATA_TX_TIME_MIN 0x0148
+#define BTM_BLE_DATA_TX_TIME_MAX 0x0848
+
/* adv tx power level */
#define BTM_BLE_ADV_TX_POWER_MIN 0 /* minimum tx power */
#define BTM_BLE_ADV_TX_POWER_LOW 1 /* low tx power */
@@ -1765,6 +1776,17 @@ extern tBTM_STATUS BTM_BleEnableDisableFilterFeature(UINT8 enable,
*******************************************************************************/
extern tBTM_STATUS BTM_BleGetEnergyInfo(tBTM_BLE_ENERGY_INFO_CBACK *p_ener_cback);
+/*******************************************************************************
+**
+** Function BTM_SetBleDataLength
+**
+** Description This function is called to set maximum BLE transmission packet size
+**
+** Returns BTM_SUCCESS if success; otherwise failed.
+**
+*******************************************************************************/
+extern tBTM_STATUS BTM_SetBleDataLength(BD_ADDR bd_addr, UINT16 tx_pdu_length);
+
#ifdef __cplusplus
}
#endif
diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h
index 92d9d844e..04c5ed665 100644
--- a/stack/include/hcidefs.h
+++ b/stack/include/hcidefs.h
@@ -333,6 +333,10 @@
#define HCI_BLE_RC_PARAM_REQ_REPLY (0x0020 | HCI_GRP_BLE_CMDS)
#define HCI_BLE_RC_PARAM_REQ_NEG_REPLY (0x0021 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_SET_DATA_LENGTH (0x0022 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_DEFAULT_DATA_LENGTH (0x0023 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_WRITE_DEFAULT_DATA_LENGTH (0x0024 | HCI_GRP_BLE_CMDS)
+
#define HCI_BLE_ADD_DEV_RESOLVING_LIST (0x0027 | HCI_GRP_BLE_CMDS)
#define HCI_BLE_RM_DEV_RESOLVING_LIST (0x0028 | HCI_GRP_BLE_CMDS)
#define HCI_BLE_CLEAR_RESOLVING_LIST (0x0029 | HCI_GRP_BLE_CMDS)
@@ -342,7 +346,6 @@
#define HCI_BLE_SET_ADDR_RESOLUTION_ENABLE (0x002D | HCI_GRP_BLE_CMDS)
#define HCI_BLE_SET_RAND_PRIV_ADDR_TIMOUT (0x002E | HCI_GRP_BLE_CMDS)
-
/* LE Get Vendor Capabilities Command OCF */
#define HCI_BLE_VENDOR_CAP_OCF (0x0153 | HCI_GRP_VENDOR_SPECIFIC)
@@ -1757,12 +1760,16 @@ typedef struct
#define HCI_LE_FEATURE_ENHANCED_PRIVACY_OFF 0
#define HCI_LE_ENHANCED_PRIVACY_SUPPORTED(x) ((x)[HCI_LE_FEATURE_ENHANCED_PRIVACY_OFF] & HCI_LE_FEATURE_ENHANCED_PRIVACY_MASK)
-
/* Extended scanner filter policy : 7 */
#define HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_MASK 0x80
#define HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_OFF 0
#define HCI_LE_EXT_SCAN_FILTER_POLICY_SUPPORTED(x) ((x)[HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_OFF] & HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_MASK)
+/* Slave-initiated Features Exchange */
+#define HCI_LE_FEATURE_DATA_LEN_EXT_MASK 0x20
+#define HCI_LE_FEATURE_DATA_LEN_EXT_OFF 0
+#define HCI_LE_DATA_LEN_EXT_SUPPORTED(x) ((x)[HCI_LE_FEATURE_DATA_LEN_EXT_OFF] & HCI_LE_FEATURE_DATA_LEN_EXT_MASK)
+
/*
** Local Supported Commands encoding
*/
diff --git a/stack/include/hcimsgs.h b/stack/include/hcimsgs.h
index dfc0d50cb..672f5fb4c 100644
--- a/stack/include/hcimsgs.h
+++ b/stack/include/hcimsgs.h
@@ -661,13 +661,13 @@ extern void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode,
#define HCIC_PARAM_SIZE_BLE_READ_REMOTE_FEAT 2
#define HCIC_PARAM_SIZE_BLE_ENCRYPT 32
#define HCIC_PARAM_SIZE_BLE_RAND 0
-#define HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED 2
+#define HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED 2
#define HCIC_BLE_RAND_DI_SIZE 8
#define HCIC_BLE_ENCRYT_KEY_SIZE 16
#define HCIC_PARAM_SIZE_BLE_START_ENC (4 + HCIC_BLE_RAND_DI_SIZE + HCIC_BLE_ENCRYT_KEY_SIZE)
#define HCIC_PARAM_SIZE_LTK_REQ_REPLY (2 + HCIC_BLE_ENCRYT_KEY_SIZE)
-#define HCIC_PARAM_SIZE_LTK_REQ_NEG_REPLY 2
+#define HCIC_PARAM_SIZE_LTK_REQ_NEG_REPLY 2
#define HCIC_BLE_CHNL_MAP_SIZE 5
#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA 31
@@ -679,6 +679,7 @@ extern void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode,
#define HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_LOCAL 7
#define HCIC_PARAM_SIZE_BLE_SET_ADDR_RESOLUTION_ENABLE 1
#define HCIC_PARAM_SIZE_BLE_SET_RAND_PRIV_ADDR_TIMOUT 2
+#define HCIC_PARAM_SIZE_BLE_SET_DATA_LENGTH 6
/* ULP HCI command */
extern BOOLEAN btsnd_hcic_ble_set_evt_mask (BT_EVENT_MASK event_mask);
@@ -771,6 +772,8 @@ extern BOOLEAN btsnd_hcic_ble_rc_param_req_neg_reply(UINT16 handle, UINT8 reason
#endif /* BLE_LLT_INCLUDED */
+extern BOOLEAN btsnd_hcic_ble_set_data_length(UINT16 conn_handle, UINT16 tx_octets,
+ UINT16 tx_time);
extern BOOLEAN btsnd_hcic_ble_add_device_resolving_list (UINT8 addr_type_peer,
BD_ADDR bda_peer,
diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c
index 94ddf4268..05ff5bf40 100644
--- a/stack/l2cap/l2c_ble.c
+++ b/stack/l2cap/l2c_ble.c
@@ -985,5 +985,103 @@ void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 i
}
#endif
+/*******************************************************************************
+**
+** Function l2cble_update_data_length
+**
+** Description This function update link tx data length if applicable
+**
+** Returns void
+**
+*******************************************************************************/
+void l2cble_update_data_length(tL2C_LCB *p_lcb)
+{
+ UINT16 tx_mtu = 0;
+ UINT16 i = 0;
+
+ L2CAP_TRACE_DEBUG("%s", __FUNCTION__);
+
+ /* See if we have a link control block for the connection */
+ if (p_lcb == NULL)
+ return;
+
+ for (i = 0; i < L2CAP_NUM_FIXED_CHNLS; i++)
+ {
+ if (i + L2CAP_FIRST_FIXED_CHNL != L2CAP_BLE_SIGNALLING_CID)
+ {
+ if ((p_lcb->p_fixed_ccbs[i] != NULL) &&
+ (tx_mtu < (p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD)))
+ tx_mtu = p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD;
+ }
+ }
+
+ if (tx_mtu > BTM_BLE_DATA_SIZE_MAX)
+ tx_mtu = BTM_BLE_DATA_SIZE_MAX;
+
+ /* update TX data length if changed */
+ if (p_lcb->tx_data_len != tx_mtu)
+ BTM_SetBleDataLength(p_lcb->remote_bd_addr, tx_mtu);
+
+}
+
+/*******************************************************************************
+**
+** Function l2cble_process_data_length_change_evt
+**
+** Description This function process the data length change event
+**
+** Returns void
+**
+*******************************************************************************/
+void l2cble_process_data_length_change_event(UINT16 handle, UINT16 tx_data_len, UINT16 rx_data_len)
+{
+ tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
+
+ L2CAP_TRACE_DEBUG("%s TX data len = %d", __FUNCTION__, tx_data_len);
+ if (p_lcb == NULL)
+ return;
+
+ if (tx_data_len > 0)
+ p_lcb->tx_data_len = tx_data_len;
+
+ /* ignore rx_data len for now */
+}
+
+/*******************************************************************************
+**
+** Function l2cble_set_fixed_channel_tx_data_length
+**
+** Description This function update max fixed channel tx data length if applicable
+**
+** Returns void
+**
+*******************************************************************************/
+void l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda, UINT16 fix_cid, UINT16 tx_mtu)
+{
+ tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(remote_bda, BT_TRANSPORT_LE);
+ UINT16 cid = fix_cid - L2CAP_FIRST_FIXED_CHNL;
+
+ L2CAP_TRACE_DEBUG("%s TX MTU = %d", __FUNCTION__, tx_mtu);
+
+ if (!controller_get_interface()->supports_ble_packet_extension())
+ {
+ L2CAP_TRACE_WARNING("%s, request not supported", __FUNCTION__);
+ return;
+ }
+
+ /* See if we have a link control block for the connection */
+ if (p_lcb == NULL)
+ return;
+
+ if (p_lcb->p_fixed_ccbs[cid] != NULL)
+ {
+ if (tx_mtu > BTM_BLE_DATA_SIZE_MAX)
+ tx_mtu = BTM_BLE_DATA_SIZE_MAX;
+
+ p_lcb->p_fixed_ccbs[cid]->tx_data_len = tx_mtu;
+ }
+
+ l2cble_update_data_length(p_lcb);
+}
#endif /* (BLE_INCLUDED == TRUE) */
diff --git a/stack/l2cap/l2c_int.h b/stack/l2cap/l2c_int.h
index 08c4ea10e..cbaca8251 100644
--- a/stack/l2cap/l2c_int.h
+++ b/stack/l2cap/l2c_int.h
@@ -313,7 +313,7 @@ typedef struct t_l2c_ccb
#if (L2CAP_NUM_FIXED_CHNLS > 0) || (L2CAP_UCD_INCLUDED == TRUE)
UINT16 fixed_chnl_idle_tout; /* Idle timeout to use for the fixed channel */
#endif
-
+ UINT16 tx_data_len;
} tL2C_CCB;
/***********************************************************************
@@ -403,6 +403,7 @@ typedef struct t_l2c_linkcb
tBT_TRANSPORT transport;
#if (BLE_INCLUDED == TRUE)
tBLE_ADDR_TYPE ble_addr_type;
+ UINT16 tx_data_len; /* tx data length used in data length extension */
#define L2C_BLE_CONN_UPDATE_DISABLE 0x1 /* disable update connection parameters */
#define L2C_BLE_NEW_CONN_PARAM 0x2 /* new connection parameter to be set */
@@ -744,6 +745,13 @@ extern void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status);
extern void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 int_max,
UINT16 latency, UINT16 timeout);
#endif
+
+extern void l2cble_update_data_length(tL2C_LCB *p_lcb);
+extern void l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda, UINT16 fix_cid,
+ UINT16 tx_mtu);
+extern void l2cble_process_data_length_change_event(UINT16 handle, UINT16 tx_data_len,
+ UINT16 rx_data_len);
+
#endif
extern void l2cu_process_fixed_disc_cback (tL2C_LCB *p_lcb);
diff --git a/stack/l2cap/l2c_utils.c b/stack/l2cap/l2c_utils.c
index d3ee908f2..e80d16b0f 100644
--- a/stack/l2cap/l2c_utils.c
+++ b/stack/l2cap/l2c_utils.c
@@ -74,6 +74,7 @@ tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding, tBT_TRANSPOR
p_lcb->is_bonding = is_bonding;
#if (BLE_INCLUDED == TRUE)
p_lcb->transport = transport;
+ p_lcb->tx_data_len = controller_get_interface()->get_ble_default_data_packet_length();
if (transport == BT_TRANSPORT_LE)
{