diff --git a/system/bta/dm/bta_dm_act.c b/system/bta/dm/bta_dm_act.c index 68d99d41f6c19f501562bcc9652dc1f2cb92ffed..1251f5d5baee2688e62d76e3dc4b3528aa6e7263 100644 --- a/system/bta/dm/bta_dm_act.c +++ b/system/bta/dm/bta_dm_act.c @@ -4755,6 +4755,24 @@ void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data) (*p_data->ble_set_adv_data.p_adv_data_cback)(status); } +/******************************************************************************* +** +** 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 diff --git a/system/bta/dm/bta_dm_api.c b/system/bta/dm/bta_dm_api.c index 47b9488211090394e7d93810b060ca0b4bfb8a33..9ff3e98e21298c87a7ccd112e55fced50d5cd969 100644 --- a/system/bta/dm/bta_dm_api.c +++ b/system/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/system/bta/dm/bta_dm_int.h b/system/bta/dm/bta_dm_int.h index 798a90975c1c684b9550b0b2dc06f2d4152e4972..cabe88eff4d70ed816c23e4d3f3cda92b945dccb 100644 --- a/system/bta/dm/bta_dm_int.h +++ b/system/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/system/bta/dm/bta_dm_main.c b/system/bta/dm/bta_dm_main.c index 75de1f3b2811cef945c36dc0278694204eb597ac..450151a2156e1540e786f88439ab2174de26711e 100644 --- a/system/bta/dm/bta_dm_main.c +++ b/system/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/system/bta/include/bta_api.h b/system/bta/include/bta_api.h index e6de6bb4959422f45aa99a56819af8a6aab9c124..9c13be45e984007e0d27cd4e1167d8299516e93b 100644 --- a/system/bta/include/bta_api.h +++ b/system/bta/include/bta_api.h @@ -2144,6 +2144,17 @@ extern void BTA_BleDisableAdvInstance(UINT8 inst_id); extern void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int, UINT16 max_int, UINT16 latency, UINT16 timeout); +/******************************************************************************* +** +** 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 diff --git a/system/device/include/controller.h b/system/device/include/controller.h index af93e4742ad97fee5a588ecf0ec4148c94194c27..2acca1bc005c4fc3fdc1aa767bab79fb46535a61 100644 --- a/system/device/include/controller.h +++ b/system/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/system/device/src/controller.c b/system/device/src/controller.c index f0d3e584dff2e77a727b505ac99c5323b38a7316..02edc4fafc9412a99dbc8b93576cb4105520ada3 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_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/system/hci/include/hci_packet_factory.h b/system/hci/include/hci_packet_factory.h index 5a50b5199b213c45ae69cc12ca2812d18ee8521f..79110e1783c58e787786850fedfb75bb05967491 100644 --- a/system/hci/include/hci_packet_factory.h +++ b/system/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/system/hci/include/hci_packet_parser.h b/system/hci/include/hci_packet_parser.h index 45b934a5dbfbf5b99cc58b82364030cf09c27cd6..57e5d1c257c990727b37f51be0b95bc319c3fe3a 100644 --- a/system/hci/include/hci_packet_parser.h +++ b/system/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/system/hci/src/hci_packet_factory.c b/system/hci/src/hci_packet_factory.c index 89b82d189c4bac59ed07ae9c4ad38abcd7f2e0c9..bc8fca51d16e0742552d190df9865a0312b06e98 100644 --- a/system/hci/src/hci_packet_factory.c +++ b/system/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/system/hci/src/hci_packet_parser.c b/system/hci/src/hci_packet_parser.c index e25b7c479694752b0c2a8e13205a87841598357d..b9f4080cdd1dc460f3e2408ca8b9b3fc743616ab 100644 --- a/system/hci/src/hci_packet_parser.c +++ b/system/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/system/stack/btm/btm_ble.c b/system/stack/btm/btm_ble.c index e492b1f3bcc0997d9d3be17dbdee61e9a8adc33c..789cfb1e60eb7974cea4ff687ada963be4a07918 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 @@ 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/system/stack/btu/btu_hcif.c b/system/stack/btu/btu_hcif.c index e3f61398c449d5ed3788af08ffaaaf0612af62fe..7005772714a888bc2a7ec283ac7c92dc9b0926b3 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_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/system/stack/gatt/gatt_cl.c b/system/stack/gatt/gatt_cl.c index 0578086bb19fc1c520c1d5b7053a7f7b52c2207e..3e623bf7bb932035a22a35667ce6778afa63659e 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 @@ 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/system/stack/gatt/gatt_sr.c b/system/stack/gatt/gatt_sr.c old mode 100755 new mode 100644 index d4323c74badd7a023cbc4681a1ddf99796e071e0..05facd60677be4dff893e456392adfb27f6e4653 --- 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 @@ 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/system/stack/hcic/hciblecmds.c b/system/stack/hcic/hciblecmds.c index 9a5e1069d31b1cf45cb7ad154b0559eb44bfb110..5d7d2106b2a3d66ebfa3f1f6ff1b09e899c9721a 100644 --- a/system/stack/hcic/hciblecmds.c +++ b/system/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/system/stack/include/btm_ble_api.h b/system/stack/include/btm_ble_api.h index 607e6871e257d376aec159a9c47cd208f5ea7ffd..df61449d987ef2a21868d98fbb63f3eb6b6a24d4 100644 --- a/system/stack/include/btm_ble_api.h +++ b/system/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/system/stack/include/hcidefs.h b/system/stack/include/hcidefs.h index 92d9d844eeff1c3f870eb62bcbfb05c21112cf2a..04c5ed66527e83a3bb10b16337801658694e77ff 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 @@ 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/system/stack/include/hcimsgs.h b/system/stack/include/hcimsgs.h index dfc0d50cb0a32b3d059019bba390220ea9123ae9..672f5fb4cdd8845a9873fe804e6cba4e47aea36a 100644 --- a/system/stack/include/hcimsgs.h +++ b/system/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/system/stack/l2cap/l2c_ble.c b/system/stack/l2cap/l2c_ble.c index 94ddf4268ecc0a7775c5609e352db42c980e0282..05ff5bf4097b80c5748be8e766bee2ed1865e560 100644 --- a/system/stack/l2cap/l2c_ble.c +++ b/system/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/system/stack/l2cap/l2c_int.h b/system/stack/l2cap/l2c_int.h index 08c4ea10ef14e9643b660afbef5c4f88a60b6690..cbaca825176478642c13e2432a31d055e5f85907 100644 --- a/system/stack/l2cap/l2c_int.h +++ b/system/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/system/stack/l2cap/l2c_utils.c b/system/stack/l2cap/l2c_utils.c index d3ee908f2f0158a0c4b2ced137e1cb182e23e2ff..e80d16b0f2712dd0cf7610525c706b04cb43d4ad 100644 --- a/system/stack/l2cap/l2c_utils.c +++ b/system/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) {