xref: /btstack/src/hci_dump.c (revision d96599227022dac90cc65c19dee07fb5e9d833af)
179662672Smatthias.ringwald /*
279662672Smatthias.ringwald  *  hci_dump.c
379662672Smatthias.ringwald  *
479662672Smatthias.ringwald  *  Dump HCI trace in BlueZ's hcidump format
579662672Smatthias.ringwald  *
679662672Smatthias.ringwald  *  Created by Matthias Ringwald on 5/26/09.
779662672Smatthias.ringwald  */
879662672Smatthias.ringwald 
979662672Smatthias.ringwald #include "hci_dump.h"
1079662672Smatthias.ringwald #include "hci.h"
1179662672Smatthias.ringwald #include "hci_transport_h4.h"
1279662672Smatthias.ringwald 
1379662672Smatthias.ringwald #include <fcntl.h>        // open
1479662672Smatthias.ringwald #include <arpa/inet.h>    // hton..
1579662672Smatthias.ringwald #include <strings.h>      // bzero
1679662672Smatthias.ringwald #include <unistd.h>       // write
1779662672Smatthias.ringwald #include <stdio.h>
188b658ebcSmatthias.ringwald #include <sys/time.h>     // for timestamps
1979662672Smatthias.ringwald 
208b658ebcSmatthias.ringwald // BLUEZ hcidump
218b658ebcSmatthias.ringwald typedef struct {
228b658ebcSmatthias.ringwald 	uint16_t	len;
238b658ebcSmatthias.ringwald 	uint8_t		in;
248b658ebcSmatthias.ringwald 	uint8_t		pad;
258b658ebcSmatthias.ringwald 	uint32_t	ts_sec;
268b658ebcSmatthias.ringwald 	uint32_t	ts_usec;
278b658ebcSmatthias.ringwald     uint8_t     packet_type;
288b658ebcSmatthias.ringwald } __attribute__ ((packed)) hcidump_hdr;
2979662672Smatthias.ringwald 
308b658ebcSmatthias.ringwald // APPLE PacketLogger
318b658ebcSmatthias.ringwald typedef struct {
328b658ebcSmatthias.ringwald 	uint32_t	len;
338b658ebcSmatthias.ringwald 	uint32_t	ts_sec;
348b658ebcSmatthias.ringwald 	uint32_t	ts_usec;
358b658ebcSmatthias.ringwald 	uint8_t		type;
368b658ebcSmatthias.ringwald } __attribute__ ((packed)) pktlog_hdr;
378b658ebcSmatthias.ringwald 
388b658ebcSmatthias.ringwald static int dump_file = -1;
398b658ebcSmatthias.ringwald static int dump_format;
408b658ebcSmatthias.ringwald static hcidump_hdr header_bluez;
418b658ebcSmatthias.ringwald static pktlog_hdr  header_packetlogger;
428b658ebcSmatthias.ringwald 
438b658ebcSmatthias.ringwald void hci_dump_open(char *filename, hci_dump_format_t format){
44*d9659922Smatthias.ringwald     if (dump_file < 0) {
4579662672Smatthias.ringwald         dump_file =  open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
468b658ebcSmatthias.ringwald         dump_format = format;
4779662672Smatthias.ringwald     }
48*d9659922Smatthias.ringwald }
4979662672Smatthias.ringwald 
5079662672Smatthias.ringwald void hci_dump_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t len) {
518b658ebcSmatthias.ringwald     if (dump_file < 0) return; // not activated yet
528b658ebcSmatthias.ringwald 
538b658ebcSmatthias.ringwald     // get time
548b658ebcSmatthias.ringwald     struct timeval curr_time;
558b658ebcSmatthias.ringwald     gettimeofday(&curr_time, NULL);
568b658ebcSmatthias.ringwald 
578b658ebcSmatthias.ringwald     switch (dump_format){
588b658ebcSmatthias.ringwald         case HCI_DUMP_BLUEZ:
598b658ebcSmatthias.ringwald             bt_store_16( (uint8_t *) &header_bluez.len, 0, 1 + len);
608b658ebcSmatthias.ringwald             header_bluez.in  = in;
618b658ebcSmatthias.ringwald             header_bluez.pad = 0;
628b658ebcSmatthias.ringwald             bt_store_32( (uint8_t *) &header_bluez.ts_sec,  0, curr_time.tv_sec);
638b658ebcSmatthias.ringwald             bt_store_32( (uint8_t *) &header_bluez.ts_usec, 0, curr_time.tv_usec);
648b658ebcSmatthias.ringwald             header_bluez.packet_type = packet_type;
658b658ebcSmatthias.ringwald             write (dump_file, &header_bluez, sizeof(hcidump_hdr) );
6679662672Smatthias.ringwald             write (dump_file, packet, len );
678b658ebcSmatthias.ringwald             break;
688b658ebcSmatthias.ringwald         case HCI_DUMP_PACKETLOGGER:
698b658ebcSmatthias.ringwald             header_packetlogger.len = htonl( sizeof(pktlog_hdr) - 4 + len);
708b658ebcSmatthias.ringwald             header_packetlogger.ts_sec =  htonl(curr_time.tv_sec);
718b658ebcSmatthias.ringwald             header_packetlogger.ts_usec = htonl(curr_time.tv_usec);
728b658ebcSmatthias.ringwald             switch (packet_type){
738b658ebcSmatthias.ringwald                 case HCI_COMMAND_DATA_PACKET:
748b658ebcSmatthias.ringwald                     header_packetlogger.type = 0x00;
758b658ebcSmatthias.ringwald                     break;
768b658ebcSmatthias.ringwald                 case HCI_ACL_DATA_PACKET:
778b658ebcSmatthias.ringwald                     if (in) {
788b658ebcSmatthias.ringwald                         header_packetlogger.type = 0x03;
798b658ebcSmatthias.ringwald                     } else {
808b658ebcSmatthias.ringwald                         header_packetlogger.type = 0x02;
818b658ebcSmatthias.ringwald                     }
828b658ebcSmatthias.ringwald                     break;
838b658ebcSmatthias.ringwald                 case HCI_EVENT_PACKET:
848b658ebcSmatthias.ringwald                     header_packetlogger.type = 0x01;
858b658ebcSmatthias.ringwald                     break;
868b658ebcSmatthias.ringwald                 default:
878b658ebcSmatthias.ringwald                     return;
888b658ebcSmatthias.ringwald             }
898b658ebcSmatthias.ringwald             write (dump_file, &header_packetlogger, sizeof(pktlog_hdr) );
908b658ebcSmatthias.ringwald             write (dump_file, packet, len );
918b658ebcSmatthias.ringwald     }
9279662672Smatthias.ringwald }
9379662672Smatthias.ringwald 
9479662672Smatthias.ringwald void hci_dump_close(){
9579662672Smatthias.ringwald     close(dump_file);
96*d9659922Smatthias.ringwald     dump_file = -1;
9779662672Smatthias.ringwald }
9879662672Smatthias.ringwald 
99