-
Notifications
You must be signed in to change notification settings - Fork 1
/
PowerMateBluetooth.cpp
209 lines (180 loc) · 6.86 KB
/
PowerMateBluetooth.cpp
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#include "stdafx.h"
#include <stdio.h>
#include <malloc.h>
#include <string>
#include <objbase.h>
#include <windows.h>
#include <setupapi.h>
#pragma comment(lib, "setupapi")
#include <bluetoothleapis.h>
#pragma comment(lib, "bluetoothapis")
#include "Volume.h"
static HANDLE OpenBluetoothDevice(const GUID* interfaceGUID)
{
HANDLE hResult = INVALID_HANDLE_VALUE;
HDEVINFO hDevInfo = SetupDiGetClassDevs(interfaceGUID, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
return hResult;
}
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
ZeroMemory(&deviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for (DWORD devInterfaceIndex = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, interfaceGUID, devInterfaceIndex, &deviceInterfaceData); devInterfaceIndex++)
{
DWORD size = 0;
if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, 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)malloc(size);
if (pInterfaceDetailData)
{
ZeroMemory(pInterfaceDetailData, sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA));
pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
SP_DEVINFO_DATA devInfoData;
ZeroMemory(&devInfoData, sizeof(SP_DEVINFO_DATA));
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, pInterfaceDetailData, size, &size, &devInfoData))
{
OutputDebugFormat(_T("Found PowerMate Bluetooth: %s\n"), pInterfaceDetailData->DevicePath);
hResult = CreateFile(
pInterfaceDetailData->DevicePath,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
}
free(pInterfaceDetailData);
if (hResult != INVALID_HANDLE_VALUE)
{
break;
}
}
}
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return hResult;
}
static void ValueChangedEventHandler(BTH_LE_GATT_EVENT_TYPE EventType, PVOID EventOutParameter, PVOID Context)
{
SCOPE_EVENT("ValueChangedEventHandler");
PBLUETOOTH_GATT_VALUE_CHANGED_EVENT ValueChangedEventParameters = (PBLUETOOTH_GATT_VALUE_CHANGED_EVENT)EventOutParameter;
if (ValueChangedEventParameters->CharacteristicValue->DataSize == 1)
{
char data = ValueChangedEventParameters->CharacteristicValue->Data[0];
switch (data)
{
case 101:
OutputDebugFormat("Notification obtained Knob Press\n");
ToggleMute();
break;
case 103:
OutputDebugFormat("Notification obtained Knob Left\n");
DecreaseVolume();
break;
case 104:
OutputDebugFormat("Notification obtained Knob Right\n");
IncreaseVolume();
break;
default:
OutputDebugFormat("Notification obtained unknown event\n");
break;
}
}
else
{
OutputDebugFormat("Notification obtained unknown data size %d\n", ValueChangedEventParameters->CharacteristicValue->DataSize);
}
}
HANDLE hBluetoothDevice = INVALID_HANDLE_VALUE;
void StartupPowerMateBluetooth()
{
// this guid is from Bluetooth LE Explorer, in the windows store
// the service GUID is the custom service for the custom characteristics on the device
// if this were a heart tracker or something standard it would use a uuid from bluetooth's website
GUID interfaceGUID;
HRESULT result = CLSIDFromString(TEXT("{25598CF7-4240-40A6-9910-080F19F91EBC}"), &interfaceGUID);
assert(result == ERROR_SUCCESS);
// this searches for a device in the windows device registry that implements the service guid above, and opens a HANDLE
hBluetoothDevice = OpenBluetoothDevice(&interfaceGUID);
if (hBluetoothDevice == INVALID_HANDLE_VALUE)
{
return;
}
// fetch the services array for the device
USHORT serviceCount = 0;
AutoFreePointer<BTH_LE_GATT_SERVICE> pServiceBuffer = NULL;
HRESULT hr = BluetoothGATTGetServices(hBluetoothDevice, 0, NULL, &serviceCount, BLUETOOTH_GATT_FLAG_NONE);
if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr)
{
OutputDebugFormat("BluetoothGATTGetServices returned unexpected HRESULT: %d\n", hr);
}
if (serviceCount)
{
pServiceBuffer = (PBTH_LE_GATT_SERVICE)malloc(sizeof(BTH_LE_GATT_SERVICE) * serviceCount);
ZeroMemory(pServiceBuffer, sizeof(BTH_LE_GATT_SERVICE) * serviceCount);
hr = BluetoothGATTGetServices(hBluetoothDevice, serviceCount, pServiceBuffer, &serviceCount, BLUETOOTH_GATT_FLAG_NONE);
if (S_OK != hr)
{
OutputDebugFormat("BluetoothGATTGetServices returned unexpected HRESULT: %d\n", hr);
}
}
// fetch the characteristics
USHORT characteristicCount = 0;
AutoFreePointer<BTH_LE_GATT_CHARACTERISTIC> pCharacteristicBuffer = NULL;
if (serviceCount)
{
hr = BluetoothGATTGetCharacteristics(hBluetoothDevice, pServiceBuffer, 0, NULL, &characteristicCount, BLUETOOTH_GATT_FLAG_NONE);
if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) != hr)
{
OutputDebugFormat("BluetoothGATTGetCharacteristics returned unexpected HRESULT: %d\n", hr);
}
if (characteristicCount)
{
pCharacteristicBuffer = (PBTH_LE_GATT_CHARACTERISTIC)malloc(sizeof(BTH_LE_GATT_CHARACTERISTIC) * characteristicCount);
ZeroMemory(pCharacteristicBuffer, sizeof(BTH_LE_GATT_CHARACTERISTIC) * characteristicCount);
hr = BluetoothGATTGetCharacteristics(hBluetoothDevice, pServiceBuffer, characteristicCount, pCharacteristicBuffer, &characteristicCount, BLUETOOTH_GATT_FLAG_NONE);
if (S_OK != hr)
{
OutputDebugFormat("BluetoothGATTGetCharacteristics returned unexpected HRESULT: %d\n", hr);
}
}
}
// iterate the characteristics and attach event handler
if (characteristicCount >= 2)
{
// 2 is the magic characteristic, BTLE is obnoxious about characteristic identity
PBTH_LE_GATT_CHARACTERISTIC currentCharacteristic = &pCharacteristicBuffer[2];
if (currentCharacteristic->IsNotifiable)
{
BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION eventRegistration;
ZeroMemory(&eventRegistration, sizeof(BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION));
eventRegistration.Characteristics[0] = *currentCharacteristic;
eventRegistration.NumCharacteristics = 1;
BLUETOOTH_GATT_EVENT_HANDLE hValueChangedEvent = INVALID_HANDLE_VALUE;
hr = BluetoothGATTRegisterEvent(hBluetoothDevice, CharacteristicValueChangedEvent, &eventRegistration, ValueChangedEventHandler, NULL, &hValueChangedEvent, BLUETOOTH_GATT_FLAG_NONE);
if (S_OK != hr)
{
OutputDebugFormat("BluetoothGATTRegisterEvent returned unexpected HRESULT: %d\n", hr);
}
else
{
OutputDebugFormat("Registered for Event Notification\n");
}
}
else
{
OutputDebugFormat("Expected characteristic isn't notifiable!\n");
}
}
}
void ShutdownPowerMateBluetooth()
{
CloseHandle(hBluetoothDevice);
}