[pulseaudio-discuss] [PATCH v3 4/7] bluetooth: Set off profile on SCO disconnect

Frédéric Dalleau frederic.dalleau at linux.intel.com
Tue Sep 20 04:55:23 PDT 2011


Sends a message from IO thread to main thread using pa_msgobject when POLLERR
or POLLHUP is received on SCO socket.
---
 src/modules/bluetooth/module-bluetooth-device.c |  136 ++++++++++++++---------
 1 files changed, 84 insertions(+), 52 deletions(-)

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 08ab868..3db9e8f 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -126,7 +126,9 @@ struct hsp_info {
     pa_hook_slot *source_state_changed_slot;
 };
 
-struct userdata {
+struct bluetooth_device {
+    pa_msgobject parent;
+
     pa_core *core;
     pa_module *module;
 
@@ -176,6 +178,15 @@ struct userdata {
     pa_bool_t filter_added;
 };
 
+enum {
+    BLUETOOTH_DEVICE_MESSAGE_SET_PROFILE     /* IO thread termination switch profiles to Off */,
+    BLUETOOTH_DEVICE_MESSAGE_MAX
+};
+
+typedef struct bluetooth_device bluetooth_device;
+PA_DEFINE_PRIVATE_CLASS(bluetooth_device, pa_msgobject);
+#define BLUETOOTH_DEVICE(o) (bluetooth_device_cast(o))
+
 #define FIXED_LATENCY_PLAYBACK_A2DP (25*PA_USEC_PER_MSEC)
 #define FIXED_LATENCY_RECORD_A2DP (25*PA_USEC_PER_MSEC)
 #define FIXED_LATENCY_PLAYBACK_HSP (125*PA_USEC_PER_MSEC)
@@ -185,10 +196,10 @@ struct userdata {
 
 #define USE_SCO_OVER_PCM(u) (u->profile == PROFILE_HSP && (u->hsp.sco_sink && u->hsp.sco_source))
 
-static int init_bt(struct userdata *u);
-static int init_profile(struct userdata *u);
+static int init_bt(struct bluetooth_device *u);
+static int init_profile(struct bluetooth_device *u);
 
-static int service_send(struct userdata *u, const bt_audio_msg_header_t *msg) {
+static int service_send(struct bluetooth_device *u, const bt_audio_msg_header_t *msg) {
     ssize_t r;
 
     pa_assert(u);
@@ -215,7 +226,7 @@ static int service_send(struct userdata *u, const bt_audio_msg_header_t *msg) {
     return -1;
 }
 
-static int service_recv(struct userdata *u, bt_audio_msg_header_t *msg, size_t room) {
+static int service_recv(struct bluetooth_device *u, bt_audio_msg_header_t *msg, size_t room) {
     ssize_t r;
 
     pa_assert(u);
@@ -267,7 +278,7 @@ read_fail:
     return -1;
 }
 
-static ssize_t service_expect(struct userdata*u, bt_audio_msg_header_t *rsp, size_t room, uint8_t expected_name, size_t expected_size) {
+static ssize_t service_expect(struct bluetooth_device*u, bt_audio_msg_header_t *rsp, size_t room, uint8_t expected_name, size_t expected_size) {
     int r;
 
     pa_assert(u);
@@ -294,7 +305,7 @@ static ssize_t service_expect(struct userdata*u, bt_audio_msg_header_t *rsp, siz
 }
 
 /* Run from main thread */
-static int parse_caps(struct userdata *u, uint8_t seid, const struct bt_get_capabilities_rsp *rsp) {
+static int parse_caps(struct bluetooth_device *u, uint8_t seid, const struct bt_get_capabilities_rsp *rsp) {
     uint16_t bytes_left;
     const codec_capabilities_t *codec;
 
@@ -375,7 +386,7 @@ static int parse_caps(struct userdata *u, uint8_t seid, const struct bt_get_capa
 }
 
 /* Run from main thread */
-static int get_caps(struct userdata *u, uint8_t seid) {
+static int get_caps(struct bluetooth_device *u, uint8_t seid) {
     union {
         struct bt_get_capabilities_req getcaps_req;
         struct bt_get_capabilities_rsp getcaps_rsp;
@@ -461,7 +472,7 @@ static uint8_t a2dp_default_bitpool(uint8_t freq, uint8_t mode) {
 }
 
 /* Run from main thread */
-static int setup_a2dp(struct userdata *u) {
+static int setup_a2dp(struct bluetooth_device *u) {
     sbc_capabilities_t *cap;
     int i;
 
@@ -665,7 +676,7 @@ static void setup_sbc(struct a2dp_info *a2dp, enum profile p) {
 }
 
 /* Run from main thread */
-static int set_conf(struct userdata *u) {
+static int set_conf(struct bluetooth_device *u) {
     union {
         struct bt_open_req open_req;
         struct bt_open_rsp open_rsp;
@@ -743,7 +754,7 @@ static int set_conf(struct userdata *u) {
 }
 
 /* from IO thread */
-static void a2dp_set_bitpool(struct userdata *u, uint8_t bitpool)
+static void a2dp_set_bitpool(struct bluetooth_device *u, uint8_t bitpool)
 {
     struct a2dp_info *a2dp;
 
@@ -777,7 +788,7 @@ static void a2dp_set_bitpool(struct userdata *u, uint8_t bitpool)
 
 /* from IO thread, except in SCO over PCM */
 
-static int setup_stream(struct userdata *u) {
+static int setup_stream(struct bluetooth_device *u) {
     struct pollfd *pollfd;
     int one;
 
@@ -814,7 +825,7 @@ static int setup_stream(struct userdata *u) {
     return 0;
 }
 
-static int start_stream_fd(struct userdata *u) {
+static int start_stream_fd(struct bluetooth_device *u) {
     union {
         bt_audio_msg_header_t rsp;
         struct bt_start_stream_req start_req;
@@ -852,7 +863,7 @@ static int start_stream_fd(struct userdata *u) {
 }
 
 /* from IO thread */
-static int stop_stream_fd(struct userdata *u) {
+static int stop_stream_fd(struct bluetooth_device *u) {
     union {
         bt_audio_msg_header_t rsp;
         struct bt_stop_stream_req start_req;
@@ -892,7 +903,7 @@ static int stop_stream_fd(struct userdata *u) {
     return r;
 }
 
-static void bt_transport_release(struct userdata *u) {
+static void bt_transport_release(struct bluetooth_device *u) {
     const char *accesstype = "rw";
     const pa_bluetooth_transport *t;
 
@@ -925,7 +936,7 @@ static void bt_transport_release(struct userdata *u) {
     }
 }
 
-static int bt_transport_acquire(struct userdata *u, pa_bool_t start) {
+static int bt_transport_acquire(struct bluetooth_device *u, pa_bool_t start) {
     const char *accesstype = "rw";
     const pa_bluetooth_transport *t;
 
@@ -963,7 +974,7 @@ done:
 
 /* Run from IO thread */
 static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
-    struct userdata *u = PA_SINK(o)->userdata;
+    struct bluetooth_device *u = PA_SINK(o)->userdata;
     pa_bool_t failed = FALSE;
     int r;
 
@@ -1043,7 +1054,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
 /* Run from IO thread */
 static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
-    struct userdata *u = PA_SOURCE(o)->userdata;
+    struct bluetooth_device *u = PA_SOURCE(o)->userdata;
     pa_bool_t failed = FALSE;
     int r;
 
@@ -1115,8 +1126,25 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
     return (r < 0 || !failed) ? r : -1;
 }
 
+/* Called from main thread context */
+static int device_process_msg(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
+    struct bluetooth_device *u = BLUETOOTH_DEVICE(obj);
+
+    switch (code) {
+        case BLUETOOTH_DEVICE_MESSAGE_SET_PROFILE: {
+            const char *profile = data;
+            pa_log_debug("Switch profile to %s requested", profile);
+
+            if (pa_card_set_profile(u->card, profile, FALSE) < 0)
+                pa_log_debug("Failed to switch profile to %s", profile);
+            break;
+        }
+    }
+    return 0;
+}
+
 /* Run from IO thread */
-static int hsp_process_render(struct userdata *u) {
+static int hsp_process_render(struct bluetooth_device *u) {
     int ret = 0;
 
     pa_assert(u);
@@ -1180,7 +1208,7 @@ static int hsp_process_render(struct userdata *u) {
 }
 
 /* Run from IO thread */
-static int hsp_process_push(struct userdata *u) {
+static int hsp_process_push(struct bluetooth_device *u) {
     int ret = 0;
     pa_memchunk memchunk;
 
@@ -1266,7 +1294,7 @@ static int hsp_process_push(struct userdata *u) {
 }
 
 /* Run from IO thread */
-static void a2dp_prepare_buffer(struct userdata *u) {
+static void a2dp_prepare_buffer(struct bluetooth_device *u) {
     pa_assert(u);
 
     if (u->a2dp.buffer_size >= u->link_mtu)
@@ -1278,7 +1306,7 @@ static void a2dp_prepare_buffer(struct userdata *u) {
 }
 
 /* Run from IO thread */
-static int a2dp_process_render(struct userdata *u) {
+static int a2dp_process_render(struct bluetooth_device *u) {
     struct a2dp_info *a2dp;
     struct rtp_header *header;
     struct rtp_payload *payload;
@@ -1411,7 +1439,7 @@ static int a2dp_process_render(struct userdata *u) {
     return ret;
 }
 
-static int a2dp_process_push(struct userdata *u) {
+static int a2dp_process_push(struct bluetooth_device *u) {
     int ret = 0;
     pa_memchunk memchunk;
 
@@ -1528,7 +1556,7 @@ static int a2dp_process_push(struct userdata *u) {
     return ret;
 }
 
-static void a2dp_reduce_bitpool(struct userdata *u)
+static void a2dp_reduce_bitpool(struct bluetooth_device *u)
 {
     struct a2dp_info *a2dp;
     uint8_t bitpool;
@@ -1550,7 +1578,7 @@ static void a2dp_reduce_bitpool(struct userdata *u)
 }
 
 static void thread_func(void *userdata) {
-    struct userdata *u = userdata;
+    struct bluetooth_device *u = userdata;
     unsigned do_write = 0;
     pa_bool_t writable = FALSE;
 
@@ -1721,6 +1749,7 @@ static void thread_func(void *userdata) {
 fail:
     /* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */
     pa_log_debug("IO thread failed");
+    pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), BLUETOOTH_DEVICE_MESSAGE_SET_PROFILE, "off", 0, NULL, NULL);
     pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
 
 finish:
@@ -1730,7 +1759,7 @@ finish:
 /* Run from main thread */
 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *userdata) {
     DBusError err;
-    struct userdata *u;
+    struct bluetooth_device *u;
 
     pa_assert(bus);
     pa_assert(m);
@@ -1814,7 +1843,7 @@ static void sink_set_volume_cb(pa_sink *s) {
     DBusMessage *m;
     dbus_uint16_t gain;
     pa_volume_t volume;
-    struct userdata *u;
+    struct bluetooth_device *u;
     char *k;
 
     pa_assert(s);
@@ -1852,7 +1881,7 @@ static void source_set_volume_cb(pa_source *s) {
     DBusMessage *m;
     dbus_uint16_t gain;
     pa_volume_t volume;
-    struct userdata *u;
+    struct bluetooth_device *u;
     char *k;
 
     pa_assert(s);
@@ -1914,7 +1943,7 @@ static char *get_name(const char *type, pa_modargs *ma, const char *device_id, p
     return pa_sprintf_malloc("bluez_%s.%s", type, n);
 }
 
-static int sco_over_pcm_state_update(struct userdata *u, pa_bool_t changed) {
+static int sco_over_pcm_state_update(struct bluetooth_device *u, pa_bool_t changed) {
     pa_assert(u);
     pa_assert(USE_SCO_OVER_PCM(u));
 
@@ -1958,7 +1987,7 @@ static int sco_over_pcm_state_update(struct userdata *u, pa_bool_t changed) {
     return 0;
 }
 
-static pa_hook_result_t sink_state_changed_cb(pa_core *c, pa_sink *s, struct userdata *u) {
+static pa_hook_result_t sink_state_changed_cb(pa_core *c, pa_sink *s, struct bluetooth_device *u) {
     pa_assert(c);
     pa_sink_assert_ref(s);
     pa_assert(u);
@@ -1971,7 +2000,7 @@ static pa_hook_result_t sink_state_changed_cb(pa_core *c, pa_sink *s, struct use
     return PA_HOOK_OK;
 }
 
-static pa_hook_result_t source_state_changed_cb(pa_core *c, pa_source *s, struct userdata *u) {
+static pa_hook_result_t source_state_changed_cb(pa_core *c, pa_source *s, struct bluetooth_device *u) {
     pa_assert(c);
     pa_source_assert_ref(s);
     pa_assert(u);
@@ -1985,7 +2014,7 @@ static pa_hook_result_t source_state_changed_cb(pa_core *c, pa_source *s, struct
 }
 
 /* Run from main thread */
-static int add_sink(struct userdata *u) {
+static int add_sink(struct bluetooth_device *u) {
     char *k;
 
     if (USE_SCO_OVER_PCM(u)) {
@@ -2051,7 +2080,7 @@ static int add_sink(struct userdata *u) {
 }
 
 /* Run from main thread */
-static int add_source(struct userdata *u) {
+static int add_source(struct bluetooth_device *u) {
     char *k;
 
     if (USE_SCO_OVER_PCM(u)) {
@@ -2122,7 +2151,7 @@ static int add_source(struct userdata *u) {
 }
 
 /* Run from main thread */
-static void shutdown_bt(struct userdata *u) {
+static void shutdown_bt(struct bluetooth_device *u) {
     pa_assert(u);
 
     if (u->stream_fd >= 0) {
@@ -2145,7 +2174,7 @@ static void shutdown_bt(struct userdata *u) {
     }
 }
 
-static int bt_transport_config_a2dp(struct userdata *u) {
+static int bt_transport_config_a2dp(struct bluetooth_device *u) {
     const pa_bluetooth_transport *t;
     struct a2dp_info *a2dp = &u->a2dp;
     a2dp_sbc_t *config;
@@ -2263,7 +2292,7 @@ static int bt_transport_config_a2dp(struct userdata *u) {
     return 0;
 }
 
-static int bt_transport_config(struct userdata *u) {
+static int bt_transport_config(struct bluetooth_device *u) {
     if (u->profile == PROFILE_HSP || u->profile == PROFILE_HFGW) {
         u->block_size = u->link_mtu;
         u->sample_spec.format = PA_SAMPLE_S16LE;
@@ -2276,7 +2305,7 @@ static int bt_transport_config(struct userdata *u) {
 }
 
 /* Run from main thread */
-static int bt_transport_open(struct userdata *u) {
+static int bt_transport_open(struct bluetooth_device *u) {
     if (bt_transport_acquire(u, FALSE) < 0)
         return -1;
 
@@ -2284,7 +2313,7 @@ static int bt_transport_open(struct userdata *u) {
 }
 
 /* Run from main thread */
-static int init_bt(struct userdata *u) {
+static int init_bt(struct bluetooth_device *u) {
     pa_assert(u);
 
     shutdown_bt(u);
@@ -2304,7 +2333,7 @@ static int init_bt(struct userdata *u) {
 }
 
 /* Run from main thread */
-static int setup_bt(struct userdata *u) {
+static int setup_bt(struct bluetooth_device *u) {
     const pa_bluetooth_device *d;
     const pa_bluetooth_transport *t;
 
@@ -2350,7 +2379,7 @@ static int setup_bt(struct userdata *u) {
 }
 
 /* Run from main thread */
-static int init_profile(struct userdata *u) {
+static int init_profile(struct bluetooth_device *u) {
     int r = 0;
     pa_assert(u);
     pa_assert(u->profile != PROFILE_OFF);
@@ -2374,7 +2403,7 @@ static int init_profile(struct userdata *u) {
 }
 
 /* Run from main thread */
-static void stop_thread(struct userdata *u) {
+static void stop_thread(struct bluetooth_device *u) {
     char *k;
 
     pa_assert(u);
@@ -2436,7 +2465,7 @@ static void stop_thread(struct userdata *u) {
 }
 
 /* Run from main thread */
-static int start_thread(struct userdata *u) {
+static int start_thread(struct bluetooth_device *u) {
     pa_assert(u);
     pa_assert(!u->thread);
     pa_assert(!u->rtpoll);
@@ -2497,7 +2526,7 @@ static int start_thread(struct userdata *u) {
     return 0;
 }
 
-static void save_sco_volume_callbacks(struct userdata *u) {
+static void save_sco_volume_callbacks(struct bluetooth_device *u) {
     pa_assert(u);
     pa_assert(USE_SCO_OVER_PCM(u));
 
@@ -2505,7 +2534,7 @@ static void save_sco_volume_callbacks(struct userdata *u) {
     u->hsp.sco_source_set_volume = u->hsp.sco_source->set_volume;
 }
 
-static void restore_sco_volume_callbacks(struct userdata *u) {
+static void restore_sco_volume_callbacks(struct bluetooth_device *u) {
     pa_assert(u);
     pa_assert(USE_SCO_OVER_PCM(u));
 
@@ -2515,7 +2544,7 @@ static void restore_sco_volume_callbacks(struct userdata *u) {
 
 /* Run from main thread */
 static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
-    struct userdata *u;
+    struct bluetooth_device *u;
     enum profile *d;
     pa_queue *inputs = NULL, *outputs = NULL;
     const pa_bluetooth_device *device;
@@ -2608,7 +2637,7 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
 }
 
 /* Run from main thread */
-static int add_card(struct userdata *u, const pa_bluetooth_device *device) {
+static int add_card(struct bluetooth_device *u, const pa_bluetooth_device *device) {
     pa_card_new_data data;
     pa_bool_t b;
     pa_card_profile *p;
@@ -2753,7 +2782,7 @@ static int add_card(struct userdata *u, const pa_bluetooth_device *device) {
 }
 
 /* Run from main thread */
-static const pa_bluetooth_device* find_device(struct userdata *u, const char *address, const char *path) {
+static const pa_bluetooth_device* find_device(struct bluetooth_device *u, const char *address, const char *path) {
     const pa_bluetooth_device *d = NULL;
 
     pa_assert(u);
@@ -2790,7 +2819,7 @@ static const pa_bluetooth_device* find_device(struct userdata *u, const char *ad
 }
 
 /* Run from main thread */
-static int setup_dbus(struct userdata *u) {
+static int setup_dbus(struct bluetooth_device *u) {
     DBusError err;
 
     dbus_error_init(&err);
@@ -2809,7 +2838,7 @@ static int setup_dbus(struct userdata *u) {
 int pa__init(pa_module* m) {
     pa_modargs *ma;
     uint32_t channels;
-    struct userdata *u;
+    struct bluetooth_device *u;
     const char *address, *path;
     DBusError err;
     char *mike, *speaker, *transport;
@@ -2824,13 +2853,16 @@ int pa__init(pa_module* m) {
         goto fail;
     }
 
-    m->userdata = u = pa_xnew0(struct userdata, 1);
+    u = pa_msgobject_new(bluetooth_device);
+    memset(((char*)u)+sizeof(u->parent), 0, sizeof(*u)-sizeof(u->parent));
+    m->userdata = u;
     u->module = m;
     u->core = m->core;
     u->service_fd = -1;
     u->stream_fd = -1;
     u->sample_spec = m->core->default_sample_spec;
     u->modargs = ma;
+    u->parent.process_msg = device_process_msg;
 
     if (pa_modargs_get_value(ma, "sco_sink", NULL) &&
         !(u->hsp.sco_sink = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sco_sink", NULL), PA_NAMEREG_SINK))) {
@@ -2933,7 +2965,7 @@ fail:
 }
 
 int pa__get_n_used(pa_module *m) {
-    struct userdata *u;
+    struct bluetooth_device *u;
 
     pa_assert(m);
     pa_assert_se(u = m->userdata);
@@ -2944,7 +2976,7 @@ int pa__get_n_used(pa_module *m) {
 }
 
 void pa__done(pa_module *m) {
-    struct userdata *u;
+    struct bluetooth_device *u;
 
     pa_assert(m);
 
-- 
1.7.4.1



More information about the pulseaudio-discuss mailing list