From: Vibhav Pant vibhavp@gmail.com
--- dlls/bluetoothapis/main.c | 1 + dlls/winebth.sys/winebth.c | 69 +++++++++++++++++++++++++++++++++++++- include/bthledef.h | 18 ++++++++++ include/wine/winebth.h | 9 +++++ 4 files changed, 96 insertions(+), 1 deletion(-)
diff --git a/dlls/bluetoothapis/main.c b/dlls/bluetoothapis/main.c index d18306d1f58..eaf723c1f36 100644 --- a/dlls/bluetoothapis/main.c +++ b/dlls/bluetoothapis/main.c @@ -35,6 +35,7 @@
#include "initguid.h" #include "bluetoothapis.h" +#include "bthledef.h" #include "bthdef.h" #include "bthioctl.h" #include "wine/winebth.h" diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index a3c420fd7bb..55ae6d6a6e0 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -20,6 +20,7 @@
#include <stdarg.h> #include <stdlib.h> +#include <stdint.h> #include <assert.h>
#include <ntstatus.h> @@ -153,13 +154,79 @@ static NTSTATUS WINAPI dispatch_auth( DEVICE_OBJECT *device, IRP *irp ) return status; }
+static void uuid_to_le( const GUID *uuid, BTH_LE_UUID *le_uuid ) +{ + if (uuid->Data1 <= UINT16_MAX && uuid->Data2 == BTH_LE_ATT_BLUETOOTH_BASE_GUID.Data2 + && uuid->Data3 == BTH_LE_ATT_BLUETOOTH_BASE_GUID.Data3 + && !memcmp( uuid->Data4, BTH_LE_ATT_BLUETOOTH_BASE_GUID.Data4, sizeof( uuid->Data4 ) )) + { + le_uuid->IsShortUuid = TRUE; + le_uuid->Value.ShortUuid = uuid->Data1; + } + else + { + le_uuid->IsShortUuid = FALSE; + le_uuid->Value.LongUuid = *uuid; + } +} + static NTSTATUS bluetooth_remote_device_dispatch( DEVICE_OBJECT *device, struct bluetooth_remote_device *ext, IRP *irp ) { IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); + ULONG outsize = stack->Parameters.DeviceIoControl.OutputBufferLength; ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; NTSTATUS status = irp->IoStatus.Status;
- FIXME( "device=%p, ext=%p, irp=%p, code=%#lx: stub!\n", device, ext, irp, code ); + TRACE( "device=%p, ext=%p, irp=%p, code=%#lx\n", device, ext, irp, code ); + + switch (code) + { + case IOCTL_WINEBTH_LE_DEVICE_GET_GATT_SERVICES: + { + const SIZE_T min_size = offsetof( struct winebth_le_device_get_gatt_services_params, services[0] ); + struct winebth_le_device_get_gatt_services_params *services = irp->AssociatedIrp.SystemBuffer; + struct bluetooth_gatt_service *svc; + SIZE_T rem; + + if (!services || outsize < min_size) + { + status = STATUS_INVALID_USER_BUFFER; + break; + } + + rem = (outsize - min_size)/sizeof( *services->services ); + status = STATUS_SUCCESS; + services->count = 0; + + EnterCriticalSection( &ext->props_cs ); + LIST_FOR_EACH_ENTRY( svc, &ext->gatt_services, struct bluetooth_gatt_service, entry ) + { + if (!svc->primary) + continue; + services->count++; + if (rem) + { + BTH_LE_GATT_SERVICE *info; + + info = &services->services[services->count - 1]; + memset( info, 0, sizeof( *info ) ); + uuid_to_le( &svc->uuid, &info->ServiceUuid ); + info->AttributeHandle = svc->handle; + rem--; + } + } + LeaveCriticalSection( &ext->props_cs ); + + irp->IoStatus.Information = offsetof( struct winebth_le_device_get_gatt_services_params, services[services->count] ); + if (services->count > rem) + status = STATUS_MORE_ENTRIES; + break; + } + default: + FIXME( "Unimplemented IOCTL code: %#lx\n", code ); + } + + irp->IoStatus.Status = status; IoCompleteRequest( irp, IO_NO_INCREMENT ); return status; } diff --git a/include/bthledef.h b/include/bthledef.h index f689260c7fe..d3d0393be99 100644 --- a/include/bthledef.h +++ b/include/bthledef.h @@ -17,5 +17,23 @@ */ #ifndef __BTHLEDEFS_H #define __BTHLEDEFS_H + +typedef struct _BTH_LE_UUID +{ + BOOLEAN IsShortUuid; + union + { + USHORT ShortUuid; + GUID LongUuid; + } Value; +} BTH_LE_UUID, *PBTH_LE_UUID; + +typedef struct _BTH_LE_GATT_SERVICE +{ + BTH_LE_UUID ServiceUuid; + USHORT AttributeHandle; +} BTH_LE_GATT_SERVICE, *PBTH_LE_GATT_SERVICE; + DEFINE_GUID( GUID_BLUETOOTHLE_DEVICE_INTERFACE, 0x781aee18, 0x7733, 0x4ce4, 0xad, 0xd0, 0x91, 0xf4, 0x1c, 0x67, 0xb5, 0x92 ); +DEFINE_GUID( BTH_LE_ATT_BLUETOOTH_BASE_GUID, 0, 0, 0x1000, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb ); #endif diff --git a/include/wine/winebth.h b/include/wine/winebth.h index c785d08d88e..6a2893d6474 100644 --- a/include/wine/winebth.h +++ b/include/wine/winebth.h @@ -36,6 +36,9 @@ #define IOCTL_WINEBTH_RADIO_START_AUTH CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xaa, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_WINEBTH_RADIO_REMOVE_DEVICE CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xab, METHOD_BUFFERED, FILE_ANY_ACCESS)
+/* Get all primary GATT services for the LE device. */ +#define IOCTL_WINEBTH_LE_DEVICE_GET_GATT_SERVICES CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xc0, METHOD_BUFFERED, FILE_ANY_ACCESS) + DEFINE_GUID( GUID_WINEBTH_AUTHENTICATION_REQUEST, 0xca67235f, 0xf621, 0x4c27, 0x85, 0x65, 0xa4, 0xd5, 0x5e, 0xa1, 0x26, 0xe8 );
@@ -75,6 +78,12 @@ struct winebth_radio_start_auth_params BTH_ADDR address; };
+struct winebth_le_device_get_gatt_services_params +{ + ULONG count; + BTH_LE_GATT_SERVICE services[0]; +}; + #pragma pack(pop)
#endif /* __WINEBTH_H__ */