This adds to the basic infrastructure needed for device inquiry/scanning.
Also, fixes radio properties being incorrectly updated.
-- v4: winebth.sys: Update properties for tracked remote devices on receiving PropertiesChanged for org.bluez.Device1 objects from BlueZ. winebth.sys: Only set the updated properties for local radios on BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_PROPERTIES_CHANGED. winebth.sys: Set the device class for remote devices from BlueZ's "Class" property. winebth.sys: Use the "Trusted" property from BlueZ device objects to set BDIF_PERSONAL. winebth.sys: Use the "Name" property of a BlueZ adapter for the local radio name. winebth.sys: Don't iterate over the remaining radios once a local device has been removed. winebth.sys: Initially set numOfDevices to 0 in IOCTL_BTH_GET_DEVICE_INFO. winebth.sys: Use the correct DBus property name in IOCTL_WINEBTH_RADIO_SET_FLAG.
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 13e4bbe29e5..75e72249234 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -345,12 +345,12 @@ NTSTATUS bluez_adapter_set_prop( void *connection, struct bluetooth_adapter_set_ switch (params->prop_flag) { case LOCAL_RADIO_CONNECTABLE: - prop_name = "Discoverable"; + prop_name = "Connectable"; val.bool_val = params->prop->boolean; val_type = DBUS_TYPE_BOOLEAN; break; case LOCAL_RADIO_DISCOVERABLE: - prop_name = "Connectable"; + prop_name = "Discoverable"; val.bool_val = params->prop->boolean; val_type = DBUS_TYPE_BOOLEAN; break;
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/winebth.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 28cc67c123c..f91413c9cb6 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -168,6 +168,7 @@ static NTSTATUS WINAPI dispatch_bluetooth( DEVICE_OBJECT *device, IRP *irp ) rem_devices = (outsize - sizeof( *list ))/sizeof(BTH_DEVICE_INFO) + 1; status = STATUS_SUCCESS; irp->IoStatus.Information = 0; + list->numOfDevices = 0;
EnterCriticalSection( &ext->remote_devices_cs ); LIST_FOR_EACH_ENTRY( device, &ext->remote_devices, struct bluetooth_remote_device, entry )
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/winebth.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index f91413c9cb6..7d6efcfa6f4 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -472,7 +472,11 @@ static void bluetooth_radio_remove_remote_device( struct winebluetooth_watcher_e 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 ); + return; } } LeaveCriticalSection( &radio->remote_devices_cs );
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 75e72249234..8fa43c79f18 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -420,6 +420,18 @@ static void bluez_radio_prop_from_dict_entry( const char *prop_name, DBusMessage TRACE_(dbus)( "(%s, %p, %p, %p, %#x)\n", debugstr_a( prop_name ), variant, props, props_mask, wanted_props_mask );
+ if (wanted_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_NAME && + !strcmp( prop_name, "Name" ) && + p_dbus_message_iter_get_arg_type( variant )) + { + 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_RADIO_PROPERTY_NAME; + } if (wanted_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_ADDRESS && !strcmp( prop_name, "Address" ) && p_dbus_message_iter_get_arg_type( variant ) == DBUS_TYPE_STRING)
From: Vibhav Pant vibhavp@gmail.com
On BlueZ, "Trusted" devices are saved to the local cache, which makes them equivalent to Win32 devices with the BDIF_PERSONAL flag set. --- dlls/winebth.sys/dbus.c | 10 ++++++++++ dlls/winebth.sys/winebth.c | 3 +++ dlls/winebth.sys/winebth_priv.h | 4 +++- 3 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 8fa43c79f18..ce5e2e38a6f 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -566,6 +566,16 @@ static void bluez_device_prop_from_dict_entry( const char *prop_name, DBusMessag props->legacy_pairing = !!legacy; *props_mask |= WINEBLUETOOTH_DEVICE_PROPERTY_LEGACY_PAIRING; } + else if (wanted_props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_TRUSTED && + !strcmp( prop_name, "Trusted" ) && + p_dbus_message_iter_get_arg_type( variant ) == DBUS_TYPE_BOOLEAN) + { + dbus_bool_t trusted; + + p_dbus_message_iter_get_basic( variant, &trusted ); + props->trusted = !!trusted; + *props_mask |= WINEBLUETOOTH_DEVICE_PROPERTY_TRUSTED; + } }
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 7d6efcfa6f4..4cab2250dba 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -206,6 +206,9 @@ static NTSTATUS WINAPI dispatch_bluetooth( DEVICE_OBJECT *device, IRP *irp ) device->props.paired) info->flags |= BDIF_SSP_PAIRED; } + if (device->props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_TRUSTED && + device->props.trusted) + info->flags |= 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 72dcf4bf130..29e16b6bd22 100644 --- a/dlls/winebth.sys/winebth_priv.h +++ b/dlls/winebth.sys/winebth_priv.h @@ -145,11 +145,12 @@ typedef UINT16 winebluetooth_device_props_mask_t; #define WINEBLUETOOTH_DEVICE_PROPERTY_CONNECTED (1 << 2) #define WINEBLUETOOTH_DEVICE_PROPERTY_PAIRED (1 << 3) #define WINEBLUETOOTH_DEVICE_PROPERTY_LEGACY_PAIRING (1 << 4) +#define WINEBLUETOOTH_DEVICE_PROPERTY_TRUSTED (1 << 5)
#define WINEBLUETOOTH_DEVICE_ALL_PROPERTIES \ (WINEBLUETOOTH_DEVICE_PROPERTY_NAME | WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS | \ WINEBLUETOOTH_DEVICE_PROPERTY_CONNECTED | WINEBLUETOOTH_DEVICE_PROPERTY_PAIRED | \ - WINEBLUETOOTH_DEVICE_PROPERTY_LEGACY_PAIRING) + WINEBLUETOOTH_DEVICE_PROPERTY_LEGACY_PAIRING | WINEBLUETOOTH_DEVICE_PROPERTY_TRUSTED)
union winebluetooth_property { @@ -179,6 +180,7 @@ struct winebluetooth_device_properties BOOL connected; BOOL paired; BOOL legacy_pairing; + BOOL trusted; };
NTSTATUS winebluetooth_radio_get_unique_name( winebluetooth_radio_t radio, char *name,
From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 7 +++++++ dlls/winebth.sys/winebth.c | 5 +++++ dlls/winebth.sys/winebth_priv.h | 11 +++++++---- 3 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index ce5e2e38a6f..872e6fa83bf 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -576,6 +576,13 @@ static void bluez_device_prop_from_dict_entry( const char *prop_name, DBusMessag props->trusted = !!trusted; *props_mask |= WINEBLUETOOTH_DEVICE_PROPERTY_TRUSTED; } + else if (wanted_props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_CLASS && + !strcmp( prop_name, "Class" ) && + p_dbus_message_iter_get_arg_type( variant ) == DBUS_TYPE_UINT32) + { + p_dbus_message_iter_get_basic( variant, &props->class ); + *props_mask |= WINEBLUETOOTH_DEVICE_PROPERTY_CLASS; + } }
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 4cab2250dba..637a24e795d 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -209,6 +209,11 @@ static NTSTATUS WINAPI dispatch_bluetooth( DEVICE_OBJECT *device, IRP *irp ) if (device->props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_TRUSTED && device->props.trusted) info->flags |= BDIF_PERSONAL; + if (device->props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_CLASS) + { + info->classOfDevice = device->props.class; + info->flags |= BDIF_COD; + } 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 29e16b6bd22..59915b70805 100644 --- a/dlls/winebth.sys/winebth_priv.h +++ b/dlls/winebth.sys/winebth_priv.h @@ -146,11 +146,13 @@ typedef UINT16 winebluetooth_device_props_mask_t; #define WINEBLUETOOTH_DEVICE_PROPERTY_PAIRED (1 << 3) #define WINEBLUETOOTH_DEVICE_PROPERTY_LEGACY_PAIRING (1 << 4) #define WINEBLUETOOTH_DEVICE_PROPERTY_TRUSTED (1 << 5) +#define WINEBLUETOOTH_DEVICE_PROPERTY_CLASS (1 << 6)
-#define WINEBLUETOOTH_DEVICE_ALL_PROPERTIES \ - (WINEBLUETOOTH_DEVICE_PROPERTY_NAME | WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS | \ - WINEBLUETOOTH_DEVICE_PROPERTY_CONNECTED | WINEBLUETOOTH_DEVICE_PROPERTY_PAIRED | \ - WINEBLUETOOTH_DEVICE_PROPERTY_LEGACY_PAIRING | WINEBLUETOOTH_DEVICE_PROPERTY_TRUSTED) +#define WINEBLUETOOTH_DEVICE_ALL_PROPERTIES \ + (WINEBLUETOOTH_DEVICE_PROPERTY_NAME | WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS | \ + WINEBLUETOOTH_DEVICE_PROPERTY_CONNECTED | WINEBLUETOOTH_DEVICE_PROPERTY_PAIRED | \ + WINEBLUETOOTH_DEVICE_PROPERTY_LEGACY_PAIRING | WINEBLUETOOTH_DEVICE_PROPERTY_TRUSTED | \ + WINEBLUETOOTH_DEVICE_PROPERTY_CLASS)
union winebluetooth_property { @@ -181,6 +183,7 @@ struct winebluetooth_device_properties BOOL paired; BOOL legacy_pairing; BOOL trusted; + UINT32 class; };
NTSTATUS winebluetooth_radio_get_unique_name( winebluetooth_radio_t radio, char *name,
From: Vibhav Pant vibhavp@gmail.com
A PropertiesChanged signal only contains the updated properties for the object, so the PE driver should only modify the properties which have their corresponding mask bit set. Additionally, unset the mask bits for invalidated properties. --- dlls/winebth.sys/winebth.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 637a24e795d..52f4a15c197 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -408,8 +408,6 @@ static void update_bluetooth_radio_properties( struct winebluetooth_watcher_even { struct bluetooth_radio *device; winebluetooth_radio_t radio = event.radio; - winebluetooth_radio_props_mask_t mask = event.changed_props_mask; - struct winebluetooth_radio_properties props = event.props;
EnterCriticalSection( &device_list_cs ); LIST_FOR_EACH_ENTRY( device, &device_list, struct bluetooth_radio, entry ) @@ -417,8 +415,27 @@ static void update_bluetooth_radio_properties( struct winebluetooth_watcher_even if (winebluetooth_radio_equal( radio, device->radio ) && !device->removed) { EnterCriticalSection( &device->props_cs ); - device->props_mask = mask; - device->props = props; + device->props_mask |= event.changed_props_mask; + device->props_mask &= ~event.invalid_props_mask; + + if (event.changed_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_NAME) + memcpy( device->props.name, event.props.name, sizeof( event.props.name )); + if (event.changed_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_ADDRESS) + device->props.address.ullLong = RtlUlonglongByteSwap( event.props.address.ullLong ); + if (event.changed_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_DISCOVERABLE) + device->props.discoverable = event.props.discoverable; + if (event.changed_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_CONNECTABLE) + device->props.connectable = event.props.connectable; + if (event.changed_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_CLASS) + device->props.class = event.props.class; + if (event.changed_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_MANUFACTURER) + device->props.manufacturer = event.props.manufacturer; + if (event.changed_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_VERSION) + device->props.version = event.props.version; + if (event.changed_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_DISCOVERING) + device->props.discovering = event.props.discovering; + if (event.changed_props_mask & WINEBLUETOOTH_RADIO_PROPERTY_PAIRABLE) + device->props.pairable = event.props.pairable; bluetooth_radio_set_properties( device->device_obj, device->props_mask, &device->props ); LeaveCriticalSection( &device->props_cs );
From: Vibhav Pant vibhavp@gmail.com
When the unix bluez watcher receives a PropertiesChanged signal for a org.bluez.Device1 object, queue a BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_PROPERTIES_CHANGED event, containing the changed and invalidated properties for the associated remote device. --- dlls/winebth.sys/dbus.c | 141 ++++++++++++++++++++++++++++++++ dlls/winebth.sys/winebth.c | 46 +++++++++++ dlls/winebth.sys/winebth_priv.h | 13 ++- 3 files changed, 199 insertions(+), 1 deletion(-)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 872e6fa83bf..153c4e60ad1 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -608,6 +608,29 @@ static NTSTATUS bluez_adapter_get_props_async( void *connection, const char *rad return STATUS_SUCCESS; }
+static NTSTATUS bluez_device_get_props_by_path_async( DBusConnection *connection, + const char *device_path, + DBusPendingCall **pending_call ) +{ + DBusMessage *request; + static const char *adapter_iface = BLUEZ_INTERFACE_DEVICE; + dbus_bool_t ret; + + request = p_dbus_message_new_method_call( BLUEZ_DEST, device_path, + DBUS_INTERFACE_PROPERTIES, "GetAll" ); + if (!request) return STATUS_NO_MEMORY; + + p_dbus_message_append_args( request, DBUS_TYPE_STRING, &adapter_iface, DBUS_TYPE_INVALID ); + ret = p_dbus_connection_send_with_reply( connection, request, pending_call, bluez_timeout ); + p_dbus_message_unref( request ); + if (!ret) + return STATUS_NO_MEMORY; + if (!*pending_call) + return STATUS_INTERNAL_ERROR; + + return STATUS_SUCCESS; +} + struct bluez_watcher_ctx { void *init_device_list_call; @@ -744,6 +767,42 @@ static void bluez_filter_radio_props_changed_callback( DBusPendingCall *call, vo p_dbus_message_unref( reply ); }
+static void bluez_filter_device_props_changed_callback( DBusPendingCall *call, void *user_data ) +{ + union winebluetooth_watcher_event_data *event = user_data; + struct winebluetooth_watcher_event_device_props_changed *changed = &event->device_props_changed; + const struct unix_name *device = (struct unix_name *)event->device_props_changed.device.handle; + DBusMessage *reply; + DBusMessageIter dict, prop_iter, variant; + const char *prop_name; + DBusError error; + + TRACE( "call %p, device %s\n", call, debugstr_a( device->str ) ); + + reply = p_dbus_pending_call_steal_reply( call ); + p_dbus_error_init( &error ); + if (p_dbus_set_error_from_message( &error, reply )) + { + ERR( "Failed to get device properties for %s: %s: %s\n", debugstr_a( device->str ), debugstr_a( error.name ), + debugstr_a( error.message ) ); + p_dbus_error_free( &error ); + p_dbus_message_unref( reply ); + return; + } + p_dbus_error_free( &error ); + + p_dbus_message_iter_init( reply, &dict ); + p_dbus_message_iter_recurse( &dict, &prop_iter ); + while((prop_name = bluez_next_dict_entry( &prop_iter, &variant ))) + { + bluez_device_prop_from_dict_entry( prop_name, &variant, &changed->props, + &changed->changed_props_mask, + changed->invalid_props_mask ); + } + changed->invalid_props_mask &= ~changed->changed_props_mask; + p_dbus_message_unref( reply ); +} + struct bluez_object_property_masks { const char *prop_name; @@ -1051,6 +1110,85 @@ static DBusHandlerResult bluez_filter( DBusConnection *conn, DBusMessage *msg, v } } } + else if (strcmp( iface, BLUEZ_INTERFACE_DEVICE ) == 0) + { + struct winebluetooth_watcher_event_device_props_changed props_changed = {0}; + struct unix_name *device; + const char *prop_name, *object_path; + union winebluetooth_watcher_event_data event; + DBusMessageIter changed_props_iter, invalid_props_iter, variant; + const static struct bluez_object_property_masks device_prop_masks[] = { + { "Name", WINEBLUETOOTH_DEVICE_PROPERTY_NAME }, + { "Address", WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS }, + { "Connected", WINEBLUETOOTH_DEVICE_PROPERTY_CONNECTED }, + { "Paired", WINEBLUETOOTH_DEVICE_PROPERTY_PAIRED }, + { "LegacyPairing", WINEBLUETOOTH_DEVICE_PROPERTY_LEGACY_PAIRING }, + { "Trusted", WINEBLUETOOTH_DEVICE_PROPERTY_TRUSTED }, + { "Class", WINEBLUETOOTH_DEVICE_PROPERTY_CLASS } + }; + + p_dbus_message_iter_next( &iter ); + p_dbus_message_iter_recurse( &iter, &changed_props_iter ); + while ((prop_name = bluez_next_dict_entry( &changed_props_iter, &variant ))) + { + bluez_device_prop_from_dict_entry( prop_name, &variant, &props_changed.props, + &props_changed.changed_props_mask, + WINEBLUETOOTH_DEVICE_ALL_PROPERTIES ); + } + p_dbus_message_iter_next( &iter ); + p_dbus_message_iter_recurse( &iter, &invalid_props_iter ); + props_changed.invalid_props_mask = bluez_dbus_get_invalidated_properties_from_iter( + &invalid_props_iter, device_prop_masks, ARRAY_SIZE( device_prop_masks ) ); + /* No properties that we're interested in have changed or been invalidated. */ + if (!props_changed.changed_props_mask && !props_changed.invalid_props_mask) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + object_path = p_dbus_message_get_path( msg ); + TRACE( "Properties changed for device %s, changed %#x, invalidated %#x\n", debugstr_a( object_path ), + props_changed.changed_props_mask, props_changed.invalid_props_mask ); + + device = unix_name_get_or_create( object_path ); + if (!device) + { + ERR( "Failed to allocate memory for device path %s\n", object_path ); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + props_changed.device.handle = (UINT_PTR)device; + event.device_props_changed = props_changed; + + if (props_changed.invalid_props_mask != 0) + { + DBusPendingCall *pending_call = NULL; + NTSTATUS status; + + status = bluez_device_get_props_by_path_async( conn, device->str, &pending_call ); + if (status) + { + ERR( "Failed to create async call to get device properties: %#x\n", (int)status ); + unix_name_free( device ); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (!bluez_event_list_queue_new_event_with_call( event_list, + BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_PROPERTIES_CHANGED, + event, pending_call, + bluez_filter_device_props_changed_callback )) + { + unix_name_free( device ); + p_dbus_pending_call_cancel( pending_call ); + p_dbus_pending_call_unref( pending_call ); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + } + else if (!bluez_event_list_queue_new_event( event_list, + BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_PROPERTIES_CHANGED, + event )) + { + + unix_name_free( device ); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + } }
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -1107,6 +1245,9 @@ static void bluez_watcher_free( struct bluez_watcher_ctx *watcher ) case BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_REMOVED: unix_name_free( (struct unix_name *)event1->event.device_removed.device.handle ); break; + case BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_PROPERTIES_CHANGED: + unix_name_free( (struct unix_name *)event1->event.device_props_changed.device.handle ); + break; } free( event1 ); } diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 52f4a15c197..b47806de077 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -510,6 +510,49 @@ static void bluetooth_radio_remove_remote_device( struct winebluetooth_watcher_e winebluetooth_device_free( event.device ); }
+static void bluetooth_radio_update_device_props( struct winebluetooth_watcher_event_device_props_changed 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; + + EnterCriticalSection( &radio->remote_devices_cs ); + LIST_FOR_EACH_ENTRY( device, &radio->remote_devices, struct bluetooth_remote_device, entry ) + { + if (winebluetooth_device_equal( event.device, device->device )) + { + EnterCriticalSection( &device->props_cs ); + device->props_mask |= event.changed_props_mask; + device->props_mask &= ~event.invalid_props_mask; + if (event.changed_props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_NAME) + memcpy( device->props.name, event.props.name, sizeof( event.props.name )); + if (event.changed_props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_ADDRESS) + device->props.address = event.props.address; + if (event.changed_props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_CONNECTED) + device->props.connected = event.props.connected; + if (event.changed_props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_PAIRED) + device->props.paired = event.props.paired; + if (event.changed_props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_LEGACY_PAIRING) + device->props.legacy_pairing = event.props.legacy_pairing; + if (event.changed_props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_TRUSTED) + device->props.trusted = event.props.trusted; + if (event.changed_props_mask & WINEBLUETOOTH_DEVICE_PROPERTY_CLASS) + device->props.class = event.props.class; + LeaveCriticalSection( &device->props_cs ); + LeaveCriticalSection( &radio->remote_devices_cs ); + goto done; + } + } + LeaveCriticalSection( &radio->remote_devices_cs ); + } +done: + LeaveCriticalSection( &device_list_cs ); + winebluetooth_device_free( event.device ); +} + static DWORD CALLBACK bluetooth_event_loop_thread_proc( void *arg ) { NTSTATUS status; @@ -542,6 +585,9 @@ static DWORD CALLBACK bluetooth_event_loop_thread_proc( void *arg ) case BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_REMOVED: bluetooth_radio_remove_remote_device( event->event_data.device_removed ); break; + case BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_PROPERTIES_CHANGED: + bluetooth_radio_update_device_props( event->event_data.device_props_changed); + 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 59915b70805..b50935c091c 100644 --- a/dlls/winebth.sys/winebth_priv.h +++ b/dlls/winebth.sys/winebth_priv.h @@ -209,7 +209,8 @@ 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 + BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_REMOVED, + BLUETOOTH_WATCHER_EVENT_TYPE_DEVICE_PROPERTIES_CHANGED };
struct winebluetooth_watcher_event_radio_added @@ -236,6 +237,15 @@ struct winebluetooth_watcher_event_device_added winebluetooth_radio_t radio; };
+struct winebluetooth_watcher_event_device_props_changed +{ + winebluetooth_device_props_mask_t changed_props_mask; + struct winebluetooth_device_properties props; + + winebluetooth_device_props_mask_t invalid_props_mask; + winebluetooth_device_t device; +}; + struct winebluetooth_watcher_event_device_removed { winebluetooth_device_t device; @@ -248,6 +258,7 @@ union winebluetooth_watcher_event_data 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_device_props_changed device_props_changed; };
struct winebluetooth_watcher_event
As usual I haven't carefully reviewed the details, but the architecture looks fine.
This merge request was approved by Elizabeth Figura.
On Fri Feb 28 14:16:26 2025 +0000, Elizabeth Figura wrote:
As usual I haven't carefully reviewed the details, but the architecture looks fine.
Thanks!