xref: /btstack/platform/posix/hci_dump_posix_fs.c (revision 128d6c999a4a7cc321497ddbaddd9cd6c8d1edef)
1*128d6c99SMatthias Ringwald /*
2*128d6c99SMatthias Ringwald  * Copyright (C) 2014-2020 BlueKitchen GmbH
3*128d6c99SMatthias Ringwald  *
4*128d6c99SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*128d6c99SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*128d6c99SMatthias Ringwald  * are met:
7*128d6c99SMatthias Ringwald  *
8*128d6c99SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*128d6c99SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*128d6c99SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*128d6c99SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*128d6c99SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*128d6c99SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*128d6c99SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*128d6c99SMatthias Ringwald  *    from this software without specific prior written permission.
16*128d6c99SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*128d6c99SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*128d6c99SMatthias Ringwald  *    monetary gain.
19*128d6c99SMatthias Ringwald  *
20*128d6c99SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*128d6c99SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*128d6c99SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*128d6c99SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24*128d6c99SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*128d6c99SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*128d6c99SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*128d6c99SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*128d6c99SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*128d6c99SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*128d6c99SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*128d6c99SMatthias Ringwald  * SUCH DAMAGE.
32*128d6c99SMatthias Ringwald  *
33*128d6c99SMatthias Ringwald  * Please inquire about commercial licensing options at
34*128d6c99SMatthias Ringwald  * [email protected]
35*128d6c99SMatthias Ringwald  *
36*128d6c99SMatthias Ringwald  */
37*128d6c99SMatthias Ringwald 
38*128d6c99SMatthias Ringwald #define BTSTACK_FILE__ "hci_dump_posix_fs.c"
39*128d6c99SMatthias Ringwald 
40*128d6c99SMatthias Ringwald /*
41*128d6c99SMatthias Ringwald  *  hci_dump_posix_fs.c
42*128d6c99SMatthias Ringwald  *
43*128d6c99SMatthias Ringwald  *  Dump HCI trace in various formats into a file:
44*128d6c99SMatthias Ringwald  *
45*128d6c99SMatthias Ringwald  *  - BlueZ's hcidump format
46*128d6c99SMatthias Ringwald  *  - Apple's PacketLogger
47*128d6c99SMatthias Ringwald  *  - stdout hexdump
48*128d6c99SMatthias Ringwald  *
49*128d6c99SMatthias Ringwald  */
50*128d6c99SMatthias Ringwald 
51*128d6c99SMatthias Ringwald #include "btstack_config.h"
52*128d6c99SMatthias Ringwald 
53*128d6c99SMatthias Ringwald // enable POSIX functions (needed for -std=c99)
54*128d6c99SMatthias Ringwald #define _POSIX_C_SOURCE 200809
55*128d6c99SMatthias Ringwald 
56*128d6c99SMatthias Ringwald #include "hci_dump_posix_fs.h"
57*128d6c99SMatthias Ringwald 
58*128d6c99SMatthias Ringwald #include "btstack_debug.h"
59*128d6c99SMatthias Ringwald #include "hci_cmd.h"
60*128d6c99SMatthias Ringwald 
61*128d6c99SMatthias Ringwald #include <time.h>
62*128d6c99SMatthias Ringwald #include <stdio.h>        // printf
63*128d6c99SMatthias Ringwald #include <fcntl.h>        // open
64*128d6c99SMatthias Ringwald #include <unistd.h>       // write
65*128d6c99SMatthias Ringwald #include <errno.h>        // errno
66*128d6c99SMatthias Ringwald #include <sys/time.h>     // for timestamps
67*128d6c99SMatthias Ringwald #include <sys/stat.h>     // file modes
68*128d6c99SMatthias Ringwald 
69*128d6c99SMatthias Ringwald static int  dump_file = -1;
70*128d6c99SMatthias Ringwald static int  dump_format;
71*128d6c99SMatthias Ringwald static char log_message_buffer[256];
72*128d6c99SMatthias Ringwald 
73*128d6c99SMatthias Ringwald static void hci_dump_posix_fs_reset(void){
74*128d6c99SMatthias Ringwald     btstack_assert(dump_file >= 0);
75*128d6c99SMatthias Ringwald     (void) lseek(dump_file, 0, SEEK_SET);
76*128d6c99SMatthias Ringwald     (void) ftruncate(dump_file, 0);
77*128d6c99SMatthias Ringwald }
78*128d6c99SMatthias Ringwald 
79*128d6c99SMatthias Ringwald static void hci_dump_posix_fs_log_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t len) {
80*128d6c99SMatthias Ringwald     if (dump_file < 0) return;
81*128d6c99SMatthias Ringwald 
82*128d6c99SMatthias Ringwald     static union {
83*128d6c99SMatthias Ringwald         uint8_t header_bluez[HCI_DUMP_HEADER_SIZE_BLUEZ];
84*128d6c99SMatthias Ringwald         uint8_t header_packetlogger[HCI_DUMP_HEADER_SIZE_PACKETLOGGER];
85*128d6c99SMatthias Ringwald     } header;
86*128d6c99SMatthias Ringwald 
87*128d6c99SMatthias Ringwald     uint32_t tv_sec = 0;
88*128d6c99SMatthias Ringwald     uint32_t tv_us  = 0;
89*128d6c99SMatthias Ringwald 
90*128d6c99SMatthias Ringwald     // get time
91*128d6c99SMatthias Ringwald     struct timeval curr_time;
92*128d6c99SMatthias Ringwald     gettimeofday(&curr_time, NULL);
93*128d6c99SMatthias Ringwald     tv_sec = curr_time.tv_sec;
94*128d6c99SMatthias Ringwald     tv_us  = curr_time.tv_usec;
95*128d6c99SMatthias Ringwald 
96*128d6c99SMatthias Ringwald     uint16_t header_len = 0;
97*128d6c99SMatthias Ringwald     switch (dump_format){
98*128d6c99SMatthias Ringwald         case HCI_DUMP_BLUEZ:
99*128d6c99SMatthias Ringwald             hci_dump_setup_header_bluez(header.header_bluez, tv_sec, tv_us, packet_type, in, len);
100*128d6c99SMatthias Ringwald             header_len = HCI_DUMP_HEADER_SIZE_BLUEZ;
101*128d6c99SMatthias Ringwald             break;
102*128d6c99SMatthias Ringwald         case HCI_DUMP_PACKETLOGGER:
103*128d6c99SMatthias Ringwald             hci_dump_setup_header_packetlogger(header.header_packetlogger, tv_sec, tv_us, packet_type, in, len);
104*128d6c99SMatthias Ringwald             header_len = HCI_DUMP_HEADER_SIZE_PACKETLOGGER;
105*128d6c99SMatthias Ringwald             break;
106*128d6c99SMatthias Ringwald         default:
107*128d6c99SMatthias Ringwald             return;
108*128d6c99SMatthias Ringwald     }
109*128d6c99SMatthias Ringwald 
110*128d6c99SMatthias Ringwald     (void) write(dump_file, &header, header_len);
111*128d6c99SMatthias Ringwald     (void) write(dump_file, packet, len );
112*128d6c99SMatthias Ringwald }
113*128d6c99SMatthias Ringwald 
114*128d6c99SMatthias Ringwald static void hci_dump_posix_fs_log_message(const char * format, va_list argptr){
115*128d6c99SMatthias Ringwald     if (dump_file < 0) return;
116*128d6c99SMatthias Ringwald     int len = vsnprintf(log_message_buffer, sizeof(log_message_buffer), format, argptr);
117*128d6c99SMatthias Ringwald     hci_dump_posix_fs_log_packet(LOG_MESSAGE_PACKET, 0, (uint8_t*) log_message_buffer, len);
118*128d6c99SMatthias Ringwald }
119*128d6c99SMatthias Ringwald 
120*128d6c99SMatthias Ringwald // returns system errno
121*128d6c99SMatthias Ringwald int hci_dump_posix_fs_open(const char *filename, hci_dump_format_t format){
122*128d6c99SMatthias Ringwald     btstack_assert(format == HCI_DUMP_BLUEZ || format == HCI_DUMP_PACKETLOGGER);
123*128d6c99SMatthias Ringwald 
124*128d6c99SMatthias Ringwald     dump_format = format;
125*128d6c99SMatthias Ringwald     int oflags = O_WRONLY | O_CREAT | O_TRUNC;
126*128d6c99SMatthias Ringwald #ifdef _WIN32
127*128d6c99SMatthias Ringwald     oflags |= O_BINARY;
128*128d6c99SMatthias Ringwald #endif
129*128d6c99SMatthias Ringwald     dump_file = open(filename, oflags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
130*128d6c99SMatthias Ringwald     if (dump_file < 0){
131*128d6c99SMatthias Ringwald         printf("failed to open file %s, errno = %d\n", filename, errno);
132*128d6c99SMatthias Ringwald         return errno;
133*128d6c99SMatthias Ringwald     }
134*128d6c99SMatthias Ringwald     return 0;
135*128d6c99SMatthias Ringwald }
136*128d6c99SMatthias Ringwald 
137*128d6c99SMatthias Ringwald void hci_dump_posix_fs_close(void){
138*128d6c99SMatthias Ringwald     close(dump_file);
139*128d6c99SMatthias Ringwald     dump_file = -1;
140*128d6c99SMatthias Ringwald }
141*128d6c99SMatthias Ringwald 
142*128d6c99SMatthias Ringwald const hci_dump_t * hci_dump_posix_fs_get_instance(void){
143*128d6c99SMatthias Ringwald     static const hci_dump_t hci_dump_instance = {
144*128d6c99SMatthias Ringwald         // void (*reset)(void);
145*128d6c99SMatthias Ringwald         &hci_dump_posix_fs_reset,
146*128d6c99SMatthias Ringwald         // void (*log_packet)(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t len);
147*128d6c99SMatthias Ringwald         &hci_dump_posix_fs_log_packet,
148*128d6c99SMatthias Ringwald         // void (*log_message)(int log_level, const char * format, va_list argptr);
149*128d6c99SMatthias Ringwald         &hci_dump_posix_fs_log_message,
150*128d6c99SMatthias Ringwald     };
151*128d6c99SMatthias Ringwald     return &hci_dump_instance;
152*128d6c99SMatthias Ringwald }
153