Skip to content

Commit a42a802

Browse files
committed
extmod/modbluetooth: Make all HCI transports trace in the same format.
- Use HCI_TRACE macro consistently. - Use the same colour formatting. - Add a tool to convert to .pcap for Wireshark. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
1 parent ab31e23 commit a42a802

File tree

3 files changed

+150
-9
lines changed

3 files changed

+150
-9
lines changed

extmod/nimble/hal/hal_uart.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
#endif
4040

4141
#define HCI_TRACE (0)
42+
#define COL_OFF "\033[0m"
43+
#define COL_GREEN "\033[0;32m"
44+
#define COL_BLUE "\033[0;34m"
4245

4346
static hal_uart_tx_cb_t hal_uart_tx_cb;
4447
static void *hal_uart_tx_arg;
@@ -71,11 +74,11 @@ void hal_uart_start_tx(uint32_t port) {
7174
}
7275

7376
#if HCI_TRACE
74-
printf("< [% 8d] %02x", (int)mp_hal_ticks_ms(), mp_bluetooth_hci_cmd_buf[0]);
77+
printf(COL_GREEN "< [% 8d] %02x", (int)mp_hal_ticks_ms(), mp_bluetooth_hci_cmd_buf[0]);
7578
for (size_t i = 1; i < len; ++i) {
7679
printf(":%02x", mp_bluetooth_hci_cmd_buf[i]);
7780
}
78-
printf("\n");
81+
printf(COL_OFF "\n");
7982
#endif
8083

8184
mp_bluetooth_hci_uart_write(mp_bluetooth_hci_cmd_buf, len);
@@ -92,7 +95,7 @@ int hal_uart_close(uint32_t port) {
9295

9396
STATIC void mp_bluetooth_hci_uart_char_cb(uint8_t chr) {
9497
#if HCI_TRACE
95-
printf("> %02x\n", chr);
98+
printf(COL_BLUE "> [% 8d] %02x" COL_OFF "\n", (int)mp_hal_ticks_ms(), chr);
9699
#endif
97100
hal_uart_rx_cb(hal_uart_rx_arg, chr);
98101
}

ports/unix/mpbthciport.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@
4646
#include <string.h>
4747

4848
#define DEBUG_printf(...) // printf(__VA_ARGS__)
49-
#define DEBUG_HCI_DUMP (0)
49+
50+
#define HCI_TRACE (0)
51+
#define COL_OFF "\033[0m"
52+
#define COL_GREEN "\033[0;32m"
53+
#define COL_BLUE "\033[0;34m"
5054

5155
uint8_t mp_bluetooth_hci_cmd_buf[4 + 256];
5256

@@ -234,8 +238,8 @@ int mp_bluetooth_hci_uart_readchar(void) {
234238
ssize_t bytes_read = read(uart_fd, &c, 1);
235239

236240
if (bytes_read == 1) {
237-
#if DEBUG_HCI_DUMP
238-
printf("[% 8ld] RX: %02x\n", mp_hal_ticks_ms(), c);
241+
#if HCI_TRACE
242+
printf(COL_BLUE "> [% 8ld] RX: %02x" COL_OFF "\n", mp_hal_ticks_ms(), c);
239243
#endif
240244
return c;
241245
} else {
@@ -250,12 +254,12 @@ int mp_bluetooth_hci_uart_write(const uint8_t *buf, size_t len) {
250254
return 0;
251255
}
252256

253-
#if DEBUG_HCI_DUMP
254-
printf("[% 8ld] TX: %02x", mp_hal_ticks_ms(), buf[0]);
257+
#if HCI_TRACE
258+
printf(COL_GREEN "< [% 8ld] TX: %02x", mp_hal_ticks_ms(), buf[0]);
255259
for (size_t i = 1; i < len; ++i) {
256260
printf(":%02x", buf[i]);
257261
}
258-
printf("\n");
262+
printf(COL_OFF "\n");
259263
#endif
260264

261265
return write(uart_fd, buf, len);

tools/hci_trace_to_pcap.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#!/usr/bin/env python3
2+
#
3+
# This file is part of the MicroPython project, http://micropython.org/
4+
#
5+
# The MIT License (MIT)
6+
#
7+
# Copyright (c) 2023 Jim Mussared
8+
#
9+
# Permission is hereby granted, free of charge, to any person obtaining a copy
10+
# of this software and associated documentation files (the "Software"), to deal
11+
# in the Software without restriction, including without limitation the rights
12+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
# copies of the Software, and to permit persons to whom the Software is
14+
# furnished to do so, subject to the following conditions:
15+
#
16+
# The above copyright notice and this permission notice shall be included in
17+
# all copies or substantial portions of the Software.
18+
#
19+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
# THE SOFTWARE.
26+
27+
# Simple script to take the output printed when HCI_TRACE is enabled in
28+
# unix/mpbthciport.c, extmod/btstack/btstack_hci_uart.c,
29+
# extmod/nimble/hal/hal_uart.c and turn it into a .pcap file suitable for use
30+
# with Wireshark.
31+
32+
import re
33+
import sys
34+
import struct
35+
36+
# pcap file header:
37+
# typedef struct pcap_hdr_s {
38+
# guint32 magic_number; /* magic number */
39+
# guint16 version_major; /* major version number */
40+
# guint16 version_minor; /* minor version number */
41+
# gint32 thiszone; /* GMT to local correction */
42+
# guint32 sigfigs; /* accuracy of timestamps */
43+
# guint32 snaplen; /* max length of captured packets, in octets */
44+
# guint32 network; /* data link type */
45+
# } pcap_hdr_t;
46+
47+
# pcap record header
48+
# typedef struct pcaprec_hdr_s {
49+
# guint32 ts_sec; /* timestamp seconds */
50+
# guint32 ts_usec; /* timestamp microseconds */
51+
# guint32 incl_len; /* number of octets of packet saved in file */
52+
# guint32 orig_len; /* actual length of packet */
53+
# } pcaprec_hdr_t;
54+
55+
_LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR = 201 # "!I" direction, followed by data
56+
sys.stdout.buffer.write(
57+
struct.pack("!IHHiIII", 0xA1B2C3D4, 2, 4, 0, 0, 65535, _LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR)
58+
)
59+
60+
_DIR_CONTROLLER_TO_HOST = 1
61+
_DIR_HOST_TO_CONTROLLER = 0
62+
63+
reassemble_timestamp = 0
64+
reassemble_packet = bytearray()
65+
66+
with open(sys.argv[1], "r") as f:
67+
for line in f:
68+
line = line.strip()
69+
m = re.match("([<>]) \\[ *([0-9]+)\\] ([A-Fa-f0-9:]+)", line)
70+
if not m:
71+
continue
72+
73+
timestamp = int(m.group(2))
74+
data = bytes.fromhex(m.group(3).replace(":", ""))
75+
76+
if m.group(1) == "<":
77+
# Host to controller.
78+
# These are always complete.
79+
sys.stdout.buffer.write(
80+
struct.pack(
81+
"!IIIII",
82+
timestamp // 1000,
83+
timestamp % 1000 * 1000,
84+
len(data) + 4,
85+
len(data) + 4,
86+
_DIR_HOST_TO_CONTROLLER,
87+
)
88+
)
89+
sys.stdout.buffer.write(data)
90+
if m.group(1) == ">":
91+
# Controller to host.
92+
# Several of the sources print byte-at-a-time so need to reconstruct packets.
93+
94+
if not reassemble_packet:
95+
# Use the timestamp of the first fragment.
96+
reassemble_timestamp = timestamp
97+
98+
reassemble_packet.extend(data)
99+
100+
if len(reassemble_packet) > 4:
101+
plen = 0
102+
if reassemble_packet[0] == 1:
103+
# command
104+
plen = 3 + reassemble_packet[3]
105+
elif reassemble_packet[0] == 2:
106+
# acl
107+
plen = 5 + reassemble_packet[3] + (reassemble_packet[4] << 8)
108+
elif reassemble_packet[0] == 4:
109+
# event
110+
plen = 3 + reassemble_packet[2]
111+
112+
if len(reassemble_packet) >= plen:
113+
# Got a complete packet.
114+
data = reassemble_packet[0:plen]
115+
reassemble_packet = reassemble_packet[plen:]
116+
reassemble_timestamp = timestamp
117+
sys.stdout.buffer.write(
118+
struct.pack(
119+
"!IIIII",
120+
reassemble_timestamp // 1000,
121+
reassemble_timestamp % 1000 * 1000,
122+
len(data) + 4,
123+
len(data) + 4,
124+
_DIR_CONTROLLER_TO_HOST,
125+
)
126+
)
127+
sys.stdout.buffer.write(data)
128+
129+
if reassemble_packet:
130+
print(
131+
"Error: Unknown byte in HCI stream. Remainder:",
132+
reassemble_packet.hex(":"),
133+
file=sys.stderr,
134+
)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy