From: Vibhav Pant <vibhavp@gmail.com> --- dlls/bluetoothapis/bluetoothapis.spec | 2 +- dlls/bluetoothapis/gatt.c | 72 ++++++++++++++++++++++++++- include/bluetoothleapis.h | 1 + include/bthledef.h | 4 ++ 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/dlls/bluetoothapis/bluetoothapis.spec b/dlls/bluetoothapis/bluetoothapis.spec index 9d171a18013..6a4af0ad34e 100644 --- a/dlls/bluetoothapis/bluetoothapis.spec +++ b/dlls/bluetoothapis/bluetoothapis.spec @@ -34,7 +34,7 @@ @ stub BluetoothGATTAbortReliableWrite @ stub BluetoothGATTBeginReliableWrite @ stub BluetoothGATTEndReliableWrite -@ stub BluetoothGATTGetCharacteristicValue +@ stdcall BluetoothGATTGetCharacteristicValue(ptr ptr long ptr ptr long) @ stdcall BluetoothGATTGetCharacteristics(ptr ptr long ptr ptr long) @ stub BluetoothGATTGetDescriptorValue @ stub BluetoothGATTGetDescriptors diff --git a/dlls/bluetoothapis/gatt.c b/dlls/bluetoothapis/gatt.c index 38cd8a1694e..225d95a5749 100644 --- a/dlls/bluetoothapis/gatt.c +++ b/dlls/bluetoothapis/gatt.c @@ -1,7 +1,7 @@ /* * BLE Generic Attribute Profile (GATT) APIs * - * Copyright 2025 Vibhav Pant + * Copyright 2025-2026 Vibhav Pant * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -144,3 +144,73 @@ HRESULT WINAPI BluetoothGATTGetCharacteristics( HANDLE device, BTH_LE_GATT_SERVI return HRESULT_FROM_WIN32( ERROR_INVALID_USER_BUFFER ); return S_OK; } + +HRESULT WINAPI BluetoothGATTGetCharacteristicValue( HANDLE device, BTH_LE_GATT_CHARACTERISTIC *chrc, ULONG size, + BTH_LE_GATT_CHARACTERISTIC_VALUE *val, USHORT *actual, ULONG flags ) +{ + struct winebth_gatt_service_read_characterisitic_value_params *params; + DWORD bytes, outsize, err; + OVERLAPPED ovl = {0}; + HRESULT ret; + + TRACE( "(%p, %p, %lu, %p, %p, %#lx)\n", device, chrc, size, val, actual, flags ); + + if (!device) + return E_HANDLE; + if (!chrc || !(size || val || actual) || (size && size < sizeof( *val ))) + return E_INVALIDARG; + if (size && !val) + return E_POINTER; + outsize = size ? offsetof( struct winebth_gatt_service_read_characterisitic_value_params, + buf[size - offsetof( BTH_LE_GATT_CHARACTERISTIC_VALUE, Data )] ) + : sizeof( *params ); + + if (!(params = calloc( 1, outsize ))) + return HRESULT_FROM_WIN32( ERROR_NO_SYSTEM_RESOURCES ); + + /* FIXME: Figure out what native does when both flags are set. */ + if (flags & BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_DEVICE) + params->from_device = 1; + if (flags & BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_CACHE) + params->from_device = 0; + + params->uuid = chrc->CharacteristicUuid; + params->handle = chrc->AttributeHandle; + ovl.hEvent = CreateEventW( NULL, TRUE, FALSE, NULL ); + err = ERROR_SUCCESS; + if (!DeviceIoControl( device, IOCTL_WINEBTH_GATT_SERVICE_READ_CHARACTERISITIC_VALUE, params, sizeof( *params ), + params, outsize, &bytes, &ovl )) + { + err = GetLastError(); + if (err == ERROR_IO_PENDING) + { + err = ERROR_SUCCESS; + if (!GetOverlappedResult( device, &ovl, &bytes, TRUE )) + err = GetLastError(); + } + } + CloseHandle( ovl.hEvent ); + + if (err) + { + free( params ); + return HRESULT_FROM_WIN32( err == ERROR_PRIVILEGE_NOT_HELD ? ERROR_INVALID_ACCESS : err ); + } + + ret = S_OK; + *actual = max( offsetof( BTH_LE_GATT_CHARACTERISTIC_VALUE, Data[params->size] ), sizeof( *val ) ); + if (val) + { + if (size >= params->size) + { + val->DataSize = params->size; + memcpy( val->Data, params->buf, params->size ); + } + else + ret = HRESULT_FROM_WIN32( ERROR_INVALID_USER_BUFFER ); + } + else + ret = HRESULT_FROM_WIN32( ERROR_MORE_DATA ); + free( params ); + return ret; +} diff --git a/include/bluetoothleapis.h b/include/bluetoothleapis.h index e790eb32aa4..510a35aad2a 100644 --- a/include/bluetoothleapis.h +++ b/include/bluetoothleapis.h @@ -26,6 +26,7 @@ extern "C" { HRESULT WINAPI BluetoothGATTGetServices( HANDLE, USHORT, BTH_LE_GATT_SERVICE *, USHORT *, ULONG ); HRESULT WINAPI BluetoothGATTGetCharacteristics( HANDLE, BTH_LE_GATT_SERVICE *, USHORT, BTH_LE_GATT_CHARACTERISTIC *, USHORT *, ULONG ); +HRESULT WINAPI BluetoothGATTGetCharacteristicValue( HANDLE, BTH_LE_GATT_CHARACTERISTIC *, ULONG, BTH_LE_GATT_CHARACTERISTIC_VALUE *, USHORT *, ULONG ); #ifdef __cplusplus } diff --git a/include/bthledef.h b/include/bthledef.h index 3cc9e01410a..aa2121cb10d 100644 --- a/include/bthledef.h +++ b/include/bthledef.h @@ -22,6 +22,10 @@ extern "C" { #endif +#define BLUETOOTH_GATT_FLAG_NONE 0 +#define BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_DEVICE 0x0004 +#define BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_CACHE 0x0008 + typedef struct _BTH_LE_UUID { BOOLEAN IsShortUuid; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10208