Bluetooth: monitor: Avoid sending corrupted packets over RTT

This fixes sending corrupted (incomplete) packets over RTT. Additional
helper buffer has been added to ensure the complete packet before it
can be sent over RTT. Once the complete packet is collected it is sent
to the RTT control block in non-blocking manner. From now there will
be no situation that only part of the packet (e.g. header) is sent
which lead btmon to fail to parse the corrupted data.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This commit is contained in:
Mariusz Skamra 2022-06-07 21:17:56 +02:00 committed by Carles Cufí
parent e7b66d1b73
commit c44ef044b8

View file

@ -64,17 +64,76 @@ static struct {
atomic_t other;
} drops;
static void drop_add(uint16_t opcode)
{
switch (opcode) {
case BT_MONITOR_COMMAND_PKT:
atomic_inc(&drops.cmd);
break;
case BT_MONITOR_EVENT_PKT:
atomic_inc(&drops.evt);
break;
case BT_MONITOR_ACL_TX_PKT:
atomic_inc(&drops.acl_tx);
break;
case BT_MONITOR_ACL_RX_PKT:
atomic_inc(&drops.acl_rx);
break;
#if defined(CONFIG_BT_BREDR)
case BT_MONITOR_SCO_TX_PKT:
atomic_inc(&drops.sco_tx);
break;
case BT_MONITOR_SCO_RX_PKT:
atomic_inc(&drops.sco_rx);
break;
#endif
default:
atomic_inc(&drops.other);
break;
}
}
#if defined(CONFIG_BT_DEBUG_MONITOR_RTT)
#include <SEGGER_RTT.h>
#define RTT_BUFFER_NAME CONFIG_BT_DEBUG_MONITOR_RTT_BUFFER_NAME
#define RTT_BUF_SIZE CONFIG_BT_DEBUG_MONITOR_RTT_BUFFER_SIZE
static uint8_t rtt_buf[RTT_BUF_SIZE];
static void monitor_send(const void *data, size_t len)
{
SEGGER_RTT_Write(CONFIG_BT_DEBUG_MONITOR_RTT_BUFFER, data, len);
static uint8_t rtt_buf[RTT_BUF_SIZE];
static size_t rtt_buf_offset;
struct bt_monitor_hdr *hdr;
unsigned int cnt = 0;
bool drop;
/* Drop any packet which cannot fit the buffer */
drop = rtt_buf_offset + len > sizeof(rtt_buf);
if (!drop) {
(void)memcpy(rtt_buf + rtt_buf_offset, data, len);
}
rtt_buf_offset += len;
/* Check if the packet is complete */
hdr = (struct bt_monitor_hdr *)rtt_buf;
if (rtt_buf_offset < sizeof(hdr->data_len) + hdr->data_len) {
return;
}
if (!drop) {
SEGGER_RTT_LOCK();
cnt = SEGGER_RTT_WriteNoLock(CONFIG_BT_DEBUG_MONITOR_RTT_BUFFER,
rtt_buf, rtt_buf_offset);
SEGGER_RTT_UNLOCK();
}
if (!cnt) {
drop_add(hdr->opcode);
}
/* Prepare for the next packet */
rtt_buf_offset = 0;
}
static void poll_out(char c)
@ -143,35 +202,6 @@ static inline void encode_hdr(struct bt_monitor_hdr *hdr, uint32_t timestamp,
hdr->data_len = sys_cpu_to_le16(4 + hdr->hdr_len + len);
}
static void drop_add(uint16_t opcode)
{
switch (opcode) {
case BT_MONITOR_COMMAND_PKT:
atomic_inc(&drops.cmd);
break;
case BT_MONITOR_EVENT_PKT:
atomic_inc(&drops.evt);
break;
case BT_MONITOR_ACL_TX_PKT:
atomic_inc(&drops.acl_tx);
break;
case BT_MONITOR_ACL_RX_PKT:
atomic_inc(&drops.acl_rx);
break;
#if defined(CONFIG_BT_BREDR)
case BT_MONITOR_SCO_TX_PKT:
atomic_inc(&drops.sco_tx);
break;
case BT_MONITOR_SCO_RX_PKT:
atomic_inc(&drops.sco_rx);
break;
#endif
default:
atomic_inc(&drops.other);
break;
}
}
void bt_monitor_send(uint16_t opcode, const void *data, size_t len)
{
struct bt_monitor_hdr hdr;
@ -382,8 +412,10 @@ static int bt_monitor_init(const struct device *d)
ARG_UNUSED(d);
#if defined(CONFIG_BT_DEBUG_MONITOR_RTT)
static uint8_t rtt_up_buf[RTT_BUF_SIZE];
SEGGER_RTT_ConfigUpBuffer(CONFIG_BT_DEBUG_MONITOR_RTT_BUFFER,
RTT_BUFFER_NAME, rtt_buf, RTT_BUF_SIZE,
RTT_BUFFER_NAME, rtt_up_buf, RTT_BUF_SIZE,
SEGGER_RTT_MODE_NO_BLOCK_SKIP);
#elif defined(CONFIG_BT_DEBUG_MONITOR_UART)
monitor_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_mon_uart));