Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/bluetoothapis/tests/gatt.c
5968 views
1
/*
2
* Tests for Bluetooth GATT methods
3
*
4
* Copyright 2025 Vibhav Pant
5
*
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19
*/
20
21
#include <stdarg.h>
22
#include <stdint.h>
23
24
#include <windef.h>
25
#include <winbase.h>
26
#include <winuser.h>
27
#include <winreg.h>
28
#include <setupapi.h>
29
30
#include <setupapi.h>
31
32
#include <initguid.h>
33
#include <bthledef.h>
34
#include <bluetoothleapis.h>
35
#include <devpkey.h>
36
#include <ddk/bthguid.h>
37
38
#include <wine/test.h>
39
40
static void test_for_all_le_devices( int line, void (*func)( HANDLE, void * ), void *data )
41
{
42
char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof( WCHAR )];
43
SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)buffer;
44
SP_DEVICE_INTERFACE_DATA iface_data;
45
HDEVINFO devinfo;
46
DWORD idx = 0, ret, n = 0;
47
BOOL found = FALSE;
48
49
devinfo = SetupDiGetClassDevsW( &GUID_BLUETOOTHLE_DEVICE_INTERFACE, NULL, NULL,
50
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );
51
ret = GetLastError();
52
ok( devinfo != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsW failed: %lu\n", ret );
53
54
iface_detail->cbSize = sizeof( *iface_detail );
55
iface_data.cbSize = sizeof( iface_data );
56
while (SetupDiEnumDeviceInterfaces( devinfo, NULL, &GUID_BLUETOOTHLE_DEVICE_INTERFACE, idx++,
57
&iface_data ))
58
{
59
SP_DEVINFO_DATA devinfo_data;
60
HANDLE device;
61
DEVPROPTYPE type;
62
WCHAR addr_str[13];
63
BOOL success;
64
65
devinfo_data.cbSize = sizeof( devinfo_data );
66
success = SetupDiGetDeviceInterfaceDetailW( devinfo, &iface_data, iface_detail, sizeof( buffer ), NULL,
67
&devinfo_data );
68
ok( success, "SetupDiGetDeviceInterfaceDetailW failed: %lu\n", GetLastError() );
69
addr_str[0] = '\0';
70
success = SetupDiGetDevicePropertyW( devinfo, &devinfo_data, &DEVPKEY_Bluetooth_DeviceAddress, &type,
71
(BYTE *)addr_str, sizeof( addr_str ), NULL, 0 );
72
ok( success, "SetupDiGetDevicePropertyW failed: %lu\n", GetLastError() );
73
ok( type == DEVPROP_TYPE_STRING, "got type %lu\n", type );
74
device = CreateFileW( iface_detail->DevicePath, GENERIC_READ | GENERIC_WRITE,
75
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
76
winetest_push_context( "device %lu", n++ );
77
trace( "Address: %s\n", debugstr_w( addr_str ) );
78
func( device, data );
79
winetest_pop_context();
80
CloseHandle( device );
81
found = TRUE;
82
}
83
84
SetupDiDestroyDeviceInfoList( devinfo );
85
if (!found)
86
skip_( __FILE__, line )( "No LE devices found.\n" );
87
}
88
89
static const char *debugstr_BTH_LE_UUID( const BTH_LE_UUID *uuid )
90
{
91
if (uuid->IsShortUuid)
92
return wine_dbg_sprintf("{ IsShortUuid=1 {%#x} }", uuid->Value.ShortUuid );
93
return wine_dbg_sprintf( "{ IsShortUuid=0 %s }", debugstr_guid( &uuid->Value.LongUuid ) );
94
}
95
96
static const char *debugstr_BTH_LE_GATT_SERVICE( const BTH_LE_GATT_SERVICE *svc )
97
{
98
return wine_dbg_sprintf( "{ %s %#x }", debugstr_BTH_LE_UUID( &svc->ServiceUuid ), svc->AttributeHandle );
99
}
100
101
static const char *debugstr_BTH_LE_GATT_CHARACTERISTIC( const BTH_LE_GATT_CHARACTERISTIC *chrc )
102
{
103
return wine_dbg_sprintf( "{ %#x %s %#x %#x %d %d %d %d %d %d %d %d }", chrc->ServiceHandle,
104
debugstr_BTH_LE_UUID( &chrc->CharacteristicUuid ), chrc->AttributeHandle,
105
chrc->CharacteristicValueHandle, chrc->IsBroadcastable, chrc->IsReadable, chrc->IsWritable,
106
chrc->IsWritableWithoutResponse, chrc->IsSignedWritable, chrc->IsNotifiable,
107
chrc->IsIndicatable, chrc->HasExtendedProperties );
108
}
109
110
static void test_service_BluetoothGATTGetCharacteristics( HANDLE device, BTH_LE_GATT_SERVICE *service )
111
{
112
HRESULT ret;
113
USHORT actual = 0, actual2 = 0, i;
114
BTH_LE_GATT_CHARACTERISTIC *buf = NULL, dummy;
115
116
ret = BluetoothGATTGetCharacteristics( device, service, 0, &dummy, &actual, 0 );
117
ok( ret == E_INVALIDARG, "got ret %#lx\n", ret );
118
119
ret = BluetoothGATTGetCharacteristics( device, NULL, 0, NULL, &actual, 0 );
120
ok( ret == E_INVALIDARG, "got ret %#lx\n", ret );
121
122
ret = BluetoothGATTGetCharacteristics( device, service, 0, NULL, &actual, 0 );
123
ok( ret == HRESULT_FROM_WIN32( ERROR_MORE_DATA ), "got ret %#lx\n", ret );
124
125
ret = BluetoothGATTGetCharacteristics( device, service, actual, NULL, &actual2, 0 );
126
ok( ret == HRESULT_FROM_WIN32( ERROR_MORE_DATA ), "got ret %#lx\n", ret );
127
ok( actual == actual2, "%u != %u\n", actual, actual2 );
128
129
buf = calloc( actual, sizeof( *buf ) );
130
ret = BluetoothGATTGetCharacteristics( device, service, actual, buf, &actual, 0 );
131
ok( ret == S_OK, "BluetoothGATTGetCharacteristics failed: %#lx\n", ret );
132
133
for (i = 0; i < actual; i++)
134
trace( "characteristic %u: %s\n", i, debugstr_BTH_LE_GATT_CHARACTERISTIC( &buf[i] ) );
135
136
free( buf );
137
}
138
139
static void test_device_BluetoothGATTGetServices( HANDLE device, void *param )
140
{
141
HRESULT ret;
142
USHORT actual = 0, i;
143
BTH_LE_GATT_SERVICE *buf;
144
145
ret = BluetoothGATTGetServices( device, 0, NULL, NULL, 0 );
146
ok( ret == E_POINTER, "got ret %#lx\n", ret );
147
148
buf = calloc( 1, sizeof( *buf ) );
149
ret = BluetoothGATTGetServices( device, 1, buf, NULL, 0 );
150
ok( ret == E_POINTER, "got ret %#lx\n", ret );
151
ret = BluetoothGATTGetServices( NULL, 1, buf, &actual, 0 );
152
ok( ret == E_HANDLE, "got ret %#lx\n", ret );
153
ret = BluetoothGATTGetServices( INVALID_HANDLE_VALUE, 1, buf, &actual, 0 );
154
ok( ret == E_HANDLE, "got ret %#lx\n", ret );
155
ret = BluetoothGATTGetServices( device, 0, buf, &actual, 0 );
156
ok( ret == E_INVALIDARG, "got ret %#lx\n", ret );
157
158
ret = BluetoothGATTGetServices( device, 0, NULL, &actual, 0 );
159
ok( ret == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) || ret == HRESULT_FROM_WIN32( ERROR_MORE_DATA ),
160
"BluetoothGATTGetServices failed: %#lx\n", ret );
161
if (!actual)
162
{
163
free( buf );
164
return;
165
}
166
167
buf = calloc( actual, sizeof( *buf ) );
168
ret = BluetoothGATTGetServices( device, actual, buf, &actual, 0 );
169
ok( ret == S_OK, "BluetoothGATTGetServices failed: %#lx\n", ret );
170
if (FAILED( ret ))
171
{
172
skip( "BluetoothGATTGetServices failed.\n" );
173
free( buf );
174
return;
175
}
176
177
for (i = 0; i < actual; i++)
178
{
179
winetest_push_context( "service %u", i );
180
trace( "%s\n", debugstr_BTH_LE_GATT_SERVICE( &buf[i] ) );
181
test_service_BluetoothGATTGetCharacteristics( device, &buf[i] );
182
winetest_pop_context();
183
}
184
185
free( buf );
186
}
187
188
static void test_BluetoothGATTGetServices( void )
189
{
190
HRESULT ret;
191
192
ret = BluetoothGATTGetServices( NULL, 0, NULL, NULL, 0 );
193
ok( ret == E_POINTER, "got ret %#lx\n", ret );
194
195
test_for_all_le_devices( __LINE__, test_device_BluetoothGATTGetServices, NULL );
196
}
197
198
static void test_device_BluetoothGATTGetCharacteristics( HANDLE device, void *data )
199
{
200
HRESULT ret;
201
USHORT actual = 0;
202
BTH_LE_GATT_SERVICE svc = {.ServiceUuid = {TRUE, {.ShortUuid = 0xdead}}, 0xbeef};
203
204
ret = BluetoothGATTGetCharacteristics( device, NULL, 0, NULL, NULL, 0 );
205
ok( ret == E_POINTER, "got ret %#lx\n", ret );
206
207
ret = BluetoothGATTGetCharacteristics( device, &svc, 0, NULL, NULL, 0 );
208
ok( ret == E_POINTER, "got ret %#lx\n", ret );
209
210
ret = BluetoothGATTGetCharacteristics( device, &svc, 0, NULL, &actual, 0 );
211
ok( ret == E_INVALIDARG, "got ret %#lx\n", ret );
212
}
213
214
static void test_BluetoothGATTGetCharacteristic( void )
215
{
216
HRESULT ret;
217
USHORT actual = 0;
218
BTH_LE_GATT_SERVICE svc = {0};
219
220
ret = BluetoothGATTGetCharacteristics( NULL, NULL, 0, NULL, NULL, 0 );
221
ok( ret == E_POINTER, "got ret %#lx\n", ret );
222
223
ret = BluetoothGATTGetCharacteristics( NULL, &svc, 0, NULL, &actual, 0 );
224
ok( ret == E_HANDLE, "got ret %#lx\n", ret );
225
226
ret = BluetoothGATTGetCharacteristics( INVALID_HANDLE_VALUE, &svc, 0, NULL, &actual, 0 );
227
ok( ret == E_HANDLE, "got ret %#lx\n", ret );
228
229
test_for_all_le_devices( __LINE__, test_device_BluetoothGATTGetCharacteristics, NULL );
230
}
231
232
START_TEST( gatt )
233
{
234
test_BluetoothGATTGetServices();
235
test_BluetoothGATTGetCharacteristic();
236
}
237
238