From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 50 +++++++++++++++++++++++++++++++++ dlls/winebth.sys/winebth.c | 25 +++++++++++++++++ dlls/winebth.sys/winebth_priv.h | 6 ++++ 3 files changed, 81 insertions(+)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 0115ddede86..965029fcfc1 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -59,6 +59,7 @@ const int bluez_timeout = -1;
#define DBUS_INTERFACE_OBJECTMANAGER "org.freedesktop.DBus.ObjectManager" #define DBUS_OBJECTMANAGER_SIGNAL_INTERFACESADDED "InterfacesAdded" +#define DBUS_OBJECTMANAGER_SIGNAL_INTERFACESREMOVED "InterfacesRemoved"
#define DBUS_INTERFACES_ADDED_SIGNATURE \ DBUS_TYPE_OBJECT_PATH_AS_STRING \ @@ -70,6 +71,10 @@ const int bluez_timeout = -1; DBUS_DICT_ENTRY_END_CHAR_AS_STRING \ DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+#define DBUS_INTERFACES_REMOVED_SIGNATURE \ + DBUS_TYPE_OBJECT_PATH_AS_STRING \ + DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING + #define BLUEZ_DEST "org.bluez" #define BLUEZ_INTERFACE_ADAPTER "org.bluez.Adapter1"
@@ -448,6 +453,51 @@ static DBusHandlerResult bluez_filter( DBusConnection *conn, DBusMessage *msg, v p_dbus_message_iter_next( &ifaces_iter ); } } + else if (p_dbus_message_is_signal( msg, DBUS_INTERFACE_OBJECTMANAGER, DBUS_OBJECTMANAGER_SIGNAL_INTERFACESREMOVED ) + && p_dbus_message_has_signature( msg, DBUS_INTERFACES_REMOVED_SIGNATURE )) + { + const char *object_path; + char **interfaces; + int n_interfaces, i; + DBusError error; + dbus_bool_t success; + + p_dbus_error_init( &error ); + success = p_dbus_message_get_args( msg, &error, DBUS_TYPE_OBJECT_PATH, &object_path, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &interfaces, + &n_interfaces, DBUS_TYPE_INVALID ); + if (!success) + { + ERR_( dbus ) + ( "error getting arguments from message: '%s: '%s'\n", error.name, error.message ); + p_dbus_error_free( &error ); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + p_dbus_error_free( &error ); + for (i = 0; i < n_interfaces; i++) + { + if (strcmp( interfaces[i], BLUEZ_INTERFACE_ADAPTER ) == 0) + { + winebluetooth_radio_t radio; + struct unix_name *radio_name; + union winebluetooth_watcher_event_data event; + + radio_name = unix_name_get_or_create( object_path ); + if (!radio_name) + { + ERR( "failed to allocate memory for adapter path %s\n", object_path ); + continue; + } + radio.handle = (UINT_PTR)radio_name; + event.radio_removed = radio; + if (!bluez_event_list_queue_new_event( + event_list, BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_REMOVED, event )) + unix_name_free( radio_name ); + } + } + p_dbus_free_string_array( interfaces ); + }
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index e9c0ecdf870..c3961d19ef4 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -192,6 +192,28 @@ static void add_bluetooth_radio( struct winebluetooth_watcher_event_radio_added IoInvalidateDeviceRelations( bus_pdo, BusRelations ); }
+static void remove_bluetooth_radio( winebluetooth_radio_t radio ) +{ + struct bluetooth_radio *device; + + EnterCriticalSection(&device_list_cs); + LIST_FOR_EACH_ENTRY(device, &device_list, struct bluetooth_radio, entry) + { + if (winebluetooth_radio_equal(radio, device->radio) && !device->removed) + { + TRACE( "Removing bluetooth radio %p\n", (void *)radio.handle ); + device->removed = TRUE; + list_remove( &device->entry ); + IoInvalidateDeviceRelations( device->device_obj, BusRelations ); + break; + } + } + LeaveCriticalSection( &device_list_cs ); + + IoInvalidateDeviceRelations( bus_pdo, BusRelations ); + winebluetooth_radio_free( radio ); +} + static DWORD CALLBACK bluetooth_event_loop_thread_proc( void *arg ) { NTSTATUS status; @@ -212,6 +234,9 @@ static DWORD CALLBACK bluetooth_event_loop_thread_proc( void *arg ) case BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_ADDED: add_bluetooth_radio( event->event_data.radio_added ); break; + case BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_REMOVED: + remove_bluetooth_radio( event->event_data.radio_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 f230a846cd2..7aae04f5f69 100644 --- a/dlls/winebth.sys/winebth_priv.h +++ b/dlls/winebth.sys/winebth_priv.h @@ -141,10 +141,15 @@ struct winebluetooth_radio_properties NTSTATUS winebluetooth_radio_get_unique_name( winebluetooth_radio_t radio, char *name, SIZE_T *size ); void winebluetooth_radio_free( winebluetooth_radio_t radio ); +static inline BOOL winebluetooth_radio_equal( winebluetooth_radio_t r1, winebluetooth_radio_t r2 ) +{ + return r1.handle == r2.handle; +}
enum winebluetooth_watcher_event_type { BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_ADDED, + BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_REMOVED, };
struct winebluetooth_watcher_event_radio_added @@ -157,6 +162,7 @@ struct winebluetooth_watcher_event_radio_added union winebluetooth_watcher_event_data { struct winebluetooth_watcher_event_radio_added radio_added; + winebluetooth_radio_t radio_removed; };
struct winebluetooth_watcher_event