Scan response on SDK15.3

Hi, I'm working with nRF52832 and S132 v6.1.1 on SDK15.3.0.
I'm using two nRF52832: one is scanning (active scanning) and one is advertising, and I want to exchange data between them using the scan request/scan response mechanism.

Using your nRF Sniffer with WireShark, I'm able to see that the scanning device is correctly sending scan requests (SCAN_REQ), and the advertising device is sending scan responses (SCAN_RSP) with my custom payload as expected:

My problem is that I've not been able to retrieve such scan response data on the scanning device.

I'm parsing the received advertising packets using on_adv_report(ble_gap_evt_adv_report_t const * p_adv_report), called by BLE_GAP_EVT_ADV_REPORT within ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context).

My understanding is that I should find the scan response data within the p_adv_report->data.p_data buffer, which is just the same where regular advertising packets data is temporarily stored. Is it correct? Because I can't seem to find the scan response data I'm looking for.

Also, how should I recognize scan response packets from regular advertising packets? I've come up with this but I'm not quite sure that's the correct way:

if ((p_adv_report->type.scan_response >> 3) & 1)
{
    // That's a scan response packet
}

else
{
    // That's a regular advertising packet
}

Finally, on the advertising device side, I'd like to ask if what I'm currently doing everytime I'm starting the advertising activity:

if (i_want_regular_adv_packet)
{
    // Filling m_advertising.enc_advdata here...
    
    m_advertising.adv_data.adv_data.len    = whatever;
    m_advertising.adv_data.adv_data.p_data = m_advertising.enc_advdata;
    
    // Explicity avoid scan response
    m_advertising.adv_data.scan_rsp_data.len    = 0;
    m_advertising.adv_data.scan_rsp_data.p_data = NULL;
}

else if (i_want_scan_response_packet)
{
    // Filling m_advertising.enc_scan_rsp_data here...
    
    m_advertising.adv_data.scan_rsp_data.len    = whatever;
    m_advertising.adv_data.scan_rsp_data.p_data = m_advertising.enc_scan_rsp_data;
    
    // Explicity avoid regular adv packet
    m_advertising.adv_data.adv_data.len    = 0;
    m_advertising.adv_data.adv_data.p_data = NULL;
}

ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);

Is it necessary to always "zero" one of the two packets, or does the softdevice take care of which packet to send in which condition (basically if upon a scan request or not).

Thank you in advance for your precious help.

Best regards,

Lorenzo

  • Hi Lorenzo,

    Finally, on the advertising device side, I'd like to ask if what I'm currently doing everytime I'm starting the advertising activity:
    Is it necessary to always "zero" one of the two packets, or does the softdevice take care of which packet to send in which condition (basically if upon a scan request or not).

    No, if one of them had to be all zeros there would be no point in the scan response packets. An advertiser always needs to send advertisement packets (if not, it is not advertising). And if there is not enough room in the advertisement packets, it can also optionally send a scan response packet if the scanner sends a scan request. This must be sent in a short window right after the advertising event, so it is not possible to get just the scan response packets an no advertising packets. This is how Bluetooth LE works.

    With regards to implementation, for a peripheral device you must always provide a advertising packet to advertise, and you can optionally also provide a scan response packet. If you do, the stack will automatically send the scan response packet if it gets a scan request.

    My understanding is that I should find the scan response data within the p_adv_report->data.p_data buffer, which is just the same where regular advertising packets data is temporarily stored. Is it correct? Because I can't seem to find the scan response data I'm looking for.

    Also, how should I recognize scan response packets from regular advertising packets? I've come up with this but I'm not quite sure that's the correct way:

    For the scanner, a scan response packet and advertising packet are handled in exactly the same way. The only way to distinguish between them is to look at the type field. This are using bitfields, so just to like this: "if (p_adv_report->type.scan_response)"

  • Thank you Einar, it's much more clear to me now!
    What's not clear is why I still can't receive scan response packets on the scanner.
    Putting a led blink within the "if (p_adv_report->type.scan_response)" is showing that no scan response packets are arriving, despite the fact that I'm seeing them with WireShark.
    Any idea of what could cause this? Meanwhile I'll try to investigate further and come back to this forum.

    Thank you!

  • Hi,

    Lorenzo said:
    Putting a led blink within the "if (p_adv_report->type.scan_response)" is showing that no scan response packets are arriving, despite the fact that I'm seeing them with WireShark.

    Is your central doing active scanning, or could it be that you see these scan responses in the trace because some other central does active scanning? If you central does it, perhaps you just don't see the LED blink because of the frequency? What if you check with a logic analyzer, or perhaps better just log a line over UART or RTT instead of blinking a LED?

    If you still have problems, perhaps you can share your central/observer code here so that we can have a look?

  • Hi, yes I can confirm it is my central device doing active scanning and sending the scan requests. The LED should be seen because it's a long blink and if I put it outside that "if" I can see it Slight smile

    Of course the next step is to print out all the received packets over UART as you suggest. 

    I'll keep you updated as soon I as I can do this test.

    Thank you very much for the moment!

Related