1#!/usr/bin/env python 2# BlueKitchen GmbH (c) 2014 3 4# convert log output to PacketLogger format 5# can be viewed with Wireshark 6 7# APPLE PacketLogger 8# typedef struct { 9# uint32_t len; 10# uint32_t ts_sec; 11# uint32_t ts_usec; 12# uint8_t type; // 0xfc for note 13# } 14 15import re 16import sys 17import time 18import os 19 20packet_counter = 0 21last_time = None 22 23def chop(line, prefix): 24 if line.startswith(prefix): 25 return line[len(prefix):] 26 return None 27 28def str2hex(value): 29 if value: 30 return int(value, 16) 31 return None 32 33def arrayForNet32(value): 34 return bytearray([value >> 24, (value >> 16) & 0xff, (value >> 8) & 0xff, value & 0xff]) 35 36def generateTimestamp(t): 37 global last_time 38 global packet_counter 39 40 # use last_time if time missing for this entry 41 if not t: 42 t = last_time 43 if t: 44 last_time = t 45 # handle ms 46 try: 47 (t1, t2) = t.split('.') 48 if t1 and t2: 49 t_obj = time.strptime(t1, "%Y-%m-%d %H:%M:%S") 50 tv_sec = int(time.mktime(t_obj)) 51 tv_usec = int(t2) * 1000 52 return (tv_sec, tv_usec) 53 except ValueError: 54 # print 'Cannot parse time', t 55 pass 56 packet_counter += 1 57 return (packet_counter, 0) 58 59def dumpPacket(fout, timestamp, type, data): 60 length = 9 + len(data) 61 (tv_sec, tv_usec) = generateTimestamp(timestamp) 62 fout.write(arrayForNet32(length)) 63 fout.write(arrayForNet32(tv_sec)) 64 fout.write(arrayForNet32(tv_usec)) 65 fout.write(bytearray([type])) 66 fout.write(data) 67 68def handleHexPacket(fout, timestamp, type, text): 69 try: 70 data = bytearray(list(map(str2hex, text.strip().split()))) 71 dumpPacket(fout, timestamp, type, data) 72 except TypeError: 73 print('Cannot parse hexdump', text.strip()) 74 75if len(sys.argv) == 1: 76 print('BTstack Console to PacketLogger converter') 77 print('Copyright 2014, BlueKitchen GmbH') 78 print('') 79 print('Usage: ', sys.argv[0], 'asci-log-file.txt [hci_dump.pkgl]') 80 print('Converted hci_dump.pklg can be viewed with Wireshark and OS X PacketLogger') 81 exit(0) 82 83infile = sys.argv[1] 84outfile = os.path.splitext(infile)[0] + ".pklg" 85if len(sys.argv) > 2: 86 outfile = sys.argv[2] 87 88# with open(outfile, 'w') as fout: 89with open (outfile, 'wb') as fout: 90 with open (infile, 'rt') as fin: 91 packet_counter = 0 92 for line in fin: 93 timestamp = None 94 parts = parts = re.match('\[(.*)\] (.*)', line) 95 if parts and len(parts.groups()) == 2: 96 (timestamp, line) = parts.groups() 97 rest = chop(line,'CMD => ') 98 if rest: 99 handleHexPacket(fout, timestamp, 0, rest) 100 continue 101 rest = chop(line,'EVT <= ') 102 if rest: 103 handleHexPacket(fout, timestamp, 1, rest) 104 continue 105 rest = chop(line,'ACL => ') 106 if rest: 107 handleHexPacket(fout, timestamp, 2, rest) 108 continue 109 rest = chop(line,'ACL <= ') 110 if rest: 111 handleHexPacket(fout, timestamp, 3, rest) 112 continue 113 rest = chop(line,'LOG -- ') 114 if rest: 115 line = rest 116 dumpPacket(fout, timestamp, 0xfc, line.encode('ascii')) 117