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.

CC2340R5: Is there a way to get the primary services UUID from a server without connecting to it

Part Number: CC2340R5
Other Parts Discussed in Thread: SYSCONFIG, CC2541

Tool/software:

Hello

CC2340 set as central.

While scanning, I would like to present a list of devices that has one specific service UUID (custom)

Any other BT device that was scanned and does not have that service available shall be ignored and not listed.

Right now I have to connect to the device and issue a GATT_DiscAllPrimaryServices(gapEstMsg->connectionHandle, bleAppTaskID); in order to discover what services that device has.

Since I have to pass a connection handle, I have to connect to the server first and then invoke this function.

Is there a way to get only the UUIDs of available services while in the scan process through the ADV Reports? Or at least run some procedure to try to discover this information without connecting to the device?

Thank you and best regards

  • Hello Alexandre,

    You can expose different sizes of UUIDs through the adv report data. Please take a look at the Adv Data in SysConfig.

    On the central side, this one can be configured to auto-connect to the peripheral based on a predefined UUID set in the peripheral. The logic would be something like this (see how uuid value is being compared):

    static bool FindSerialStreamServer(
            const uint8_t *uuid, const uint8_t *pManufData, uint8_t manDataLen,
            uint8_t *pData, uint8_t dataLen)
    {
        uint8_t matchingIdAndUuid = 0;
        uint8_t adLen;
        uint8_t adType;
        uint8_t *pEnd;
    
        pEnd = pData + dataLen - 1;
    
        // While end of data not reached
        while ((dataLen > 0) && (pData < pEnd))
        {
            // Get length of next AD item
            adLen = *pData++;
            if (adLen > 0)
            {
                adType = *pData;
    
                // If AD type is for 128-bit service UUID
                if ((adType == GAP_ADTYPE_128BIT_MORE)
                        || (adType == GAP_ADTYPE_128BIT_COMPLETE))
                {
                    pData++;
                    adLen--;
    
                    // For each UUID in list
                    while (adLen >= 2 && pData < pEnd)
                    {
                        // Check for match
                        if (!memcmp(pData, uuid, ATT_UUID_SIZE))
                        {
                            matchingIdAndUuid++;
                        }
    
                        // Go to next
                        pData += 2;
                        adLen -= 2;
                    }
    
                    // Handle possible erroneous extra byte in UUID list
                    if (adLen == 1)
                    {
                        pData++;
                    }
                }
    
                // REMOVED FOR TESTING
                if (adType == GAP_ADTYPE_MANUFACTURER_SPECIFIC)
                {
                    // Floor to the lowest length
                    uint8_t len = adLen;
                    if (manDataLen < len)
                    {
                        len = manDataLen;
                    }
    
                    if (memcmp(pManufData, pData, len))
                    {
                        matchingIdAndUuid++;
                    }
                }
    
                if (matchingIdAndUuid < 2)
                {
                    // Go to next item
                    pData += adLen;
                }
                else
                {
                    return TRUE;
                }
    
            }
        }
    
        // Match not found
        return FALSE;
    }
    

    Hope this helps.

    David.

  • Hello David

    Thank you for taking the time to help.

    I´m also using nRF Connect app to connect to my peripherals and the app can retrieve Services and also the Device Name information without connecting, so my peripherals are already advertising this, or the app runs some procedure to retrieve the information without connecting. Since this information is displayed instantly (app opnes, scans for half second and shows all information as the image below), I believe it got all data through the advertising packets.

    In red below is two types of devices in red. First one is one using CC2541. Second one is using BT900. Both have the service 0x181D (Weight Scale) discovered by the app without connecting.

    The code you posted look promising but the arguments passed to the static bool FindSerialStreamServer require a pData buffer to look for UUIDs and also the pData lenght value.

    I believe it is to look for inside the data buffer of the advertising packet received but looking inside the GapScan_Evt_AdvRpt_t advReport in Central_ScanEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData) function (app_central.c) I have an empty pData buffer and 0 as dataLen.

    The adv report addres is from my peripheral but the dataLen and pData are empty.

    I did enable the extra data fields to be recorded in gap_scanner.h file:

    /// Default adv report fields to record
    #define SCAN_PARAM_DFLT_RPT_FIELDS         (SCAN_ADVRPT_FLD_EVENTTYPE|\
                                                SCAN_ADVRPT_FLD_ADDRTYPE |\
                                                SCAN_ADVRPT_FLD_ADDRESS  |\
                                                SCAN_ADVRPT_FLD_ADVSID   |\
                                                SCAN_ADVRPT_FLD_RSSI     |\
                                                SCAN_ADVRPT_FLD_DATALEN  |\
                                                SCAN_ADVRPT_FLD_TXPOWER  |\
                                                SCAN_ADVRPT_FLD_PRDADVINTERVAL  )

    Still I have no data inside the Central_ScanEventHandler in (app_central.c)

    Can you point in which function this report might have the full data buffer and length information to check the UUID´s?

  • Hello Alexandre,

    I think this training material can be useful to understand how to retrieve the advertisement report: Bluetooth Low Energy Scanning and Advertising (See task 2: Scanning Task 2 – Print Scanning Results). See that the bleStk_GapScan_Evt_AdvRpt_t structure contains the pData. Also please remember to add the BLEAPPUTIL_ADV_REPORT event to the centralScanHandler handler as described by the guide.

    BR,

    David.

  • Thank you David I found the place where the adv reports have dataLen and pData to search for info.

    Case is resolved.

  • Oh by the way. Can you point a documentation so I can check the meaning of each field in the advertisement pData?

    The original issue is now resolved and since I will have to understand the meaning of the adv data, any doc that could help is welcome.

    Thank you

  • Hello Alexandre,

    Glad to know you are able to move forward.

    I would suggest to take a look at SysConfig for a first reference. If you click on the "?" symbol, you can see information about the field.

    For more details you can also check the fields in the Bluetooth LE spec: https://www.bluetooth.com/specifications/specs/core-specification-5-3/

    BR,

    David.