xref: /btstack/src/hci_dump.c (revision 5e0fa50d748b1efe512bf0a4de9b4be3297fa05b)
1 /*
2  *  hci_dump.c
3  *
4  *  Dump HCI trace in BlueZ's hcidump format
5  *
6  *  Created by Matthias Ringwald on 5/26/09.
7  */
8 
9 #include "hci_dump.h"
10 #include "hci.h"
11 #include "hci_transport_h4.h"
12 
13 #include <fcntl.h>        // open
14 #include <arpa/inet.h>    // hton..
15 #include <strings.h>      // bzero
16 #include <unistd.h>       // write
17 #include <stdio.h>
18 #include <sys/time.h>     // for timestamps
19 
20 // BLUEZ hcidump
21 typedef struct {
22 	uint16_t	len;
23 	uint8_t		in;
24 	uint8_t		pad;
25 	uint32_t	ts_sec;
26 	uint32_t	ts_usec;
27     uint8_t     packet_type;
28 } __attribute__ ((packed)) hcidump_hdr;
29 
30 // APPLE PacketLogger
31 typedef struct {
32 	uint32_t	len;
33 	uint32_t	ts_sec;
34 	uint32_t	ts_usec;
35 	uint8_t		type;
36 } __attribute__ ((packed)) pktlog_hdr;
37 
38 static int dump_file = -1;
39 static int dump_format;
40 static hcidump_hdr header_bluez;
41 static pktlog_hdr  header_packetlogger;
42 
43 void hci_dump_open(char *filename, hci_dump_format_t format){
44     if (dump_file < 0) {
45         dump_file =  open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
46         dump_format = format;
47     }
48 }
49 
50 void hci_dump_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t len) {
51     if (dump_file < 0) return; // not activated yet
52 
53     // get time
54     struct timeval curr_time;
55     gettimeofday(&curr_time, NULL);
56 
57     switch (dump_format){
58         case HCI_DUMP_BLUEZ:
59             bt_store_16( (uint8_t *) &header_bluez.len, 0, 1 + len);
60             header_bluez.in  = in;
61             header_bluez.pad = 0;
62             bt_store_32( (uint8_t *) &header_bluez.ts_sec,  0, curr_time.tv_sec);
63             bt_store_32( (uint8_t *) &header_bluez.ts_usec, 0, curr_time.tv_usec);
64             header_bluez.packet_type = packet_type;
65             write (dump_file, &header_bluez, sizeof(hcidump_hdr) );
66             write (dump_file, packet, len );
67             break;
68         case HCI_DUMP_PACKETLOGGER:
69             header_packetlogger.len = htonl( sizeof(pktlog_hdr) - 4 + len);
70             header_packetlogger.ts_sec =  htonl(curr_time.tv_sec);
71             header_packetlogger.ts_usec = htonl(curr_time.tv_usec);
72             switch (packet_type){
73                 case HCI_COMMAND_DATA_PACKET:
74                     header_packetlogger.type = 0x00;
75                     break;
76                 case HCI_ACL_DATA_PACKET:
77                     if (in) {
78                         header_packetlogger.type = 0x03;
79                     } else {
80                         header_packetlogger.type = 0x02;
81                     }
82                     break;
83                 case HCI_EVENT_PACKET:
84                     header_packetlogger.type = 0x01;
85                     break;
86                 default:
87                     return;
88             }
89             write (dump_file, &header_packetlogger, sizeof(pktlog_hdr) );
90             write (dump_file, packet, len );
91     }
92 }
93 
94 void hci_dump_close(){
95     close(dump_file);
96     dump_file = -1;
97 }
98 
99