From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/dbus.c | 46 ++++++++++++++++++++++++++++++++ dlls/winebth.sys/winebluetooth.h | 2 ++ dlls/winebth.sys/winebth.c | 25 +++++++++++++++++ 3 files changed, 73 insertions(+)
diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 5f148d45b78..4b9e7e88b59 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 \ @@ -455,6 +456,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; + union winebluetooth_watcher_event_data event; + radio.handle = unix_name_get_or_create( object_path ); + + if (!radio.handle) + { + ERR( "failed to allocate memory for adapter path %s\n", object_path ); + continue; + } + event.radio_removed = radio; + if (!bluez_event_list_queue_new_event( + event_list, BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_REMOVED, event )) + { + unix_name_free(radio.handle); + } + } + } + p_dbus_free_string_array( interfaces ); + }
final_count = list_count( event_list ); assert( final_count >= init_count ); diff --git a/dlls/winebth.sys/winebluetooth.h b/dlls/winebth.sys/winebluetooth.h index aa6491b625f..f386d6bf69b 100644 --- a/dlls/winebth.sys/winebluetooth.h +++ b/dlls/winebth.sys/winebluetooth.h @@ -101,6 +101,7 @@ enum winebluetooth_watcher_event_type { BLUETOOTH_WATCHER_EVENT_TYPE_NONE, BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_ADDED, + BLUETOOTH_WATCHER_EVENT_TYPE_RADIO_REMOVED, };
struct winebluetooth_watcher_event_radio_added @@ -113,6 +114,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 diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 51a4e29d3ca..b57dc3bbfb3 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -196,6 +196,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 void remove_pending_irps(struct bluetooth_radio *device) { LIST_ENTRY *entry; @@ -230,6 +252,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 ); }