I am a newbie in Windows application development. Currently I'm working on a project to write a communication layer using Bluetooth low energy which should work on both windows 8.1 and windows 10. Below is the code that I used to run to list the BLE services,
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <setupapi.h>
#include <devguid.h>
#include <regstr.h>
#include <bthdef.h>
#include <bluetoothleapis.h>
#pragma comment(lib, "SetupAPI")
#pragma comment(lib, "BluetoothApis.lib")
#define TO_SEARCH_DEVICE_UUID "{0000b81d-0000-1000-8000-00805f9b34fb}"
void EventNotif(BTH_LE_GATT_EVENT_TYPE EventType, PVOID EventOutParameter, PVOID Context)
{
printf("notification obtained ");
PBLUETOOTH_GATT_VALUE_CHANGED_EVENT ValueChangedEventParameters = (PBLUETOOTH_GATT_VALUE_CHANGED_EVENT)EventOutParameter;
HRESULT hr;
if (0 == ValueChangedEventParameters->CharacteristicValue->DataSize) {
hr = E_FAIL;
printf("datasize 0\n");
}
else {
printf("char ");
unsigned heart_rate;
if (0x01 == (ValueChangedEventParameters->CharacteristicValue->Data[0] & 0x01)) {
heart_rate = ValueChangedEventParameters->CharacteristicValue->Data[1] * 256 + ValueChangedEventParameters->CharacteristicValue->Data[2];
}
else {
heart_rate = ValueChangedEventParameters->CharacteristicValue->Data[1];
}
printf("%d\n", heart_rate);
}
}
HANDLE GetBLEHandle(__in GUID AGuid)
{
HDEVINFO hDI;
SP_DEVICE_INTERFACE_DATA did;
SP_DEVINFO_DATA dd;
GUID BluetoothInterfaceGUID = AGuid;
HANDLE hComm = NULL;
hDI = SetupDiGetClassDevs(&BluetoothInterfaceGUID, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (hDI == INVALID_HANDLE_VALUE) return NULL;
did.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
dd.cbSize = sizeof(SP_DEVINFO_DATA);
for (DWORD i = 0; SetupDiEnumDeviceInterfaces(hDI, NULL, &BluetoothInterfaceGUID, i, &did); i++)
{
SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
DeviceInterfaceDetailData.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
DWORD size = 0;
if (!SetupDiGetDeviceInterfaceDetail(hDI, &did, NULL, 0, &size, 0))
{
int err = GetLastError();
if (err == ERROR_NO_MORE_ITEMS) break;
PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)GlobalAlloc(GPTR, size);
pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(hDI, &did, pInterfaceDetailData, size, &size, &dd))
break;
hComm = CreateFile(
pInterfaceDetailData->DevicePath,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
GlobalFree(pInterfaceDetailData);
}
}
SetupDiDestroyDeviceInfoList(hDI);
return hComm;
}
int main(int argc, char *argv[], char *envp[])
{
GUID AGuid;
CLSIDFromString(TEXT(TO_SEARCH_DEVICE_UUID), &AGuid);
HANDLE hLEDevice = GetBLEHandle(AGuid);
USHORT serviceBufferCount;
HRESULT hr = BluetoothGATTGetServices(
hLEDevice,
0,
NULL,
&serviceBufferCount,
BLUETOOTH_GATT_FLAG_NONE);
if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) {
printf("BluetoothGATTGetServices - Buffer Size %d", hr);
}
PBTH_LE_GATT_SERVICE pServiceBuffer = (PBTH_LE_GATT_SERVICE)
malloc(sizeof(BTH_LE_GATT_SERVICE) * serviceBufferCount);
if (NULL == pServiceBuffer) {
printf("pServiceBuffer out of memory\r\n");
}
else {
RtlZeroMemory(pServiceBuffer,
sizeof(BTH_LE_GATT_SERVICE) * serviceBufferCount);
}
USHORT numServices;
hr = BluetoothGATTGetServices(
hLEDevice,
serviceBufferCount,
pServiceBuffer,
&numServices,
BLUETOOTH_GATT_FLAG_NONE);
if (S_OK != hr) {
printf("BluetoothGATTGetServices - Buffer Size %d", hr);
}
USHORT charBufferSize;
hr = BluetoothGATTGetCharacteristics(
hLEDevice,
pServiceBuffer,
0,
NULL,
&charBufferSize,
BLUETOOTH_GATT_FLAG_NONE);
if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) {
printf("BluetoothGATTGetCharacteristics - Buffer Size %d", hr);
}
PBTH_LE_GATT_CHARACTERISTIC pCharBuffer;
if (charBufferSize > 0) {
pCharBuffer = (PBTH_LE_GATT_CHARACTERISTIC)
malloc(charBufferSize * sizeof(BTH_LE_GATT_CHARACTERISTIC));
if (NULL == pCharBuffer) {
printf("pCharBuffer out of memory\r\n");
}
else {
RtlZeroMemory(pCharBuffer,
charBufferSize * sizeof(BTH_LE_GATT_CHARACTERISTIC));
}
USHORT numChars;
hr = BluetoothGATTGetCharacteristics(
hLEDevice,
pServiceBuffer,
charBufferSize,
pCharBuffer,
&numChars,
BLUETOOTH_GATT_FLAG_NONE);
if (S_OK != hr) {
printf("BluetoothGATTGetCharacteristics - Actual Data %d", hr);
}
if (numChars != charBufferSize) {
printf("buffer size and buffer size actual size mismatch\r\n");
}
}
PBTH_LE_GATT_CHARACTERISTIC currGattChar;
for (int ii = 0; ii <charBufferSize; ii++) {
currGattChar = &pCharBuffer[ii];
USHORT charValueDataSize;
PBTH_LE_GATT_CHARACTERISTIC_VALUE pCharValueBuffer;
USHORT descriptorBufferSize;
hr = BluetoothGATTGetDescriptors(
hLEDevice,
currGattChar,
0,
NULL,
&descriptorBufferSize,
BLUETOOTH_GATT_FLAG_NONE);
if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) {
printf("BluetoothGATTGetDescriptors - Buffer Size %d", hr);
}
PBTH_LE_GATT_DESCRIPTOR pDescriptorBuffer;
if (descriptorBufferSize > 0) {
pDescriptorBuffer = (PBTH_LE_GATT_DESCRIPTOR)
malloc(descriptorBufferSize
* sizeof(BTH_LE_GATT_DESCRIPTOR));
if (NULL == pDescriptorBuffer) {
printf("pDescriptorBuffer out of memory\r\n");
}
else {
RtlZeroMemory(pDescriptorBuffer, descriptorBufferSize);
}
USHORT numDescriptors;
hr = BluetoothGATTGetDescriptors(
hLEDevice,
currGattChar,
descriptorBufferSize,
pDescriptorBuffer,
&numDescriptors,
BLUETOOTH_GATT_FLAG_NONE);
if (S_OK != hr) {
printf("BluetoothGATTGetDescriptors - Actual Data %d", hr);
}
if (numDescriptors != descriptorBufferSize) {
printf("buffer size and buffer size actual size mismatch\r\n");
}
for (int kk = 0; kk<numDescriptors; kk++) {
PBTH_LE_GATT_DESCRIPTOR currGattDescriptor = &pDescriptorBuffer[kk];
USHORT descValueDataSize;
hr = BluetoothGATTGetDescriptorValue(
hLEDevice,
currGattDescriptor,
0,
NULL,
&descValueDataSize,
BLUETOOTH_GATT_FLAG_NONE);
if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) {
printf("BluetoothGATTGetDescriptorValue - Buffer Size %d", hr);
}
PBTH_LE_GATT_DESCRIPTOR_VALUE pDescValueBuffer = (PBTH_LE_GATT_DESCRIPTOR_VALUE)malloc(descValueDataSize);
if (NULL == pDescValueBuffer) {
printf("pDescValueBuffer out of memory\r\n");
}
else {
RtlZeroMemory(pDescValueBuffer, descValueDataSize);
}
hr = BluetoothGATTGetDescriptorValue(
hLEDevice,
currGattDescriptor,
(ULONG)descValueDataSize,
pDescValueBuffer,
NULL,
BLUETOOTH_GATT_FLAG_NONE);
if (S_OK != hr) {
printf("BluetoothGATTGetDescriptorValue - Actual Data %d", hr);
}
if (currGattDescriptor->AttributeHandle < 255) {
BTH_LE_GATT_DESCRIPTOR_VALUE newValue;
RtlZeroMemory(&newValue, sizeof(newValue));
newValue.DescriptorType = ClientCharacteristicConfiguration;
newValue.ClientCharacteristicConfiguration.IsSubscribeToNotification = TRUE;
hr = BluetoothGATTSetDescriptorValue(
hLEDevice,
currGattDescriptor,
&newValue,
BLUETOOTH_GATT_FLAG_NONE);
if (S_OK != hr) {
printf("BluetoothGATTGetDescriptorValue - Actual Data %d", hr);
}
else {
printf("setting notification for serivice handle %d\n", currGattDescriptor->ServiceHandle);
}
}
}
}
BLUETOOTH_GATT_EVENT_HANDLE EventHandle;
if (currGattChar->IsNotifiable) {
printf("Setting Notification for ServiceHandle %d\n", currGattChar->ServiceHandle);
BTH_LE_GATT_EVENT_TYPE EventType = CharacteristicValueChangedEvent;
BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION EventParameterIn;
EventParameterIn.Characteristics[0] = *currGattChar;
EventParameterIn.NumCharacteristics = 1;
if (S_OK != hr) {
printf("BluetoothGATTRegisterEvent - Actual Data %d", hr);
}
}
if (currGattChar->IsReadable) {
hr = BluetoothGATTGetCharacteristicValue(
hLEDevice,
currGattChar,
0,
NULL,
&charValueDataSize,
BLUETOOTH_GATT_FLAG_NONE);
if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) {
printf("BluetoothGATTGetCharacteristicValue - Buffer Size %d", hr);
}
pCharValueBuffer = (PBTH_LE_GATT_CHARACTERISTIC_VALUE)malloc(charValueDataSize);
if (NULL == pCharValueBuffer) {
printf("pCharValueBuffer out of memory\r\n");
}
else {
RtlZeroMemory(pCharValueBuffer, charValueDataSize);
}
hr = BluetoothGATTGetCharacteristicValue(
hLEDevice,
currGattChar,
(ULONG)charValueDataSize,
pCharValueBuffer,
NULL,
BLUETOOTH_GATT_FLAG_NONE);
if (S_OK != hr) {
printf("BluetoothGATTGetCharacteristicValue - Actual Data %d", hr);
}
printf("\n Printing a read (not notifiable) characterstic (maybe) body sensor value");
for (int iii = 0; iii< pCharValueBuffer->DataSize; iii++) { printf("%d", pCharValueBuffer->Data[iii]);
}
printf("\n");
free(pCharValueBuffer);
pCharValueBuffer = NULL;
}
}
while (1) {
Sleep(1000);
UCHAR dataBuffer[sizeof(int)];
BTH_LE_GATT_CHARACTERISTIC_VALUE newValue;
newValue.DataSize = 4;
newValue.Data[0] = 1234;
if (hr != S_OK) {
printf("Failed to write characteristic\n");
}
}
CloseHandle(hLEDevice);
if (GetLastError() != NO_ERROR &&
GetLastError() != ERROR_NO_MORE_ITEMS)
{
return 1;
}
return 0;
}
The code compiled successfully and runs in debug mode. However the near by BLE services are not listed. Also when I close the application from debug mode I get the below errors in the debug console,
onecore\drivers\bluetooth\legacy\win32leadapter\client\lib\gattlegacyapiclient.cpp(164)\BluetoothApis.dll!5177642F: (caller: 51773B3A) ReturnHr(1) tid(2094) 80070006 The handle is invalid. onecore\drivers\bluetooth\legacy\win32leadapter\client\lib\gattlegacyapiclient.cpp(164)\BluetoothApis.dll!5177642F: (caller: 51773B3A) ReturnHr(2) tid(2094) 80070006 The handle is invalid. onecore\drivers\bluetooth\legacy\win32leadapter\client\lib\gattlegacyapiclient.cpp(308)\BluetoothApis.dll!51775956: (caller: 517739ED) ReturnHr(3) tid(2094) 80070006 The handle is invalid.
What I have tried:
My development environment is VS 2017 on Windows 10.
Please help me to sort out this issue