diff --git a/components/bt/bluedroid/api/include/esp_bt_defs.h b/components/bt/bluedroid/api/include/esp_bt_defs.h index 8259046e83..513d37ec42 100644 --- a/components/bt/bluedroid/api/include/esp_bt_defs.h +++ b/components/bt/bluedroid/api/include/esp_bt_defs.h @@ -50,6 +50,7 @@ typedef enum { ESP_BT_STATUS_TIMEOUT, /* relate to BT_STATUS_TIMEOUT in bt_def.h */ ESP_BT_STATUS_PEER_LE_DATA_LEN_UNSUPPORTED, /* relate to BTM_PEER_LE_DATA_LEN_UNSUPPORTED in btm_api.h */ ESP_BT_STATUS_CONTROL_LE_DATA_LEN_UNSUPPORTED,/* relate to BTM_CONTROL_LE_DATA_LEN_UNSUPPORTED in btm_api.h */ + ESP_BT_STATUS_ERR_ILLEGAL_PARAMETER_FMT, /* relate to HCI_ERR_ILLEGAL_PARAMETER_FMT in hcidefs.h */ } esp_bt_status_t; diff --git a/components/bt/bluedroid/bta/dm/bta_dm_act.c b/components/bt/bluedroid/bta/dm/bta_dm_act.c index 1ca0b06fe5..12ceef36cc 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_act.c @@ -4516,13 +4516,6 @@ void bta_dm_ble_set_conn_scan_params (tBTA_DM_MSG *p_data) *******************************************************************************/ void bta_dm_ble_update_conn_params (tBTA_DM_MSG *p_data) { - tACL_CONN *p_acl_cb = btm_bda_to_acl(p_data->ble_update_conn_params.bd_addr, BT_TRANSPORT_LE); - if (p_acl_cb == NULL) { - APPL_TRACE_ERROR("%s error: Invalid connection bd_addr.", __func__); - return; - } else { - p_acl_cb->update_conn_param_cb = p_data->ble_update_conn_params.update_conn_param_cb; - } 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, diff --git a/components/bt/bluedroid/bta/dm/bta_dm_api.c b/components/bt/bluedroid/bta/dm/bta_dm_api.c index 095fd55570..58414c2370 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_api.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_api.c @@ -1991,7 +1991,7 @@ void BTA_DmEnableScanFilter(UINT8 action, tBTA_DM_BLE_PF_STATUS_CBACK *p_cmpl_cb ** *******************************************************************************/ void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int, UINT16 max_int, - UINT16 latency, UINT16 timeout, tBTA_UPDATE_CONN_PARAM_CBACK *update_conn_param_cb) + UINT16 latency, UINT16 timeout) { tBTA_DM_API_UPDATE_CONN_PARAM *p_msg; @@ -2004,7 +2004,6 @@ void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int, UINT16 max p_msg->max_int = max_int; p_msg->latency = latency; p_msg->timeout = timeout; - p_msg->update_conn_param_cb = update_conn_param_cb; bta_sys_sendmsg(p_msg); } } diff --git a/components/bt/bluedroid/bta/dm/bta_dm_int.h b/components/bt/bluedroid/bta/dm/bta_dm_int.h index 0980f1f8af..204b8e58c2 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_int.h +++ b/components/bt/bluedroid/bta/dm/bta_dm_int.h @@ -645,7 +645,6 @@ typedef struct { UINT16 max_int; UINT16 latency; UINT16 timeout; - tBTA_UPDATE_CONN_PARAM_CBACK *update_conn_param_cb; } tBTA_DM_API_UPDATE_CONN_PARAM; #if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index 22f3d6b180..c8283936a0 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -861,9 +861,6 @@ void bta_gattc_set_discover_st(tBTA_GATTC_SERV *p_srcb) tBTA_GATTC_CB *p_cb = &bta_gattc_cb; UINT8 i; -#if BLE_INCLUDED == TRUE - L2CA_EnableUpdateBleConnParams(p_srcb->server_bda, FALSE); -#endif for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++) { if (p_cb->clcb[i].p_srcb == p_srcb) { p_cb->clcb[i].status = BTA_GATT_OK; @@ -993,11 +990,6 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) APPL_TRACE_DEBUG("bta_gattc_disc_cmpl conn_id=%d", p_clcb->bta_conn_id); -#if BLE_INCLUDED == TRUE - if (p_clcb->transport == BTA_TRANSPORT_LE) { - L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, TRUE); - } -#endif p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE; p_clcb->disc_active = FALSE; diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c b/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c index ff6207ab55..506fd9e140 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c @@ -36,6 +36,7 @@ #include "btm_api.h" #include "btm_ble_api.h" #include "allocator.h" +#include "l2c_api.h" #define LOG_TAG "bt_bta_gattc" // #include "osi/include/log.h" @@ -587,6 +588,13 @@ static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache); #endif + + //server discover end, update connection parameters +#if BLE_INCLUDED == TRUE + if (p_clcb->transport == BTA_TRANSPORT_LE) { + L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, TRUE); + } +#endif /* save cache to NV */ p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE; bta_gattc_co_cache_open(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT, diff --git a/components/bt/bluedroid/bta/include/bta_api.h b/components/bt/bluedroid/bta/include/bta_api.h index 1313b90c8b..fb02175f68 100644 --- a/components/bt/bluedroid/bta/include/bta_api.h +++ b/components/bt/bluedroid/bta/include/bta_api.h @@ -2210,7 +2210,7 @@ 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, tBTA_UPDATE_CONN_PARAM_CBACK *update_conn_param_cb); + UINT16 max_int, UINT16 latency, UINT16 timeout); /******************************************************************************* ** diff --git a/components/bt/bluedroid/btc/core/btc_task.c b/components/bt/bluedroid/btc/core/btc_task.c index 534a0059ba..52cbf6dcff 100644 --- a/components/bt/bluedroid/btc/core/btc_task.c +++ b/components/bt/bluedroid/btc/core/btc_task.c @@ -141,7 +141,7 @@ int btc_init(void) { xBtcQueue = xQueueCreate(BTC_TASK_QUEUE_NUM, sizeof(btc_msg_t)); xTaskCreatePinnedToCore(btc_task, "Btc_task", BTC_TASK_STACK_SIZE, NULL, BTC_TASK_PRIO, &xBtcTaskHandle, 0); - + btc_gap_callback_init(); /* TODO: initial the profile_tab */ return BT_STATUS_SUCCESS; diff --git a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c index 43ab55e659..92c772da17 100644 --- a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c +++ b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c @@ -126,6 +126,9 @@ static esp_bt_status_t btc_hci_to_esp_status(uint8_t hci_status) case HCI_ERR_PARAM_OUT_OF_RANGE: esp_status = ESP_BT_STATUS_PARAM_OUT_OF_RANGE; break; + case HCI_ERR_ILLEGAL_PARAMETER_FMT: + esp_status = ESP_BT_STATUS_ERR_ILLEGAL_PARAMETER_FMT; + break; default: esp_status = ESP_BT_STATUS_FAIL; break; @@ -626,8 +629,7 @@ static void btc_stop_scan_callback(tBTA_STATUS status) } } -void btc_update_conn_param_callback (UINT8 status, BD_ADDR bd_addr, - tBTM_LE_UPDATE_CONN_PRAMS *update_conn_params) +void btc_update_conn_param_callback (UINT8 status, BD_ADDR bd_addr, tBTM_LE_UPDATE_CONN_PRAMS *update_conn_params) { esp_ble_gap_cb_param_t param; bt_status_t ret; @@ -724,8 +726,7 @@ static void btc_ble_stop_advertising(tBTA_START_STOP_ADV_CMPL_CBACK *stop_adv_cb } static void btc_ble_update_conn_params(BD_ADDR bd_addr, uint16_t min_int, - uint16_t max_int, uint16_t latency, uint16_t timeout, - tBTA_UPDATE_CONN_PARAM_CBACK *update_conn_param_cb) + uint16_t max_int, uint16_t latency, uint16_t timeout) { if (min_int > max_int) { min_int = max_int; @@ -736,7 +737,7 @@ static void btc_ble_update_conn_params(BD_ADDR bd_addr, uint16_t min_int, } BTA_DmBleUpdateConnectionParams(bd_addr, min_int, max_int, - latency, timeout, update_conn_param_cb); + latency, timeout); } static void btc_ble_set_pkt_data_len(BD_ADDR remote_device, uint16_t tx_data_length, tBTA_SET_PKT_DATA_LENGTH_CBACK *p_set_pkt_data_cback) @@ -1065,8 +1066,7 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) arg->conn_update_params.conn_params.min_int, arg->conn_update_params.conn_params.max_int, arg->conn_update_params.conn_params.latency, - arg->conn_update_params.conn_params.timeout, - btc_update_conn_param_callback); + arg->conn_update_params.conn_params.timeout); break; case BTC_GAP_BLE_ACT_SET_PKT_DATA_LEN: btc_ble_set_pkt_data_len(arg->set_pkt_data_len.remote_device, arg->set_pkt_data_len.tx_data_length, btc_set_pkt_length_callback); @@ -1186,3 +1186,10 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) btc_gap_ble_arg_deep_free(msg); } + +//register connection parameter update callback +void btc_gap_callback_init(void) +{ + BTM_BleRegiseterConnParamCallback(btc_update_conn_param_callback); + +} diff --git a/components/bt/bluedroid/btc/profile/std/include/btc_gap_ble.h b/components/bt/bluedroid/btc/profile/std/include/btc_gap_ble.h index 507089a267..b6da536065 100644 --- a/components/bt/bluedroid/btc/profile/std/include/btc_gap_ble.h +++ b/components/bt/bluedroid/btc/profile/std/include/btc_gap_ble.h @@ -136,6 +136,6 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); void btc_gap_ble_arg_deep_free(btc_msg_t *msg); void btc_gap_ble_cb_deep_free(btc_msg_t *msg); void btc_gap_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); - +void btc_gap_callback_init(void); #endif /* __BTC_GAP_BLE_H__ */ diff --git a/components/bt/bluedroid/stack/btm/btm_ble_gap.c b/components/bt/bluedroid/stack/btm/btm_ble_gap.c index 4edd1a5f0f..c7cc57a5a4 100644 --- a/components/bt/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/bluedroid/stack/btm/btm_ble_gap.c @@ -61,6 +61,7 @@ static tBTM_BLE_VSC_CB cmn_ble_vsc_cb; static tBTM_BLE_CTRL_FEATURES_CBACK *p_ctrl_le_feature_rd_cmpl_cback = NULL; #endif +tBTM_CallbackFunc conn_param_update_cb; /******************************************************************************* ** Local functions *******************************************************************************/ @@ -220,6 +221,19 @@ const UINT8 btm_le_state_combo_tbl[BTM_BLE_STATE_MAX][BTM_BLE_STATE_MAX][2] = { /* check LE combo state supported */ #define BTM_LE_STATES_SUPPORTED(x, y, z) ((x)[(z)] & (y)) +/******************************************************************************* +** +** Function BTM_BleRegiseterConnParamCallback +** +** Description register connection parameters update callback func +** +** Returns void +** +*******************************************************************************/ +void BTM_BleRegiseterConnParamCallback(tBTM_UPDATE_CONN_PARAM_CBACK *update_conn_param_cb) +{ + conn_param_update_cb.update_conn_param_cb = update_conn_param_cb; +} /******************************************************************************* ** diff --git a/components/bt/bluedroid/stack/btu/btu_hcif.c b/components/bt/bluedroid/stack/btu/btu_hcif.c index 02e6823331..933f517b4a 100644 --- a/components/bt/bluedroid/stack/btu/btu_hcif.c +++ b/components/bt/bluedroid/stack/btu/btu_hcif.c @@ -124,6 +124,7 @@ static void btu_ble_ll_conn_complete_evt (UINT8 *p, UINT16 evt_len); static void btu_ble_process_adv_pkt (UINT8 *p); 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_ll_get_conn_param_format_err_from_contoller (UINT8 status, UINT16 handle); #if (SMP_INCLUDED == TRUE) static void btu_ble_proc_ltk_req (UINT8 *p); static void btu_hcif_encryption_key_refresh_cmpl_evt (UINT8 *p); @@ -1126,6 +1127,13 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c case HCI_BLE_CREATE_LL_CONN: btm_ble_create_ll_conn_complete(status); break; + case HCI_BLE_UPD_LL_CONN_PARAMS: + if (p_cmd != NULL){ + p_cmd++; + STREAM_TO_UINT16 (handle, p_cmd); + btu_ble_ll_get_conn_param_format_err_from_contoller(status, handle); + } + break; #endif #if BTM_SCO_INCLUDED == TRUE @@ -1752,6 +1760,14 @@ static void btu_ble_ll_conn_param_upd_evt (UINT8 *p, UINT16 evt_len) conn_latency, conn_timeout); } +static void btu_ble_ll_get_conn_param_format_err_from_contoller (UINT8 status, UINT16 handle) +{ + /* host send illegal connection parameters format, controller would send + back HCI_ERR_ILLEGAL_PARAMETER_FMT */ + l2cble_get_conn_param_format_err_from_contoller(status, handle); + +} + static void btu_ble_read_remote_feat_evt (UINT8 *p) { btm_ble_read_remote_features_complete(p); diff --git a/components/bt/bluedroid/stack/include/btm_ble_api.h b/components/bt/bluedroid/stack/include/btm_ble_api.h index d7f0692867..d23313cb81 100644 --- a/components/bt/bluedroid/stack/include/btm_ble_api.h +++ b/components/bt/bluedroid/stack/include/btm_ble_api.h @@ -163,12 +163,12 @@ typedef UINT8 tBTM_BLE_SFP; /* default connection interval min */ #ifndef BTM_BLE_CONN_INT_MIN_DEF -#define BTM_BLE_CONN_INT_MIN_DEF 24 /* recommended min: 30ms = 24 * 1.25 */ +#define BTM_BLE_CONN_INT_MIN_DEF 10 /* recommended min: 12.5 ms = 10 * 1.25 */ #endif /* default connection interval max */ #ifndef BTM_BLE_CONN_INT_MAX_DEF -#define BTM_BLE_CONN_INT_MAX_DEF 40 /* recommended max: 50 ms = 56 * 1.25 */ +#define BTM_BLE_CONN_INT_MAX_DEF 12 /* recommended max: 15 ms = 12 * 1.25 */ #endif /* default slave latency */ @@ -860,6 +860,20 @@ tBTM_BLE_SCAN_SETUP_CBACK bta_ble_scan_setup_cb; extern "C" { #endif */ + +/******************************************************************************* +** +** Function BTM_BleRegiseterConnParamCallback +** +** Description register connection parameters update callback func +** +** Parameters: update_conn_param_cb +** +** Returns void +** +*******************************************************************************/ +void BTM_BleRegiseterConnParamCallback(tBTM_UPDATE_CONN_PARAM_CBACK *update_conn_param_cb); + /******************************************************************************* ** ** Function BTM_SecAddBleDevice diff --git a/components/bt/bluedroid/stack/include/btm_int.h b/components/bt/bluedroid/stack/include/btm_int.h index 2e017463b4..42468d9586 100644 --- a/components/bt/bluedroid/stack/include/btm_int.h +++ b/components/bt/bluedroid/stack/include/btm_int.h @@ -114,7 +114,6 @@ UINT8 conn_addr_type; /* local device address type for this co BD_ADDR active_remote_addr; /* remote address used on this connection */ UINT8 active_remote_addr_type; /* local device address type for this connection */ BD_FEATURES peer_le_features; /* Peer LE Used features mask for the device */ -tBTM_UPDATE_CONN_PARAM_CBACK *update_conn_param_cb; tBTM_SET_PKT_DATA_LENGTH_CBACK *p_set_pkt_data_cback; tBTM_LE_SET_PKT_DATA_LENGTH_PARAMS data_length_params; #endif @@ -873,6 +872,12 @@ typedef struct { #endif } tBTM_CB; +typedef struct{ + //connection parameters update callback + tBTM_UPDATE_CONN_PARAM_CBACK *update_conn_param_cb; +}tBTM_CallbackFunc; + +extern tBTM_CallbackFunc conn_param_update_cb; /* #ifdef __cplusplus extern "C" diff --git a/components/bt/bluedroid/stack/l2cap/include/l2c_int.h b/components/bt/bluedroid/stack/l2cap/include/l2c_int.h index 4199a9252a..ef31d1095e 100644 --- a/components/bt/bluedroid/stack/l2cap/include/l2c_int.h +++ b/components/bt/bluedroid/stack/l2cap/include/l2c_int.h @@ -405,14 +405,24 @@ typedef struct t_l2c_linkcb { #define L2C_BLE_NEW_CONN_PARAM 0x2 /* new connection parameter to be set */ #define L2C_BLE_UPDATE_PENDING 0x4 /* waiting for connection update finished */ #define L2C_BLE_NOT_DEFAULT_PARAM 0x8 /* not using default connection parameters */ +#define L2C_BLE_UPDATE_PARAM_FULL 0x10 /* update connection parameters full, can not update */ UINT8 conn_update_mask; - - UINT16 min_interval; /* parameters as requested by peripheral */ - UINT16 max_interval; - UINT16 conn_int; - UINT16 latency; - UINT16 timeout; - + /* cache connection parameters that wait to update */ + UINT16 waiting_update_conn_min_interval; + UINT16 waiting_update_conn_max_interval; + UINT16 waiting_update_conn_latency; + UINT16 waiting_update_conn_timeout; + /* cache parameters that is being updated */ + UINT16 updating_conn_min_interval; + UINT16 updating_conn_max_interval; + bool updating_param_flag; + /* current connection parameters that current connection is using */ + UINT16 current_used_conn_interval; + UINT16 current_used_conn_latency; + UINT16 current_used_conn_timeout; + /* connection parameters update order: + waiting_update_conn_xx -> updating_conn_xx -> current_used_conn_xx + */ #endif #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) @@ -736,6 +746,7 @@ extern void l2cble_notify_le_connection (BD_ADDR bda); extern void l2c_ble_link_adjust_allocation (void); extern void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status, UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout); +extern void l2cble_get_conn_param_format_err_from_contoller(UINT8 status, UINT16 handle); #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) extern void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 int_max, @@ -748,6 +759,7 @@ extern void l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda, UINT16 f extern void l2c_send_update_conn_params_cb(tL2C_LCB *p_lcb, UINT8 status); extern void l2cble_process_data_length_change_event(UINT16 handle, UINT16 tx_data_len, UINT16 rx_data_len); +extern UINT32 CalConnectParamTimeout(tL2C_LCB *p_lcb); #endif extern void l2cu_process_fixed_disc_cback (tL2C_LCB *p_lcb); diff --git a/components/bt/bluedroid/stack/l2cap/l2c_ble.c b/components/bt/bluedroid/stack/l2cap/l2c_ble.c index f6f8319fc1..48f3a5d0cd 100644 --- a/components/bt/bluedroid/stack/l2cap/l2c_ble.c +++ b/components/bt/bluedroid/stack/l2cap/l2c_ble.c @@ -117,14 +117,30 @@ BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_in return (FALSE); } - p_lcb->min_interval = min_int; - p_lcb->max_interval = max_int; - p_lcb->latency = latency; - p_lcb->timeout = timeout; + if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PARAM_FULL){ + UINT8 status = HCI_ERR_ILLEGAL_COMMAND; + L2CAP_TRACE_ERROR("There are two connection parameter requests that are being updated, please try later "); + if (conn_param_update_cb.update_conn_param_cb != NULL) { + tBTM_LE_UPDATE_CONN_PRAMS update_param; + update_param.max_conn_int = max_int; + update_param.min_conn_int = min_int; + update_param.conn_int = p_lcb->current_used_conn_interval; + update_param.slave_latency = p_lcb->current_used_conn_latency; + update_param.supervision_tout = p_lcb->current_used_conn_timeout; + (conn_param_update_cb.update_conn_param_cb)(status, p_lcb->remote_bd_addr, &update_param); + } + return (FALSE); + } + + p_lcb->waiting_update_conn_min_interval = min_int; + p_lcb->waiting_update_conn_max_interval = max_int; + p_lcb->waiting_update_conn_latency = latency; + p_lcb->waiting_update_conn_timeout = timeout; p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM; if(l2cble_start_conn_update(p_lcb) == TRUE) { - btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, L2CAP_UPDATE_CONN_PARAM_TOUT); + UINT32 time = CalConnectParamTimeout(p_lcb); + btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time); } return (TRUE); @@ -167,6 +183,10 @@ BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable) return (FALSE); } + if (p_lcb->current_used_conn_interval <= BTM_BLE_CONN_INT_MAX_DEF && (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0){ + return (FALSE); + } + if (enable) { p_lcb->conn_update_mask &= ~L2C_BLE_CONN_UPDATE_DISABLE; } else { @@ -174,7 +194,8 @@ BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable) } if (l2cble_start_conn_update(p_lcb) == TRUE) { - btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, L2CAP_UPDATE_CONN_PARAM_TOUT); + UINT32 time = CalConnectParamTimeout(p_lcb); + btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time); } return (TRUE); @@ -304,10 +325,11 @@ void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type, p_lcb->transport = BT_TRANSPORT_LE; /* update link parameter, set slave link as non-spec default upon link up */ - p_lcb->min_interval = p_lcb->max_interval = conn_interval; - p_lcb->timeout = conn_timeout; - p_lcb->latency = conn_latency; + p_lcb->waiting_update_conn_min_interval = p_lcb->waiting_update_conn_max_interval = p_lcb->current_used_conn_interval = conn_interval; + p_lcb->waiting_update_conn_timeout = p_lcb->current_used_conn_timeout = conn_timeout; + p_lcb->waiting_update_conn_latency = p_lcb->current_used_conn_latency = conn_latency; p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM; + p_lcb->updating_param_flag = false; /* If there are any preferred connection parameters, set them now */ if ( (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN ) && @@ -326,10 +348,10 @@ void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type, handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int, p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout); - p_lcb->min_interval = p_dev_rec->conn_params.min_conn_int; - p_lcb->max_interval = p_dev_rec->conn_params.max_conn_int; - p_lcb->timeout = p_dev_rec->conn_params.supervision_tout; - p_lcb->latency = p_dev_rec->conn_params.slave_latency; + p_lcb->waiting_update_conn_min_interval = p_dev_rec->conn_params.min_conn_int; + p_lcb->waiting_update_conn_max_interval = p_dev_rec->conn_params.max_conn_int; + p_lcb->waiting_update_conn_timeout = p_dev_rec->conn_params.supervision_tout; + p_lcb->waiting_update_conn_latency = p_dev_rec->conn_params.slave_latency; btsnd_hcic_ble_upd_ll_conn_params (handle, p_dev_rec->conn_params.min_conn_int, @@ -403,10 +425,11 @@ void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE typ p_lcb->transport = BT_TRANSPORT_LE; /* update link parameter, set slave link as non-spec default upon link up */ - p_lcb->min_interval = p_lcb->max_interval = conn_interval; - p_lcb->timeout = conn_timeout; - p_lcb->latency = conn_latency; + p_lcb->waiting_update_conn_min_interval = p_lcb->waiting_update_conn_max_interval = p_lcb->current_used_conn_interval = conn_interval; + p_lcb->waiting_update_conn_timeout = p_lcb->current_used_conn_timeout = conn_timeout; + p_lcb->waiting_update_conn_latency = p_lcb->current_used_conn_latency = conn_latency; p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM; + p_lcb->updating_param_flag = false; /* Tell BTM Acl management about the link */ p_dev_rec = btm_find_or_alloc_dev (bda); @@ -469,10 +492,10 @@ static BOOLEAN l2cble_start_conn_update (tL2C_LCB *p_lcb) #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) && (BLE_SLAVE_UPD_CONN_PARAMS == TRUE) tACL_CONN *p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE); #endif /* defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) && (BLE_SLAVE_UPD_CONN_PARAMS == TRUE */ - UINT8 status; if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) { - L2CAP_TRACE_ERROR("%s, the last connection update command still pending.", __func__); + L2CAP_TRACE_WARNING("%s, the last connection update command still pending.", __func__); + p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PARAM_FULL; return FALSE; } @@ -482,7 +505,7 @@ static BOOLEAN l2cble_start_conn_update (tL2C_LCB *p_lcb) up to what has been requested during connection establishement */ if (p_lcb->conn_update_mask & L2C_BLE_NOT_DEFAULT_PARAM && /* current connection interval is greater than default min */ - p_lcb->min_interval > BTM_BLE_CONN_INT_MIN) { + p_lcb->waiting_update_conn_min_interval > BTM_BLE_CONN_INT_MIN) { /* use 7.5 ms as fast connection parameter, 0 slave latency */ min_conn_int = max_conn_int = BTM_BLE_CONN_INT_MIN; slave_latency = BTM_BLE_CONN_SLAVE_LATENCY_DEF; @@ -500,15 +523,17 @@ static BOOLEAN l2cble_start_conn_update (tL2C_LCB *p_lcb) } else { l2cu_send_peer_ble_par_req (p_lcb, min_conn_int, max_conn_int, slave_latency, supervision_tout); } + + //cache save + p_lcb->updating_conn_min_interval = min_conn_int; + p_lcb->updating_conn_max_interval = max_conn_int; + p_lcb->updating_param_flag = true; + p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING; p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM; p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM; return TRUE; - } else { - status = HCI_ERR_ILLEGAL_COMMAND; - L2CAP_TRACE_ERROR("%s, staus = %x, line = %d", __func__, status, __LINE__); - btu_stop_timer(&p_lcb->upda_con_timer); - l2c_send_update_conn_params_cb(p_lcb, status); + }else { return FALSE; } } else { @@ -521,18 +546,23 @@ static BOOLEAN l2cble_start_conn_update (tL2C_LCB *p_lcb) HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features)) #endif ) { - 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); + btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->waiting_update_conn_min_interval, + p_lcb->waiting_update_conn_max_interval, p_lcb->waiting_update_conn_latency, p_lcb->waiting_update_conn_timeout, 0, 0); } else { - l2cu_send_peer_ble_par_req (p_lcb, p_lcb->min_interval, p_lcb->max_interval, - p_lcb->latency, p_lcb->timeout); + l2cu_send_peer_ble_par_req (p_lcb, p_lcb->waiting_update_conn_min_interval, p_lcb->waiting_update_conn_max_interval, + p_lcb->waiting_update_conn_latency, p_lcb->waiting_update_conn_timeout); } + + //cache save + p_lcb->updating_conn_min_interval = p_lcb->waiting_update_conn_min_interval; + p_lcb->updating_conn_max_interval = p_lcb->waiting_update_conn_max_interval; + p_lcb->updating_param_flag = true; + p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING; p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM; p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM; return TRUE; } else { - btu_stop_timer(&p_lcb->upda_con_timer); return FALSE; } } @@ -553,36 +583,77 @@ void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status, UINT16 conn_in { tL2C_LCB *p_lcb; - L2CAP_TRACE_DEBUG("l2cble_process_conn_update_evt"); /* See if we have a link control block for the remote device */ p_lcb = l2cu_find_lcb_by_handle(handle); if (!p_lcb) { L2CAP_TRACE_WARNING("l2cble_process_conn_update_evt: Invalid handle: %d", handle); return; } - - p_lcb->conn_int = conn_interval; - p_lcb->latency = conn_latency; - p_lcb->timeout = conn_timeout; - tACL_CONN *p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE); - p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING; - - if (status != HCI_SUCCESS) { + if (status == HCI_SUCCESS){ + p_lcb->current_used_conn_interval = conn_interval; + p_lcb->current_used_conn_latency = conn_latency; + p_lcb->current_used_conn_timeout = conn_timeout; + }else{ L2CAP_TRACE_WARNING("l2cble_process_conn_update_evt: Error status: %d", status); } - if (l2cble_start_conn_update(p_lcb) == TRUE) { - btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, L2CAP_UPDATE_CONN_PARAM_TOUT); - } + p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING; + p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PARAM_FULL; - btu_stop_timer (&p_lcb->timer_entry); - - if (p_acl_cb->update_conn_param_cb != NULL) { + btu_stop_timer(&p_lcb->upda_con_timer); + + if (conn_param_update_cb.update_conn_param_cb != NULL) { l2c_send_update_conn_params_cb(p_lcb, status); } + if (l2cble_start_conn_update(p_lcb) == TRUE) { + UINT32 time = CalConnectParamTimeout(p_lcb); + btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time); + } + + btu_stop_timer (&p_lcb->timer_entry); + L2CAP_TRACE_DEBUG("l2cble_process_conn_update_evt: conn_update_mask=%d", p_lcb->conn_update_mask); } + +/******************************************************************************* +** +** Function l2cble_get_conn_param_format_err_from_contoller +** +** Description This function is called when host get illegal connection paramrters +** format status from controller +** +** Returns void +** +*******************************************************************************/ +void l2cble_get_conn_param_format_err_from_contoller (UINT8 status, UINT16 handle) +{ + tL2C_LCB *p_lcb; + + /* See if we have a link control block for the remote device */ + p_lcb = l2cu_find_lcb_by_handle(handle); + if (!p_lcb) { + L2CAP_TRACE_ERROR("%s: Invalid handle: %d", __FUNCTION__, handle); + return; + } + + p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING; + + btu_stop_timer (&p_lcb->upda_con_timer); + + if (conn_param_update_cb.update_conn_param_cb != NULL) { + l2c_send_update_conn_params_cb(p_lcb, status); + } + if ((p_lcb->conn_update_mask & L2C_BLE_UPDATE_PARAM_FULL) != 0){ + p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PARAM_FULL; + if (l2cble_start_conn_update(p_lcb) == TRUE) { + UINT32 time = CalConnectParamTimeout(p_lcb); + btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time); + } + } + +} + /******************************************************************************* ** ** Function l2cble_process_sig_cmd @@ -630,32 +701,34 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len) STREAM_TO_UINT16 (timeout, p); /* 0x000A - 0x0C80 */ /* If we are a master, the slave wants to update the parameters */ if (p_lcb->link_role == HCI_ROLE_MASTER) { - if (min_interval < BTM_BLE_CONN_INT_MIN_LIMIT) { - min_interval = BTM_BLE_CONN_INT_MIN_LIMIT; - } - if (min_interval < BTM_BLE_CONN_INT_MIN || min_interval > BTM_BLE_CONN_INT_MAX || max_interval < BTM_BLE_CONN_INT_MIN || max_interval > BTM_BLE_CONN_INT_MAX || latency > BTM_BLE_CONN_LATENCY_MAX || - /*(timeout >= max_interval && latency > (timeout * 10/(max_interval * 1.25) - 1)) ||*/ timeout < BTM_BLE_CONN_SUP_TOUT_MIN || timeout > BTM_BLE_CONN_SUP_TOUT_MAX || - timeout <= ((1 + latency)*max_interval*2) || + /* The supervision_timeout parameter defines the link supervision timeout for the connection. + The supervision_timeout in milliseconds shall be large than (1 + latency) * max_interval * 2, + where max_interval is given in milliseconds. (See [Vol 6] Part B, Section 4.5.2). + supervision_timeout (mult of 10ms); conn_interval (mult of 1.25ms) + (max_interval * 1.25 * 2) replaced by ((max_interval * 5) >> 1). + */ + ((timeout * 10) < ((1 + latency) *((max_interval * 5) >> 1))) || max_interval < min_interval) { l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id); - UINT8 status = HCI_ERR_PARAM_OUT_OF_RANGE; - l2c_send_update_conn_params_cb(p_lcb, status); + + L2CAP_TRACE_ERROR("slave connection parameters update failed, the parameters are out of range"); + } else { l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_OK, id); - - p_lcb->min_interval = min_interval; - p_lcb->max_interval = max_interval; - p_lcb->latency = latency; - p_lcb->timeout = timeout; + p_lcb->waiting_update_conn_min_interval = min_interval; + p_lcb->waiting_update_conn_max_interval = max_interval; + p_lcb->waiting_update_conn_latency = latency; + p_lcb->waiting_update_conn_timeout = timeout; p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM; if (l2cble_start_conn_update(p_lcb) == TRUE) { - btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, L2CAP_UPDATE_CONN_PARAM_TOUT); + UINT32 time = CalConnectParamTimeout(p_lcb); + btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time); } } } else { @@ -669,6 +742,8 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len) UINT8 status = (result == 0) ? HCI_SUCCESS : HCI_ERR_PARAM_OUT_OF_RANGE; if (status != HCI_SUCCESS) { btu_stop_timer(&p_lcb->upda_con_timer); + p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING; + p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PARAM_FULL; l2c_send_update_conn_params_cb(p_lcb, status); } break; @@ -945,10 +1020,7 @@ void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 i tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle (handle); if (p_lcb != NULL) { - p_lcb->min_interval = int_min; - p_lcb->max_interval = int_max; - p_lcb->latency = latency; - p_lcb->timeout = timeout; + /* if update is enabled, always accept connection parameter update */ if ((p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0) { p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING; @@ -1087,16 +1159,48 @@ void l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda, UINT16 fix_cid, *******************************************************************************/ void l2c_send_update_conn_params_cb(tL2C_LCB *p_lcb, UINT8 status) { - tACL_CONN *p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE); - if (p_acl_cb != NULL && p_acl_cb->update_conn_param_cb != NULL) { + if(conn_param_update_cb.update_conn_param_cb != NULL){ tBTM_LE_UPDATE_CONN_PRAMS update_param; - update_param.max_conn_int = p_lcb->max_interval; - update_param.min_conn_int = p_lcb->min_interval; - update_param.conn_int = p_lcb->conn_int; - update_param.slave_latency = p_lcb->latency; - update_param.supervision_tout = p_lcb->timeout; - (p_acl_cb->update_conn_param_cb)(status, p_acl_cb->active_remote_addr, &update_param); + //if myself update the connection parameters + if (p_lcb->updating_param_flag){ + update_param.max_conn_int = p_lcb->updating_conn_max_interval; + update_param.min_conn_int = p_lcb->updating_conn_min_interval; + p_lcb->updating_param_flag = false; + }else{ + // remote device update the connection parameters + update_param.max_conn_int = update_param.min_conn_int = 0; + } + // current connection parameters + update_param.conn_int = p_lcb->current_used_conn_interval; + update_param.slave_latency = p_lcb->current_used_conn_latency; + update_param.supervision_tout = p_lcb->current_used_conn_timeout; + + (conn_param_update_cb.update_conn_param_cb)(status, p_lcb->remote_bd_addr, &update_param); } } +/******************************************************************************* +** +** Function CalConnectParamTimeout +** +** Description This function is called to calculate the connection parameter timeout. +** +** Returns timeout +** +*******************************************************************************/ +UINT32 CalConnectParamTimeout(tL2C_LCB *p_lcb) +{ + UINT32 timeout = 6; + if (p_lcb != NULL){ + //1.25 * conn_int *(1+ latency) *32 + timeout = (40 * ( 1 + p_lcb->current_used_conn_latency) * p_lcb->current_used_conn_interval + 500) / 1000; + if (timeout < 1){ + timeout = 1; + }else if (timeout > 120){ + timeout = 120; + } + } + return timeout; +} + #endif /* (BLE_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/stack/l2cap/l2c_main.c b/components/bt/bluedroid/stack/l2cap/l2c_main.c index d995d7376b..f5ec21703e 100644 --- a/components/bt/bluedroid/stack/l2cap/l2c_main.c +++ b/components/bt/bluedroid/stack/l2cap/l2c_main.c @@ -896,7 +896,12 @@ void l2c_process_timeout (TIMER_LIST_ENT *p_tle) break; case BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS: { UINT8 status = HCI_ERR_HOST_TIMEOUT; - l2c_send_update_conn_params_cb((tL2C_LCB *)p_tle->param, status); + tL2C_LCB *p_lcb = (tL2C_LCB *)p_tle->param; + if (p_lcb){ + p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING; + p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PARAM_FULL; + } + l2c_send_update_conn_params_cb(p_lcb, status); break; } } diff --git a/examples/bluetooth/gatt_client/main/gattc_demo.c b/examples/bluetooth/gatt_client/main/gattc_demo.c index d38ce6af50..dc83d7f106 100644 --- a/examples/bluetooth/gatt_client/main/gattc_demo.c +++ b/examples/bluetooth/gatt_client/main/gattc_demo.c @@ -306,7 +306,15 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *par } ESP_LOGI(GATTC_TAG, "stop adv successfully"); break; - + case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: + ESP_LOGI(GATTC_TAG, "update connetion params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d", + param->update_conn_params.status, + param->update_conn_params.min_int, + param->update_conn_params.max_int, + param->update_conn_params.conn_int, + param->update_conn_params.latency, + param->update_conn_params.timeout); + break; default: break; } diff --git a/examples/bluetooth/gatt_server/main/gatts_demo.c b/examples/bluetooth/gatt_server/main/gatts_demo.c index b6e15b9dde..2782c026d0 100644 --- a/examples/bluetooth/gatt_server/main/gatts_demo.c +++ b/examples/bluetooth/gatt_server/main/gatts_demo.c @@ -471,8 +471,8 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t)); /* For the IOS system, please reference the apple official documents about the ble connection parameters restrictions. */ conn_params.latency = 0; - conn_params.max_int = 0x50; // max_int = 0x50*1.25ms = 100ms - conn_params.min_int = 0x30; // min_int = 0x30*1.25ms = 60ms + conn_params.max_int = 0x20; // max_int = 0x20*1.25ms = 40ms + conn_params.min_int = 0x10; // min_int = 0x10*1.25ms = 20ms conn_params.timeout = 400; // timeout = 400*10ms = 4000ms ESP_LOGI(GATTS_TAG, "ESP_GATTS_CONNECT_EVT, conn_id %d, remote %02x:%02x:%02x:%02x:%02x:%02x:, is_conn %d", param->connect.conn_id,