This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to interpret first 8 bytes of ble_l2cap_evt_t.rx.data (SDK v11 SD130 v2)

Hello

I'm trying to track lost packets in a connection by showing the sequence number of each packet received. Specifically it's about an application that sends new measurements in 3 packets each connection interval. Some measurements are divided over 2 packets so if a packet is lost, it is very important that the central application is aware of this. I think the sequence number is somewhere inside the ble_l2cap_evt_t.rx.data array of a received notification event but I'm not getting what I would expect. The code below tries to illustrate what I mean. Inside the for loop I print the first 7 bytes of the array. The rest of the data array gives the real payload (as expected):

static void on_hvx(ble_nus_c_t * p_ble_nus_c, const ble_evt_t * p_ble_evt)
{
// HVX can only occur from client sending.
if ( (p_ble_nus_c->handles.nus_rx_handle != BLE_GATT_HANDLE_INVALID)
        &&(p_ble_evt->evt.gattc_evt.params.hvx.handle==p_ble_nus_c->handles.nus_rx_handle)
        && (p_ble_nus_c->evt_handler != NULL)
    )
  {
    //After index 7 you get data payload
    for (int8_t i = 0; i < 8; i++)
    {
				
				printf("%d\t",p_ble_evt->evt.l2cap_evt.params.rx.data[i]);
    }
			ble_nus_c_evt_t ble_nus_c_evt;

    ble_nus_c_evt.evt_type = BLE_NUS_C_EVT_NUS_RX_EVT;
    ble_nus_c_evt.p_data   = (uint8_t *)p_ble_evt->evt.gattc_evt.params.hvx.data;
    ble_nus_c_evt.data_len = p_ble_evt->evt.gattc_evt.params.hvx.len;

    p_ble_nus_c->evt_handler(p_ble_nus_c, &ble_nus_c_evt);
  }
}

But I see that those first 7 bytes are always the same for all packets... So I guess the sequence number is not in there. My question is, if it is in there, how should I interpret it? And if it's not (what most likely will be the case) how can I get the sequence number out of a received notification event related to a received packet (or is this not possible?) ?

Kind regards

Mathias

EDIT 1 Picture of sniffing receiving side + sniffing file

image description

image description

Sniffing file

EDIT 2 Including of code files

I put together some code files with parts of my code, representing what you asked. The first two are peripheral code, the other one is central code.

This one contains the method that handles the measures made and puts them ready to send. It also contains the method of my custom service and characteristic that handles the real sending of a notification. Sending of packets with measurements.cpp

This one contains the method that handles an ACTIVE & NACTIVE, where on the end of each radio event, the measuring and setting data ready to send is started again (which is already done before the following radio event starts, this is already validated through GPIO testing). Initialising the sending of measurements each interval.cpp

This one contains the event handler where also the notifications are handled. There the printing of the notifications is showcased. Receiving notifications and printing them.cpp

EDIT 3 Including of sniff

The sniff is made using Perytons protocol analyzer. I already tried see that sometimes an err packet is sniffed (instead of a normal packet). If I check the order for the packet before and after this red packet, there should be a packet in between there so there's a packet missing there. But this could (and will be probably be) the sniffer's fault. Petter.anlb

  • And so the packet that is not accepted by the central because of full buffers is thus not ACKed and will be send again by peripheral before sending anything after that?

  • yes - the underlying transport is 100% reliable. It either delivers every single packet in order or it times out. All the way from L2CAP one end to L2CAP the other, a packet goes in, the packet comes out.

    The central can keep the connection alive sending zero length packets with the 'wrong' sequence bit set for as long as the peripheral will take it, the peripheral will keep sending the current packet (and not retiring TX buffers) until it sees it's been accepted.

    That probably is worthy of actually testing. Don't consume the packets on the central side, see what happens. The peripheral should stop retiring TX buffers and the connection should stay up with ZLPs flying one way and the constantly same next packet the other.

  • Okay, thanks for your help so far. I will look a bit further into the issue and hope I'll find the real culprit then. I'll also test what you said and see if it's like that. I'll keep you posted!

  • I think I fixed the culprit.. I checked the missing packets on central side with the packets that overflowed the TX buffer at peripheral side and it was always those that were missing. I thought that the packet that overflows the buffer, was already put in the buffer but just couldn't be send. But apparently(and very much logically) this is not the case and thus this packet needs to be send again.. :/ Very stupid so, as always, I'm very sorry for taking up so much of your time. Thanks for your help both!

Related