198 lines
8.2 KiB
Diff
198 lines
8.2 KiB
Diff
|
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
|
||
|
|