This MR introduces an initial implementation for `IOCTL_BTH_GET_DEVICE_INFO` which returns a list of known/cached devices by BlueZ.
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 118 +++++++++++++++++++++++++++++-- dlls/winebth.sys/unixlib.c | 9 +++ dlls/winebth.sys/unixlib.h | 7 ++ dlls/winebth.sys/winebluetooth.c | 9 +++ dlls/winebth.sys/winebth.c | 51 +++++++++++++ dlls/winebth.sys/winebth_priv.h | 31 ++++++++ 6 files changed, 221 insertions(+), 4 deletions(-)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 1ab7ebaea74..d8a4247d453 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -115,6 +115,7 @@ const int bluez_timeout = -1;
#define BLUEZ_DEST "org.bluez" #define BLUEZ_INTERFACE_ADAPTER "org.bluez.Adapter1" +#define BLUEZ_INTERFACE_DEVICE "org.bluez.Device1"
#define DO_FUNC( f ) typeof( f ) (*p_##f) DBUS_FUNCS; @@ -491,6 +492,40 @@ static void bluez_radio_prop_from_dict_entry( const char *prop_name, DBusMessage } }
+static void bluez_device_prop_from_dict_entry( const char *prop_name, DBusMessageIter *variant, + struct winebluetooth_device_properties *props, + winebluetooth_device_props_mask_t *props_mask, + winebluetooth_device_props_mask_t wanted_props_mask ) +{ + TRACE_( dbus )( "(%s, %p, %p, %p, %#x)\n", debugstr_a( prop_name ), variant, props, props_mask, + wanted_props_mask ); + + + if (wanted_props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_NAME && + !strcmp( prop_name, "Name" ) && + p_dbus_message_iter_get_arg_type( variant ) == DBUS_TYPE_STRING) + { + const char *name_str; + SIZE_T len; + + p_dbus_message_iter_get_basic( variant, &name_str ); + len = strlen( name_str ); + memcpy( props->name, name_str, min( len + 1, ARRAYSIZE( props->name ) ) ); + props->name[ARRAYSIZE( props->name ) - 1] = '\0'; + *props_mask |= WINEBLUETOOTH_DEVICE_PROPERTY_NAME; + } + else if (wanted_props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS && + !strcmp( prop_name, "Address" ) && + p_dbus_message_iter_get_arg_type( variant ) == DBUS_TYPE_STRING) + { + const char *addr_str; + + p_dbus_message_iter_get_basic( variant, &addr_str ); + parse_mac_address( addr_str, props->address.rgBytes ); + *props_mask |= WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS; + } +} + static NTSTATUS bluez_adapter_get_props_async( void *connection, const char *radio_object_path, DBusPendingCall **call ) { @@ -520,6 +555,8 @@ struct bluez_watcher_ctx
/* struct bluez_init_entry */ struct list initial_radio_list; + /* struct bluez_init_entry */ + struct list initial_device_list;
/* struct bluez_watcher_event */ struct list event_list; @@ -529,6 +566,7 @@ struct bluez_init_entry { union { struct winebluetooth_watcher_event_radio_added radio; + struct winebluetooth_watcher_event_device_added device; } object; struct list entry; }; @@ -929,6 +967,10 @@ static void bluez_watcher_free( struct bluez_watcher_ctx *watcher ) case BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_PROPERTIES_CHANGED: unix_name_free( (struct unix_name *)event1->event.radio_props_changed.radio.handle ); break; + case BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_ADDED: + unix_name_free( (struct unix_name *)event1->event.device_added.radio.handle ); + unix_name_free( (struct unix_name *)event1->event.device_added.device.handle ); + break; } free( event1 ); } @@ -955,7 +997,7 @@ NTSTATUS bluez_watcher_init( void *connection, void **ctx ) } watcher_ctx->init_device_list_call = call; list_init( &watcher_ctx->initial_radio_list ); - + list_init( &watcher_ctx->initial_device_list ); list_init( &watcher_ctx->event_list );
/* The bluez_dbus_loop thread will free up the watcher when the disconnect message is processed (i.e, @@ -1010,7 +1052,8 @@ void bluez_watcher_close( void *connection, void *ctx ) p_dbus_connection_remove_filter( connection, bluez_filter, ctx ); }
-static NTSTATUS bluez_build_initial_device_lists( DBusMessage *reply, struct list *adapter_list ) +static NTSTATUS bluez_build_initial_device_lists( DBusMessage *reply, struct list *adapter_list, + struct list *device_list ) { DBusMessageIter dict, paths_iter, iface_iter, prop_iter; const char *path; @@ -1062,10 +1105,65 @@ static NTSTATUS bluez_build_initial_device_lists( DBusMessage *reply, struct lis debugstr_a( radio_name->str ), radio_name ); break; } + else if (!strcmp( iface, BLUEZ_INTERFACE_DEVICE )) + { + const char *prop_name; + DBusMessageIter variant; + struct bluez_init_entry *init_device; + struct unix_name *device_name, *radio_name = NULL; + + init_device = calloc( 1, sizeof( *init_device ) ); + if (!init_device) + { + status = STATUS_NO_MEMORY; + goto done; + } + device_name = unix_name_get_or_create( path ); + if (!device_name) + { + free( init_device ); + status = STATUS_NO_MEMORY; + goto done; + } + init_device->object.device.device.handle = (UINT_PTR)device_name; + + while((prop_name = bluez_next_dict_entry( &prop_iter, &variant ))) + { + if (!strcmp( prop_name, "Adapter" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_OBJECT_PATH) + { + const char *path; + p_dbus_message_iter_get_basic( &variant, &path ); + radio_name = unix_name_get_or_create( path ); + if (!radio_name) + { + unix_name_free( device_name ); + free( init_device ); + status = STATUS_NO_MEMORY; + goto done; + } + init_device->object.device.radio.handle = (UINT_PTR)radio_name; + } + else + bluez_device_prop_from_dict_entry( prop_name, &variant, &init_device->object.device.props, + &init_device->object.device.known_props_mask, + WINEBLUETOOTH_DEVICE_ALL_PROPERTIES ); + } + if (!init_device->object.device.radio.handle) + { + unix_name_free( device_name ); + free( init_device ); + ERR( "Could not find the associated adapter for device %s\n", debugstr_a( path ) ); + break; + } + list_add_tail( device_list, &init_device->entry ); + TRACE( "Found BlueZ org.bluez.Device1 object %s: %p\n", debugstr_a( path ), device_name ); + break; + } } }
- TRACE( "Initial device list: radios: %d\n", list_count( adapter_list ) ); + TRACE( "Initial device list: radios: %d, devices: %d\n", list_count( adapter_list ), list_count( device_list ) ); done: return status; } @@ -1083,6 +1181,17 @@ static BOOL bluez_watcher_event_queue_ready( struct bluez_watcher_ctx *ctx, stru free( radio ); return TRUE; } + if (!list_empty( &ctx->initial_device_list )) + { + struct bluez_init_entry *device; + + device = LIST_ENTRY( list_head( &ctx->initial_device_list ), struct bluez_init_entry, entry ); + event->event_type = BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_ADDED; + event->event_data.device_added = device->object.device; + list_remove( &device->entry ); + free( device ); + return TRUE; + } if (!list_empty( &ctx->event_list )) { struct bluez_watcher_event *watcher_event = @@ -1147,7 +1256,8 @@ NTSTATUS bluez_dbus_loop( void *c, void *watcher, p_dbus_connection_unref( connection ); return STATUS_NO_MEMORY; } - status = bluez_build_initial_device_lists( reply, &watcher_ctx->initial_radio_list ); + status = bluez_build_initial_device_lists( reply, &watcher_ctx->initial_radio_list, + &watcher_ctx->initial_device_list ); p_dbus_message_unref( reply ); if (status != STATUS_SUCCESS) { diff --git a/dlls/winebth.sys/unixlib.c b/dlls/winebth.sys/unixlib.c index b7bf4012ce3..a80a51d9cf1 100644 --- a/dlls/winebth.sys/unixlib.c +++ b/dlls/winebth.sys/unixlib.c @@ -164,6 +164,13 @@ static NTSTATUS bluetooth_adapter_set_prop( void *arg ) return bluez_adapter_set_prop( dbus_connection, params ); }
+static NTSTATUS bluetooth_device_free( void *args ) +{ + struct bluetooth_device_free_params *params = args; + unix_name_free( params->device ); + return STATUS_SUCCESS; +} + static NTSTATUS bluetooth_get_event( void *args ) { struct bluetooth_get_event_params *params = args; @@ -181,6 +188,8 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { bluetooth_adapter_get_unique_name, bluetooth_adapter_free,
+ bluetooth_device_free, + bluetooth_get_event, };
diff --git a/dlls/winebth.sys/unixlib.h b/dlls/winebth.sys/unixlib.h index f1530bcde19..002cc2cc3aa 100644 --- a/dlls/winebth.sys/unixlib.h +++ b/dlls/winebth.sys/unixlib.h @@ -49,6 +49,11 @@ struct bluetooth_adapter_free_params unix_name_t adapter; };
+struct bluetooth_device_free_params +{ + unix_name_t device; +}; + struct bluetooth_adapter_get_unique_name_params { unix_name_t adapter; @@ -79,6 +84,8 @@ enum bluetoothapis_funcs unix_bluetooth_adapter_get_unique_name, unix_bluetooth_adapter_free,
+ unix_bluetooth_device_free, + unix_bluetooth_get_event,
unix_funcs_count diff --git a/dlls/winebth.sys/winebluetooth.c b/dlls/winebth.sys/winebluetooth.c index a477e00fc08..6ebfe55ac28 100644 --- a/dlls/winebth.sys/winebluetooth.c +++ b/dlls/winebth.sys/winebluetooth.c @@ -77,6 +77,15 @@ void winebluetooth_radio_free( winebluetooth_radio_t radio ) UNIX_BLUETOOTH_CALL( bluetooth_adapter_free, &args ); }
+void winebluetooth_device_free( winebluetooth_device_t device ) +{ + struct bluetooth_device_free_params args = {0}; + TRACE( "(%p)\n", (void *)device.handle ); + + args.device = device.handle; + UNIX_BLUETOOTH_CALL( bluetooth_device_free, &args ); +} + NTSTATUS winebluetooth_get_event( struct winebluetooth_event *result ) { struct bluetooth_get_event_params params = {0}; diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 5bdea771d6f..43631e02967 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -78,6 +78,19 @@ struct bluetooth_radio WCHAR *hw_name; UNICODE_STRING bthport_symlink_name; UNICODE_STRING bthradio_symlink_name; + + CRITICAL_SECTION remote_devices_cs; + struct list remote_devices; /* Guarded by remote_devices_cs */ +}; + +struct bluetooth_remote_device +{ + struct list entry; + + winebluetooth_device_t device; + CRITICAL_SECTION props_cs; + winebluetooth_device_props_mask_t props_mask; /* Guarded by props_cs */ + struct winebluetooth_device_properties props; /* Guarded by props_cs */ };
static NTSTATUS WINAPI dispatch_bluetooth( DEVICE_OBJECT *device, IRP *irp ) @@ -270,8 +283,10 @@ static void add_bluetooth_radio( struct winebluetooth_watcher_event_radio_added device->hw_name = hw_name; device->props = event.props; device->props_mask = event.props_mask; + list_init( &device->remote_devices );
InitializeCriticalSection( &device->props_cs ); + InitializeCriticalSection( &device->remote_devices_cs );
EnterCriticalSection( &device_list_cs ); list_add_tail( &device_list, &device->entry ); @@ -330,6 +345,39 @@ static void update_bluetooth_radio_properties( struct winebluetooth_watcher_even LeaveCriticalSection( &device_list_cs ); }
+static void bluetooth_radio_add_remote_device( struct winebluetooth_watcher_event_device_added event ) +{ + struct bluetooth_radio *radio; + + EnterCriticalSection( &device_list_cs ); + LIST_FOR_EACH_ENTRY( radio, &device_list, struct bluetooth_radio, entry ) + { + if (winebluetooth_radio_equal( event.radio, radio->radio )) + { + struct bluetooth_remote_device *remote_device; + + remote_device = calloc( 1, sizeof( *remote_device ) ); + if (!remote_device) + { + winebluetooth_device_free( event.device ); + break; + } + + InitializeCriticalSection( &remote_device->props_cs ); + remote_device->device = event.device; + remote_device->props_mask = event.known_props_mask; + remote_device->props = event.props; + + EnterCriticalSection( &radio->remote_devices_cs ); + list_add_tail( &radio->remote_devices, &remote_device->entry ); + LeaveCriticalSection( &radio->remote_devices_cs ); + break; + } + } + LeaveCriticalSection( &device_list_cs ); + winebluetooth_radio_free( event.radio ); +} + static DWORD CALLBACK bluetooth_event_loop_thread_proc( void *arg ) { NTSTATUS status; @@ -356,6 +404,9 @@ static DWORD CALLBACK bluetooth_event_loop_thread_proc( void *arg ) case BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_PROPERTIES_CHANGED: update_bluetooth_radio_properties( event->event_data.radio_props_changed ); break; + case BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_ADDED: + bluetooth_radio_add_remote_device( event->event_data.device_added ); + break; default: FIXME( "Unknown bluetooth watcher event code: %#x\n", event->event_type ); } diff --git a/dlls/winebth.sys/winebth_priv.h b/dlls/winebth.sys/winebth_priv.h index 79ef0bd457a..cdedea7bab1 100644 --- a/dlls/winebth.sys/winebth_priv.h +++ b/dlls/winebth.sys/winebth_priv.h @@ -133,6 +133,19 @@ typedef UINT16 winebluetooth_radio_props_mask_t; WINEBLUETOOTH_RADIO_PROPERTY_VERSION | WINEBLUETOOTH_RADIO_PROPERTY_DISCOVERING | \ WINEBLUETOOTH_RADIO_PROPERTY_PAIRABLE)
+typedef struct +{ + UINT_PTR handle; +} winebluetooth_device_t; + +typedef UINT16 winebluetooth_device_props_mask_t; + +#define WINEBLUETOOTH_DEVICE_PROPERTY_NAME (1) +#define WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS (1 << 1) + +#define WINEBLUETOOTH_DEVICE_ALL_PROPERTIES \ + (WINEBLUETOOTH_DEVICE_PROPERTY_NAME | WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS) + union winebluetooth_property { BOOL boolean; @@ -154,6 +167,12 @@ struct winebluetooth_radio_properties BYTE version; };
+struct winebluetooth_device_properties +{ + BLUETOOTH_ADDRESS address; + CHAR name[BLUETOOTH_MAX_NAME_SIZE]; +}; + NTSTATUS winebluetooth_radio_get_unique_name( winebluetooth_radio_t radio, char *name, SIZE_T *size ); void winebluetooth_radio_free( winebluetooth_radio_t radio ); @@ -165,11 +184,14 @@ NTSTATUS winebluetooth_radio_set_property( winebluetooth_radio_t radio, ULONG prop_flag, union winebluetooth_property *property );
+void winebluetooth_device_free( winebluetooth_device_t device ); + enum winebluetooth_watcher_event_type { BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_ADDED, BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_REMOVED, BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_PROPERTIES_CHANGED, + BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_ADDED, };
struct winebluetooth_watcher_event_radio_added @@ -188,11 +210,20 @@ struct winebluetooth_watcher_event_radio_props_changed winebluetooth_radio_t radio; };
+struct winebluetooth_watcher_event_device_added +{ + winebluetooth_device_props_mask_t known_props_mask; + struct winebluetooth_device_properties props; + winebluetooth_device_t device; + winebluetooth_radio_t radio; +}; + union winebluetooth_watcher_event_data { struct winebluetooth_watcher_event_radio_added radio_added; winebluetooth_radio_t radio_removed; struct winebluetooth_watcher_event_radio_props_changed radio_props_changed; + struct winebluetooth_watcher_event_device_added device_added; };
struct winebluetooth_watcher_event
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/winebth.c | 62 ++++++++++++++++++++++++++++++++++++++ include/bthioctl.h | 7 +++++ 2 files changed, 69 insertions(+)
diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 43631e02967..5d1f128c491 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -148,6 +148,68 @@ static NTSTATUS WINAPI dispatch_bluetooth( DEVICE_OBJECT *device, IRP *irp ) status = STATUS_SUCCESS; break; } + case IOCTL_BTH_GET_DEVICE_INFO: + { + BTH_DEVICE_INFO_LIST *list = irp->AssociatedIrp.SystemBuffer; + struct bluetooth_remote_device *device; + SIZE_T rem_devices; + + FIXME("IOCTL_BTH_GET_DEVICE_INFO: semi-stub!\n"); + + if (!list) + { + status = STATUS_INVALID_PARAMETER; + break; + } + if (outsize < sizeof( *list )) + { + status = STATUS_INVALID_BUFFER_SIZE; + break; + } + + rem_devices = (outsize - sizeof( *list ))/sizeof(BTH_DEVICE_INFO) + 1; + status = STATUS_SUCCESS; + irp->IoStatus.Information = 0; + + EnterCriticalSection( &ext->remote_devices_cs ); + LIST_FOR_EACH_ENTRY( device, &ext->remote_devices, struct bluetooth_remote_device, entry ) + { + list->numOfDevices++; + if (rem_devices > 0) + { + BTH_DEVICE_INFO *info; + + info = &list->deviceList[list->numOfDevices - 1]; + memset( info, 0, sizeof( *info ) ); + + EnterCriticalSection( &device->props_cs ); + if (device->props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_NAME) + { + info->flags |= BDIF_NAME; + memcpy( info->name, device->props.name, sizeof( info->name ) ); + } + if (device->props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS) + { + info->flags |= BDIF_ADDRESS; + info->address = RtlUlonglongByteSwap( device->props.address.ullLong ); + } + LeaveCriticalSection( &device->props_cs ); + + irp->IoStatus.Information += sizeof( *info ); + rem_devices--; + } + } + LeaveCriticalSection( &ext->remote_devices_cs ); + + irp->IoStatus.Information += sizeof( *list ); + if (list->numOfDevices) + irp->IoStatus.Information -= sizeof( BTH_DEVICE_INFO ); + + /* The output buffer needs to be exactly sized. */ + if (rem_devices) + status = STATUS_INVALID_BUFFER_SIZE; + break; + } case IOCTL_WINEBTH_RADIO_SET_FLAG: { const struct winebth_radio_set_flag_params *params = irp->AssociatedIrp.SystemBuffer; diff --git a/include/bthioctl.h b/include/bthioctl.h index a822c054f6c..56a665e9f41 100644 --- a/include/bthioctl.h +++ b/include/bthioctl.h @@ -23,6 +23,7 @@ #define __BTHIOCTL_H__
#define IOCTL_BTH_GET_LOCAL_INFO CTL_CODE(FILE_DEVICE_BLUETOOTH, 0x00, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_BTH_GET_DEVICE_INFO CTL_CODE(FILE_DEVICE_BLUETOOTH, 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
#include <pshpack1.h>
@@ -43,6 +44,12 @@ typedef struct _BTH_LOCAL_RADIO_INFO BTH_RADIO_INFO radioInfo; } BTH_LOCAL_RADIO_INFO, *PBTH_LOCAL_RADIO_INFO;
+typedef struct _BTH_DEVICE_INFO_LIST +{ + ULONG numOfDevices; + BTH_DEVICE_INFO deviceList[1]; +} BTH_DEVICE_INFO_LIST, *PBTH_DEVICE_INFO_LIST; + #include <poppack.h>
#endif /* __BTHIOCTL_H__ */
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 20 ++++++++++++++++++++ dlls/winebth.sys/winebth.c | 6 ++++++ dlls/winebth.sys/winebth_priv.h | 13 +++++++++---- 3 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index d8a4247d453..bebe11e4f2b 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -524,6 +524,26 @@ static void bluez_device_prop_from_dict_entry( const char *prop_name, DBusMessag parse_mac_address( addr_str, props->address.rgBytes ); *props_mask |= WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS; } + else if (wanted_props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_CONNECTED && + !strcmp( prop_name, "Connected" ) && + p_dbus_message_iter_get_arg_type( variant ) == DBUS_TYPE_BOOLEAN) + { + dbus_bool_t connected; + + p_dbus_message_iter_get_basic( variant, &connected ); + props->connected = !!connected; + *props_mask |= WINEBLUETOOTH_DEVICE_PROPERTY_CONNECTED; + } + else if (wanted_props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_PAIRED && + !strcmp( prop_name, "Paired" ) && + p_dbus_message_iter_get_arg_type( variant ) == DBUS_TYPE_BOOLEAN) + { + dbus_bool_t paired; + + p_dbus_message_iter_get_basic( variant, &paired ); + props->paired = !!paired; + *props_mask |= WINEBLUETOOTH_DEVICE_PROPERTY_PAIRED; + } }
static NTSTATUS bluez_adapter_get_props_async( void *connection, const char *radio_object_path, diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 5d1f128c491..5c0376c4324 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -193,6 +193,12 @@ static NTSTATUS WINAPI dispatch_bluetooth( DEVICE_OBJECT *device, IRP *irp ) info->flags |= BDIF_ADDRESS; info->address = RtlUlonglongByteSwap( device->props.address.ullLong ); } + if (device->props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_CONNECTED && + device->props.connected) + info->flags |= BDIF_CONNECTED; + if (device->props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_PAIRED && + device->props.paired) + info->flags |= (BDIF_PAIRED | BDIF_PERSONAL); LeaveCriticalSection( &device->props_cs );
irp->IoStatus.Information += sizeof( *info ); diff --git a/dlls/winebth.sys/winebth_priv.h b/dlls/winebth.sys/winebth_priv.h index cdedea7bab1..0646a18409f 100644 --- a/dlls/winebth.sys/winebth_priv.h +++ b/dlls/winebth.sys/winebth_priv.h @@ -140,11 +140,14 @@ typedef struct
typedef UINT16 winebluetooth_device_props_mask_t;
-#define WINEBLUETOOTH_DEVICE_PROPERTY_NAME (1) -#define WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS (1 << 1) +#define WINEBLUETOOTH_DEVICE_PROPERTY_NAME (1) +#define WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS (1 << 1) +#define WINEBLUETOOTH_DEVICE_PROPERTY_CONNECTED (1 << 2) +#define WINEBLUETOOTH_DEVICE_PROPERTY_PAIRED (1 << 3)
-#define WINEBLUETOOTH_DEVICE_ALL_PROPERTIES \ - (WINEBLUETOOTH_DEVICE_PROPERTY_NAME | WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS) +#define WINEBLUETOOTH_DEVICE_ALL_PROPERTIES \ + (WINEBLUETOOTH_DEVICE_PROPERTY_NAME | WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS | \ + WINEBLUETOOTH_DEVICE_PROPERTY_CONNECTED | WINEBLUETOOTH_DEVICE_PROPERTY_PAIRED)
union winebluetooth_property { @@ -171,6 +174,8 @@ struct winebluetooth_device_properties { BLUETOOTH_ADDRESS address; CHAR name[BLUETOOTH_MAX_NAME_SIZE]; + BOOL connected; + BOOL paired; };
NTSTATUS winebluetooth_radio_get_unique_name( winebluetooth_radio_t radio, char *name,
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 58 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index bebe11e4f2b..b3bd366370f 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -796,6 +796,64 @@ static DBusHandlerResult bluez_filter( DBusConnection *conn, DBusMessage *msg, v unix_name_free( radio ); } } + else if (!strcmp( iface_name, BLUEZ_INTERFACE_DEVICE )) + { + struct winebluetooth_watcher_event_device_added device_added = {0}; + struct unix_name *device_name, *radio_name = NULL; + DBusMessageIter props_iter, variant; + const char *prop_name; + + device_name = unix_name_get_or_create( object_path ); + device_added.device.handle = (UINT_PTR)device_name; + if (!device_name) + { + ERR("Failed to allocate memory for device path %s\n", debugstr_a( object_path )); + break; + } + p_dbus_message_iter_next( &iface_entry ); + p_dbus_message_iter_recurse( &iface_entry, &props_iter ); + + while((prop_name = bluez_next_dict_entry( &props_iter, &variant ))) + { + if (!strcmp( prop_name, "Adapter" ) && + p_dbus_message_iter_get_arg_type( &variant ) == DBUS_TYPE_OBJECT_PATH) + { + const char *path; + + p_dbus_message_iter_get_basic( &variant, &path ); + radio_name = unix_name_get_or_create( path ); + if (!radio_name) + { + unix_name_free( device_name ); + ERR("Failed to allocate memory for radio path %s\n", debugstr_a( path )); + break; + } + device_added.radio.handle = (UINT_PTR)radio_name; + } + else + bluez_device_prop_from_dict_entry( prop_name, &variant, &device_added.props, + &device_added.known_props_mask, + WINEBLUETOOTH_DEVICE_ALL_PROPERTIES ); + } + + if (!radio_name) + { + unix_name_free( device_name ); + ERR( "Could not find the associated adapter for device %s\n", debugstr_a( object_path ) ); + break; + } + else + { + union winebluetooth_watcher_event_data event = { .device_added = device_added }; + TRACE( "New BlueZ org.bluez.Device1 object added at %s: %p\n", debugstr_a( object_path ), + device_name ); + if (!bluez_event_list_queue_new_event( event_list, BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_ADDED, event )) + { + unix_name_free( device_name ); + unix_name_free( radio_name ); + } + } + } p_dbus_message_iter_next( &ifaces_iter ); } }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 19 +++++++++++++++++++ dlls/winebth.sys/winebth.c | 27 +++++++++++++++++++++++++++ dlls/winebth.sys/winebth_priv.h | 7 +++++++ 3 files changed, 53 insertions(+)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index b3bd366370f..4ce43116944 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -899,6 +899,22 @@ static DBusHandlerResult bluez_filter( DBusConnection *conn, DBusMessage *msg, v event_list, BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_REMOVED, event )) unix_name_free( radio_name ); } + else if (!strcmp( interfaces[i], BLUEZ_INTERFACE_DEVICE )) + { + struct unix_name *device; + union winebluetooth_watcher_event_data event; + + device = unix_name_get_or_create( object_path ); + if (!device) + { + ERR( "Failed to allocate memory for adapter path %s\n", object_path ); + continue; + } + event.device_removed.device.handle = (UINT_PTR)device; + if (!bluez_event_list_queue_new_event( event_list, BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_REMOVED, + event )) + unix_name_free( device ); + } } p_dbus_free_string_array( interfaces ); } @@ -1049,6 +1065,9 @@ static void bluez_watcher_free( struct bluez_watcher_ctx *watcher ) unix_name_free( (struct unix_name *)event1->event.device_added.radio.handle ); unix_name_free( (struct unix_name *)event1->event.device_added.device.handle ); break; + case BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_REMOVED: + unix_name_free( (struct unix_name *)event1->event.device_removed.device.handle ); + break; } free( event1 ); } diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 5c0376c4324..0ff8cfdce8e 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -446,6 +446,30 @@ static void bluetooth_radio_add_remote_device( struct winebluetooth_watcher_even winebluetooth_radio_free( event.radio ); }
+static void bluetooth_radio_remove_remote_device( struct winebluetooth_watcher_event_device_removed event ) +{ + struct bluetooth_radio *radio; + + EnterCriticalSection( &device_list_cs ); + LIST_FOR_EACH_ENTRY( radio, &device_list, struct bluetooth_radio, entry ) + { + struct bluetooth_remote_device *device, *next; + + EnterCriticalSection( &radio->remote_devices_cs ); + LIST_FOR_EACH_ENTRY_SAFE( device, next, &radio->remote_devices, struct bluetooth_remote_device, entry ) + { + list_remove( &device->entry ); + winebluetooth_device_free( device->device ); + DeleteCriticalSection( &device->props_cs ); + free( device ); + break; + } + LeaveCriticalSection( &radio->remote_devices_cs ); + } + LeaveCriticalSection( &device_list_cs ); + winebluetooth_device_free( event.device ); +} + static DWORD CALLBACK bluetooth_event_loop_thread_proc( void *arg ) { NTSTATUS status; @@ -475,6 +499,9 @@ static DWORD CALLBACK bluetooth_event_loop_thread_proc( void *arg ) case BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_ADDED: bluetooth_radio_add_remote_device( event->event_data.device_added ); break; + case BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_REMOVED: + bluetooth_radio_remove_remote_device( event->event_data.device_removed ); + break; default: FIXME( "Unknown bluetooth watcher event code: %#x\n", event->event_type ); } diff --git a/dlls/winebth.sys/winebth_priv.h b/dlls/winebth.sys/winebth_priv.h index 0646a18409f..b5ee1bc0908 100644 --- a/dlls/winebth.sys/winebth_priv.h +++ b/dlls/winebth.sys/winebth_priv.h @@ -197,6 +197,7 @@ enum winebluetooth_watcher_event_type BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_REMOVED, BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_PROPERTIES_CHANGED, BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_ADDED, + BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_REMOVED };
struct winebluetooth_watcher_event_radio_added @@ -223,12 +224,18 @@ struct winebluetooth_watcher_event_device_added winebluetooth_radio_t radio; };
+struct winebluetooth_watcher_event_device_removed +{ + winebluetooth_device_t device; +}; + union winebluetooth_watcher_event_data { struct winebluetooth_watcher_event_radio_added radio_added; winebluetooth_radio_t radio_removed; struct winebluetooth_watcher_event_radio_props_changed radio_props_changed; struct winebluetooth_watcher_event_device_added device_added; + struct winebluetooth_watcher_event_device_removed device_removed; };
struct winebluetooth_watcher_event