Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/bluetoothapis/gatt.c
5965 views
1
/*
2
* BLE Generic Attribute Profile (GATT) APIs
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
22
#include <stdarg.h>
23
#include <stdint.h>
24
25
#include <windef.h>
26
#include <winbase.h>
27
28
#include <bthsdpdef.h>
29
#include <bluetoothapis.h>
30
#include <bthdef.h>
31
#include <winioctl.h>
32
33
#include <bthledef.h>
34
#include <bluetoothleapis.h>
35
36
#include <wine/winebth.h>
37
#include "wine/debug.h"
38
39
WINE_DEFAULT_DEBUG_CHANNEL( bluetoothapis );
40
41
static const char *debugstr_BTH_LE_UUID( const BTH_LE_UUID *uuid )
42
{
43
if (uuid->IsShortUuid)
44
return wine_dbg_sprintf("{ IsShortUuid=1 {%#x} }", uuid->Value.ShortUuid );
45
return wine_dbg_sprintf( "{ IsShortUuid=0 %s }", debugstr_guid( &uuid->Value.LongUuid ) );
46
}
47
48
static const char *debugstr_BTH_LE_GATT_SERVICE( const BTH_LE_GATT_SERVICE *svc )
49
{
50
if (!svc)
51
return wine_dbg_sprintf( "(null)" );
52
return wine_dbg_sprintf( "{ %s %#x }", debugstr_BTH_LE_UUID( &svc->ServiceUuid ), svc->AttributeHandle );
53
}
54
55
HRESULT WINAPI BluetoothGATTGetServices( HANDLE le_device, USHORT count, BTH_LE_GATT_SERVICE *buf,
56
USHORT *actual, ULONG flags )
57
{
58
struct winebth_le_device_get_gatt_services_params *services;
59
SIZE_T services_count = 1;
60
61
TRACE( "(%p, %u, %p, %p, %#lx)\n", le_device, count, buf, actual, flags );
62
63
if (!actual)
64
return E_POINTER;
65
66
if ((!buf && count) || (buf && !count))
67
return E_INVALIDARG;
68
69
for (;;)
70
{
71
DWORD size, bytes;
72
73
size = offsetof( struct winebth_le_device_get_gatt_services_params, services[services_count] );
74
services = calloc( 1, size );
75
if (!services)
76
return HRESULT_FROM_WIN32( ERROR_NO_SYSTEM_RESOURCES );
77
if (!DeviceIoControl( le_device, IOCTL_WINEBTH_LE_DEVICE_GET_GATT_SERVICES, NULL, 0, services, size, &bytes, NULL )
78
&& GetLastError() != ERROR_MORE_DATA)
79
{
80
free( services );
81
return HRESULT_FROM_WIN32( GetLastError() );
82
}
83
if (!services->count)
84
{
85
*actual = 0;
86
free( services );
87
return S_OK;
88
}
89
if (services_count != services->count)
90
{
91
services_count = services->count;
92
free( services );
93
continue;
94
}
95
break;
96
}
97
98
*actual = services_count;
99
if (!buf)
100
{
101
free( services );
102
return HRESULT_FROM_WIN32( ERROR_MORE_DATA );
103
}
104
105
memcpy( buf, services->services, min( services_count, count ) * sizeof( *buf ) );
106
free( services );
107
if (count < services_count)
108
return HRESULT_FROM_WIN32( ERROR_INVALID_USER_BUFFER );
109
110
return S_OK;
111
}
112
113
HRESULT WINAPI BluetoothGATTGetCharacteristics( HANDLE device, BTH_LE_GATT_SERVICE *service, USHORT count,
114
BTH_LE_GATT_CHARACTERISTIC *buf, USHORT *actual, ULONG flags )
115
{
116
struct winebth_le_device_get_gatt_characteristics_params *chars;
117
DWORD size, bytes;
118
119
TRACE( "(%p, %s, %u, %p, %p, %#lx)\n", device, debugstr_BTH_LE_GATT_SERVICE( service ), count, buf, actual, flags );
120
121
if (flags)
122
FIXME( "Unsupported flags: %#lx\n", flags );
123
124
if (!actual)
125
return E_POINTER;
126
127
if ((buf && !count) || !service)
128
return E_INVALIDARG;
129
130
size = offsetof( struct winebth_le_device_get_gatt_characteristics_params, characteristics[count] );
131
chars = calloc( 1, size );
132
if (!chars)
133
return HRESULT_FROM_WIN32( ERROR_NO_SYSTEM_RESOURCES );
134
chars->service = *service;
135
if (!DeviceIoControl( device, IOCTL_WINEBTH_LE_DEVICE_GET_GATT_CHARACTERISTICS, chars, size, chars,
136
size, &bytes, NULL ) && GetLastError() != ERROR_MORE_DATA)
137
{
138
free( chars );
139
return HRESULT_FROM_WIN32( GetLastError() );
140
}
141
142
*actual = chars->count;
143
if (!chars->count)
144
{
145
free( chars );
146
return S_OK;
147
}
148
if (!buf)
149
{
150
free( chars );
151
return HRESULT_FROM_WIN32( ERROR_MORE_DATA );
152
}
153
memcpy( buf, chars->characteristics, min( count, chars->count ) * sizeof( *buf ) );
154
free( chars );
155
if (count < *actual)
156
return HRESULT_FROM_WIN32( ERROR_INVALID_USER_BUFFER );
157
return S_OK;
158
}
159
160