티스토리 뷰

카테고리 없음

aaa

바람사탕 2022. 4. 5. 18:07
반응형

//https://ddangeun.tistory.com/96?msclkid=88afc7c5b48211ecb9a004700ee05c78
//먼저 PC는 블루투스 페어링 하여야 하고, 지정된 UUID를 입력해 데이터를 read할 수 있습니다.
//또한 앞서 프로젝트 속성->c/c++->고급->호출 규칙->stdcall 로 바꾸어줍니다.


//How to get notification values from a HR BLE monitor
//Ensure that you have paired the HR BLE monitor with the computer
 
#include <stdio.h>
#include <windows.h>
//#include <devguid.h>
//#include <regstr.h>
//#include <bthdef.h>
//#include <setupapi.h>
//#include <Bluetoothleapis.h>
#pragma comment(lib, "SetupAPI")
//#pragma comment(lib, "BluetoothApis.lib")

typedef enum _BTH_LE_GATT_EVENT_TYPE {
  CharacteristicValueChangedEvent
} BTH_LE_GATT_EVENT_TYPE;
 






/*
BLUETOOTHAPIS.DLL
BthpEnableA2DPIfPresent
BthpIsConnectableByDefault
BthpSetServiceState
BthpSetServiceStateEx
BthpTranspose32Bits
BluetoothAddressToString
BluetoothDisconnectDevice
BluetoothEnableDiscovery
BluetoothEnableIncomingConnections
BluetoothEnumerateInstalledServices
BluetoothEnumerateInstalledServicesEx
BluetoothEnumerateLocalServices
BluetoothFindBrowseGroupClose
BluetoothFindClassIdClose
BluetoothFindDeviceClose
BluetoothFindFirstBrowseGroup
BluetoothFindFirstClassId
BluetoothFindFirstDevice
BluetoothFindFirstProfileDescriptor
BluetoothFindFirstProtocolDescriptorStack
BluetoothFindFirstProtocolEntry
BluetoothFindFirstRadio
BluetoothFindFirstService
BluetoothFindFirstServiceEx
BluetoothFindNextBrowseGroup
BluetoothFindNextClassId
BluetoothFindNextDevice
BluetoothFindNextProfileDescriptor
BluetoothFindNextProtocolDescriptorStack
BluetoothFindNextProtocolEntry
BluetoothFindNextRadio
BluetoothFindNextService
BluetoothFindProfileDescriptorClose
BluetoothFindProtocolDescriptorStackClose
BluetoothFindProtocolEntryClose
BluetoothFindRadioClose
BluetoothFindServiceClose
BluetoothGATTAbortReliableWrite
BluetoothGATTBeginReliableWrite
BluetoothGATTEndReliableWrite
BluetoothGATTGetCharacteristicValue
BluetoothGATTGetCharacteristics
BluetoothGATTGetDescriptorValue
BluetoothGATTGetDescriptors
BluetoothGATTGetIncludedServices
BluetoothGATTGetServices
BluetoothGATTRegisterEvent
BluetoothGATTSetCharacteristicValue
BluetoothGATTSetDescriptorValue
BluetoothGATTUnregisterEvent
BluetoothGetDeviceInfo
BluetoothGetLocalServiceInfo
BluetoothGetRadioInfo
BluetoothGetServicePnpInstance
BluetoothIsConnectable
BluetoothIsDiscoverable
BluetoothIsVersionAvailable
BluetoothRegisterForAuthentication
BluetoothRegisterForAuthenticationEx
BluetoothRemoveDevice
BluetoothSdpEnumAttributes
BluetoothSdpGetAttributeValue
BluetoothSdpGetContainerElementData
BluetoothSdpGetElementData
BluetoothSdpGetString
BluetoothSendAuthenticationResponse
BluetoothSendAuthenticationResponseEx
BluetoothSetLocalServiceInfo
BluetoothSetServiceState
BluetoothSetServiceStateEx
BluetoothUnregisterAuthentication
BluetoothUpdateDeviceRecord
BthpCheckForUnsupportedGuid
BthpCleanupBRDeviceNode
BthpCleanupDeviceLocalServices
BthpCleanupDeviceRemoteServices
BthpCleanupLEDeviceNodes
BthpEnableAllServices
BthpEnableConnectableAndDiscoverable
BthpEnableRadioSoftware
BthpFindPnpInfo
BthpGATTCloseSession
BthpInnerRecord
BthpIsBluetoothServiceRunning
BthpIsDiscoverable
BthpIsDiscoverableByDefault
BthpIsRadioSoftwareEnabled
BthpIsTopOfServiceGroup
BthpMapStatusToErr
BthpNextRecord
BthpRegisterForAuthentication
BthpTranspose16Bits
BthpTransposeAndExtendBytes
DllCanUnloadNow
FindNextOpenVCOMPort
InstallIncomingComPort
ShouldForceAuthentication

*/
//@
typedef struct _BLUETOOTH_FIND_RADIO_PARAMS {
  DWORD dwSize;
DWORD buf[128];
} BLUETOOTH_FIND_RADIO_PARAMS;
#ifndef HBLUETOOTH_RADIO_FIND
#define HBLUETOOTH_RADIO_FIND HANDLE
#define HDEVINFO HANDLE
#define BTH_ADDR unsigned __int64
#define BLUETOOTH_MAX_NAME_SIZE 256
#define __int3264 __int32
typedef unsigned __int3264 ULONG_PTR;
#define WINSETUPAPI
#endif

typedef struct _SP_DEVINFO_DATA {
  DWORD     cbSize;
  GUID      ClassGuid;
  DWORD     DevInst;
  ULONG_PTR Reserved;
} SP_DEVINFO_DATA, *PSP_DEVINFO_DATA;
typedef struct _SP_DEVICE_INTERFACE_DATA {
  DWORD     cbSize;
  GUID      InterfaceClassGuid;
  DWORD     Flags;
  ULONG_PTR Reserved;
} SP_DEVICE_INTERFACE_DATA, *PSP_DEVICE_INTERFACE_DATA;
typedef struct _BLUETOOTH_ADDRESS {
  union {
    BTH_ADDR ullLong;
    BYTE     rgBytes[6];
  };
} BLUETOOTH_ADDRESS_STRUCT;

typedef struct _BTH_LE_GATT_CHARACTERISTIC_VALUE {
  ULONG DataSize;
  UCHAR Data[1];
} BTH_LE_GATT_CHARACTERISTIC_VALUE, *PBTH_LE_GATT_CHARACTERISTIC_VALUE;

typedef struct _BLUETOOTH_RADIO_INFO {
  DWORD             dwSize;
  BLUETOOTH_ADDRESS_STRUCT address;
  WCHAR             szName[BLUETOOTH_MAX_NAME_SIZE];
  ULONG             ulClassofDevice;
  USHORT            lmpSubversion;
  USHORT            manufacturer;
} BLUETOOTH_RADIO_INFO, *PBLUETOOTH_RADIO_INFO;
typedef struct _BLUETOOTH_GATT_VALUE_CHANGED_EVENT {
  USHORT                            ChangedAttributeHandle;
  size_t                            CharacteristicValueDataSize;
  PBTH_LE_GATT_CHARACTERISTIC_VALUE CharacteristicValue;
} BLUETOOTH_GATT_VALUE_CHANGED_EVENT, *PBLUETOOTH_GATT_VALUE_CHANGED_EVENT;

//@
typedef HBLUETOOTH_RADIO_FIND (*FUN_BluetoothFindFirstRadio)(
        const BLUETOOTH_FIND_RADIO_PARAMS *pbtfrp,
HANDLE                            *phRadio
);
FUN_BluetoothFindFirstRadio BluetoothFindFirstRadio;

typedef BOOL (*FUN_BluetoothFindNextRadio)(
  HBLUETOOTH_RADIO_FIND hFind,
  HANDLE                *phRadio
);
FUN_BluetoothFindNextRadio BluetoothFindNextRadio;

typedef BOOL (*FUN_BluetoothFindRadioClose)(
  HBLUETOOTH_RADIO_FIND hFind
);
FUN_BluetoothFindRadioClose BluetoothFindRadioClose;

typedef DWORD (*FUN_BluetoothGetRadioInfo)(
  HANDLE                hRadio,
  PBLUETOOTH_RADIO_INFO pRadioInfo
);
FUN_BluetoothGetRadioInfo BluetoothGetRadioInfo;

//@
//SetupAPI.dll
typedef WINSETUPAPI HDEVINFO (*FUNC_SetupDiGetClassDevsW)(
  const GUID *ClassGuid,
  PCWSTR     Enumerator,
  HWND       hwndParent,
  DWORD      Flags
);
FUNC_SetupDiGetClassDevsW SetupDiGetClassDevsW;//A함수가 없다


//@
HMODULE BLUETOOTHAPIS_DLL, SetupAPI_dll;
void BT_LoadLibrary()
{
BLUETOOTHAPIS_DLL=LoadLibrary("BLUETOOTHAPIS.DLL");
if(BLUETOOTHAPIS_DLL)
{
BluetoothFindFirstRadio=(FUN_BluetoothFindFirstRadio)GetProcAddress(BLUETOOTHAPIS_DLL,"BluetoothFindFirstRadio");
BluetoothFindNextRadio=(FUN_BluetoothFindNextRadio)GetProcAddress(BLUETOOTHAPIS_DLL,"BluetoothFindNextRadio");
BluetoothFindRadioClose=(FUN_BluetoothFindRadioClose)GetProcAddress(BLUETOOTHAPIS_DLL,"BluetoothFindRadioClose");
BluetoothGetRadioInfo=(FUN_BluetoothGetRadioInfo)GetProcAddress(BLUETOOTHAPIS_DLL,"BluetoothGetRadioInfo");
}
SetupAPI_dll=LoadLibrary("SetupAPI.DLL");
if(SetupAPI_dll)
{
SetupDiGetClassDevsW=(FUNC_SetupDiGetClassDevsW)GetProcAddress(SetupAPI_dll,"SetupDiGetClassDevsW");
}
}
void BT_FreeLibrary()
{
if(BLUETOOTHAPIS_DLL)
{
FreeLibrary(BLUETOOTHAPIS_DLL);
BLUETOOTHAPIS_DLL=0;
}
if(SetupAPI_dll)
{
FreeLibrary(SetupAPI_dll);
SetupAPI_dll=0;
}
}
void test_BT_Find()
{
if(BLUETOOTHAPIS_DLL)
{
HANDLE h;
BLUETOOTH_FIND_RADIO_PARAMS a;
a.dwSize=sizeof(a);
if(BluetoothFindFirstRadio(&a,&h))
{
while(1)
{



if(BluetoothFindNextRadio(&a,&h)==FALSE)break;
}
BluetoothFindRadioClose(h);
}
}
}
class BT_DLL_class
{
public:
BT_DLL_class()
{
BT_LoadLibrary();
test_BT_Find();
}
~BT_DLL_class()
{
BT_FreeLibrary();
}
};
BT_DLL_class __BT_DLL_class;















//@



/*

//Read Data
//this is the notification function
//the way ValueChangedEventParameters is utilized is shown in
//HealthHeartRateService::HeartRateMeasurementEvent()
//a function in Windows Driver Kit (WDK) 8.0 Samples.zip\C++\WDK 8.0 Samples\Bluetooth Low Energy (LE) 
//Generic Attribute (GATT) Profile Drivers\Solution\WpdHealthHeartRate\HealthHeartRateService.cpp
void SomethingHappened(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("HR ");
for(int i=0; i<ValueChangedEventParameters->CharacteristicValue->DataSize;i++) {
printf("%c",ValueChangedEventParameters->CharacteristicValue->Data[i]);
}
// if the first bit is set, then the value is the next 2 bytes.  If it is clear, the value is in the next byte
//The Heart Rate Value Format bit (bit 0 of the Flags field) indicates if the data format of 
//the Heart Rate Measurement Value field is in a format of UINT8 or UINT16. 
//When the Heart Rate Value format is sent in a UINT8 format, the Heart Rate Value 
//Format bit shall be set to 0. When the Heart Rate Value format is sent in a UINT16 
//format, the Heart Rate Value Format bit shall be set to 1
//from this PDF https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=239866
//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("%0x\n", heart_rate);
}
}
 
//this function works to get a handle for a BLE device based on its GUID
//copied from http://social.msdn.microsoft.com/Forums/windowshardware/en-US/e5e1058d-5a64-4e60-b8e2-0ce327c13058/erroraccessdenied-error-when-trying-to-receive-data-from-bluetooth-low-energy-devices?forum=wdk
//credits to Andrey_sh
HANDLE GetBLEHandle(GUID AGuid)
{
HDEVINFO hDI;
SP_DEVICE_INTERFACE_DATA did;
SP_DEVINFO_DATA dd;
GUID BluetoothInterfaceGUID = AGuid;
HANDLE hComm = NULL;
 
hDI = SetupDiGetClassDevsW(&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 ScanBLE(GUID aGuid)
{
SP_DEVINFO_DATA dd;

HDEVINFO hDI = SetupDiGetClassDevsW(&aGuid, NULL, NULL,  DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

if (hDI == INVALID_HANDLE_VALUE) { printf("Invalid handle"); return 1; }

// Enumerate through all devices in Set.
dd.cbSize = sizeof(SP_DEVINFO_DATA);


for (DWORD i = 0; SetupDiEnumDeviceInfo(hDI, i, &dd); i++)
{
bool hasError = false;

DWORD nameData;
LPTSTR nameBuffer = NULL;
DWORD nameBufferSize = 0;

while (!SetupDiGetDeviceRegistryProperty(
hDI,
&dd,
SPDRP_FRIENDLYNAME,
&nameData,
(PBYTE)nameBuffer,
nameBufferSize,
&nameBufferSize))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
// Double the size to avoid problems on W2K MBCS systems per KB 888609.
if (nameBuffer) delete(nameBuffer);
nameBuffer = new wchar_t[nameBufferSize * 2];
}
else
{
hasError = true;
printf("error: could not get name data (%d)\n", GetLastError());
break;
}
}

DWORD addressData;
LPTSTR addressBuffer = NULL;
DWORD addressBufferSize = 0;

while (!SetupDiGetDeviceRegistryProperty(
hDI,
&dd,
SPDRP_HARDWAREID,
&addressData,
(PBYTE)addressBuffer,
addressBufferSize,
&addressBufferSize))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
if (addressBuffer) delete(addressBuffer);
addressBuffer = new wchar_t[addressBufferSize * 2];
}
else
{
hasError = true;
printf("error: could not get address data (%d)\n", GetLastError());
break;
}   
}

LPTSTR deviceIdBuffer = NULL;
DWORD deviceIdBufferSize = 0;

while (!SetupDiGetDeviceInstanceId(
hDI,
&dd,
deviceIdBuffer,
deviceIdBufferSize,
&deviceIdBufferSize))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
if (deviceIdBuffer) delete(deviceIdBuffer);
deviceIdBuffer = new wchar_t[deviceIdBufferSize * 2];
}
else
{
hasError = true;
printf("error: could not get device instance id (%d)\n", GetLastError());
break;
}
}

if (hasError) { continue; }

std::string name = util::to_narrow(nameBuffer);
std::string address = util::to_narrow(addressBuffer);
std::string deviceId = util::to_narrow(deviceIdBuffer);
std::cout << "Found--> Name: " << name << ", Addr: " << address << ", ID: " << deviceId << std::endl;

delete[] nameBuffer;
delete[] addressBuffer;
delete[] deviceIdBuffer;
}

if (hDI) SetupDiDestroyDeviceInfoList(hDI); // SetupDiGetClassDevsW() 함수 사용시 삭제필요.

return 0;
}

int ConnectBLE(GUID aGuid)
{
// Step 1: find the BLE device handle from its GUID
// Get the handle
g_hLEDevice = GetBLEHandle(aGuid);
GetGATTClient(g_hLEDevice);
return 0;

void DisconnectBLE(HANDLE hDevice)
{
if (hDevice) {
// disconnect the remote BLE
WriteBLE(hDevice, &g_pCharacteristicBuffer[0], (UCHAR*)"AT+RESET", 8);

SetLastError(NO_ERROR);
CloseHandle(hDevice);
hDevice = 0;
printf("CloseHandle\n");
if (GetLastError()) cout << "Error: " << GetLastErrorAsString() << endl;
//ERROR_NO_UNICODE_TRANSLATION   1113 (0x459)
}

initBLEBuffers();
}


void callbackBLENotify(BTH_LE_GATT_EVENT_TYPE EventType, PVOID EventOutParameter, PVOID Context)
{
PBLUETOOTH_GATT_VALUE_CHANGED_EVENT ValueChangedEventParameters = (PBLUETOOTH_GATT_VALUE_CHANGED_EVENT)EventOutParameter;
HRESULT hr;
if (0 == ValueChangedEventParameters->CharacteristicValue->DataSize) {
hr = E_FAIL;
printf("Fail: datasize 0\n");
}
else {
for(ULONG i=0; i<ValueChangedEventParameters->CharacteristicValue->DataSize;i++) {
printf("%0x ",ValueChangedEventParameters->CharacteristicValue->Data[i]);
}  
}
}
//Read - Notify를 설정하여 callback 함수로 데이터를 읽어 들인다.
void SetBLENotify(HANDLE hDevice, PBTH_LE_GATT_CHARACTERISTIC pCharacterisic)
{
static BLUETOOTH_GATT_EVENT_HANDLE hRxEvent = NULL;

if (hRxEvent == NULL) {
cout << "Set notify mode: register callback function." << endl;
// set the appropriate callback function when the descriptor change value
if (pCharacterisic->IsNotifiable) {
printf("Setting Notification for ServiceHandle %d\n", pCharacterisic->ServiceHandle);
BTH_LE_GATT_EVENT_TYPE EventType = CharacteristicValueChangedEvent;

BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION EventParameterIn;
EventParameterIn.Characteristics[0] = *pCharacterisic;
EventParameterIn.NumCharacteristics = 1;



HRESULT hr = BluetoothGATTRegisterEvent(
hDevice,
EventType,
&EventParameterIn,
callbackBLENotify,
NULL,
&hRxEvent,
BLUETOOTH_GATT_FLAG_NONE);

if (S_OK != hr) {
printf("BluetoothGATTRegisterEvent - Actual Data %d\n", hr);
}
}
}
else {
cout << "Unset notify mode: unregister callback function." << endl;
if (hRxEvent) {
HRESULT hRet = BluetoothGATTUnregisterEvent(hRxEvent, BLUETOOTH_GATT_FLAG_NONE); // BluetoothGATTRegisterEvent()
if (hRet != S_OK) cout << "BluetoothGATTUnregisterEvent Error: " << GetLastError() << endl; // whatever. we don't care now!
}
hRxEvent = NULL;
}
}



//Write
void WriteBLE(HANDLE hDevice, PBTH_LE_GATT_CHARACTERISTIC pCharacterisic, unsigned char * data, unsigned long length)
{
BTH_LE_GATT_RELIABLE_WRITE_CONTEXT relialeWriteContext = NULL;
if (pCharacterisic == NULL) {
cout << "pTXCharacteristic is null." << endl;
return;
}

if (pCharacterisic->IsSignedWritable || pCharacterisic->IsWritable || pCharacterisic->IsWritableWithoutResponse) {

HRESULT hr = BluetoothGATTBeginReliableWrite(
hDevice,
&relialeWriteContext,
BLUETOOTH_GATT_FLAG_NONE);

if (SUCCEEDED(hr))
{
PBTH_LE_GATT_CHARACTERISTIC_VALUE newValue = (PBTH_LE_GATT_CHARACTERISTIC_VALUE)new UCHAR[sizeof(ULONG)+length];

newValue->DataSize = (ULONG)length;
memcpy(newValue->Data, data, length);

HRESULT hr = BluetoothGATTSetCharacteristicValue(
hDevice,
pCharacterisic,
newValue,
NULL,
BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE);

delete newValue;
}

if (NULL != relialeWriteContext)
{
BluetoothGATTEndReliableWrite(
hDevice,
relialeWriteContext,
BLUETOOTH_GATT_FLAG_NONE);
}
}
else
{
cout << "characteristic is not writable"  << endl;
}

void Bluetooth_start(char *uuid)
{
//Step 1: find the BLE device handle from its GUID
GUID AGuid;
//GUID can be constructed from "{xxx....}" string using CLSID
CLSIDFromString(TEXT(TO_SEARCH_DEVICE_UUID), &AGuid);
 
//now get the handle 
HANDLE hLEDevice = GetBLEHandle(AGuid);
 
 
//Step 2: Get a list of services that the device advertises
// first send 0,NULL as the parameters to BluetoothGATTServices inorder to get the number of
// services in serviceBufferCount
USHORT serviceBufferCount;
// Determine Services Buffer Size
HRESULT hr = BluetoothGATTGetServices(
hLEDevice,
0,
NULL,
&serviceBufferCount,
BLUETOOTH_GATT_FLAG_NONE);
 
if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) {
printf("BluetoothGATTGetServices - Buffer Size %d\n", 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);
}
 
// Retrieve Services
USHORT numServices;
hr = BluetoothGATTGetServices(
hLEDevice,
serviceBufferCount,
pServiceBuffer,
&numServices,
BLUETOOTH_GATT_FLAG_NONE);
 
if (S_OK != hr) {
printf("BluetoothGATTGetServices - Buffer Size %d\n", hr);
}
 
 
//Step 3: now get the list of charactersitics. note how the pServiceBuffer is required from step 2
// Determine Characteristic Buffer Size
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\n", hr);
}
 
PBTH_LE_GATT_CHARACTERISTIC pCharBuffer = NULL;
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));
}
 
// Retrieve Characteristics
USHORT numChars;
hr = BluetoothGATTGetCharacteristics(
hLEDevice,
pServiceBuffer,
charBufferSize,
pCharBuffer,
&numChars,
BLUETOOTH_GATT_FLAG_NONE);
 
if (S_OK != hr) {
printf("BluetoothGATTGetCharacteristics - Actual Data %d\n", hr);
}
 
if (numChars != charBufferSize) {
printf("buffer size and buffer size actual size mismatch\r\n");
}
}
 
 
//Step 4: now get the list of descriptors. note how the pCharBuffer is required from step 3
//descriptors are required as we descriptors that are notification based will have to be written
//once IsSubcribeToNotification set to true, we set the appropriate callback function
//need for setting descriptors for notification according to
//http://social.msdn.microsoft.com/Forums/en-US/11d3a7ce-182b-4190-bf9d-64fefc3328d9/windows-bluetooth-le-apis-event-callbacks?forum=wdk
PBTH_LE_GATT_CHARACTERISTIC currGattChar;
for (int ii = 0; ii < charBufferSize; ii++) {
currGattChar = &pCharBuffer[ii];
USHORT charValueDataSize;
PBTH_LE_GATT_CHARACTERISTIC_VALUE pCharValueBuffer;
 
 
// Determine Descriptor Buffer Size
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\n", 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);
}
 
// Retrieve Descriptors
USHORT numDescriptors;
hr = BluetoothGATTGetDescriptors(
hLEDevice,
currGattChar,
descriptorBufferSize,
pDescriptorBuffer,
&numDescriptors,
BLUETOOTH_GATT_FLAG_NONE);
 
if (S_OK != hr) {
printf("BluetoothGATTGetDescriptors - Actual Data %d\n", 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];

// Determine Descriptor Value Buffer Size
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\n", 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);
}
 
// Retrieve the Descriptor Value
hr = BluetoothGATTGetDescriptorValue(
hLEDevice,
currGattDescriptor,
(ULONG)descValueDataSize,
pDescValueBuffer,
NULL,
BLUETOOTH_GATT_FLAG_NONE);
if (S_OK != hr) {
printf("BluetoothGATTGetDescriptorValue - Actual Data %d\n", hr);
}
//you may also get a descriptor that is read (and not notify) andi am guessing the attribute handle is out of limits
// we set all descriptors that are notifiable to notify us via IsSubstcibeToNotification
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\n", hr);
}
else {
printf("setting notification for serivice handle %d\n", currGattDescriptor->ServiceHandle);
}
 
}
 
}
}
 
 
//set the appropriate callback function when the descriptor change value
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;
hr = BluetoothGATTRegisterEvent(
hLEDevice,
EventType,
&EventParameterIn,
SomethingHappened,
NULL,
&EventHandle,
BLUETOOTH_GATT_FLAG_NONE);
 
if (S_OK != hr) {
printf("BluetoothGATTRegisterEvent - Actual Data %d", hr);
}
}
 
 
if (currGattChar->IsReadable) {//currGattChar->IsReadable
// Determine Characteristic Value Buffer Size
hr = BluetoothGATTGetCharacteristicValue(
hLEDevice,
currGattChar,
0,
NULL,
&charValueDataSize,
BLUETOOTH_GATT_FLAG_NONE);
 
if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr) {
printf("BluetoothGATTGetCharacteristicValue - Buffer Size %d\n", hr);
}
 
pCharValueBuffer = (PBTH_LE_GATT_CHARACTERISTIC_VALUE)malloc(charValueDataSize);
 
if (NULL == pCharValueBuffer) {
printf("pCharValueBuffer out of memory\r\n");
}
else {
RtlZeroMemory(pCharValueBuffer, charValueDataSize);
}
 
// Retrieve the Characteristic Value
hr = BluetoothGATTGetCharacteristicValue(
hLEDevice,
currGattChar,
(ULONG)charValueDataSize,
pCharValueBuffer,
NULL,
BLUETOOTH_GATT_FLAG_NONE);
 
if (S_OK != hr) {
printf("BluetoothGATTGetCharacteristicValue - Actual Data %d", hr);
}
 
//print the characeteristic Value
//for an HR monitor this might be the body sensor location
printf("\n Printing a read (not notifiable) characterstic (maybe) body sensor value");
for (int iii = 0; iii < pCharValueBuffer->DataSize; iii++) {// ideally check ->DataSize before printing
printf("%d", pCharValueBuffer->Data[iii]);
}
printf("\n");
 
 
// Free before going to next iteration, or memory leak.
free(pCharValueBuffer);
pCharValueBuffer = NULL;
}
 
}
 
/ *
//go into an inf loop that sleeps. you will ideally see notifications from the HR device
while (1) {
Sleep(1000);
//printf("look for notification");
}
 
if (GetLastError() != NO_ERROR &&
GetLastError() != ERROR_NO_MORE_ITEMS)
{
// Insert error handling here.
return 1;
}* /
}
void Bluetooth_Close()
{
CloseHandle(hLEDevice);
hLEDevice=0;
}
#define TO_SEARCH_DEVICE_UUID "{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}" //we use UUID for an HR BLE device 
void BLE_main()
{
Bluetooth_start(TO_SEARCH_DEVICE_UUID);
//go into an inf loop that sleeps. you will ideally see notifications from the HR device
while (1)
{
Sleep(1000);
//printf("look for notification");
}
Bluetooth_Close();
}

*/

















int main(int argc, char* argv[], char* envp[])
{
test_BT_Find();
//BLE_main();
return 0;
}

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함