Winsock 2 发现蓝牙设备只显示以前配对的设备

Winsock 2 discovering Bluetooth devices only showing previously paired devices

我目前正在尝试使用 WINSOCK 2 API 以发现附近可用的蓝牙设备。我使用的代码基于可以在 here.

中找到的 Microsoft 示例

我主要使用 WSALookupServiceNext 遍历可用设备。问题是我只得到以前配对的蓝牙设备的列表,而我没有看到任何其他设备。我添加了一些代码以打印设备信息:

*********************
Winsock search started!
*********************

Device #:1
Device name:MagicBox II
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x00025b3dc371, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Device #:2
Device name:Mpow Flame
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x501801101c68, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Device #:3
Device name:WH-1000XM2
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x702605aba41d, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Device #:4
Device name:Magicbuds
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x5017032a701b, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0

这是相应的代码部分,(我事先调用了 WSAStartup):

void WSALookupAvailableDevices(void)
{
    WSAQUERYSET     wsaQuery{};
    LPWSAQUERYSET   pwsaResults{};
    HANDLE          hLookup{};

    CSADDR_INFO     *pAddrInfo{};
    SOCKADDR_BTH    *pBtSockRemote{}, 
                    *pBtSockLocal{};

    char    buffer[4096] = {};
    int     nDevicesFound = 1;
    DWORD   swSize = sizeof(buffer);
    DWORD   flags = LUP_RETURN_ADDR | LUP_RETURN_NAME | LUP_RES_SERVICE | LUP_CONTAINERS | LUP_RETURN_BLOB | LUP_RETURN_TYPE;

    /*Preparing the query set*/
    wsaQuery.dwNameSpace = NS_BTH;
    wsaQuery.dwSize = sizeof(WSAQUERYSET);


    if (WSALookupServiceBegin(&wsaQuery, flags, &hLookup) == SOCKET_ERROR)
    {
        wprintf(L"Shit something went wrong! error: %d!\n", WSAGetLastError());
        return;
    }

    wprintf(L"*********************\n");
    wprintf(L"Winsock search started!\n");
    wprintf(L"*********************\n\n");


    /*Preparing the queryset return buffer*/
    pwsaResults = (LPWSAQUERYSET)buffer;
    pwsaResults->dwNameSpace = NS_BTH;
    pwsaResults->dwSize = sizeof(WSAQUERYSET);

    while (WSALookupServiceNext(hLookup, flags, &swSize, pwsaResults) == NO_ERROR)
    {
        pAddrInfo       = (CSADDR_INFO*)pwsaResults->lpcsaBuffer;
        pBtSockRemote   = (SOCKADDR_BTH*)(pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr);
        pBtSockLocal    = (SOCKADDR_BTH*)(pwsaResults->lpcsaBuffer->LocalAddr.lpSockaddr);

        wprintf(L"Device #:%d\n", nDevicesFound);
        wprintf(L"Device name:%s\n", pwsaResults->lpszServiceInstanceName);
        wprintf(L"Device connected: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_CONNECTED));
        wprintf(L"Device remembered: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_REMEMBERED)>0);
        wprintf(L"Device authenticated: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_AUTHENTICATED)>0);
        wprintf(L"Remote Bluetooth device is 0x%04x%08x, server channel = %d\n",
            GET_NAP(pBtSockRemote->btAddr), GET_SAP(pBtSockRemote->btAddr), pBtSockRemote->port);
        wprintf(L"Local Bluetooth device is 0x%04x%08x, server channel = %d\n",
            GET_NAP(pBtSockLocal->btAddr), GET_SAP(pBtSockLocal->btAddr), pBtSockLocal->port);

        nDevicesFound++;

    }
    WSALookupServiceEnd(hLookup);
    wprintf(L"\n");
}

提前感谢您的帮助!

LUP_FLUSHCACHE 就是您所需要的。是的,它总是 return 配对设备(除了发现)。我的意思是如果设备配对 WSALookup return 它在列表中,即使它不可用(关闭或超出范围)。

https://docs.microsoft.com/en-us/windows/desktop/bluetooth/bluetooth-and-wsalookupservicebegin-for-device-inquiry

DWORD   flags = LUP_RETURN_ADDR | LUP_RETURN_NAME | LUP_RES_SERVICE | LUP_CONTAINERS | LUP_RETURN_BLOB | LUP_RETURN_TYPE | LUP_FLUSHCACHE;

但发现设备的最佳方法是使用此标志集。

DWORD   flags = LUP_RETURN_ADDR | LUP_CONTAINERS | LUP_FLUSHCACHE;

此外,最好提供额外的信息 (BTH_QUERY_DEVICE),以便您可以设置发现超时和其他参数

BTH_QUERY_DEVICE qDev;
qDev.LAP = 0;
qDev.length = bTimeout; // Timeout in seconds
BLOB Blb;
Blb.cbSize = sizeof(BTH_QUERY_DEVICE);
Blb.pBlobData = (PBYTE)&qDev;
QuerySet.lpBlob = &Blb;

https://docs.microsoft.com/th-th/windows/desktop/api/ws2bth/ns-ws2bth-_bth_query_device

发现完成后(请注意 WSALookupServiceBegin 需要时间(块)直到发现完成)您可以使用 BluetoothGetDeviceInfo 获取扩展信息,例如设备名称和其他信息。

https://docs.microsoft.com/en-us/windows/desktop/api/bluetoothapis/nf-bluetoothapis-bluetoothgetdeviceinfo

您应该知道,由于某些蓝牙限制,名称解析只能在发现完成后才能执行。而且这个操作可能需要时间。因此,如果您在发现完成后立即调用 BluetoothGetDeviceInfo,您仍然可以获得新发现设备(之前未发现的设备)的空设备名称。

除了切换到 WinRT API 或等待一段时间再读取设备名称外,没有其他简单的方法可以解决此问题。您还可以使用 WM_DEVICECHANGE 消息来获取有关设备名称解析的通知

https://docs.microsoft.com/en-us/windows/desktop/bluetooth/bluetooth-and-wm-devicechange-messages

还有一个问题:MS 堆栈总是 return在发现过程中 sd 配对设备,即使它们不可用。