From 3e17f888c840270472ec618b3c3b27472288669c Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Mon, 6 Oct 2025 01:17:40 +0300 Subject: [PATCH] bthost: handle L2CAP_FLOW_CONTROL_CREDIT_IND Parse L2CAP_FLOW_CONTROL_CREDIT_IND and track credits, instead of sending reject response. Nothing is done with the credit counts currently. --- emulator/bthost.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/emulator/bthost.c b/emulator/bthost.c index 93023331e..b00f8f2b6 100644 --- a/emulator/bthost.c +++ b/emulator/bthost.c @@ -184,6 +184,8 @@ struct l2conn { uint16_t scid; uint16_t dcid; uint16_t psm; + uint16_t rx_credits; + uint16_t tx_credits; enum l2cap_mode mode; uint16_t data_len; uint16_t recv_len; @@ -2459,6 +2461,8 @@ static bool l2cap_le_conn_req(struct bthost *bthost, struct btconn *conn, le16_to_cpu(req->scid), le16_to_cpu(psm)); l2conn->mode = L2CAP_MODE_LE_CRED; + l2conn->rx_credits = le16_to_cpu(rsp.credits); + l2conn->tx_credits = le16_to_cpu(req->credits); if (cb_data && l2conn->psm == cb_data->psm && cb_data->func) cb_data->func(conn->handle, l2conn->dcid, @@ -2476,10 +2480,13 @@ static bool l2cap_le_conn_rsp(struct bthost *bthost, struct btconn *conn, if (len < sizeof(*rsp)) return false; + /* TODO add L2CAP connection before with proper PSM */ l2conn = bthost_add_l2cap_conn(bthost, conn, 0, le16_to_cpu(rsp->dcid), 0); l2conn->mode = L2CAP_MODE_LE_CRED; + l2conn->rx_credits = 1; + l2conn->tx_credits = le16_to_cpu(rsp->credits); return true; } @@ -2544,12 +2551,32 @@ static bool l2cap_ecred_conn_rsp(struct bthost *bthost, struct btconn *conn, l2conn = bthost_add_l2cap_conn(bthost, conn, 0, le16_to_cpu(rsp->scid[i]), 0); l2conn->mode = L2CAP_MODE_LE_ENH_CRED; + l2conn->tx_credits = rsp->pdu->credits; + l2conn->rx_credits = 1; } return true; } +static bool l2cap_le_flowctl_creds(struct bthost *bthost, struct btconn *conn, + uint8_t ident, const void *data, uint16_t len) +{ + const struct bt_l2cap_pdu_le_flowctl_creds *ind = data; + struct l2conn *l2conn; + + if (len < sizeof(*ind)) + return false; + + l2conn = btconn_find_l2cap_conn_by_dcid(conn, ind->cid); + if (!l2conn) + return true; + + l2conn->tx_credits += ind->credits; + + return true; +} + static bool l2cap_le_rsp(uint8_t code) { switch (code) { @@ -2624,6 +2651,11 @@ static void l2cap_le_sig(struct bthost *bthost, struct btconn *conn, data + sizeof(*hdr), hdr_len); break; + case BT_L2CAP_PDU_LE_FLOWCTL_CREDS: + ret = l2cap_le_flowctl_creds(bthost, conn, hdr->ident, + data + sizeof(*hdr), hdr_len); + break; + default: bthost_debug(bthost, "Unknown L2CAP code 0x%02x", hdr->code); ret = false; -- 2.47.3