From ea41a21b0ed65b01a21fe785c28b8bec8df87de7 Mon Sep 17 00:00:00 2001 From: xiongweichao Date: Mon, 19 Sep 2022 20:20:22 +0800 Subject: [PATCH] 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;