179662672Smatthias.ringwald /*
2a0c35809S[email protected] * Copyright (C) 2014 BlueKitchen GmbH
31713bceaSmatthias.ringwald *
41713bceaSmatthias.ringwald * Redistribution and use in source and binary forms, with or without
51713bceaSmatthias.ringwald * modification, are permitted provided that the following conditions
61713bceaSmatthias.ringwald * are met:
71713bceaSmatthias.ringwald *
81713bceaSmatthias.ringwald * 1. Redistributions of source code must retain the above copyright
91713bceaSmatthias.ringwald * notice, this list of conditions and the following disclaimer.
101713bceaSmatthias.ringwald * 2. Redistributions in binary form must reproduce the above copyright
111713bceaSmatthias.ringwald * notice, this list of conditions and the following disclaimer in the
121713bceaSmatthias.ringwald * documentation and/or other materials provided with the distribution.
131713bceaSmatthias.ringwald * 3. Neither the name of the copyright holders nor the names of
141713bceaSmatthias.ringwald * contributors may be used to endorse or promote products derived
151713bceaSmatthias.ringwald * from this software without specific prior written permission.
166b64433eSmatthias.ringwald * 4. Any redistribution, use, or modification is done solely for
176b64433eSmatthias.ringwald * personal benefit and not for any commercial purpose or for
186b64433eSmatthias.ringwald * monetary gain.
191713bceaSmatthias.ringwald *
20a0c35809S[email protected] * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
211713bceaSmatthias.ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
221713bceaSmatthias.ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
232fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
242fca4dadSMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
251713bceaSmatthias.ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
261713bceaSmatthias.ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
271713bceaSmatthias.ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
281713bceaSmatthias.ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
291713bceaSmatthias.ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
301713bceaSmatthias.ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311713bceaSmatthias.ringwald * SUCH DAMAGE.
321713bceaSmatthias.ringwald *
33a0c35809S[email protected] * Please inquire about commercial licensing options at
34a0c35809S[email protected] * [email protected]
356b64433eSmatthias.ringwald *
361713bceaSmatthias.ringwald */
371713bceaSmatthias.ringwald
38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "hci_dump.c"
39ab2c6ae4SMatthias Ringwald
401713bceaSmatthias.ringwald /*
4179662672Smatthias.ringwald * hci_dump.c
4279662672Smatthias.ringwald *
43128d6c99SMatthias Ringwald * Dump HCI trace in various formats based on platform-specific implementation
4479662672Smatthias.ringwald */
4579662672Smatthias.ringwald
467907f069SMatthias Ringwald #include "btstack_config.h"
47128d6c99SMatthias Ringwald #include "btstack_debug.h"
48128d6c99SMatthias Ringwald #include "btstack_bool.h"
49128d6c99SMatthias Ringwald #include "btstack_util.h"
50a1d7dd1fSmatthias.ringwald
51b45b7749SMilanka Ringwald static const hci_dump_t * hci_dump_implementation;
52128d6c99SMatthias Ringwald static int max_nr_packets;
53128d6c99SMatthias Ringwald static int nr_packets;
54cdc66b5eSMatthias Ringwald static bool packet_log_enabled;
558b658ebcSmatthias.ringwald
568a37b10aSMatthias Ringwald // levels: debug, info, error
57128d6c99SMatthias Ringwald static bool log_level_enabled[3] = { 1, 1, 1};
588a37b10aSMatthias Ringwald
hci_dump_log_level_active(int log_level)59128d6c99SMatthias Ringwald static bool hci_dump_log_level_active(int log_level){
60b45b7749SMilanka Ringwald if (hci_dump_implementation == NULL) return false;
61128d6c99SMatthias Ringwald if (log_level < HCI_DUMP_LOG_LEVEL_DEBUG) return false;
62128d6c99SMatthias Ringwald if (log_level > HCI_DUMP_LOG_LEVEL_ERROR) return false;
63128d6c99SMatthias Ringwald return log_level_enabled[log_level];
64d9659922Smatthias.ringwald }
6579662672Smatthias.ringwald
hci_dump_init(const hci_dump_t * hci_dump_impl)66b45b7749SMilanka Ringwald void hci_dump_init(const hci_dump_t * hci_dump_impl){
67128d6c99SMatthias Ringwald max_nr_packets = -1;
68128d6c99SMatthias Ringwald nr_packets = 0;
69b45b7749SMilanka Ringwald hci_dump_implementation = hci_dump_impl;
70cdc66b5eSMatthias Ringwald packet_log_enabled = true;
71128d6c99SMatthias Ringwald }
72128d6c99SMatthias Ringwald
hci_dump_set_max_packets(int packets)732992c131Smatthias.ringwald void hci_dump_set_max_packets(int packets){
742992c131Smatthias.ringwald max_nr_packets = packets;
752992c131Smatthias.ringwald }
76128d6c99SMatthias Ringwald
hci_dump_enable_packet_log(bool enabled)77cdc66b5eSMatthias Ringwald void hci_dump_enable_packet_log(bool enabled){
78cdc66b5eSMatthias Ringwald packet_log_enabled = enabled;
79cdc66b5eSMatthias Ringwald }
80cdc66b5eSMatthias Ringwald
hci_dump_packet(uint8_t packet_type,uint8_t in,uint8_t * packet,uint16_t len)81128d6c99SMatthias Ringwald void hci_dump_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t len) {
82b45b7749SMilanka Ringwald if (hci_dump_implementation == NULL) {
83cdc66b5eSMatthias Ringwald return;
84cdc66b5eSMatthias Ringwald }
85cdc66b5eSMatthias Ringwald if (packet_log_enabled == false) {
86cdc66b5eSMatthias Ringwald return;
87cdc66b5eSMatthias Ringwald }
88cdc66b5eSMatthias Ringwald
89128d6c99SMatthias Ringwald if (max_nr_packets > 0){
90b45b7749SMilanka Ringwald if ((nr_packets >= max_nr_packets) && (hci_dump_implementation->reset != NULL)) {
91128d6c99SMatthias Ringwald nr_packets = 0;
92b45b7749SMilanka Ringwald (*hci_dump_implementation->reset)();
93128d6c99SMatthias Ringwald }
94128d6c99SMatthias Ringwald nr_packets++;
95128d6c99SMatthias Ringwald }
96b45b7749SMilanka Ringwald (*hci_dump_implementation->log_packet)(packet_type, in, packet, len);
97128d6c99SMatthias Ringwald }
98128d6c99SMatthias Ringwald
hci_dump_log(int log_level,const char * format,...)99128d6c99SMatthias Ringwald void hci_dump_log(int log_level, const char * format, ...){
100128d6c99SMatthias Ringwald if (!hci_dump_log_level_active(log_level)) return;
101128d6c99SMatthias Ringwald
102128d6c99SMatthias Ringwald va_list argptr;
103128d6c99SMatthias Ringwald va_start(argptr, format);
1042d17d4c0SMatthias Ringwald (*hci_dump_implementation->log_message)(log_level, format, argptr);
105128d6c99SMatthias Ringwald va_end(argptr);
106128d6c99SMatthias Ringwald }
107128d6c99SMatthias Ringwald
108128d6c99SMatthias Ringwald #ifdef __AVR__
hci_dump_log_P(int log_level,PGM_P format,...)109128d6c99SMatthias Ringwald void hci_dump_log_P(int log_level, PGM_P format, ...){
110128d6c99SMatthias Ringwald if (!hci_dump_log_level_active(log_level)) return;
111128d6c99SMatthias Ringwald
112128d6c99SMatthias Ringwald va_list argptr;
113128d6c99SMatthias Ringwald va_start(argptr, format);
1142d17d4c0SMatthias Ringwald (*hci_dump_implementation->log_message_P)(log_level, format, argptr);
115128d6c99SMatthias Ringwald va_end(argptr);
116128d6c99SMatthias Ringwald }
1177c5f7483Smatthias.ringwald #endif
1182992c131Smatthias.ringwald
hci_dump_btstack_event(const uint8_t * packet,uint16_t len)119be78df3bSMatthias Ringwald void hci_dump_btstack_event(const uint8_t *packet, uint16_t len){
120be78df3bSMatthias Ringwald #ifdef ENABLE_LOG_BTSTACK_EVENTS
121*57ea53d1SMatthias Ringwald hci_dump_packet(HCI_EVENT_PACKET, 1, packet, len);
122be78df3bSMatthias Ringwald #else
123be78df3bSMatthias Ringwald UNUSED(packet);
124be78df3bSMatthias Ringwald UNUSED(len);
125be78df3bSMatthias Ringwald #endif
126be78df3bSMatthias Ringwald }
127be78df3bSMatthias Ringwald
hci_dump_enable_log_level(int log_level,int enable)128128d6c99SMatthias Ringwald void hci_dump_enable_log_level(int log_level, int enable){
129128d6c99SMatthias Ringwald if (log_level < HCI_DUMP_LOG_LEVEL_DEBUG) return;
130128d6c99SMatthias Ringwald if (log_level > HCI_DUMP_LOG_LEVEL_ERROR) return;
131128d6c99SMatthias Ringwald log_level_enabled[log_level] = enable != 0;
132128d6c99SMatthias Ringwald }
133128d6c99SMatthias Ringwald
hci_dump_setup_header_packetlogger(uint8_t * buffer,uint32_t tv_sec,uint32_t tv_us,uint8_t packet_type,uint8_t in,uint16_t len)134128d6c99SMatthias Ringwald void hci_dump_setup_header_packetlogger(uint8_t * buffer, uint32_t tv_sec, uint32_t tv_us, uint8_t packet_type, uint8_t in, uint16_t len){
135128d6c99SMatthias Ringwald big_endian_store_32( buffer, 0, HCI_DUMP_HEADER_SIZE_PACKETLOGGER - 4 + len);
1365fa31a99SMatthias Ringwald big_endian_store_32( buffer, 4, tv_sec);
1375fa31a99SMatthias Ringwald big_endian_store_32( buffer, 8, tv_us);
1385fa31a99SMatthias Ringwald uint8_t packet_logger_type = 0;
1395fa31a99SMatthias Ringwald switch (packet_type){
1405fa31a99SMatthias Ringwald case HCI_COMMAND_DATA_PACKET:
1415fa31a99SMatthias Ringwald packet_logger_type = 0x00;
1425fa31a99SMatthias Ringwald break;
1435fa31a99SMatthias Ringwald case HCI_ACL_DATA_PACKET:
1445fa31a99SMatthias Ringwald packet_logger_type = in ? 0x03 : 0x02;
1455fa31a99SMatthias Ringwald break;
1465fa31a99SMatthias Ringwald case HCI_SCO_DATA_PACKET:
1475fa31a99SMatthias Ringwald packet_logger_type = in ? 0x09 : 0x08;
1485fa31a99SMatthias Ringwald break;
1499cbc67b4SMatthias Ringwald case HCI_ISO_DATA_PACKET:
1509cbc67b4SMatthias Ringwald packet_logger_type = in ? 0x0d : 0x0c;
1519cbc67b4SMatthias Ringwald break;
1525fa31a99SMatthias Ringwald case HCI_EVENT_PACKET:
1535fa31a99SMatthias Ringwald packet_logger_type = 0x01;
1545fa31a99SMatthias Ringwald break;
1555fa31a99SMatthias Ringwald case LOG_MESSAGE_PACKET:
1565fa31a99SMatthias Ringwald packet_logger_type = 0xfc;
1575fa31a99SMatthias Ringwald break;
1585fa31a99SMatthias Ringwald default:
1595fa31a99SMatthias Ringwald return;
1605fa31a99SMatthias Ringwald }
1615fa31a99SMatthias Ringwald buffer[12] = packet_logger_type;
1625fa31a99SMatthias Ringwald }
1635fa31a99SMatthias Ringwald
hci_dump_setup_header_bluez(uint8_t * buffer,uint32_t tv_sec,uint32_t tv_us,uint8_t packet_type,uint8_t in,uint16_t len)164128d6c99SMatthias Ringwald void hci_dump_setup_header_bluez(uint8_t * buffer, uint32_t tv_sec, uint32_t tv_us, uint8_t packet_type, uint8_t in, uint16_t len){
1654ea43905SMatthias Ringwald little_endian_store_16( buffer, 0u, 1u + len);
1665fa31a99SMatthias Ringwald buffer[2] = in;
1675fa31a99SMatthias Ringwald buffer[3] = 0;
1685fa31a99SMatthias Ringwald little_endian_store_32( buffer, 4, tv_sec);
1695fa31a99SMatthias Ringwald little_endian_store_32( buffer, 8, tv_us);
1705fa31a99SMatthias Ringwald buffer[12] = packet_type;
1715fa31a99SMatthias Ringwald }
172a9b0ec79SMatthias Ringwald
173a9b0ec79SMatthias Ringwald // From https://fte.com/webhelpii/hsu/Content/Technical_Information/BT_Snoop_File_Format.htm
hci_dump_setup_header_btsnoop(uint8_t * buffer,uint32_t ts_usec_high,uint32_t ts_usec_low,uint32_t cumulative_drops,uint8_t packet_type,uint8_t in,uint16_t len)174a9b0ec79SMatthias Ringwald void hci_dump_setup_header_btsnoop(uint8_t * buffer, uint32_t ts_usec_high, uint32_t ts_usec_low, uint32_t cumulative_drops, uint8_t packet_type, uint8_t in, uint16_t len) {
175a9b0ec79SMatthias Ringwald uint32_t packet_flags = 0;
176a9b0ec79SMatthias Ringwald if (in){
177a9b0ec79SMatthias Ringwald packet_flags |= 1;
178a9b0ec79SMatthias Ringwald }
179a9b0ec79SMatthias Ringwald switch (packet_type){
180a9b0ec79SMatthias Ringwald case HCI_COMMAND_DATA_PACKET:
181a9b0ec79SMatthias Ringwald case HCI_EVENT_PACKET:
182a9b0ec79SMatthias Ringwald packet_flags |= 2;
183a9b0ec79SMatthias Ringwald default:
184a9b0ec79SMatthias Ringwald break;
185a9b0ec79SMatthias Ringwald }
186a9b0ec79SMatthias Ringwald big_endian_store_32(buffer, 0, len); // Original Length
187a9b0ec79SMatthias Ringwald big_endian_store_32(buffer, 4, len); // Included Length
188a9b0ec79SMatthias Ringwald big_endian_store_32(buffer, 8, packet_flags); // Packet Flags
189a9b0ec79SMatthias Ringwald big_endian_store_32(buffer, 12, cumulative_drops); // Cumulativ Drops
190a9b0ec79SMatthias Ringwald big_endian_store_32(buffer, 16, ts_usec_high); // Timestamp Microseconds High
191a9b0ec79SMatthias Ringwald big_endian_store_32(buffer, 20, ts_usec_low); // Timestamp Microseconds Low
192a9b0ec79SMatthias Ringwald }
193