CuriousGeorge
CuriousGeorge

Reputation: 7410

How do I find the port name for a bluetooth device with a specific device name?

How do I find the port name for a bluetooth device with a specific device name?

I have this code, which enumerates all bluetooth devices, but doesn't give me their port name:

HBLUETOOTH_DEVICE_FIND founded_device;

BLUETOOTH_DEVICE_INFO device_info;
device_info.dwSize = sizeof(device_info);

BLUETOOTH_DEVICE_SEARCH_PARAMS search_criteria;
search_criteria.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS);
search_criteria.fReturnAuthenticated = TRUE;
search_criteria.fReturnRemembered = FALSE;
search_criteria.fReturnConnected = FALSE;
search_criteria.fReturnUnknown = FALSE;
search_criteria.fIssueInquiry = FALSE;
search_criteria.cTimeoutMultiplier = 0;

founded_device = BluetoothFindFirstDevice(&search_criteria, &device_info);

if(founded_device == NULL)
    return -1;

do {
    wstring ws = device_info.szName;
    cout << string(ws.begin(), ws.end()) << endl;

} while (BluetoothFindNextDevice(founded_device, &device_info));

And then I have this code, which enumerates all port names but doesn't give me the device name:

DWORD bytesNeeded = 0;
DWORD portCount = 0;

BOOL ret = EnumPorts(nullptr, 2, nullptr, 0, &bytesNeeded, &portCount);

BYTE *ports = new BYTE[bytesNeeded];

if(EnumPorts(nullptr, 2, (LPBYTE)ports, bytesNeeded, &bytesNeeded, &portCount))
{
    PORT_INFO_2 *portInfo = (PORT_INFO_2*)ports;

    for(DWORD i = 0; i < portCount; ++i)
        cout << portInfo[i].pPortName << endl;
}

delete [] ports;

I need to automatically connect to a specific device when my app is started, so I need to either get the port name for the bluetooth device in the first piece of code so I can connect to it, or check each portname in the second piece of code to make sure it's the right device before connecting to it.

How do I do it?

Upvotes: 1

Views: 2975

Answers (2)

Varvari Pavel
Varvari Pavel

Reputation: 11

Under the key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM you can find a subkey which has a list of keys containing the device address.

Under this last key, you can find a subkey named Device Parameters which finally has the PortName value.

The code is written in C++ with MFC libraries and is tested under Windows XP, 7 and 10. I hope it helps you !

// Returns the outgoing COM port of a bluetooth device given by address
int GetBluetoothCOM( CString sAddr )
{
    int iPort = 0;

    HKEY hKey_1;
    DWORD KeyNdx_1 = 0;
    DWORD MaxKeyLen_1;
    char KeyNam_1[ MAX_PATH + 1 ];
    LONG RetVal_1;

    sAddr.MakeUpper();
    sAddr.Replace( ":", "" );
    sAddr.Replace( " ", "" );

    // Enumerate keys under: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM
    RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum\\BTHENUM", NULL, KEY_READ | KEY_ENUMERATE_SUB_KEYS, &hKey_1 );

    while( true )
    {
        MaxKeyLen_1 = MAX_PATH;
        RetVal_1 = RegEnumKeyEx( hKey_1, KeyNdx_1, KeyNam_1, &MaxKeyLen_1, NULL, NULL, NULL, NULL );

        if( RetVal_1 == ERROR_NO_MORE_ITEMS )
        {
            break;
        }

        if( RetVal_1 == ERROR_SUCCESS )
        {
            HKEY hKey_2;
            DWORD KeyNdx_2 = 0;
            DWORD MaxKeyLen_2;
            char KeyNam_2[ MAX_PATH + 1 ];
            LONG RetVal_2;

            // Enumerate subkeys
            RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum\\BTHENUM\\" + CString( KeyNam_1 ), NULL, KEY_READ | KEY_ENUMERATE_SUB_KEYS, &hKey_2 );

            while( true )
            {
                MaxKeyLen_2 = MAX_PATH;
                RetVal_2 = RegEnumKeyEx( hKey_2, KeyNdx_2, KeyNam_2, &MaxKeyLen_2, NULL, NULL, NULL, NULL );

                if( RetVal_2 == ERROR_NO_MORE_ITEMS )
                {
                    break;
                }

                if( RetVal_2 == ERROR_SUCCESS )
                {
                    // Find out if the key name contains &ADDRESS_
                    CString sKey = "SYSTEM\\CurrentControlSet\\Enum\\BTHENUM\\" + CString( KeyNam_1 ) + "\\" + CString( KeyNam_2 );

                    sKey.MakeUpper();

                    if( sKey.Find( "&" + sAddr + "_" ) != -1 )
                    {
                        HKEY hKey;
                        char szPort[ 100 + 1 ];
                        DWORD dwLen = 100;

                        // I find out the device
                        RegOpenKeyEx( HKEY_LOCAL_MACHINE, sKey + "\\Device Parameters", 0, KEY_READ, &hKey );
                        if( RegQueryValueEx( hKey, "PortName", NULL, NULL, ( LPBYTE ) &szPort, &dwLen ) == ERROR_SUCCESS )
                        {
                            szPort[ dwLen ] = 0;
                            CString sPort = CString( szPort );

                            sPort.MakeUpper();

                            if( sPort.Find( "COM" ) == -1 )
                            {
                                RegCloseKey( hKey );
                                continue;
                            }

                            sPort.Replace( "COM", "" );
                            sPort.Trim();

                            iPort = atoi( sPort.GetBuffer() );

                            if( iPort != 0 )
                            {
                                RegCloseKey( hKey );
                                break;
                            }
                        }
                        RegCloseKey( hKey );
                    }
                }

                ++KeyNdx_2;
            }

            RegCloseKey( hKey_2 );

            if( iPort != 0 )
            {
                break;
            }
        }

        ++KeyNdx_1;
    };

    RegCloseKey( hKey_1 );

    return iPort;
}

Upvotes: 1

RonenKr
RonenKr

Reputation: 213

I remember struggling with this in the past. the only solution i found was to use sockets for communicating with the Bluetooth device using its address, then use the send() and recv() methods for communicating with the device.

// assuming you have the BT device address in blueToothDeviceAddr;
char blueToothDeviceAddr[18];

SOCKET sock;
SOCKADDR_BTH sa = { 0,0,0,0 };
int sa_len = sizeof(sa);

// initialize windows sockets
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD( 2, 0 );
if( WSAStartup( wVersionRequested, &wsaData ) != 0 ) 
{
    ExitProcess(100);
}

// parse the specified Bluetooth address

if( SOCKET_ERROR == WSAStringToAddress( blueToothDeviceAddr, AF_BTH, 
    NULL, (LPSOCKADDR) &sa, &sa_len ) ) 
{
        ExitProcess(101);
}

// query it for the right port

// create the socket
sock = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if( SOCKET_ERROR == sock ) 
{
    ExitProcess(102);
}

// fill in the rest of the SOCKADDR_BTH struct
GUID pService = (GUID)SerialPortServiceClass_UUID;
SOCKADDR_BTH outSA;
sa.port = SDPGetPort(blueToothDeviceAddr, (LPGUID) &pService,&outSA);
if( sa.port == 0 ) 
{
    ExitProcess(103);
}

// in case you have a pass code you need to register for authetication callback 
// look the web for this part

// connect to the device
if( SOCKET_ERROR == connect( sock, (LPSOCKADDR) &outSA, sa_len ) ) 
{
    int lastError = GetLastError();
    ExitProcess(105);
}

Upvotes: 1

Related Questions