pmaports/temp/pulseaudio/0011-bluetooth-support-AT-COPS.patch

166 lines
6.9 KiB
Diff
Raw Normal View History

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