diff --git a/apps/bttester/src/bttester.h b/apps/bttester/src/bttester.h index 767d9fffb..641db8bd8 100644 --- a/apps/bttester/src/bttester.h +++ b/apps/bttester/src/bttester.h @@ -755,6 +755,7 @@ struct l2cap_read_supported_commands_rp { } __packed; #define L2CAP_CONNECT_OPT_ECFC 0x01 +#define L2CAP_CONNECT_OPT_HOLD_CREDIT 0x02 #define L2CAP_CONNECT 0x02 struct l2cap_connect_cmd { @@ -809,6 +810,11 @@ struct l2cap_reconfigure_cmd { uint8_t idxs[]; } __packed; +#define L2CAP_CREDITS 0x08 +struct l2cap_credits_cmd { + uint8_t chan_id; +} __packed; + /* events */ #define L2CAP_EV_CONNECTION_REQ 0x80 struct l2cap_connection_req_ev { diff --git a/apps/bttester/src/l2cap.c b/apps/bttester/src/l2cap.c index 41a51d81b..7890e7cce 100644 --- a/apps/bttester/src/l2cap.c +++ b/apps/bttester/src/l2cap.c @@ -48,6 +48,7 @@ static os_membuf_t tester_sdu_coc_mem[ struct os_mbuf_pool sdu_os_mbuf_pool; static struct os_mempool sdu_coc_mbuf_mempool; +static bool hold_credit = false; static struct channel { uint8_t chan_id; /* Internal number that identifies L2CAP channel. */ @@ -105,10 +106,13 @@ tester_l2cap_coc_recv(struct ble_l2cap_chan *chan, struct os_mbuf *sdu) (uint32_t) chan, OS_MBUF_PKTLEN(sdu)); os_mbuf_free_chain(sdu); - sdu = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); - assert(sdu != NULL); + if (!hold_credit) { + sdu = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); + assert(sdu != NULL); - ble_l2cap_recv_ready(chan, sdu); + + ble_l2cap_recv_ready(chan, sdu); + } } static void recv_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan, @@ -398,6 +402,7 @@ static void connect(uint8_t *data, uint16_t len) int rc; int i, j; bool ecfc = cmd->options & L2CAP_CONNECT_OPT_ECFC; + hold_credit = cmd->options & L2CAP_CONNECT_OPT_HOLD_CREDIT; SYS_LOG_DBG("connect: type: %d addr: %s", addr->type, bt_hex(addr->val, 6)); @@ -611,6 +616,35 @@ fail: BTP_STATUS_FAILED); } +static void credits(uint8_t *data, uint16_t len) +{ + const struct l2cap_credits_cmd *cmd = (void *)data; + struct os_mbuf *sdu; + int rc; + + struct channel *channel = get_channel(cmd->chan_id); + if (channel == NULL) { + goto fail; + } + + sdu = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); + if (sdu == NULL) { + os_mbuf_free_chain(sdu); + goto fail; + } + + rc = ble_l2cap_recv_ready(channel->chan, sdu); + if (rc != 0) { + goto fail; + } + tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_CREDITS, CONTROLLER_INDEX, + BTP_STATUS_SUCCESS); + return; +fail: + tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_CREDITS, CONTROLLER_INDEX, + BTP_STATUS_FAILED); +} + static void reconfigure(const uint8_t *data, uint16_t len) { const struct l2cap_reconfigure_cmd *cmd = (void *) data; @@ -696,6 +730,9 @@ void tester_handle_l2cap(uint8_t opcode, uint8_t index, uint8_t *data, case L2CAP_RECONFIGURE: reconfigure(data, len); return; + case L2CAP_CREDITS: + credits(data, len); + return; default: tester_rsp(BTP_SERVICE_ID_L2CAP, opcode, index, BTP_STATUS_UNKNOWN_CMD);