|
| 1 | +''' |
| 2 | +Convert ArduinoBLE debug files into Btsnoop files ready to be analyzed using wireshark or hcidump |
| 3 | +Btsnoop file format reference |
| 4 | + https://www.fte.com/WebHelpII/Sodera/Content/Technical_Information/BT_Snoop_File_Format.htm |
| 5 | +''' |
| 6 | + |
| 7 | +import os |
| 8 | +import argparse |
| 9 | + |
| 10 | +DEBUG = False |
| 11 | + |
| 12 | +parser = argparse.ArgumentParser() |
| 13 | +parser.add_argument('-i', dest='inputPath', type=str, required=True, help='input file containing debug log') |
| 14 | +parser.add_argument('-o', dest='outputPath', type=str, required=True, help='result file that will contain the btsnoop encoded debug file') |
| 15 | +args = parser.parse_args() |
| 16 | + |
| 17 | +# Extract only hci debug messages |
| 18 | +def extractHCIDebugPrint(inputPath, outputPath): |
| 19 | + inputFile = open(inputPath, 'r') |
| 20 | + outputFile = open(outputPath, 'w') |
| 21 | + for inputLine in inputFile: |
| 22 | + lineItems = inputLine.split() |
| 23 | + if (len(lineItems) < 7) or (lineItems[1] != "->") or (lineItems[2] != "HCI"): |
| 24 | + if (len(lineItems) < 4) or (lineItems[0] != "HCI") or ((lineItems[3] != "<-") and (lineItems[3] != "->")): |
| 25 | + continue |
| 26 | + outputFile.write(inputLine) |
| 27 | + outputFile.close() |
| 28 | + |
| 29 | +# Return packet in btsnoop format |
| 30 | +def buildBinaryPacket(hciMessage, hciDirection, hciType): |
| 31 | + commandFlag = 1 if (hciType == "COMMAND" or hciType == "EVENT") else 0 |
| 32 | + directionFlag = 0 if (hciDirection == "TX") else 1 |
| 33 | + flagHex = ("0" * 7) + str((commandFlag * 2) + directionFlag) |
| 34 | + timestampHex = "0" * 16 |
| 35 | + packetDropHex = "0" * 8 |
| 36 | + dataLengthHex = format( (int(len(hciMessage) / 2)), 'x') |
| 37 | + packetLengthHex = ("0" * (8 - len(dataLengthHex))) + dataLengthHex |
| 38 | + binaryPacket = bytearray.fromhex(packetLengthHex + packetLengthHex + flagHex + packetDropHex + timestampHex + hciMessage) |
| 39 | + if DEBUG: |
| 40 | + print(len(hciMessage)) |
| 41 | + print(dataLengthHex) |
| 42 | + print(packetLengthHex) |
| 43 | + print(flagHex) |
| 44 | + print('\n') |
| 45 | + return binaryPacket |
| 46 | + |
| 47 | +def buildBinaryHeader(): |
| 48 | + defaultHeader = "6274736e6f6f700000000001000003ea" |
| 49 | + binaryHeader = bytearray.fromhex(defaultHeader) |
| 50 | + return binaryHeader |
| 51 | + |
| 52 | +def convertToBtsnoop(inputPath, outputPath): |
| 53 | + # Open output file and write the Btsnoop header |
| 54 | + outputFile = open(outputPath,'wb') |
| 55 | + header = buildBinaryHeader() |
| 56 | + outputFile.write(header) |
| 57 | + |
| 58 | + # Open input file containing HCI debug packets |
| 59 | + inputFile = open(inputPath, 'r') |
| 60 | + for inputLine in inputFile: |
| 61 | + lineItems = inputLine.split() |
| 62 | + # For a safer script, do not use indexes but look for symbols in the line |
| 63 | + baseIndex = lineItems.index("HCI") |
| 64 | + hciMessage = lineItems[baseIndex + 4] |
| 65 | + hciDirection = lineItems[baseIndex + 2] |
| 66 | + hciType = lineItems[baseIndex + 1] |
| 67 | + # Build and write the encoded line |
| 68 | + btsnoopPacket = buildBinaryPacket(hciMessage, hciDirection, hciType) |
| 69 | + outputFile.write(btsnoopPacket) |
| 70 | + if DEBUG: |
| 71 | + print(hciDirection) |
| 72 | + print(hciMessage) |
| 73 | + print(hciType) |
| 74 | + print('\n') |
| 75 | + outputFile.close() |
| 76 | + |
| 77 | +inputPath = args.inputPath |
| 78 | +outputPath = args.outputPath |
| 79 | +tempFile = "temp-debug-print.txt" |
| 80 | +# Run |
| 81 | +extractHCIDebugPrint(inputPath,tempFile) |
| 82 | +convertToBtsnoop(tempFile, outputPath) |
| 83 | +# Delete temp file |
| 84 | +os.remove(tempFile) |
| 85 | + |
0 commit comments