Pairing bluetooth device in windows c ++

I need to be able to connect a device using C ++ code for windows (specifically win7 or newer). I wrote some code that should work, but it doesn't. I can pair a lot of devices, Roku, headset, speakers, etc. but for some reason the device I need to pair with won't work.

It always returns error code 0x05, which according to bthdefs.h is BTH_ERROR_AUTHENTICATION_FAILURE.

So the weird part here. It never tries to authenticate. The callback function that must be called to provide the access token during pairing is not called. I have verified that it is summoned with other devices like a headset.

I've tried using BluetoothAuthenticateDeviceEx () without a callback function that needs to call the GUI on windows to complete pairing. It appears for my headset and other devices, and it will not appear for my device.

As a side note, I can connect the device using the window connection wizard. It just refuses to work programmatically.

I cannot figure out what the difference is between the winapi code I am using and what the Windows master does during pairing.

Here is the simplest test application I could get. My current application was using Qt and mingw to build. This app uses MSVC 2012 and clean Windows code to remove any obfuscation from the problem. All my code has the same problems with this error code 5.

#include <windows.h>
#include "bthdef.h"
#include "BluetoothAPIs.h"
#include <tchar.h>
#include <string>
#include <iostream>
#include <vector>

#pragma comment(lib, "bthprops.lib")

using namespace std;

vector<BLUETOOTH_DEVICE_INFO> scanDevices()
{
    vector<BLUETOOTH_DEVICE_INFO> res;

    BLUETOOTH_DEVICE_SEARCH_PARAMS bdsp;
    BLUETOOTH_DEVICE_INFO bdi;
    HBLUETOOTH_DEVICE_FIND hbf;

    ZeroMemory(&bdsp, sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS));

    // set options for how we want to load our list of BT devices
    bdsp.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS);
    bdsp.fReturnAuthenticated = TRUE;
    bdsp.fReturnRemembered = TRUE;
    bdsp.fReturnUnknown = TRUE;
    bdsp.fReturnConnected = TRUE;
    bdsp.fIssueInquiry = TRUE;
    bdsp.cTimeoutMultiplier = 4;
    bdsp.hRadio = NULL;

    bdi.dwSize = sizeof(bdi);

    // enumerate our bluetooth devices
    hbf = BluetoothFindFirstDevice(&bdsp, &bdi);
    if (hbf)
    {
        do
        {
            res.push_back(bdi);
        } while (BluetoothFindNextDevice(hbf, &bdi));

        // close our device enumerator
        BluetoothFindDeviceClose(hbf);
    }

    return res;
}

BOOL CALLBACK bluetoothAuthCallback(LPVOID param, PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS params)
{
    cout << "callback happened" << endl;
    return TRUE;
}

void pairDevice(BLUETOOTH_DEVICE_INFO device)
{
    wstring ws = device.szName;
    cout << "Pairing device " << string(ws.begin(), ws.end()) << endl;

    // register callback
    cout << "Registering callback" << endl;
    HBLUETOOTH_AUTHENTICATION_REGISTRATION hCallbackHandle = 0;
    DWORD result = BluetoothRegisterForAuthenticationEx(&device, &hCallbackHandle, (PFN_AUTHENTICATION_CALLBACK_EX)&bluetoothAuthCallback, NULL);
    if (result != ERROR_SUCCESS)
    {
        cout << "Failed to register callback" << endl;
        return;
    }

    // authenticate
    result = BluetoothAuthenticateDeviceEx(NULL, NULL, &device, NULL, MITMProtectionNotRequired);
    //DWORD result = BluetoothAuthenticateDeviceEx(NULL, NULL, &device, NULL, MITMProtectionRequired);
    //DWORD result = BluetoothAuthenticateDeviceEx(NULL, NULL, &device, NULL, MITMProtectionNotRequiredBonding);
    //DWORD result = BluetoothAuthenticateDeviceEx(NULL, NULL, &device, NULL, MITMProtectionRequiredBonding);
    //DWORD result = BluetoothAuthenticateDeviceEx(NULL, NULL, &device, NULL, MITMProtectionNotRequiredGeneralBonding);
    //DWORD result = BluetoothAuthenticateDeviceEx(NULL, NULL, &device, NULL, MITMProtectionRequiredGeneralBonding);
    //DWORD result = BluetoothAuthenticateDeviceEx(NULL, NULL, &device, NULL, MITMProtectionNotDefined);
    switch (result)
    {
    case ERROR_SUCCESS:
        cout << "pair device success" << endl;
        break;

    case ERROR_CANCELLED:
        cout << "pair device failed, user cancelled" << endl;
        break;

    case ERROR_INVALID_PARAMETER:
        cout << "pair device failed, invalid parameter" << endl;
        break;

    case ERROR_NO_MORE_ITEMS:
        cout << "pair device failed, device appears paired already" << endl;
        break;

    default:
        cout << "pair device failed, unknown error, code " << (unsigned int)result << endl;
        break;
    }
}

int _tmain(int argc, _TCHAR *argv[])
{
    cout << "Scanning bluetooth devices..." << endl;
    cout.flush();

    // scan devices
    vector<BLUETOOTH_DEVICE_INFO> devices = scanDevices();

    cout << "Got " << devices.size() << " devices" << endl;

    // list all devices
    int pdIndex = -1;
    int foundDev = -1;
    vector<BLUETOOTH_DEVICE_INFO>::const_iterator devci;
    for (devci=devices.begin();devci!=devices.end();devci++)
    {
        pdIndex++;
        wstring ws = (*devci).szName;
        cout << "Device: " << string(ws.begin(), ws.end()) << endl;

        // see if we find our device (case sensitive)
        if (ws.find(L"smp") != string::npos)
            foundDev = pdIndex;
    }

    // pick our ismp device
    if (foundDev == -1)
    {
        cout << "Could not find a device to pair" << endl;
        return 1;
    }

    BLUETOOTH_DEVICE_INFO pd = devices[foundDev];
    wstring ws = pd.szName;
    cout << "Found device to pair, " << string(ws.begin(), ws.end()) << endl;

    // attempt to pair device
    pairDevice(pd);

    return 0;
}

      

+3


source to share


2 answers


As far as I know, I see a lot of problems in your code:

1) you call BluetoothRegisterForAuthenticationEx inside your call on "pairDevice": the hCallbackHandle variable will only live during the call so you must register before the 'pairDevice'

2) you don't call BluetoothUnregister afterwards

3) you are not removing the hCallbackHandle



4) your "bluetoothAuthCallback" is empty: you should do something like

BLUETOOTH_AUTHENTICATE_RESPONSE response;
::ZeroMemory(&response,sizeof(BLUETOOTH_AUTHENTICATE_RESPONSE));
response.authMethod = cbparams->authenticationMethod;
response.bthAddressRemote = cbparams->deviceInfo.Address;
response.negativeResponse = FALSE;
DWORD error=::BluetoothSendAuthenticationResponseEx(nullptr, &response);

      

(see above comment ;-)

5) your call to "BluetoothAuthenticateDeviceEx" will trigger the callback routine asynchronously ... so you need to "wait" for it ... before leaving the main () function ...

+3


source


Perhaps you should add a response to your authentication callback. Smth like this:



BLUETOOTH_DEVICE_INFO aw = params->deviceInfo;
HANDLE lRadio = NULL;

BLUETOOTH_AUTHENTICATE_RESPONSE bar2Send;
::ZeroMemory(&bar2Send, sizeof(BLUETOOTH_AUTHENTICATE_RESPONSE));
bar2Send.bthAddressRemote = params->deviceInfo.Address;
bar2Send.authMethod = params->authenticationMethod;

DWORD result = BluetoothSendAuthenticationResponseEx(lRadio, &bar2Send);

      

+1


source







All Articles