diff options
author | Jim Mussared <jim.mussared@gmail.com> | 2023-04-13 11:33:43 +1000 |
---|---|---|
committer | Jim Mussared <jim.mussared@gmail.com> | 2023-04-26 11:37:20 +1000 |
commit | a42a8022d8d2c9fc1fe05ff5ac60b650e481a62d (patch) | |
tree | 6466d0e51ecfa031602b14e514a58c8857b90798 /tools | |
parent | ab31e23f7a0bc8379f117f0e31403751cbfcf837 (diff) | |
download | micropython-a42a8022d8d2c9fc1fe05ff5ac60b650e481a62d.tar.gz micropython-a42a8022d8d2c9fc1fe05ff5ac60b650e481a62d.zip |
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>
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/hci_trace_to_pcap.py | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/tools/hci_trace_to_pcap.py b/tools/hci_trace_to_pcap.py new file mode 100755 index 0000000000..d55df3fb61 --- /dev/null +++ b/tools/hci_trace_to_pcap.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python3 +# +# This file is part of the MicroPython project, http://micropython.org/ +# +# The MIT License (MIT) +# +# Copyright (c) 2023 Jim Mussared +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +# Simple script to take the output printed when HCI_TRACE is enabled in +# unix/mpbthciport.c, extmod/btstack/btstack_hci_uart.c, +# extmod/nimble/hal/hal_uart.c and turn it into a .pcap file suitable for use +# with Wireshark. + +import re +import sys +import struct + +# pcap file header: +# typedef struct pcap_hdr_s { +# guint32 magic_number; /* magic number */ +# guint16 version_major; /* major version number */ +# guint16 version_minor; /* minor version number */ +# gint32 thiszone; /* GMT to local correction */ +# guint32 sigfigs; /* accuracy of timestamps */ +# guint32 snaplen; /* max length of captured packets, in octets */ +# guint32 network; /* data link type */ +# } pcap_hdr_t; + +# pcap record header +# typedef struct pcaprec_hdr_s { +# guint32 ts_sec; /* timestamp seconds */ +# guint32 ts_usec; /* timestamp microseconds */ +# guint32 incl_len; /* number of octets of packet saved in file */ +# guint32 orig_len; /* actual length of packet */ +# } pcaprec_hdr_t; + +_LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR = 201 # "!I" direction, followed by data +sys.stdout.buffer.write( + struct.pack("!IHHiIII", 0xA1B2C3D4, 2, 4, 0, 0, 65535, _LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR) +) + +_DIR_CONTROLLER_TO_HOST = 1 +_DIR_HOST_TO_CONTROLLER = 0 + +reassemble_timestamp = 0 +reassemble_packet = bytearray() + +with open(sys.argv[1], "r") as f: + for line in f: + line = line.strip() + m = re.match("([<>]) \\[ *([0-9]+)\\] ([A-Fa-f0-9:]+)", line) + if not m: + continue + + timestamp = int(m.group(2)) + data = bytes.fromhex(m.group(3).replace(":", "")) + + if m.group(1) == "<": + # Host to controller. + # These are always complete. + sys.stdout.buffer.write( + struct.pack( + "!IIIII", + timestamp // 1000, + timestamp % 1000 * 1000, + len(data) + 4, + len(data) + 4, + _DIR_HOST_TO_CONTROLLER, + ) + ) + sys.stdout.buffer.write(data) + if m.group(1) == ">": + # Controller to host. + # Several of the sources print byte-at-a-time so need to reconstruct packets. + + if not reassemble_packet: + # Use the timestamp of the first fragment. + reassemble_timestamp = timestamp + + reassemble_packet.extend(data) + + if len(reassemble_packet) > 4: + plen = 0 + if reassemble_packet[0] == 1: + # command + plen = 3 + reassemble_packet[3] + elif reassemble_packet[0] == 2: + # acl + plen = 5 + reassemble_packet[3] + (reassemble_packet[4] << 8) + elif reassemble_packet[0] == 4: + # event + plen = 3 + reassemble_packet[2] + + if len(reassemble_packet) >= plen: + # Got a complete packet. + data = reassemble_packet[0:plen] + reassemble_packet = reassemble_packet[plen:] + reassemble_timestamp = timestamp + sys.stdout.buffer.write( + struct.pack( + "!IIIII", + reassemble_timestamp // 1000, + reassemble_timestamp % 1000 * 1000, + len(data) + 4, + len(data) + 4, + _DIR_CONTROLLER_TO_HOST, + ) + ) + sys.stdout.buffer.write(data) + +if reassemble_packet: + print( + "Error: Unknown byte in HCI stream. Remainder:", + reassemble_packet.hex(":"), + file=sys.stderr, + ) |