mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-25 18:35:17 +00:00
hci_dump: support PacketLogger or BlueZ format output via SEGGER RTT Channel 1 Up
This commit is contained in:
parent
6ed7c861fe
commit
5fa31a9940
@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||
|
||||
### Added
|
||||
- SM: generate and store ER / IR keys in TLV, unless manually set by application
|
||||
- hci_dump: support PacketLogger or BlueZ format output via SEGGER RTT Channel 1 Up
|
||||
|
||||
### Fixed
|
||||
- SM: fix internal buffer overrun during random address generation
|
||||
|
179
src/hci_dump.c
179
src/hci_dump.c
@ -46,7 +46,6 @@
|
||||
* - Apple's PacketLogger
|
||||
* - stdout hexdump
|
||||
*
|
||||
* Created by Matthias Ringwald on 5/26/09.
|
||||
*/
|
||||
|
||||
#include "btstack_config.h"
|
||||
@ -69,6 +68,11 @@
|
||||
#include <sys/stat.h> // for mode flags
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SEGGER_RTT
|
||||
#include "SEGGER_RTT.h"
|
||||
static char channel1_out[1024];
|
||||
#endif
|
||||
|
||||
// BLUEZ hcidump - struct not used directly, but left here as documentation
|
||||
typedef struct {
|
||||
uint16_t len;
|
||||
@ -92,10 +96,12 @@ pktlog_hdr;
|
||||
#define PKTLOG_HDR_SIZE 13
|
||||
|
||||
static int dump_file = -1;
|
||||
#ifdef HAVE_POSIX_FILE_IO
|
||||
static int dump_format;
|
||||
static uint8_t header_bluez[HCIDUMP_HDR_SIZE];
|
||||
static uint8_t header_packetlogger[PKTLOG_HDR_SIZE];
|
||||
static union {
|
||||
uint8_t header_bluez[HCIDUMP_HDR_SIZE];
|
||||
uint8_t header_packetlogger[PKTLOG_HDR_SIZE];
|
||||
} header;
|
||||
#ifdef HAVE_POSIX_FILE_IO
|
||||
static char time_string[40];
|
||||
static int max_nr_packets = -1;
|
||||
static int nr_packets = 0;
|
||||
@ -106,8 +112,10 @@ static char log_message_buffer[256];
|
||||
static int log_level_enabled[3] = { 1, 1, 1};
|
||||
|
||||
void hci_dump_open(const char *filename, hci_dump_format_t format){
|
||||
#ifdef HAVE_POSIX_FILE_IO
|
||||
|
||||
dump_format = format;
|
||||
|
||||
#ifdef HAVE_POSIX_FILE_IO
|
||||
if (dump_format == HCI_DUMP_STDOUT) {
|
||||
dump_file = fileno(stdout);
|
||||
} else {
|
||||
@ -116,15 +124,30 @@ void hci_dump_open(const char *filename, hci_dump_format_t format){
|
||||
#ifdef _WIN32
|
||||
oflags |= O_BINARY;
|
||||
#endif
|
||||
|
||||
dump_file = open(filename, oflags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
|
||||
if (dump_file < 0){
|
||||
printf("hci_dump_open: failed to open file %s\n", filename);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
UNUSED(filename);
|
||||
UNUSED(format);
|
||||
|
||||
#ifdef ENABLE_SEGGER_RTT
|
||||
switch (dump_format){
|
||||
case HCI_DUMP_PACKETLOGGER:
|
||||
case HCI_DUMP_BLUEZ:
|
||||
// Configure up channel 1, options:
|
||||
// - SEGGER_RTT_MODE_NO_BLOCK_SKIP
|
||||
// - SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
|
||||
// Note: with SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL, firwmware will hang if RTT not supported/debug probe not connected
|
||||
// Note: with SEGGER_RTT_MODE_NO_BLOCK_SKIP, there's a chance for log file corruption if second write (packet) is skipped
|
||||
SEGGER_RTT_ConfigUpBuffer(1, "hci_dump", &channel1_out[0], sizeof(channel1_out), SEGGER_RTT_MODE_NO_BLOCK_SKIP) ;;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
dump_file = 1;
|
||||
#endif
|
||||
@ -136,6 +159,42 @@ void hci_dump_set_max_packets(int packets){
|
||||
}
|
||||
#endif
|
||||
|
||||
static void hci_dump_packetlogger_setup_header(uint8_t * buffer, uint32_t tv_sec, uint32_t tv_us, uint8_t packet_type, uint8_t in, uint16_t len){
|
||||
big_endian_store_32( buffer, 0, PKTLOG_HDR_SIZE - 4 + len);
|
||||
big_endian_store_32( buffer, 4, tv_sec);
|
||||
big_endian_store_32( buffer, 8, tv_us);
|
||||
uint8_t packet_logger_type = 0;
|
||||
switch (packet_type){
|
||||
case HCI_COMMAND_DATA_PACKET:
|
||||
packet_logger_type = 0x00;
|
||||
break;
|
||||
case HCI_ACL_DATA_PACKET:
|
||||
packet_logger_type = in ? 0x03 : 0x02;
|
||||
break;
|
||||
case HCI_SCO_DATA_PACKET:
|
||||
packet_logger_type = in ? 0x09 : 0x08;
|
||||
break;
|
||||
case HCI_EVENT_PACKET:
|
||||
packet_logger_type = 0x01;
|
||||
break;
|
||||
case LOG_MESSAGE_PACKET:
|
||||
packet_logger_type = 0xfc;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
buffer[12] = packet_logger_type;
|
||||
}
|
||||
|
||||
static void hci_dump_bluez_setup_header(uint8_t * buffer, uint32_t tv_sec, uint32_t tv_us, uint8_t packet_type, uint8_t in, uint16_t len){
|
||||
little_endian_store_16( buffer, 0, 1 + len);
|
||||
buffer[2] = in;
|
||||
buffer[3] = 0;
|
||||
little_endian_store_32( buffer, 4, tv_sec);
|
||||
little_endian_store_32( buffer, 8, tv_us);
|
||||
buffer[12] = packet_type;
|
||||
}
|
||||
|
||||
static void printf_packet(uint8_t packet_type, uint8_t in, uint8_t * packet, uint16_t len){
|
||||
switch (packet_type){
|
||||
case HCI_COMMAND_DATA_PACKET:
|
||||
@ -187,7 +246,7 @@ static void printf_timestamp(void){
|
||||
uint32_t time_ms = btstack_run_loop_get_time_ms();
|
||||
int seconds = time_ms / 1000;
|
||||
int minutes = seconds / 60;
|
||||
unsigned int hours = minutes / 60;
|
||||
unsigned int hours = minutes / 60;
|
||||
|
||||
uint16_t p_ms = time_ms - (seconds * 1000);
|
||||
uint16_t p_seconds = seconds - (minutes * 60);
|
||||
@ -201,7 +260,6 @@ void hci_dump_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t
|
||||
if (dump_file < 0) return; // not activated yet
|
||||
|
||||
#ifdef HAVE_POSIX_FILE_IO
|
||||
|
||||
// don't grow bigger than max_nr_packets
|
||||
if (dump_format != HCI_DUMP_STDOUT && max_nr_packets > 0){
|
||||
if (nr_packets >= max_nr_packets){
|
||||
@ -213,76 +271,55 @@ void hci_dump_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t
|
||||
}
|
||||
nr_packets++;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (dump_format == HCI_DUMP_STDOUT){
|
||||
printf_timestamp();
|
||||
printf_packet(packet_type, in, packet, len);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t tv_sec = 0;
|
||||
uint32_t tv_us = 0;
|
||||
|
||||
// get time
|
||||
#ifdef HAVE_POSIX_FILE_IO
|
||||
struct timeval curr_time;
|
||||
gettimeofday(&curr_time, NULL);
|
||||
tv_sec = curr_time.tv_sec;
|
||||
tv_us = curr_time.tv_usec;
|
||||
#else
|
||||
uint32_t time_ms = btstack_run_loop_get_time_ms();
|
||||
tv_us = time_ms * 1000;
|
||||
tv_sec = 946728000UL + (time_ms / 1000);
|
||||
#endif
|
||||
|
||||
uint16_t header_len = 0;
|
||||
switch (dump_format){
|
||||
case HCI_DUMP_BLUEZ:
|
||||
hci_dump_bluez_setup_header(header.header_bluez, tv_sec, tv_us, packet_type, in, len);
|
||||
header_len = HCIDUMP_HDR_SIZE;
|
||||
break;
|
||||
case HCI_DUMP_PACKETLOGGER:
|
||||
hci_dump_packetlogger_setup_header(header.header_packetlogger, tv_sec, tv_us, packet_type, in, len);
|
||||
header_len = PKTLOG_HDR_SIZE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_POSIX_FILE_IO
|
||||
// avoid -Wunused-result
|
||||
int res = 0;
|
||||
switch (dump_format){
|
||||
case HCI_DUMP_STDOUT: {
|
||||
printf_timestamp();
|
||||
printf_packet(packet_type, in, packet, len);
|
||||
break;
|
||||
}
|
||||
|
||||
case HCI_DUMP_BLUEZ:
|
||||
little_endian_store_16( header_bluez, 0, 1 + len);
|
||||
header_bluez[2] = in;
|
||||
header_bluez[3] = 0;
|
||||
little_endian_store_32( header_bluez, 4, (uint32_t) curr_time.tv_sec);
|
||||
little_endian_store_32( header_bluez, 8, curr_time.tv_usec);
|
||||
header_bluez[12] = packet_type;
|
||||
res = write (dump_file, header_bluez, HCIDUMP_HDR_SIZE);
|
||||
res = write (dump_file, packet, len );
|
||||
break;
|
||||
|
||||
case HCI_DUMP_PACKETLOGGER:
|
||||
big_endian_store_32( header_packetlogger, 0, PKTLOG_HDR_SIZE - 4 + len);
|
||||
big_endian_store_32( header_packetlogger, 4, (uint32_t) curr_time.tv_sec);
|
||||
big_endian_store_32( header_packetlogger, 8, curr_time.tv_usec);
|
||||
switch (packet_type){
|
||||
case HCI_COMMAND_DATA_PACKET:
|
||||
header_packetlogger[12] = 0x00;
|
||||
break;
|
||||
case HCI_ACL_DATA_PACKET:
|
||||
if (in) {
|
||||
header_packetlogger[12] = 0x03;
|
||||
} else {
|
||||
header_packetlogger[12] = 0x02;
|
||||
}
|
||||
break;
|
||||
case HCI_SCO_DATA_PACKET:
|
||||
if (in) {
|
||||
header_packetlogger[12] = 0x09;
|
||||
} else {
|
||||
header_packetlogger[12] = 0x08;
|
||||
}
|
||||
break;
|
||||
case HCI_EVENT_PACKET:
|
||||
header_packetlogger[12] = 0x01;
|
||||
break;
|
||||
case LOG_MESSAGE_PACKET:
|
||||
header_packetlogger[12] = 0xfc;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
res = write (dump_file, &header_packetlogger, PKTLOG_HDR_SIZE);
|
||||
res = write (dump_file, packet, len );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
res = write (dump_file, &header, header_len);
|
||||
res = write (dump_file, packet, len );
|
||||
UNUSED(res);
|
||||
#else
|
||||
|
||||
printf_timestamp();
|
||||
printf_packet(packet_type, in, packet, len);
|
||||
|
||||
#endif
|
||||
#ifdef ENABLE_SEGGER_RTT
|
||||
SEGGER_RTT_Write(1, &header, header_len);
|
||||
SEGGER_RTT_Write(1, packet, len);
|
||||
#endif
|
||||
UNUSED(header_len);
|
||||
}
|
||||
|
||||
static int hci_dump_log_level_active(int log_level){
|
||||
|
Loading…
x
Reference in New Issue
Block a user