File 0003-bluetooth-add-a-new-PA_BLUETOOTH_PROFILE_HFP_AG.patch of Package pulseaudio-modules-bt

From 30210ca1e7169a6f60356479b54b80885b56ebd2 Mon Sep 17 00:00:00 2001
From: Faidon Liambotis <paravoid@debian.org>
Date: Mon, 5 Aug 2019 18:26:43 +0200
Subject: [PATCH 3/9] bluetooth: add a new PA_BLUETOOTH_PROFILE_HFP_AG

Add a new, currently unused profile for HFP AG, duplicating HSP AG, but
keeping it separate and distinct from each other.

Signed-off-by: Faidon Liambotis <paravoid@debian.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 src/modules/bluetooth/bluez5-util.c           |  9 ++-
 src/modules/bluetooth/bluez5-util.h           |  1 +
 .../bluetooth/module-bluetooth-policy.c       | 10 ++-
 src/modules/bluetooth/module-bluez5-device.c  | 69 ++++++++++++++-----
 4 files changed, 64 insertions(+), 25 deletions(-)

diff --git a/src/modules/bluetooth/bluez5-util.c b/src/modules/bluetooth/bluez5-util.c
index 926947ccb4ae..7201f9b26182 100644
--- a/src/modules/bluetooth/bluez5-util.c
+++ b/src/modules/bluetooth/bluez5-util.c
@@ -201,8 +201,9 @@ static bool device_supports_profile(pa_bluetooth_device *device, pa_bluetooth_pr
         case PA_BLUETOOTH_PROFILE_HFP_HF:
             return show_hfp && !!pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HFP_HF);
         case PA_BLUETOOTH_PROFILE_HSP_AG:
-            return !!pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HSP_AG)
-                || !!pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HFP_AG);
+            return !!pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HSP_AG);
+        case PA_BLUETOOTH_PROFILE_HFP_AG:
+            return !!pa_hashmap_get(device->uuids, PA_BLUETOOTH_UUID_HFP_AG);
         case PA_BLUETOOTH_PROFILE_OFF:
             pa_assert_not_reached();
     }
@@ -1361,7 +1362,7 @@ void pa_bluetooth_discovery_set_ofono_running(pa_bluetooth_discovery *y, bool is
         pa_bluetooth_device *d;
 
         PA_HASHMAP_FOREACH(d, y->devices, state) {
-            if (device_supports_profile(d, PA_BLUETOOTH_PROFILE_HSP_AG)) {
+            if (device_supports_profile(d, PA_BLUETOOTH_PROFILE_HFP_AG)) {
                 DBusMessage *m;
 
                 pa_assert_se(m = dbus_message_new_method_call(BLUEZ_SERVICE, d->path, "org.bluez.Device1", "Disconnect"));
@@ -1614,6 +1615,8 @@ const char *pa_bluetooth_profile_to_string(pa_bluetooth_profile_t profile) {
             return "headset_audio_gateway";
         case PA_BLUETOOTH_PROFILE_HFP_HF:
             return "handsfree";
+        case PA_BLUETOOTH_PROFILE_HFP_AG:
+            return "handsfree_audio_gateway";
         case PA_BLUETOOTH_PROFILE_OFF:
             return "off";
     }
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
index 0c57b04c4785..e0598cf2ada8 100644
--- a/src/modules/bluetooth/bluez5-util.h
+++ b/src/modules/bluetooth/bluez5-util.h
@@ -61,6 +61,7 @@ typedef enum profile {
     PA_BLUETOOTH_PROFILE_HSP_HS,
     PA_BLUETOOTH_PROFILE_HSP_AG,
     PA_BLUETOOTH_PROFILE_HFP_HF,
+    PA_BLUETOOTH_PROFILE_HFP_AG,
     PA_BLUETOOTH_PROFILE_OFF
 } pa_bluetooth_profile_t;
 #define PA_BLUETOOTH_PROFILE_COUNT PA_BLUETOOTH_PROFILE_OFF
diff --git a/src/modules/bluetooth/module-bluetooth-policy.c b/src/modules/bluetooth/module-bluetooth-policy.c
index 20f8b8f490a8..d431c3e027a1 100644
--- a/src/modules/bluetooth/module-bluetooth-policy.c
+++ b/src/modules/bluetooth/module-bluetooth-policy.c
@@ -42,7 +42,7 @@ PA_MODULE_LOAD_ONCE(true);
 PA_MODULE_USAGE(
         "auto_switch=<Switch between HFP/HSP and A2DP profile? (0 - never, 1 - media.role=phone, 2 - heuristic> "
         "a2dp_source=<Handle a2dp_source card profile (sink role)?> "
-        "ag=<Handle headset_audio_gateway card profile (headset role)?> ");
+        "ag=<Handle audio gateway card profile (headset role)?> ");
 
 static const char* const valid_modargs[] = {
     "auto_switch",
@@ -92,7 +92,9 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
 
     if (u->enable_a2dp_source && pa_bt_prefix_eq(s, "a2dp_source"))
         role = "music";
-    else if (u->enable_ag && pa_streq(s, "headset_audio_gateway"))
+    else if (u->enable_ag &&
+             (pa_streq(s, "headset_audio_gateway") ||
+              pa_streq(s, "handsfree_audio_gateway")))
         role = "phone";
     else {
         pa_log_debug("Profile %s cannot be selected for loopback", s);
@@ -131,7 +133,9 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void *
     if (!s)
         return PA_HOOK_OK;
 
-    if (u->enable_ag && pa_streq(s, "headset_audio_gateway"))
+    if (u->enable_ag &&
+        (pa_streq(s, "headset_audio_gateway") ||
+         pa_streq(s, "handsfree_audio_gateway")))
         role = "phone";
     else {
         pa_log_debug("Profile %s cannot be selected for loopback", s);
diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
index 41fb83985e09..d7073dd9ec79 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -263,7 +263,8 @@ static int sco_process_render(struct userdata *u) {
     pa_assert(u);
     pa_assert(u->profile == PA_BLUETOOTH_PROFILE_HSP_HS ||
               u->profile == PA_BLUETOOTH_PROFILE_HSP_AG ||
-              u->profile == PA_BLUETOOTH_PROFILE_HFP_HF);
+              u->profile == PA_BLUETOOTH_PROFILE_HFP_HF ||
+              u->profile == PA_BLUETOOTH_PROFILE_HFP_AG);
     pa_assert(u->sink);
 
     pa_sink_render_full(u->sink, u->write_block_size, &memchunk);
@@ -334,7 +335,8 @@ static int sco_process_push(struct userdata *u) {
     pa_assert(u);
     pa_assert(u->profile == PA_BLUETOOTH_PROFILE_HSP_HS ||
               u->profile == PA_BLUETOOTH_PROFILE_HSP_AG ||
-              u->profile == PA_BLUETOOTH_PROFILE_HFP_HF);
+              u->profile == PA_BLUETOOTH_PROFILE_HFP_HF ||
+              u->profile == PA_BLUETOOTH_PROFILE_HFP_AG);
     pa_assert(u->source);
     pa_assert(u->read_smoother);
 
@@ -729,7 +731,8 @@ static void transport_release(struct userdata *u) {
 static void transport_config_mtu(struct userdata *u) {
     if (u->profile == PA_BLUETOOTH_PROFILE_HSP_HS
         || u->profile == PA_BLUETOOTH_PROFILE_HSP_AG
-        || u->profile == PA_BLUETOOTH_PROFILE_HFP_HF) {
+        || u->profile == PA_BLUETOOTH_PROFILE_HFP_HF
+        || u->profile == PA_BLUETOOTH_PROFILE_HFP_AG) {
         u->read_block_size = u->read_link_mtu;
         u->write_block_size = u->write_link_mtu;
 
@@ -943,7 +946,8 @@ static void source_set_volume_cb(pa_source *s) {
     pa_cvolume_set(&s->real_volume, u->sample_spec.channels, volume);
 
     /* Set soft volume when in headset role */
-    if (u->profile == PA_BLUETOOTH_PROFILE_HSP_AG)
+    if (u->profile == PA_BLUETOOTH_PROFILE_HSP_AG ||
+        u->profile == PA_BLUETOOTH_PROFILE_HFP_AG)
         pa_cvolume_set(&s->soft_volume, u->sample_spec.channels, volume);
 
     /* If we are in the AG role, we send a command to the head set to change
@@ -976,6 +980,7 @@ static int add_source(struct userdata *u) {
         switch (u->profile) {
             case PA_BLUETOOTH_PROFILE_A2DP_SOURCE:
             case PA_BLUETOOTH_PROFILE_HSP_AG:
+            case PA_BLUETOOTH_PROFILE_HFP_AG:
                 data.suspend_cause = PA_SUSPEND_USER;
                 break;
             case PA_BLUETOOTH_PROFILE_HSP_HS:
@@ -1008,7 +1013,8 @@ static int add_source(struct userdata *u) {
 
     if (u->profile == PA_BLUETOOTH_PROFILE_HSP_HS
         || u->profile == PA_BLUETOOTH_PROFILE_HSP_AG
-        || u->profile == PA_BLUETOOTH_PROFILE_HFP_HF) {
+        || u->profile == PA_BLUETOOTH_PROFILE_HFP_HF
+        || u->profile == PA_BLUETOOTH_PROFILE_HFP_AG) {
         pa_source_set_set_volume_callback(u->source, source_set_volume_cb);
         u->source->n_volume_steps = 16;
     }
@@ -1123,7 +1129,8 @@ static void sink_set_volume_cb(pa_sink *s) {
     pa_cvolume_set(&s->real_volume, u->sample_spec.channels, volume);
 
     /* Set soft volume when in headset role */
-    if (u->profile == PA_BLUETOOTH_PROFILE_HSP_AG)
+    if (u->profile == PA_BLUETOOTH_PROFILE_HSP_AG ||
+        u->profile == PA_BLUETOOTH_PROFILE_HFP_AG)
         pa_cvolume_set(&s->soft_volume, u->sample_spec.channels, volume);
 
     /* If we are in the AG role, we send a command to the head set to change
@@ -1155,6 +1162,7 @@ static int add_sink(struct userdata *u) {
     if (!u->transport_acquired)
         switch (u->profile) {
             case PA_BLUETOOTH_PROFILE_HSP_AG:
+            case PA_BLUETOOTH_PROFILE_HFP_AG:
                 data.suspend_cause = PA_SUSPEND_USER;
                 break;
             case PA_BLUETOOTH_PROFILE_HSP_HS:
@@ -1190,7 +1198,8 @@ static int add_sink(struct userdata *u) {
 
     if (u->profile == PA_BLUETOOTH_PROFILE_HSP_HS
         || u->profile == PA_BLUETOOTH_PROFILE_HSP_AG
-        || u->profile == PA_BLUETOOTH_PROFILE_HFP_HF) {
+        || u->profile == PA_BLUETOOTH_PROFILE_HFP_HF
+        || u->profile == PA_BLUETOOTH_PROFILE_HFP_AG) {
         pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
         u->sink->n_volume_steps = 16;
     }
@@ -1201,7 +1210,8 @@ static int add_sink(struct userdata *u) {
 static void transport_config(struct userdata *u) {
     if (u->profile == PA_BLUETOOTH_PROFILE_HSP_HS
         || u->profile == PA_BLUETOOTH_PROFILE_HSP_AG
-        || u->profile == PA_BLUETOOTH_PROFILE_HFP_HF) {
+        || u->profile == PA_BLUETOOTH_PROFILE_HFP_HF
+        || u->profile == PA_BLUETOOTH_PROFILE_HFP_AG) {
         u->sample_spec.format = PA_SAMPLE_S16LE;
         u->sample_spec.channels = 1;
         u->sample_spec.rate = 8000;
@@ -1267,9 +1277,11 @@ static int setup_transport(struct userdata *u) {
 
     u->transport = t;
 
-    if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SOURCE || u->profile == PA_BLUETOOTH_PROFILE_HSP_AG)
+    if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SOURCE ||
+        u->profile == PA_BLUETOOTH_PROFILE_HSP_AG ||
+        u->profile == PA_BLUETOOTH_PROFILE_HFP_AG) {
         transport_acquire(u, true); /* In case of error, the sink/sources will be created suspended */
-    else {
+    } else {
         int transport_error;
 
         transport_error = transport_acquire(u, false);
@@ -1290,6 +1302,7 @@ static pa_direction_t get_profile_direction(pa_bluetooth_profile_t p) {
         [PA_BLUETOOTH_PROFILE_HSP_HS] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT,
         [PA_BLUETOOTH_PROFILE_HSP_AG] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT,
         [PA_BLUETOOTH_PROFILE_HFP_HF] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT,
+        [PA_BLUETOOTH_PROFILE_HFP_AG] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT,
         [PA_BLUETOOTH_PROFILE_OFF] = 0
     };
 
@@ -1623,7 +1636,8 @@ static int start_thread(struct userdata *u) {
 
         /* If we are in the headset role, the sink should not become default
          * unless there is no other sound device available. */
-        if (u->profile == PA_BLUETOOTH_PROFILE_HSP_AG)
+        if (u->profile == PA_BLUETOOTH_PROFILE_HSP_AG ||
+            u->profile == PA_BLUETOOTH_PROFILE_HFP_AG)
             u->sink->priority = 1500;
 
         pa_sink_put(u->sink);
@@ -1639,7 +1653,9 @@ static int start_thread(struct userdata *u) {
         /* If we are in the headset role or the device is an a2dp source,
          * the source should not become default unless there is no other
          * sound device available. */
-        if (u->profile == PA_BLUETOOTH_PROFILE_HSP_AG || u->profile == PA_BLUETOOTH_PROFILE_A2DP_SOURCE)
+        if (u->profile == PA_BLUETOOTH_PROFILE_HSP_AG ||
+            u->profile == PA_BLUETOOTH_PROFILE_HFP_AG ||
+            u->profile == PA_BLUETOOTH_PROFILE_A2DP_SOURCE)
             u->source->priority = 1500;
 
         pa_source_put(u->source);
@@ -1923,8 +1939,8 @@ static pa_card_profile *create_card_profile(struct userdata *u, pa_bluetooth_pro
         p_info = PA_CARD_PROFILE_DATA(cp);
         break;
 
-    case PA_BLUETOOTH_PROFILE_HSP_HS:
-        cp = pa_card_profile_new(name, _("Headset Head Unit (HSP)"), sizeof(pa_bluetooth_profile_info_t));
+    case PA_BLUETOOTH_PROFILE_HFP_HF:
+        cp = pa_card_profile_new(name, _("Handsfree (HFP)"), sizeof(pa_bluetooth_profile_info_t));
         cp->priority = 30;
         cp->n_sinks = 1;
         cp->n_sources = 1;
@@ -1936,8 +1952,8 @@ static pa_card_profile *create_card_profile(struct userdata *u, pa_bluetooth_pro
         p_info = PA_CARD_PROFILE_DATA(cp);
         break;
 
-    case PA_BLUETOOTH_PROFILE_HFP_HF:
-        cp = pa_card_profile_new(name, _("Handsfree (HFP)"), sizeof(pa_bluetooth_profile_info_t));
+    case PA_BLUETOOTH_PROFILE_HSP_HS:
+        cp = pa_card_profile_new(name, _("Headset (HSP)"), sizeof(pa_bluetooth_profile_info_t));
         cp->priority = 30;
         cp->n_sinks = 1;
         cp->n_sources = 1;
@@ -1949,8 +1965,21 @@ static pa_card_profile *create_card_profile(struct userdata *u, pa_bluetooth_pro
         p_info = PA_CARD_PROFILE_DATA(cp);
         break;
 
+    case PA_BLUETOOTH_PROFILE_HFP_AG:
+        cp = pa_card_profile_new(name, _("Handsfree Audio Gateway (HFP)"), sizeof(pa_bluetooth_profile_info_t));
+        cp->priority = 10;
+        cp->n_sinks = 1;
+        cp->n_sources = 1;
+        cp->max_sink_channels = 1;
+        cp->max_source_channels = 1;
+        pa_hashmap_put(input_port->profiles, cp->name, cp);
+        pa_hashmap_put(output_port->profiles, cp->name, cp);
+
+        p_info = PA_CARD_PROFILE_DATA(cp);
+        break;
+
     case PA_BLUETOOTH_PROFILE_HSP_AG:
-        cp = pa_card_profile_new(name, _("Headset Audio Gateway (HSP/HFP)"), sizeof(pa_bluetooth_profile_info_t));
+        cp = pa_card_profile_new(name, _("Headset Audio Gateway (HSP)"), sizeof(pa_bluetooth_profile_info_t));
         cp->priority = 10;
         cp->n_sinks = 1;
         cp->n_sources = 1;
@@ -2063,10 +2092,12 @@ static int uuid_to_profile(const char *uuid, pa_bluetooth_profile_t *_r) {
         *_r = PA_BLUETOOTH_PROFILE_A2DP_SOURCE;
     else if (pa_bluetooth_uuid_is_hsp_hs(uuid))
         *_r = PA_BLUETOOTH_PROFILE_HSP_HS;
+    else if (pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_AG))
+        *_r = PA_BLUETOOTH_PROFILE_HSP_AG;
     else if (pa_streq(uuid, PA_BLUETOOTH_UUID_HFP_HF))
         *_r = PA_BLUETOOTH_PROFILE_HFP_HF;
-    else if (pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_AG) || pa_streq(uuid, PA_BLUETOOTH_UUID_HFP_AG))
-        *_r = PA_BLUETOOTH_PROFILE_HSP_AG;
+    else if (pa_streq(uuid, PA_BLUETOOTH_UUID_HFP_AG))
+        *_r = PA_BLUETOOTH_PROFILE_HFP_AG;
     else
         return -PA_ERR_INVALID;
 
-- 
2.26.2

openSUSE Build Service is sponsored by