[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