bluetooth: handle absence of bluez D-Bus service properly

This commit is contained in:
Lennart Poettering 2009-07-01 02:20:23 +02:00
parent 1104141d78
commit c3958aaa07

View file

@ -309,6 +309,17 @@ static void run_callback(pa_bluetooth_discovery *y, pa_bluetooth_device *d, pa_b
pa_hook_fire(&y->hook, d); pa_hook_fire(&y->hook, d);
} }
static void remove_all_devices(pa_bluetooth_discovery *y) {
pa_bluetooth_device *d;
pa_assert(y);
while ((d = pa_hashmap_steal_first(y->devices))) {
run_callback(y, d, TRUE);
device_free(d);
}
}
static void get_properties_reply(DBusPendingCall *pending, void *userdata) { static void get_properties_reply(DBusPendingCall *pending, void *userdata) {
DBusMessage *r; DBusMessage *r;
DBusMessageIter arg_i, element_i; DBusMessageIter arg_i, element_i;
@ -332,6 +343,12 @@ static void get_properties_reply(DBusPendingCall *pending, void *userdata) {
if (dbus_message_is_method_call(p->message, "org.bluez.Device", "GetProperties")) if (dbus_message_is_method_call(p->message, "org.bluez.Device", "GetProperties"))
d->device_info_valid = valid; d->device_info_valid = valid;
if (dbus_message_is_error(r, DBUS_ERROR_SERVICE_UNKNOWN)) {
pa_log_debug("Bluetooth daemon is apparently not available.");
remove_all_devices(y);
goto finish2;
}
if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) { if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
if (!dbus_message_is_error(r, DBUS_ERROR_UNKNOWN_METHOD)) if (!dbus_message_is_error(r, DBUS_ERROR_UNKNOWN_METHOD))
@ -383,6 +400,7 @@ static void get_properties_reply(DBusPendingCall *pending, void *userdata) {
finish: finish:
run_callback(y, d, FALSE); run_callback(y, d, FALSE);
finish2:
dbus_message_unref(r); dbus_message_unref(r);
PA_LLIST_REMOVE(pa_dbus_pending, y->pending, p); PA_LLIST_REMOVE(pa_dbus_pending, y->pending, p);
@ -412,6 +430,9 @@ static void found_device(pa_bluetooth_discovery *y, const char* path) {
pa_assert(y); pa_assert(y);
pa_assert(path); pa_assert(path);
if (pa_hashmap_get(y->devices, path))
return;
d = device_new(path); d = device_new(path);
pa_hashmap_put(y->devices, d->path, d); pa_hashmap_put(y->devices, d->path, d);
@ -439,9 +460,15 @@ static void list_devices_reply(DBusPendingCall *pending, void *userdata) {
pa_assert_se(y = p->context_data); pa_assert_se(y = p->context_data);
pa_assert_se(r = dbus_pending_call_steal_reply(pending)); pa_assert_se(r = dbus_pending_call_steal_reply(pending));
if (dbus_message_is_error(r, DBUS_ERROR_SERVICE_UNKNOWN)) {
pa_log_debug("Bluetooth daemon is apparently not available.");
remove_all_devices(y);
goto finish;
}
if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) { if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
pa_log("Error from ListDevices reply: %s", dbus_message_get_error_name(r)); pa_log("Error from ListDevices reply: %s", dbus_message_get_error_name(r));
goto end; goto finish;
} }
if (!dbus_message_get_args(r, &e, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &paths, &num, DBUS_TYPE_INVALID)) { if (!dbus_message_get_args(r, &e, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &paths, &num, DBUS_TYPE_INVALID)) {
@ -454,7 +481,7 @@ static void list_devices_reply(DBusPendingCall *pending, void *userdata) {
found_device(y, paths[i]); found_device(y, paths[i]);
} }
end: finish:
if (paths) if (paths)
dbus_free_string_array (paths); dbus_free_string_array (paths);
@ -487,9 +514,15 @@ static void list_adapters_reply(DBusPendingCall *pending, void *userdata) {
pa_assert_se(y = p->context_data); pa_assert_se(y = p->context_data);
pa_assert_se(r = dbus_pending_call_steal_reply(pending)); pa_assert_se(r = dbus_pending_call_steal_reply(pending));
if (dbus_message_is_error(r, DBUS_ERROR_SERVICE_UNKNOWN)) {
pa_log_debug("Bluetooth daemon is apparently not available.");
remove_all_devices(y);
goto finish;
}
if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) { if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
pa_log("Error from ListAdapters reply: %s", dbus_message_get_error_name(r)); pa_log("Error from ListAdapters reply: %s", dbus_message_get_error_name(r));
goto end; goto finish;
} }
if (!dbus_message_get_args(r, &e, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &paths, &num, DBUS_TYPE_INVALID)) { if (!dbus_message_get_args(r, &e, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &paths, &num, DBUS_TYPE_INVALID)) {
@ -502,7 +535,7 @@ static void list_adapters_reply(DBusPendingCall *pending, void *userdata) {
found_adapter(y, paths[i]); found_adapter(y, paths[i]);
} }
end: finish:
if (paths) if (paths)
dbus_free_string_array (paths); dbus_free_string_array (paths);
@ -615,6 +648,32 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
run_callback(y, d, FALSE); run_callback(y, d, FALSE);
} }
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
} else if (dbus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged")) {
const char *name, *old_owner, *new_owner;
if (!dbus_message_get_args(m, &err,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_STRING, &old_owner,
DBUS_TYPE_STRING, &new_owner,
DBUS_TYPE_INVALID)) {
pa_log("Failed to parse org.freedesktop.DBus.NameOwnerChanged: %s", err.message);
goto fail;
}
if (pa_streq(name, "org.bluez")) {
if (old_owner && *old_owner) {
pa_log_debug("Bluetooth daemon disappeared.");
remove_all_devices(y);
}
if (new_owner && *new_owner) {
pa_log_debug("Bluetooth daemon appeared.");
list_adapters(y);
}
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
} }
@ -699,6 +758,7 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c) {
if (pa_dbus_add_matches( if (pa_dbus_add_matches(
pa_dbus_connection_get(y->connection), &err, pa_dbus_connection_get(y->connection), &err,
"type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged'",
"type='signal',sender='org.bluez',interface='org.bluez.Manager',member='AdapterAdded'", "type='signal',sender='org.bluez',interface='org.bluez.Manager',member='AdapterAdded'",
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'", "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'",
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceCreated'", "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceCreated'",
@ -734,8 +794,6 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_ref(pa_bluetooth_discovery *y) {
} }
void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) { void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) {
pa_bluetooth_device *d;
pa_assert(y); pa_assert(y);
pa_assert(PA_REFCNT_VALUE(y) > 0); pa_assert(PA_REFCNT_VALUE(y) > 0);
@ -745,16 +803,13 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) {
pa_dbus_free_pending_list(&y->pending); pa_dbus_free_pending_list(&y->pending);
if (y->devices) { if (y->devices) {
while ((d = pa_hashmap_steal_first(y->devices))) { remove_all_devices(y);
run_callback(y, d, TRUE);
device_free(d);
}
pa_hashmap_free(y->devices, NULL, NULL); pa_hashmap_free(y->devices, NULL, NULL);
} }
if (y->connection) { if (y->connection) {
pa_dbus_remove_matches(pa_dbus_connection_get(y->connection), pa_dbus_remove_matches(pa_dbus_connection_get(y->connection),
"type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged'",
"type='signal',sender='org.bluez',interface='org.bluez.Manager',member='AdapterAdded'", "type='signal',sender='org.bluez',interface='org.bluez.Manager',member='AdapterAdded'",
"type='signal',sender='org.bluez',interface='org.bluez.Manager',member='AdapterRemoved'", "type='signal',sender='org.bluez',interface='org.bluez.Manager',member='AdapterRemoved'",
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'", "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'",