Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pairing a bluetooth device in windows with c++

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

It always returns an error code of 0x05 which according to bthdefs.h is defined as BTH_ERROR_AUTHENTICATION_FAILURE.

So the weird part here. It never tries to authenticate. The callback function that should get called to provide the passkey during pairing doesn't get called. I have verified it does get called with other devices like a headset.

I have tried using BluetoothAuthenticateDeviceEx() without the callback function which should pop up the GUI in windows to finish the pairing. It pops up for my headset and other devices, it won't pop up for my device.

As a side note I can pair the device using Window's bluetooth wizard just fine. It just refuses to work programmatically.

I can't figure out what the difference is between the winapi code I am using and what windows' wizard is doing during pairing.

Here is the simplest test app I could get. My real app was using Qt and mingw to build. This app uses MSVC 2012 and pure windows code to remove any obfuscation from the problem. All my code has the same problems with that 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;
}
like image 611
ambershark Avatar asked Sep 09 '14 08:09

ambershark


People also ask

Why won't my Bluetooth device pair with my computer?

Turn off Bluetooth, wait a few seconds, then turn it back on. Remove the Bluetooth device, then add it again: Select Start , then select Settings > Devices > Bluetooth & other devices .. In Bluetooth, select the device you're having problems connecting to, and then select Remove device > Yes.

How do you I connect a Bluetooth device into PC?

On your PC, select Start > Settings > Devices > Bluetooth & other devices > Add Bluetooth or other device > Bluetooth. Choose the device and follow additional instructions if they appear, then select Done.


1 Answers

As far as I know, I can see many problems in your code:

1) you are calling BluetoothRegisterForAuthenticationEx inside your call to 'pairDevice': hCallbackHandle variable will only live during the call so you must Register before 'pairDevice'

2) your are not calling BluetoothUnregister afterwards

3) you are not deleting the hCallbackHandle handle

4) your 'bluetoothAuthCallback' is empty: you must 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 have to 'wait' for it... before leaving the main() function...

like image 166
adanteny Avatar answered Sep 21 '22 01:09

adanteny