From e32c8dcd38b8e2282559a325c59fd6b7fa187d2f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 24 Oct 2008 12:19:47 +0300 Subject: Limit the amount of connected HSP/HFP devices and make it configurable It's very tricky to get the multiple connected HSP/HFP devices use case right. E.g. in the case of in-band ringtone the specification mandates us to open SCO to the HFP before sending RING indications. So, in the case of multiple connected devices we would have to open multimple simultaneous SCO connections which simply isn't a wise thing to do. --- audio/audio.conf | 3 +++ audio/headset.c | 4 ++++ audio/manager.c | 39 +++++++++++++++++++++++++++++++++++++++ audio/manager.h | 2 ++ 4 files changed, 48 insertions(+) diff --git a/audio/audio.conf b/audio/audio.conf index f50c826d..33a84e1e 100644 --- a/audio/audio.conf +++ b/audio/audio.conf @@ -23,6 +23,9 @@ # Defaults to false HFP=false +# Maximum number of connected HSP/HFP devices per adapter. Defaults to 1 +MaxConnections=1 + # Just an example of potential config options for the other interfaces #[A2DP] #SBCSources=1 diff --git a/audio/headset.c b/audio/headset.c index 77498d73..0a7f18ed 100644 --- a/audio/headset.c +++ b/audio/headset.c @@ -1466,6 +1466,10 @@ static DBusMessage *hs_connect(DBusConnection *conn, DBusMessage *msg, return g_dbus_create_error(msg, ERROR_INTERFACE ".NotReady", "Telephony subsystem not ready"); + if (!manager_allow_headset_connection(&device->src)) + return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAllowed", + "Too many connected devices"); + err = rfcomm_connect(device, NULL, NULL, NULL); if (err < 0) return g_dbus_create_error(msg, ERROR_INTERFACE diff --git a/audio/manager.c b/audio/manager.c index ae63b997..4441b90f 100644 --- a/audio/manager.c +++ b/audio/manager.c @@ -97,6 +97,7 @@ struct audio_adapter { GIOChannel *hsp_hs_server; }; +static int max_connected_headsets = 1; static DBusConnection *connection = NULL; static GKeyFile *config = NULL; static GSList *adapters = NULL; @@ -452,6 +453,9 @@ static void ag_io_cb(GIOChannel *chan, int err, const bdaddr_t *src, if (!device) goto drop; + if (!manager_allow_headset_connection(&device->src)) + goto drop; + if (!device->headset) btd_device_add_uuid(device->btd_dev, remote_uuid); @@ -919,6 +923,16 @@ int audio_manager_init(DBusConnection *conn, GKeyFile *conf) } else enabled.hfp = b; + err = NULL; + i = g_key_file_get_integer(config, "Headset", "MaxConnected", + &err); + if (err) { + debug("audio.conf: %s", err->message); + g_error_free(err); + err = NULL; + } else + max_connected_headsets = i; + proceed: if (enabled.headset) { telephony_init(); @@ -1062,3 +1076,28 @@ struct audio_device *manager_get_device(const bdaddr_t *src, return dev; } + +gboolean manager_allow_headset_connection(bdaddr_t *src) +{ + GSList *l; + int connected = 0; + + for (l = devices; l != NULL; l = l->next) { + struct audio_device *dev = l->data; + struct headset *hs = dev->headset; + + if (bacmp(&dev->src, src)) + continue; + + if (!hs) + continue; + + if (headset_get_state(dev) > HEADSET_STATE_DISCONNECTED) + connected++; + + if (connected > max_connected_headsets) + return FALSE; + } + + return TRUE; +} diff --git a/audio/manager.h b/audio/manager.h index 6dfd7ef3..e56ec3b3 100644 --- a/audio/manager.h +++ b/audio/manager.h @@ -41,3 +41,5 @@ struct audio_device *manager_find_device(const bdaddr_t *bda, const char *interf struct audio_device *manager_get_device(const bdaddr_t *src, const bdaddr_t *dst); + +gboolean manager_allow_headset_connection(bdaddr_t *src); -- cgit