Commit ca7258f5 authored by pali's avatar pali
Browse files

WIP: bluetooth: Add support for hsphfpd service to handle HSP and HFP profiles

parent d737263c
......@@ -2147,6 +2147,7 @@ module_bluetooth_discover_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_bluet
# Bluetooth BlueZ 5 sink / source
libbluez5_util_la_SOURCES = \
modules/bluetooth/hsphfpd.c \
modules/bluetooth/bluez5-util.c \
modules/bluetooth/bluez5-util.h \
modules/bluetooth/a2dp-codec-api.h \
......
......@@ -118,6 +118,7 @@ struct pa_bluetooth_discovery {
pa_hashmap *transports;
int headset_backend;
pa_bluetooth_backend *hsphfpd_backend;
pa_bluetooth_backend *legacy_hsp_backend;
PA_LLIST_HEAD(pa_dbus_pending, pending);
};
......@@ -381,6 +382,11 @@ void pa_bluetooth_transport_set_state(pa_bluetooth_transport *t, pa_bluetooth_tr
}
}
pa_bluetooth_transport *pa_bluetooth_transport_get(pa_bluetooth_discovery *y, const char *path) {
pa_assert(path);
return pa_hashmap_get(y->transports, path);
}
void pa_bluetooth_transport_put(pa_bluetooth_transport *t) {
pa_assert(t);
......@@ -1336,6 +1342,13 @@ static void parse_interfaces_and_properties(pa_bluetooth_discovery *y, DBusMessa
return;
}
/* This function may be called only by hsphfpd backend.
Legacy HSP backend may be enabled only when hsphfpd daemon is not running. */
void pa_bluetooth_discovery_legacy_hsp_backend_enable(pa_bluetooth_discovery *y, bool enable) {
if (y->legacy_hsp_backend)
pa_bluetooth_legacy_hsp_backend_enable(y->legacy_hsp_backend, enable);
}
static void get_managed_objects_reply(DBusPendingCall *pending, void *userdata) {
pa_dbus_pending *p;
pa_bluetooth_discovery *y;
......@@ -1377,6 +1390,9 @@ static void get_managed_objects_reply(DBusPendingCall *pending, void *userdata)
if (!y->legacy_hsp_backend && (y->headset_backend == HEADSET_BACKEND_AUTO || y->headset_backend == HEADSET_BACKEND_LEGACY_HSP))
y->legacy_hsp_backend = pa_bluetooth_legacy_hsp_backend_new(y->core, y, (y->headset_backend == HEADSET_BACKEND_LEGACY_HSP));
if (!y->hsphfpd_backend && (y->headset_backend == HEADSET_BACKEND_AUTO || y->headset_backend == HEADSET_BACKEND_HSPHFPD))
y->hsphfpd_backend = pa_bluetooth_hsphfpd_backend_new(y->core, y);
finish:
dbus_message_unref(r);
......@@ -1429,6 +1445,10 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
pa_hashmap_remove_all(y->devices);
pa_hashmap_remove_all(y->adapters);
y->objects_listed = false;
if (y->hsphfpd_backend) {
pa_bluetooth_hsphfpd_backend_free(y->hsphfpd_backend);
y->hsphfpd_backend = NULL;
}
if (y->legacy_hsp_backend) {
pa_bluetooth_legacy_hsp_backend_free(y->legacy_hsp_backend);
y->legacy_hsp_backend = NULL;
......@@ -2398,6 +2418,9 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) {
pa_dbus_free_pending_list(&y->pending);
if (y->hsphfpd_backend)
pa_bluetooth_hsphfpd_backend_free(y->hsphfpd_backend);
if (y->legacy_hsp_backend)
pa_bluetooth_legacy_hsp_backend_free(y->legacy_hsp_backend);
......
......@@ -85,6 +85,7 @@ struct pa_bluetooth_transport {
uint8_t *config;
size_t config_size;
bool soft_volume;
uint16_t microphone_gain;
uint16_t speaker_gain;
......@@ -132,22 +133,26 @@ struct pa_bluetooth_adapter {
bool media_application_registered;
};
pa_bluetooth_backend *pa_bluetooth_hsphfpd_backend_new(pa_core *c, pa_bluetooth_discovery *y);
void pa_bluetooth_hsphfpd_backend_free(pa_bluetooth_backend *b);
#ifdef HAVE_BLUEZ_5_LEGACY_HSP
pa_bluetooth_backend *pa_bluetooth_legacy_hsp_backend_new(pa_core *c, pa_bluetooth_discovery *y, bool enable_hs_role);
pa_bluetooth_backend *pa_bluetooth_legacy_hsp_backend_new(pa_core *c, pa_bluetooth_discovery *y, bool enable);
void pa_bluetooth_legacy_hsp_backend_free(pa_bluetooth_backend *b);
void pa_bluetooth_legacy_hsp_backend_enable_hs_role(pa_bluetooth_backend *b, bool enable_hs_role);
void pa_bluetooth_legacy_hsp_backend_enable(pa_bluetooth_backend *b, bool enable);
#else
static inline pa_bluetooth_backend *pa_bluetooth_legacy_hsp_backend_new(pa_core *c, pa_bluetooth_discovery *y, bool enable_hs_role) {
static inline pa_bluetooth_backend *pa_bluetooth_legacy_hsp_backend_new(pa_core *c, pa_bluetooth_discovery *y, bool enable) {
return NULL;
}
static inline void pa_bluetooth_legacy_hsp_backend_free(pa_bluetooth_backend *b) {}
static inline void pa_bluetooth_legacy_hsp_backend_enable_hs_role(pa_bluetooth_backend *b, bool enable_hs_role) {}
static inline void pa_bluetooth_legacy_hsp_backend_enable(pa_bluetooth_backend *b, bool enable) {}
#endif
pa_bluetooth_transport *pa_bluetooth_transport_new(pa_bluetooth_device *d, const char *owner, const char *path,
pa_bluetooth_profile_t p, const uint8_t *config, size_t size);
void pa_bluetooth_transport_set_state(pa_bluetooth_transport *t, pa_bluetooth_transport_state_t state);
pa_bluetooth_transport *pa_bluetooth_transport_get(pa_bluetooth_discovery *y, const char *path);
void pa_bluetooth_transport_put(pa_bluetooth_transport *t);
void pa_bluetooth_transport_unlink(pa_bluetooth_transport *t);
void pa_bluetooth_transport_free(pa_bluetooth_transport *t);
......@@ -181,10 +186,12 @@ static inline bool pa_bluetooth_uuid_is_hsp_hs(const char *uuid) {
return pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_HS) || pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_HS_ALT);
}
#define HEADSET_BACKEND_HSPHFPD 0
#define HEADSET_BACKEND_LEGACY_HSP 1
#define HEADSET_BACKEND_AUTO 2
pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *core, int headset_backend);
pa_bluetooth_discovery* pa_bluetooth_discovery_ref(pa_bluetooth_discovery *y);
void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y);
void pa_bluetooth_discovery_legacy_hsp_backend_enable(pa_bluetooth_discovery *y, bool enable);
#endif
This diff is collapsed.
......@@ -40,7 +40,7 @@ struct pa_bluetooth_backend {
pa_core *core;
pa_dbus_connection *connection;
pa_bluetooth_discovery *discovery;
bool enable_hs_role;
bool enabled;
PA_LLIST_HEAD(pa_dbus_pending, pending);
};
......@@ -659,25 +659,27 @@ static void profile_done(pa_bluetooth_backend *b, pa_bluetooth_profile_t profile
}
}
void pa_bluetooth_legacy_hsp_backend_enable_hs_role(pa_bluetooth_backend *legacy_hsp_backend, bool enable_hs_role) {
if (enable_hs_role == legacy_hsp_backend->enable_hs_role)
void pa_bluetooth_legacy_hsp_backend_enable(pa_bluetooth_backend *backend, bool enable) {
if (enable == backend->enabled)
return;
if (enable_hs_role)
profile_init(legacy_hsp_backend, PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY);
else
profile_done(legacy_hsp_backend, PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY);
if (enable) {
pa_log_warn("Enabling legacy HSP backend");
profile_init(backend, PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT);
profile_init(backend, PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY);
} else {
pa_log_warn("Disabling legacy HSP backend");
profile_done(backend, PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT);
profile_done(backend, PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY);
}
legacy_hsp_backend->enable_hs_role = enable_hs_role;
backend->enabled = enable;
}
pa_bluetooth_backend *pa_bluetooth_legacy_hsp_backend_new(pa_core *c, pa_bluetooth_discovery *y, bool enable_hs_role) {
pa_bluetooth_backend *pa_bluetooth_legacy_hsp_backend_new(pa_core *c, pa_bluetooth_discovery *y, bool enable) {
pa_bluetooth_backend *backend;
DBusError err;
pa_log_debug("Bluetooth Headset Backend API support using the legacy HSP backend");
backend = pa_xnew0(pa_bluetooth_backend, 1);
backend->core = c;
......@@ -690,11 +692,12 @@ pa_bluetooth_backend *pa_bluetooth_legacy_hsp_backend_new(pa_core *c, pa_bluetoo
}
backend->discovery = y;
backend->enable_hs_role = enable_hs_role;
backend->enabled = enable;
if (enable_hs_role)
profile_init(backend, PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY);
profile_init(backend, PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT);
if (enable) {
profile_init(backend, PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT);
profile_init(backend, PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY);
}
return backend;
}
......@@ -704,9 +707,10 @@ void pa_bluetooth_legacy_hsp_backend_free(pa_bluetooth_backend *backend) {
pa_dbus_free_pending_list(&backend->pending);
if (backend->enable_hs_role)
profile_done(backend, PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY);
profile_done(backend, PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT);
if (backend->enabled) {
profile_done(backend, PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY);
profile_done(backend, PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT);
}
pa_dbus_connection_unref(backend->connection);
......
......@@ -3,6 +3,7 @@ libbluez5_util_sources = [
'a2dp-codec-sbc.c',
'a2dp-codec-util.c',
'bluez5-util.c',
'hsphfpd.c',
]
libbluez5_util_headers = [
......
......@@ -30,7 +30,7 @@ PA_MODULE_DESCRIPTION("Detect available Bluetooth daemon and load the correspond
PA_MODULE_VERSION(PACKAGE_VERSION);
PA_MODULE_LOAD_ONCE(true);
PA_MODULE_USAGE(
"headset=legacy_hsp|auto"
"headset=auto|hsphfpd|legacy_hsp"
"autodetect_mtu=<boolean>"
);
......
......@@ -35,7 +35,7 @@ PA_MODULE_DESCRIPTION("Detect available BlueZ 5 Bluetooth audio devices and load
PA_MODULE_VERSION(PACKAGE_VERSION);
PA_MODULE_LOAD_ONCE(true);
PA_MODULE_USAGE(
"headset=legacy_hsp|auto"
"headset=auto|hsphfpd|legacy_hsp"
"autodetect_mtu=<boolean>"
);
......@@ -92,8 +92,6 @@ static pa_hook_result_t device_connection_changed_cb(pa_bluetooth_discovery *y,
return PA_HOOK_OK;
}
const char *default_headset_backend = "auto";
int pa__init(pa_module *m) {
struct userdata *u;
pa_modargs *ma;
......@@ -108,14 +106,22 @@ int pa__init(pa_module *m) {
goto fail;
}
pa_assert_se(headset_str = pa_modargs_get_value(ma, "headset", default_headset_backend));
pa_assert_se(headset_str = pa_modargs_get_value(ma, "headset", "auto"));
if (pa_streq(headset_str, "hsphfpd"))
headset_backend = HEADSET_BACKEND_HSPHFPD;
#ifdef HAVE_BLUEZ_5_LEGACY_HSP
/* For backward compatibility we also support "native" as alias for "legacy_hsp" */
if (pa_streq(headset_str, "native") || pa_streq(headset_str, "legacy_hsp"))
else if (pa_streq(headset_str, "native") || pa_streq(headset_str, "legacy_hsp"))
headset_backend = HEADSET_BACKEND_LEGACY_HSP;
#endif
else if (pa_streq(headset_str, "auto"))
headset_backend = HEADSET_BACKEND_AUTO;
else {
pa_log("headset parameter must be either legacy_hsp or auto (found %s)", headset_str);
pa_log("headset parameter must be either hsphfpd"
#ifdef HAVE_BLUEZ_5_LEGACY_HSP
", legacy_hsp"
#endif
" or auto (found %s)", headset_str);
goto fail;
}
......
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