Link to home
Start Free TrialLog in
Avatar of A_Ridiculously_Long_Unique_Name
A_Ridiculously_Long_Unique_NameFlag for Australia

asked on

How to get Bluetooth friendly name

This is a programming question.

We are presently using the WSALookupServiceBegin and WSALookupServiceNext functions to retrieve the Bluetooth address and Friendly Name. The idea is that performing a query with ulFlags set to LUP_CONTAINERS, LUP_RETURN_NAME, LUP_RETURN_ADDR we should be able to iterate over the collection to build a list of available devices and present the list of friendly names to the user.

The problem is the friendly name is not always populated. About 50% of the time we will get the friendly name and the other 50% of the time we get the Address only.

I have used the LUP_FLUSHCACHE flag with ulFlags but this has not helped. I have experimented with inserting Sleep statements in various parts of the loop but that hasn't worked either.

I am basically copying the sample program from the SDK "bthcxn.cpp".

Can someone tell me what is going wrong?

Also if I have a Bluetooth address (which is pretty reliably returned), how can I query that device directly for it's friendly name?


Sample Code:



//-----------------------------------------------------------------------------
// Get a collection of bluetooth devices in range
// Formatted as friendly name, compatible mac address (without CRC)
//
CDeviceNumberList GetDeviceNumbers()
{
    CDeviceNumberList devicesInRange;

    PWSAQUERYSET      pWSAQuerySet;
    ULONG           ulPQSSize = sizeof(WSAQUERYSET);
    pWSAQuerySet = (PWSAQUERYSET) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulPQSSize);

    if (!pWSAQuerySet) return devicesInRange;


    // There is some a glitch in the WSALookupServiceBegin function, where on the first
    // time through the collection, the lpszServiceInstanceName field is not populated.
    // As per the SDK sample, performe the query twice, second time flushing the cache
    // this seems to reliably return the lpszServiceInstanceName.
    //
    int success = 0;    // number of successful iterations
    int retry = 0;
    while (retry < 5 && success < 2 && pWSAQuerySet)
    {
        //
        // WSALookupService is used for both service search and device inquiry
        // LUP_CONTAINERS is the flag which signals that we're doing a device inquiry.
        //
        ULONG ulFlags = LUP_CONTAINERS;

        //
        // Friendly device name (if available) will be returned in lpszServiceInstanceName
        //
        ulFlags |= LUP_RETURN_NAME;

        //
        // BTH_ADDR will be returned in lpcsaBuffer member of WSAQUERYSET
        //
        ulFlags |= LUP_RETURN_ADDR;

        // As per the SDK example, on the 2nd query, flush the cache
        if (retry)
        {
            // Perform a fresh lookup instead of using the device cache.
            //
            ulFlags |= LUP_FLUSHCACHE;

            Sleep(2000);
        }

        //
        // Start the lookup service
        //
        HANDLE hLookup = 0;
        ZeroMemory(pWSAQuerySet, ulPQSSize);
        pWSAQuerySet->dwNameSpace = NS_BTH;
        pWSAQuerySet->dwSize = sizeof(WSAQUERYSET);

        int iResult = WSALookupServiceBegin(pWSAQuerySet, ulFlags, &hLookup);
        if (iResult == NO_ERROR && hLookup)
        {
            // If this is the second successful query, use the results
            // Note: i will be non-zero on the subsequent query
            while (pWSAQuerySet && success)
            //while (pWSAQuerySet)
            {
                iResult = WSALookupServiceNext(hLookup, ulFlags, &ulPQSSize, pWSAQuerySet);
                if (iResult == NO_ERROR)
                {                
                    CDeviceNumber   deviceNumber;

                    CString temp(pWSAQuerySet->lpszServiceInstanceName);
                    deviceNumber.friendlyName = temp;

                    const char *macAddr = pWSAQuerySet->lpcsaBuffer->RemoteAddr.lpSockaddr->sa_data;
                    //for (int i = 6; i >= 0; i--)
                    //    deviceNumber.macAddress.append( CHex::ByteToHexString(macAddr[i]) );
                    deviceNumber.macAddress.append("AA:BB:CC");

                    devicesInRange.push_back(deviceNumber);                    
                }
                else
                {
                    iResult = WSAGetLastError();
                    if (iResult == WSAEFAULT)
                    {
                        //
                        // The buffer size for QUERYSET was insufficient.
                        // In such case 3rd parameter "ulPQSSize" of function "WSALookupServiceNext()" receives
                        // the required size.  So we can use this parameter to reallocate memory for QUERYSET.
                        //
                        HeapFree(GetProcessHeap(), 0, pWSAQuerySet);
                        pWSAQuerySet = (PWSAQUERYSET) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulPQSSize);
                    }
                    else
                    {
                        // End of the collection
                        break;
                    }
                }
            }
            WSALookupServiceEnd(hLookup);
            success++;
        }
        else
        {
            iResult = WSAGetLastError();
        }
        retry++;
    }


    if (pWSAQuerySet)
        HeapFree(GetProcessHeap(), 0, pWSAQuerySet);

    return devicesInRange;
}




Thanks
ASKER CERTIFIED SOLUTION
Avatar of A_Ridiculously_Long_Unique_Name
A_Ridiculously_Long_Unique_Name
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial