This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Packet Sniffer Format (PSD) for bluetooth

Other Parts Discussed in Thread: CC2540

I have read the document about PSD files, but i haven't seen how is stored the information on the BLE channel used by the packet.

I also have a question about the timestamp field (8 octets field), the value in the PSD file should be divided by some clock value to get the time in microseconds. From what i can observe the ratio between the file and the value displayed by the packet snifer is about 419.4

Have I missed some documentation addendum?

Thanks for any pointer

Laurent

  • Laurent von Allmen said:
    I have read the document about PSD files, but i haven't seen how is stored the information on the BLE channel used by the packet.

    In the .psd file, byte 13 is the length byte. The BLE raw data is placed in byte 14 and out. This information should contain the address information, if available.

    Laurent von Allmen said:
    I also have a question about the timestamp field (8 octets field), the value in the PSD file should be divided by some clock value to get the time in microseconds. From what i can observe the ratio between the file and the value displayed by the packet snifer is about 419.4

    For CC2540, you must divide the .psd timestamp value with 32 (The CC2540EM runs at 32 MHz).

    Hope this helps.

    Br,
    ABO 

  • Thank you for the clarification. I have found that the radio channel is stored in the last byte of the array defined by the length at byte 13. This octet is holding as far as I have seen 0x80 + channelNumber.

    * byte [0] – Packet Information
    * bytes [1-4] –  Packet number (LSB first)
    * byte [5-12] – Timestamp (microseconds, LSB first)
    * byte [13] Packet length. The packet length will include 2 bytes for FCS if bit 0 in the Packet Information is set
    * byte [12+Packet length] – RSSI
    * byte [13+Packet length] – 0x80 + channelNumber

    The three byte before RSSI are holding the CRC

    Best regards

    Laurent 

  • What is the required divisor for CC2540 when sniffing Bluetooth Low Energy packets using 2.16.3.0?  The closest number that I've found is 419.43!!!  But that number does not work with all 'timestamps'.

    Here is a screenshot with the raw values (LSB first, I know) and with the TI Sniffer's interpretation:

    This is the code that I'm using to parse the .psd file:

    import sys
    import struct

    psd = struct.Struct("< B I Q B")

    first_timestamp_us = 0

    last_timestamp_us = 0

    with open(sys.argv[1], "rb") as fp:

       while True:

          data = fp.read(271)

          if len(data) == 271:

             (packet_info, packet_number, timestamp, packet_length) = psd.unpack(data[0:14])
             packet = data[14:(14 + packet_length)]

             if 0 == first_timestamp_us:
                first_timestamp_us = timestamp
                timestamp = 0
             else:
                timestamp = timestamp - first_timestamp_us

             print("%2x %6u %12d [%3u]" % (packet_info, packet_number, timestamp, packet_length))
             last_timestamp_us = timestamp

          else:
             print("Short read: %d" % (len(data)))
             break


  • The time stamp format for the CC2540 sniffer is a bit tricky. Here's what you need to do:

    uint64_t timeLo = rawTimestamp & 0xFFFF;

    uint64_t timeHi = (rawTimestamp >> 16);

    uint64_t timeStamp = timeHi*5000 + timeLo;

    uint64_t timeStampUs = timeStamp / 32;

     

  • Hi M!

    I can confirm that the formula works.

    Here is the updated script, just in case it might be useful to somebody:

    import sys
    import struct

    psd = struct.Struct("< B I Q B")

    first_timestamp_us = 0
    last_timestamp_us = 0

    with open(sys.argv[1], "rb") as fp:

       while True:

          data = fp.read(271)

          if len(data) == 271:

             (packet_info, packet_number, raw_timestamp, packet_length) = psd.unpack(data[0:14])
             packet = data[14:(14 + packet_length)]

             time_lo = raw_timestamp & 0xFFFF
             time_hi = raw_timestamp >> 16
             timestamp = (time_hi * 5000 + time_lo) >> 5

             if 0 == first_timestamp_us:
                first_timestamp_us = timestamp
                timestamp = 0
             else:
                timestamp = timestamp - first_timestamp_us

             print("%2x %6u %12dus (+%8.3fms) [%3u]" % (packet_info, packet_number, timestamp, (timestamp - last_timestamp_us) / 1000.0, packet_length))
             last_timestamp_us = timestamp

          else:
             if len(data):
                print("Short read: %d" % (len(data)))
             break


  • Hello,

    Has any one noticed that Packet Sniffer PSD from CC2540 USB dongle is not strictly following packet definitions in the Packet Sniffer Instruction Manual? Or am I the only person who finds this confusing?

    Here is one piece of valid data from PSD files:

    0x0 0x4f 0x1 0x0 0x0 0x5e 0xc 0xe8 0xc5 0x4 0x0 0x0 0x0 0x2d 0xd6 0xbe 0x89 0x8e 0x0 0x22 0x32 0x15 0x0 0x61 0x2 0x0 0x2 0x1 0x6 0x7 0x3 0x3 0x18 0x2 0x18 0x4 0x18 0x3 0x19 0x0 0x2 0x2 0xa 0xfe 0x9 0x9 0x41 0x53 0x2d 0x44 0x31 0x35 0x33 0x32 0x64 0xcb 0x54 0x20 0xa6 0x54 0x6f (all zeros onwards...)

    For readability, I dissected the data as follows:

    0x0 :packet information
    0x4f 0x1 0x0 0x0 :packet no
    0x5e 0xc 0xe8 0xc5 0x4 0x0 0x0 0x0 :timestamp
    0x2d :length = 45
    0xd6 0xbe 0x89 0x8e 0x0 0x22 0x32 0x15 0x0 0x61 0x2 0x0 0x2 0x1 0x6 0x7 0x3 0x3 0x18 0x2 0x18 0x4 0x18 0x3 0x19 0x0 0x2 0x2 0xa 0xfe 0x9 0x9 0x41 0x53 0x2d 0x44 0x31 0x35 0x33 0x32 0x64 0xcb 0x54 0x20 0xa6 : As packet info bit zero is 0, these 45 bytes should be the payload
    0x54 0x6f : This should be the two bytes of FCS.
    (all zeros onwards...)

    Here FCS indicates that CRC is not OK as the highest bit of FCS Byte 2 is zero.

    But the packet sniffer shows that this packet is CRC OK. 

    Here is a piece of invalid data:

    0x0 0x4e 0x1 0x0 0x0 0x18 0xd 0x47 0xc4 0x4 0x0 0x0 0x0 0x2d 0xd6 0xbe 0x89 0x8e 0x0 0x22 0x32 0x15 0x0 0x61 0x2 0x0 0x64 0x1 0x6 0x7 0x3 0x3 0x18 0x2 0x18 0x4 0x18 0x3 0x19 0x0 0x2 0x2 0xa 0xfe 0x9 0x9 0x41 0x53 0x2d 0x44 0x31 0x35 0x33 0x32 0x64 0xcb 0x54 0x21 0x26 0x54 0x6f (all zeros onwards...)

    It turns out that, the packet sniffer is using the last two bytes inside the actual payload as FCS (as highlighted in the above invalid data) But bit zero of packet information indicates that the length doesn't include FCS right?

    Thanks for any advice.

    EDIT. I attached my PSD file4405.sniff.data.psd.

    YJ

  • Hi YJ,

    You assume that the packet record in the .psd file is zeroed-out for every packet. This is not true, so there might be some left-over bytes from another packet at the end of the stored packet. This means you have to use the total packet length byte and the length byte in the BLE packet header to properly parse the content:

    Here's the correct parsed data

    0x0 : Packet information
    0x4f 0x1 0x0 0x0 : Packet number
    0x5e 0xc 0xe8 0xc5 0x4 0x0 0x0 0x0 : Timestamp
    0x2d : Packet sniffer payload length = 45 --> This is the number of payload bytes in the "packet sniffer packet"
    0xd6 0xbe 0x89 0x8e : (4) BLE Access Address/Sync Word
    0x0 0x22 : (2) BLE Header, indicating a BLE packet of 34 bytes
    0x32 0x15 0x0 0x61 0x2 0x0 0x2 0x1
    0x6 0x7 0x3 0x3 0x18 0x2 0x18 0x4
    0x18 0x3 0x19 0x0 0x2 0x2 0xa 0xfe
    0x9 0x9 0x41 0x53 0x2d 0x44 0x31 0x35
    0x33 0x32 : (34) Payload
    0x64 0xcb 0x54 : (3) Packet checksum
    0x20 : RSSI (raw RSSI value)
    0xa6 : CRC OK bit (MSB) OR-ed with the channel number (in this case CRC OK, channel 0x26 (38 decimal))
    0x54 0x6f : Junk 

  • But to your point: The description of the PSD packet format for the BLE sniffer is at best misleading. I will report the issue to the development team.

  • Thank you, M.

    Indeed it is a bit misleading. The FCS field in PSD corresponds to the junk values according to the User Manual. Also there is no mention of channel numbers in the manual. I was able to parse the data correct following your interpretation. 

    YJ.

  • Thanks for the clarification and for walking through the PSD data fields in such detail. I am trying to filter out packets with FCS errors in data from a CC2540 USB dongle. Can you point me to the byte position in the packet payload where the FCS is reported.

    From a recent data session:

    This packet reports FCS = OK

    01,4b,00,00,00,08,11,56,3b,00,00,00,0026,00,25,d6,be,89,8e,40,1a,a9,a6,cb,27,93,6f,02,01,1a,05,03,cd,ab,46,e6,0a,09,4c,69,67,68,74,42,6c,75,65,60,8b,3a,3e

    While this packet reports FCS = ERROR

    01,4c,00,00,00,e2,10,1e,3c,00,00,00,0026,00,25,d6,be,89,8e,40,1a,a9,a6,cb,27,93,6f,02,01,1a,05,03,cd,ab,46,e6,0a,09,4c,69,67,68,34,4c,6c,75,65,60,8b,3a,3d

    Other than the packet number and time stamps (which are expected to be different), all bytes are the same EXCEPT for bytes #43 and #44. Are these the FCS bytes I am looking for?

    Thanks in advance

    Orlando

  • Hi Orlando,

    Which version of the packet sniffer are you using? 2.17.0 or newer? It's important to know that the PSD file format changed slightly in rev 2.17.0. We've effectively added a 2-byte packet length field after the 8 bytes timestamp field in order to support very long packets for other devices. The rest of the data in the stored record is unchanged. So for your packet, you'll see:

    01: Packet Info
    4b,00,00,00: Packet number
    08,11,56,3b,00,00,00,00: Timestamp
    26,00: LENGTH - ADDED FROM REV 2.17.0 and onwards
    25: "Payload" Length
    d6,be,89,8e: Access address
    40,1a: BLE header
    a9,a6,cb,27,93,6f,02,01
    1a,05,03,cd,ab,46,e6,0a
    09,4c,69,67,68,74,42,6c
    75,65: BLE payload
    60,8b,3a: CRC
    3e: Raw RSSI
    --:  Your'e missing the byte with the CRC OK bit and the channel number 

  • Sign Bit said:

    Hi M!

    I can confirm that the formula works.

    Here is the updated script, just in case it might be useful to somebody:

    import sys
    import struct

    psd = struct.Struct("< B I Q B")

    first_timestamp_us = 0
    last_timestamp_us = 0

    with open(sys.argv[1], "rb") as fp:

       while True:

          data = fp.read(271)

          if len(data) == 271:

             (packet_info, packet_number, raw_timestamp, packet_length) = psd.unpack(data[0:14])
             packet = data[14:(14 + packet_length)]

             time_lo = raw_timestamp & 0xFFFF
             time_hi = raw_timestamp >> 16
             timestamp = (time_hi * 5000 + time_lo) >> 5

             if 0 == first_timestamp_us:
                first_timestamp_us = timestamp
                timestamp = 0
             else:
                timestamp = timestamp - first_timestamp_us

             print("%2x %6u %12dus (+%8.3fms) [%3u]" % (packet_info, packet_number, timestamp, (timestamp - last_timestamp_us) / 1000.0, packet_length))
             last_timestamp_us = timestamp

          else:
             if len(data):
                print("Short read: %d" % (len(data)))
             break


    Sign Bit, I'm new to scripting. What scripting language is this and how can I build and run it?

  • Looks like Python.