xref: /btstack/src/hci_dump.c (revision 8b658ebcf868c8176b3f7e17042b1385b71e098d)
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     dump_file =  open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
45     dump_format = format;
46 }
47 
48 void hci_dump_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t len) {
49     if (dump_file < 0) return; // not activated yet
50 
51     // get time
52     struct timeval curr_time;
53     gettimeofday(&curr_time, NULL);
54 
55     switch (dump_format){
56         case HCI_DUMP_BLUEZ:
57             bt_store_16( (uint8_t *) &header_bluez.len, 0, 1 + len);
58             header_bluez.in  = in;
59             header_bluez.pad = 0;
60             bt_store_32( (uint8_t *) &header_bluez.ts_sec,  0, curr_time.tv_sec);
61             bt_store_32( (uint8_t *) &header_bluez.ts_usec, 0, curr_time.tv_usec);
62             header_bluez.packet_type = packet_type;
63             write (dump_file, &header_bluez, sizeof(hcidump_hdr) );
64             write (dump_file, packet, len );
65             break;
66         case HCI_DUMP_PACKETLOGGER:
67             header_packetlogger.len = htonl( sizeof(pktlog_hdr) - 4 + len);
68             header_packetlogger.ts_sec =  htonl(curr_time.tv_sec);
69             header_packetlogger.ts_usec = htonl(curr_time.tv_usec);
70             switch (packet_type){
71                 case HCI_COMMAND_DATA_PACKET:
72                     header_packetlogger.type = 0x00;
73                     break;
74                 case HCI_ACL_DATA_PACKET:
75                     if (in) {
76                         header_packetlogger.type = 0x03;
77                     } else {
78                         header_packetlogger.type = 0x02;
79                     }
80                     break;
81                 case HCI_EVENT_PACKET:
82                     header_packetlogger.type = 0x01;
83                     break;
84                 default:
85                     return;
86             }
87             write (dump_file, &header_packetlogger, sizeof(pktlog_hdr) );
88             write (dump_file, packet, len );
89     }
90 }
91 
92 void hci_dump_close(){
93     close(dump_file);
94 }
95 
96