Hi, Attached is a tentative patch proposal, I'm not sure how to make this modification in a good way. Maybe the check for G_IO_NVAL in sco_cb should not be removed, but that is the GIOCondition the callback receives when shutting down the SCO socket. It was added in commit http://git.kernel.org/?p=bluetooth/bluez.git;a=commit;h=6834de18b98fea0e7d370a296318115a659047af Br, Daniel
From 608c2d4322fa2a9dbe61f6c97cacd4c73f9d26ef Mon Sep 17 00:00:00 2001 From: Daniel Orstadius <daniel.orstadius@xxxxxxxxx> Date: Thu, 24 Feb 2011 12:31:34 +0200 Subject: [PATCH] Close SCO before headset interface state change When the SCO connection is released by the MediaTransport interface, wait for the SCO callback before entering the HEADSET_STATE_CONNECTED state. The reason for the patch is to notify the headset state change on D-Bus at a later stage in the SCO disconnection process. In case the user of the Media interface wants to start sending audio over A2DP, the audio routing switch can be delayed until the D-Bus signal is received (some headsets have issues if AVDTP Start is sent before or while the SCO link is being disconnected). --- audio/headset.c | 15 ++++++--------- 1 files changed, 6 insertions(+), 9 deletions(-) diff --git a/audio/headset.c b/audio/headset.c index bdaa8da..ec6ef08 100644 --- a/audio/headset.c +++ b/audio/headset.c @@ -1233,7 +1233,7 @@ static int handle_event(struct audio_device *device, const char *buf) return -EINVAL; } -static void close_sco(struct audio_device *device) +static void close_sco(struct audio_device *device, gboolean remove_callback) { struct headset *hs = device->headset; @@ -1245,7 +1245,7 @@ static void close_sco(struct audio_device *device) hs->sco = NULL; } - if (hs->sco_id) { + if (remove_callback && hs->sco_id) { g_source_remove(hs->sco_id); hs->sco_id = 0; } @@ -1340,9 +1340,6 @@ failed: static gboolean sco_cb(GIOChannel *chan, GIOCondition cond, struct audio_device *device) { - if (cond & G_IO_NVAL) - return FALSE; - error("Audio connection got disconnected"); headset_set_state(device, HEADSET_STATE_CONNECTED); @@ -2142,7 +2139,7 @@ static void headset_free(struct audio_device *dev) hs->dc_timer = 0; } - close_sco(dev); + close_sco(dev, TRUE); headset_close_rfcomm(dev); @@ -2474,7 +2471,7 @@ void headset_set_state(struct audio_device *dev, headset_state_t state) switch (state) { case HEADSET_STATE_DISCONNECTED: value = FALSE; - close_sco(dev); + close_sco(dev, TRUE); headset_close_rfcomm(dev); emit_property_changed(dev->conn, dev->path, AUDIO_HEADSET_INTERFACE, "State", @@ -2497,7 +2494,7 @@ void headset_set_state(struct audio_device *dev, headset_state_t state) DBUS_TYPE_STRING, &state_str); break; case HEADSET_STATE_CONNECTED: - close_sco(dev); + close_sco(dev, TRUE); if (hs->state != HEADSET_STATE_PLAY_IN_PROGRESS) emit_property_changed(dev->conn, dev->path, AUDIO_HEADSET_INTERFACE, "State", @@ -2622,7 +2619,7 @@ gboolean headset_unlock(struct audio_device *dev, headset_lock_t lock) return TRUE; if (hs->state == HEADSET_STATE_PLAYING) - headset_set_state(dev, HEADSET_STATE_CONNECTED); + close_sco(dev, FALSE); if (hs->auto_dc) { if (hs->state == HEADSET_STATE_CONNECTED) -- 1.6.0.4