Skip to content

Commit

Permalink
[BT] Move BT tracing to UART1 (IO12) & output in BlueZ btmon tty format
Browse files Browse the repository at this point in the history
Transient on the ESP32 IOs after reset will make the PC running btmon
receive a spurious bytes which completely throw off irremediably btmon
tty parser.

So the trick is to release the ESP32 reset and then right after issue
the following command on the PC in hope of missing that spurious byte.

Usage: btmon --tty /dev/ttyUSB0 --tty-speed 921600 -w trace.log
  • Loading branch information
darthcloud committed Dec 8, 2024
1 parent 51cf1dc commit eb7f91b
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 20 deletions.
1 change: 1 addition & 0 deletions main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ idf_component_register(SRCS "main.c"
"bluetooth/att_cfg.c"
"bluetooth/att_hid.c"
"bluetooth/smp.c"
"bluetooth/mon.c"
"bluetooth/hidp/hidp.c"
"bluetooth/hidp/generic.c"
"bluetooth/hidp/ps3.c"
Expand Down
30 changes: 10 additions & 20 deletions main/bluetooth/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "smp.h"
#include "tools/util.h"
#include "debug.h"
#include "mon.h"
#include "system/fs.h"
#include "adapter/config.h"
#include "adapter/gameid.h"
Expand Down Expand Up @@ -68,9 +69,6 @@ static uint32_t frag_size = 0;
static uint32_t frag_offset = 0;
static uint8_t frag_buf[1024];

#ifdef CONFIG_BLUERETRO_BT_H4_TRACE
static void bt_h4_trace(uint8_t *data, uint16_t len, uint8_t dir);
#endif /* CONFIG_BLUERETRO_BT_H4_TRACE */
static int32_t bt_host_load_bdaddr_from_nvs(void);
static int32_t bt_host_load_keys_from_file(struct bt_host_link_keys *data);
static int32_t bt_host_store_keys_on_file(struct bt_host_link_keys *data);
Expand All @@ -86,21 +84,6 @@ static esp_vhci_host_callback_t vhci_host_cb = {
bt_host_rx_pkt
};

#ifdef CONFIG_BLUERETRO_BT_H4_TRACE
static void bt_h4_trace(uint8_t *data, uint16_t len, uint8_t dir) {
if (dir)
printf("I ");
else
printf("O ");

printf("%06X", 0);
for (uint32_t i = 0; i < len; i++) {
printf(" %02X", data[i]);
}
printf("\n");
}
#endif /* CONFIG_BLUERETRO_BT_H4_TRACE */

static int32_t bt_host_load_bdaddr_from_nvs(void) {
esp_err_t err;
nvs_handle_t nvs;
Expand Down Expand Up @@ -215,7 +198,8 @@ static void bt_tx_task(void *param) {
}
else {
#ifdef CONFIG_BLUERETRO_BT_H4_TRACE
bt_h4_trace(packet, packet_len, BT_TX);
bt_mon_tx((packet[0] == BT_HCI_H4_TYPE_CMD) ? BT_MON_CMD : BT_MON_ACL_TX,
packet + 1, packet_len - 1);
#endif /* CONFIG_BLUERETRO_BT_H4_TRACE */
atomic_clear_bit(&bt_flags, BT_CTRL_READY);
esp_vhci_host_send_packet(packet, packet_len);
Expand Down Expand Up @@ -405,7 +389,8 @@ static void bt_host_tx_pkt_ready(void) {
static int bt_host_rx_pkt(uint8_t *data, uint16_t len) {
struct bt_hci_pkt *bt_hci_pkt = (struct bt_hci_pkt *)data;
#ifdef CONFIG_BLUERETRO_BT_H4_TRACE
bt_h4_trace(data, len, BT_RX);
bt_mon_tx((bt_hci_pkt->h4_hdr.type == BT_HCI_H4_TYPE_EVT) ? BT_MON_EVT : BT_MON_ACL_RX,
data + 1, len - 1);
#endif /* CONFIG_BLUERETRO_BT_H4_TRACE */

#ifdef CONFIG_BLUERETRO_BT_TIMING_TESTS
Expand Down Expand Up @@ -633,6 +618,11 @@ int32_t bt_host_init(void) {

bt_host_load_bdaddr_from_nvs();

#ifdef CONFIG_BLUERETRO_BT_H4_TRACE
bt_mon_init(UART_NUM_1, 921600, UART_DATA_8_BITS, UART_STOP_BITS_1,
UART_PARITY_DISABLE, UART_HW_FLOWCTRL_DISABLE);
#endif

esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();

if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
Expand Down
65 changes: 65 additions & 0 deletions main/bluetooth/mon.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2024, Jacques Gagnon
* SPDX-License-Identifier: Apache-2.0
*/

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <esp_timer.h>
#include "mon.h"
#include "host.h"
#include "zephyr/hci.h"

#define BT_MON_TX_PIN 12
#define BT_MON_RX_PIN 13
#define BT_MON_RTS_PIN 15
#define BT_MON_CTS_PIN 14

struct bt_mon_hdr {
uint16_t data_len;
uint16_t opcode;
uint8_t flags;
uint8_t hdr_len;
uint8_t ts_type;
uint32_t ts_data;
} __packed;

static int uart_port;
static struct bt_mon_hdr mon_hdr = {0};

int bt_mon_init(int port_num, int32_t baud_rate, uint8_t data_bits, uint8_t stop_bits,
uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl) {
uart_config_t uart_cfg = {
.baud_rate = baud_rate,
.data_bits = data_bits,
.parity = parity,
.stop_bits = stop_bits,
.flow_ctrl = flow_ctl,
.source_clk = UART_SCLK_DEFAULT,
.rx_flow_ctrl_thresh = UART_HW_FIFO_LEN(port_num) - 1,
};
uart_port = port_num;

printf("# %s: set uart pin tx:%d\n", __FUNCTION__, BT_MON_TX_PIN);
printf("# %s: set baud_rate:%ld.\n", __FUNCTION__, baud_rate);

ESP_ERROR_CHECK(uart_driver_delete(port_num));
ESP_ERROR_CHECK(uart_driver_install(port_num, UART_HW_FIFO_LEN(port_num) * 2, 0, 0, NULL, 0));
ESP_ERROR_CHECK(uart_param_config(port_num, &uart_cfg));
ESP_ERROR_CHECK(uart_set_pin(port_num, BT_MON_TX_PIN, BT_MON_RX_PIN, BT_MON_RTS_PIN, BT_MON_CTS_PIN));

return 0;
}

void IRAM_ATTR bt_mon_tx(uint16_t opcode, uint8_t *data, uint16_t len) {
mon_hdr.data_len = len + 4 + 5;
mon_hdr.opcode = opcode;
mon_hdr.hdr_len = 5;
mon_hdr.ts_type = 8;
mon_hdr.ts_data = esp_timer_get_time() / 100;

uart_write_bytes(uart_port, &mon_hdr, sizeof(mon_hdr));
uart_write_bytes(uart_port, data, len);
}
20 changes: 20 additions & 0 deletions main/bluetooth/mon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2024, Jacques Gagnon
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef _BT_MON_H_
#define _BT_MON_H_

#include "driver/uart.h"

#define BT_MON_CMD 2
#define BT_MON_EVT 3
#define BT_MON_ACL_TX 4
#define BT_MON_ACL_RX 5

int bt_mon_init(int port_num, int32_t baud_rate, uint8_t data_bits,
uint8_t stop_bits, uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl);
void bt_mon_tx(uint16_t opcode, uint8_t *data, uint16_t len);

#endif /* _BT_MON_H_ */

0 comments on commit eb7f91b

Please sign in to comment.