[pulseaudio-commits] 6 commits - configure.ac src/modules src/pulse src/pulsecore src/tests

Arun Raghavan arun at kemper.freedesktop.org
Thu Oct 30 22:20:13 PDT 2014


 configure.ac                                 |    6 
 src/modules/bluetooth/backend-native.c       |  501 +++++++++++++++++++++++++++
 src/modules/bluetooth/bluez5-util.c          |    2 
 src/modules/bluetooth/bluez5-util.h          |   11 
 src/modules/bluetooth/module-bluez5-device.c |  172 ++++++++-
 src/modules/module-tunnel.c                  |    4 
 src/pulse/context.c                          |    4 
 src/pulsecore/creds.h                        |   10 
 src/pulsecore/iochannel.c                    |   32 -
 src/pulsecore/iochannel.h                    |    2 
 src/pulsecore/pdispatch.c                    |   18 
 src/pulsecore/pdispatch.h                    |    2 
 src/pulsecore/protocol-native.c              |    4 
 src/pulsecore/pstream-util.c                 |   20 -
 src/pulsecore/pstream.c                      |   62 +--
 src/pulsecore/pstream.h                      |    4 
 src/tests/srbchannel-test.c                  |    2 
 17 files changed, 754 insertions(+), 102 deletions(-)

New commits:
commit 5dfa83385c457766954d40d8998eda028ed7d57b
Author: Arun Raghavan <arun at accosted.net>
Date:   Fri Oct 31 10:15:02 2014 +0530

    bluetooth: Fix some native backend command sending
    
    We weren't writing out one character from the "OK" response, and the
    "AT" part of the "+VGS" and "+VGM" commands was missing. Also, the spec
    says that the command is terminated by only a CR and not an LF (probably
    doesn't hurt, but let's adhere to the spec for now).

diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
index aa2b756..a9dc64c 100644
--- a/src/modules/bluetooth/backend-native.c
+++ b/src/modules/bluetooth/backend-native.c
@@ -248,7 +248,7 @@ static void rfcomm_io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_i
 
         pa_log_debug("RFCOMM >> OK");
 
-        len = write(fd, "\r\nOK\r\n", 5);
+        len = write(fd, "\r\nOK\r\n", 6);
 
         /* we ignore any errors, it's not critical and real errors should
          * be caught with the HANGUP and ERROR events handled above */
@@ -285,8 +285,8 @@ static void set_speaker_gain(pa_bluetooth_transport *t, uint16_t gain) {
 
     t->speaker_gain = gain;
 
-    len = sprintf(buf, "+VGS=%d\r\n", gain);
-    pa_log_debug("RFCOMM >> +VGS=%d", gain);
+    len = sprintf(buf, "AT+VGS=%d\r", gain);
+    pa_log_debug("RFCOMM >> AT+VGS=%d", gain);
 
     written = write(trfc->rfcomm_fd, buf, len);
 
@@ -304,8 +304,8 @@ static void set_microphone_gain(pa_bluetooth_transport *t, uint16_t gain) {
 
     t->microphone_gain = gain;
 
-    len = sprintf(buf, "+VGM=%d\r\n", gain);
-    pa_log_debug("RFCOMM >> +VGM=%d", gain);
+    len = sprintf(buf, "AT+VGM=%d\r", gain);
+    pa_log_debug("RFCOMM >> AT+VGM=%d", gain);
 
     written = write (trfc->rfcomm_fd, buf, len);
 

commit 34a5c754a90e46168c8a540ee13d9289dfb31247
Author: Wim Taymans <wim.taymans at gmail.com>
Date:   Fri Oct 24 09:56:52 2014 +0200

    backend-native: implement volume control
    
    Parse the gain changed AT commands from the headset and fire 2 new
    hooks as a result. The device will connect to those hooks and change the
    source/sink volumes.
    
    When the source/sink volume changes, set the gain on the microphone or
    speaker respectively. Make sure we do nothing if the transport can not
    handle the gain changes.

diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
index db9bce9..aa2b756 100644
--- a/src/modules/bluetooth/backend-native.c
+++ b/src/modules/bluetooth/backend-native.c
@@ -114,6 +114,7 @@ static int bluez5_sco_acquire_cb(pa_bluetooth_transport *t, bool optional, size_
     src_addr = d->adapter->address;
     dst_addr = d->address;
 
+    /* don't use ba2str to avoid -lbluetooth */
     for (i = 5; i >= 0; i--, src_addr += 3)
         src.b[i] = strtol(src_addr, NULL, 16);
     for (i = 5; i >= 0; i--, dst_addr += 3)
@@ -230,13 +231,25 @@ 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];
         ssize_t len;
+        int gain;
 
         len = read(fd, buf, 511);
         buf[len] = 0;
         pa_log_debug("RFCOMM << %s", buf);
 
+        if (sscanf(buf, "AT+VGS=%d", &gain) == 1) {
+          t->speaker_gain = gain;
+          pa_hook_fire(pa_bluetooth_discovery_hook(t->device->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_SPEAKER_GAIN_CHANGED), t);
+
+        } else if (sscanf(buf, "AT+VGM=%d", &gain) == 1) {
+          t->microphone_gain = gain;
+          pa_hook_fire(pa_bluetooth_discovery_hook(t->device->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_MICROPHONE_GAIN_CHANGED), t);
+        }
+
         pa_log_debug("RFCOMM >> OK");
-        len = write (fd, "\r\nOK\r\n", 5);
+
+        len = write(fd, "\r\nOK\r\n", 5);
+
         /* we ignore any errors, it's not critical and real errors should
          * be caught with the HANGUP and ERROR events handled above */
         if (len < 0)
@@ -262,6 +275,44 @@ static void transport_destroy(pa_bluetooth_transport *t) {
     pa_xfree(trfc);
 }
 
+static void set_speaker_gain(pa_bluetooth_transport *t, uint16_t gain) {
+    struct transport_rfcomm *trfc = t->userdata;
+    char buf[512];
+    ssize_t len, written;
+
+    if (t->speaker_gain == gain)
+      return;
+
+    t->speaker_gain = gain;
+
+    len = sprintf(buf, "+VGS=%d\r\n", gain);
+    pa_log_debug("RFCOMM >> +VGS=%d", gain);
+
+    written = write(trfc->rfcomm_fd, buf, len);
+
+    if (written != len)
+        pa_log_error("RFCOMM write error: %s", pa_cstrerror(errno));
+}
+
+static void set_microphone_gain(pa_bluetooth_transport *t, uint16_t gain) {
+    struct transport_rfcomm *trfc = t->userdata;
+    char buf[512];
+    ssize_t len, written;
+
+    if (t->microphone_gain == gain)
+      return;
+
+    t->microphone_gain = gain;
+
+    len = sprintf(buf, "+VGM=%d\r\n", gain);
+    pa_log_debug("RFCOMM >> +VGM=%d", gain);
+
+    written = write (trfc->rfcomm_fd, buf, len);
+
+    if (written != len)
+        pa_log_error("RFCOMM write error: %s", pa_cstrerror(errno));
+}
+
 static DBusMessage *profile_new_connection(DBusConnection *conn, DBusMessage *m, void *userdata) {
     pa_bluetooth_backend *b = userdata;
     pa_bluetooth_device *d;
@@ -308,6 +359,8 @@ static DBusMessage *profile_new_connection(DBusConnection *conn, DBusMessage *m,
     t->acquire = bluez5_sco_acquire_cb;
     t->release = bluez5_sco_release_cb;
     t->destroy = transport_destroy;
+    t->set_speaker_gain = set_speaker_gain;
+    t->set_microphone_gain = set_microphone_gain;
 
     trfc = pa_xnew0(struct transport_rfcomm, 1);
     trfc->rfcomm_fd = fd;
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
index 1a8a364..3ef0ac8 100644
--- a/src/modules/bluetooth/bluez5-util.h
+++ b/src/modules/bluetooth/bluez5-util.h
@@ -40,6 +40,8 @@ typedef struct pa_bluetooth_backend pa_bluetooth_backend;
 typedef enum pa_bluetooth_hook {
     PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED,          /* Call data: pa_bluetooth_device */
     PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED,            /* Call data: pa_bluetooth_transport */
+    PA_BLUETOOTH_HOOK_TRANSPORT_MICROPHONE_GAIN_CHANGED,  /* Call data: pa_bluetooth_transport */
+    PA_BLUETOOTH_HOOK_TRANSPORT_SPEAKER_GAIN_CHANGED,     /* Call data: pa_bluetooth_transport */
     PA_BLUETOOTH_HOOK_MAX
 } pa_bluetooth_hook_t;
 
@@ -61,6 +63,8 @@ typedef enum pa_bluetooth_transport_state {
 typedef int (*pa_bluetooth_transport_acquire_cb)(pa_bluetooth_transport *t, bool optional, size_t *imtu, size_t *omtu);
 typedef void (*pa_bluetooth_transport_release_cb)(pa_bluetooth_transport *t);
 typedef void (*pa_bluetooth_transport_destroy_cb)(pa_bluetooth_transport *t);
+typedef void (*pa_bluetooth_transport_set_speaker_gain_cb)(pa_bluetooth_transport *t, uint16_t gain);
+typedef void (*pa_bluetooth_transport_set_microphone_gain_cb)(pa_bluetooth_transport *t, uint16_t gain);
 
 struct pa_bluetooth_transport {
     pa_bluetooth_device *device;
@@ -73,11 +77,16 @@ struct pa_bluetooth_transport {
     uint8_t *config;
     size_t config_size;
 
+    uint16_t microphone_gain;
+    uint16_t speaker_gain;
+
     pa_bluetooth_transport_state_t state;
 
     pa_bluetooth_transport_acquire_cb acquire;
     pa_bluetooth_transport_release_cb release;
     pa_bluetooth_transport_destroy_cb destroy;
+    pa_bluetooth_transport_set_speaker_gain_cb set_speaker_gain;
+    pa_bluetooth_transport_set_microphone_gain_cb set_microphone_gain;
     void *userdata;
 };
 
diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
index 15731d1..d077161 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -66,6 +66,7 @@ PA_MODULE_USAGE("path=<device object path>");
 
 #define BITPOOL_DEC_LIMIT 32
 #define BITPOOL_DEC_STEP 5
+#define HSP_MAX_GAIN 15
 
 static const char* const valid_modargs[] = {
     "path",
@@ -103,6 +104,8 @@ struct userdata {
 
     pa_hook_slot *device_connection_changed_slot;
     pa_hook_slot *transport_state_changed_slot;
+    pa_hook_slot *transport_speaker_gain_changed_slot;
+    pa_hook_slot *transport_microphone_gain_changed_slot;
 
     pa_bluetooth_discovery *discovery;
     pa_bluetooth_device *device;
@@ -903,6 +906,40 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
 }
 
 /* Run from main thread */
+static void source_set_volume_cb(pa_source *s) {
+    uint16_t gain;
+    pa_volume_t volume;
+    struct userdata *u;
+
+    pa_assert(s);
+    pa_assert(s->core);
+
+    u = s->userdata;
+
+    pa_assert(u);
+    pa_assert(u->source == s);
+    pa_assert(u->profile == PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT);
+
+    if (u->transport->set_microphone_gain == NULL)
+      return;
+
+    gain = (pa_cvolume_max(&s->real_volume) * HSP_MAX_GAIN) / PA_VOLUME_NORM;
+
+    if (gain > HSP_MAX_GAIN)
+        gain = HSP_MAX_GAIN;
+
+    volume = (pa_volume_t) (gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
+
+    /* increment volume by one to correct rounding errors */
+    if (volume < PA_VOLUME_NORM)
+        volume++;
+
+    pa_cvolume_set(&s->real_volume, u->sample_spec.channels, volume);
+
+    u->transport->set_microphone_gain(u->transport, gain);
+}
+
+/* Run from main thread */
 static int add_source(struct userdata *u) {
     pa_source_new_data data;
 
@@ -944,6 +981,10 @@ static int add_source(struct userdata *u) {
     u->source->userdata = u;
     u->source->parent.process_msg = source_process_msg;
 
+    if (u->profile == PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT) {
+        pa_source_set_set_volume_callback(u->source, source_set_volume_cb);
+        u->source->n_volume_steps = 16;
+    }
     return 0;
 }
 
@@ -1022,6 +1063,40 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 }
 
 /* Run from main thread */
+static void sink_set_volume_cb(pa_sink *s) {
+    uint16_t gain;
+    pa_volume_t volume;
+    struct userdata *u;
+
+    pa_assert(s);
+    pa_assert(s->core);
+
+    u = s->userdata;
+
+    pa_assert(u);
+    pa_assert(u->sink == s);
+    pa_assert(u->profile == PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT);
+
+    if (u->transport->set_speaker_gain == NULL)
+      return;
+
+    gain = (pa_cvolume_max(&s->real_volume) * HSP_MAX_GAIN) / PA_VOLUME_NORM;
+
+    if (gain > HSP_MAX_GAIN)
+        gain = HSP_MAX_GAIN;
+
+    volume = (pa_volume_t) (gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
+
+    /* increment volume by one to correct rounding errors */
+    if (volume < PA_VOLUME_NORM)
+        volume++;
+
+    pa_cvolume_set(&s->real_volume, u->sample_spec.channels, volume);
+
+    u->transport->set_speaker_gain(u->transport, gain);
+}
+
+/* Run from main thread */
 static int add_sink(struct userdata *u) {
     pa_sink_new_data data;
 
@@ -1064,6 +1139,10 @@ static int add_sink(struct userdata *u) {
     u->sink->userdata = u;
     u->sink->parent.process_msg = sink_process_msg;
 
+    if (u->profile == PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT) {
+        pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
+        u->sink->n_volume_steps = 16;
+    }
     return 0;
 }
 
@@ -1975,6 +2054,54 @@ static pa_hook_result_t transport_state_changed_cb(pa_bluetooth_discovery *y, pa
     return PA_HOOK_OK;
 }
 
+static pa_hook_result_t transport_speaker_gain_changed_cb(pa_bluetooth_discovery *y, pa_bluetooth_transport *t, struct userdata *u) {
+    pa_volume_t volume;
+    pa_cvolume v;
+    uint16_t gain;
+
+    pa_assert(t);
+    pa_assert(u);
+
+    if (t != u->transport)
+      return PA_HOOK_OK;
+
+    gain = t->speaker_gain;
+    volume = (pa_volume_t) (gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
+
+    /* increment volume by one to correct rounding errors */
+    if (volume < PA_VOLUME_NORM)
+        volume++;
+
+    pa_cvolume_set(&v, u->sample_spec.channels, volume);
+    pa_sink_volume_changed(u->sink, &v);
+
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t transport_microphone_gain_changed_cb(pa_bluetooth_discovery *y, pa_bluetooth_transport *t, struct userdata *u) {
+    pa_volume_t volume;
+    pa_cvolume v;
+    uint16_t gain;
+
+    pa_assert(t);
+    pa_assert(u);
+
+    if (t != u->transport)
+      return PA_HOOK_OK;
+
+    gain = t->microphone_gain;
+    volume = (pa_volume_t) (gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
+
+    /* increment volume by one to correct rounding errors */
+    if (volume < PA_VOLUME_NORM)
+        volume++;
+
+    pa_cvolume_set(&v, u->sample_spec.channels, volume);
+    pa_source_volume_changed(u->source, &v);
+
+    return PA_HOOK_OK;
+}
+
 /* Run from main thread context */
 static int device_process_msg(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
     struct bluetooth_msg *m = BLUETOOTH_MSG(obj);
@@ -2039,6 +2166,13 @@ int pa__init(pa_module* m) {
         pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED),
                         PA_HOOK_NORMAL, (pa_hook_cb_t) transport_state_changed_cb, u);
 
+    u->transport_speaker_gain_changed_slot =
+        pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_SPEAKER_GAIN_CHANGED), PA_HOOK_NORMAL, (pa_hook_cb_t) transport_speaker_gain_changed_cb, u);
+
+    u->transport_microphone_gain_changed_slot =
+        pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_MICROPHONE_GAIN_CHANGED), PA_HOOK_NORMAL, (pa_hook_cb_t) transport_microphone_gain_changed_cb, u);
+
+
     if (add_card(u) < 0)
         goto fail;
 
@@ -2091,6 +2225,12 @@ void pa__done(pa_module *m) {
     if (u->transport_state_changed_slot)
         pa_hook_slot_free(u->transport_state_changed_slot);
 
+    if (u->transport_speaker_gain_changed_slot)
+        pa_hook_slot_free(u->transport_speaker_gain_changed_slot);
+
+    if (u->transport_microphone_gain_changed_slot)
+        pa_hook_slot_free(u->transport_microphone_gain_changed_slot);
+
     if (u->sbc_info.buffer)
         pa_xfree(u->sbc_info.buffer);
 

commit 7d4a497b3db6e3c58fb5fe64131c8f81cade85b7
Author: Wim Taymans <wim.taymans at gmail.com>
Date:   Fri Oct 24 09:56:51 2014 +0200

    backend-native: add a new native headset backend
    
    Add a simple native headset backend that implements support for the
    blutooth HSP profile.
    This allows pulseaudio to output audio to a Headset using the HSP profile.
    
    Make the native backend the default.

diff --git a/configure.ac b/configure.ac
index f807699..f165eb4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1036,14 +1036,14 @@ AM_CONDITIONAL([HAVE_BLUEZ], [test "x$HAVE_BLUEZ" = x1])
 ## Bluetooth Headset profiles backend ##
 
 AC_ARG_WITH(bluetooth_headset_backend,
-    AS_HELP_STRING([--with-bluetooth-headset-backend=<ofono|null>],[Backend for Bluetooth headset profiles (ofono)]))
+    AS_HELP_STRING([--with-bluetooth-headset-backend=<ofono|native|null>],[Backend for Bluetooth headset profiles (native)]))
 if test -z "$with_bluetooth_headset_backend" ; then
-    BLUETOOTH_HEADSET_BACKEND=ofono
+    BLUETOOTH_HEADSET_BACKEND=native
 else
     BLUETOOTH_HEADSET_BACKEND=$with_bluetooth_headset_backend
 fi
 
-AS_IF([test "x$BLUETOOTH_HEADSET_BACKEND" != "xofono" && test "x$BLUETOOTH_HEADSET_BACKEND" != "xnull"],
+AS_IF([test "x$BLUETOOTH_HEADSET_BACKEND" != "xofono" && test "x$BLUETOOTH_HEADSET_BACKEND" != "xnull" && test "x$BLUETOOTH_HEADSET_BACKEND" != "xnative"],
     [AC_MSG_ERROR([*** Invalid Bluetooth Headset backend])])
 
 AC_SUBST(BLUETOOTH_HEADSET_BACKEND)
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
new file mode 100644
index 0000000..db9bce9
--- /dev/null
+++ b/src/modules/bluetooth/backend-native.c
@@ -0,0 +1,448 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2014 Wim Taymans <wim.taymans at gmail.com>
+
+  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, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulsecore/shared.h>
+#include <pulsecore/core-error.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/dbus-shared.h>
+#include <pulsecore/log.h>
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sco.h>
+
+#include "bluez5-util.h"
+
+struct pa_bluetooth_backend {
+  pa_core *core;
+  pa_dbus_connection *connection;
+  pa_bluetooth_discovery *discovery;
+
+  PA_LLIST_HEAD(pa_dbus_pending, pending);
+};
+
+struct transport_rfcomm {
+    int rfcomm_fd;
+    pa_io_event *rfcomm_io;
+    pa_mainloop_api *mainloop;
+};
+
+#define BLUEZ_SERVICE "org.bluez"
+#define BLUEZ_MEDIA_TRANSPORT_INTERFACE BLUEZ_SERVICE ".MediaTransport1"
+
+#define BLUEZ_ERROR_NOT_SUPPORTED "org.bluez.Error.NotSupported"
+
+#define BLUEZ_PROFILE_MANAGER_INTERFACE BLUEZ_SERVICE ".ProfileManager1"
+#define BLUEZ_PROFILE_INTERFACE BLUEZ_SERVICE ".Profile1"
+
+#define HSP_AG_PROFILE "/Profile/HSPAGProfile"
+
+#define PROFILE_INTROSPECT_XML                                          \
+    DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                           \
+    "<node>"                                                            \
+    " <interface name=\"" BLUEZ_PROFILE_INTERFACE "\">"                 \
+    "  <method name=\"Release\">"                                       \
+    "  </method>"                                                       \
+    "  <method name=\"RequestDisconnection\">"                          \
+    "   <arg name=\"device\" direction=\"in\" type=\"o\"/>"             \
+    "  </method>"                                                       \
+    "  <method name=\"NewConnection\">"                                 \
+    "   <arg name=\"device\" direction=\"in\" type=\"o\"/>"             \
+    "   <arg name=\"fd\" direction=\"in\" type=\"h\"/>"                 \
+    "   <arg name=\"opts\" direction=\"in\" type=\"a{sv}\"/>"           \
+    "  </method>"                                                       \
+    " </interface>"                                                     \
+    " <interface name=\"org.freedesktop.DBus.Introspectable\">"         \
+    "  <method name=\"Introspect\">"                                    \
+    "   <arg name=\"data\" type=\"s\" direction=\"out\"/>"              \
+    "  </method>"                                                       \
+    " </interface>"                                                     \
+    "</node>"
+
+static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_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 int bluez5_sco_acquire_cb(pa_bluetooth_transport *t, bool optional, size_t *imtu, size_t *omtu) {
+    pa_bluetooth_device *d = t->device;
+    struct sockaddr_sco addr;
+    int err, i;
+    int sock;
+    bdaddr_t src;
+    bdaddr_t dst;
+    const char *src_addr, *dst_addr;
+
+    src_addr = d->adapter->address;
+    dst_addr = d->address;
+
+    for (i = 5; i >= 0; i--, src_addr += 3)
+        src.b[i] = strtol(src_addr, NULL, 16);
+    for (i = 5; i >= 0; i--, dst_addr += 3)
+        dst.b[i] = strtol(dst_addr, NULL, 16);
+
+    sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
+    if (sock < 0) {
+        pa_log_error("socket(SEQPACKET, SCO) %s", pa_cstrerror(errno));
+        return -1;
+    }
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sco_family = AF_BLUETOOTH;
+    bacpy(&addr.sco_bdaddr, &src);
+
+    if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+        pa_log_error("bind(): %s", pa_cstrerror(errno));
+        goto fail_close;
+    }
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sco_family = AF_BLUETOOTH;
+    bacpy(&addr.sco_bdaddr, &dst);
+
+    pa_log_info ("doing connect\n");
+    err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
+    if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) {
+        pa_log_error("connect(): %s", pa_cstrerror(errno));
+        goto fail_close;
+    }
+
+    /* The "48" below is hardcoded until we get meaningful MTU values exposed
+     * by the kernel */
+
+    if (imtu)
+        *imtu = 48;
+
+    if (omtu)
+        *omtu = 48;
+
+    return sock;
+
+fail_close:
+    close(sock);
+    return -1;
+}
+
+static void bluez5_sco_release_cb(pa_bluetooth_transport *t) {
+    pa_log_info("Transport %s released", t->path);
+    /* device will close the SCO socket for us */
+}
+
+static void register_profile_reply(DBusPendingCall *pending, void *userdata) {
+    DBusMessage *r;
+    pa_dbus_pending *p;
+    pa_bluetooth_backend *b;
+    char *profile;
+
+    pa_assert(pending);
+    pa_assert_se(p = userdata);
+    pa_assert_se(b = p->context_data);
+    pa_assert_se(profile = p->call_data);
+    pa_assert_se(r = dbus_pending_call_steal_reply(pending));
+
+    if (dbus_message_is_error(r, BLUEZ_ERROR_NOT_SUPPORTED)) {
+        pa_log_info("Couldn't register profile %s because it is disabled in BlueZ", profile);
+        goto finish;
+    }
+
+    if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
+        pa_log_error(BLUEZ_PROFILE_MANAGER_INTERFACE ".RegisterProfile() failed: %s: %s", dbus_message_get_error_name(r),
+                     pa_dbus_get_error_message(r));
+        goto finish;
+    }
+
+finish:
+    dbus_message_unref(r);
+
+    PA_LLIST_REMOVE(pa_dbus_pending, b->pending, p);
+    pa_dbus_pending_free(p);
+
+    pa_xfree(profile);
+}
+
+static void register_profile(pa_bluetooth_backend *b, const char *profile, const char *uuid) {
+    DBusMessage *m;
+    DBusMessageIter i, d;
+
+    pa_log_debug("Registering Profile %s", profile);
+
+    pa_assert_se(m = dbus_message_new_method_call(BLUEZ_SERVICE, "/org/bluez", BLUEZ_PROFILE_MANAGER_INTERFACE, "RegisterProfile"));
+
+    dbus_message_iter_init_append(m, &i);
+    dbus_message_iter_append_basic(&i, DBUS_TYPE_OBJECT_PATH, &profile);
+    dbus_message_iter_append_basic(&i, DBUS_TYPE_STRING, &uuid);
+    dbus_message_iter_open_container(&i, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING
+            DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &d);
+    dbus_message_iter_close_container(&i, &d);
+
+    send_and_add_to_pending(b, m, register_profile_reply, pa_xstrdup(profile));
+}
+
+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_assert(io);
+    pa_assert(t);
+
+    if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) {
+        pa_log_info("Lost RFCOMM connection.");
+        goto fail;
+    }
+
+    if (events & PA_IO_EVENT_INPUT) {
+        char buf[512];
+        ssize_t len;
+
+        len = read(fd, buf, 511);
+        buf[len] = 0;
+        pa_log_debug("RFCOMM << %s", buf);
+
+        pa_log_debug("RFCOMM >> OK");
+        len = write (fd, "\r\nOK\r\n", 5);
+        /* we ignore any errors, it's not critical and real errors should
+         * be caught with the HANGUP and ERROR events handled above */
+        if (len < 0)
+            pa_log_error("RFCOMM write error: %s", pa_cstrerror(errno));
+    }
+
+    return;
+
+fail:
+    pa_bluetooth_transport_unlink(t);
+    pa_bluetooth_transport_free(t);
+    return;
+}
+
+static void transport_destroy(pa_bluetooth_transport *t) {
+    struct transport_rfcomm *trfc = t->userdata;
+
+    trfc->mainloop->io_free(trfc->rfcomm_io);
+
+    shutdown(trfc->rfcomm_fd, SHUT_RDWR);
+    close (trfc->rfcomm_fd);
+
+    pa_xfree(trfc);
+}
+
+static DBusMessage *profile_new_connection(DBusConnection *conn, DBusMessage *m, void *userdata) {
+    pa_bluetooth_backend *b = userdata;
+    pa_bluetooth_device *d;
+    pa_bluetooth_transport *t;
+    pa_bluetooth_profile_t p;
+    DBusMessage *r;
+    int fd;
+    const char *sender, *path, *handler;
+    DBusMessageIter arg_i;
+    char *pathfd;
+    struct transport_rfcomm *trfc;
+
+    if (!dbus_message_iter_init(m, &arg_i) || !pa_streq(dbus_message_get_signature(m), "oha{sv}")) {
+        pa_log_error("Invalid signature found in NewConnection");
+        goto fail;
+    }
+
+    handler = dbus_message_get_path(m);
+    pa_assert (pa_streq(handler, HSP_AG_PROFILE));
+
+    pa_assert(dbus_message_iter_get_arg_type(&arg_i) == DBUS_TYPE_OBJECT_PATH);
+    dbus_message_iter_get_basic(&arg_i, &path);
+
+    d = pa_bluetooth_discovery_get_device_by_path(b->discovery, path);
+    if (d == NULL) {
+        pa_log_error("Device doesnt exist for %s", path);
+        goto fail;
+    }
+
+    pa_assert_se(dbus_message_iter_next(&arg_i));
+
+    pa_assert(dbus_message_iter_get_arg_type(&arg_i) == DBUS_TYPE_UNIX_FD);
+    dbus_message_iter_get_basic(&arg_i, &fd);
+
+    pa_log_debug("dbus: NewConnection path=%s, fd=%d", path, fd);
+
+    sender = dbus_message_get_sender(m);
+
+    p = PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT;
+    pathfd = pa_sprintf_malloc ("%s/fd%d", path, fd);
+    d->transports[p] = t = pa_bluetooth_transport_new(d, sender, pathfd, p, NULL, 0);
+    pa_xfree(pathfd);
+
+    t->acquire = bluez5_sco_acquire_cb;
+    t->release = bluez5_sco_release_cb;
+    t->destroy = transport_destroy;
+
+    trfc = pa_xnew0(struct transport_rfcomm, 1);
+    trfc->rfcomm_fd = fd;
+    trfc->mainloop = b->core->mainloop;
+    trfc->rfcomm_io = trfc->mainloop->io_new(b->core->mainloop, fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP,
+        rfcomm_io_callback, t);
+    t->userdata =  trfc;
+
+    pa_bluetooth_transport_put(t);
+
+    pa_log_debug("Transport %s available for profile %s", t->path, pa_bluetooth_profile_to_string(t->profile));
+
+    pa_assert_se(r = dbus_message_new_method_return(m));
+
+    return r;
+
+fail:
+    pa_assert_se(r = dbus_message_new_error(m, "org.bluez.Error.InvalidArguments", "Unable to handle new connection"));
+    return r;
+}
+
+static DBusMessage *profile_request_disconnection(DBusConnection *conn, DBusMessage *m, void *userdata) {
+    DBusMessage *r;
+
+    pa_assert_se(r = dbus_message_new_method_return(m));
+
+    return r;
+}
+
+static DBusHandlerResult profile_handler(DBusConnection *c, DBusMessage *m, void *userdata) {
+    pa_bluetooth_backend *b = userdata;
+    DBusMessage *r = NULL;
+    const char *path, *interface, *member;
+
+    pa_assert(b);
+
+    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);
+
+    if (!pa_streq(path, HSP_AG_PROFILE))
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+    if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
+        const char *xml = PROFILE_INTROSPECT_XML;
+
+        pa_assert_se(r = dbus_message_new_method_return(m));
+        pa_assert_se(dbus_message_append_args(r, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID));
+
+    } else if (dbus_message_is_method_call(m, BLUEZ_PROFILE_INTERFACE, "Release")) {
+    } else if (dbus_message_is_method_call(m, BLUEZ_PROFILE_INTERFACE, "RequestDisconnection")) {
+        r = profile_request_disconnection(c, m, userdata);
+    } else if (dbus_message_is_method_call(m, BLUEZ_PROFILE_INTERFACE, "NewConnection"))
+        r = profile_new_connection(c, m, userdata);
+    else
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+    if (r) {
+        pa_assert_se(dbus_connection_send(pa_dbus_connection_get(b->connection), r, NULL));
+        dbus_message_unref(r);
+    }
+
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void profile_init(pa_bluetooth_backend *b, pa_bluetooth_profile_t profile) {
+    static const DBusObjectPathVTable vtable_profile = {
+        .message_function = profile_handler,
+    };
+    const char *object_name;
+    const char *uuid;
+
+    pa_assert(b);
+
+    switch (profile) {
+        case PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT:
+            object_name = HSP_AG_PROFILE;
+            uuid = PA_BLUETOOTH_UUID_HSP_AG;
+            break;
+        default:
+            pa_assert_not_reached();
+            break;
+    }
+
+    pa_assert_se(dbus_connection_register_object_path(pa_dbus_connection_get(b->connection), object_name, &vtable_profile, b));
+    register_profile(b, object_name, uuid);
+}
+
+static void profile_done(pa_bluetooth_backend *b, pa_bluetooth_profile_t profile) {
+    pa_assert(b);
+
+    switch (profile) {
+        case PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT:
+            dbus_connection_unregister_object_path(pa_dbus_connection_get(b->connection), HSP_AG_PROFILE);
+            break;
+        default:
+            pa_assert_not_reached();
+            break;
+    }
+}
+
+pa_bluetooth_backend *pa_bluetooth_backend_new(pa_core *c, pa_bluetooth_discovery *y) {
+    pa_bluetooth_backend *backend;
+    DBusError err;
+
+    pa_log_debug("Bluetooth Headset Backend API support using the NULL backend");
+
+    backend = pa_xnew0(pa_bluetooth_backend, 1);
+    backend->core = c;
+
+    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;
+    }
+
+    backend->discovery = y;
+
+    profile_init(backend, PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT);
+
+    return backend;
+}
+
+void pa_bluetooth_backend_free(pa_bluetooth_backend *backend) {
+    pa_assert(backend);
+
+    pa_dbus_free_pending_list(&backend->pending);
+
+    profile_done(backend, PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT);
+
+    pa_dbus_connection_unref(backend->connection);
+
+    pa_xfree(backend);
+}

commit d7199bafea7be9ca26ee9a551e245de0f4bc9e29
Author: Wim Taymans <wim.taymans at gmail.com>
Date:   Fri Oct 24 09:56:50 2014 +0200

    bluez5-util: add destroy function
    
    Add a destroy function to the transport that is called before freeing
    the transport. Useful for cleaning up extra userdata.

diff --git a/src/modules/bluetooth/bluez5-util.c b/src/modules/bluetooth/bluez5-util.c
index 1ee2f33..9431aed 100644
--- a/src/modules/bluetooth/bluez5-util.c
+++ b/src/modules/bluetooth/bluez5-util.c
@@ -205,6 +205,8 @@ void pa_bluetooth_transport_unlink(pa_bluetooth_transport *t) {
 void pa_bluetooth_transport_free(pa_bluetooth_transport *t) {
     pa_assert(t);
 
+    if (t->destroy)
+        t->destroy(t);
     pa_bluetooth_transport_unlink(t);
 
     pa_xfree(t->owner);
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
index 8db4a17..1a8a364 100644
--- a/src/modules/bluetooth/bluez5-util.h
+++ b/src/modules/bluetooth/bluez5-util.h
@@ -60,6 +60,7 @@ typedef enum pa_bluetooth_transport_state {
 
 typedef int (*pa_bluetooth_transport_acquire_cb)(pa_bluetooth_transport *t, bool optional, size_t *imtu, size_t *omtu);
 typedef void (*pa_bluetooth_transport_release_cb)(pa_bluetooth_transport *t);
+typedef void (*pa_bluetooth_transport_destroy_cb)(pa_bluetooth_transport *t);
 
 struct pa_bluetooth_transport {
     pa_bluetooth_device *device;
@@ -76,6 +77,7 @@ struct pa_bluetooth_transport {
 
     pa_bluetooth_transport_acquire_cb acquire;
     pa_bluetooth_transport_release_cb release;
+    pa_bluetooth_transport_destroy_cb destroy;
     void *userdata;
 };
 

commit 2251085ddacd780163ed2d84194aff3a0d5153f7
Author: Wim Taymans <wim.taymans at gmail.com>
Date:   Fri Oct 24 09:56:49 2014 +0200

    bluez5-device: use get_profile_direction
    
    Use the get_profile_direction() helper function to decide when to add a
    source and a sink instead of enumerating profiles.

diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
index 48e498b..15731d1 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -1210,6 +1210,19 @@ static int setup_transport(struct userdata *u) {
 }
 
 /* Run from main thread */
+static pa_direction_t get_profile_direction(pa_bluetooth_profile_t p) {
+    static const pa_direction_t profile_direction[] = {
+        [PA_BLUETOOTH_PROFILE_A2DP_SINK] = PA_DIRECTION_OUTPUT,
+        [PA_BLUETOOTH_PROFILE_A2DP_SOURCE] = PA_DIRECTION_INPUT,
+        [PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT,
+        [PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT,
+        [PA_BLUETOOTH_PROFILE_OFF] = 0
+    };
+
+    return profile_direction[p];
+}
+
+/* Run from main thread */
 static int init_profile(struct userdata *u) {
     int r = 0;
     pa_assert(u);
@@ -1220,13 +1233,11 @@ static int init_profile(struct userdata *u) {
 
     pa_assert(u->transport);
 
-    if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK || u->profile == PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT ||
-        u->profile == PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY)
+    if (get_profile_direction (u->profile) & PA_DIRECTION_OUTPUT)
         if (add_sink(u) < 0)
             r = -1;
 
-    if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SOURCE || u->profile == PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT ||
-        u->profile == PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY)
+    if (get_profile_direction (u->profile) & PA_DIRECTION_INPUT)
         if (add_source(u) < 0)
             r = -1;
 
@@ -1546,19 +1557,6 @@ static char *cleanup_name(const char *name) {
 }
 
 /* Run from main thread */
-static pa_direction_t get_profile_direction(pa_bluetooth_profile_t p) {
-    static const pa_direction_t profile_direction[] = {
-        [PA_BLUETOOTH_PROFILE_A2DP_SINK] = PA_DIRECTION_OUTPUT,
-        [PA_BLUETOOTH_PROFILE_A2DP_SOURCE] = PA_DIRECTION_INPUT,
-        [PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT,
-        [PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT,
-        [PA_BLUETOOTH_PROFILE_OFF] = 0
-    };
-
-    return profile_direction[p];
-}
-
-/* Run from main thread */
 static pa_available_t get_port_availability(struct userdata *u, pa_direction_t direction) {
     pa_available_t result = PA_AVAILABLE_NO;
     unsigned i;

commit 8718496d1497ea32ef83a46a30625cac096d9f95
Author: Arun Raghavan <arun at accosted.net>
Date:   Wed Aug 6 07:48:19 2014 +0530

    creds: Rename pa_ancil to pa_cmsg_ancil_data
    
    Makes the purpose of the structure clearear.

diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index 69547eb..cfbcd1a 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -1780,14 +1780,14 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) {
 }
 
 /* Called from main context */
-static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_ancil *ancil, void *userdata) {
+static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_cmsg_ancil_data *ancil_data, void *userdata) {
     struct userdata *u = userdata;
 
     pa_assert(p);
     pa_assert(packet);
     pa_assert(u);
 
-    if (pa_pdispatch_run(u->pdispatch, packet, ancil, u) < 0) {
+    if (pa_pdispatch_run(u->pdispatch, packet, ancil_data, u) < 0) {
         pa_log("Invalid packet");
         pa_module_unload_request(u->module, true);
         return;
diff --git a/src/pulse/context.c b/src/pulse/context.c
index ec9f3ac..d5da9b8 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -328,7 +328,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) {
     pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED);
 }
 
-static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_ancil *ancil, void *userdata) {
+static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_cmsg_ancil_data *ancil_data, void *userdata) {
     pa_context *c = userdata;
 
     pa_assert(p);
@@ -337,7 +337,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_a
 
     pa_context_ref(c);
 
-    if (pa_pdispatch_run(c->pdispatch, packet, ancil, c) < 0)
+    if (pa_pdispatch_run(c->pdispatch, packet, ancil_data, c) < 0)
         pa_context_fail(c, PA_ERR_PROTOCOL);
 
     pa_context_unref(c);
diff --git a/src/pulsecore/creds.h b/src/pulsecore/creds.h
index 06806bc..43f6166 100644
--- a/src/pulsecore/creds.h
+++ b/src/pulsecore/creds.h
@@ -31,10 +31,10 @@
 #include <pulsecore/socket.h>
 #include <stdbool.h>
 
-#define MAX_ANCIL_FDS 2
+#define MAX_ANCIL_DATA_FDS 2
 
 typedef struct pa_creds pa_creds;
-typedef struct pa_ancil pa_ancil;
+typedef struct pa_cmsg_ancil_data pa_cmsg_ancil_data;
 
 #if defined(SCM_CREDENTIALS)
 
@@ -46,12 +46,12 @@ struct pa_creds {
 };
 
 /* Struct for handling ancillary data, i e, extra data that can be sent together with a message
-   over unix pipes. Supports sending and receiving credentials and file descriptors. */
-struct pa_ancil {
+ * over unix pipes. Supports sending and receiving credentials and file descriptors. */
+struct pa_cmsg_ancil_data {
     pa_creds creds;
     bool creds_valid;
     int nfd;
-    int fds[MAX_ANCIL_FDS];
+    int fds[MAX_ANCIL_DATA_FDS];
 };
 
 #else
diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c
index 6b1fc7a..ae9b42c 100644
--- a/src/pulsecore/iochannel.c
+++ b/src/pulsecore/iochannel.c
@@ -355,7 +355,7 @@ ssize_t pa_iochannel_write_with_fds(pa_iochannel*io, const void*data, size_t l,
     struct iovec iov;
     union {
         struct cmsghdr hdr;
-        uint8_t data[CMSG_SPACE(sizeof(int) * MAX_ANCIL_FDS)];
+        uint8_t data[CMSG_SPACE(sizeof(int) * MAX_ANCIL_DATA_FDS)];
     } cmsg;
 
     pa_assert(io);
@@ -364,7 +364,7 @@ ssize_t pa_iochannel_write_with_fds(pa_iochannel*io, const void*data, size_t l,
     pa_assert(io->ofd >= 0);
     pa_assert(fds);
     pa_assert(nfd > 0);
-    pa_assert(nfd <= MAX_ANCIL_FDS);
+    pa_assert(nfd <= MAX_ANCIL_DATA_FDS);
 
     pa_zero(iov);
     iov.iov_base = (void*) data;
@@ -391,24 +391,24 @@ ssize_t pa_iochannel_write_with_fds(pa_iochannel*io, const void*data, size_t l,
     return r;
 }
 
-ssize_t pa_iochannel_read_with_ancil(pa_iochannel*io, void*data, size_t l, pa_ancil *ancil) {
+ssize_t pa_iochannel_read_with_ancil_data(pa_iochannel*io, void*data, size_t l, pa_cmsg_ancil_data *ancil_data) {
     ssize_t r;
     struct msghdr mh;
     struct iovec iov;
     union {
         struct cmsghdr hdr;
-        uint8_t data[CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(sizeof(int) * MAX_ANCIL_FDS)];
+        uint8_t data[CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(sizeof(int) * MAX_ANCIL_DATA_FDS)];
     } cmsg;
 
     pa_assert(io);
     pa_assert(data);
     pa_assert(l);
     pa_assert(io->ifd >= 0);
-    pa_assert(ancil);
+    pa_assert(ancil_data);
 
     if (io->ifd_type > 0) {
-        ancil->creds_valid = false;
-        ancil->nfd = 0;
+        ancil_data->creds_valid = false;
+        ancil_data->nfd = 0;
         return pa_iochannel_read(io, data, l);
     }
 
@@ -426,8 +426,8 @@ ssize_t pa_iochannel_read_with_ancil(pa_iochannel*io, void*data, size_t l, pa_an
     if ((r = recvmsg(io->ifd, &mh, 0)) >= 0) {
         struct cmsghdr *cmh;
 
-        ancil->creds_valid = false;
-        ancil->nfd = 0;
+        ancil_data->creds_valid = false;
+        ancil_data->nfd = 0;
 
         for (cmh = CMSG_FIRSTHDR(&mh); cmh; cmh = CMSG_NXTHDR(&mh, cmh)) {
 
@@ -439,21 +439,21 @@ ssize_t pa_iochannel_read_with_ancil(pa_iochannel*io, void*data, size_t l, pa_an
                 pa_assert(cmh->cmsg_len == CMSG_LEN(sizeof(struct ucred)));
                 memcpy(&u, CMSG_DATA(cmh), sizeof(struct ucred));
 
-                ancil->creds.gid = u.gid;
-                ancil->creds.uid = u.uid;
-                ancil->creds_valid = true;
+                ancil_data->creds.gid = u.gid;
+                ancil_data->creds.uid = u.uid;
+                ancil_data->creds_valid = true;
             }
             else if (cmh->cmsg_type == SCM_RIGHTS) {
                 int nfd = (cmh->cmsg_len - CMSG_LEN(0)) / sizeof(int);
-                if (nfd > MAX_ANCIL_FDS) {
+                if (nfd > MAX_ANCIL_DATA_FDS) {
                     int i;
                     pa_log("Trying to receive too many file descriptors!");
                     for (i = 0; i < nfd; i++)
                         pa_close(((int*) CMSG_DATA(cmh))[i]);
                     continue;
                 }
-                memcpy(ancil->fds, CMSG_DATA(cmh), nfd * sizeof(int));
-                ancil->nfd = nfd;
+                memcpy(ancil_data->fds, CMSG_DATA(cmh), nfd * sizeof(int));
+                ancil_data->nfd = nfd;
             }
         }
 
@@ -463,7 +463,7 @@ ssize_t pa_iochannel_read_with_ancil(pa_iochannel*io, void*data, size_t l, pa_an
 
     if (r == -1 && errno == ENOTSOCK) {
         io->ifd_type = 1;
-        return pa_iochannel_read_with_ancil(io, data, l, ancil);
+        return pa_iochannel_read_with_ancil_data(io, data, l, ancil_data);
     }
 
     return r;
diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h
index 390f798..959ee88 100644
--- a/src/pulsecore/iochannel.h
+++ b/src/pulsecore/iochannel.h
@@ -59,7 +59,7 @@ int pa_iochannel_creds_enable(pa_iochannel *io);
 
 ssize_t pa_iochannel_write_with_fds(pa_iochannel*io, const void*data, size_t l, int nfd, const int *fds);
 ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const pa_creds *ucred);
-ssize_t pa_iochannel_read_with_ancil(pa_iochannel*io, void*data, size_t l, pa_ancil *ancil);
+ssize_t pa_iochannel_read_with_ancil_data(pa_iochannel*io, void*data, size_t l, pa_cmsg_ancil_data *ancil_data);
 #endif
 
 bool pa_iochannel_is_readable(pa_iochannel*io);
diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c
index fdb27c9..53284ee 100644
--- a/src/pulsecore/pdispatch.c
+++ b/src/pulsecore/pdispatch.c
@@ -221,7 +221,7 @@ struct pa_pdispatch {
     PA_LLIST_HEAD(struct reply_info, replies);
     pa_pdispatch_drain_cb_t drain_callback;
     void *drain_userdata;
-    const pa_ancil *ancil;
+    const pa_cmsg_ancil_data *ancil_data;
     bool use_rtclock;
 };
 
@@ -291,7 +291,7 @@ static void run_action(pa_pdispatch *pd, struct reply_info *r, uint32_t command,
     pa_pdispatch_unref(pd);
 }
 
-int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_ancil *ancil, void *userdata) {
+int pa_pdispatch_run(pa_pdispatch *pd, pa_packet *packet, const pa_cmsg_ancil_data *ancil_data, void *userdata) {
     uint32_t tag, command;
     pa_tagstruct *ts = NULL;
     int ret = -1;
@@ -325,7 +325,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_ancil *ancil,
 }
 #endif
 
-    pd->ancil = ancil;
+    pd->ancil_data = ancil_data;
 
     if (command == PA_COMMAND_ERROR || command == PA_COMMAND_REPLY) {
         struct reply_info *r;
@@ -349,7 +349,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_ancil *ancil,
     ret = 0;
 
 finish:
-    pd->ancil = NULL;
+    pd->ancil_data = NULL;
 
     if (ts)
         pa_tagstruct_free(ts);
@@ -444,8 +444,8 @@ const pa_creds * pa_pdispatch_creds(pa_pdispatch *pd) {
     pa_assert(pd);
     pa_assert(PA_REFCNT_VALUE(pd) >= 1);
 
-    if (pd->ancil && pd->ancil->creds_valid)
-         return &pd->ancil->creds;
+    if (pd->ancil_data && pd->ancil_data->creds_valid)
+         return &pd->ancil_data->creds;
     return NULL;
 }
 
@@ -454,9 +454,9 @@ const int * pa_pdispatch_fds(pa_pdispatch *pd, int *nfd) {
     pa_assert(PA_REFCNT_VALUE(pd) >= 1);
     pa_assert(nfd);
 
-    if (pd->ancil) {
-         *nfd = pd->ancil->nfd;
-         return pd->ancil->fds;
+    if (pd->ancil_data) {
+         *nfd = pd->ancil_data->nfd;
+         return pd->ancil_data->fds;
     }
 
     *nfd = 0;
diff --git a/src/pulsecore/pdispatch.h b/src/pulsecore/pdispatch.h
index 038f90d..df2e2fd 100644
--- a/src/pulsecore/pdispatch.h
+++ b/src/pulsecore/pdispatch.h
@@ -41,7 +41,7 @@ pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, bool use_rtclock, const pa_pd
 void pa_pdispatch_unref(pa_pdispatch *pd);
 pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd);
 
-int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*p, const pa_ancil *ancil, void *userdata);
+int pa_pdispatch_run(pa_pdispatch *pd, pa_packet *p, const pa_cmsg_ancil_data *ancil_data, void *userdata);
 
 void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa_pdispatch_cb_t callback, void *userdata, pa_free_cb_t free_cb);
 
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 2ef1854..c0cd0e0 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -4888,14 +4888,14 @@ static void command_set_port_latency_offset(pa_pdispatch *pd, uint32_t command,
 
 /*** pstream callbacks ***/
 
-static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_ancil *ancil, void *userdata) {
+static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_cmsg_ancil_data *ancil_data, void *userdata) {
     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
 
     pa_assert(p);
     pa_assert(packet);
     pa_native_connection_assert_ref(c);
 
-    if (pa_pdispatch_run(c->pdispatch, packet, ancil, c) < 0) {
+    if (pa_pdispatch_run(c->pdispatch, packet, ancil_data, c) < 0) {
         pa_log("invalid packet.");
         native_connection_unlink(c);
     }
diff --git a/src/pulsecore/pstream-util.c b/src/pulsecore/pstream-util.c
index 0403ab7..9ccd5a4 100644
--- a/src/pulsecore/pstream-util.c
+++ b/src/pulsecore/pstream-util.c
@@ -28,7 +28,7 @@
 
 #include "pstream-util.h"
 
-static void pa_pstream_send_tagstruct_with_ancil(pa_pstream *p, pa_tagstruct *t, const pa_ancil *ancil) {
+static void pa_pstream_send_tagstruct_with_ancil_data(pa_pstream *p, pa_tagstruct *t, const pa_cmsg_ancil_data *ancil_data) {
     size_t length;
     uint8_t *data;
     pa_packet *packet;
@@ -38,7 +38,7 @@ static void pa_pstream_send_tagstruct_with_ancil(pa_pstream *p, pa_tagstruct *t,
 
     pa_assert_se(data = pa_tagstruct_free_data(t, &length));
     pa_assert_se(packet = pa_packet_new_dynamic(data, length));
-    pa_pstream_send_packet(p, packet, ancil);
+    pa_pstream_send_packet(p, packet, ancil_data);
     pa_packet_unref(packet);
 }
 
@@ -46,35 +46,35 @@ static void pa_pstream_send_tagstruct_with_ancil(pa_pstream *p, pa_tagstruct *t,
 
 void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const pa_creds *creds) {
     if (creds) {
-        pa_ancil a;
+        pa_cmsg_ancil_data a;
 
         a.nfd = 0;
         a.creds_valid = true;
         a.creds = *creds;
-        pa_pstream_send_tagstruct_with_ancil(p, t, &a);
+        pa_pstream_send_tagstruct_with_ancil_data(p, t, &a);
     }
     else
-        pa_pstream_send_tagstruct_with_ancil(p, t, NULL);
+        pa_pstream_send_tagstruct_with_ancil_data(p, t, NULL);
 }
 
 void pa_pstream_send_tagstruct_with_fds(pa_pstream *p, pa_tagstruct *t, int nfd, const int *fds) {
     if (nfd > 0) {
-        pa_ancil a;
+        pa_cmsg_ancil_data a;
 
         a.nfd = nfd;
         a.creds_valid = false;
-        pa_assert(nfd <= MAX_ANCIL_FDS);
+        pa_assert(nfd <= MAX_ANCIL_DATA_FDS);
         memcpy(a.fds, fds, sizeof(int) * nfd);
-        pa_pstream_send_tagstruct_with_ancil(p, t, &a);
+        pa_pstream_send_tagstruct_with_ancil_data(p, t, &a);
     }
     else
-        pa_pstream_send_tagstruct_with_ancil(p, t, NULL);
+        pa_pstream_send_tagstruct_with_ancil_data(p, t, NULL);
 }
 
 #else
 
 void pa_pstream_send_tagstruct_with_creds(pa_pstream *p, pa_tagstruct *t, const pa_creds *creds) {
-    pa_pstream_send_tagstruct_with_ancil(p, t, NULL);
+    pa_pstream_send_tagstruct_with_ancil_data(p, t, NULL);
 }
 
 void pa_pstream_send_tagstruct_with_fds(pa_pstream *p, pa_tagstruct *t, int nfd, const int *fds) {
diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index ceda728..c32b44c 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -95,8 +95,8 @@ struct item_info {
     /* packet info */
     pa_packet *packet;
 #ifdef HAVE_CREDS
-    bool with_ancil;
-    pa_ancil ancil;
+    bool with_ancil_data;
+    pa_cmsg_ancil_data ancil_data;
 #endif
 
     /* memblock info */
@@ -170,8 +170,8 @@ struct pa_pstream {
     pa_mempool *mempool;
 
 #ifdef HAVE_CREDS
-    pa_ancil read_ancil, write_ancil;
-    bool send_ancil_now;
+    pa_cmsg_ancil_data read_ancil_data, write_ancil_data;
+    bool send_ancil_data_now;
 #endif
 };
 
@@ -324,7 +324,7 @@ static void pstream_free(pa_pstream *p) {
     pa_xfree(p);
 }
 
-void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_ancil *ancil) {
+void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_cmsg_ancil_data *ancil_data) {
     struct item_info *i;
 
     pa_assert(p);
@@ -341,12 +341,12 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_ancil *anc
     i->packet = pa_packet_ref(packet);
 
 #ifdef HAVE_CREDS
-    if ((i->with_ancil = !!ancil)) {
-        i->ancil = *ancil;
-        if (ancil->creds_valid)
-            pa_assert(ancil->nfd == 0);
+    if ((i->with_ancil_data = !!ancil_data)) {
+        i->ancil_data = *ancil_data;
+        if (ancil_data->creds_valid)
+            pa_assert(ancil_data->nfd == 0);
         else
-            pa_assert(ancil->nfd > 0);
+            pa_assert(ancil_data->nfd > 0);
     }
 #endif
 
@@ -389,7 +389,7 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa
         i->offset = offset;
         i->seek_mode = seek_mode;
 #ifdef HAVE_CREDS
-        i->with_ancil = false;
+        i->with_ancil_data = false;
 #endif
 
         pa_queue_push(p->send_queue, i);
@@ -416,7 +416,7 @@ void pa_pstream_send_release(pa_pstream *p, uint32_t block_id) {
     item->type = PA_PSTREAM_ITEM_SHMRELEASE;
     item->block_id = block_id;
 #ifdef HAVE_CREDS
-    item->with_ancil = false;
+    item->with_ancil_data = false;
 #endif
 
     pa_queue_push(p->send_queue, item);
@@ -453,7 +453,7 @@ void pa_pstream_send_revoke(pa_pstream *p, uint32_t block_id) {
     item->type = PA_PSTREAM_ITEM_SHMREVOKE;
     item->block_id = block_id;
 #ifdef HAVE_CREDS
-    item->with_ancil = false;
+    item->with_ancil_data = false;
 #endif
 
     pa_queue_push(p->send_queue, item);
@@ -577,8 +577,8 @@ static void prepare_next_write_item(pa_pstream *p) {
     }
 
 #ifdef HAVE_CREDS
-    if ((p->send_ancil_now = p->write.current->with_ancil))
-        p->write_ancil = p->write.current->ancil;
+    if ((p->send_ancil_data_now = p->write.current->with_ancil_data))
+        p->write_ancil_data = p->write.current->ancil_data;
 #endif
 }
 
@@ -637,16 +637,16 @@ static int do_write(pa_pstream *p) {
     pa_assert(l > 0);
 
 #ifdef HAVE_CREDS
-    if (p->send_ancil_now) {
-        if (p->write_ancil.creds_valid) {
-            pa_assert(p->write_ancil.nfd == 0);
-            if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_ancil.creds)) < 0)
+    if (p->send_ancil_data_now) {
+        if (p->write_ancil_data.creds_valid) {
+            pa_assert(p->write_ancil_data.nfd == 0);
+            if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_ancil_data.creds)) < 0)
                 goto fail;
         }
         else
-            if ((r = pa_iochannel_write_with_fds(p->io, d, l, p->write_ancil.nfd, p->write_ancil.fds)) < 0)
+            if ((r = pa_iochannel_write_with_fds(p->io, d, l, p->write_ancil_data.nfd, p->write_ancil_data.fds)) < 0)
                 goto fail;
-        p->send_ancil_now = false;
+        p->send_ancil_data_now = false;
     } else
 #endif
     if (p->srb)
@@ -719,19 +719,19 @@ static int do_read(pa_pstream *p, struct pstream_read *re) {
     else
 #ifdef HAVE_CREDS
     {
-        pa_ancil b;
+        pa_cmsg_ancil_data b;
 
-        if ((r = pa_iochannel_read_with_ancil(p->io, d, l, &b)) <= 0)
+        if ((r = pa_iochannel_read_with_ancil_data(p->io, d, l, &b)) <= 0)
             goto fail;
 
         if (b.creds_valid) {
-            p->read_ancil.creds_valid = true;
-            p->read_ancil.creds = b.creds;
+            p->read_ancil_data.creds_valid = true;
+            p->read_ancil_data.creds = b.creds;
         }
         if (b.nfd > 0) {
-            pa_assert(b.nfd <= MAX_ANCIL_FDS);
-            p->read_ancil.nfd = b.nfd;
-            memcpy(p->read_ancil.fds, b.fds, sizeof(int) * b.nfd);
+            pa_assert(b.nfd <= MAX_ANCIL_DATA_FDS);
+            p->read_ancil_data.nfd = b.nfd;
+            memcpy(p->read_ancil_data.fds, b.fds, sizeof(int) * b.nfd);
         }
     }
 #else
@@ -880,7 +880,7 @@ static int do_read(pa_pstream *p, struct pstream_read *re) {
 
                 if (p->receive_packet_callback)
 #ifdef HAVE_CREDS
-                    p->receive_packet_callback(p, re->packet, &p->read_ancil, p->receive_packet_callback_userdata);
+                    p->receive_packet_callback(p, re->packet, &p->read_ancil_data, p->receive_packet_callback_userdata);
 #else
                     p->receive_packet_callback(p, re->packet, NULL, p->receive_packet_callback_userdata);
 #endif
@@ -942,8 +942,8 @@ frame_done:
     re->data = NULL;
 
 #ifdef HAVE_CREDS
-    p->read_ancil.creds_valid = false;
-    p->read_ancil.nfd = 0;
+    p->read_ancil_data.creds_valid = false;
+    p->read_ancil_data.nfd = 0;
 #endif
 
     return 0;
diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h
index 8e4056c..cbea237 100644
--- a/src/pulsecore/pstream.h
+++ b/src/pulsecore/pstream.h
@@ -38,7 +38,7 @@
 
 typedef struct pa_pstream pa_pstream;
 
-typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const pa_ancil *ancil, void *userdata);
+typedef void (*pa_pstream_packet_cb_t)(pa_pstream *p, pa_packet *packet, const pa_cmsg_ancil_data *ancil_data, void *userdata);
 typedef void (*pa_pstream_memblock_cb_t)(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata);
 typedef void (*pa_pstream_notify_cb_t)(pa_pstream *p, void *userdata);
 typedef void (*pa_pstream_block_id_cb_t)(pa_pstream *p, uint32_t block_id, void *userdata);
@@ -50,7 +50,7 @@ void pa_pstream_unref(pa_pstream*p);
 
 void pa_pstream_unlink(pa_pstream *p);
 
-void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_ancil *ancil);
+void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_cmsg_ancil_data *ancil_data);
 void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk);
 void pa_pstream_send_release(pa_pstream *p, uint32_t block_id);
 void pa_pstream_send_revoke(pa_pstream *p, uint32_t block_id);
diff --git a/src/tests/srbchannel-test.c b/src/tests/srbchannel-test.c
index bf7b0f0..ce5930b 100644
--- a/src/tests/srbchannel-test.c
+++ b/src/tests/srbchannel-test.c
@@ -36,7 +36,7 @@ static unsigned packets_received;
 static unsigned packets_checksum;
 static size_t packets_length;
 
-static void packet_received(pa_pstream *p, pa_packet *packet, const pa_ancil *ancil, void *userdata) {
+static void packet_received(pa_pstream *p, pa_packet *packet, const pa_cmsg_ancil_data *ancil_data, void *userdata) {
     unsigned i;
     fail_unless(packets_length == packet->length);
     packets_received++;



More information about the pulseaudio-commits mailing list