From bce0e93b73b9ea3f1ed11566cf87d49d5ded3b1f Mon Sep 17 00:00:00 2001 From: xiongweichao Date: Wed, 17 Aug 2022 15:30:20 +0800 Subject: [PATCH 1/6] bt: Enter the congestion state when the queue length waiting for the peer to ack is greater than or equal to the L2CAP ERTM tx window size --- .../bluedroid/common/include/common/bt_target.h | 2 +- .../bt/host/bluedroid/stack/l2cap/l2c_fcr.c | 3 +++ .../bt/host/bluedroid/stack/l2cap/l2c_utils.c | 15 +++++++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/components/bt/host/bluedroid/common/include/common/bt_target.h b/components/bt/host/bluedroid/common/include/common/bt_target.h index 83abc9ba8c..22de4d6c7b 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -1578,7 +1578,7 @@ /* ERTM Tx window size */ #ifndef RFC_FCR_OPT_TX_WINDOW_SIZE -#define RFC_FCR_OPT_TX_WINDOW_SIZE 20 +#define RFC_FCR_OPT_TX_WINDOW_SIZE 10 #endif /* ERTM Maximum transmissions before disconnecting */ diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_fcr.c b/components/bt/host/bluedroid/stack/l2cap/l2c_fcr.c index ecf0bd6c68..aafb4b380d 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_fcr.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_fcr.c @@ -928,6 +928,9 @@ static BOOLEAN process_reqseq (tL2C_CCB *p_ccb, UINT16 ctrl_word) full_sdus_xmitted++; } osi_free(p_tmp); + if (p_ccb->cong_sent) { + l2cu_check_channel_congestion(p_ccb); + } } /* If we are still in a wait_ack state, do not mess with the timer */ diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c b/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c index ea887b036e..06eebe80b2 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c @@ -3613,6 +3613,9 @@ void l2cu_set_acl_hci_header (BT_HDR *p_buf, tL2C_CCB *p_ccb) void l2cu_check_channel_congestion (tL2C_CCB *p_ccb) { size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q); +#if (CLASSIC_BT_INCLUDED == TRUE) + size_t q_waiting_ack_count = fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q); +#endif #if (L2CAP_UCD_INCLUDED == TRUE) if ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) { @@ -3625,7 +3628,11 @@ void l2cu_check_channel_congestion (tL2C_CCB *p_ccb) /* If this channel was congested */ if ( p_ccb->cong_sent ) { /* If the channel is not congested now, tell the app */ - if (q_count <= (p_ccb->buff_quota / 2)) { + if (q_count <= (p_ccb->buff_quota / 2) +#if (CLASSIC_BT_INCLUDED == TRUE) + && (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE || q_waiting_ack_count < p_ccb->our_cfg.fcr.tx_win_sz) +#endif + ) { p_ccb->cong_sent = FALSE; if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) { L2CAP_TRACE_DEBUG ("L2CAP - Calling CongestionStatus_Cb (FALSE), CID: 0x%04x xmit_hold_q.count: %u buff_quota: %u", @@ -3664,7 +3671,11 @@ void l2cu_check_channel_congestion (tL2C_CCB *p_ccb) } else { tL2C_LCB *p_lcb = p_ccb->p_lcb; /* If this channel was not congested but it is congested now, tell the app */ - if (q_count > p_ccb->buff_quota || (p_lcb && (p_lcb->link_xmit_data_q) && (list_length(p_lcb->link_xmit_data_q) + q_count) > p_ccb->buff_quota)) { + if (q_count > p_ccb->buff_quota || (p_lcb && (p_lcb->link_xmit_data_q) && (list_length(p_lcb->link_xmit_data_q) + q_count) > p_ccb->buff_quota) +#if (CLASSIC_BT_INCLUDED == TRUE) + || (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE && q_waiting_ack_count >= p_ccb->our_cfg.fcr.tx_win_sz) +#endif + ) { p_ccb->cong_sent = TRUE; if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) { L2CAP_TRACE_DEBUG ("L2CAP - Calling CongestionStatus_Cb (TRUE),CID:0x%04x,XmitQ:%u,Quota:%u", From 6d9987f4c8d7e6fbaf89cd514e4c9f418f8c5a83 Mon Sep 17 00:00:00 2001 From: xiongweichao Date: Mon, 19 Sep 2022 20:20:22 +0800 Subject: [PATCH 2/6] bt: Split SPP application layer data packets according to the MTU of the peer --- .../bluedroid/bta/include/bta/bta_jv_api.h | 2 + .../bt/host/bluedroid/bta/jv/bta_jv_act.c | 5 ++ .../bluedroid/btc/profile/std/spp/btc_spp.c | 7 ++- .../bluedroid/stack/include/stack/port_api.h | 8 +++ .../bt/host/bluedroid/stack/rfcomm/port_rfc.c | 49 +++++++++++++------ 5 files changed, 53 insertions(+), 18 deletions(-) diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h index 8564b07399..f7293f88e6 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h @@ -286,6 +286,7 @@ typedef struct { /* data associated with BTA_JV_RFCOMM_OPEN_EVT */ typedef struct { tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT16 peer_mtu; /* Max MTU that port can send */ UINT32 handle; /* The connection handle */ BD_ADDR rem_bda; /* The peer address */ } tBTA_JV_RFCOMM_OPEN; @@ -293,6 +294,7 @@ typedef struct { /* data associated with BTA_JV_RFCOMM_SRV_OPEN_EVT */ typedef struct { tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ + UINT16 peer_mtu; /* Max MTU that port can send */ UINT32 handle; /* The connection handle */ UINT32 new_listen_handle; /* The new listen handle */ BD_ADDR rem_bda; /* The peer address */ diff --git a/components/bt/host/bluedroid/bta/jv/bta_jv_act.c b/components/bt/host/bluedroid/bta/jv/bta_jv_act.c index f3106600a1..da3a1225f5 100644 --- a/components/bt/host/bluedroid/bta/jv/bta_jv_act.c +++ b/components/bt/host/bluedroid/bta/jv/bta_jv_act.c @@ -1685,6 +1685,7 @@ static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle, void* dat BD_ADDR rem_bda = {0}; UINT16 lcid; tBTA_JV_RFCOMM_CBACK *p_cback; /* the callback function */ + tPORT_MGMT_CL_CALLBACK_ARG *p_mgmt_cb_arg = (tPORT_MGMT_CL_CALLBACK_ARG *)data; APPL_TRACE_DEBUG( "bta_jv_port_mgmt_cl_cback:code:%d, port_handle%d", code, port_handle); if (NULL == p_cb || NULL == p_cb->p_cback) { @@ -1701,6 +1702,9 @@ static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle, void* dat evt_data.rfc_open.status = BTA_JV_SUCCESS; bdcpy(evt_data.rfc_open.rem_bda, rem_bda); p_pcb->state = BTA_JV_ST_CL_OPEN; + if (p_mgmt_cb_arg) { + evt_data.rfc_open.peer_mtu = p_mgmt_cb_arg->peer_mtu; + } p_cb->p_cback(BTA_JV_RFCOMM_OPEN_EVT, &evt_data, p_pcb->user_data); } else { evt_data.rfc_close.handle = p_pcb->handle; @@ -1981,6 +1985,7 @@ static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle, void *dat } evt_data.rfc_srv_open.handle = p_pcb->handle; evt_data.rfc_srv_open.status = BTA_JV_SUCCESS; + evt_data.rfc_srv_open.peer_mtu = p_mgmt_cb_arg->peer_mtu; bdcpy(evt_data.rfc_srv_open.rem_bda, rem_bda); tBTA_JV_PCB *p_pcb_new_listen = bta_jv_add_rfc_port(p_cb, p_pcb); if (p_pcb_new_listen) { diff --git a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c index db1607ff38..5651213a08 100644 --- a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c @@ -52,8 +52,8 @@ typedef struct { uint8_t serial; uint8_t scn; uint8_t max_session; + uint16_t mtu; uint32_t id; - uint32_t mtu;//unused uint32_t sdp_handle; uint32_t rfc_handle; uint32_t rfc_port_handle; @@ -133,6 +133,7 @@ static spp_slot_t *spp_malloc_slot(void) (*slot)->fd = -1; (*slot)->connected = false; (*slot)->is_server = false; + (*slot)->mtu = 0; (*slot)->write_data = NULL; (*slot)->close_alarm = NULL; /* clear the old event bits */ @@ -333,6 +334,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u slot_new->max_session = slot->max_session; strcpy(slot_new->service_name, slot->service_name); slot_new->sdp_handle = slot->sdp_handle; + slot_new->mtu = p_data->rfc_srv_open.peer_mtu; slot_new->rfc_handle = p_data->rfc_srv_open.handle; slot_new->rfc_port_handle = BTA_JvRfcommGetPortHdl(slot_new->rfc_handle); BTA_JvSetPmProfile(p_data->rfc_srv_open.handle, BTA_JV_PM_ALL, BTA_JV_CONN_OPEN); @@ -375,6 +377,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u } slot->connected = true; slot->rfc_handle = p_data->rfc_open.handle; + slot->mtu = p_data->rfc_open.peer_mtu; slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_data->rfc_open.handle); BTA_JvSetPmProfile(p_data->rfc_open.handle, BTA_JV_PM_ID_1, BTA_JV_CONN_OPEN); break; @@ -1384,7 +1387,7 @@ static ssize_t spp_vfs_write(int fd, const void * data, size_t size) tx_event_group_val = 0; if (size) { if (p_buf == NULL) { - write_size = size < BTA_JV_DEF_RFC_MTU ? size : BTA_JV_DEF_RFC_MTU; + write_size = size < slot->mtu ? size : slot->mtu; if ((p_buf = osi_malloc(sizeof(BT_HDR) + write_size)) == NULL) { BTC_TRACE_ERROR("%s malloc failed!", __func__); errno = ENOMEM; diff --git a/components/bt/host/bluedroid/stack/include/stack/port_api.h b/components/bt/host/bluedroid/stack/include/stack/port_api.h index fb9e7574ba..928f8eb962 100644 --- a/components/bt/host/bluedroid/stack/include/stack/port_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/port_api.h @@ -113,8 +113,16 @@ typedef void (tPORT_MGMT_CALLBACK) (UINT32 code, UINT16 port_handle, void* data) typedef struct { BOOLEAN accept; /* If upper layer accepts the incoming connection */ BOOLEAN ignore_rfc_state; /* If need to ignore rfc state for PORT_CheckConnection */ + UINT16 peer_mtu; /* Max MTU that port can send */ } tPORT_MGMT_SR_CALLBACK_ARG; +/** + * Define the client port manage callback function argument + */ +typedef struct { + UINT16 peer_mtu; /* Max MTU that port can send */ +} tPORT_MGMT_CL_CALLBACK_ARG; + /* ** Define events that registered application can receive in the callback */ diff --git a/components/bt/host/bluedroid/stack/rfcomm/port_rfc.c b/components/bt/host/bluedroid/stack/rfcomm/port_rfc.c index ddcef1bb7c..c925ed9cb5 100644 --- a/components/bt/host/bluedroid/stack/rfcomm/port_rfc.c +++ b/components/bt/host/bluedroid/stack/rfcomm/port_rfc.c @@ -427,9 +427,11 @@ void PORT_ParNegCnf (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT8 cl, UINT8 k) void PORT_DlcEstablishInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu) { tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci); - tPORT_MGMT_SR_CALLBACK_ARG mgmt_cb_arg = { + tPORT_MGMT_CL_CALLBACK_ARG cl_mgmt_cb_arg = {0}; + tPORT_MGMT_SR_CALLBACK_ARG sr_mgmt_cb_arg = { .accept = TRUE, .ignore_rfc_state = FALSE, + .peer_mtu = 0, }; RFCOMM_TRACE_DEBUG ("PORT_DlcEstablishInd p_mcb:%p, dlci:%d mtu:%di, p_port:%p", p_mcb, dlci, mtu, p_port); @@ -464,22 +466,29 @@ void PORT_DlcEstablishInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu) } if (p_port->p_mgmt_callback) { - /** - * @note - * 1. The manage callback function may change the value of accept in mgmt_cb_arg. - * 2. Use mgmt_cb_arg.ignore_rfc_state to work around the issue caused by sending - * RFCOMM establish response after the manage callback function. - */ - mgmt_cb_arg.ignore_rfc_state = TRUE; - p_port->p_mgmt_callback (PORT_SUCCESS, p_port->inx, &mgmt_cb_arg); + if (p_port->is_server) { + sr_mgmt_cb_arg.peer_mtu = p_port->peer_mtu; + /** + * @note + * 1. The manage callback function may change the value of accept in mgmt_cb_arg. + * 2. Use mgmt_cb_arg.ignore_rfc_state to work around the issue caused by sending + * RFCOMM establish response after the manage callback function. + */ + sr_mgmt_cb_arg.ignore_rfc_state = TRUE; + p_port->p_mgmt_callback (PORT_SUCCESS, p_port->inx, &sr_mgmt_cb_arg); + + if (!sr_mgmt_cb_arg.accept) { + RFCOMM_DlcEstablishRsp(p_mcb, dlci, 0, RFCOMM_LOW_RESOURCES); + return; + } + } else { + cl_mgmt_cb_arg.peer_mtu = p_port->peer_mtu; + p_port->p_mgmt_callback (PORT_SUCCESS, p_port->inx, &cl_mgmt_cb_arg); + } } - if (mgmt_cb_arg.accept) { - RFCOMM_DlcEstablishRsp(p_mcb, dlci, p_port->mtu, RFCOMM_SUCCESS); - p_port->state = PORT_STATE_OPENED; - } else { - RFCOMM_DlcEstablishRsp(p_mcb, dlci, 0, RFCOMM_LOW_RESOURCES); - } + RFCOMM_DlcEstablishRsp(p_mcb, dlci, p_port->mtu, RFCOMM_SUCCESS); + p_port->state = PORT_STATE_OPENED; } @@ -496,6 +505,8 @@ void PORT_DlcEstablishInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu) void PORT_DlcEstablishCnf (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT16 result) { tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci); + tPORT_MGMT_SR_CALLBACK_ARG sr_mgmt_cb_arg = {0}; + tPORT_MGMT_CL_CALLBACK_ARG cl_mgmt_cb_arg = {0}; RFCOMM_TRACE_EVENT ("PORT_DlcEstablishCnf dlci:%d mtu:%d result:%d", dlci, mtu, result); @@ -522,7 +533,13 @@ void PORT_DlcEstablishCnf (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT16 resul } if (p_port->p_mgmt_callback) { - p_port->p_mgmt_callback (PORT_SUCCESS, p_port->inx, NULL); + if (p_port->is_server) { + sr_mgmt_cb_arg.peer_mtu = p_port->peer_mtu; + p_port->p_mgmt_callback (PORT_SUCCESS, p_port->inx, &sr_mgmt_cb_arg); + } else { + cl_mgmt_cb_arg.peer_mtu = p_port->peer_mtu; + p_port->p_mgmt_callback (PORT_SUCCESS, p_port->inx, &cl_mgmt_cb_arg); + } } p_port->state = PORT_STATE_OPENED; From aa25c4391c3e9af2a035e831098707eb714f0f94 Mon Sep 17 00:00:00 2001 From: xiongweichao Date: Tue, 27 Sep 2022 15:12:35 +0800 Subject: [PATCH 3/6] bt: Replaced the tx queue in SPP VFS mode with ringbuffer --- components/bt/host/bluedroid/Kconfig.in | 9 + .../btc/profile/std/include/btc_spp.h | 2 - .../bluedroid/btc/profile/std/spp/btc_spp.c | 228 ++++++++++-------- .../include/common/bluedroid_user_config.h | 6 + .../common/include/common/bt_target.h | 4 + 5 files changed, 147 insertions(+), 102 deletions(-) diff --git a/components/bt/host/bluedroid/Kconfig.in b/components/bt/host/bluedroid/Kconfig.in index d03f182b11..1666865f4b 100644 --- a/components/bt/host/bluedroid/Kconfig.in +++ b/components/bt/host/bluedroid/Kconfig.in @@ -61,6 +61,15 @@ config BT_SPP_ENABLED help This enables the Serial Port Profile +config BT_SPP_SEND_BUF_DEFAULT + int "SPP default send buffer size" + depends on BT_SPP_ENABLED + range 100 10000 + default 4000 + help + Sets the default send buffer size for new SPP channels. Setting a smaller + default SNDBUF size can save some memory, but may decrease performance. + config BT_L2CAP_ENABLED bool "BT L2CAP" depends on BT_CLASSIC_ENABLED diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_spp.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_spp.h index 0615b456c4..7f0f9e81b4 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_spp.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_spp.h @@ -18,8 +18,6 @@ #define ESP_SPP_MAX_SESSION BTA_JV_MAX_RFC_SR_SESSION #define ESP_SPP_SERVER_NAME_MAX 32 -#define ESP_SPP_RINGBUF_SIZE 1000 - #define BTC_SPP_INVALID_SCN 0x00 typedef enum { diff --git a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c index 5651213a08..44dd4ed664 100644 --- a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c @@ -49,10 +49,12 @@ typedef struct { typedef struct { bool connected; bool is_server; + bool is_writing; uint8_t serial; uint8_t scn; uint8_t max_session; uint16_t mtu; + uint16_t write_data_len; uint32_t id; uint32_t sdp_handle; uint32_t rfc_handle; @@ -64,7 +66,10 @@ typedef struct { esp_spp_sec_t security; esp_bd_addr_t addr; slot_data_t rx; - slot_data_t tx; + union { + slot_data_t tx; + RingbufHandle_t ringbuf_write; + }; uint8_t service_uuid[16]; char service_name[ESP_SPP_SERVER_NAME_MAX + 1]; } spp_slot_t; @@ -135,6 +140,8 @@ static spp_slot_t *spp_malloc_slot(void) (*slot)->is_server = false; (*slot)->mtu = 0; (*slot)->write_data = NULL; + (*slot)->write_data_len = 0; + (*slot)->is_writing = false; (*slot)->close_alarm = NULL; /* clear the old event bits */ if (spp_local_param.tx_event_group) { @@ -146,12 +153,18 @@ static spp_slot_t *spp_malloc_slot(void) err_no = 1; goto err; } - if (init_slot_data(&(*slot)->tx, SLOT_TX_QUEUE_SIZE)) { - BTC_TRACE_ERROR("%s unable to malloc tx queue!", __func__); - err_no = 2; - goto err; - } - if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) { + if (spp_local_param.spp_mode == ESP_SPP_MODE_CB) { + if (init_slot_data(&(*slot)->tx, SLOT_TX_QUEUE_SIZE)) { + BTC_TRACE_ERROR("%s unable to malloc tx queue!", __func__); + err_no = 2; + goto err; + } + } else { + if (((*slot)->ringbuf_write = xRingbufferCreate(BTC_SPP_SEND_BUF_DEFAULT, RINGBUF_TYPE_BYTEBUF)) == NULL) { + BTC_TRACE_ERROR("%s write ringbuffer create error!", __func__); + err_no = 2; + goto err; + } if (esp_vfs_register_fd(spp_local_param.spp_vfs_id, &(*slot)->fd) != ESP_OK) { BTC_TRACE_ERROR("%s unable to register fd!", __func__); err_no = 3; @@ -166,7 +179,9 @@ static spp_slot_t *spp_malloc_slot(void) err: switch (err_no) { case 3: - free_slot_data(&(*slot)->tx); + if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) { + vRingbufferDelete((*slot)->ringbuf_write); + } case 2: free_slot_data(&(*slot)->rx); case 1: @@ -239,7 +254,7 @@ static void close_timeout_handler(void *arg) status = btc_transfer_context(&msg, arg, sizeof(tBTA_JV), NULL); if (arg) { - free(arg); + osi_free(arg); } if (status != BT_STATUS_SUCCESS) { @@ -256,8 +271,10 @@ static void spp_free_slot(spp_slot_t *slot) if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) { (void) esp_vfs_unregister_fd(spp_local_param.spp_vfs_id, slot->fd); xEventGroupSetBits(spp_local_param.tx_event_group, SLOT_CLOSE_BIT(slot->serial)); + vRingbufferDelete(slot->ringbuf_write); + } else { + free_slot_data(&slot->tx); } - free_slot_data(&slot->tx); free_slot_data(&slot->rx); if (slot->close_alarm) { osi_alarm_free(slot->close_alarm); @@ -734,7 +751,7 @@ static void btc_spp_stop_srv(btc_spp_args_t *arg) esp_spp_status_t ret = ESP_SPP_SUCCESS; bool is_remove_all = false; uint8_t i, j, srv_cnt = 0; - uint8_t *srv_scn_arr = osi_malloc(MAX_RFC_PORTS); + uint8_t *srv_scn_arr = NULL; if (arg->stop_srv.scn == BTC_SPP_INVALID_SCN) { is_remove_all = true; } @@ -745,6 +762,7 @@ static void btc_spp_stop_srv(btc_spp_args_t *arg) ret = ESP_SPP_NEED_INIT; break; } + srv_scn_arr = osi_malloc(MAX_RFC_PORTS); if (srv_scn_arr == NULL) { BTC_TRACE_ERROR("%s malloc srv_scn_arr failed\n", __func__); ret = ESP_SPP_NO_RESOURCE; @@ -837,6 +855,7 @@ static void btc_spp_stop_srv(btc_spp_args_t *arg) static void btc_spp_write(btc_spp_args_t *arg) { esp_spp_status_t ret = ESP_SPP_SUCCESS; + do { if (!is_spp_init()) { BTC_TRACE_ERROR("%s SPP have not been init\n", __func__); @@ -857,18 +876,23 @@ static void btc_spp_write(btc_spp_args_t *arg) break; } if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) { - BT_HDR *p_buf; - if ((p_buf = fixed_queue_try_peek_first(slot->tx.queue)) != NULL && p_buf->layer_specific == 0) { - p_buf->event++; - p_buf->layer_specific = 1; - BTA_JvRfcommWrite(arg->write.handle, slot->id, p_buf->len, p_buf->data + p_buf->offset); + if (slot->is_writing) { + osi_mutex_unlock(&spp_local_param.spp_slot_mutex); + return; + } + size_t item_size = 0; + uint8_t *data = xRingbufferReceiveUpTo(slot->ringbuf_write, &item_size, 0, slot->mtu); + if (item_size > 0) { + slot->write_data = data; + slot->write_data_len = item_size; + slot->is_writing = true; + BTA_JvRfcommWrite(arg->write.handle, slot->id, item_size, data); } } else { if (fixed_queue_enqueue(slot->tx.queue, arg->write.p_data, 0)) { BTA_JvRfcommWrite(arg->write.handle, slot->id, arg->write.len, arg->write.p_data); } else { ret = ESP_SPP_NO_RESOURCE; - break; } } osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -1066,37 +1090,44 @@ void btc_spp_cb_handler(btc_msg_t *msg) } } else { if (slot) { - BT_HDR *p_buf; + size_t item_size = 0; + size_t items_waiting = 0; serial = slot->serial; - if ((p_buf = fixed_queue_try_peek_first(slot->tx.queue)) == NULL) { - osi_mutex_unlock(&spp_local_param.spp_slot_mutex); - break; - } if (p_data->rfc_write.status == BTA_JV_SUCCESS) { - p_buf->len -= p_data->rfc_write.len; - p_buf->offset += p_data->rfc_write.len; - p_buf->layer_specific = 0; - if (p_buf->len == 0) { - osi_free(fixed_queue_dequeue(slot->tx.queue, FIXED_QUEUE_MAX_TIMEOUT)); - if (fixed_queue_length(slot->tx.queue) <= SLOT_TX_QUEUE_LOW_WM) { - xEventGroupSetBits(spp_local_param.tx_event_group, SLOT_WRITE_BIT(serial)); - } + vRingbufferReturnItem(slot->ringbuf_write,slot->write_data); + slot->write_data = NULL; + slot->is_writing = false; + slot->write_data_len = 0; + vRingbufferGetInfo(slot->ringbuf_write, NULL, NULL, NULL, NULL, &items_waiting); + if (BTC_SPP_SEND_BUF_DEFAULT > items_waiting) { + xEventGroupSetBits(spp_local_param.tx_event_group, SLOT_WRITE_BIT(serial)); } - - if ((p_buf = fixed_queue_try_peek_first(slot->tx.queue)) != NULL && p_buf->layer_specific == 0 && - !p_data->rfc_write.cong) { - p_buf->layer_specific = 1; - p_buf->event++; - BTA_JvRfcommWrite(p_data->rfc_write.handle, slot->id, p_buf->len, p_buf->data + p_buf->offset); + if (items_waiting == 0) { + osi_mutex_unlock(&spp_local_param.spp_slot_mutex); + break; + } + if (!p_data->rfc_write.cong) { + uint8_t *data = xRingbufferReceiveUpTo(slot->ringbuf_write, &item_size, 0, slot->mtu); + if (item_size > 0) { + slot->write_data = data; + slot->write_data_len = item_size; + slot->is_writing = true; + BTA_JvRfcommWrite(p_data->rfc_write.handle, slot->id, item_size, data); + } } } else { if (!p_data->rfc_write.old_cong) { // PORT_WriteDataCO failed - BTC_TRACE_ERROR("PORT_WriteDataCO failed p_buf:%p, handle:%d\n", p_buf, + BTC_TRACE_ERROR("PORT_WriteDataCO failed p_buf:%p, handle:%d\n", slot->write_data, p_data->rfc_write.handle); } else { // need rewrite - p_buf->layer_specific = 0; + if (!p_data->rfc_write.cong && slot->connected) { + slot->is_writing = true; + BTA_JvRfcommWrite(p_data->rfc_write.handle, slot->id, slot->write_data_len, slot->write_data); + } else { + slot->is_writing = false; + } } } } @@ -1188,12 +1219,19 @@ void btc_spp_cb_handler(btc_msg_t *msg) BTC_TRACE_ERROR("%s unable to find RFCOMM slot, event:%d!", __func__, event); break; } - if (!p_data->rfc_cong.cong) { - BT_HDR *p_buf; - if ((p_buf = fixed_queue_try_peek_first(slot->tx.queue)) != NULL && p_buf->layer_specific == 0) { - p_buf->event++; - p_buf->layer_specific = 1; - BTA_JvRfcommWrite(p_data->rfc_cong.handle, slot->id, p_buf->len, p_buf->data + p_buf->offset); + if (!p_data->rfc_cong.cong && !slot->is_writing) { + if (slot->write_data == NULL && slot->write_data_len == 0) { + size_t item_size = 0; + uint8_t *data = xRingbufferReceiveUpTo(slot->ringbuf_write, &item_size, 0, slot->mtu); + if (item_size > 0) { + slot->write_data = data; + slot->write_data_len = item_size; + slot->is_writing = true; + BTA_JvRfcommWrite(p_data->rfc_cong.handle, slot->id, item_size, data); + } + } else { + slot->is_writing = true; + BTA_JvRfcommWrite(p_data->rfc_cong.handle, slot->id, slot->write_data_len, slot->write_data); } } osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -1378,77 +1416,67 @@ static ssize_t spp_vfs_write(int fd, const void * data, size_t size) serial = slot->serial; osi_mutex_unlock(&spp_local_param.spp_slot_mutex); - ssize_t sent = 0, write_size = 0; - size_t tx_len; - BT_HDR *p_buf = NULL; - bool enqueue_status= false; + ssize_t sent = 0; + size_t items_waiting = 0; + size_t item_size = 0; EventBits_t tx_event_group_val = 0; - while (1) { + BaseType_t done = false; + while (size) { tx_event_group_val = 0; - if (size) { - if (p_buf == NULL) { - write_size = size < slot->mtu ? size : slot->mtu; - if ((p_buf = osi_malloc(sizeof(BT_HDR) + write_size)) == NULL) { - BTC_TRACE_ERROR("%s malloc failed!", __func__); - errno = ENOMEM; - sent = -1; - break; - } - p_buf->offset = 0; - p_buf->len = write_size; - p_buf->event = 0; // indicate the p_buf be sent count - p_buf->layer_specific = 0; // indicate the p_buf whether to be sent, 0 - ready to send; 1 - have sent - memcpy((UINT8 *)(p_buf + 1), data + sent, write_size); - } - } else { - break; - } - osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - if ((slot = spp_local_param.spp_slots[serial]) != NULL) { - tx_len = fixed_queue_length(slot->tx.queue); - enqueue_status = fixed_queue_enqueue(slot->tx.queue, p_buf, 0); - if (!enqueue_status) { - BTC_TRACE_DEBUG("%s tx_len:%d, fd:%d\n", __func__, fixed_queue_length(slot->tx.queue), fd); - osi_mutex_unlock(&spp_local_param.spp_slot_mutex); - //block untill under water level, be closed or time out - tx_event_group_val = - xEventGroupWaitBits(spp_local_param.tx_event_group, SLOT_WRITE_BIT(serial) | SLOT_CLOSE_BIT(serial), pdTRUE, - pdFALSE, VFS_WRITE_TIMEOUT / portTICK_PERIOD_MS); - if (tx_event_group_val & SLOT_CLOSE_BIT(serial)) { - BTC_TRACE_ERROR("%s exit for RFCOMM close, fd:%d!", __func__, fd); - errno = EPIPE; - sent = -1; - break; - } else if (tx_event_group_val & SLOT_WRITE_BIT(serial)) { + slot = spp_local_param.spp_slots[serial]; + if (slot && slot->connected) { + items_waiting = 0; + item_size = 0; + vRingbufferGetInfo(slot->ringbuf_write, NULL, NULL, NULL, NULL, &items_waiting); + if (items_waiting < BTC_SPP_SEND_BUF_DEFAULT) { + if ((BTC_SPP_SEND_BUF_DEFAULT - items_waiting) > size) { + item_size = size; + done = xRingbufferSend(slot->ringbuf_write, (void *)data + sent, item_size, 0); + } else { + item_size = BTC_SPP_SEND_BUF_DEFAULT - items_waiting; + done = xRingbufferSend(slot->ringbuf_write, (void *)data + sent, item_size, 0); + } + + if (done) { + sent += item_size; + size -= item_size; + if (slot->write_data == NULL) { + spp_send_data_to_btc(slot->rfc_handle, 0, NULL, ESP_SPP_MODE_VFS); + } + osi_mutex_unlock(&spp_local_param.spp_slot_mutex); continue; - } else if (tx_event_group_val == 0) { - BTC_TRACE_ERROR("%s exit for time out, fd:%d!", __func__, fd); - errno = EBUSY; - sent = -1; - break; } } - if (tx_len == 0) { - spp_send_data_to_btc(slot->rfc_handle, 0, NULL, ESP_SPP_MODE_VFS); + + BTC_TRACE_DEBUG("%s items_waiting:%d, fd:%d\n", __func__, items_waiting, fd); + osi_mutex_unlock(&spp_local_param.spp_slot_mutex); + + // block untill under water level, be closed or time out + tx_event_group_val = + xEventGroupWaitBits(spp_local_param.tx_event_group, SLOT_WRITE_BIT(serial) | SLOT_CLOSE_BIT(serial), pdTRUE, + pdFALSE, VFS_WRITE_TIMEOUT / portTICK_PERIOD_MS); + if (tx_event_group_val & SLOT_CLOSE_BIT(serial)) { + BTC_TRACE_ERROR("%s exit for RFCOMM close, fd:%d!", __func__, fd); + errno = EPIPE; + sent = -1; + break; + } else if (tx_event_group_val & SLOT_WRITE_BIT(serial)) { + continue; + } else if (tx_event_group_val == 0) { + BTC_TRACE_ERROR("%s exit for time out, fd:%d!", __func__, fd); + errno = EBUSY; + sent = -1; + break; } - sent += write_size; - size -= write_size; - p_buf = NULL; } else { osi_mutex_unlock(&spp_local_param.spp_slot_mutex); errno = EPIPE; sent = -1; break; } - osi_mutex_unlock(&spp_local_param.spp_slot_mutex); } - //errors occur, need to cleanup - if (p_buf) { - osi_free(p_buf); - p_buf = NULL; - } return sent; } diff --git a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h index 4362cd10fd..7a017f8cc8 100644 --- a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h +++ b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h @@ -296,6 +296,12 @@ #define UC_BT_HFP_WBS_ENABLE FALSE #endif +#ifdef CONFIG_BT_SPP_SEND_BUF_DEFAULT +#define UC_BT_SPP_SEND_BUF_DEFAULT CONFIG_BT_SPP_SEND_BUF_DEFAULT +#else +#define UC_BT_SPP_SEND_BUF_DEFAULT 0 +#endif + /********************************************************** * Memory reference **********************************************************/ diff --git a/components/bt/host/bluedroid/common/include/common/bt_target.h b/components/bt/host/bluedroid/common/include/common/bt_target.h index 22de4d6c7b..66a0e08181 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -351,6 +351,10 @@ #define SBC_ENC_INCLUDED FALSE #endif +#ifndef BTC_SPP_SEND_BUF_DEFAULT +#define BTC_SPP_SEND_BUF_DEFAULT UC_BT_SPP_SEND_BUF_DEFAULT +#endif + /****************************************************************************** ** ** BTA-layer components From 6d57e7878d6bdc277107d1029664a00bbc2e837c Mon Sep 17 00:00:00 2001 From: xiongweichao Date: Tue, 27 Sep 2022 16:25:50 +0800 Subject: [PATCH 4/6] bt: Keep the maximum number of credits unchanged --- .../bluedroid/bta/include/bta/bta_jv_api.h | 1 + .../bluedroid/btc/profile/std/spp/btc_spp.c | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h index f7293f88e6..42c4f35e44 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h @@ -53,6 +53,7 @@ typedef UINT8 tBTA_JV_STATUS; #define BTA_JV_MAX_L2C_CONN GAP_MAX_CONNECTIONS /* GAP handle is used as index, hence do not change this value */ #define BTA_JV_MAX_SCN PORT_MAX_RFC_PORTS /* same as BTM_MAX_SCN (in btm_int.h) */ #define BTA_JV_MAX_RFC_CONN MAX_RFC_PORTS +#define BTA_JV_MAX_CREDIT_NUM PORT_RX_BUF_HIGH_WM #ifndef BTA_JV_DEF_RFC_MTU #define BTA_JV_DEF_RFC_MTU (3*330) diff --git a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c index 44dd4ed664..ea36e9895e 100644 --- a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c @@ -54,6 +54,7 @@ typedef struct { uint8_t scn; uint8_t max_session; uint16_t mtu; + uint16_t credit_rx; uint16_t write_data_len; uint32_t id; uint32_t sdp_handle; @@ -139,6 +140,7 @@ static spp_slot_t *spp_malloc_slot(void) (*slot)->connected = false; (*slot)->is_server = false; (*slot)->mtu = 0; + (*slot)->credit_rx = BTA_JV_MAX_CREDIT_NUM; (*slot)->write_data = NULL; (*slot)->write_data_len = 0; (*slot)->is_writing = false; @@ -1277,6 +1279,9 @@ void btc_spp_cb_handler(btc_msg_t *msg) } } if (count != 0) { + osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); + slot->credit_rx += count; + osi_mutex_unlock(&spp_local_param.spp_slot_mutex); BTA_JvRfcommFlowControl(p_data->data_ind.handle, count); BTC_TRACE_DEBUG("%s give credits:%d\n", __func__, count); } @@ -1342,16 +1347,17 @@ int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf) BTC_TRACE_DEBUG("%s data post! %d, %d", __func__, slot->rfc_handle, rx_len); status = btc_transfer_context(&msg, &p_data, sizeof(tBTA_JV), NULL); assert(status == BT_STATUS_SUCCESS); - } else if (fixed_queue_length(slot->rx.queue) > 2) { - BTC_TRACE_DEBUG("%s data post stop! %d %d", __func__, slot->rfc_handle, fixed_queue_length(slot->rx.queue)); - ret = 0; // reserved for other flow control } } else { fixed_queue_enqueue(slot->rx.queue, p_buf, FIXED_QUEUE_MAX_TIMEOUT); - if (fixed_queue_length(slot->rx.queue) > 2) { - BTC_TRACE_DEBUG("%s data post stop! %d %d", __func__, slot->rfc_handle, fixed_queue_length(slot->rx.queue)); - ret = 0; // reserved for other flow control - } + } + if (--slot->credit_rx == 0) { + BTC_TRACE_DEBUG("%s data post stop! %d %d", __func__, slot->rfc_handle, fixed_queue_length(slot->rx.queue)); + ret = 0; // reserved for other flow control + } + if (slot->credit_rx > BTA_JV_MAX_CREDIT_NUM) { + BTC_TRACE_WARNING("%s credit %d", __func__, slot->credit_rx); + assert(0); } osi_mutex_unlock(&spp_local_param.spp_slot_mutex); return ret; @@ -1580,6 +1586,7 @@ static ssize_t spp_vfs_read(int fd, void * dst, size_t size) } if (count > 0) { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); + slot->credit_rx += count; if ((slot = spp_local_param.spp_slots[serial]) != NULL) { BTA_JvRfcommFlowControl(slot->rfc_handle, count); BTC_TRACE_DEBUG("%s give credits:%d\n", __func__, count); From c2c9b090c722a00c86e44bcf485c1d0b019f3566 Mon Sep 17 00:00:00 2001 From: xiongweichao Date: Mon, 21 Nov 2022 19:15:37 +0800 Subject: [PATCH 5/6] bt: Added esp_spp_enhance_init() API to indicate whether to enable L2CAP ERTM --- .../bt/host/bluedroid/api/esp_spp_api.c | 14 +++- .../bluedroid/api/include/api/esp_spp_api.h | 76 ++++++++++++++----- .../bluedroid/bta/include/bta/bta_jv_api.h | 13 ++++ .../bt/host/bluedroid/bta/jv/bta_jv_act.c | 16 ++++ .../bt/host/bluedroid/bta/jv/bta_jv_api.c | 27 +++++++ .../bt/host/bluedroid/bta/jv/bta_jv_main.c | 3 +- .../bluedroid/bta/jv/include/bta_jv_int.h | 11 ++- .../btc/profile/std/include/btc_spp.h | 1 + .../bluedroid/btc/profile/std/spp/btc_spp.c | 1 + .../bluedroid/stack/include/stack/port_api.h | 11 +++ .../bluedroid/stack/rfcomm/include/port_int.h | 1 + .../bt/host/bluedroid/stack/rfcomm/port_api.c | 14 ++++ .../bluedroid/stack/rfcomm/rfc_l2cap_if.c | 9 +-- .../host/bluedroid/stack/rfcomm/rfc_mx_fsm.c | 25 ++++-- .../host/bluedroid/stack/rfcomm/rfc_utils.c | 3 +- .../classic_bt/bt_spp_acceptor/main/main.c | 9 ++- .../classic_bt/bt_spp_initiator/main/main.c | 9 ++- .../bt_spp_vfs_acceptor/main/main.c | 7 +- .../bt_spp_vfs_initiator/main/main.c | 8 +- 19 files changed, 208 insertions(+), 50 deletions(-) diff --git a/components/bt/host/bluedroid/api/esp_spp_api.c b/components/bt/host/bluedroid/api/esp_spp_api.c index 75f60900e8..1a0cf30165 100644 --- a/components/bt/host/bluedroid/api/esp_spp_api.c +++ b/components/bt/host/bluedroid/api/esp_spp_api.c @@ -34,6 +34,16 @@ esp_err_t esp_spp_register_callback(esp_spp_cb_t callback) esp_err_t esp_spp_init(esp_spp_mode_t mode) +{ + esp_spp_cfg_t bt_spp_cfg = { + .mode = mode, + .enable_l2cap_ertm = true, + }; + + return esp_spp_enhanced_init(&bt_spp_cfg); +} + +esp_err_t esp_spp_enhanced_init(const esp_spp_cfg_t *cfg) { btc_msg_t msg; btc_spp_args_t arg; @@ -43,7 +53,9 @@ esp_err_t esp_spp_init(esp_spp_mode_t mode) msg.pid = BTC_PID_SPP; msg.act = BTC_SPP_ACT_INIT; - arg.init.mode = mode; + arg.init.mode = cfg->mode; + arg.init.enable_l2cap_ertm = cfg->enable_l2cap_ertm; + return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } diff --git a/components/bt/host/bluedroid/api/include/api/esp_spp_api.h b/components/bt/host/bluedroid/api/include/api/esp_spp_api.h index 67cbe969c2..7bf0555fdf 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_spp_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_spp_api.h @@ -14,17 +14,16 @@ extern "C" { #endif -typedef enum { - ESP_SPP_SUCCESS = 0, /*!< Successful operation. */ - ESP_SPP_FAILURE, /*!< Generic failure. */ - ESP_SPP_BUSY, /*!< Temporarily can not handle this request. */ - ESP_SPP_NO_DATA, /*!< No data */ - ESP_SPP_NO_RESOURCE, /*!< No more resource */ - ESP_SPP_NEED_INIT, /*!< SPP module shall init first */ - ESP_SPP_NEED_DEINIT, /*!< SPP module shall deinit first */ - ESP_SPP_NO_CONNECTION, /*!< Connection may have been closed */ - ESP_SPP_NO_SERVER, /*!< No SPP server */ -} esp_spp_status_t; +#define ESP_SPP_MAX_MTU (3*330) /*!< SPP max MTU */ +#define ESP_SPP_MAX_SCN 31 /*!< SPP max SCN */ + +/** + * @brief SPP default configuration + */ +#define BT_SPP_DEFAULT_CONFIG() { \ + .mode = ESP_SPP_MODE_VFS, \ + .enable_l2cap_ertm = true, \ +} /* Security Setting Mask Use these three mask mode: @@ -41,6 +40,18 @@ Use these three mask mode: #define ESP_SPP_SEC_IN_16_DIGITS 0x4000 /*!< Min 16 digit for pin code relate to BTA_SEC_IN_16_DIGITS in bta/bta_api.h*/ typedef uint16_t esp_spp_sec_t; +typedef enum { + ESP_SPP_SUCCESS = 0, /*!< Successful operation. */ + ESP_SPP_FAILURE, /*!< Generic failure. */ + ESP_SPP_BUSY, /*!< Temporarily can not handle this request. */ + ESP_SPP_NO_DATA, /*!< No data */ + ESP_SPP_NO_RESOURCE, /*!< No more resource */ + ESP_SPP_NEED_INIT, /*!< SPP module shall init first */ + ESP_SPP_NEED_DEINIT, /*!< SPP module shall deinit first */ + ESP_SPP_NO_CONNECTION, /*!< Connection may have been closed */ + ESP_SPP_NO_SERVER, /*!< No SPP server */ +} esp_spp_status_t; + typedef enum { ESP_SPP_ROLE_MASTER = 0, /*!< Role: master */ ESP_SPP_ROLE_SLAVE = 1, /*!< Role: slave */ @@ -51,8 +62,14 @@ typedef enum { ESP_SPP_MODE_VFS = 1, /*!< Use VFS to write/read data */ } esp_spp_mode_t; -#define ESP_SPP_MAX_MTU (3*330) /*!< SPP max MTU */ -#define ESP_SPP_MAX_SCN 31 /*!< SPP max SCN */ +/** + * @brief SPP configuration parameters + */ +typedef struct { + esp_spp_mode_t mode; /*!< Choose the mode of SPP, ESP_SPP_MODE_CB or ESP_SPP_MODE_VFS. */ + bool enable_l2cap_ertm; /*!< Enable/disable Logical Link Control and Adaptation Layer Protocol enhanced retransmission mode. */ +} esp_spp_cfg_t; + /** * @brief SPP callback function events */ @@ -221,14 +238,31 @@ esp_err_t esp_spp_register_callback(esp_spp_cb_t callback); * - ESP_OK: success * - other: failed */ -esp_err_t esp_spp_init(esp_spp_mode_t mode); +esp_err_t esp_spp_init(esp_spp_mode_t mode) __attribute__((deprecated("Please use esp_spp_enhanced_init"))); + + +/** + * @brief This function is called to init SPP module. + * When the operation is completed, the callback function will be called with ESP_SPP_INIT_EVT. + * This function should be called after esp_bluedroid_enable() completes successfully. + * + * @param[in] cfg: SPP configuration. + * + * @note The member variable enable_l2cap_etrm in esp_spp_cfg_t can affect all L2CAP channel + * configurations of the upper layer RFCOMM protocol. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_spp_enhanced_init(const esp_spp_cfg_t *cfg); /** * @brief This function is called to uninit SPP module. * The operation will close all active SPP connection first, then the callback function will be called * with ESP_SPP_CLOSE_EVT, and the number of ESP_SPP_CLOSE_EVT is equal to the number of connection. * When the operation is completed, the callback function will be called with ESP_SPP_UNINIT_EVT. - * This function should be called after esp_spp_init() completes successfully. + * This function should be called after esp_spp_init()/esp_spp_enhanced_init() completes successfully. * * @return * - ESP_OK: success @@ -240,7 +274,7 @@ esp_err_t esp_spp_deinit(void); /** * @brief This function is called to performs service discovery for the services provided by the given peer device. * When the operation is completed, the callback function will be called with ESP_SPP_DISCOVERY_COMP_EVT. - * This function must be called after esp_spp_init() successful and before esp_spp_deinit(). + * This function must be called after esp_spp_init()/esp_spp_enhanced_init() successful and before esp_spp_deinit(). * * @param[in] bd_addr: Remote device bluetooth device address. * @@ -254,7 +288,7 @@ esp_err_t esp_spp_start_discovery(esp_bd_addr_t bd_addr); * @brief This function makes an SPP connection to a remote BD Address. * When the connection is initiated or failed to initiate, the callback is called with ESP_SPP_CL_INIT_EVT. * When the connection is established or failed, the callback is called with ESP_SPP_OPEN_EVT. - * This function must be called after esp_spp_init() successful and before esp_spp_deinit(). + * This function must be called after esp_spp_init()/esp_spp_enhanced_init() successful and before esp_spp_deinit(). * * @param[in] sec_mask: Security Setting Mask. Suggest to use ESP_SPP_SEC_NONE, ESP_SPP_SEC_AUTHORIZE or ESP_SPP_SEC_AUTHENTICATE only. * @param[in] role: Master or slave. @@ -270,7 +304,7 @@ esp_err_t esp_spp_connect(esp_spp_sec_t sec_mask, esp_spp_role_t role, uint8_t r /** * @brief This function closes an SPP connection. * When the operation is completed, the callback function will be called with ESP_SPP_CLOSE_EVT. - * This function must be called after esp_spp_init() successful and before esp_spp_deinit(). + * This function must be called after esp_spp_init()/esp_spp_enhanced_init() successful and before esp_spp_deinit(). * * @param[in] handle: The connection handle. * @@ -285,7 +319,7 @@ esp_err_t esp_spp_disconnect(uint32_t handle); * SPP connection request from a remote Bluetooth device. * When the server is started successfully, the callback is called with ESP_SPP_START_EVT. * When the connection is established, the callback is called with ESP_SPP_SRV_OPEN_EVT. - * This function must be called after esp_spp_init() successful and before esp_spp_deinit(). + * This function must be called after esp_spp_init()/esp_spp_enhanced_init() successful and before esp_spp_deinit(). * * @param[in] sec_mask: Security Setting Mask. Suggest to use ESP_SPP_SEC_NONE, ESP_SPP_SEC_AUTHORIZE or ESP_SPP_SEC_AUTHENTICATE only. * @param[in] role: Master or slave. @@ -304,7 +338,7 @@ esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask, esp_spp_role_t role, uint8_t * The operation will close all active SPP connection first, then the callback function will be called * with ESP_SPP_CLOSE_EVT, and the number of ESP_SPP_CLOSE_EVT is equal to the number of connection. * When the operation is completed, the callback is called with ESP_SPP_SRV_STOP_EVT. - * This function must be called after esp_spp_init() successful and before esp_spp_deinit(). + * This function must be called after esp_spp_init()/esp_spp_enhanced_init() successful and before esp_spp_deinit(). * * @return * - ESP_OK: success @@ -318,7 +352,7 @@ esp_err_t esp_spp_stop_srv(void); * The operation will close all active SPP connection first on the specific SPP server, then the callback function will be called * with ESP_SPP_CLOSE_EVT, and the number of ESP_SPP_CLOSE_EVT is equal to the number of connection. * When the operation is completed, the callback is called with ESP_SPP_SRV_STOP_EVT. - * This function must be called after esp_spp_init() successful and before esp_spp_deinit(). + * This function must be called after esp_spp_init()/esp_spp_enhanced_init() successful and before esp_spp_deinit(). * * @param[in] scn: Server channel number. * diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h index 42c4f35e44..241c97a86e 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_jv_api.h @@ -805,6 +805,19 @@ extern tBTA_JV_STATUS BTA_JvL2capWriteFixed(UINT16 channel, BD_ADDR *addr, UINT3 #endif /* BTA_JV_L2CAP_INCLUDED */ #if BTA_JV_RFCOMM_INCLUDED +/******************************************************************************* +** +** Function BTA_JvRfcommConfig +** +** Description This function is to configure RFCOMM. +** +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +extern tBTA_JV_STATUS BTA_JvRfcommConfig(BOOLEAN enable_l2cap_ertm); + /******************************************************************************* ** ** Function BTA_JvRfcommConnect diff --git a/components/bt/host/bluedroid/bta/jv/bta_jv_act.c b/components/bt/host/bluedroid/bta/jv/bta_jv_act.c index da3a1225f5..a739e7fce9 100644 --- a/components/bt/host/bluedroid/bta/jv/bta_jv_act.c +++ b/components/bt/host/bluedroid/bta/jv/bta_jv_act.c @@ -1764,6 +1764,22 @@ static void bta_jv_port_event_cl_cback(UINT32 code, UINT16 port_handle) } } +/******************************************************************************* +** +** Function bta_jv_rfcomm_config +** +** Description Configure RFCOMM +** +** Returns void +** +*******************************************************************************/ +void bta_jv_rfcomm_config(tBTA_JV_MSG *p_data) +{ + APPL_TRACE_DEBUG("%s enable_l2cap_ertm:%d", __func__, p_data->rfcomm_config.enable_l2cap_ertm); + + PORT_SetL2capErtm(p_data->rfcomm_config.enable_l2cap_ertm); +} + /******************************************************************************* ** ** Function bta_jv_rfcomm_connect diff --git a/components/bt/host/bluedroid/bta/jv/bta_jv_api.c b/components/bt/host/bluedroid/bta/jv/bta_jv_api.c index dc060fcb6e..7ca6f7d567 100644 --- a/components/bt/host/bluedroid/bta/jv/bta_jv_api.c +++ b/components/bt/host/bluedroid/bta/jv/bta_jv_api.c @@ -862,6 +862,33 @@ tBTA_JV_STATUS BTA_JvL2capWriteFixed(UINT16 channel, BD_ADDR *addr, UINT32 req_i #endif /* BTA_JV_L2CAP_INCLUDED */ #if BTA_JV_RFCOMM_INCLUDED +/******************************************************************************* +** +** Function BTA_JvRfcommConfig +** +** Description This function is to configure RFCOMM. +** +** Returns BTA_JV_SUCCESS, if the request is being processed. +** BTA_JV_FAILURE, otherwise. +** +*******************************************************************************/ +tBTA_JV_STATUS BTA_JvRfcommConfig(BOOLEAN enable_l2cap_ertm) +{ + tBTA_JV_STATUS status = BTA_JV_FAILURE; + tBTA_JV_API_RFCOMM_CONFIG *p_msg; + + APPL_TRACE_API( "%s", __func__); + + if ((p_msg = (tBTA_JV_API_RFCOMM_CONFIG *)osi_malloc(sizeof(tBTA_JV_API_RFCOMM_CONFIG))) != NULL) { + p_msg->hdr.event = BTA_JV_API_RFCOMM_CONFIG_EVT; + p_msg->enable_l2cap_ertm = enable_l2cap_ertm; + bta_sys_sendmsg(p_msg); + status = BTA_JV_SUCCESS; + } + + return (status); +} + /******************************************************************************* ** ** Function BTA_JvRfcommConnect diff --git a/components/bt/host/bluedroid/bta/jv/bta_jv_main.c b/components/bt/host/bluedroid/bta/jv/bta_jv_main.c index a71d884b92..f233e93350 100644 --- a/components/bt/host/bluedroid/bta/jv/bta_jv_main.c +++ b/components/bt/host/bluedroid/bta/jv/bta_jv_main.c @@ -63,6 +63,7 @@ const tBTA_JV_ACTION bta_jv_action[] = { bta_jv_l2cap_write, /* BTA_JV_API_L2CAP_WRITE_EVT */ #endif /* BTA_JV_L2CAP_INCLUDED */ #if BTA_JV_RFCOMM_INCLUDED + bta_jv_rfcomm_config, /* BTA_JV_API_RFCOMM_CONFIG_EVT */ bta_jv_rfcomm_connect, /* BTA_JV_API_RFCOMM_CONNECT_EVT */ bta_jv_rfcomm_close, /* BTA_JV_API_RFCOMM_CLOSE_EVT */ bta_jv_rfcomm_start_server, /* BTA_JV_API_RFCOMM_START_SERVER_EVT */ @@ -70,7 +71,7 @@ const tBTA_JV_ACTION bta_jv_action[] = { bta_jv_rfcomm_read, /* BTA_JV_API_RFCOMM_READ_EVT */ bta_jv_rfcomm_write, /* BTA_JV_API_RFCOMM_WRITE_EVT */ bta_jv_rfcomm_flow_control, /* BTA_JV_API_RFCOMM_FLOW_CONTROL_EVT */ - #endif /* BTA_JV_RFCOMM_INCLUDED */ +#endif /* BTA_JV_RFCOMM_INCLUDED */ bta_jv_set_pm_profile, /* BTA_JV_API_SET_PM_PROFILE_EVT */ bta_jv_change_pm_state, /* BTA_JV_API_PM_STATE_CHANGE_EVT */ #if BTA_JV_L2CAP_INCLUDED diff --git a/components/bt/host/bluedroid/bta/jv/include/bta_jv_int.h b/components/bt/host/bluedroid/bta/jv/include/bta_jv_int.h index 320e1a8608..af1e3699d3 100644 --- a/components/bt/host/bluedroid/bta/jv/include/bta_jv_int.h +++ b/components/bt/host/bluedroid/bta/jv/include/bta_jv_int.h @@ -57,6 +57,7 @@ enum { BTA_JV_API_L2CAP_WRITE_EVT, #endif /* BTA_JV_L2CAP_INCLUDED */ #if BTA_JV_RFCOMM_INCLUDED + BTA_JV_API_RFCOMM_CONFIG_EVT, BTA_JV_API_RFCOMM_CONNECT_EVT, BTA_JV_API_RFCOMM_CLOSE_EVT, BTA_JV_API_RFCOMM_START_SERVER_EVT, @@ -83,7 +84,7 @@ enum { /* data type for BTA_JV_API_ENABLE_EVT */ typedef struct { - BT_HDR hdr; + BT_HDR hdr; tBTA_JV_DM_CBACK *p_cback; } tBTA_JV_API_ENABLE; @@ -257,6 +258,12 @@ typedef struct { #endif /* BTA_JV_L2CAP_INCLUDED */ #if BTA_JV_RFCOMM_INCLUDED +/* data type for BTA_JV_API_RFCOMM_CONFIG_EVT */ +typedef struct { + BT_HDR hdr; + BOOLEAN enable_l2cap_ertm; +} tBTA_JV_API_RFCOMM_CONFIG; + /* data type for BTA_JV_API_RFCOMM_CONNECT_EVT */ typedef struct { BT_HDR hdr; @@ -392,6 +399,7 @@ typedef union { tBTA_JV_API_L2CAP_WRITE_FIXED l2cap_write_fixed; #endif /* BTA_JV_L2CAP_INCLUDED */ #if BTA_JV_RFCOMM_INCLUDED + tBTA_JV_API_RFCOMM_CONFIG rfcomm_config; tBTA_JV_API_RFCOMM_CONNECT rfcomm_connect; tBTA_JV_API_RFCOMM_READ rfcomm_read; tBTA_JV_API_RFCOMM_WRITE rfcomm_write; @@ -463,6 +471,7 @@ extern void bta_jv_l2cap_read (tBTA_JV_MSG *p_data); extern void bta_jv_l2cap_write (tBTA_JV_MSG *p_data); #endif /* BTA_JV_L2CAP_INCLUDED */ #if BTA_JV_RFCOMM_INCLUDED +extern void bta_jv_rfcomm_config (tBTA_JV_MSG *p_data); extern void bta_jv_rfcomm_connect (tBTA_JV_MSG *p_data); extern void bta_jv_rfcomm_close (tBTA_JV_MSG *p_data); extern void bta_jv_rfcomm_start_server (tBTA_JV_MSG *p_data); diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_spp.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_spp.h index 7f0f9e81b4..f9c59fa1b2 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_spp.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_spp.h @@ -36,6 +36,7 @@ typedef union { //BTC_SPP_ACT_INIT struct init_arg { esp_spp_mode_t mode; + bool enable_l2cap_ertm; } init; //BTC_SPP_ACT_UNINIT struct uninit_arg { diff --git a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c index ea36e9895e..d478ab6832 100644 --- a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c @@ -548,6 +548,7 @@ static void btc_spp_init(btc_spp_args_t *arg) spp_local_param.spp_mode = arg->init.mode; spp_local_param.spp_slot_id = 0; BTA_JvEnable((tBTA_JV_DM_CBACK *)btc_spp_dm_inter_cb); + BTA_JvRfcommConfig(arg->init.enable_l2cap_ertm); } while (0); if (ret != ESP_SPP_SUCCESS) { diff --git a/components/bt/host/bluedroid/stack/include/stack/port_api.h b/components/bt/host/bluedroid/stack/include/stack/port_api.h index 928f8eb962..599cfaa3d4 100644 --- a/components/bt/host/bluedroid/stack/include/stack/port_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/port_api.h @@ -692,6 +692,17 @@ extern UINT8 PORT_SetTraceLevel (UINT8 new_level); *******************************************************************************/ extern const char *PORT_GetResultString (const uint8_t result_code); +/******************************************************************************* +** +** Function PORT_SetL2capErtm +** +** Description This function sets whether RFCOMM uses L2CAP ERTM. +** +** Returns void +** +*******************************************************************************/ +extern void PORT_SetL2capErtm (BOOLEAN enable_l2cap_ertm); + #ifdef __cplusplus } #endif diff --git a/components/bt/host/bluedroid/stack/rfcomm/include/port_int.h b/components/bt/host/bluedroid/stack/rfcomm/include/port_int.h index 5961811698..8ceb14423b 100644 --- a/components/bt/host/bluedroid/stack/rfcomm/include/port_int.h +++ b/components/bt/host/bluedroid/stack/rfcomm/include/port_int.h @@ -209,6 +209,7 @@ typedef struct t_port_info tPORT; typedef struct { tPORT port[MAX_RFC_PORTS]; /* Port info pool */ tRFC_MCB rfc_mcb[MAX_BD_CONNECTIONS]; /* RFCOMM bd_connections pool */ + BOOLEAN enable_l2cap_ertm; /* enable/disable l2cap ertm */ } tPORT_CB; #ifdef __cplusplus diff --git a/components/bt/host/bluedroid/stack/rfcomm/port_api.c b/components/bt/host/bluedroid/stack/rfcomm/port_api.c index 4e1baf52a0..1aa38ff77c 100644 --- a/components/bt/host/bluedroid/stack/rfcomm/port_api.c +++ b/components/bt/host/bluedroid/stack/rfcomm/port_api.c @@ -1866,4 +1866,18 @@ const char *PORT_GetResultString (const uint8_t result_code) return result_code_strings[result_code]; } +/******************************************************************************* +** +** Function PORT_SetL2capErtm +** +** Description This function sets whether RFCOMM uses L2CAP ERTM. +** +** Returns void +** +*******************************************************************************/ +void PORT_SetL2capErtm (BOOLEAN enable_l2cap_ertm) +{ + rfc_cb.port.enable_l2cap_ertm = enable_l2cap_ertm; +} + #endif ///(defined RFCOMM_INCLUDED && RFCOMM_INCLUDED == TRUE) diff --git a/components/bt/host/bluedroid/stack/rfcomm/rfc_l2cap_if.c b/components/bt/host/bluedroid/stack/rfcomm/rfc_l2cap_if.c index a30bf25cf4..aa28da9d1b 100644 --- a/components/bt/host/bluedroid/stack/rfcomm/rfc_l2cap_if.c +++ b/components/bt/host/bluedroid/stack/rfcomm/rfc_l2cap_if.c @@ -128,8 +128,8 @@ void RFCOMM_ConnectInd (BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id) } if (p_mcb == NULL) { - // L2CA_ConnectRsp (bd_addr, id, lcid, L2CAP_CONN_NO_RESOURCES, 0); - L2CA_ErtmConnectRsp (bd_addr, id, lcid, L2CAP_CONN_NO_RESOURCES, 0, &rfc_l2c_etm_opt); + tL2CAP_ERTM_INFO *ertm_opt = rfc_cb.port.enable_l2cap_ertm ? &rfc_l2c_etm_opt : NULL; + L2CA_ErtmConnectRsp (bd_addr, id, lcid, L2CAP_CONN_NO_RESOURCES, 0, ertm_opt); return; } p_mcb->lcid = lcid; @@ -189,10 +189,9 @@ void RFCOMM_ConnectCnf (UINT16 lcid, UINT16 result) } else { RFCOMM_TRACE_DEBUG ("RFCOMM_ConnectCnf peer gave up pending LCID(0x%x)", p_mcb->pending_lcid); + tL2CAP_ERTM_INFO *ertm_opt = rfc_cb.port.enable_l2cap_ertm ? &rfc_l2c_etm_opt : NULL; /* Peer gave up his connection request, make sure cleaning up L2CAP channel */ - // L2CA_ConnectRsp (p_mcb->bd_addr, p_mcb->pending_id, p_mcb->pending_lcid, L2CAP_CONN_NO_RESOURCES, 0); - L2CA_ErtmConnectRsp (p_mcb->bd_addr, p_mcb->pending_id, p_mcb->pending_lcid, L2CAP_CONN_NO_RESOURCES, 0, - &rfc_l2c_etm_opt); + L2CA_ErtmConnectRsp (p_mcb->bd_addr, p_mcb->pending_id, p_mcb->pending_lcid, L2CAP_CONN_NO_RESOURCES, 0, ertm_opt); p_mcb->pending_lcid = 0; } diff --git a/components/bt/host/bluedroid/stack/rfcomm/rfc_mx_fsm.c b/components/bt/host/bluedroid/stack/rfcomm/rfc_mx_fsm.c index 8dc4d1af11..d3986813c3 100644 --- a/components/bt/host/bluedroid/stack/rfcomm/rfc_mx_fsm.c +++ b/components/bt/host/bluedroid/stack/rfcomm/rfc_mx_fsm.c @@ -136,15 +136,20 @@ void rfc_mx_sm_execute (tRFC_MCB *p_mcb, UINT16 event, void *p_data) *******************************************************************************/ void rfc_mx_sm_state_idle (tRFC_MCB *p_mcb, UINT16 event, void *p_data) { + tL2CAP_ERTM_INFO *ertm_opt = NULL; + RFCOMM_TRACE_EVENT ("rfc_mx_sm_state_idle - evt:%d", event); + switch (event) { case RFC_MX_EVENT_START_REQ: /* Initialize L2CAP MTU */ p_mcb->peer_l2cap_mtu = L2CAP_DEFAULT_MTU - RFCOMM_MIN_OFFSET - 1; - // if ((p_mcb->lcid = L2CA_ConnectReq (BT_PSM_RFCOMM, p_mcb->bd_addr)) == 0) { - if ((p_mcb->lcid = L2CA_ErtmConnectReq (BT_PSM_RFCOMM, p_mcb->bd_addr, &rfc_l2c_etm_opt)) == 0) { + ertm_opt = rfc_cb.port.enable_l2cap_ertm ? &rfc_l2c_etm_opt : NULL; + p_mcb->lcid = L2CA_ErtmConnectReq (BT_PSM_RFCOMM, p_mcb->bd_addr, ertm_opt); + + if (p_mcb->lcid == 0) { PORT_StartCnf (p_mcb, RFCOMM_ERROR); return; } @@ -164,8 +169,8 @@ void rfc_mx_sm_state_idle (tRFC_MCB *p_mcb, UINT16 event, void *p_data) case RFC_MX_EVENT_CONN_IND: rfc_timer_start (p_mcb, RFCOMM_CONN_TIMEOUT); - // L2CA_ConnectRsp (p_mcb->bd_addr, *((UINT8 *)p_data), p_mcb->lcid, L2CAP_CONN_OK, 0); - L2CA_ErtmConnectRsp (p_mcb->bd_addr, *((UINT8 *)p_data), p_mcb->lcid, L2CAP_CONN_OK, 0, &rfc_l2c_etm_opt); + ertm_opt = rfc_cb.port.enable_l2cap_ertm ? &rfc_l2c_etm_opt : NULL; + L2CA_ErtmConnectRsp (p_mcb->bd_addr, *((UINT8 *)p_data), p_mcb->lcid, L2CAP_CONN_OK, 0, ertm_opt); rfc_mx_send_config_req (p_mcb); @@ -502,9 +507,11 @@ void rfc_mx_sm_state_disc_wait_ua (tRFC_MCB *p_mcb, UINT16 event, void *p_data) L2CA_DisconnectReq (p_mcb->lcid); if (p_mcb->restart_required) { + tL2CAP_ERTM_INFO *ertm_opt = rfc_cb.port.enable_l2cap_ertm ? &rfc_l2c_etm_opt : NULL; /* Start Request was received while disconnecting. Execute it again */ - // if ((p_mcb->lcid = L2CA_ConnectReq (BT_PSM_RFCOMM, p_mcb->bd_addr)) == 0) { - if ((p_mcb->lcid = L2CA_ErtmConnectReq (BT_PSM_RFCOMM, p_mcb->bd_addr, &rfc_l2c_etm_opt)) == 0) { + p_mcb->lcid = L2CA_ErtmConnectReq(BT_PSM_RFCOMM, p_mcb->bd_addr, ertm_opt); + + if (p_mcb->lcid == 0) { PORT_StartCnf (p_mcb, RFCOMM_ERROR); return; } @@ -576,8 +583,10 @@ static void rfc_mx_send_config_req (tRFC_MCB *p_mcb) cfg.mtu_present = TRUE; cfg.mtu = L2CAP_MTU_SIZE; - cfg.fcr_present = TRUE; - cfg.fcr = rfc_l2c_fcr_opts_def; + if (rfc_cb.port.enable_l2cap_ertm) { + cfg.fcr_present = TRUE; + cfg.fcr = rfc_l2c_fcr_opts_def; + } /* Defaults set by memset cfg.flush_to_present = FALSE; diff --git a/components/bt/host/bluedroid/stack/rfcomm/rfc_utils.c b/components/bt/host/bluedroid/stack/rfcomm/rfc_utils.c index 5ab3ac3e22..b766918d0e 100644 --- a/components/bt/host/bluedroid/stack/rfcomm/rfc_utils.c +++ b/components/bt/host/bluedroid/stack/rfcomm/rfc_utils.c @@ -188,7 +188,8 @@ tRFC_MCB *rfc_alloc_multiplexer_channel (BD_ADDR bd_addr, BOOLEAN is_initiator) return (NULL); } -void osi_free_fun(void *p){ +void osi_free_fun(void *p) +{ osi_free(p); } /******************************************************************************* diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/main/main.c b/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/main/main.c index 93bbb2031f..84bd7b0dae 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -30,6 +30,7 @@ #define SPP_SHOW_MODE SPP_SHOW_SPEED /*Choose show mode: show data or speed*/ static const esp_spp_mode_t esp_spp_mode = ESP_SPP_MODE_CB; +static const bool esp_spp_enable_l2cap_ertm = true; static struct timeval time_new, time_old; static long data_num = 0; @@ -241,7 +242,11 @@ void app_main(void) return; } - if ((ret = esp_spp_init(esp_spp_mode)) != ESP_OK) { + esp_spp_cfg_t bt_spp_cfg = { + .mode = esp_spp_mode, + .enable_l2cap_ertm = esp_spp_enable_l2cap_ertm, + }; + if ((ret = esp_spp_enhanced_init(&bt_spp_cfg)) != ESP_OK) { ESP_LOGE(SPP_TAG, "%s spp init failed: %s\n", __func__, esp_err_to_name(ret)); return; } diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/main/main.c b/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/main/main.c index 665e877d45..fd5a013084 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -31,6 +31,7 @@ #define SPP_SHOW_MODE SPP_SHOW_SPEED /*Choose show mode: show data or speed*/ static const esp_spp_mode_t esp_spp_mode = ESP_SPP_MODE_CB; +static const bool esp_spp_enable_l2cap_ertm = true; static struct timeval time_new, time_old; static long data_num = 0; @@ -384,7 +385,11 @@ void app_main(void) return; } - if ((ret = esp_spp_init(esp_spp_mode)) != ESP_OK) { + esp_spp_cfg_t bt_spp_cfg = { + .mode = esp_spp_mode, + .enable_l2cap_ertm = esp_spp_enable_l2cap_ertm, + }; + if ((ret = esp_spp_enhanced_init(&bt_spp_cfg)) != ESP_OK) { ESP_LOGE(SPP_TAG, "%s spp init failed: %s\n", __func__, esp_err_to_name(ret)); return; } diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/main.c b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/main.c index 8abc839a53..abcdde4d8b 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_acceptor/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -38,8 +38,6 @@ #define SPP_SERVER_NAME "SPP_SERVER" #define EXAMPLE_DEVICE_NAME "ESP_SPP_ACCEPTOR" -static const esp_spp_mode_t esp_spp_mode = ESP_SPP_MODE_VFS; - static const esp_spp_sec_t sec_mask = ESP_SPP_SEC_AUTHENTICATE; static const esp_spp_role_t role_slave = ESP_SPP_ROLE_SLAVE; @@ -250,7 +248,8 @@ void app_main(void) spp_task_task_start_up(); - if (esp_spp_init(esp_spp_mode) != ESP_OK) { + esp_spp_cfg_t bt_spp_cfg = BT_SPP_DEFAULT_CONFIG(); + if (esp_spp_enhanced_init(&bt_spp_cfg) != ESP_OK) { ESP_LOGE(SPP_TAG, "%s spp init failed", __func__); return; } diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/main.c b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/main.c index 17cc07a5ed..dea4c6d2bf 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -37,8 +37,6 @@ #define SPP_TAG "SPP_INITIATOR_DEMO" #define EXAMPLE_DEVICE_NAME "ESP_SPP_INITIATOR" -static const esp_spp_mode_t esp_spp_mode = ESP_SPP_MODE_VFS; - static const esp_spp_sec_t sec_mask = ESP_SPP_SEC_AUTHENTICATE; static const esp_spp_role_t role_master = ESP_SPP_ROLE_MASTER; @@ -332,7 +330,9 @@ void app_main(void) } spp_task_task_start_up(); - if (esp_spp_init(esp_spp_mode) != ESP_OK) { + + esp_spp_cfg_t bt_spp_cfg = BT_SPP_DEFAULT_CONFIG(); + if (esp_spp_enhanced_init(&bt_spp_cfg) != ESP_OK) { ESP_LOGE(SPP_TAG, "%s spp init failed", __func__); return; } From 654e19846420f2d965b47ff8ed4bc1fd34c4a6be Mon Sep 17 00:00:00 2001 From: xiongweichao Date: Thu, 17 Nov 2022 10:46:52 +0800 Subject: [PATCH 6/6] bt: Remove SPP default send buffer size option and add parameters to configure send buffer size in esp_spp_enhance_init() --- components/bt/host/bluedroid/Kconfig.in | 9 --------- components/bt/host/bluedroid/api/esp_spp_api.c | 8 ++++++++ .../bt/host/bluedroid/api/include/api/esp_spp_api.h | 4 ++++ .../host/bluedroid/btc/profile/std/include/btc_spp.h | 1 + .../bt/host/bluedroid/btc/profile/std/spp/btc_spp.c | 12 +++++++----- .../common/include/common/bluedroid_user_config.h | 6 ------ .../host/bluedroid/common/include/common/bt_target.h | 4 ---- .../bluedroid/classic_bt/bt_spp_acceptor/main/main.c | 1 + .../classic_bt/bt_spp_initiator/main/main.c | 1 + 9 files changed, 22 insertions(+), 24 deletions(-) diff --git a/components/bt/host/bluedroid/Kconfig.in b/components/bt/host/bluedroid/Kconfig.in index 1666865f4b..d03f182b11 100644 --- a/components/bt/host/bluedroid/Kconfig.in +++ b/components/bt/host/bluedroid/Kconfig.in @@ -61,15 +61,6 @@ config BT_SPP_ENABLED help This enables the Serial Port Profile -config BT_SPP_SEND_BUF_DEFAULT - int "SPP default send buffer size" - depends on BT_SPP_ENABLED - range 100 10000 - default 4000 - help - Sets the default send buffer size for new SPP channels. Setting a smaller - default SNDBUF size can save some memory, but may decrease performance. - config BT_L2CAP_ENABLED bool "BT L2CAP" depends on BT_CLASSIC_ENABLED diff --git a/components/bt/host/bluedroid/api/esp_spp_api.c b/components/bt/host/bluedroid/api/esp_spp_api.c index 1a0cf30165..34585d0dec 100644 --- a/components/bt/host/bluedroid/api/esp_spp_api.c +++ b/components/bt/host/bluedroid/api/esp_spp_api.c @@ -38,6 +38,7 @@ esp_err_t esp_spp_init(esp_spp_mode_t mode) esp_spp_cfg_t bt_spp_cfg = { .mode = mode, .enable_l2cap_ertm = true, + .tx_buffer_size = ESP_SPP_MAX_TX_BUFFER_SIZE, }; return esp_spp_enhanced_init(&bt_spp_cfg); @@ -49,12 +50,19 @@ esp_err_t esp_spp_enhanced_init(const esp_spp_cfg_t *cfg) btc_spp_args_t arg; ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (cfg->mode == ESP_SPP_MODE_VFS && (cfg->tx_buffer_size < ESP_SPP_MIN_TX_BUFFER_SIZE || + cfg->tx_buffer_size > ESP_SPP_MAX_TX_BUFFER_SIZE)) { + LOG_WARN("Invalid tx buffer size"); + return ESP_ERR_INVALID_ARG; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_SPP; msg.act = BTC_SPP_ACT_INIT; arg.init.mode = cfg->mode; arg.init.enable_l2cap_ertm = cfg->enable_l2cap_ertm; + arg.init.tx_buffer_size = cfg->tx_buffer_size; return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } diff --git a/components/bt/host/bluedroid/api/include/api/esp_spp_api.h b/components/bt/host/bluedroid/api/include/api/esp_spp_api.h index 7bf0555fdf..a874c25c89 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_spp_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_spp_api.h @@ -16,6 +16,8 @@ extern "C" { #define ESP_SPP_MAX_MTU (3*330) /*!< SPP max MTU */ #define ESP_SPP_MAX_SCN 31 /*!< SPP max SCN */ +#define ESP_SPP_MIN_TX_BUFFER_SIZE 100 /*!< SPP min tx buffer */ +#define ESP_SPP_MAX_TX_BUFFER_SIZE (ESP_SPP_MAX_MTU * 10) /*!< SPP max tx buffer size */ /** * @brief SPP default configuration @@ -23,6 +25,7 @@ extern "C" { #define BT_SPP_DEFAULT_CONFIG() { \ .mode = ESP_SPP_MODE_VFS, \ .enable_l2cap_ertm = true, \ + .tx_buffer_size = ESP_SPP_MAX_TX_BUFFER_SIZE, \ } /* Security Setting Mask @@ -68,6 +71,7 @@ typedef enum { typedef struct { esp_spp_mode_t mode; /*!< Choose the mode of SPP, ESP_SPP_MODE_CB or ESP_SPP_MODE_VFS. */ bool enable_l2cap_ertm; /*!< Enable/disable Logical Link Control and Adaptation Layer Protocol enhanced retransmission mode. */ + uint16_t tx_buffer_size; /*!< Tx buffer size for a new SPP channel. A smaller setting can save memory, but may incur a decrease in throughput. Only for ESP_SPP_MODE_VFS mode. */ } esp_spp_cfg_t; /** diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_spp.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_spp.h index f9c59fa1b2..94216a2a16 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_spp.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_spp.h @@ -37,6 +37,7 @@ typedef union { struct init_arg { esp_spp_mode_t mode; bool enable_l2cap_ertm; + UINT16 tx_buffer_size; } init; //BTC_SPP_ACT_UNINIT struct uninit_arg { diff --git a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c index d478ab6832..f5515b8ee0 100644 --- a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c @@ -76,6 +76,7 @@ typedef struct { } spp_slot_t; typedef struct { + uint16_t tx_buffer_size; spp_slot_t *spp_slots[MAX_RFC_PORTS + 1]; uint32_t spp_slot_id; esp_spp_mode_t spp_mode; @@ -162,7 +163,7 @@ static spp_slot_t *spp_malloc_slot(void) goto err; } } else { - if (((*slot)->ringbuf_write = xRingbufferCreate(BTC_SPP_SEND_BUF_DEFAULT, RINGBUF_TYPE_BYTEBUF)) == NULL) { + if (((*slot)->ringbuf_write = xRingbufferCreate(spp_local_param.tx_buffer_size, RINGBUF_TYPE_BYTEBUF)) == NULL) { BTC_TRACE_ERROR("%s write ringbuffer create error!", __func__); err_no = 2; goto err; @@ -547,6 +548,7 @@ static void btc_spp_init(btc_spp_args_t *arg) } spp_local_param.spp_mode = arg->init.mode; spp_local_param.spp_slot_id = 0; + spp_local_param.tx_buffer_size = arg->init.tx_buffer_size; BTA_JvEnable((tBTA_JV_DM_CBACK *)btc_spp_dm_inter_cb); BTA_JvRfcommConfig(arg->init.enable_l2cap_ertm); } while (0); @@ -1102,7 +1104,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) slot->is_writing = false; slot->write_data_len = 0; vRingbufferGetInfo(slot->ringbuf_write, NULL, NULL, NULL, NULL, &items_waiting); - if (BTC_SPP_SEND_BUF_DEFAULT > items_waiting) { + if (spp_local_param.tx_buffer_size > items_waiting) { xEventGroupSetBits(spp_local_param.tx_event_group, SLOT_WRITE_BIT(serial)); } if (items_waiting == 0) { @@ -1436,12 +1438,12 @@ static ssize_t spp_vfs_write(int fd, const void * data, size_t size) items_waiting = 0; item_size = 0; vRingbufferGetInfo(slot->ringbuf_write, NULL, NULL, NULL, NULL, &items_waiting); - if (items_waiting < BTC_SPP_SEND_BUF_DEFAULT) { - if ((BTC_SPP_SEND_BUF_DEFAULT - items_waiting) > size) { + if (items_waiting < spp_local_param.tx_buffer_size) { + if ((spp_local_param.tx_buffer_size - items_waiting) > size) { item_size = size; done = xRingbufferSend(slot->ringbuf_write, (void *)data + sent, item_size, 0); } else { - item_size = BTC_SPP_SEND_BUF_DEFAULT - items_waiting; + item_size = spp_local_param.tx_buffer_size - items_waiting; done = xRingbufferSend(slot->ringbuf_write, (void *)data + sent, item_size, 0); } diff --git a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h index 7a017f8cc8..4362cd10fd 100644 --- a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h +++ b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h @@ -296,12 +296,6 @@ #define UC_BT_HFP_WBS_ENABLE FALSE #endif -#ifdef CONFIG_BT_SPP_SEND_BUF_DEFAULT -#define UC_BT_SPP_SEND_BUF_DEFAULT CONFIG_BT_SPP_SEND_BUF_DEFAULT -#else -#define UC_BT_SPP_SEND_BUF_DEFAULT 0 -#endif - /********************************************************** * Memory reference **********************************************************/ diff --git a/components/bt/host/bluedroid/common/include/common/bt_target.h b/components/bt/host/bluedroid/common/include/common/bt_target.h index 66a0e08181..22de4d6c7b 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -351,10 +351,6 @@ #define SBC_ENC_INCLUDED FALSE #endif -#ifndef BTC_SPP_SEND_BUF_DEFAULT -#define BTC_SPP_SEND_BUF_DEFAULT UC_BT_SPP_SEND_BUF_DEFAULT -#endif - /****************************************************************************** ** ** BTA-layer components diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/main/main.c b/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/main/main.c index 84bd7b0dae..b2fa933601 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/main/main.c @@ -245,6 +245,7 @@ void app_main(void) esp_spp_cfg_t bt_spp_cfg = { .mode = esp_spp_mode, .enable_l2cap_ertm = esp_spp_enable_l2cap_ertm, + .tx_buffer_size = 0, /* Only used for ESP_SPP_MODE_VFS mode */ }; if ((ret = esp_spp_enhanced_init(&bt_spp_cfg)) != ESP_OK) { ESP_LOGE(SPP_TAG, "%s spp init failed: %s\n", __func__, esp_err_to_name(ret)); diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/main/main.c b/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/main/main.c index fd5a013084..c70d4df28a 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/main/main.c @@ -388,6 +388,7 @@ void app_main(void) esp_spp_cfg_t bt_spp_cfg = { .mode = esp_spp_mode, .enable_l2cap_ertm = esp_spp_enable_l2cap_ertm, + .tx_buffer_size = 0, /* Only used for ESP_SPP_MODE_VFS mode */ }; if ((ret = esp_spp_enhanced_init(&bt_spp_cfg)) != ESP_OK) { ESP_LOGE(SPP_TAG, "%s spp init failed: %s\n", __func__, esp_err_to_name(ret));