Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/bluetoothapis/gatt.c
8749 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
DWORD size, bytes;
60
61
TRACE( "(%p, %u, %p, %p, %#lx)\n", le_device, count, buf, actual, flags );
62
63
if (flags)
64
FIXME( "Unsupported flags: %#lx\n", flags );
65
66
if (!actual)
67
return E_POINTER;
68
69
if (!!buf != !!count)
70
return E_INVALIDARG;
71
72
size = offsetof( struct winebth_le_device_get_gatt_services_params, services[count] );
73
if (!(services = calloc( 1, size )))
74
return HRESULT_FROM_WIN32( ERROR_NO_SYSTEM_RESOURCES );
75
if (!DeviceIoControl( le_device, IOCTL_WINEBTH_LE_DEVICE_GET_GATT_SERVICES, NULL, 0, services, size, &bytes,
76
NULL ) && GetLastError() != ERROR_MORE_DATA)
77
{
78
free( services );
79
return HRESULT_FROM_WIN32( GetLastError() );
80
}
81
82
*actual = services->count;
83
if (!services->count)
84
{
85
free( services );
86
return S_OK;
87
}
88
if (!buf)
89
{
90
free( services );
91
return HRESULT_FROM_WIN32( ERROR_MORE_DATA );
92
}
93
memcpy( buf, services->services, min( count, services->count ) * sizeof( *buf ) );
94
free( services );
95
if (count < *actual)
96
return HRESULT_FROM_WIN32( ERROR_INVALID_USER_BUFFER );
97
return S_OK;
98
}
99
100
HRESULT WINAPI BluetoothGATTGetCharacteristics( HANDLE device, BTH_LE_GATT_SERVICE *service, USHORT count,
101
BTH_LE_GATT_CHARACTERISTIC *buf, USHORT *actual, ULONG flags )
102
{
103
struct winebth_le_device_get_gatt_characteristics_params *chars;
104
DWORD size, bytes;
105
106
TRACE( "(%p, %s, %u, %p, %p, %#lx)\n", device, debugstr_BTH_LE_GATT_SERVICE( service ), count, buf, actual, flags );
107
108
if (flags)
109
FIXME( "Unsupported flags: %#lx\n", flags );
110
111
if (!actual)
112
return E_POINTER;
113
114
if ((buf && !count) || !service)
115
return E_INVALIDARG;
116
117
size = offsetof( struct winebth_le_device_get_gatt_characteristics_params, characteristics[count] );
118
chars = calloc( 1, size );
119
if (!chars)
120
return HRESULT_FROM_WIN32( ERROR_NO_SYSTEM_RESOURCES );
121
chars->service = *service;
122
if (!DeviceIoControl( device, IOCTL_WINEBTH_LE_DEVICE_GET_GATT_CHARACTERISTICS, chars, size, chars,
123
size, &bytes, NULL ) && GetLastError() != ERROR_MORE_DATA)
124
{
125
free( chars );
126
return HRESULT_FROM_WIN32( GetLastError() );
127
}
128
129
*actual = chars->count;
130
if (!chars->count)
131
{
132
free( chars );
133
return S_OK;
134
}
135
if (!buf)
136
{
137
free( chars );
138
return HRESULT_FROM_WIN32( ERROR_MORE_DATA );
139
}
140
memcpy( buf, chars->characteristics, min( count, chars->count ) * sizeof( *buf ) );
141
free( chars );
142
if (count < *actual)
143
return HRESULT_FROM_WIN32( ERROR_INVALID_USER_BUFFER );
144
return S_OK;
145
}
146
147