Commit 25f32006 authored by pali's avatar pali
Browse files

fixup! bluetooth: Add support for automatic connection of disconnected profiles

parent dd83bf0a
......@@ -52,6 +52,7 @@
#define BLUEZ_MEDIA_TRANSPORT_INTERFACE BLUEZ_SERVICE ".MediaTransport1"
#define BLUEZ_ERROR_NOT_SUPPORTED "org.bluez.Error.NotSupported"
#define BLUEZ_ERROR_NOT_AVAILABLE "org.bluez.Error.NotAvailable"
#define A2DP_OBJECT_MANAGER_PATH "/A2DPEndpoint"
#define A2DP_SOURCE_ENDPOINT A2DP_OBJECT_MANAGER_PATH "/Source"
......@@ -1789,7 +1790,7 @@ static void change_a2dp_profile_reply(DBusPendingCall *pending, void *userdata)
pa_xfree(data->codec_endpoints);
} else if (dbus_message_get_type(r) != DBUS_MESSAGE_TYPE_ERROR) {
pa_log_info("Changing a2dp profile for %s to %s via endpoint %s succeeded", data->device_path, pa_bluetooth_profile_to_string(data->profile), data->codec_endpoints[data->codec_endpoints_i-1]);
pa_hook_fire(&y->hooks[PA_BLUETOOTH_HOOK_PROFILE_CONNECTION_CHANGED], &(struct pa_bluetooth_device_and_profile){ device, data->profile });
pa_hook_fire(&y->hooks[PA_BLUETOOTH_HOOK_PROFILE_CONNECTION_CHANGED], &(struct pa_bluetooth_device_and_profile){ device, data->profile, PA_BLUETOOTH_STATUS_SUCCESS });
pa_xfree(data->codec_endpoints);
} else {
pa_log_warn("Changing a2dp profile for %s to %s via endpoint %s failed: %s: %s", data->device_path, pa_bluetooth_profile_to_string(data->profile), data->codec_endpoints[data->codec_endpoints_i-1], dbus_message_get_error_name(r), pa_dbus_get_error_message(r));
......@@ -1824,7 +1825,7 @@ static bool change_a2dp_profile_next(pa_bluetooth_device *device, pa_bluetooth_p
next:
if (codec_endpoints_i >= codec_endpoints_count) {
pa_log_error("Changing a2dp profile for %s to %s failed: No endpoint accepted connection", device->path, pa_bluetooth_profile_to_string(profile));
pa_hook_fire(&device->discovery->hooks[PA_BLUETOOTH_HOOK_PROFILE_CONNECTION_CHANGED], &(struct pa_bluetooth_device_and_profile){ device, profile });
pa_hook_fire(&device->discovery->hooks[PA_BLUETOOTH_HOOK_PROFILE_CONNECTION_CHANGED], &(struct pa_bluetooth_device_and_profile){ device, profile, PA_BLUETOOTH_STATUS_NOTAVAILABLE });
pa_xfree(codec_endpoints);
return false;
}
......@@ -1908,6 +1909,7 @@ static void pa_bluetooth_device_connect_profile_reply(DBusPendingCall *pending,
pa_dbus_pending *p;
pa_bluetooth_discovery *y;
pa_bluetooth_device *device;
pa_bluetooth_status status;
struct connect_profile_data *data;
pa_assert(pending);
......@@ -1924,8 +1926,15 @@ static void pa_bluetooth_device_connect_profile_reply(DBusPendingCall *pending,
else
pa_log_info("Connecting device %s to profile %s (%s) succeeded", data->device_path, pa_bluetooth_profile_to_string(data->profile), data->profile_uuid);
if (device)
pa_hook_fire(&y->hooks[PA_BLUETOOTH_HOOK_PROFILE_CONNECTION_CHANGED], &(struct pa_bluetooth_device_and_profile){ device, data->profile });
if (device) {
if (dbus_message_get_type(r) != DBUS_MESSAGE_TYPE_ERROR)
status = PA_BLUETOOTH_STATUS_SUCCESS;
else if (dbus_message_is_error(r, BLUEZ_ERROR_NOT_AVAILABLE))
status = PA_BLUETOOTH_STATUS_NOTAVAILABLE;
else
status = PA_BLUETOOTH_STATUS_FAILED;
pa_hook_fire(&y->hooks[PA_BLUETOOTH_HOOK_PROFILE_CONNECTION_CHANGED], &(struct pa_bluetooth_device_and_profile){ device, data->profile, status });
}
dbus_message_unref(r);
......
......@@ -65,9 +65,16 @@ typedef enum pa_bluetooth_hook {
#define PA_BLUETOOTH_PROFILE_A2DP_START_INDEX 5
typedef unsigned pa_bluetooth_profile_t;
typedef enum {
PA_BLUETOOTH_STATUS_SUCCESS,
PA_BLUETOOTH_STATUS_FAILED,
PA_BLUETOOTH_STATUS_NOTAVAILABLE,
} pa_bluetooth_status;
struct pa_bluetooth_device_and_profile {
pa_bluetooth_device *device;
pa_bluetooth_profile_t profile;
pa_bluetooth_status status;
};
typedef enum pa_bluetooth_transport_state {
......
......@@ -2361,6 +2361,7 @@ static pa_hook_result_t device_connection_changed_cb(pa_bluetooth_discovery *y,
static pa_hook_result_t profile_connection_changed_cb(pa_bluetooth_discovery *y, const struct pa_bluetooth_device_and_profile *device_and_profile, struct userdata *u) {
const pa_bluetooth_device *d = device_and_profile->device;
pa_bluetooth_profile_t p = device_and_profile->profile;
pa_bluetooth_status s = device_and_profile->status;
pa_bluetooth_transport *t;
pa_card_profile *cp;
......@@ -2368,8 +2369,6 @@ static pa_hook_result_t profile_connection_changed_cb(pa_bluetooth_discovery *y,
pa_assert(p);
pa_assert(u);
pa_log_debug("profile_connection_changed_cb d=%p p=%d u->device=%p u->device->new_profile_in_progress=%d", d, p, u->device, u->device->new_profile_in_progress);
if (d != u->device || !u->device->new_profile_in_progress)
return PA_HOOK_OK;
......@@ -2391,9 +2390,10 @@ static pa_hook_result_t profile_connection_changed_cb(pa_bluetooth_discovery *y,
/* Activate newly connected profile */
pa_assert_se(cp = pa_hashmap_get(u->card->profiles, pa_bluetooth_profile_to_string(p)));
pa_card_set_profile(u->card, cp, true);
} else {
} else if (s != PA_BLUETOOTH_STATUS_NOTAVAILABLE) {
/* Some bluetooth headsets do not allow connecting both HSP and HFP profile at the same time
* Try to first disconnect one profile and then connect second profile */
* Try to first disconnect one profile and then connect second profile
* But do not try it when previous attempt failed with error "NotAvailable", it means hsphfpd or pulseaudio cannot handle that profile */
u->device->new_profile_in_progress = p;
if (p == PA_BLUETOOTH_PROFILE_HSP_HEAD_UNIT && u->device->transports[PA_BLUETOOTH_PROFILE_HFP_HEAD_UNIT] && u->device->transports[PA_BLUETOOTH_PROFILE_HFP_HEAD_UNIT]->state >= PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED)
pa_bluetooth_device_disconnect_and_connect_profile(u->device, PA_BLUETOOTH_PROFILE_HFP_HEAD_UNIT, PA_BLUETOOTH_PROFILE_HSP_HEAD_UNIT);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment