1

Winsock API を使用して Windows で Bluetooth プログラミングを試してみましたが、ホストに Bluetooth がないかどうか、またはスキャン セットが空であるかどうかを判断する方法で問題が発生しました。

したがって、プログラムは非常に単純です。Winsock を開始し、WSALookupServiceBegin を呼び出してから、デバイスをスキャンしながら ServiceNext と ServiceEnd を呼び出します。開発マシンには Bluetooth 無線があり、ドライバーは Microsoft BT Stack で、Windows のデバイス ウィザードを使用してデバイスを見つけることができます。

問題は、WSALookupServiceBegin の呼び出し時に、次の 2 つのケースで WSASERVICE_NOT_FOUND が返されることです。

  1. ホスト マシンにアダプタがありません
  2. 範囲内にスキャンする Bluetooth デバイスがありません (つまり、空のスキャン セット)。

だから私の質問は:

  1. これは期待されていますか?
  2. どちらが起こっているかをさらに特定するにはどうすればよいですか?

前もって感謝します!

添付コード:

int main(int argc, char **argv)
{
    WSADATA wsd;
    BOOL retVal;

    if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
        printf("WSAStartup() failed with error code %ld\n", WSAGetLastError());
    else
        printf("WSAStartup() is OK!\n");

    scan();

    if (WSACleanup() == 0)
        printf("WSACleanup() is OK!\n");
    else
        printf("WSACleanup() failed with error code %ld\n", WSAGetLastError());

    return 0;
}

そしてscan();

void scan()
{
    WSAQUERYSET queryset;

    memset(&queryset, 0, sizeof(WSAQUERYSET));
    queryset.dwSize = sizeof(WSAQUERYSET);
    queryset.dwNameSpace = NS_BTH;

    // begin query
    HANDLE hDeviceLookup;
    if (WSALookupServiceBegin(&queryset, LUP_FLUSHCACHE | LUP_CONTAINERS, &hDeviceLookup)) {
        int last_error = WSAGetLastError();
        wcout << getWinErrorMessage(last_error) << endl;

        return;
    }

    int bufSize = 0x2000;
    void* buf = malloc(bufSize);

    int result = -1;
    while (result == -1) {
        memset(buf, 0, bufSize);

        LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET)buf;
        pwsaResults->dwSize = sizeof(WSAQUERYSET);
        pwsaResults->dwNameSpace = NS_BTH;

        DWORD size = bufSize;

        if (hDeviceLookup == NULL) {
            break;
        }
        if (WSALookupServiceNext(hDeviceLookup, LUP_RETURN_NAME | LUP_RETURN_ADDR | LUP_RETURN_BLOB, &size, pwsaResults)) {
            int last_error = WSAGetLastError();
            switch (last_error) {
            case WSAENOMORE:
            case WSA_E_NO_MORE:
                result = 2;
                break;
            default:
                wcout << getWinErrorMessage(last_error) << endl;
                result = 3;
            }
            WSALookupServiceEnd(hDeviceLookup);
            hDeviceLookup = NULL;

            break;
        }

        BTH_DEVICE_INFO *p_inqRes = (BTH_DEVICE_INFO *)pwsaResults->lpBlob->pBlobData;
        // get device name
        WCHAR name[256];
        BOOL bHaveName = pwsaResults->lpszServiceInstanceName && *(pwsaResults->lpszServiceInstanceName);
        wcout << pwsaResults->lpszServiceInstanceName << endl;
        int deviceClass = p_inqRes->classOfDevice;
        BTH_ADDR deviceAddr;

        deviceAddr = ((SOCKADDR_BTH *)pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr)->btAddr;
    }

    if (buf != NULL) {
        free(buf);
    }

    if (hDeviceLookup != NULL) {
        WSALookupServiceEnd(hDeviceLookup);
        hDeviceLookup = NULL;
    }
}
4

1 に答える 1

1

次のコードを使用して、Windows Bluetooth スタックを使用できるかどうか、および必要なハードウェアが存在するかどうかを判断します。

CanUseBluetooth() は、Bluetooth プロトコルを理解する winsock プロバイダーがあることを確認するだけです。その場合は、スタックがインストールされています。

static bool CanUseBluetooth(
   bool throwOnFailure)
{
   static const CAddressTypeBluetooth addressType;

   SOCKET s = ::socket(addressType.Family(), SOCK_STREAM, addressType.Protocol());

   const bool canUseBluetooth = (s != INVALID_SOCKET);

   const DWORD lastError = ::GetLastError();

   ::closesocket(s);

   if (!canUseBluetooth && throwOnFailure)
   {
      throw CWin32Exception(_T("CUsesXPBluetooth::CanUseBluetooth()"), lastError);
   }

   return canUseBluetooth;
}

HarwareActive() は、ワイルドカード アドレスにバインドできることを確認します。バインドできる場合は、Windows スタックを使用しているアクティブな Bluetooth ハードウェアがいくつかあります。

static bool HardwareActive(
   bool throwOnFailure)
{
   static const CAddressTypeBluetooth addressType;

   SOCKET s = ::socket(addressType.Family(), SOCK_STREAM, addressType.Protocol());

   if (s == INVALID_SOCKET)
   {
      const DWORD lastError = ::GetLastError();

      ::closesocket(s);

      throw CWin32Exception(_T("CUsesXPBluetooth::HardwareActive() - CanUseBluetooth"), lastError);
   }

   bool hardwareActive = true;

   static const IAddress &address = addressType.WildcardAddress();

   if (SOCKET_ERROR == ::bind(s, &address.AsSockAddr(), address.Size()))
   {
      hardwareActive = false;
   }

   const DWORD lastError = ::GetLastError();

   ::closesocket(s);

   if (!hardwareActive && throwOnFailure)
   {
      throw CWin32Exception(_T("CUsesXPBluetooth::HardwareActive()"), lastError);
   }

   return hardwareActive;
}
于 2013-11-27T11:07:01.647 に答える