xref: /btstack/src/hci_dump.c (revision edd159b3a19b50d3ca5904b7fc7d2688749b8529)
1 /*
2  * Copyright (C) 2014 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define BTSTACK_FILE__ "hci_dump.c"
39 
40 /*
41  *  hci_dump.c
42  *
43  *  Dump HCI trace in various formats based on platform-specific implementation
44  */
45 
46 #include "btstack_config.h"
47 #include "btstack_debug.h"
48 #include "btstack_bool.h"
49 #include "btstack_util.h"
50 
51 static const hci_dump_t * hci_dump_implementation;
52 static int  max_nr_packets;
53 static int  nr_packets;
54 static bool packet_log_enabled;
55 
56 // levels: debug, info, error
57 static bool log_level_enabled[3] = { 1, 1, 1};
58 
59 static bool hci_dump_log_level_active(int log_level){
60     if (hci_dump_implementation == NULL) return false;
61     if (log_level < HCI_DUMP_LOG_LEVEL_DEBUG) return false;
62     if (log_level > HCI_DUMP_LOG_LEVEL_ERROR) return false;
63     return log_level_enabled[log_level];
64 }
65 
66 void hci_dump_init(const hci_dump_t * hci_dump_impl){
67     max_nr_packets = -1;
68     nr_packets = 0;
69     hci_dump_implementation = hci_dump_impl;
70     packet_log_enabled = true;
71 }
72 
73 void hci_dump_set_max_packets(int packets){
74     max_nr_packets = packets;
75 }
76 
77 void hci_dump_enable_packet_log(bool enabled){
78     packet_log_enabled = enabled;
79 }
80 
81 void hci_dump_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t len) {
82     if (hci_dump_implementation == NULL) {
83         return;
84     }
85     if (packet_log_enabled == false) {
86         return;
87     }
88 
89     if (max_nr_packets > 0){
90         if ((nr_packets >= max_nr_packets) && (hci_dump_implementation->reset != NULL)) {
91             nr_packets = 0;
92             (*hci_dump_implementation->reset)();
93         }
94         nr_packets++;
95     }
96     (*hci_dump_implementation->log_packet)(packet_type, in, packet, len);
97 }
98 
99 void hci_dump_log(int log_level, const char * format, ...){
100     if (!hci_dump_log_level_active(log_level)) return;
101 
102     va_list argptr;
103     va_start(argptr, format);
104     (*hci_dump_implementation->log_message)(log_level, format, argptr);
105     va_end(argptr);
106 }
107 
108 #ifdef __AVR__
109 void hci_dump_log_P(int log_level, PGM_P format, ...){
110     if (!hci_dump_log_level_active(log_level)) return;
111 
112     va_list argptr;
113     va_start(argptr, format);
114     (*hci_dump_implementation->log_message_P)(log_level, format, argptr);
115     va_end(argptr);
116 }
117 #endif
118 
119 void hci_dump_btstack_event(const uint8_t *packet, uint16_t len){
120 #ifdef ENABLE_LOG_BTSTACK_EVENTS
121     hci_dump_packet(HCI_EVENT_PACKET, 1, packet, size);
122 #else
123     UNUSED(packet);
124     UNUSED(len);
125 #endif
126 }
127 
128 void hci_dump_enable_log_level(int log_level, int enable){
129     if (log_level < HCI_DUMP_LOG_LEVEL_DEBUG) return;
130     if (log_level > HCI_DUMP_LOG_LEVEL_ERROR) return;
131     log_level_enabled[log_level] = enable != 0;
132 }
133 
134 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){
135     big_endian_store_32( buffer, 0, HCI_DUMP_HEADER_SIZE_PACKETLOGGER - 4 + len);
136     big_endian_store_32( buffer, 4, tv_sec);
137     big_endian_store_32( buffer, 8, tv_us);
138     uint8_t packet_logger_type = 0;
139     switch (packet_type){
140         case HCI_COMMAND_DATA_PACKET:
141             packet_logger_type = 0x00;
142             break;
143         case HCI_ACL_DATA_PACKET:
144             packet_logger_type = in ? 0x03 : 0x02;
145             break;
146         case HCI_SCO_DATA_PACKET:
147             packet_logger_type = in ? 0x09 : 0x08;
148             break;
149         case HCI_ISO_DATA_PACKET:
150             packet_logger_type = in ? 0x0d : 0x0c;
151             break;
152         case HCI_EVENT_PACKET:
153             packet_logger_type = 0x01;
154             break;
155         case LOG_MESSAGE_PACKET:
156             packet_logger_type = 0xfc;
157             break;
158         default:
159             return;
160     }
161     buffer[12] = packet_logger_type;
162 }
163 
164 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){
165     little_endian_store_16( buffer, 0u, 1u + len);
166     buffer[2] = in;
167     buffer[3] = 0;
168     little_endian_store_32( buffer, 4, tv_sec);
169     little_endian_store_32( buffer, 8, tv_us);
170     buffer[12] = packet_type;
171 }
172 
173 // From https://fte.com/webhelpii/hsu/Content/Technical_Information/BT_Snoop_File_Format.htm
174 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) {
175     uint32_t packet_flags = 0;
176     if (in){
177         packet_flags |= 1;
178     }
179     switch (packet_type){
180         case HCI_COMMAND_DATA_PACKET:
181         case HCI_EVENT_PACKET:
182             packet_flags |= 2;
183         default:
184             break;
185     }
186     big_endian_store_32(buffer,  0, len);               // Original Length
187     big_endian_store_32(buffer,  4, len);               // Included Length
188     big_endian_store_32(buffer,  8, packet_flags);      // Packet Flags
189     big_endian_store_32(buffer, 12, cumulative_drops);  // Cumulativ Drops
190     big_endian_store_32(buffer, 16, ts_usec_high);            // Timestamp Microseconds High
191     big_endian_store_32(buffer, 20, ts_usec_low);             // Timestamp Microseconds Low
192 }
193