temp/pulseaudio: drop (MR 5163)
Upstream MR has been closed by Dylan 2 months ago, and this feature is already present in pipewire. We are doing considerably amount of work to get Pipewire production-ready in postmarketOS, including features to let users choose. Given HFP support is actually a nice-to-have feature, but not a great requirement, our fork is outdated (aports is on 17.0), and that the upstream MR has been dropped and is not being worked on, it might be time to drop this.
This commit is contained in:
parent
263d00790e
commit
be9ac83d73
32 changed files with 0 additions and 4790 deletions
|
@ -1,110 +0,0 @@
|
|||
From 355c4cc3f70abee505d2aad0a37d453a44ead1c2 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Wed, 6 Apr 2022 08:15:13 +0200
|
||||
Subject: [PATCH 01/26] bluez5-util: move pa_bluetooth_discovery to header
|
||||
|
||||
---
|
||||
src/modules/bluetooth/bluez5-util.c | 23 -----------------------
|
||||
src/modules/bluetooth/bluez5-util.h | 24 ++++++++++++++++++++++++
|
||||
src/modules/meson.build | 2 +-
|
||||
3 files changed, 25 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/src/modules/bluetooth/bluez5-util.c b/src/modules/bluetooth/bluez5-util.c
|
||||
index 83f2932e9..2f8d6faf1 100644
|
||||
--- a/src/modules/bluetooth/bluez5-util.c
|
||||
+++ b/src/modules/bluetooth/bluez5-util.c
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <pulsecore/core.h>
|
||||
#include <pulsecore/core-error.h>
|
||||
#include <pulsecore/core-util.h>
|
||||
-#include <pulsecore/dbus-shared.h>
|
||||
#include <pulsecore/log.h>
|
||||
#include <pulsecore/macro.h>
|
||||
#include <pulsecore/refcnt.h>
|
||||
@@ -128,28 +127,6 @@ static uint16_t volume_to_a2dp_gain(pa_volume_t volume) {
|
||||
return gain;
|
||||
}
|
||||
|
||||
-struct pa_bluetooth_discovery {
|
||||
- PA_REFCNT_DECLARE;
|
||||
-
|
||||
- pa_core *core;
|
||||
- pa_dbus_connection *connection;
|
||||
- bool filter_added;
|
||||
- bool matches_added;
|
||||
- bool objects_listed;
|
||||
- pa_hook hooks[PA_BLUETOOTH_HOOK_MAX];
|
||||
- pa_hashmap *adapters;
|
||||
- pa_hashmap *devices;
|
||||
- pa_hashmap *transports;
|
||||
- pa_bluetooth_profile_status_t profiles_status[PA_BLUETOOTH_PROFILE_COUNT];
|
||||
-
|
||||
- int headset_backend;
|
||||
- pa_bluetooth_backend *ofono_backend, *native_backend;
|
||||
- PA_LLIST_HEAD(pa_dbus_pending, pending);
|
||||
- bool enable_native_hsp_hs;
|
||||
- bool enable_native_hfp_hf;
|
||||
- bool enable_msbc;
|
||||
-};
|
||||
-
|
||||
static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, DBusMessage *m,
|
||||
DBusPendingCallNotifyFunction func, void *call_data) {
|
||||
pa_dbus_pending *p;
|
||||
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
|
||||
index 86eb6301e..f899d9d0c 100644
|
||||
--- a/src/modules/bluetooth/bluez5-util.h
|
||||
+++ b/src/modules/bluetooth/bluez5-util.h
|
||||
@@ -22,6 +22,7 @@
|
||||
***/
|
||||
|
||||
#include <pulsecore/core.h>
|
||||
+#include <pulsecore/dbus-shared.h>
|
||||
|
||||
#include "a2dp-codec-util.h"
|
||||
|
||||
@@ -134,6 +135,29 @@ struct pa_bluetooth_transport {
|
||||
void *userdata;
|
||||
};
|
||||
|
||||
+struct pa_bluetooth_discovery {
|
||||
+ PA_REFCNT_DECLARE;
|
||||
+
|
||||
+ pa_core *core;
|
||||
+ pa_dbus_connection *connection;
|
||||
+ bool filter_added;
|
||||
+ bool matches_added;
|
||||
+ bool objects_listed;
|
||||
+ pa_hook hooks[PA_BLUETOOTH_HOOK_MAX];
|
||||
+ pa_hashmap *adapters;
|
||||
+ pa_hashmap *devices;
|
||||
+ pa_hashmap *transports;
|
||||
+ pa_bluetooth_profile_status_t profiles_status[PA_BLUETOOTH_PROFILE_COUNT];
|
||||
+
|
||||
+ int headset_backend;
|
||||
+ pa_bluetooth_backend *ofono_backend, *native_backend;
|
||||
+ PA_LLIST_HEAD(pa_dbus_pending, pending);
|
||||
+ bool enable_native_hsp_hs;
|
||||
+ bool enable_native_hfp_hf;
|
||||
+ bool enable_msbc;
|
||||
+};
|
||||
+
|
||||
+
|
||||
struct pa_bluetooth_device {
|
||||
pa_bluetooth_discovery *discovery;
|
||||
pa_bluetooth_adapter *adapter;
|
||||
diff --git a/src/modules/meson.build b/src/modules/meson.build
|
||||
index 1ae172971..08c754948 100644
|
||||
--- a/src/modules/meson.build
|
||||
+++ b/src/modules/meson.build
|
||||
@@ -123,7 +123,7 @@ if cdata.has('HAVE_BLUEZ_5')
|
||||
all_modules += [
|
||||
[ 'module-bluetooth-discover', 'bluetooth/module-bluetooth-discover.c' ],
|
||||
[ 'module-bluetooth-policy', 'bluetooth/module-bluetooth-policy.c', [], [], [dbus_dep] ],
|
||||
- [ 'module-bluez5-device', 'bluetooth/module-bluez5-device.c', [], [], [], libbluez5_util ],
|
||||
+ [ 'module-bluez5-device', 'bluetooth/module-bluez5-device.c', [], [], [dbus_dep], libbluez5_util ],
|
||||
[ 'module-bluez5-discover', 'bluetooth/module-bluez5-discover.c', [], [], [dbus_dep], libbluez5_util ],
|
||||
]
|
||||
endif
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,194 +0,0 @@
|
|||
From 5aebba47f8215d5c580602a34082fc27081d963d Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Tue, 5 Apr 2022 20:10:05 +0200
|
||||
Subject: [PATCH 02/26] bluetooth: add AT+BIA support
|
||||
|
||||
AT+BIA is used to enable/disable CIND indicators by Bluetooth HFP spec.
|
||||
By default, all indicators are enabled on connection.
|
||||
AT+BIA will configure which indicators should be disabled then,
|
||||
the disabled indicators may be enabled later on again with AT+BIA.
|
||||
When the connection is lost and recovered, all indicators are enabled
|
||||
again. The HF will reconfigure the indicators again with an AT+BIA
|
||||
command.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 93 ++++++++++++++++++++++++--
|
||||
1 file changed, 87 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index f6b85e90d..d26edc1c9 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -39,6 +39,11 @@
|
||||
#include "bluez5-util.h"
|
||||
#include "bt-codec-msbc.h"
|
||||
|
||||
+#define MANDATORY_CALL_INDICATORS \
|
||||
+ "(\"call\",(0-1))," \
|
||||
+ "(\"callsetup\",(0-3))," \
|
||||
+ "(\"callheld\",(0-2))" \
|
||||
+
|
||||
struct pa_bluetooth_backend {
|
||||
pa_core *core;
|
||||
pa_dbus_connection *connection;
|
||||
@@ -47,6 +52,8 @@ struct pa_bluetooth_backend {
|
||||
bool enable_shared_profiles;
|
||||
bool enable_hsp_hs;
|
||||
bool enable_hfp_hf;
|
||||
+ bool cmer_indicator_reporting_enabled;
|
||||
+ uint32_t cind_enabled_indicators;
|
||||
|
||||
PA_LLIST_HEAD(pa_dbus_pending, pending);
|
||||
};
|
||||
@@ -97,6 +104,20 @@ enum hfp_ag_features {
|
||||
HFP_AG_INDICATORS = 10,
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * Always keep this struct in sync with indicator discovery of AT+CIND=?
|
||||
+ * These indicators are used in bitflags and intentionally start at 1
|
||||
+ * since AT+CIND indicators start at index 1.
|
||||
+ */
|
||||
+typedef enum pa_bluetooth_ag_to_hf_indicators {
|
||||
+ CIND_CALL_INDICATOR = 1,
|
||||
+ CIND_CALL_SETUP_INDICATOR = 2,
|
||||
+ CIND_CALL_HELD_INDICATOR = 3,
|
||||
+ CIND_SERVICE_INDICATOR = 4,
|
||||
+ CIND_BATT_CHG_INDICATOR = 5,
|
||||
+ CIND_INDICATOR_MAX = 6
|
||||
+} pa_bluetooth_ag_to_hf_indicators_t;
|
||||
+
|
||||
/* gateway features we support, which is as little as we can get away with */
|
||||
static uint32_t hfp_features =
|
||||
/* HFP 1.6 requires this */
|
||||
@@ -588,8 +609,9 @@ static pa_volume_t set_source_volume(pa_bluetooth_transport *t, pa_volume_t volu
|
||||
|
||||
static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf)
|
||||
{
|
||||
+ struct pa_bluetooth_discovery *discovery = t->device->discovery;
|
||||
struct hfp_config *c = t->config;
|
||||
- int indicator, val;
|
||||
+ int indicator, mode, val;
|
||||
char str[5];
|
||||
const char *r;
|
||||
size_t len;
|
||||
@@ -607,6 +629,34 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
c->supports_indicators = !!(1 << HFP_HF_INDICATORS);
|
||||
c->state = 1;
|
||||
|
||||
+ return true;
|
||||
+ } else if (sscanf(buf, "AT+BIA=%s", str) == 1) {
|
||||
+ /* Indicators start with index 1 and follow the order of the AT+CIND=? response */
|
||||
+ indicator = 1;
|
||||
+
|
||||
+ while ((r = pa_split_in_place(str, ",", &len, &state))) {
|
||||
+ /* Ignore updates to mandantory indicators which are always ON */
|
||||
+ if (indicator == CIND_CALL_INDICATOR
|
||||
+ || indicator == CIND_CALL_SETUP_INDICATOR
|
||||
+ || indicator == CIND_CALL_HELD_INDICATOR)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Indicators may have no value and should be skipped */
|
||||
+ if (len == 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (len == 1 && r[0] == '1')
|
||||
+ discovery->native_backend->cind_enabled_indicators |= (1 << indicator);
|
||||
+ else if (len == 1 && r[0] == '0')
|
||||
+ discovery->native_backend->cind_enabled_indicators &= ~(1 << indicator);
|
||||
+ else {
|
||||
+ pa_log_error("Unable to parse indicator of AT+BIA command: %s", buf);
|
||||
+ rfcomm_write_response(fd, "ERROR");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ indicator++;
|
||||
+ }
|
||||
return true;
|
||||
} else if (sscanf(buf, "AT+BAC=%3s", str) == 1) {
|
||||
c->support_msbc = false;
|
||||
@@ -637,10 +687,8 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
rfcomm_write_response(fd, "+CIND: "
|
||||
/* many indicators can be supported, only call and
|
||||
* callheld are mandatory, so that's all we reply */
|
||||
- "(\"service\",(0-1)),"
|
||||
- "(\"call\",(0-1)),"
|
||||
- "(\"callsetup\",(0-3)),"
|
||||
- "(\"callheld\",(0-2))");
|
||||
+ MANDATORY_CALL_INDICATORS ",",
|
||||
+ "(\"service\",(0-1))");
|
||||
c->state = 2;
|
||||
|
||||
return true;
|
||||
@@ -650,7 +698,24 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
|
||||
return true;
|
||||
} else if ((c->state == 2 || c->state == 3) && pa_startswith(buf, "AT+CMER=")) {
|
||||
- rfcomm_write_response(fd, "OK");
|
||||
+ if (sscanf(buf, "AT+CMER=%d,%*d,%*d,%d", &mode, &val) == 2) {
|
||||
+ /* Bluetooth HFP spec only defines mode == 3 */
|
||||
+ if (mode != 3) {
|
||||
+ pa_log_warn("Unexpected mode for AT+CMER: %d", mode);
|
||||
+ }
|
||||
+
|
||||
+ /* Configure CMER event reporting */
|
||||
+ discovery->native_backend->cmer_indicator_reporting_enabled = !!val;
|
||||
+
|
||||
+ pa_log_debug("Event indications enabled? %s", pa_yes_no(val));
|
||||
+
|
||||
+ rfcomm_write_response(fd, "OK");
|
||||
+ }
|
||||
+ else {
|
||||
+ pa_log_error("Unable to parse AT+CMER command: %s", buf);
|
||||
+ rfcomm_write_response(fd, "ERROR");
|
||||
+ return false;
|
||||
+ }
|
||||
|
||||
if (c->support_codec_negotiation) {
|
||||
if (c->support_msbc && pa_bluetooth_discovery_get_enable_msbc(t->device->discovery)) {
|
||||
@@ -740,6 +805,8 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
|
||||
static void rfcomm_io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
|
||||
pa_bluetooth_transport *t = userdata;
|
||||
+ pa_bluetooth_discovery *discovery = t->device->discovery;
|
||||
+ int i;
|
||||
|
||||
pa_assert(io);
|
||||
pa_assert(t);
|
||||
@@ -860,6 +927,11 @@ static void rfcomm_io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_i
|
||||
return;
|
||||
|
||||
fail:
|
||||
+ /* Service Connection lost, reset indicators and event reporting to default values */
|
||||
+ discovery->native_backend->cmer_indicator_reporting_enabled = false;
|
||||
+ for (i = 1; i < CIND_INDICATOR_MAX; i++)
|
||||
+ discovery->native_backend->cind_enabled_indicators |= (1 << i);
|
||||
+
|
||||
pa_bluetooth_transport_unlink(t);
|
||||
pa_bluetooth_transport_free(t);
|
||||
}
|
||||
@@ -1188,6 +1260,7 @@ void pa_bluetooth_native_backend_enable_shared_profiles(pa_bluetooth_backend *na
|
||||
pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_discovery *y, bool enable_shared_profiles) {
|
||||
pa_bluetooth_backend *backend;
|
||||
DBusError err;
|
||||
+ int i;
|
||||
|
||||
pa_log_debug("Bluetooth Headset Backend API support using the native backend");
|
||||
|
||||
@@ -1220,6 +1293,14 @@ pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_d
|
||||
if (backend->enable_shared_profiles)
|
||||
native_backend_apply_profile_registration_change(backend, true);
|
||||
|
||||
+ /* All CIND indicators are enabled by default until overriden by AT+BIA */
|
||||
+ for (i = 1; i < CIND_INDICATOR_MAX; i++)
|
||||
+ backend->cind_enabled_indicators |= (1 << i);
|
||||
+
|
||||
+ /* While all CIND indicators are enabled, event reporting is not enabled by default */
|
||||
+ backend->cmer_indicator_reporting_enabled = false;
|
||||
+
|
||||
+
|
||||
return backend;
|
||||
}
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,393 +0,0 @@
|
|||
From 0c8451cae9c585793fa98fb99864d5228127bbf9 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Tue, 5 Apr 2022 20:26:09 +0200
|
||||
Subject: [PATCH 03/26] bluetooth: add UPower backend
|
||||
|
||||
UPower provides information about the power supply and battery
|
||||
level of the host. Add a backend to retrieve the host battery level.
|
||||
---
|
||||
src/modules/bluetooth/meson.build | 4 +-
|
||||
src/modules/bluetooth/upower.c | 300 ++++++++++++++++++++++++++++++
|
||||
src/modules/bluetooth/upower.h | 41 ++++
|
||||
3 files changed, 344 insertions(+), 1 deletion(-)
|
||||
create mode 100644 src/modules/bluetooth/upower.c
|
||||
create mode 100644 src/modules/bluetooth/upower.h
|
||||
|
||||
diff --git a/src/modules/bluetooth/meson.build b/src/modules/bluetooth/meson.build
|
||||
index ca77ee6aa..0703d5086 100644
|
||||
--- a/src/modules/bluetooth/meson.build
|
||||
+++ b/src/modules/bluetooth/meson.build
|
||||
@@ -16,6 +16,8 @@ libbluez5_util_headers = [
|
||||
|
||||
if get_option('bluez5-native-headset')
|
||||
libbluez5_util_sources += [ 'backend-native.c' ]
|
||||
+ libbluez5_util_sources += [ 'upower.c' ]
|
||||
+ libbluez5_util_headers += [ 'upower.h' ]
|
||||
endif
|
||||
|
||||
if get_option('bluez5-ofono-headset')
|
||||
@@ -35,7 +37,7 @@ libbluez5_util = shared_library('bluez5-util',
|
||||
c_args : [pa_c_args, server_c_args],
|
||||
link_args : [nodelete_link_args],
|
||||
include_directories : [configinc, topinc],
|
||||
- dependencies : [libpulse_dep, libpulsecommon_dep, libpulsecore_dep, bluez_dep, dbus_dep, sbc_dep, libintl_dep, bluez5_gst_dep, bluez5_gstapp_dep],
|
||||
+ dependencies : [libpulse_dep, libpulsecommon_dep, libpulsecore_dep, bluez_dep, dbus_dep, sbc_dep, libintl_dep, bluez5_gst_dep, bluez5_gstapp_dep, libm_dep],
|
||||
install : true,
|
||||
install_rpath : privlibdir,
|
||||
install_dir : modlibexecdir,
|
||||
diff --git a/src/modules/bluetooth/upower.c b/src/modules/bluetooth/upower.c
|
||||
new file mode 100644
|
||||
index 000000000..b5cb89bfe
|
||||
--- /dev/null
|
||||
+++ b/src/modules/bluetooth/upower.c
|
||||
@@ -0,0 +1,300 @@
|
||||
+/***
|
||||
+ This file is part of PulseAudio.
|
||||
+
|
||||
+ Copyrigth 2022 Dylan Van Assche <me@dylanvanassche.be>
|
||||
+
|
||||
+ PulseAudio is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU Lesser General Public License as
|
||||
+ published by the Free Software Foundation; either version 2.1 of the
|
||||
+ License, or (at your option) any later version.
|
||||
+
|
||||
+ PulseAudio is distributed in the hope that it will be useful, but
|
||||
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||
+***/
|
||||
+#ifdef HAVE_CONFIG_H
|
||||
+#include <config.h>
|
||||
+#endif
|
||||
+
|
||||
+#include <math.h>
|
||||
+#include <pulsecore/core-error.h>
|
||||
+#include <pulsecore/core-util.h>
|
||||
+#include <pulsecore/dbus-shared.h>
|
||||
+#include <pulsecore/log.h>
|
||||
+#include <pulse/timeval.h>
|
||||
+#include <pulse/rtclock.h>
|
||||
+
|
||||
+#include "upower.h"
|
||||
+
|
||||
+static pa_dbus_pending* send_and_add_to_pending(pa_upower_backend *backend, DBusMessage *m,
|
||||
+ DBusPendingCallNotifyFunction func, void *call_data) {
|
||||
+
|
||||
+ pa_dbus_pending *p;
|
||||
+ DBusPendingCall *call;
|
||||
+
|
||||
+ pa_assert(backend);
|
||||
+ pa_assert(m);
|
||||
+
|
||||
+ pa_assert_se(dbus_connection_send_with_reply(pa_dbus_connection_get(backend->connection), m, &call, -1));
|
||||
+
|
||||
+ p = pa_dbus_pending_new(pa_dbus_connection_get(backend->connection), m, call, backend, call_data);
|
||||
+ PA_LLIST_PREPEND(pa_dbus_pending, backend->pending, p);
|
||||
+ dbus_pending_call_set_notify(call, func, p, NULL);
|
||||
+
|
||||
+ return p;
|
||||
+}
|
||||
+
|
||||
+static void parse_percentage(pa_upower_backend *b, DBusMessageIter *i) {
|
||||
+ double percentage;
|
||||
+ unsigned int battery_level;
|
||||
+
|
||||
+ pa_assert(i);
|
||||
+ pa_assert(dbus_message_iter_get_arg_type(i) == DBUS_TYPE_DOUBLE);
|
||||
+
|
||||
+ dbus_message_iter_get_basic(i, &percentage);
|
||||
+ battery_level = (unsigned int) round(percentage / 20.0);
|
||||
+
|
||||
+ if (battery_level != b->battery_level) {
|
||||
+ b->battery_level = battery_level;
|
||||
+ pa_log_debug("AG battery level updated (%d/5)", b->battery_level);
|
||||
+ pa_hook_fire(pa_bluetooth_discovery_hook(b->discovery, PA_BLUETOOTH_HOOK_HOST_BATTERY_LEVEL_CHANGED), b);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void get_percentage_reply(DBusPendingCall *pending, void *userdata) {
|
||||
+ pa_dbus_pending *p;
|
||||
+ pa_upower_backend *b;
|
||||
+ DBusMessage *r;
|
||||
+ DBusMessageIter arg_i, variant_i;
|
||||
+
|
||||
+ pa_assert(pending);
|
||||
+ pa_assert_se(p = userdata);
|
||||
+ pa_assert_se(b = p->context_data);
|
||||
+ pa_assert_se(r = dbus_pending_call_steal_reply(pending));
|
||||
+
|
||||
+ if (dbus_message_is_error(r, DBUS_ERROR_UNKNOWN_METHOD)) {
|
||||
+ pa_log_warn("UPower D-Bus Display Device not available");
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
|
||||
+ pa_log_error("Get() failed: %s: %s", dbus_message_get_error_name(r), pa_dbus_get_error_message(r));
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ if (!dbus_message_iter_init(r, &arg_i) || !pa_streq(dbus_message_get_signature(r), "v")) {
|
||||
+ pa_log_error("Invalid reply signature for Get()");
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ dbus_message_iter_recurse(&arg_i, &variant_i);
|
||||
+ parse_percentage(b, &variant_i);
|
||||
+
|
||||
+finish:
|
||||
+ dbus_message_unref(r);
|
||||
+
|
||||
+ PA_LLIST_REMOVE(pa_dbus_pending, b->pending, p);
|
||||
+ pa_dbus_pending_free(p);
|
||||
+}
|
||||
+
|
||||
+static const char *check_variant_property(DBusMessageIter *i) {
|
||||
+ const char *key;
|
||||
+
|
||||
+ pa_assert(i);
|
||||
+
|
||||
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) {
|
||||
+ pa_log_error("Property name not a string.");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ dbus_message_iter_get_basic(i, &key);
|
||||
+
|
||||
+ if (!dbus_message_iter_next(i)) {
|
||||
+ pa_log_error("Property value missing");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_VARIANT) {
|
||||
+ pa_log_error("Property value not a variant.");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return key;
|
||||
+}
|
||||
+
|
||||
+static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *data) {
|
||||
+ DBusError err;
|
||||
+ DBusMessage *m2;
|
||||
+ static const char* upower_device_interface = UPOWER_SERVICE UPOWER_DEVICE_INTERFACE;
|
||||
+ static const char* percentage_property = "Percentage";
|
||||
+ pa_upower_backend *b = data;
|
||||
+ const char *path, *interface, *member;
|
||||
+
|
||||
+ pa_assert(bus);
|
||||
+ pa_assert(m);
|
||||
+ pa_assert(b);
|
||||
+
|
||||
+ dbus_error_init(&err);
|
||||
+
|
||||
+ path = dbus_message_get_path(m);
|
||||
+ interface = dbus_message_get_interface(m);
|
||||
+ member = dbus_message_get_member(m);
|
||||
+
|
||||
+ pa_log_debug("dbus: path=%s, interface=%s, member=%s", path, interface, member);
|
||||
+
|
||||
+ /* UPower D-Bus status change */
|
||||
+ if (dbus_message_is_signal(m, DBUS_INTERFACE_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_error("Failed to parse " DBUS_INTERFACE_DBUS ".NameOwnerChanged: %s", err.message);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ if (pa_streq(name, UPOWER_SERVICE)) {
|
||||
+
|
||||
+ /* UPower disappeared from D-Bus */
|
||||
+ if (old_owner && *old_owner) {
|
||||
+ pa_log_debug("UPower disappeared from D-Bus");
|
||||
+ b->battery_level = 0;
|
||||
+ pa_hook_fire(pa_bluetooth_discovery_hook(b->discovery, PA_BLUETOOTH_HOOK_HOST_BATTERY_LEVEL_CHANGED), b);
|
||||
+ }
|
||||
+
|
||||
+ /* UPower appeared on D-Bus */
|
||||
+ if (new_owner && *new_owner) {
|
||||
+ pa_log_debug("UPower appeared on D-Bus");
|
||||
+
|
||||
+ /* Update battery level */
|
||||
+ pa_assert_se(m2 = dbus_message_new_method_call(UPOWER_SERVICE, UPOWER_DISPLAY_DEVICE_OBJECT, DBUS_INTERFACE_PROPERTIES, "Get"));
|
||||
+ pa_assert_se(dbus_message_append_args(m2,
|
||||
+ DBUS_TYPE_STRING, &upower_device_interface,
|
||||
+ DBUS_TYPE_STRING, &percentage_property,
|
||||
+ DBUS_TYPE_INVALID));
|
||||
+ send_and_add_to_pending(b, m2, get_percentage_reply, NULL);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
+ /* UPower battery level property updates */
|
||||
+ } else if (dbus_message_is_signal(m, DBUS_INTERFACE_PROPERTIES, "PropertiesChanged")) {
|
||||
+ DBusMessageIter arg_i, element_i;
|
||||
+
|
||||
+ if (!dbus_message_iter_init(m, &arg_i) || !pa_streq(dbus_message_get_signature(m), "sa{sv}as")) {
|
||||
+ pa_log_error("Invalid signature found in PropertiesChanged");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* Skip interface name */
|
||||
+ pa_assert_se(dbus_message_iter_next(&arg_i));
|
||||
+ pa_assert(dbus_message_iter_get_arg_type(&arg_i) == DBUS_TYPE_ARRAY);
|
||||
+
|
||||
+ dbus_message_iter_recurse(&arg_i, &element_i);
|
||||
+
|
||||
+ /* Parse UPower property updates */
|
||||
+ while (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
|
||||
+ DBusMessageIter dict_i, variant_i;
|
||||
+ const char *key;
|
||||
+
|
||||
+ dbus_message_iter_recurse(&element_i, &dict_i);
|
||||
+
|
||||
+ /* Retrieve property name */
|
||||
+ key = check_variant_property(&dict_i);
|
||||
+ if (key == NULL) {
|
||||
+ pa_log_error("Received invalid property!");
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ dbus_message_iter_recurse(&dict_i, &variant_i);
|
||||
+
|
||||
+ if(pa_streq(path, UPOWER_DISPLAY_DEVICE_OBJECT)) {
|
||||
+ pa_log_debug("UPower Device property updated: %s", key);
|
||||
+
|
||||
+ if(pa_streq(key, "Percentage"))
|
||||
+ parse_percentage(b, &variant_i);
|
||||
+ }
|
||||
+
|
||||
+ dbus_message_iter_next(&element_i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+fail:
|
||||
+ dbus_error_free(&err);
|
||||
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
+}
|
||||
+
|
||||
+unsigned int pa_upower_get_battery_level(pa_upower_backend *backend) {
|
||||
+ return backend->battery_level;
|
||||
+}
|
||||
+
|
||||
+pa_upower_backend *pa_upower_backend_new(pa_core *c, pa_bluetooth_discovery *d) {
|
||||
+ pa_upower_backend *backend;
|
||||
+ DBusError err;
|
||||
+ DBusMessage *m;
|
||||
+ static const char* upower_device_interface = UPOWER_SERVICE UPOWER_DEVICE_INTERFACE;
|
||||
+ static const char* percentage_property = "Percentage";
|
||||
+
|
||||
+ pa_log_debug("Native backend enabled UPower battery status reporting");
|
||||
+
|
||||
+ backend = pa_xnew0(pa_upower_backend, 1);
|
||||
+ backend->core = c;
|
||||
+ backend->discovery = d;
|
||||
+
|
||||
+ /* Get DBus connection */
|
||||
+ dbus_error_init(&err);
|
||||
+ if (!(backend->connection = pa_dbus_bus_get(c, DBUS_BUS_SYSTEM, &err))) {
|
||||
+ pa_log("Failed to get D-Bus connection: %s", err.message);
|
||||
+ dbus_error_free(&err);
|
||||
+ pa_xfree(backend);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ /* Add filter callback for DBus connection */
|
||||
+ if (!dbus_connection_add_filter(pa_dbus_connection_get(backend->connection), filter_cb, backend, NULL)) {
|
||||
+ pa_log_error("Failed to add filter function");
|
||||
+ pa_dbus_connection_unref(backend->connection);
|
||||
+ pa_xfree(backend);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ /* Register for battery level changes from UPower */
|
||||
+ if (pa_dbus_add_matches(pa_dbus_connection_get(backend->connection), &err,
|
||||
+ "type='signal',sender='" DBUS_SERVICE_DBUS "',interface='" DBUS_INTERFACE_DBUS "',member='NameOwnerChanged',"
|
||||
+ "arg0='" UPOWER_SERVICE "'",
|
||||
+ "type='signal',sender='" UPOWER_SERVICE "',interface='" DBUS_INTERFACE_PROPERTIES "',member='PropertiesChanged'",
|
||||
+ NULL) < 0) {
|
||||
+ pa_log("Failed to add UPower D-Bus matches: %s", err.message);
|
||||
+ dbus_connection_remove_filter(pa_dbus_connection_get(backend->connection), filter_cb, backend);
|
||||
+ pa_dbus_connection_unref(backend->connection);
|
||||
+ pa_xfree(backend);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ /* Initialize battery level by requesting it from UPower */
|
||||
+ pa_assert_se(m = dbus_message_new_method_call(UPOWER_SERVICE, UPOWER_DISPLAY_DEVICE_OBJECT, DBUS_INTERFACE_PROPERTIES, "Get"));
|
||||
+ pa_assert_se(dbus_message_append_args(m,
|
||||
+ DBUS_TYPE_STRING, &upower_device_interface,
|
||||
+ DBUS_TYPE_STRING, &percentage_property,
|
||||
+ DBUS_TYPE_INVALID));
|
||||
+ send_and_add_to_pending(backend, m, get_percentage_reply, NULL);
|
||||
+
|
||||
+ return backend;
|
||||
+}
|
||||
+
|
||||
+void pa_upower_backend_free(pa_upower_backend *backend) {
|
||||
+ pa_assert(backend);
|
||||
+
|
||||
+ pa_dbus_free_pending_list(&backend->pending);
|
||||
+
|
||||
+ pa_dbus_connection_unref(backend->connection);
|
||||
+
|
||||
+ pa_xfree(backend);
|
||||
+}
|
||||
+
|
||||
diff --git a/src/modules/bluetooth/upower.h b/src/modules/bluetooth/upower.h
|
||||
new file mode 100644
|
||||
index 000000000..3e9ee9291
|
||||
--- /dev/null
|
||||
+++ b/src/modules/bluetooth/upower.h
|
||||
@@ -0,0 +1,41 @@
|
||||
+#pragma once
|
||||
+
|
||||
+/***
|
||||
+ This file is part of PulseAudio.
|
||||
+
|
||||
+ Copyrigth 2022 Dylan Van Assche <me@dylanvanassche.be>
|
||||
+
|
||||
+ PulseAudio is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU Lesser General Public License as
|
||||
+ published by the Free Software Foundation; either version 2.1 of the
|
||||
+ License, or (at your option) any later version.
|
||||
+
|
||||
+ PulseAudio is distributed in the hope that it will be useful, but
|
||||
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||
+***/
|
||||
+
|
||||
+#include "bluez5-util.h"
|
||||
+
|
||||
+#define UPOWER_SERVICE "org.freedesktop.UPower"
|
||||
+#define UPOWER_DEVICE_INTERFACE ".Device"
|
||||
+#define UPOWER_DISPLAY_DEVICE_OBJECT "/org/freedesktop/UPower/devices/DisplayDevice"
|
||||
+
|
||||
+struct pa_upower_backend {
|
||||
+ pa_core *core;
|
||||
+ pa_dbus_connection *connection;
|
||||
+ pa_bluetooth_discovery *discovery;
|
||||
+ unsigned int battery_level;
|
||||
+
|
||||
+ PA_LLIST_HEAD(pa_dbus_pending, pending);
|
||||
+};
|
||||
+
|
||||
+pa_upower_backend *pa_upower_backend_new(pa_core *c, pa_bluetooth_discovery *d);
|
||||
+void pa_upower_backend_free(pa_upower_backend *backend);
|
||||
+void pa_upower_register_transport(pa_upower_backend *backend, pa_bluetooth_transport *t);
|
||||
+void pa_upower_unregister_transport(pa_upower_backend *backend);
|
||||
+unsigned int pa_upower_get_battery_level(pa_upower_backend *backend);
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
From 78e255eefb417275e73f8ed96ce08bf7c3a1dff9 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Tue, 5 Apr 2022 20:39:11 +0200
|
||||
Subject: [PATCH 04/26] bluetooth: hook up UPower backend
|
||||
|
||||
Hook up the UPower backend to backend-native to report
|
||||
the host battery level to the HF.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 100 +++++++++++++++++++++++--
|
||||
src/modules/bluetooth/bluez5-util.h | 2 +
|
||||
2 files changed, 95 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index d26edc1c9..a490d6efd 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "bluez5-util.h"
|
||||
#include "bt-codec-msbc.h"
|
||||
+#include "upower.h"
|
||||
|
||||
#define MANDATORY_CALL_INDICATORS \
|
||||
"(\"call\",(0-1))," \
|
||||
@@ -49,6 +50,8 @@ struct pa_bluetooth_backend {
|
||||
pa_dbus_connection *connection;
|
||||
pa_bluetooth_discovery *discovery;
|
||||
pa_hook_slot *adapter_uuids_changed_slot;
|
||||
+ pa_hook_slot *host_battery_level_changed_slot;
|
||||
+ pa_upower_backend *upower;
|
||||
bool enable_shared_profiles;
|
||||
bool enable_hsp_hs;
|
||||
bool enable_hfp_hf;
|
||||
@@ -683,17 +686,27 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
|
||||
return true;
|
||||
} else if (c->state == 1 && pa_startswith(buf, "AT+CIND=?")) {
|
||||
- /* we declare minimal no indicators */
|
||||
- rfcomm_write_response(fd, "+CIND: "
|
||||
- /* many indicators can be supported, only call and
|
||||
- * callheld are mandatory, so that's all we reply */
|
||||
- MANDATORY_CALL_INDICATORS ",",
|
||||
- "(\"service\",(0-1))");
|
||||
+ /* UPower backend available, declare support for more indicators */
|
||||
+ if (discovery->native_backend->upower) {
|
||||
+ rfcomm_write_response(fd, "+CIND: "
|
||||
+ MANDATORY_CALL_INDICATORS ","
|
||||
+ "(\"service\",(0-1)),"
|
||||
+ "(\"battchg\",(0-5))");
|
||||
+
|
||||
+ /* Minimal indicators supported without any additional backend */
|
||||
+ } else {
|
||||
+ rfcomm_write_response(fd, "+CIND: "
|
||||
+ MANDATORY_CALL_INDICATORS ","
|
||||
+ "(\"service\",(0-1))");
|
||||
+ }
|
||||
c->state = 2;
|
||||
|
||||
return true;
|
||||
} else if (c->state == 2 && pa_startswith(buf, "AT+CIND?")) {
|
||||
- rfcomm_write_response(fd, "+CIND: 0,0,0,0");
|
||||
+ if (discovery->native_backend->upower)
|
||||
+ rfcomm_write_response(fd, "+CIND: 0,0,0,0,%u", pa_upower_get_battery_level(discovery->native_backend->upower));
|
||||
+ else
|
||||
+ rfcomm_write_response(fd, "+CIND: 0,0,0,0");
|
||||
c->state = 3;
|
||||
|
||||
return true;
|
||||
@@ -803,6 +816,67 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
return true;
|
||||
}
|
||||
|
||||
+static int get_rfcomm_fd (pa_bluetooth_discovery *discovery) {
|
||||
+ struct pa_bluetooth_transport *t;
|
||||
+ struct transport_data *trd = NULL;
|
||||
+ pa_bluetooth_profile_t profiles[] = { PA_BLUETOOTH_PROFILE_HSP_HS, PA_BLUETOOTH_PROFILE_HSP_AG, PA_BLUETOOTH_PROFILE_HFP_HF };
|
||||
+ int i;
|
||||
+ bool found_transport = false;
|
||||
+ void *state = NULL;
|
||||
+
|
||||
+ /* Find RFCOMM transport by checking if a HSP or HFP profile transport is available */
|
||||
+ while ((t = pa_hashmap_iterate(discovery->transports, &state, NULL))) {
|
||||
+ /* Skip non-connected transports */
|
||||
+ if (!t || t->state == PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED) {
|
||||
+ pa_log_debug("Profile %d disconnected or unavailable", i);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Break when an RFCOMM capable transport profile is available */
|
||||
+ for (i = 0; i < (sizeof profiles / sizeof *profiles); i++) {
|
||||
+ if (t->profile == profiles[i]) {
|
||||
+ trd = t->userdata;
|
||||
+ found_transport = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (found_transport)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Skip if RFCOMM channel is not available yet */
|
||||
+ if (!trd) {
|
||||
+ pa_log_info("RFCOMM not available yet, skipping notification");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return trd->rfcomm_fd;
|
||||
+}
|
||||
+
|
||||
+static pa_hook_result_t host_battery_level_changed_cb(pa_bluetooth_discovery *y, const pa_upower_backend *u, pa_bluetooth_backend *b) {
|
||||
+ int rfcomm_fd;
|
||||
+
|
||||
+ pa_assert(y);
|
||||
+ pa_assert(u);
|
||||
+ pa_assert(b);
|
||||
+
|
||||
+ /* Get RFCOMM channel if available */
|
||||
+ rfcomm_fd = get_rfcomm_fd (y);
|
||||
+ if (rfcomm_fd < 0)
|
||||
+ return PA_HOOK_OK;
|
||||
+
|
||||
+ /* Notify HF about AG battery level change over RFCOMM */
|
||||
+ if (b->cmer_indicator_reporting_enabled && (b->cind_enabled_indicators & (1 << CIND_BATT_CHG_INDICATOR))) {
|
||||
+ rfcomm_write_response(rfcomm_fd, "+CIEV: %d,%d", CIND_BATT_CHG_INDICATOR, u->battery_level);
|
||||
+ pa_log_debug("HG notified of AG's battery level change");
|
||||
+ /* Skip notification if indicator is disabled or event reporting is completely disabled */
|
||||
+ } else
|
||||
+ pa_log_debug("Battery level change indicator disabled, skipping notification");
|
||||
+
|
||||
+ return PA_HOOK_OK;
|
||||
+}
|
||||
+
|
||||
static void rfcomm_io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
|
||||
pa_bluetooth_transport *t = userdata;
|
||||
pa_bluetooth_discovery *discovery = t->device->discovery;
|
||||
@@ -1284,6 +1358,10 @@ pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_d
|
||||
pa_hook_connect(pa_bluetooth_discovery_hook(y, PA_BLUETOOTH_HOOK_ADAPTER_UUIDS_CHANGED), PA_HOOK_NORMAL,
|
||||
(pa_hook_cb_t) adapter_uuids_changed_cb, backend);
|
||||
|
||||
+ backend->host_battery_level_changed_slot =
|
||||
+ pa_hook_connect(pa_bluetooth_discovery_hook(y, PA_BLUETOOTH_HOOK_HOST_BATTERY_LEVEL_CHANGED), PA_HOOK_NORMAL,
|
||||
+ (pa_hook_cb_t) host_battery_level_changed_cb, backend);
|
||||
+
|
||||
if (!backend->enable_hsp_hs && !backend->enable_hfp_hf)
|
||||
pa_log_warn("Both HSP HS and HFP HF bluetooth profiles disabled in native backend. Native backend will not register for headset connections.");
|
||||
|
||||
@@ -1293,6 +1371,8 @@ pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_d
|
||||
if (backend->enable_shared_profiles)
|
||||
native_backend_apply_profile_registration_change(backend, true);
|
||||
|
||||
+ backend->upower = pa_upower_backend_new(c, y);
|
||||
+
|
||||
/* All CIND indicators are enabled by default until overriden by AT+BIA */
|
||||
for (i = 1; i < CIND_INDICATOR_MAX; i++)
|
||||
backend->cind_enabled_indicators |= (1 << i);
|
||||
@@ -1312,12 +1392,18 @@ void pa_bluetooth_native_backend_free(pa_bluetooth_backend *backend) {
|
||||
if (backend->adapter_uuids_changed_slot)
|
||||
pa_hook_slot_free(backend->adapter_uuids_changed_slot);
|
||||
|
||||
+ if (backend->host_battery_level_changed_slot)
|
||||
+ pa_hook_slot_free(backend->host_battery_level_changed_slot);
|
||||
+
|
||||
if (backend->enable_shared_profiles)
|
||||
native_backend_apply_profile_registration_change(backend, false);
|
||||
|
||||
if (backend->enable_hsp_hs)
|
||||
profile_done(backend, PA_BLUETOOTH_PROFILE_HSP_HS);
|
||||
|
||||
+ if (backend->upower)
|
||||
+ pa_upower_backend_free(backend->upower);
|
||||
+
|
||||
pa_dbus_connection_unref(backend->connection);
|
||||
|
||||
pa_xfree(backend);
|
||||
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
|
||||
index f899d9d0c..a24a0b823 100644
|
||||
--- a/src/modules/bluetooth/bluez5-util.h
|
||||
+++ b/src/modules/bluetooth/bluez5-util.h
|
||||
@@ -63,12 +63,14 @@ typedef struct pa_bluetooth_device pa_bluetooth_device;
|
||||
typedef struct pa_bluetooth_adapter pa_bluetooth_adapter;
|
||||
typedef struct pa_bluetooth_discovery pa_bluetooth_discovery;
|
||||
typedef struct pa_bluetooth_backend pa_bluetooth_backend;
|
||||
+typedef struct pa_upower_backend pa_upower_backend;
|
||||
|
||||
typedef enum pa_bluetooth_hook {
|
||||
PA_BLUETOOTH_HOOK_ADAPTER_UUIDS_CHANGED, /* Call data: pa_bluetooth_adapter */
|
||||
PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED, /* Call data: pa_bluetooth_device */
|
||||
PA_BLUETOOTH_HOOK_DEVICE_UNLINK, /* Call data: pa_bluetooth_device */
|
||||
PA_BLUETOOTH_HOOK_DEVICE_BATTERY_LEVEL_CHANGED, /* Call data: pa_bluetooth_device */
|
||||
+ PA_BLUETOOTH_HOOK_HOST_BATTERY_LEVEL_CHANGED, /* Call data: pa_upower_backend */
|
||||
PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED, /* Call data: pa_bluetooth_transport */
|
||||
PA_BLUETOOTH_HOOK_TRANSPORT_SOURCE_VOLUME_CHANGED, /* Call data: pa_bluetooth_transport */
|
||||
PA_BLUETOOTH_HOOK_TRANSPORT_SINK_VOLUME_CHANGED, /* Call data: pa_bluetooth_transport */
|
||||
--
|
||||
2.35.1
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1,40 +0,0 @@
|
|||
From 72b92267a8f906a3ecd10c571407802810e01bcc Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Wed, 13 Apr 2022 18:27:44 +0200
|
||||
Subject: [PATCH 06/26] bluetooth: only reply OK for supported AT cmds
|
||||
|
||||
PulseAudio should always be honest to Bluetooth devices even when audio is connected.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 9 +++------
|
||||
1 file changed, 3 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index a490d6efd..1fadb4b14 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -2,6 +2,7 @@
|
||||
This file is part of PulseAudio.
|
||||
|
||||
Copyright 2014 Wim Taymans <wim.taymans at gmail.com>
|
||||
+ Copyright 2021-2022 Dylan Van Assche <me at dylanvanassche.be>
|
||||
|
||||
PulseAudio is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as
|
||||
@@ -808,12 +809,8 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
return false;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * once we're fully connected, just reply OK to everything
|
||||
- * it will just be the headset sending the occasional status
|
||||
- * update, but we process only the ones we care about
|
||||
- */
|
||||
- return true;
|
||||
+ /* Unsupported commands return ERROR */
|
||||
+ return false
|
||||
}
|
||||
|
||||
static int get_rfcomm_fd (pa_bluetooth_discovery *discovery) {
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
From 81045feccb25b627c2c6cfc105c27b2599573fd2 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Wed, 13 Apr 2022 18:29:08 +0200
|
||||
Subject: [PATCH 07/26] bluetooth: Always reply to AT+CIND
|
||||
|
||||
Once the stateful negotiation is complete, still reply
|
||||
to AT+CIND? and AT+CIND=? since we will report actual data here
|
||||
such as cellular service status, roaming, signal, and battery level.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 22 ++++++++++++++++++----
|
||||
1 file changed, 18 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index 1fadb4b14..77792146a 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -686,7 +686,7 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
/* no state change */
|
||||
|
||||
return true;
|
||||
- } else if (c->state == 1 && pa_startswith(buf, "AT+CIND=?")) {
|
||||
+ } else if (c->state >= 1 && pa_startswith(buf, "AT+CIND=?")) {
|
||||
/* UPower backend available, declare support for more indicators */
|
||||
if (discovery->native_backend->upower) {
|
||||
rfcomm_write_response(fd, "+CIND: "
|
||||
@@ -700,15 +700,29 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
MANDATORY_CALL_INDICATORS ","
|
||||
"(\"service\",(0-1))");
|
||||
}
|
||||
- c->state = 2;
|
||||
+
|
||||
+ /*
|
||||
+ * Only change codec negotiation state when the first AT+CIND=? command is received
|
||||
+ * Bluetooth HFP 1.8 specification specifies that this AT command is issued 'at least once'.
|
||||
+ */
|
||||
+ if (c->state < 2)
|
||||
+ c->state = 2;
|
||||
|
||||
return true;
|
||||
- } else if (c->state == 2 && pa_startswith(buf, "AT+CIND?")) {
|
||||
+ } else if (c->state >= 2 && pa_startswith(buf, "AT+CIND?")) {
|
||||
if (discovery->native_backend->upower)
|
||||
rfcomm_write_response(fd, "+CIND: 0,0,0,0,%u", pa_upower_get_battery_level(discovery->native_backend->upower));
|
||||
else
|
||||
rfcomm_write_response(fd, "+CIND: 0,0,0,0");
|
||||
- c->state = 3;
|
||||
+
|
||||
+ /*
|
||||
+ * Only change codec negotiation state when the first AT+CIND? command is received.
|
||||
+ * The Bluetooth HFP 1.8 specification does not define how many times this command is issued.
|
||||
+ * Some HF devices issue this one multiple times breaking the codec negotiation stateful state,
|
||||
+ * so only update the state once.
|
||||
+ */
|
||||
+ if (c->state < 3)
|
||||
+ c->state = 3;
|
||||
|
||||
return true;
|
||||
} else if ((c->state == 2 || c->state == 3) && pa_startswith(buf, "AT+CMER=")) {
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
From ff2d7b76bf4878f47a2df1261219c9d9e14f8c9e Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Wed, 13 Apr 2022 19:56:41 +0200
|
||||
Subject: [PATCH 08/26] bluetooth: support AT+CMEE
|
||||
|
||||
AT+CMEE is now supported and extended error messages are returned
|
||||
when an ERROR occurs. By default, these error codes are disabled,
|
||||
the HF must enable them explicitely with AT+CMEE=1 (numeric mode).
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 71 +++++++++++++++++++++-----
|
||||
src/modules/bluetooth/bluez5-util.h | 6 +++
|
||||
2 files changed, 65 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index 77792146a..3110c5ef2 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -57,6 +57,7 @@ struct pa_bluetooth_backend {
|
||||
bool enable_hsp_hs;
|
||||
bool enable_hfp_hf;
|
||||
bool cmer_indicator_reporting_enabled;
|
||||
+ bool cmee_extended_error_reporting_enabled;
|
||||
uint32_t cind_enabled_indicators;
|
||||
|
||||
PA_LLIST_HEAD(pa_dbus_pending, pending);
|
||||
@@ -125,7 +126,7 @@ typedef enum pa_bluetooth_ag_to_hf_indicators {
|
||||
/* gateway features we support, which is as little as we can get away with */
|
||||
static uint32_t hfp_features =
|
||||
/* HFP 1.6 requires this */
|
||||
- (1 << HFP_AG_ESTATUS ) | (1 << HFP_AG_CODECS) | (1 << HFP_AG_INDICATORS);
|
||||
+ (1 << HFP_AG_ESTATUS ) | (1 << HFP_AG_CODECS) | (1 << HFP_AG_INDICATORS) | (1 << HFP_AG_EERR);
|
||||
|
||||
#define HSP_AG_PROFILE "/Profile/HSPAGProfile"
|
||||
#define HFP_AG_PROFILE "/Profile/HFPAGProfile"
|
||||
@@ -256,6 +257,14 @@ static void rfcomm_write_response(int fd, const char *fmt, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
+/* Send Extended Error messages if enabled */
|
||||
+static void rfcomm_write_error(pa_bluetooth_backend *b, int fd, unsigned int error) {
|
||||
+ if (b->cmee_extended_error_reporting_enabled)
|
||||
+ rfcomm_write_response(fd, "+CME ERROR: %d", error);
|
||||
+ else
|
||||
+ rfcomm_write_response(fd, "ERROR");
|
||||
+}
|
||||
+
|
||||
static int sco_setsockopt_enable_bt_voice(pa_bluetooth_transport *t, int fd) {
|
||||
/* the mSBC codec requires a special transparent eSCO connection */
|
||||
struct bt_voice voice;
|
||||
@@ -621,6 +630,30 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
size_t len;
|
||||
const char *state;
|
||||
|
||||
+ /* Extended error reporting. Described in Bluetooth HFP 1.8 spec. */
|
||||
+ if (sscanf(buf, "AT+CMEE=%d", &val) == 1) {
|
||||
+ switch(val) {
|
||||
+ /* Disable extended error reporting */
|
||||
+ case 0:
|
||||
+ discovery->native_backend->cmee_extended_error_reporting_enabled = false;
|
||||
+ return true;
|
||||
+ /* Enable extend error reporting in numeric mode */
|
||||
+ case 1:
|
||||
+ discovery->native_backend->cmee_extended_error_reporting_enabled = true;
|
||||
+ return true;
|
||||
+ /* Enable extend error reporting in verbose mode */
|
||||
+ case 2:
|
||||
+ pa_log_warn("Extended Error Reporting verbose mode is unsupported by Bluetooth HFP 1.8");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_OPERATION_NOT_SUPPORTED);
|
||||
+ return false;
|
||||
+ default:
|
||||
+ pa_log_warn("Unknown AT+CMEE value: %d", val);
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
||||
+ return false;
|
||||
+ }
|
||||
+ pa_assert_not_reached();
|
||||
+ }
|
||||
+
|
||||
/* first-time initialize selected codec to CVSD */
|
||||
if (c->selected_codec == 0)
|
||||
c->selected_codec = 1;
|
||||
@@ -655,7 +688,7 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
discovery->native_backend->cind_enabled_indicators &= ~(1 << indicator);
|
||||
else {
|
||||
pa_log_error("Unable to parse indicator of AT+BIA command: %s", buf);
|
||||
- rfcomm_write_response(fd, "ERROR");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -741,7 +774,7 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
}
|
||||
else {
|
||||
pa_log_error("Unable to parse AT+CMER command: %s", buf);
|
||||
- rfcomm_write_response(fd, "ERROR");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -767,7 +800,7 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
pa_bluetooth_transport_reconfigure(t, pa_bluetooth_get_hf_codec("mSBC"), sco_transport_write, sco_setsockopt_enable_bt_voice);
|
||||
} else {
|
||||
pa_assert_fp(val != 1 && val != 2);
|
||||
- rfcomm_write_response(fd, "ERROR");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -798,14 +831,14 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
pa_log_notice("Battery Level: %d%%", val);
|
||||
if (val < 0 || val > 100) {
|
||||
pa_log_error("Battery HF indicator %d out of [0, 100] range", val);
|
||||
- rfcomm_write_response(fd, "ERROR");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
||||
return false;
|
||||
}
|
||||
pa_bluetooth_device_report_battery_level(t->device, val, "HFP 1.7 HF indicator");
|
||||
break;
|
||||
default:
|
||||
pa_log_error("Unknown HF indicator %u", indicator);
|
||||
- rfcomm_write_response(fd, "ERROR");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_OPERATION_NOT_SUPPORTED);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -819,12 +852,23 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
if (c->state != 5) {
|
||||
pa_log_error("HFP negotiation failed in state %d with inbound %s\n",
|
||||
c->state, buf);
|
||||
- rfcomm_write_response(fd, "ERROR");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
||||
return false;
|
||||
}
|
||||
|
||||
- /* Unsupported commands return ERROR */
|
||||
- return false
|
||||
+ /*
|
||||
+ * Unsupported commands return ERROR.
|
||||
+ * Unsupported AT commands from HFP 1.8:
|
||||
+ * - AT+BINP
|
||||
+ * - AT+BLDN
|
||||
+ * - ATD>
|
||||
+ * - AT+BVRA
|
||||
+ * - AT+BTRH
|
||||
+ * - AT+CHLD
|
||||
+ * - AT+CCWA
|
||||
+ */
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_OPERATION_NOT_SUPPORTED);
|
||||
+ return false;
|
||||
}
|
||||
|
||||
static int get_rfcomm_fd (pa_bluetooth_discovery *discovery) {
|
||||
@@ -996,12 +1040,13 @@ static void rfcomm_io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_i
|
||||
break;
|
||||
}
|
||||
}
|
||||
- if (!do_reply)
|
||||
- rfcomm_write_response(fd, "ERROR");
|
||||
+ if (!do_reply) {
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
||||
+ }
|
||||
} else if (t->config) { /* t->config is only non-null for hfp profile */
|
||||
do_reply = hfp_rfcomm_handle(fd, t, buf);
|
||||
} else {
|
||||
- rfcomm_write_response(fd, "ERROR");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
||||
do_reply = false;
|
||||
}
|
||||
|
||||
@@ -1391,6 +1436,8 @@ pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_d
|
||||
/* While all CIND indicators are enabled, event reporting is not enabled by default */
|
||||
backend->cmer_indicator_reporting_enabled = false;
|
||||
|
||||
+ /* CMEE is disabled by default */
|
||||
+ backend->cmee_extended_error_reporting_enabled = false;
|
||||
|
||||
return backend;
|
||||
}
|
||||
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
|
||||
index f69176425..4cc5c2882 100644
|
||||
--- a/src/modules/bluetooth/bluez5-util.h
|
||||
+++ b/src/modules/bluetooth/bluez5-util.h
|
||||
@@ -211,6 +211,12 @@ struct pa_bluetooth_adapter {
|
||||
bool battery_provider_registered;
|
||||
};
|
||||
|
||||
+/* extended error reporting values, described in Bluetooth HFP 1.8 spec */
|
||||
+typedef enum pa_bluetooth_cmee {
|
||||
+ CMEE_AG_FAILURE = 0,
|
||||
+ CMEE_OPERATION_NOT_SUPPORTED = 4,
|
||||
+} pa_bluetooth_cmee_t;
|
||||
+
|
||||
#ifdef HAVE_BLUEZ_5_OFONO_HEADSET
|
||||
pa_bluetooth_backend *pa_bluetooth_ofono_backend_new(pa_core *c, pa_bluetooth_discovery *y);
|
||||
void pa_bluetooth_ofono_backend_free(pa_bluetooth_backend *b);
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
From 0dc5b589220e830ab18ddbcf90f2cfbe1c4927f7 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Wed, 13 Apr 2022 20:25:47 +0200
|
||||
Subject: [PATCH 09/26] bluetooth: support AT+NREC
|
||||
|
||||
AT+NREC=0 disables Noise Reduction and Echo Canceling in the AG.
|
||||
Bluetooth HFP 1.8 only supports the disable operation, so return
|
||||
an CME ERROR extended error code if another value is send by the HF.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 7 +++++++
|
||||
src/modules/bluetooth/bluez5-util.h | 3 ++-
|
||||
2 files changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index 3110c5ef2..394c2a4da 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -652,6 +652,13 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
return false;
|
||||
}
|
||||
pa_assert_not_reached();
|
||||
+ } else if (sscanf(buf, "AT+NREC=%d", &val) == 1) {
|
||||
+ if (val == 0)
|
||||
+ return true;
|
||||
+
|
||||
+ /* Noise Redction and Echo Canceling can only have value '0' (disable) following Bluetooth HFP 1.8 */
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_OPERATION_NOT_ALLOWED);
|
||||
+ return false;
|
||||
}
|
||||
|
||||
/* first-time initialize selected codec to CVSD */
|
||||
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
|
||||
index 4cc5c2882..fa26a8361 100644
|
||||
--- a/src/modules/bluetooth/bluez5-util.h
|
||||
+++ b/src/modules/bluetooth/bluez5-util.h
|
||||
@@ -214,7 +214,8 @@ struct pa_bluetooth_adapter {
|
||||
/* extended error reporting values, described in Bluetooth HFP 1.8 spec */
|
||||
typedef enum pa_bluetooth_cmee {
|
||||
CMEE_AG_FAILURE = 0,
|
||||
- CMEE_OPERATION_NOT_SUPPORTED = 4,
|
||||
+ CMEE_OPERATION_NOT_ALLOWED = 3,
|
||||
+ CMEE_OPERATION_NOT_SUPPORTED = 4
|
||||
} pa_bluetooth_cmee_t;
|
||||
|
||||
#ifdef HAVE_BLUEZ_5_OFONO_HEADSET
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
From 79d8cf24785fc52a3d0cee48590143fb409201b8 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Thu, 14 Apr 2022 19:15:34 +0200
|
||||
Subject: [PATCH 10/26] bluetooth: support AT+BCC
|
||||
|
||||
HFs send AT+BCC to (re)start codec negotiations.
|
||||
Support this command by (re)setting the codec negotiations state and
|
||||
reply OK.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index 394c2a4da..89a174f9a 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -666,7 +666,12 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
c->selected_codec = 1;
|
||||
|
||||
/* stateful negotiation */
|
||||
- if (c->state == 0 && sscanf(buf, "AT+BRSF=%d", &val) == 1) {
|
||||
+ if (strstr(buf, "AT+BCC")) {
|
||||
+ pa_log_debug("HF asked to start codec negotiations");
|
||||
+ c->state = 0;
|
||||
+ return true;
|
||||
+ }
|
||||
+ else if (c->state == 0 && sscanf(buf, "AT+BRSF=%d", &val) == 1) {
|
||||
c->capabilities = val;
|
||||
pa_log_info("HFP capabilities returns 0x%x", val);
|
||||
rfcomm_write_response(fd, "+BRSF: %d", hfp_features);
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
From ccac2886c516aa0ac2e76406b782de0abc700e92 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Thu, 14 Apr 2022 19:47:46 +0200
|
||||
Subject: [PATCH 11/26] bluetooth: support AT+COPS
|
||||
|
||||
AT+COPS=3,X sets the operator name format and AT+COPS? returns
|
||||
the current network operator name. Supports this command when
|
||||
ModemManager is available to provide this information.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 72 +++++++++++++++++++++++++-
|
||||
src/modules/bluetooth/bluez5-util.h | 11 +++-
|
||||
2 files changed, 81 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index 89a174f9a..c0c14acf3 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "bluez5-util.h"
|
||||
#include "bt-codec-msbc.h"
|
||||
#include "upower.h"
|
||||
+#include "modemmanager.h"
|
||||
|
||||
#define MANDATORY_CALL_INDICATORS \
|
||||
"(\"call\",(0-1))," \
|
||||
@@ -53,12 +54,14 @@ struct pa_bluetooth_backend {
|
||||
pa_hook_slot *adapter_uuids_changed_slot;
|
||||
pa_hook_slot *host_battery_level_changed_slot;
|
||||
pa_upower_backend *upower;
|
||||
+ pa_modemmanager_backend *modemmanager;
|
||||
bool enable_shared_profiles;
|
||||
bool enable_hsp_hs;
|
||||
bool enable_hfp_hf;
|
||||
bool cmer_indicator_reporting_enabled;
|
||||
bool cmee_extended_error_reporting_enabled;
|
||||
uint32_t cind_enabled_indicators;
|
||||
+ pa_bluetooth_cops_t cops_format;
|
||||
|
||||
PA_LLIST_HEAD(pa_dbus_pending, pending);
|
||||
};
|
||||
@@ -624,7 +627,7 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
{
|
||||
struct pa_bluetooth_discovery *discovery = t->device->discovery;
|
||||
struct hfp_config *c = t->config;
|
||||
- int indicator, mode, val;
|
||||
+ int indicator, mode, val, val2;
|
||||
char str[5];
|
||||
const char *r;
|
||||
size_t len;
|
||||
@@ -659,6 +662,68 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
/* Noise Redction and Echo Canceling can only have value '0' (disable) following Bluetooth HFP 1.8 */
|
||||
rfcomm_write_error(discovery->native_backend, fd, CMEE_OPERATION_NOT_ALLOWED);
|
||||
return false;
|
||||
+ } else if (sscanf(buf, "AT+COPS=%d,%d", &val, &val2) == 2) {
|
||||
+ /* Return error if ModemManager is unavailable */
|
||||
+ if (!discovery->native_backend->modemmanager || !pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("ModemManager backend unavailable, cannot set AT+COPS format");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Only AT+COPS=3,X is allowed by Bluetooth HFP 1.8 */
|
||||
+ if (val != 3)
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_OPERATION_NOT_ALLOWED);
|
||||
+
|
||||
+ /* Set AT+COPS format */
|
||||
+ if (val2 == 0) {
|
||||
+ discovery->native_backend->cops_format = COPS_LONG_FORMAT;
|
||||
+ return true;
|
||||
+ } else if (val2 == 2) {
|
||||
+ discovery->native_backend->cops_format = COPS_NUMERIC_FORMAT;
|
||||
+ return true;
|
||||
+ } else {
|
||||
+ discovery->native_backend->cops_format = COPS_UNKNOWN_FORMAT;
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_OPERATION_NOT_ALLOWED);
|
||||
+ return false;
|
||||
+ }
|
||||
+ } else if (strstr(buf, "AT+COPS?")) {
|
||||
+ /* Return error if ModemManager is unavailable */
|
||||
+ if (!discovery->native_backend->modemmanager || !pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("ModemManager backend unavailable, cannot answer AT+COPS?");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
+ return false;
|
||||
+ } else if (!pa_modemmanager_has_service(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("No network service, cannot answer AT+COPS?");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_NETWORK_SERVICE);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ switch(discovery->native_backend->cops_format) {
|
||||
+ case COPS_LONG_FORMAT: {
|
||||
+ char *operator_name = pa_modemmanager_get_operator_name(discovery->native_backend->modemmanager);
|
||||
+ if (operator_name) {
|
||||
+ rfcomm_write_response(fd, "+COPS: 0,0,\"%s\"", operator_name);
|
||||
+ return true;
|
||||
+ }
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_NETWORK_SERVICE);
|
||||
+ return false;
|
||||
+ }
|
||||
+ case COPS_NUMERIC_FORMAT: {
|
||||
+ char *operator_code = pa_modemmanager_get_operator_code(discovery->native_backend->modemmanager);
|
||||
+ if (operator_code) {
|
||||
+ rfcomm_write_response(fd, "+COPS: 2,0,\"%s\"", operator_code);
|
||||
+ return true;
|
||||
+ }
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_NETWORK_SERVICE);
|
||||
+ return false;
|
||||
+ }
|
||||
+ case COPS_UNKNOWN_FORMAT: {
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
||||
+ return false;
|
||||
+ }
|
||||
+ default:
|
||||
+ pa_assert_not_reached();
|
||||
+ }
|
||||
}
|
||||
|
||||
/* first-time initialize selected codec to CVSD */
|
||||
@@ -1441,6 +1506,8 @@ pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_d
|
||||
|
||||
backend->upower = pa_upower_backend_new(c, y);
|
||||
|
||||
+ backend->modemmanager = pa_modemmanager_backend_new(c, y);
|
||||
+
|
||||
/* All CIND indicators are enabled by default until overriden by AT+BIA */
|
||||
for (i = 1; i < CIND_INDICATOR_MAX; i++)
|
||||
backend->cind_enabled_indicators |= (1 << i);
|
||||
@@ -1473,6 +1540,9 @@ void pa_bluetooth_native_backend_free(pa_bluetooth_backend *backend) {
|
||||
|
||||
if (backend->upower)
|
||||
pa_upower_backend_free(backend->upower);
|
||||
+
|
||||
+ if (backend->modemmanager)
|
||||
+ pa_modemmanager_backend_free(backend->modemmanager);
|
||||
|
||||
pa_dbus_connection_unref(backend->connection);
|
||||
|
||||
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
|
||||
index fa26a8361..9ac9880a8 100644
|
||||
--- a/src/modules/bluetooth/bluez5-util.h
|
||||
+++ b/src/modules/bluetooth/bluez5-util.h
|
||||
@@ -214,10 +214,19 @@ struct pa_bluetooth_adapter {
|
||||
/* extended error reporting values, described in Bluetooth HFP 1.8 spec */
|
||||
typedef enum pa_bluetooth_cmee {
|
||||
CMEE_AG_FAILURE = 0,
|
||||
+ CMEE_NO_CONNECTION_TO_PHONE = 1,
|
||||
CMEE_OPERATION_NOT_ALLOWED = 3,
|
||||
- CMEE_OPERATION_NOT_SUPPORTED = 4
|
||||
+ CMEE_OPERATION_NOT_SUPPORTED = 4,
|
||||
+ CMEE_NO_NETWORK_SERVICE = 30
|
||||
} pa_bluetooth_cmee_t;
|
||||
|
||||
+/* AT+COPS format, described in Bluetooth HFP 1.8 spec */
|
||||
+typedef enum pa_bluetooth_cops {
|
||||
+ COPS_LONG_FORMAT = 0,
|
||||
+ COPS_NUMERIC_FORMAT = 1,
|
||||
+ COPS_UNKNOWN_FORMAT = 2
|
||||
+} pa_bluetooth_cops_t;
|
||||
+
|
||||
#ifdef HAVE_BLUEZ_5_OFONO_HEADSET
|
||||
pa_bluetooth_backend *pa_bluetooth_ofono_backend_new(pa_core *c, pa_bluetooth_discovery *y);
|
||||
void pa_bluetooth_ofono_backend_free(pa_bluetooth_backend *b);
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
From 739ca09cc36553703d2b24ba99b64f8641fcf987 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Thu, 14 Apr 2022 20:16:24 +0200
|
||||
Subject: [PATCH 12/26] bluetooth: support AT+CNUM
|
||||
|
||||
AT+CNUM returns the phone number of the subscriber.
|
||||
Supports this AT command when ModemManager is available.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 25 +++++++++++++++++++++++++
|
||||
src/modules/bluetooth/bluez5-util.h | 6 ++++++
|
||||
2 files changed, 31 insertions(+)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index c0c14acf3..19ca497d5 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -724,6 +724,31 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
default:
|
||||
pa_assert_not_reached();
|
||||
}
|
||||
+ } else if (strstr(buf, "AT+CNUM")) {
|
||||
+ char *number;
|
||||
+ unsigned int type;
|
||||
+
|
||||
+ /* Return error if ModemManager is unavailable */
|
||||
+ if (!discovery->native_backend->modemmanager || !pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("ModemManager backend unavailable, cannot answer AT+CNUM");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ number = pa_modemmanager_get_own_number(discovery->native_backend->modemmanager);
|
||||
+ if (!number) {
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* International numbers start with '+' */
|
||||
+ if (strncmp("+", number, 1) == 0)
|
||||
+ type = CLIP_INTERNATIONAL_NUMBER;
|
||||
+ else
|
||||
+ type = CLIP_NATIONAL_NUMBER;
|
||||
+
|
||||
+ rfcomm_write_response(fd, "+CNUM: ,\"%s\",%d,,4", number, type);
|
||||
+ return true;
|
||||
}
|
||||
|
||||
/* first-time initialize selected codec to CVSD */
|
||||
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
|
||||
index 9ac9880a8..638a793b7 100644
|
||||
--- a/src/modules/bluetooth/bluez5-util.h
|
||||
+++ b/src/modules/bluetooth/bluez5-util.h
|
||||
@@ -227,6 +227,12 @@ typedef enum pa_bluetooth_cops {
|
||||
COPS_UNKNOWN_FORMAT = 2
|
||||
} pa_bluetooth_cops_t;
|
||||
|
||||
+/* CLIP number formats, described in Bluetooth HFP 1.8 spec */
|
||||
+typedef enum pa_bluetooth_clip {
|
||||
+ CLIP_INTERNATIONAL_NUMBER = 145,
|
||||
+ CLIP_NATIONAL_NUMBER = 129
|
||||
+} pa_bluetooth_clip_t;
|
||||
+
|
||||
#ifdef HAVE_BLUEZ_5_OFONO_HEADSET
|
||||
pa_bluetooth_backend *pa_bluetooth_ofono_backend_new(pa_core *c, pa_bluetooth_discovery *y);
|
||||
void pa_bluetooth_ofono_backend_free(pa_bluetooth_backend *b);
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
From fafe1fc716a9482e2ea883fb79edf90a7c89d33d Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Thu, 14 Apr 2022 20:43:42 +0200
|
||||
Subject: [PATCH 13/26] bluetooth: support more AT+CIND? indicators
|
||||
|
||||
If ModemManager is available, report service status, roaming status and
|
||||
signal strength as well when an AT+CIND? command is received.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 24 +++++++++++++++++-------
|
||||
1 file changed, 17 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index 19ca497d5..fcbae5540 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -123,7 +123,9 @@ typedef enum pa_bluetooth_ag_to_hf_indicators {
|
||||
CIND_CALL_HELD_INDICATOR = 3,
|
||||
CIND_SERVICE_INDICATOR = 4,
|
||||
CIND_BATT_CHG_INDICATOR = 5,
|
||||
- CIND_INDICATOR_MAX = 6
|
||||
+ CIND_ROAMING_INDICATOR = 6,
|
||||
+ CIND_SIGNAL_STRENGTH_INDICATOR = 7,
|
||||
+ CIND_INDICATOR_MAX = 8
|
||||
} pa_bluetooth_ag_to_hf_indicators_t;
|
||||
|
||||
/* gateway features we support, which is as little as we can get away with */
|
||||
@@ -822,14 +824,16 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
|
||||
return true;
|
||||
} else if (c->state >= 1 && pa_startswith(buf, "AT+CIND=?")) {
|
||||
- /* UPower backend available, declare support for more indicators */
|
||||
- if (discovery->native_backend->upower) {
|
||||
+ /* UPower and ModemManager backends available, declare support for more indicators */
|
||||
+ if (discovery->native_backend->upower && discovery->native_backend->modemmanager && pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
rfcomm_write_response(fd, "+CIND: "
|
||||
MANDATORY_CALL_INDICATORS ","
|
||||
"(\"service\",(0-1)),"
|
||||
- "(\"battchg\",(0-5))");
|
||||
+ "(\"battchg\",(0-5)),"
|
||||
+ "(\"roam\",(0-1)),"
|
||||
+ "(\"signal\",(0-5))");
|
||||
|
||||
- /* Minimal indicators supported without any additional backend */
|
||||
+ /* Minimal indicators supported without any additional backends */
|
||||
} else {
|
||||
rfcomm_write_response(fd, "+CIND: "
|
||||
MANDATORY_CALL_INDICATORS ","
|
||||
@@ -845,8 +849,14 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
|
||||
return true;
|
||||
} else if (c->state >= 2 && pa_startswith(buf, "AT+CIND?")) {
|
||||
- if (discovery->native_backend->upower)
|
||||
- rfcomm_write_response(fd, "+CIND: 0,0,0,0,%u", pa_upower_get_battery_level(discovery->native_backend->upower));
|
||||
+ if (discovery->native_backend->upower && discovery->native_backend->modemmanager && pa_modemmanager_has_modem(discovery->native_backend->modemmanager))
|
||||
+ rfcomm_write_response(fd, "+CIND: %u,%u,0,%u,%u,%u,%u",
|
||||
+ discovery->native_backend->cind_call_indicator,
|
||||
+ discovery->native_backend->cind_call_setup_indicator,
|
||||
+ pa_modemmanager_has_service(discovery->native_backend->modemmanager),
|
||||
+ pa_upower_get_battery_level(discovery->native_backend->upower),
|
||||
+ pa_modemmanager_is_roaming(discovery->native_backend->modemmanager),
|
||||
+ pa_modemmanager_get_signal_strength(discovery->native_backend->modemmanager));
|
||||
else
|
||||
rfcomm_write_response(fd, "+CIND: 0,0,0,0");
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
From 07adf1b246ba1db7b4c5bb9555f1d392b856c049 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Thu, 14 Apr 2022 20:52:36 +0200
|
||||
Subject: [PATCH 14/26] bluetooth: support AT+CLIP
|
||||
|
||||
Enable or disable Call Line Indication reporting (+CLIP) when
|
||||
a call is incoming to display the number that is calling on the HF's
|
||||
screen.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 20 ++++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index fcbae5540..1eaa36b4a 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -62,6 +62,7 @@ struct pa_bluetooth_backend {
|
||||
bool cmee_extended_error_reporting_enabled;
|
||||
uint32_t cind_enabled_indicators;
|
||||
pa_bluetooth_cops_t cops_format;
|
||||
+ bool clip_call_line_reporting_enabled;
|
||||
|
||||
PA_LLIST_HEAD(pa_dbus_pending, pending);
|
||||
};
|
||||
@@ -751,6 +752,22 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
|
||||
rfcomm_write_response(fd, "+CNUM: ,\"%s\",%d,,4", number, type);
|
||||
return true;
|
||||
+ } else if (sscanf(buf, "AT+CLIP=%d", &val) == 1) {
|
||||
+ switch(val) {
|
||||
+ /* Disable call line reporting */
|
||||
+ case 0:
|
||||
+ discovery->native_backend->clip_call_line_reporting_enabled = false;
|
||||
+ return true;
|
||||
+ /* Enable call line reporting */
|
||||
+ case 1:
|
||||
+ discovery->native_backend->clip_call_line_reporting_enabled = true;
|
||||
+ return true;
|
||||
+ default:
|
||||
+ pa_log_warn("Unknown AT+CLIP value: %d", val);
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
||||
+ return false;
|
||||
+ }
|
||||
+ pa_assert_not_reached();
|
||||
}
|
||||
|
||||
/* first-time initialize selected codec to CVSD */
|
||||
@@ -1553,6 +1570,9 @@ pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_d
|
||||
/* CMEE is disabled by default */
|
||||
backend->cmee_extended_error_reporting_enabled = false;
|
||||
|
||||
+ /* CLIP is disabled by default */
|
||||
+ backend->clip_call_line_reporting_enabled = false;
|
||||
+
|
||||
return backend;
|
||||
}
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
From d10422fafd9eececfa6755617c41b05f895e5a5b Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Thu, 14 Apr 2022 21:03:37 +0200
|
||||
Subject: [PATCH 15/26] bluetooth: support AT+CREG?
|
||||
|
||||
AT+CREG? is not officialy supported by the Bluetooth HFP 1.8 spec,
|
||||
but some car multimedia systems use it. AT+CREG? reports if the phone
|
||||
has network available or not with a +CREG response.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 22 ++++++++++++++++++++++
|
||||
1 file changed, 22 insertions(+)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index 1eaa36b4a..2fa769d07 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -770,6 +770,28 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
pa_assert_not_reached();
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * Out-of-spec Bluetooth HFP 1.8 AT commands.
|
||||
+ * Some car multimedia systems implement the HFP spec,
|
||||
+ * but also use out-of-spec AT commands which are normally supported
|
||||
+ * by any 3GPP compliant modem such as:
|
||||
+ * - AT+CREG?: Get service status
|
||||
+ * - AT+CGMM: Get modem model
|
||||
+ * - AT+CGMI: Get modem manufacturer
|
||||
+ * - AT+CGMR: Get modem revision
|
||||
+ * - AT+CGSN: Get modem IMEI
|
||||
+ *
|
||||
+ * These AT commands are additionally supported if ModemManager is available.
|
||||
+ */
|
||||
+ if (strstr(buf, "AT+CREG?")) {
|
||||
+ if (discovery->native_backend->modemmanager && pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
+ rfcomm_write_response(fd, "+CREG: 0,%d", pa_modemmanager_has_service(discovery->native_backend->modemmanager));
|
||||
+ return true;
|
||||
+ }
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
/* first-time initialize selected codec to CVSD */
|
||||
if (c->selected_codec == 0)
|
||||
c->selected_codec = 1;
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
From ee52128fbb8bc953c43b8c53763443c715fa64c8 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Fri, 15 Apr 2022 07:29:49 +0200
|
||||
Subject: [PATCH 16/26] bluetooth: support AT+CGMM
|
||||
|
||||
Return the modem model if ModemManager is available when the HF
|
||||
sends an out-of-spec AT+CGMM command.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index 2fa769d07..2c39a090c 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -790,6 +790,13 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
}
|
||||
rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
return false;
|
||||
+ } else if (strstr(buf, "AT+CGMM") && pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
+ if (discovery->native_backend->modemmanager) {
|
||||
+ rfcomm_write_response(fd, "%s", pa_modemmanager_get_modem_model(discovery->native_backend->modemmanager));
|
||||
+ return true;
|
||||
+ }
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
+ return false;
|
||||
}
|
||||
|
||||
/* first-time initialize selected codec to CVSD */
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
From 6e851563dbe4e90a37b0f8fef1604395acba47b4 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Fri, 15 Apr 2022 07:31:43 +0200
|
||||
Subject: [PATCH 17/26] bluetooth: support AT+CGMI
|
||||
|
||||
Return the modem manufacturer if ModemManager is available.
|
||||
AT+CGMI is an out-of-spec AT command for Bluetooth HFP, but car
|
||||
multimedia units use it since it is a standard 3GPP command.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index 2c39a090c..3099b13fc 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -797,6 +797,13 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
}
|
||||
rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
return false;
|
||||
+ } else if (strstr(buf, "AT+CGMI") && pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
+ if (discovery->native_backend->modemmanager) {
|
||||
+ rfcomm_write_response(fd, "%s", pa_modemmanager_get_modem_manufacturer(discovery->native_backend->modemmanager));
|
||||
+ return true;
|
||||
+ }
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
+ return false;
|
||||
}
|
||||
|
||||
/* first-time initialize selected codec to CVSD */
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
From 5fd316c23c3051be2394c16bf97ee189fc07ce23 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Fri, 15 Apr 2022 07:33:19 +0200
|
||||
Subject: [PATCH 18/26] bluetooth: support AT+CGMR
|
||||
|
||||
Return the modem revision when HF sends an out-of-spec AT+CGMR
|
||||
command. This is a 3GPP standardized command so lets support it.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index 3099b13fc..cf016a282 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -804,6 +804,13 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
}
|
||||
rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
return false;
|
||||
+ } else if (strstr(buf, "AT+CGMR")) {
|
||||
+ if (discovery->native_backend->modemmanager && pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
+ rfcomm_write_response(fd, "%s", pa_modemmanager_get_modem_revision(discovery->native_backend->modemmanager));
|
||||
+ return true;
|
||||
+ }
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
+ return false;
|
||||
}
|
||||
|
||||
/* first-time initialize selected codec to CVSD */
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
From f39e071a558a9b3a301028c7f3506f024d60ceea Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Fri, 15 Apr 2022 07:35:11 +0200
|
||||
Subject: [PATCH 19/26] bluetooth: support AT+CGSN
|
||||
|
||||
Return the modem's IMEI number when car multimedia systems (HF)
|
||||
send an AT+CGSN 3GPP AT command, even though it is not supported by the
|
||||
Bluetooth HFP 1.8 spec.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index cf016a282..fec24a57b 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -811,6 +811,13 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
}
|
||||
rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
return false;
|
||||
+ } else if (strstr(buf, "AT+CGSN") && pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
+ if (discovery->native_backend->modemmanager) {
|
||||
+ rfcomm_write_response(fd, "%s", pa_modemmanager_get_modem_imei(discovery->native_backend->modemmanager));
|
||||
+ return true;
|
||||
+ }
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
+ return false;
|
||||
}
|
||||
|
||||
/* first-time initialize selected codec to CVSD */
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
From 320d906f8e64b1713dc09c8e95316c4de515f70f Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Fri, 15 Apr 2022 08:18:48 +0200
|
||||
Subject: [PATCH 20/26] bluetooth: support AT+CLCC
|
||||
|
||||
Report ongoing calls when the HF sends an AT+CLCC command.
|
||||
Currently, only one ongoing call is supported, three-way calling is not
|
||||
implemented. Any additional calls are ignored.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 61 ++++++++++++++++++++++++++
|
||||
src/modules/bluetooth/bluez5-util.h | 9 ++++
|
||||
2 files changed, 70 insertions(+)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index fec24a57b..faefed9bd 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -768,6 +768,67 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
return false;
|
||||
}
|
||||
pa_assert_not_reached();
|
||||
+ } else if (strstr(buf, "AT+CLCC")) {
|
||||
+ pa_hashmap *calls;
|
||||
+ call_status_t *call;
|
||||
+ unsigned int type;
|
||||
+ unsigned int clcc_status;
|
||||
+
|
||||
+ /* Return error if ModemManager is unavailable */
|
||||
+ if (!discovery->native_backend->modemmanager || !pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("ModemManager backend unavailable, cannot answer AT+CLCC");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
+ return false;
|
||||
+ } else if (!pa_modemmanager_has_service(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("No network service, cannot answer AT+CLCC");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_NETWORK_SERVICE);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ calls = pa_modemmanager_get_calls(discovery->native_backend->modemmanager);
|
||||
+
|
||||
+ /* Check if we have any ongoing calls, if not return OK */
|
||||
+ if (pa_hashmap_isempty(calls))
|
||||
+ return true;
|
||||
+
|
||||
+ /* FIXME: support three-way calling */
|
||||
+ call = pa_hashmap_first(calls);
|
||||
+
|
||||
+ /* Map call status to CLCC status numbers */
|
||||
+ if (call->status == PA_MODEMMANAGER_CALL_STATE_INVALID) {
|
||||
+ pa_log_warn("Unable to answer AT+CLCC, call state is unknown");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
||||
+ return false;
|
||||
+ } else if (call->is_incoming && call->status == PA_MODEMMANAGER_CALL_STATE_RINGING) {
|
||||
+ clcc_status = CLCC_INCOMING;
|
||||
+ } else if (!call->is_incoming && call->status == PA_MODEMMANAGER_CALL_STATE_RINGING) {
|
||||
+ clcc_status = CLCC_ALERTING;
|
||||
+ } else if (!call->is_incoming && call->status == PA_MODEMMANAGER_CALL_STATE_DIALING) {
|
||||
+ clcc_status = CLCC_DIALING;
|
||||
+ } else if (call->status == PA_MODEMMANAGER_CALL_STATE_ACTIVE) {
|
||||
+ clcc_status = CLCC_ACTIVE;
|
||||
+ } else if (call->status == PA_MODEMMANAGER_CALL_STATE_TERMINATED) {
|
||||
+ pa_log_debug("Call terminated already, do not report it.");
|
||||
+ return true;
|
||||
+ /* FIXME: support three-way calling */
|
||||
+ } else {
|
||||
+ pa_assert_not_reached();
|
||||
+ }
|
||||
+
|
||||
+ /* Check if call has a number, if not drop it since number and type are optional */
|
||||
+ if (!call->number) {
|
||||
+ rfcomm_write_response(fd, "+CLCC: %d,%d,%d,%d,%d", 1, call->is_incoming, clcc_status, 0, 0);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ /* International numbers start with '+' */
|
||||
+ if (strncmp("+", call->number, 1) == 0)
|
||||
+ type = CLIP_INTERNATIONAL_NUMBER;
|
||||
+ else
|
||||
+ type = CLIP_NATIONAL_NUMBER;
|
||||
+
|
||||
+ rfcomm_write_response(fd, "+CLCC: %d,%d,%d,%d,%d,\"%s\",%d", 1, call->is_incoming, clcc_status, 0, 0, call->number, type);
|
||||
+ return true;
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
|
||||
index 638a793b7..fb88f00e2 100644
|
||||
--- a/src/modules/bluetooth/bluez5-util.h
|
||||
+++ b/src/modules/bluetooth/bluez5-util.h
|
||||
@@ -233,6 +233,15 @@ typedef enum pa_bluetooth_clip {
|
||||
CLIP_NATIONAL_NUMBER = 129
|
||||
} pa_bluetooth_clip_t;
|
||||
|
||||
+/* CLCC call states, described in Bluetooth HFP 1.8 spec */
|
||||
+/* FIXME: support three-way calling */
|
||||
+typedef enum pa_bluetooth_clcc {
|
||||
+ CLCC_ACTIVE = 0,
|
||||
+ CLCC_DIALING = 2,
|
||||
+ CLCC_ALERTING = 3,
|
||||
+ CLCC_INCOMING = 4
|
||||
+} pa_bluetooth_clcc_t;
|
||||
+
|
||||
#ifdef HAVE_BLUEZ_5_OFONO_HEADSET
|
||||
pa_bluetooth_backend *pa_bluetooth_ofono_backend_new(pa_core *c, pa_bluetooth_discovery *y);
|
||||
void pa_bluetooth_ofono_backend_free(pa_bluetooth_backend *b);
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,365 +0,0 @@
|
|||
From 6861de91294c8bed206e8338d1074ebc57683ae4 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Sat, 16 Apr 2022 08:46:13 +0200
|
||||
Subject: [PATCH 21/26] bluetooth: support +CIEV, RING, and +CLIP URCs
|
||||
|
||||
Report changes of the CIND indicators and calls to the HF with URCs:
|
||||
|
||||
- +CIEV: report any change to the CIND indicators such as signal
|
||||
strength, roaming status, service status, etc.
|
||||
- RING: play a ringtone on the HF side for incoming calls.
|
||||
- +CLIP: enhanced call status reports the subscriber number to the HF
|
||||
for incoming calls.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 258 +++++++++++++++++++++++++
|
||||
src/modules/bluetooth/bluez5-util.h | 12 ++
|
||||
2 files changed, 270 insertions(+)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index faefed9bd..e12b38d71 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -29,6 +29,8 @@
|
||||
#include <pulsecore/core-util.h>
|
||||
#include <pulsecore/dbus-shared.h>
|
||||
#include <pulsecore/log.h>
|
||||
+#include <pulse/timeval.h>
|
||||
+#include <pulse/rtclock.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
@@ -42,6 +44,7 @@
|
||||
#include "upower.h"
|
||||
#include "modemmanager.h"
|
||||
|
||||
+#define RING_WAIT_TIME ((pa_usec_t) (3 * PA_USEC_PER_SEC))
|
||||
#define MANDATORY_CALL_INDICATORS \
|
||||
"(\"call\",(0-1))," \
|
||||
"(\"callsetup\",(0-3))," \
|
||||
@@ -49,10 +52,17 @@
|
||||
|
||||
struct pa_bluetooth_backend {
|
||||
pa_core *core;
|
||||
+ pa_time_event *timer_ring_event;
|
||||
pa_dbus_connection *connection;
|
||||
pa_bluetooth_discovery *discovery;
|
||||
pa_hook_slot *adapter_uuids_changed_slot;
|
||||
pa_hook_slot *host_battery_level_changed_slot;
|
||||
+ pa_hook_slot *host_operation_succeed_slot;
|
||||
+ pa_hook_slot *host_operation_failed_slot;
|
||||
+ pa_hook_slot *host_signal_strength_changed_slot;
|
||||
+ pa_hook_slot *host_has_service_changed_slot;
|
||||
+ pa_hook_slot *host_is_roaming_changed_slot;
|
||||
+ pa_hook_slot *host_calls_changed_slot;
|
||||
pa_upower_backend *upower;
|
||||
pa_modemmanager_backend *modemmanager;
|
||||
bool enable_shared_profiles;
|
||||
@@ -63,6 +73,8 @@ struct pa_bluetooth_backend {
|
||||
uint32_t cind_enabled_indicators;
|
||||
pa_bluetooth_cops_t cops_format;
|
||||
bool clip_call_line_reporting_enabled;
|
||||
+ unsigned int cind_call_indicator;
|
||||
+ unsigned int cind_call_setup_indicator;
|
||||
|
||||
PA_LLIST_HEAD(pa_dbus_pending, pending);
|
||||
};
|
||||
@@ -1172,6 +1184,206 @@ static pa_hook_result_t host_battery_level_changed_cb(pa_bluetooth_discovery *y,
|
||||
return PA_HOOK_OK;
|
||||
}
|
||||
|
||||
+static pa_hook_result_t host_operation_failed_cb(pa_bluetooth_discovery *y, const pa_modemmanager_backend *m, pa_bluetooth_backend *b) {
|
||||
+ int rfcomm_fd;
|
||||
+
|
||||
+ pa_assert(y);
|
||||
+ pa_assert(m);
|
||||
+ pa_assert(b);
|
||||
+
|
||||
+ /* Get RFCOMM channel if available */
|
||||
+ rfcomm_fd = get_rfcomm_fd (y);
|
||||
+ if (rfcomm_fd < 0)
|
||||
+ return PA_HOOK_OK;
|
||||
+
|
||||
+ /* Notify HF about AG operation failure over RFCOMM */
|
||||
+ rfcomm_write_error(b, rfcomm_fd, CMEE_AG_FAILURE);
|
||||
+
|
||||
+ return PA_HOOK_OK;
|
||||
+}
|
||||
+
|
||||
+static pa_hook_result_t host_operation_succeed_cb(pa_bluetooth_discovery *y, const pa_modemmanager_backend *m, pa_bluetooth_backend *b) {
|
||||
+ int rfcomm_fd;
|
||||
+
|
||||
+ pa_assert(y);
|
||||
+ pa_assert(m);
|
||||
+ pa_assert(b);
|
||||
+
|
||||
+ /* Get RFCOMM channel if available */
|
||||
+ rfcomm_fd = get_rfcomm_fd (y);
|
||||
+ if (rfcomm_fd < 0)
|
||||
+ return PA_HOOK_OK;
|
||||
+
|
||||
+ /* Notify HF about AG operation succeed over RFCOMM */
|
||||
+ rfcomm_write_response(rfcomm_fd, "OK");
|
||||
+
|
||||
+ return PA_HOOK_OK;
|
||||
+}
|
||||
+
|
||||
+static pa_hook_result_t host_signal_strength_changed_cb(pa_bluetooth_discovery *y, const pa_modemmanager_backend *m, pa_bluetooth_backend *b) {
|
||||
+ int rfcomm_fd;
|
||||
+
|
||||
+ pa_assert(y);
|
||||
+ pa_assert(m);
|
||||
+ pa_assert(b);
|
||||
+
|
||||
+ /* Get RFCOMM channel if available */
|
||||
+ rfcomm_fd = get_rfcomm_fd (y);
|
||||
+ if (rfcomm_fd < 0)
|
||||
+ return PA_HOOK_OK;
|
||||
+
|
||||
+ /* Notify HF about AG signal strength change */
|
||||
+ if (b->cmer_indicator_reporting_enabled && (b->cind_enabled_indicators & (1 << CIND_SIGNAL_STRENGTH_INDICATOR))) {
|
||||
+ rfcomm_write_response(rfcomm_fd, "+CIEV: %d,%d", CIND_SIGNAL_STRENGTH_INDICATOR, pa_modemmanager_get_signal_strength(m));
|
||||
+ /* Skip notification if indicator is disabled or event reporting is completely disabled */
|
||||
+ } else
|
||||
+ pa_log_debug("Signal strength change indicator disabled, skipping notification");
|
||||
+
|
||||
+ return PA_HOOK_OK;
|
||||
+}
|
||||
+
|
||||
+static pa_hook_result_t host_has_service_changed_cb(pa_bluetooth_discovery *y, const pa_modemmanager_backend *m, pa_bluetooth_backend *b) {
|
||||
+ int rfcomm_fd;
|
||||
+
|
||||
+ pa_assert(y);
|
||||
+ pa_assert(m);
|
||||
+ pa_assert(b);
|
||||
+
|
||||
+ /* Get RFCOMM channel if available */
|
||||
+ rfcomm_fd = get_rfcomm_fd (y);
|
||||
+ if (rfcomm_fd < 0)
|
||||
+ return PA_HOOK_OK;
|
||||
+
|
||||
+ /* Notify HF about AG cellular service status change */
|
||||
+ if (b->cmer_indicator_reporting_enabled && (b->cind_enabled_indicators & (1 << CIND_SERVICE_INDICATOR))) {
|
||||
+ rfcomm_write_response(rfcomm_fd, "+CIEV: %d,%d", CIND_SERVICE_INDICATOR, pa_modemmanager_has_service(m));
|
||||
+ /* Skip notification if indicator is disabled or event reporting is completely disabled */
|
||||
+ } else
|
||||
+ pa_log_debug("Cellular service status change indicator disabled, skipping notification");
|
||||
+
|
||||
+ return PA_HOOK_OK;
|
||||
+}
|
||||
+
|
||||
+static pa_hook_result_t host_is_roaming_changed_cb(pa_bluetooth_discovery *y, const pa_modemmanager_backend *m, pa_bluetooth_backend *b) {
|
||||
+ int rfcomm_fd;
|
||||
+
|
||||
+ pa_assert(y);
|
||||
+ pa_assert(m);
|
||||
+ pa_assert(b);
|
||||
+
|
||||
+ /* Get RFCOMM channel if available */
|
||||
+ rfcomm_fd = get_rfcomm_fd (y);
|
||||
+ if (rfcomm_fd < 0)
|
||||
+ return PA_HOOK_OK;
|
||||
+
|
||||
+ /* Notify HF about AG roaming status change */
|
||||
+ if (b->cmer_indicator_reporting_enabled && (b->cind_enabled_indicators & (1 << CIND_ROAMING_INDICATOR))) {
|
||||
+ rfcomm_write_response(rfcomm_fd, "+CIEV: %d,%d", CIND_ROAMING_INDICATOR, pa_modemmanager_is_roaming(m));
|
||||
+ /* Skip notification if indicator is disabled or event reporting is completely disabled */
|
||||
+ } else
|
||||
+ pa_log_debug("Roaming status change indicator disabled, skipping notification");
|
||||
+
|
||||
+ return PA_HOOK_OK;
|
||||
+}
|
||||
+
|
||||
+static void timer_ring_cb(pa_mainloop_api *a, pa_time_event *e, const struct timeval *t, void *userdata) {
|
||||
+ int rfcomm_fd;
|
||||
+ unsigned int type;
|
||||
+ pa_bluetooth_discovery *y = userdata;
|
||||
+ pa_hashmap *calls;
|
||||
+ call_status_t *call;
|
||||
+
|
||||
+ /* Get RFCOMM channel if available */
|
||||
+ rfcomm_fd = get_rfcomm_fd (y);
|
||||
+ if (rfcomm_fd < 0)
|
||||
+ return;
|
||||
+
|
||||
+ calls = pa_modemmanager_get_calls(y->native_backend->modemmanager);
|
||||
+
|
||||
+ /* Stop ringing if no calls are available */
|
||||
+ if (pa_hashmap_isempty(calls))
|
||||
+ return;
|
||||
+
|
||||
+ /* FIXME: support three-way calling */
|
||||
+ call = pa_hashmap_first(calls);
|
||||
+
|
||||
+ /* Send RING indicator */
|
||||
+ rfcomm_write_response(rfcomm_fd, "RING");
|
||||
+
|
||||
+ /* If enabled, send +CLIP indications to HF about the caller */
|
||||
+ if (y->native_backend->clip_call_line_reporting_enabled && call->number) {
|
||||
+ /* International numbers start with '+' */
|
||||
+ if (strncmp("+", call->number, 1) == 0)
|
||||
+ type = CLIP_INTERNATIONAL_NUMBER;
|
||||
+ else
|
||||
+ type = CLIP_NATIONAL_NUMBER;
|
||||
+ rfcomm_write_response(rfcomm_fd, "+CLIP: \"%s\",%d", call->number, type);
|
||||
+ }
|
||||
+
|
||||
+ if (y->native_backend->timer_ring_event)
|
||||
+ pa_core_rttime_restart(y->native_backend->core, y->native_backend->timer_ring_event, pa_rtclock_now() + RING_WAIT_TIME);
|
||||
+}
|
||||
+
|
||||
+static pa_hook_result_t host_calls_changed_cb(pa_bluetooth_discovery *y, const pa_modemmanager_backend *m, pa_bluetooth_backend *b) {
|
||||
+ int rfcomm_fd;
|
||||
+ unsigned int call_indicator;
|
||||
+ unsigned int call_setup_indicator;
|
||||
+ pa_hashmap *calls;
|
||||
+ call_status_t *call;
|
||||
+
|
||||
+ pa_assert(y);
|
||||
+ pa_assert(m);
|
||||
+ pa_assert(b);
|
||||
+
|
||||
+ /* Get RFCOMM channel if available */
|
||||
+ rfcomm_fd = get_rfcomm_fd (y);
|
||||
+ if (rfcomm_fd < 0)
|
||||
+ return PA_HOOK_OK;
|
||||
+
|
||||
+ calls = pa_modemmanager_get_calls(m);
|
||||
+ call = pa_hashmap_isempty(calls)? NULL: pa_hashmap_first(calls);
|
||||
+
|
||||
+ /* Notify HF about call indicator state, if changed */
|
||||
+ if (call && call->status == PA_MODEMMANAGER_CALL_STATE_ACTIVE)
|
||||
+ call_indicator = CIND_CALL_AT_LEAST_ONE;
|
||||
+ else
|
||||
+ call_indicator = CIND_CALL_NONE;
|
||||
+
|
||||
+ if (b->cind_call_indicator != call_indicator) {
|
||||
+ b->cind_call_indicator = call_indicator;
|
||||
+ rfcomm_write_response(rfcomm_fd, "+CIEV: %d,%d", CIND_CALL_INDICATOR, b->cind_call_indicator);
|
||||
+ }
|
||||
+
|
||||
+ /* Notify HF about call setup indicator state, if changed */
|
||||
+ if (call && call->is_incoming && call->status == PA_MODEMMANAGER_CALL_STATE_RINGING)
|
||||
+ call_setup_indicator = CIND_CALL_SETUP_INCOMING;
|
||||
+ else if (call && !call->is_incoming && call->status == PA_MODEMMANAGER_CALL_STATE_DIALING)
|
||||
+ call_setup_indicator = CIND_CALL_SETUP_OUTGOING_DIALING;
|
||||
+ else if (call && !call->is_incoming && call->status == PA_MODEMMANAGER_CALL_STATE_RINGING)
|
||||
+ call_setup_indicator = CIND_CALL_SETUP_OUTGOING_ALERTING;
|
||||
+ else
|
||||
+ call_setup_indicator = CIND_CALL_SETUP_NONE;
|
||||
+
|
||||
+ if (b->cind_call_setup_indicator != call_setup_indicator) {
|
||||
+ b->cind_call_setup_indicator = call_setup_indicator;
|
||||
+ rfcomm_write_response(rfcomm_fd, "+CIEV: %d,%d", CIND_CALL_SETUP_INDICATOR, b->cind_call_setup_indicator);
|
||||
+ }
|
||||
+
|
||||
+ /* Start/stop ringing */
|
||||
+ if (call && call->is_incoming && call->status == PA_MODEMMANAGER_CALL_STATE_RINGING) {
|
||||
+ if (!b->timer_ring_event) {
|
||||
+ pa_log_debug("RING indicator started");
|
||||
+ b->timer_ring_event = pa_core_rttime_new(b->core, pa_rtclock_now(), timer_ring_cb, y);
|
||||
+ }
|
||||
+ } else if (b->timer_ring_event) {
|
||||
+ pa_log_debug("RING indicator stopped");
|
||||
+ b->core->mainloop->time_free(b->timer_ring_event);
|
||||
+ b->timer_ring_event = NULL;
|
||||
+ }
|
||||
+
|
||||
+ return PA_HOOK_OK;
|
||||
+}
|
||||
+
|
||||
static void rfcomm_io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
|
||||
pa_bluetooth_transport *t = userdata;
|
||||
pa_bluetooth_discovery *discovery = t->device->discovery;
|
||||
@@ -1658,6 +1870,30 @@ pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_d
|
||||
pa_hook_connect(pa_bluetooth_discovery_hook(y, PA_BLUETOOTH_HOOK_HOST_BATTERY_LEVEL_CHANGED), PA_HOOK_NORMAL,
|
||||
(pa_hook_cb_t) host_battery_level_changed_cb, backend);
|
||||
|
||||
+ backend->host_operation_failed_slot =
|
||||
+ pa_hook_connect(pa_bluetooth_discovery_hook(y, PA_BLUETOOTH_HOOK_HOST_OPERATION_FAILED), PA_HOOK_NORMAL,
|
||||
+ (pa_hook_cb_t) host_operation_failed_cb, backend);
|
||||
+
|
||||
+ backend->host_operation_succeed_slot =
|
||||
+ pa_hook_connect(pa_bluetooth_discovery_hook(y, PA_BLUETOOTH_HOOK_HOST_OPERATION_SUCCEED), PA_HOOK_NORMAL,
|
||||
+ (pa_hook_cb_t) host_operation_succeed_cb, backend);
|
||||
+
|
||||
+ backend->host_signal_strength_changed_slot =
|
||||
+ pa_hook_connect(pa_bluetooth_discovery_hook(y, PA_BLUETOOTH_HOOK_HOST_SIGNAL_STRENGTH_CHANGED), PA_HOOK_NORMAL,
|
||||
+ (pa_hook_cb_t) host_signal_strength_changed_cb, backend);
|
||||
+
|
||||
+ backend->host_has_service_changed_slot =
|
||||
+ pa_hook_connect(pa_bluetooth_discovery_hook(y, PA_BLUETOOTH_HOOK_HOST_HAS_SERVICE_CHANGED), PA_HOOK_NORMAL,
|
||||
+ (pa_hook_cb_t) host_has_service_changed_cb, backend);
|
||||
+
|
||||
+ backend->host_is_roaming_changed_slot =
|
||||
+ pa_hook_connect(pa_bluetooth_discovery_hook(y, PA_BLUETOOTH_HOOK_HOST_IS_ROAMING_CHANGED), PA_HOOK_NORMAL,
|
||||
+ (pa_hook_cb_t) host_is_roaming_changed_cb, backend);
|
||||
+
|
||||
+ backend->host_calls_changed_slot =
|
||||
+ pa_hook_connect(pa_bluetooth_discovery_hook(y, PA_BLUETOOTH_HOOK_HOST_CALLS_CHANGED), PA_HOOK_NORMAL,
|
||||
+ (pa_hook_cb_t) host_calls_changed_cb, backend);
|
||||
+
|
||||
if (!backend->enable_hsp_hs && !backend->enable_hfp_hf)
|
||||
pa_log_warn("Both HSP HS and HFP HF bluetooth profiles disabled in native backend. Native backend will not register for headset connections.");
|
||||
|
||||
@@ -1684,6 +1920,10 @@ pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_d
|
||||
/* CLIP is disabled by default */
|
||||
backend->clip_call_line_reporting_enabled = false;
|
||||
|
||||
+ /* TODO: Initiate CIND call & callsetup indicators at startup */
|
||||
+ backend->cind_call_indicator = CIND_CALL_NONE;
|
||||
+ backend->cind_call_setup_indicator = CIND_CALL_SETUP_NONE;
|
||||
+
|
||||
return backend;
|
||||
}
|
||||
|
||||
@@ -1698,6 +1938,24 @@ void pa_bluetooth_native_backend_free(pa_bluetooth_backend *backend) {
|
||||
if (backend->host_battery_level_changed_slot)
|
||||
pa_hook_slot_free(backend->host_battery_level_changed_slot);
|
||||
|
||||
+ if (backend->host_operation_failed_slot)
|
||||
+ pa_hook_slot_free(backend->host_operation_failed_slot);
|
||||
+
|
||||
+ if (backend->host_operation_succeed_slot)
|
||||
+ pa_hook_slot_free(backend->host_operation_succeed_slot);
|
||||
+
|
||||
+ if (backend->host_signal_strength_changed_slot)
|
||||
+ pa_hook_slot_free(backend->host_signal_strength_changed_slot);
|
||||
+
|
||||
+ if (backend->host_has_service_changed_slot)
|
||||
+ pa_hook_slot_free(backend->host_has_service_changed_slot);
|
||||
+
|
||||
+ if (backend->host_is_roaming_changed_slot)
|
||||
+ pa_hook_slot_free(backend->host_is_roaming_changed_slot);
|
||||
+
|
||||
+ if (backend->host_calls_changed_slot)
|
||||
+ pa_hook_slot_free(backend->host_calls_changed_slot);
|
||||
+
|
||||
if (backend->enable_shared_profiles)
|
||||
native_backend_apply_profile_registration_change(backend, false);
|
||||
|
||||
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
|
||||
index fb88f00e2..35b3153b8 100644
|
||||
--- a/src/modules/bluetooth/bluez5-util.h
|
||||
+++ b/src/modules/bluetooth/bluez5-util.h
|
||||
@@ -242,6 +242,18 @@ typedef enum pa_bluetooth_clcc {
|
||||
CLCC_INCOMING = 4
|
||||
} pa_bluetooth_clcc_t;
|
||||
|
||||
+typedef enum pa_bluetooth_cind_call {
|
||||
+ CIND_CALL_NONE = 0,
|
||||
+ CIND_CALL_AT_LEAST_ONE = 1,
|
||||
+} pa_bluetooth_cind_call_t;
|
||||
+
|
||||
+typedef enum pa_bluetooth_cind_call_setup {
|
||||
+ CIND_CALL_SETUP_NONE = 0,
|
||||
+ CIND_CALL_SETUP_INCOMING = 1,
|
||||
+ CIND_CALL_SETUP_OUTGOING_DIALING = 2,
|
||||
+ CIND_CALL_SETUP_OUTGOING_ALERTING = 3
|
||||
+} pa_bluetooth_cind_call_setup_t;
|
||||
+
|
||||
#ifdef HAVE_BLUEZ_5_OFONO_HEADSET
|
||||
pa_bluetooth_backend *pa_bluetooth_ofono_backend_new(pa_core *c, pa_bluetooth_discovery *y);
|
||||
void pa_bluetooth_ofono_backend_free(pa_bluetooth_backend *b);
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
From 8d2504c42a1910b4b6bf80a0474f4b5502c4f490 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Sat, 16 Apr 2022 16:37:10 +0200
|
||||
Subject: [PATCH 22/26] bluetooth: support AT+VTS
|
||||
|
||||
Send DTMF tones to the active call when the HF sends AT+VTS=$character.
|
||||
Return an error if more than one character is given or ModemManager is
|
||||
unavailable.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 32 ++++++++++++++++++++++++++
|
||||
src/modules/bluetooth/bluez5-util.h | 1 +
|
||||
2 files changed, 33 insertions(+)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index e12b38d71..306de44a7 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -841,6 +841,38 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
|
||||
rfcomm_write_response(fd, "+CLCC: %d,%d,%d,%d,%d,\"%s\",%d", 1, call->is_incoming, clcc_status, 0, 0, call->number, type);
|
||||
return true;
|
||||
+ } else if (strstr(buf, "AT+VTS=")) {
|
||||
+ char *call_key = NULL;
|
||||
+ char dtmf_char[2]; /* character and '\0' */
|
||||
+
|
||||
+ /* AT+VTS is only possible if ModemManager is availble */
|
||||
+ if (!discovery->native_backend->modemmanager || !pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("ModemManager backend unavailable, cannot send DTMF tone with AT+VTS");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
+ return false;
|
||||
+ } else if (!pa_modemmanager_has_service(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("No network service, cannot send DTMF tone with AT+VTS");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_NETWORK_SERVICE);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Parse DTMF character, HFP spec allows 1 character. Return an error if parsing failed. */
|
||||
+ val = sscanf(buf, "AT+VTS=%1s", dtmf_char);
|
||||
+ if (val != 1) {
|
||||
+ pa_log_warn("Cannot parse DTMF character from \"%s\"", buf);
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_INVALID_CHARACTERS_TEXT_STRING);
|
||||
+ return false;
|
||||
+ }
|
||||
+ call_key = pa_modemmanager_get_active_call_key(discovery->native_backend->modemmanager);
|
||||
+ if (call_key)
|
||||
+ pa_modemmanager_send_dtmf(discovery->native_backend->modemmanager, call_key, dtmf_char);
|
||||
+ else {
|
||||
+ pa_log_warn("No active call, cannot send DTMF tone with AT+VTS");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_OPERATION_NOT_ALLOWED);
|
||||
+ }
|
||||
+
|
||||
+ /* AT response will be reported through PA_BLUETOOTH_HOST_OPERATION_{SUCCEED, FAILED} hook */
|
||||
+ return false;
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
|
||||
index 35b3153b8..4802cca69 100644
|
||||
--- a/src/modules/bluetooth/bluez5-util.h
|
||||
+++ b/src/modules/bluetooth/bluez5-util.h
|
||||
@@ -217,6 +217,7 @@ typedef enum pa_bluetooth_cmee {
|
||||
CMEE_NO_CONNECTION_TO_PHONE = 1,
|
||||
CMEE_OPERATION_NOT_ALLOWED = 3,
|
||||
CMEE_OPERATION_NOT_SUPPORTED = 4,
|
||||
+ CMEE_INVALID_CHARACTERS_TEXT_STRING = 25,
|
||||
CMEE_NO_NETWORK_SERVICE = 30
|
||||
} pa_bluetooth_cmee_t;
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
From 48286245124ed08e57624b1e069cfa2ce4776568 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Sat, 16 Apr 2022 19:37:04 +0200
|
||||
Subject: [PATCH 23/26] bluetooth: support ATA
|
||||
|
||||
Accept incoming calls if the HF sends 'ATA'.
|
||||
The first call in the call list is accepted,
|
||||
multiparty calling is not supported (yet).
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 31 ++++++++++++++++++++++++++
|
||||
1 file changed, 31 insertions(+)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index 306de44a7..6f6241479 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -873,6 +873,37 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
|
||||
/* AT response will be reported through PA_BLUETOOTH_HOST_OPERATION_{SUCCEED, FAILED} hook */
|
||||
return false;
|
||||
+ } else if (strstr(buf, "ATA")) {
|
||||
+ pa_hashmap *calls;
|
||||
+ char *call_key = NULL;
|
||||
+ call_status_t *call = NULL;
|
||||
+
|
||||
+ /* ATA is only possible if ModemManager is availble */
|
||||
+ if (!discovery->native_backend->modemmanager || !pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("ModemManager backend unavailable, cannot reject call with ATA");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
+ return false;
|
||||
+ } else if (!pa_modemmanager_has_service(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("No network service, cannot accept call with ATA");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_NETWORK_SERVICE);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Accept call is available */
|
||||
+ calls = pa_modemmanager_get_calls(discovery->native_backend->modemmanager);
|
||||
+ call_key = pa_modemmanager_get_active_call_key(discovery->native_backend->modemmanager);
|
||||
+ if (call_key)
|
||||
+ call = pa_hashmap_get(calls, call_key);
|
||||
+
|
||||
+ if (call && call->status == PA_MODEMMANAGER_CALL_STATE_RINGING && call->is_incoming)
|
||||
+ pa_modemmanager_accept_call(discovery->native_backend->modemmanager, call_key);
|
||||
+ else {
|
||||
+ pa_log_warn("Cannot accept call, call must be incoming and ringing");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_OPERATION_NOT_ALLOWED);
|
||||
+ }
|
||||
+
|
||||
+ /* AT response will be reported through PA_BLUETOOTH_HOST_OPERATION_{SUCCEED, FAILED} hook */
|
||||
+ return false;
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
From 12610afa56b74e7db44086d81709faedda2b83e9 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Sat, 16 Apr 2022 19:53:38 +0200
|
||||
Subject: [PATCH 24/26] bluetooth: support AT+CHUP
|
||||
|
||||
Hangup or reject a call when the HF sends 'AT+CHUP'.
|
||||
If the call is on going, it is ended. If the call is ringing and
|
||||
incoming, it is rejected. The same interface in ModemManager is used for
|
||||
this functionality. This AT command is only available if ModemManager is
|
||||
present.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 37 ++++++++++++++++++++++++--
|
||||
1 file changed, 35 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index 6f6241479..d502cff78 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -144,7 +144,7 @@ typedef enum pa_bluetooth_ag_to_hf_indicators {
|
||||
/* gateway features we support, which is as little as we can get away with */
|
||||
static uint32_t hfp_features =
|
||||
/* HFP 1.6 requires this */
|
||||
- (1 << HFP_AG_ESTATUS ) | (1 << HFP_AG_CODECS) | (1 << HFP_AG_INDICATORS) | (1 << HFP_AG_EERR);
|
||||
+ (1 << HFP_AG_ESTATUS ) | (1 << HFP_AG_CODECS) | (1 << HFP_AG_INDICATORS) | (1 << HFP_AG_EERR) | (1 << HFP_AG_REJECT);
|
||||
|
||||
#define HSP_AG_PROFILE "/Profile/HSPAGProfile"
|
||||
#define HFP_AG_PROFILE "/Profile/HFPAGProfile"
|
||||
@@ -904,7 +904,40 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
|
||||
/* AT response will be reported through PA_BLUETOOTH_HOST_OPERATION_{SUCCEED, FAILED} hook */
|
||||
return false;
|
||||
- }
|
||||
+ } else if (strstr(buf, "AT+CHUP")) {
|
||||
+ pa_hashmap *calls;
|
||||
+ char *call_key = NULL;
|
||||
+ call_status_t *call = NULL;
|
||||
+
|
||||
+ /* AT+CHUP is only possible if ModemManager is availble */
|
||||
+ if (!discovery->native_backend->modemmanager || !pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("ModemManager backend unavailable, cannot reject call with AT+CHUP");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
+ return false;
|
||||
+ } else if (!pa_modemmanager_has_service(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("No network service, cannot reject call with ATD+CHUP");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_NETWORK_SERVICE);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Hangup/reject call is available */
|
||||
+ calls = pa_modemmanager_get_calls(discovery->native_backend->modemmanager);
|
||||
+ call_key = pa_modemmanager_get_active_call_key(discovery->native_backend->modemmanager);
|
||||
+ if (call_key)
|
||||
+ call = pa_hashmap_get(calls, call_key);
|
||||
+
|
||||
+ if (call && (call->status == PA_MODEMMANAGER_CALL_STATE_ACTIVE
|
||||
+ || call->status == PA_MODEMMANAGER_CALL_STATE_RINGING
|
||||
+ || call->status == PA_MODEMMANAGER_CALL_STATE_DIALING))
|
||||
+ pa_modemmanager_end_call(discovery->native_backend->modemmanager, call_key);
|
||||
+ else {
|
||||
+ pa_log_warn("Cannot end call, call must be active, ringing or dialing");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_OPERATION_NOT_ALLOWED);
|
||||
+ }
|
||||
+
|
||||
+ /* AT response will be reported through PA_BLUETOOTH_HOST_OPERATION_{SUCCEED, FAILED} hook */
|
||||
+ return false;
|
||||
+ }
|
||||
|
||||
/*
|
||||
* Out-of-spec Bluetooth HFP 1.8 AT commands.
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
From d2748e1952c282ce82e93daaeb2f25bb10ce46ab Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Sat, 16 Apr 2022 20:29:54 +0200
|
||||
Subject: [PATCH 25/26] bluetooth: support ATD$number;
|
||||
|
||||
Start a call when HF sends 'ATD$number;'
|
||||
This AT command is only available when ModemManager is present.
|
||||
Number is filtered for any invalid characters, if an invalid character
|
||||
is found, the call is aborted and an error is returned.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 57 ++++++++++++++++++++++++++
|
||||
src/modules/bluetooth/bluez5-util.h | 1 +
|
||||
2 files changed, 58 insertions(+)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index d502cff78..b6991ae13 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -44,6 +44,9 @@
|
||||
#include "upower.h"
|
||||
#include "modemmanager.h"
|
||||
|
||||
+#define MAX_NUMBER_LENGTH 30
|
||||
+#define STR_VALUE(x) STR(x)
|
||||
+#define STR(x) #x
|
||||
#define RING_WAIT_TIME ((pa_usec_t) (3 * PA_USEC_PER_SEC))
|
||||
#define MANDATORY_CALL_INDICATORS \
|
||||
"(\"call\",(0-1))," \
|
||||
@@ -935,6 +938,60 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
||||
rfcomm_write_error(discovery->native_backend, fd, CMEE_OPERATION_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
+ /* AT response will be reported through PA_BLUETOOTH_HOST_OPERATION_{SUCCEED, FAILED} hook */
|
||||
+ return false;
|
||||
+ } else if (strstr(buf, "ATD")) {
|
||||
+ int k, j;
|
||||
+ char number[MAX_NUMBER_LENGTH];
|
||||
+ char number_filtered[MAX_NUMBER_LENGTH];
|
||||
+
|
||||
+ /* ATD$number; is only possible if ModemManager is availble */
|
||||
+ if (!discovery->native_backend->modemmanager || !pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("ModemManager backend unavailable, cannot create call with ATD$number;");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
||||
+ return false;
|
||||
+ } else if (!pa_modemmanager_has_service(discovery->native_backend->modemmanager)) {
|
||||
+ pa_log_debug("No network service, cannot create call with ATD$number;");
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_NETWORK_SERVICE);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Try to parse number from ATD command */
|
||||
+ if (sscanf(buf, "ATD%" STR_VALUE(MAX_NUMBER_LENGTH) "s;", number) != 1) {
|
||||
+ pa_log_debug("Cannot parse ATD$number: \"%s\"", buf);
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Filter extracted number from invalid characters
|
||||
+ * Allowed characters: 0-9, *, #, +, A-C
|
||||
+ */
|
||||
+ k=0;
|
||||
+ memset(number_filtered, '\0', sizeof(char) * MAX_NUMBER_LENGTH);
|
||||
+ for (j=0; j < MAX_NUMBER_LENGTH; j++) {
|
||||
+ if ((number[j] >= '0' && number[j] <= '9')
|
||||
+ || (number[j] == '*')
|
||||
+ || (number[j] == '#')
|
||||
+ || (number[j] == '+')
|
||||
+ || (number[j] >= 'A' && number[j] <= 'C')) {
|
||||
+ number_filtered[k] = number[j];
|
||||
+ k++;
|
||||
+ }
|
||||
+ /* ATD commands ends with ';'. */
|
||||
+ else if (number[j] == ';')
|
||||
+ break;
|
||||
+ /* Send error for invalid characters */
|
||||
+ else {
|
||||
+ pa_log_warn("Call creation canceled, invalid character found in dial string: %c", number[j]);
|
||||
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_INVALID_CHARACTERS_DIAL_STRING);
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Create call for filtered number */
|
||||
+ pa_modemmanager_start_call(discovery->native_backend->modemmanager, number_filtered);
|
||||
+
|
||||
/* AT response will be reported through PA_BLUETOOTH_HOST_OPERATION_{SUCCEED, FAILED} hook */
|
||||
return false;
|
||||
}
|
||||
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
|
||||
index 4802cca69..ccbe6ba78 100644
|
||||
--- a/src/modules/bluetooth/bluez5-util.h
|
||||
+++ b/src/modules/bluetooth/bluez5-util.h
|
||||
@@ -218,6 +218,7 @@ typedef enum pa_bluetooth_cmee {
|
||||
CMEE_OPERATION_NOT_ALLOWED = 3,
|
||||
CMEE_OPERATION_NOT_SUPPORTED = 4,
|
||||
CMEE_INVALID_CHARACTERS_TEXT_STRING = 25,
|
||||
+ CMEE_INVALID_CHARACTERS_DIAL_STRING = 27,
|
||||
CMEE_NO_NETWORK_SERVICE = 30
|
||||
} pa_bluetooth_cmee_t;
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
From aff9bf69960c3e2ac1d7c35176e9f3b34389f656 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Tue, 19 Apr 2022 20:15:09 +0200
|
||||
Subject: [PATCH 26/26] bluetooth: strip additional out-of-spec '\r\n' chars
|
||||
|
||||
Some HF devices do not comply strictly with the HFP specification
|
||||
and send additional '\r\n' sequences besides the expected ones.
|
||||
This breaks AT command parsing in PulseAudio.
|
||||
|
||||
To work around this problem, strip these characters before processing
|
||||
the AT command and responses.
|
||||
---
|
||||
src/modules/bluetooth/backend-native.c | 22 ++++++++++++++++++----
|
||||
1 file changed, 18 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
index b6991ae13..8aa83f025 100644
|
||||
--- a/src/modules/bluetooth/backend-native.c
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -1556,19 +1556,33 @@ static void rfcomm_io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_i
|
||||
}
|
||||
|
||||
if (events & PA_IO_EVENT_INPUT) {
|
||||
- char buf[512];
|
||||
+ char buf[512], raw_buf[512];
|
||||
ssize_t len;
|
||||
int gain, dummy;
|
||||
bool do_reply = false;
|
||||
int vendor, product, version, features;
|
||||
- int num;
|
||||
+ int num, i, j;
|
||||
|
||||
- len = pa_read(fd, buf, 511, NULL);
|
||||
+ len = pa_read(fd, raw_buf, 511, NULL);
|
||||
if (len < 0) {
|
||||
pa_log_error("RFCOMM read error: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
- buf[len] = 0;
|
||||
+ raw_buf[len] = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Filter '\r' and '\n' characters out since some HF devices
|
||||
+ * send too much \r\n sequences in their responses
|
||||
+ */
|
||||
+ memset(buf, '\0', sizeof(char) * 512);
|
||||
+ j=0;
|
||||
+ for (i=0; i<512; i++) {
|
||||
+ if (raw_buf[i] == '\r' || raw_buf[i] == '\n')
|
||||
+ continue;
|
||||
+ buf[j] = raw_buf[i];
|
||||
+ j++;
|
||||
+ }
|
||||
+ buf[j] = 0;
|
||||
pa_log_debug("RFCOMM << %s", buf);
|
||||
|
||||
/* There are only four HSP AT commands:
|
||||
--
|
||||
2.35.1
|
||||
|
|
@ -1,285 +0,0 @@
|
|||
# Forked from Alpine for enhanced Bluetooth HFP support
|
||||
|
||||
pkgname=pulseaudio
|
||||
pkgver=9999_git20220621
|
||||
_pkgver=16.1
|
||||
pkgrel=2
|
||||
pkgdesc="featureful, general-purpose sound server"
|
||||
provider_priority=10
|
||||
url="https://www.freedesktop.org/wiki/Software/PulseAudio/"
|
||||
arch="all"
|
||||
license="LGPL-2.1-or-later"
|
||||
options="pmb:strict !check"
|
||||
makedepends="
|
||||
meson
|
||||
tdb-dev
|
||||
alsa-lib-dev
|
||||
libasyncns-dev
|
||||
dbus-dev
|
||||
glib-dev
|
||||
gtk+3.0-dev
|
||||
orc-dev
|
||||
orc-compiler
|
||||
libsndfile-dev
|
||||
soxr-dev
|
||||
libx11-dev
|
||||
libxcb-dev
|
||||
libice-dev
|
||||
libsm-dev
|
||||
libxtst-dev
|
||||
avahi-dev
|
||||
sbc-dev
|
||||
fftw-dev
|
||||
jack-dev
|
||||
openssl-dev>3
|
||||
speexdsp-dev
|
||||
eudev-dev
|
||||
libcap-dev
|
||||
bluez-dev
|
||||
check-dev
|
||||
libtool
|
||||
perl
|
||||
perl-xml-parser
|
||||
m4
|
||||
gstreamer-dev
|
||||
gst-plugins-base-dev
|
||||
modemmanager-dev
|
||||
"
|
||||
depends_openrc="alsa-utils alsa-utils-openrc"
|
||||
subpackages="
|
||||
$pkgname-dev
|
||||
$pkgname-doc
|
||||
$pkgname-bluez
|
||||
libpulse-mainloop-glib:_libpulse_mainloop_glib
|
||||
$pkgname-alsa
|
||||
$pkgname-utils
|
||||
$pkgname-jack
|
||||
$pkgname-zeroconf
|
||||
$pkgname-openrc
|
||||
$pkgname-bash-completion
|
||||
$pkgname-zsh-completion
|
||||
$pkgname-lang
|
||||
$pkgname-equalizer
|
||||
libpulse:_libpulse
|
||||
"
|
||||
install="pulseaudio.post-install"
|
||||
builddir="$srcdir/$pkgname-$_pkgver"
|
||||
source="https://freedesktop.org/software/pulseaudio/releases/pulseaudio-$_pkgver.tar.xz
|
||||
0001-bluez5-util-move-pa_bluetooth_discovery-to-header.patch
|
||||
0002-bluetooth-add-AT-BIA-support.patch
|
||||
0003-bluetooth-add-UPower-backend.patch
|
||||
0004-bluetooth-hook-up-UPower-backend.patch
|
||||
0005-bluetooth-add-ModemManager-backend.patch
|
||||
0006-bluetooth-only-reply-OK-for-supported-AT-cmds.patch
|
||||
0007-bluetooth-Always-reply-to-AT-CIND.patch
|
||||
0008-bluetooth-support-AT-CMEE.patch
|
||||
0009-bluetooth-support-AT-NREC.patch
|
||||
0010-bluetooth-support-AT-BCC.patch
|
||||
0011-bluetooth-support-AT-COPS.patch
|
||||
0012-bluetooth-support-AT-CNUM.patch
|
||||
0013-bluetooth-support-more-AT-CIND-indicators.patch
|
||||
0014-bluetooth-support-AT-CLIP.patch
|
||||
0015-bluetooth-support-AT-CREG.patch
|
||||
0016-bluetooth-support-AT-CGMM.patch
|
||||
0017-bluetooth-support-AT-CGMI.patch
|
||||
0018-bluetooth-support-AT-CGMR.patch
|
||||
0019-bluetooth-support-AT-CGSN.patch
|
||||
0020-bluetooth-support-AT-CLCC.patch
|
||||
0021-bluetooth-support-CIEV-RING-and-CLIP-URCs.patch
|
||||
0022-bluetooth-support-AT-VTS.patch
|
||||
0023-bluetooth-support-ATA.patch
|
||||
0024-bluetooth-support-AT-CHUP.patch
|
||||
0025-bluetooth-support-ATD-number.patch
|
||||
0026-bluetooth-strip-additional-out-of-spec-r-n-chars.patch
|
||||
link-libintl.patch
|
||||
remove-once-test.patch
|
||||
$pkgname.initd
|
||||
$pkgname.confd
|
||||
"
|
||||
|
||||
case "$CARCH" in
|
||||
x86|x86_64|aarch64)
|
||||
makedepends="$makedepends webrtc-audio-processing-dev"
|
||||
_webrtc_aec="enabled"
|
||||
;;
|
||||
* )
|
||||
_webrtc_aec="disabled" # webrtc-audio-processing not available
|
||||
;;
|
||||
esac
|
||||
|
||||
prepare() {
|
||||
default_prepare
|
||||
|
||||
sed "s|sysconfdir, 'dbus-1'|datadir, 'dbus-1'|" \
|
||||
-i src/daemon/meson.build
|
||||
}
|
||||
|
||||
build() {
|
||||
# See pma#2368
|
||||
_lto_enable="false"
|
||||
abuild-meson \
|
||||
-Db_lto="$_lto_enable" \
|
||||
-Dgcov=false \
|
||||
-Dman=true \
|
||||
-Dtests="$(want_check && echo true || echo false)" \
|
||||
-Dsystem_user=pulse \
|
||||
-Dsystem_group=pulse \
|
||||
-Ddatabase=tdb \
|
||||
-Dalsa=enabled \
|
||||
-Dasyncns=enabled \
|
||||
-Davahi=enabled \
|
||||
-Dbluez5=enabled \
|
||||
-Ddbus=enabled \
|
||||
-Dfftw=enabled \
|
||||
-Dglib=enabled \
|
||||
-Dgsettings=enabled \
|
||||
-Dgtk=enabled \
|
||||
-Dhal-compat=false \
|
||||
-Dipv6=true \
|
||||
-Djack=enabled \
|
||||
-Dlirc=disabled \
|
||||
-Dopenssl=enabled \
|
||||
-Dorc=enabled \
|
||||
-Dsamplerate=disabled \
|
||||
-Dsoxr=enabled \
|
||||
-Dspeex=enabled \
|
||||
-Dsystemd=disabled \
|
||||
-Dudev=enabled \
|
||||
-Dx11=enabled \
|
||||
-Dudevrulesdir=/usr/lib/udev/rules.d \
|
||||
-Dgstreamer=enabled \
|
||||
-Dwebrtc-aec="$_webrtc_aec" \
|
||||
-Ddoxygen=false \
|
||||
-Dstream-restore-clear-old-devices=true \
|
||||
. output
|
||||
meson compile -C output
|
||||
}
|
||||
|
||||
check() {
|
||||
XDG_RUNTIME_DIR="$(mktemp -d)" \
|
||||
meson test --no-rebuild --print-errorlogs -C output
|
||||
}
|
||||
|
||||
package() {
|
||||
DESTDIR="$pkgdir" meson install --no-rebuild -C output
|
||||
|
||||
install -Dm755 "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
|
||||
install -Dm644 "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
|
||||
|
||||
# Assumes that any volume adjustment is intended by the user, who can control
|
||||
# each app's volume. Misbehaving clients can trigger earsplitting volume
|
||||
# jumps. App volumes can diverge wildly and cause apps without their own
|
||||
# volume control to fall below sink volume; a sink-only volume control will
|
||||
# suddenly be unable to make such an app loud enough.
|
||||
sed '/flat-volumes/iflat-volumes = no' -i "$pkgdir"/etc/pulse/daemon.conf
|
||||
|
||||
# Disable cork-request module, can result in e.g. media players unpausing
|
||||
# when there's a Skype call incoming
|
||||
sed 's|/usr/bin/pactl load-module module-x11-cork-request|#&|' \
|
||||
-i "$pkgdir"/usr/bin/start-pulseaudio-x11
|
||||
|
||||
# Required by qpaeq
|
||||
sed '/Load several protocols/aload-module module-dbus-protocol' \
|
||||
-i "$pkgdir"/etc/pulse/default.pa
|
||||
}
|
||||
|
||||
openrc() {
|
||||
replaces="$pkgname-system" # Backward compatibility
|
||||
default_openrc
|
||||
}
|
||||
|
||||
_libpulse() {
|
||||
pkgdesc="Pulseaudio libraries"
|
||||
replaces="$pkgname-libs"
|
||||
|
||||
amove usr/lib/pulseaudio/libpulse*
|
||||
amove usr/lib/libpulse.so.0*
|
||||
amove usr/lib/libpulse-simple.so.0*
|
||||
amove etc/pulse/client.conf
|
||||
}
|
||||
|
||||
_libpulse_mainloop_glib() {
|
||||
pkgdesc="Pulseaudio mainloop-glib library"
|
||||
|
||||
amove usr/lib/libpulse-mainloop-glib.so.*
|
||||
}
|
||||
|
||||
bluez() {
|
||||
pkgdesc="Pulseaudio Bluetooth support"
|
||||
install_if="$pkgname=$pkgver-r$pkgrel bluez"
|
||||
provider_priority=10 # highest (other provider is pipewire-pulse)
|
||||
|
||||
amove usr/lib/pulseaudio/modules/*bluez*.so
|
||||
amove usr/lib/pulseaudio/modules/*bluetooth*.so
|
||||
}
|
||||
|
||||
alsa() {
|
||||
pkgdesc="Pulseaudio ALSA support"
|
||||
install_if="$pkgname=$pkgver-r$pkgrel alsa-lib"
|
||||
|
||||
amove usr/lib/pulseaudio/modules/*alsa*.so
|
||||
}
|
||||
|
||||
utils() {
|
||||
pkgdesc="Pulseaudio utilities"
|
||||
|
||||
amove usr/bin/pa*
|
||||
amove usr/bin/start-pulseaudio-x11
|
||||
}
|
||||
|
||||
jack() {
|
||||
pkgdesc="Pulseaudio JACK support"
|
||||
|
||||
amove usr/lib/pulseaudio/modules/*jack*.so
|
||||
}
|
||||
|
||||
zeroconf() {
|
||||
pkgdesc="Pulseaudio Zeroconf support"
|
||||
depends="avahi"
|
||||
|
||||
amove usr/lib/pulseaudio/modules/*avahi*.so
|
||||
amove usr/lib/pulseaudio/modules/*zeroconf*.so
|
||||
amove usr/lib/pulseaudio/modules/*raop*.so
|
||||
}
|
||||
|
||||
equalizer() {
|
||||
pkgdesc="Equalizer for $pkgname"
|
||||
depends="pulseaudio=$pkgver-r$pkgrel py3-qt5 py3-dbus"
|
||||
|
||||
amove usr/bin/qpaeq
|
||||
amove usr/lib/pulseaudio/modules/module-equalizer-sink.so
|
||||
}
|
||||
|
||||
sha512sums="
|
||||
33b0b4292f05e0882f3ec822cf5720414bb34c523d80fe287b9740d6be219787c562e8024c9b0d9e2ee010771ca72c7ae4f27df1bbef9c9cb6bb6a23cbcc412f pulseaudio-16.1.tar.xz
|
||||
c0a5a4854be7f8c5421671b7c5b890d9f097f8d0a1ac20009549786c28a66c9f28ac58863eea12f467ced87cbdb6093ea1a8444b9f1c1abda2aaa7e64c6c640a 0001-bluez5-util-move-pa_bluetooth_discovery-to-header.patch
|
||||
c84e4e0591c21348be197fae4b54bdd437a8e39803daa8448fcaf03119a39723214b81b8c32b5a6b166fc4449b78a44c7633bd09a77902903d15b17299a58234 0002-bluetooth-add-AT-BIA-support.patch
|
||||
a2ceac55f6cc8097569fec5e7a76f9e6ce3c79dacb27f5f19baed3a808e9be30e3c9a22b84b74e3d774d16f2d45c93e64a1248fc56b6d3cd897f620d46f581f9 0003-bluetooth-add-UPower-backend.patch
|
||||
ffe399905f400628c0bcb732c6000ced30a3835884dfd0910bebf4af81ca63e743bb144e845978fda02ec4c81295e87ccf596b55d68e4c59ff827e5b1102a72e 0004-bluetooth-hook-up-UPower-backend.patch
|
||||
58f7fc83c3c15e9df3b36cc192113d29fc6020823a36b30b68702373248a93c6e60a174a3c71c693547d33de55a9d20e72cf65f3957cea323b04c222d5d701ff 0005-bluetooth-add-ModemManager-backend.patch
|
||||
98c0b80638603899b1639fedcc5edcde721f22cd3e7abed425015c933e65769b295a80b0d6a444fc5144cd1c6851dce41710dd8361fce2bfe5022ed913ad82ba 0006-bluetooth-only-reply-OK-for-supported-AT-cmds.patch
|
||||
535b242b76fc494138a16b326708eaa4d410fbc5a779bda1471e25c56440d7e9a4c80b0bccd3ba5e0026f40c09e3b7b84bbb409e51c020deff8c9b0ead74fb71 0007-bluetooth-Always-reply-to-AT-CIND.patch
|
||||
cdd7d3d47932c11ff7bd2bd4589b26dd3d92180fd4c156e70f57dcf5b560e05cd37d548a6e5280e47d258804f9dcaa3dd498d9dcdbb2e5c4e87f9f81dc7de73a 0008-bluetooth-support-AT-CMEE.patch
|
||||
7b6a99b1d76781c36007b746bf2a47f163efeca843f36d75d4485c688d8f3a7fcafc9c36c1aa2ff02759184e20d387a89beea36ca0da64e23bb29dfc71feb55c 0009-bluetooth-support-AT-NREC.patch
|
||||
b2bda75da4a4a5a2511fd3cd9ac8da8b3c59276a6396106e2249dd31053b68797f3f923177e6cd06fd7ae3cb3e2110e8bf8facb269d80a0e637a6f38cd8bb68c 0010-bluetooth-support-AT-BCC.patch
|
||||
53bdf256fb2db1d6997204ba9504b584423946e177f8e1a819de0fafea29092a1925a0f7cde253635aa1f83c67e6b91bf3608fe543bc2185cd2ddf4aa5942054 0011-bluetooth-support-AT-COPS.patch
|
||||
f3063daac100ef5d1fba792bb900a434be8cd0f9093a9be1ab68d84b8f94f39efc16c59d749f293e9b7556632866688757dc3d6e922096102f4583acb3f3cf5a 0012-bluetooth-support-AT-CNUM.patch
|
||||
19880702e533bb46a67f09e8848bc2741a275c20b847dea96a0dba0424639715b0cd3d25a9168916cdc4ae4462b67855a3bb3b1d8384c12292fbacc032c2f0fa 0013-bluetooth-support-more-AT-CIND-indicators.patch
|
||||
cd3d67672ff77d7908b01b4a377901d5e008b31b88d0e2c86918263c10a250aaf807cbf54cc3b095b1bf38ee533b3c0f409c5e1e2ced1df045fc64f421e02f78 0014-bluetooth-support-AT-CLIP.patch
|
||||
967983f1e589945da4c0139d3d7d7be2c796f4a9ab52b344acd19723170c220dd7e00feafd2ad0a0481940f27c01176ccd54418758acedbc1c686d3426df9812 0015-bluetooth-support-AT-CREG.patch
|
||||
61c400797405120cb065dea285e79a0056d716ff5ade3c8ea5a7e9f205c6895c0885f5ddb8c1abeec08ce3cf195b79bf7dc4d20281c5f7d5ee668accddab8cb9 0016-bluetooth-support-AT-CGMM.patch
|
||||
42a3739a44bdcc01df0f3fa6fac5efb88f4fcf69686b529f8390d58b4becfd9b948d3ddea80aa5b8d007d96e22b4a87dedb5cbff610f008c317b31c8ae700774 0017-bluetooth-support-AT-CGMI.patch
|
||||
6a4cd357126ebe99647bd3f4780ca109f2e823e0653851663d1d000b98e156ac17293058c8b94263371e303233f1c8e56073b523c91588d75989acb45b660ac2 0018-bluetooth-support-AT-CGMR.patch
|
||||
b83d00a32c8e28c566e74ab8edd35e107313f31f4ff2ead21d6f9446a79f6ec520e7a737ef79844d46fbcceaad74fdaeb14ad37a865284c259f768156514f858 0019-bluetooth-support-AT-CGSN.patch
|
||||
c58265d7c8f201765a254b2b26ff38f89ac2392acfb57024592e01096a997394322e726425fd02c37e21f6ab72638206d891354b2cd950102e7c13d87e026d40 0020-bluetooth-support-AT-CLCC.patch
|
||||
c93be49e11055af356a01cc3545f984348dcff052f8777ef0127e2a9cab241fa83682550a5ffd69589d6603f1fb47ad3da248ff055b6c983e50ed817c63d1008 0021-bluetooth-support-CIEV-RING-and-CLIP-URCs.patch
|
||||
d0663f8962f916d2149f44fe6d598ddea6df3cee542ee5ba9b418d05397c88a9c16368f9da2f96750e8bfb6a8e747e59fdc10f52fa59d1096ed6e59625c5dabd 0022-bluetooth-support-AT-VTS.patch
|
||||
a39cbab500be77e88a7b8dd615ce7e1a2f8d678b19fe823552bb5d1279e2ae06aac3c353e03e10d601c53a5befe731ce00f8163c7b3a1e7b4b0c26a4fdde1730 0023-bluetooth-support-ATA.patch
|
||||
9b93fd3dd2859b600d9eed9097f89b2a26220603eccdc61c6edb9b3b7488a97dbc5cee0dd4c40da3d1cbd8849023fd48f30ea1da0668c0bae189337bc8d1db9f 0024-bluetooth-support-AT-CHUP.patch
|
||||
3eec77a1b39dbab93a4284de433946b70d6b9f972e62b02f076cb4a45b1f288e32ae05d8d557ed13ef21eded407951f9c0f48c78bdac9d47f318d2c7b288e10c 0025-bluetooth-support-ATD-number.patch
|
||||
76b486095b1f2bb5d23837ed8f08d5ac7533e7c9621b2534c85b39a932663ffcf86b7fefaba1f2abc6aa7a95660c658cbcdeef20427b8ebb6e05cf532ee48731 0026-bluetooth-strip-additional-out-of-spec-r-n-chars.patch
|
||||
2c31c5bc592e748248215f8f62f85687cfec230b05f65441e6dafa5fa77d4967e97636209b2011a4501ed1337ecd880b264baa175586fc85183a980846cb8146 link-libintl.patch
|
||||
c1223cf42538d91f31dbcb1a167537a1d3b6e8a3bf1b454cdebf95c25ca6f3b444848e9d546f092988851f71fe2c9dd9c4a781a58795e2f57d98563963a4630a remove-once-test.patch
|
||||
d3a95453361d4b12e2d4df73a72bbdc9343e2a46e8f5f3aac07b3cb1f9e016fd89816745f485468d144911900a2b38741a371f91cf08285c4b4988e4403d91a0 pulseaudio.initd
|
||||
75b54581591519d63a3362b155c0f9b0501a60763ab394693a456c44d0216138cf3a40bdd0f7442028663bc045e9ffee286f8f8eaf2ee3bb17379b43615fee0e pulseaudio.confd
|
||||
"
|
|
@ -1,30 +0,0 @@
|
|||
diff --git a/meson.build b/meson.build
|
||||
index 658eeee..349752e 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -307,6 +307,12 @@ else
|
||||
libintl_dep = cc.find_library('intl')
|
||||
endif
|
||||
|
||||
+if cc.has_function('libintl_dgettext')
|
||||
+ libintl_dep = []
|
||||
+else
|
||||
+ libintl_dep = cc.find_library('intl')
|
||||
+endif
|
||||
+
|
||||
# Symbols
|
||||
|
||||
if cc.has_header_symbol('signal.h', 'SIGXCPU')
|
||||
diff --git a/src/pulse/meson.build b/src/pulse/meson.build
|
||||
index aaebff5..3f68ac3 100644
|
||||
--- a/src/pulse/meson.build
|
||||
+++ b/src/pulse/meson.build
|
||||
@@ -84,7 +84,7 @@ libpulse = shared_library('pulse',
|
||||
dependencies : [libm_dep, thread_dep, libpulsecommon_dep, dbus_dep, dl_dep, iconv_dep, libintl_dep],
|
||||
implicit_include_directories : false)
|
||||
|
||||
-libpulse_dep = declare_dependency(link_with: libpulse)
|
||||
+libpulse_dep = declare_dependency(link_with: libpulse, dependencies: libintl_dep)
|
||||
|
||||
install_headers(
|
||||
libpulse_headers, 'simple.h',
|
|
@ -1,7 +0,0 @@
|
|||
# Config file for /etc/init.d/pulseaudio
|
||||
# $Header: /var/cvsroot/gentoo-x86/media-sound/pulseaudio/files/pulseaudio.conf.d,v 1.6 2006/07/29 15:34:18 flameeyes Exp $
|
||||
|
||||
# For more see "pulseaudio -h".
|
||||
|
||||
# Startup options
|
||||
PA_OPTS="--log-target=syslog --disallow-module-loading=1"
|
|
@ -1,81 +0,0 @@
|
|||
#!/sbin/openrc-run
|
||||
# Copyright 1999-2011 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: /var/cvsroot/gentoo-x86/media-sound/pulseaudio/files/pulseaudio.init.d-5,v 1.1 2011/03/27 16:58:49 ssuominen Exp $
|
||||
|
||||
depend() {
|
||||
need localmount
|
||||
use net
|
||||
|
||||
local script="/etc/pulse/system.pa"
|
||||
|
||||
for opt in ${PA_OPTS}; do
|
||||
case "$opt" in
|
||||
--file=*) script="${opt#*=}" ;;
|
||||
-F*) script="${opt#-F}" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
config "$script"
|
||||
|
||||
local needs="$(get_options need)"
|
||||
if [ -n "${needs}" ]; then
|
||||
need ${needs}
|
||||
return
|
||||
fi
|
||||
|
||||
if grep -E -q '^[[:space:]]*load-module[[:space:]]+module-console-kit' "$script"; then
|
||||
needs="${needs} consolekit"
|
||||
fi
|
||||
|
||||
#ifdef UDEV
|
||||
if grep -E -q '^[[:space:]]*load-module[[:space:]]+module-udev-detect' "$script"; then
|
||||
needs="${needs} udev"
|
||||
fi
|
||||
#endif
|
||||
|
||||
#ifdef AVAHI
|
||||
if grep -E -q '^[[:space:]]*load-module[[:space:]]+module-zeroconf-publish' "$script"; then
|
||||
needs="${needs} avahi-daemon"
|
||||
fi
|
||||
#endif
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
if grep -E -q '^[[:space:]]*load-module[[:space:]]+module-bt-proximity' "$script"; then
|
||||
needs="${needs} bluetooth"
|
||||
fi
|
||||
#endif
|
||||
|
||||
#ifdef ALSA
|
||||
if grep -E -q '^[[:space:]]*load-module[[:space:]]+module-alsa-(sink|source)' "$script" ||
|
||||
grep -E -q '^[[:space:]]*load-module[[:space:]]+module-(udev-)?detect' "$script" ||
|
||||
grep -E -q '^[[:space:]]*add-autoload-source[[:space:]]+(input|output)[[:space:]]+module-alsa-(sink|source)' "$script"; then
|
||||
needs="${needs} alsa" # in Alpine install alsa-utils to provide /etc/init.d/alsa (not alsasound as in Gentoo).
|
||||
fi
|
||||
#endif
|
||||
|
||||
need "${needs}"
|
||||
save_options need "${needs}"
|
||||
}
|
||||
|
||||
start() {
|
||||
if [ -z "${PULSEAUDIO_SHOULD_NOT_GO_SYSTEMWIDE}" ]; then
|
||||
eerror "Please don't use system wide PulseAudio unless you read the"
|
||||
eerror "documentation available at http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/SystemWide/"
|
||||
eerror ""
|
||||
eerror "When you're done, please set the variable PULSEAUDIO_SHOULD_NOT_GO_SYSTEMWIDE in"
|
||||
eerror "/etc/conf.d/pulseaudio . Please remember that upstream does not support this mode"
|
||||
eerror "when used for standard desktop configurations."
|
||||
return 1
|
||||
fi
|
||||
ebegin "Starting pulseaudio"
|
||||
PA_ALL_OPTS="${PA_OPTS} --fail=1 --daemonize=1 --system"
|
||||
start-stop-daemon --start --exec /usr/bin/pulseaudio -- ${PA_ALL_OPTS}
|
||||
eend $?
|
||||
}
|
||||
|
||||
stop() {
|
||||
ebegin "Stopping pulseaudio"
|
||||
start-stop-daemon --stop --quiet --exec /usr/bin/pulseaudio --pidfile /var/run/pulse/pid
|
||||
eend $?
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/sh
|
||||
# Alpine Linux post-install script for socklog
|
||||
# Copyright 2019 Leo (thinkabit.ukim@gmail.com)
|
||||
# Distributed under the terms of the GNU General Public License, v2 or later
|
||||
|
||||
addgroup -S pulse-access 2>/dev/null
|
||||
addgroup -S pulse 2>/dev/null
|
||||
|
||||
adduser -S -D -H -h /var/run/pulse -g "PulseAudio daemon" -G pulse pulse 2>/dev/null
|
||||
adduser pulse audio 2>/dev/null
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
--- a/src/tests/meson.build
|
||||
+++ b/src/tests/meson.build
|
||||
@@ -111,13 +111,6 @@
|
||||
]
|
||||
endif
|
||||
|
||||
- if host_machine.system() != 'darwin'
|
||||
- default_tests += [
|
||||
- [ 'once-test', 'once-test.c',
|
||||
- [ check_dep, thread_dep, libpulse_dep, libpulsecommon_dep, libpulsecore_dep, libatomic_ops_dep ] ],
|
||||
- ]
|
||||
- endif
|
||||
-
|
||||
if alsa_dep.found()
|
||||
default_tests += [
|
||||
[ 'alsa-mixer-path-test', 'alsa-mixer-path-test.c',
|
Loading…
Reference in a new issue