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
diff --git a/system/bta/dm/bta_dm_act.c b/system/bta/dm/bta_dm_act.c
index 68d99d4..1251f5d 100644
--- a/system/bta/dm/bta_dm_act.c
+++ b/system/bta/dm/bta_dm_act.c
@@ -4757,6 +4757,24 @@
/*******************************************************************************
**
+** 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/system/bta/dm/bta_dm_api.c b/system/bta/dm/bta_dm_api.c
index 47b9488..9ff3e98 100644
--- a/system/bta/dm/bta_dm_api.c
+++ b/system/bta/dm/bta_dm_api.c
@@ -1882,6 +1882,32 @@
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/system/bta/dm/bta_dm_int.h b/system/bta/dm/bta_dm_int.h
index 798a9097..cabe88e 100644
--- a/system/bta/dm/bta_dm_int.h
+++ b/system/bta/dm/bta_dm_int.h
@@ -99,6 +99,7 @@
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 @@
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 @@
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_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/system/bta/dm/bta_dm_main.c b/system/bta/dm/bta_dm_main.c
index 75de1f3..450151a 100644
--- a/system/bta/dm/bta_dm_main.c
+++ b/system/bta/dm/bta_dm_main.c
@@ -96,6 +96,7 @@
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/system/bta/include/bta_api.h b/system/bta/include/bta_api.h
index e6de6bb..9c13be4 100644
--- a/system/bta/include/bta_api.h
+++ b/system/bta/include/bta_api.h
@@ -2146,6 +2146,17 @@
/*******************************************************************************
**
+** 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/system/device/include/controller.h b/system/device/include/controller.h
index af93e47..2acca1b 100644
--- a/system/device/include/controller.h
+++ b/system/device/include/controller.h
@@ -51,6 +51,7 @@
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 @@
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/system/device/src/controller.c b/system/device/src/controller.c
index f0d3e58..02edc4f 100644
--- a/system/device/src/controller.c
+++ b/system/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_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 @@
&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 @@
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 @@
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 @@
supports_master_slave_role_switch,
supports_ble,
+ supports_ble_packet_extension,
supports_ble_connection_parameters_request,
supports_ble_privacy,
@@ -428,6 +450,7 @@
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/system/hci/include/hci_packet_factory.h b/system/hci/include/hci_packet_factory.h
index 5a50b51..79110e1 100644
--- a/system/hci/include/hci_packet_factory.h
+++ b/system/hci/include/hci_packet_factory.h
@@ -38,6 +38,7 @@
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/system/hci/include/hci_packet_parser.h b/system/hci/include/hci_packet_parser.h
index 45b934a..57e5d1c 100644
--- a/system/hci/include/hci_packet_parser.h
+++ b/system/hci/include/hci_packet_parser.h
@@ -87,6 +87,10 @@
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/system/hci/src/hci_packet_factory.c b/system/hci/src/hci_packet_factory.c
index 89b82d1..bc8fca5 100644
--- a/system/hci/src/hci_packet_factory.c
+++ b/system/hci/src/hci_packet_factory.c
@@ -133,6 +133,10 @@
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 @@
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/system/hci/src/hci_packet_parser.c b/system/hci/src/hci_packet_parser.c
index e25b7c47..b9f4080 100644
--- a/system/hci/src/hci_packet_parser.c
+++ b/system/hci/src/hci_packet_parser.c
@@ -173,6 +173,16 @@
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 @@
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/system/stack/btm/btm_ble.c b/system/stack/btm/btm_ble.c
index e492b1f..789cfb1 100644
--- a/system/stack/btm/btm_ble.c
+++ b/system/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 @@
}
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/system/stack/btu/btu_hcif.c b/system/stack/btu/btu_hcif.c
index e3f6139..7005772 100644
--- a/system/stack/btu/btu_hcif.c
+++ b/system/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_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 @@
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 @@
#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/system/stack/gatt/gatt_cl.c b/system/stack/gatt/gatt_cl.c
index 0578086..3e623bf 100644
--- a/system/stack/gatt/gatt_cl.c
+++ b/system/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 @@
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/system/stack/gatt/gatt_sr.c b/system/stack/gatt/gatt_sr.c
old mode 100755
new mode 100644
index d4323c7..05facd6
--- a/system/stack/gatt/gatt_sr.c
+++ b/system/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 @@
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/system/stack/hcic/hciblecmds.c b/system/stack/hcic/hciblecmds.c
index 9a5e106..5d7d210 100644
--- a/system/stack/hcic/hciblecmds.c
+++ b/system/stack/hcic/hciblecmds.c
@@ -929,6 +929,29 @@
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/system/stack/include/btm_ble_api.h b/system/stack/include/btm_ble_api.h
index 607e687..df61449 100644
--- a/system/stack/include/btm_ble_api.h
+++ b/system/stack/include/btm_ble_api.h
@@ -327,10 +327,21 @@
#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_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/system/stack/include/hcidefs.h b/system/stack/include/hcidefs.h
index 92d9d84..04c5ed6 100644
--- a/system/stack/include/hcidefs.h
+++ b/system/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 @@
#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/system/stack/include/hcimsgs.h b/system/stack/include/hcimsgs.h
index dfc0d50..672f5fb 100644
--- a/system/stack/include/hcimsgs.h
+++ b/system/stack/include/hcimsgs.h
@@ -661,13 +661,13 @@
#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 @@
#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 @@
#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/system/stack/l2cap/l2c_ble.c b/system/stack/l2cap/l2c_ble.c
index 94ddf42..05ff5bf 100644
--- a/system/stack/l2cap/l2c_ble.c
+++ b/system/stack/l2cap/l2c_ble.c
@@ -985,5 +985,103 @@
}
#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/system/stack/l2cap/l2c_int.h b/system/stack/l2cap/l2c_int.h
index 08c4ea1..cbaca82 100644
--- a/system/stack/l2cap/l2c_int.h
+++ b/system/stack/l2cap/l2c_int.h
@@ -313,7 +313,7 @@
#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 @@
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_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/system/stack/l2cap/l2c_utils.c b/system/stack/l2cap/l2c_utils.c
index d3ee908..e80d16b 100644
--- a/system/stack/l2cap/l2c_utils.c
+++ b/system/stack/l2cap/l2c_utils.c
@@ -74,6 +74,7 @@
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)
{