1 /****************************************************************************
2 **
3 ** Copyright (C) 2018 The Qt Company Ltd.
4 ** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtBluetooth module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #ifndef QWINLOWENERGYBLUETOOTH_P_H
42 #define QWINLOWENERGYBLUETOOTH_P_H
43 
44 //
45 //  W A R N I N G
46 //  -------------
47 //
48 // This file is not part of the Qt API.  It exists purely as an
49 // implementation detail.  This header file may change from version to
50 // version without notice, or even be removed.
51 //
52 // We mean it.
53 //
54 
55 #include <QtCore/qlibrary.h>
56 
57 #include <qt_windows.h>
58 
59 #define WIN32_FROM_HRESULT(hr)  \
60     (SUCCEEDED(hr) ? ERROR_SUCCESS : \
61     (HRESULT_FACILITY(hr) == FACILITY_WIN32 ? HRESULT_CODE(hr) : (hr)))
62 
63 #define BLUETOOTH_GATT_FLAG_NONE                        0x00000000
64 #define BLUETOOTH_GATT_FLAG_CONNECTION_ENCRYPTED        0x00000001
65 #define BLUETOOTH_GATT_FLAG_CONNECTION_AUTHENTICATED    0x00000002
66 #define BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_DEVICE      0x00000004
67 #define BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_CACHE       0x00000008
68 #define BLUETOOTH_GATT_FLAG_SIGNED_WRITE                0x00000010
69 #define BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE      0x00000020
70 #define BLUETOOTH_GATT_FLAG_RETURN_ALL                  0x00000040
71 
72 typedef enum _BTH_LE_GATT_DESCRIPTOR_TYPE {
73     CharacteristicExtendedProperties,
74     CharacteristicUserDescription,
75     ClientCharacteristicConfiguration,
76     ServerCharacteristicConfiguration,
77     CharacteristicFormat,
78     CharacteristicAggregateFormat,
79     CustomDescriptor
80 } BTH_LE_GATT_DESCRIPTOR_TYPE, *PBTH_LE_GATT_DESCRIPTOR_TYPE;
81 
82 typedef enum _BTH_LE_GATT_EVENT_TYPE {
83     CharacteristicValueChangedEvent
84 } BTH_LE_GATT_EVENT_TYPE;
85 
86 typedef struct _BTH_LE_UUID {
87     BOOLEAN IsShortUuid;
88     union {
89         USHORT ShortUuid;
90         GUID LongUuid;
91     } Value;
92 } BTH_LE_UUID, *PBTH_LE_UUID;
93 
94 typedef struct _BTH_LE_GATT_SERVICE {
95     BTH_LE_UUID ServiceUuid;
96     USHORT AttributeHandle;
97 } BTH_LE_GATT_SERVICE, *PBTH_LE_GATT_SERVICE;
98 
99 typedef struct _BTH_LE_GATT_CHARACTERISTIC {
100     USHORT ServiceHandle;
101     BTH_LE_UUID CharacteristicUuid;
102     USHORT AttributeHandle;
103     USHORT CharacteristicValueHandle;
104     BOOLEAN IsBroadcastable;
105     BOOLEAN IsReadable;
106     BOOLEAN IsWritable;
107     BOOLEAN IsWritableWithoutResponse;
108     BOOLEAN IsSignedWritable;
109     BOOLEAN IsNotifiable;
110     BOOLEAN IsIndicatable;
111     BOOLEAN HasExtendedProperties;
112 } BTH_LE_GATT_CHARACTERISTIC, *PBTH_LE_GATT_CHARACTERISTIC;
113 
114 typedef struct _BTH_LE_GATT_CHARACTERISTIC_VALUE {
115     ULONG DataSize;
116     UCHAR Data[1];
117 } BTH_LE_GATT_CHARACTERISTIC_VALUE, *PBTH_LE_GATT_CHARACTERISTIC_VALUE;
118 
119 typedef struct _BTH_LE_GATT_DESCRIPTOR {
120     USHORT ServiceHandle;
121     USHORT CharacteristicHandle;
122     BTH_LE_GATT_DESCRIPTOR_TYPE DescriptorType;
123     BTH_LE_UUID DescriptorUuid;
124     USHORT AttributeHandle;
125 } BTH_LE_GATT_DESCRIPTOR, *PBTH_LE_GATT_DESCRIPTOR;
126 
127 typedef struct _BTH_LE_GATT_DESCRIPTOR_VALUE {
128     BTH_LE_GATT_DESCRIPTOR_TYPE DescriptorType;
129     BTH_LE_UUID DescriptorUuid;
130     union {
131         struct {
132             BOOLEAN IsReliableWriteEnabled;
133             BOOLEAN IsAuxiliariesWritable;
134         } CharacteristicExtendedProperties;
135         struct {
136             BOOLEAN IsSubscribeToNotification;
137             BOOLEAN IsSubscribeToIndication;
138         } ClientCharacteristicConfiguration;
139         struct {
140             BOOLEAN IsBroadcast;
141         } ServerCharacteristicConfiguration;
142         struct {
143             UCHAR Format;
144             UCHAR Exponent;
145             BTH_LE_UUID Unit;
146             UCHAR NameSpace;
147             BTH_LE_UUID Description;
148         } CharacteristicFormat;
149     };
150     ULONG DataSize;
151     UCHAR Data[1];
152 } BTH_LE_GATT_DESCRIPTOR_VALUE, *PBTH_LE_GATT_DESCRIPTOR_VALUE;
153 
154 typedef struct _BLUETOOTH_GATT_VALUE_CHANGED_EVENT {
155     USHORT ChangedAttributeHandle;
156     size_t CharacteristicValueDataSize;
157     PBTH_LE_GATT_CHARACTERISTIC_VALUE CharacteristicValue;
158 } BLUETOOTH_GATT_VALUE_CHANGED_EVENT, *PBLUETOOTH_GATT_VALUE_CHANGED_EVENT;
159 
160 typedef struct _BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION {
161     USHORT NumCharacteristics;
162     BTH_LE_GATT_CHARACTERISTIC Characteristics[1];
163 } BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION, *PBLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION;
164 
165 typedef VOID (CALLBACK *PFNBLUETOOTH_GATT_EVENT_CALLBACK)(
166         BTH_LE_GATT_EVENT_TYPE EventType,
167         PVOID EventOutParameter,
168         PVOID Context
169         );
170 
171 typedef ULONG64 BTH_LE_GATT_RELIABLE_WRITE_CONTEXT, *PBTH_LE_GATT_RELIABLE_WRITE_CONTEXT;
172 
173 #define DEFINEFUNC(ret, func, ...) \
174     typedef ret (WINAPI *fp_##func)(__VA_ARGS__); \
175     static fp_##func func;
176 
177 #define RESOLVEFUNC(func) \
178     func = (fp_##func)resolveFunction(library, #func); \
179     if (!func) \
180         return false;
181 
DEFINEFUNC(HRESULT,BluetoothGATTGetServices,HANDLE,USHORT,PBTH_LE_GATT_SERVICE,PUSHORT,ULONG)182 DEFINEFUNC(HRESULT, BluetoothGATTGetServices, HANDLE, USHORT, PBTH_LE_GATT_SERVICE, PUSHORT, ULONG)
183 DEFINEFUNC(HRESULT, BluetoothGATTGetIncludedServices, HANDLE, PBTH_LE_GATT_SERVICE, USHORT, PBTH_LE_GATT_SERVICE, PUSHORT, ULONG)
184 DEFINEFUNC(HRESULT, BluetoothGATTGetCharacteristics, HANDLE, PBTH_LE_GATT_SERVICE, USHORT, PBTH_LE_GATT_CHARACTERISTIC, PUSHORT, ULONG)
185 DEFINEFUNC(HRESULT, BluetoothGATTGetDescriptors, HANDLE, PBTH_LE_GATT_CHARACTERISTIC, USHORT, PBTH_LE_GATT_DESCRIPTOR, PUSHORT, ULONG)
186 DEFINEFUNC(HRESULT, BluetoothGATTGetCharacteristicValue, HANDLE, PBTH_LE_GATT_CHARACTERISTIC, ULONG, PBTH_LE_GATT_CHARACTERISTIC_VALUE, PUSHORT, ULONG)
187 DEFINEFUNC(HRESULT, BluetoothGATTGetDescriptorValue, HANDLE, PBTH_LE_GATT_DESCRIPTOR, ULONG, PBTH_LE_GATT_DESCRIPTOR_VALUE, PUSHORT, ULONG)
188 DEFINEFUNC(HRESULT, BluetoothGATTBeginReliableWrite, HANDLE, PBTH_LE_GATT_RELIABLE_WRITE_CONTEXT, ULONG)
189 DEFINEFUNC(HRESULT, BluetoothGATTEndReliableWrite, HANDLE, BTH_LE_GATT_RELIABLE_WRITE_CONTEXT, ULONG)
190 DEFINEFUNC(HRESULT, BluetoothGATTAbortReliableWrite, HANDLE, BTH_LE_GATT_RELIABLE_WRITE_CONTEXT, ULONG)
191 DEFINEFUNC(HRESULT, BluetoothGATTSetCharacteristicValue, HANDLE, PBTH_LE_GATT_CHARACTERISTIC, PBTH_LE_GATT_CHARACTERISTIC_VALUE, BTH_LE_GATT_RELIABLE_WRITE_CONTEXT, ULONG)
192 DEFINEFUNC(HRESULT, BluetoothGATTSetDescriptorValue, HANDLE, PBTH_LE_GATT_DESCRIPTOR, PBTH_LE_GATT_DESCRIPTOR_VALUE, ULONG)
193 DEFINEFUNC(HRESULT, BluetoothGATTRegisterEvent, HANDLE, BTH_LE_GATT_EVENT_TYPE, PVOID, PFNBLUETOOTH_GATT_EVENT_CALLBACK, PVOID, PHANDLE, ULONG)
194 DEFINEFUNC(HRESULT, BluetoothGATTUnregisterEvent, HANDLE, ULONG)
195 
196 static inline QFunctionPointer resolveFunction(QLibrary *library, const char *func)
197 {
198     QFunctionPointer symbolFunctionPointer = library->resolve(func);
199     if (!symbolFunctionPointer)
200         qWarning("Cannot resolve '%s' in '%s'.", func, qPrintable(library->fileName()));
201     return symbolFunctionPointer;
202 }
203 
resolveFunctions(QLibrary * library)204 static inline bool resolveFunctions(QLibrary *library)
205 {
206     if (!library->isLoaded()) {
207         library->setFileName(QStringLiteral("bluetoothapis"));
208         if (!library->load()) {
209             qWarning("Unable to load '%s' library.", qPrintable(library->fileName()));
210             return false;
211         }
212     }
213 
214     RESOLVEFUNC(BluetoothGATTGetServices)
215     RESOLVEFUNC(BluetoothGATTGetIncludedServices)
216     RESOLVEFUNC(BluetoothGATTGetCharacteristics)
217     RESOLVEFUNC(BluetoothGATTGetDescriptors)
218     RESOLVEFUNC(BluetoothGATTGetCharacteristicValue)
219     RESOLVEFUNC(BluetoothGATTGetDescriptorValue)
220     RESOLVEFUNC(BluetoothGATTBeginReliableWrite)
221     RESOLVEFUNC(BluetoothGATTEndReliableWrite)
222     RESOLVEFUNC(BluetoothGATTAbortReliableWrite)
223     RESOLVEFUNC(BluetoothGATTSetCharacteristicValue)
224     RESOLVEFUNC(BluetoothGATTSetDescriptorValue)
225     RESOLVEFUNC(BluetoothGATTRegisterEvent)
226     RESOLVEFUNC(BluetoothGATTUnregisterEvent)
227 
228     return true;
229 }
230 
231 #endif // QWINLOWENERGYBLUETOOTH_P_H
232