[PATCH v2 12/12] android/handsfree: Make remote device non-static

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Remote device object is now created on-demand instead of being static.
---
 android/handsfree.c | 121 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 70 insertions(+), 51 deletions(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index 1381929..356dbe0 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -37,6 +37,8 @@
 #include "src/sdp-client.h"
 #include "src/uuid-helper.h"
 #include "src/shared/hfp.h"
+#include "src/shared/queue.h"
+#include "src/shared/util.h"
 #include "btio/btio.h"
 #include "hal-msg.h"
 #include "ipc-common.h"
@@ -155,7 +157,7 @@ static const struct hfp_codec codecs_defaults[] = {
 	{ CODEC_ID_MSBC, false, false},
 };
 
-static struct hf_device device;
+static struct queue *devices = NULL;
 
 static uint32_t hfp_ag_features = 0;
 
@@ -220,64 +222,71 @@ static void init_codecs(struct hf_device *dev)
 		dev->codecs[MSBC_OFFSET].local_supported = true;
 }
 
-static void device_init(struct hf_device *dev, const bdaddr_t *bdaddr)
+static struct hf_device *device_create(const bdaddr_t *bdaddr)
 {
-	bacpy(&dev->bdaddr, bdaddr);
+	struct hf_device *dev;
+
+	dev = new0(struct hf_device, 1);
+	if (!dev)
+		return NULL;
 
+	bacpy(&dev->bdaddr, bdaddr);
 	dev->setup_state = HAL_HANDSFREE_CALL_STATE_IDLE;
+	dev->state = HAL_EV_HANDSFREE_CONN_STATE_DISCONNECTED;
+	dev->audio_state = HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED;
 
 	memcpy(dev->inds, inds_defaults, sizeof(dev->inds));
 
 	init_codecs(dev);
 
-	set_state(dev, HAL_EV_HANDSFREE_CONN_STATE_CONNECTING);
+	if (!queue_push_head(devices, dev)) {
+		free(dev);
+		return NULL;
+	}
+
+	return dev;
 }
 
-static void device_cleanup(struct hf_device *dev)
+static void device_destroy(struct hf_device *dev)
 {
-	if (dev->gw) {
-		hfp_gw_unref(dev->gw);
-		dev->gw = NULL;
-	}
+	hfp_gw_unref(dev->gw);
 
-	set_state(dev, HAL_EV_HANDSFREE_CONN_STATE_DISCONNECTED);
-
-	if (dev->sco_watch) {
+	if (dev->sco_watch)
 		g_source_remove(dev->sco_watch);
-		dev->sco_watch = 0;
-	}
 
 	if (dev->sco) {
 		g_io_channel_shutdown(dev->sco, TRUE, NULL);
 		g_io_channel_unref(dev->sco);
-		dev->sco = NULL;
 	}
 
-	if (dev->ring) {
-		g_source_remove(dev->ring);
-		dev->ring = 0;
-
-		g_free(dev->clip);
-	}
+	g_source_remove(dev->ring);
+	g_free(dev->clip);
 
 	set_audio_state(dev, HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED);
+	set_state(dev, HAL_EV_HANDSFREE_CONN_STATE_DISCONNECTED);
 
-	memset(dev, 0, sizeof(*dev));
+	queue_remove(devices, dev);
+	free(dev);
 }
 
 static struct hf_device *find_default_device(void)
 {
 	/* TODO should be replaced by find_device() eventually */
 
-	return &device;
+	return queue_peek_head(devices);
 }
 
-static struct hf_device *find_device(const bdaddr_t *bdaddr)
+static bool match_by_bdaddr(const void *data, const void *match_data)
 {
-	if (bacmp(&device.bdaddr, bdaddr))
-		return NULL;
+	const struct hf_device *dev = data;
+	const bdaddr_t *addr = match_data;
 
-	return &device;
+	return !bacmp(&dev->bdaddr, addr);
+}
+
+static struct hf_device *find_device(const bdaddr_t *bdaddr)
+{
+	return queue_find(devices, match_by_bdaddr, bdaddr);
 }
 
 static struct hf_device *get_device(const bdaddr_t *bdaddr)
@@ -288,7 +297,11 @@ static struct hf_device *get_device(const bdaddr_t *bdaddr)
 	if (dev)
 		return dev;
 
-	return &device;
+	/* TODO For now allow only 1 remote device */
+	if (!queue_isempty(devices))
+		return NULL;
+
+	return device_create(bdaddr);
 }
 
 static void disconnect_watch(void *user_data)
@@ -297,7 +310,7 @@ static void disconnect_watch(void *user_data)
 
 	DBG("");
 
-	device_cleanup(dev);
+	device_destroy(dev);
 }
 
 static void at_cmd_unknown(const char *command, void *user_data)
@@ -1418,7 +1431,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 
 failed:
 	g_io_channel_shutdown(chan, TRUE, NULL);
-	device_cleanup(dev);
+	device_destroy(dev);
 }
 
 static void confirm_cb(GIOChannel *chan, gpointer data)
@@ -1451,15 +1464,16 @@ static void confirm_cb(GIOChannel *chan, gpointer data)
 		goto drop;
 	}
 
-	device_init(dev, &bdaddr);
-
 	if (!bt_io_accept(chan, connect_cb, dev, NULL, NULL)) {
 		error("handsfree: failed to accept connection");
-		device_cleanup(dev);
+		device_destroy(dev);
 		goto drop;
 	}
 
 	dev->hsp = GPOINTER_TO_INT(data);
+
+	set_state(dev, HAL_EV_HANDSFREE_CONN_STATE_CONNECTING);
+
 	return;
 
 drop:
@@ -1538,7 +1552,7 @@ static void sdp_hsp_search_cb(sdp_list_t *recs, int err, gpointer data)
 	return;
 
 fail:
-	device_cleanup(dev);
+	device_destroy(dev);
 }
 
 static int sdp_search_hsp(struct hf_device *dev)
@@ -1626,7 +1640,7 @@ static void sdp_hfp_search_cb(sdp_list_t *recs, int err, gpointer data)
 	return;
 
 fail:
-	device_cleanup(dev);
+	device_destroy(dev);
 }
 
 static int sdp_search_hfp(struct hf_device *dev)
@@ -1650,13 +1664,8 @@ static void handle_connect(const void *buf, uint16_t len)
 
 	DBG("");
 
-	dev = find_default_device();
-	if (dev) {
-		status = HAL_STATUS_FAILED;
-		goto failed;
-	}
-
 	android2bdaddr(&cmd->bdaddr, &bdaddr);
+
 	dev = get_device(&bdaddr);
 	if (!dev) {
 		status = HAL_STATUS_FAILED;
@@ -1671,17 +1680,17 @@ static void handle_connect(const void *buf, uint16_t len)
 	ba2str(&bdaddr, addr);
 	DBG("connecting to %s", addr);
 
-	device_init(dev, &bdaddr);
-
 	/* prefer HFP over HSP */
 	ret = hfp_server ? sdp_search_hfp(dev) : sdp_search_hsp(dev);
 	if (ret < 0) {
 		error("handsfree: SDP search failed");
-		device_cleanup(dev);
+		device_destroy(dev);
 		status = HAL_STATUS_FAILED;
 		goto failed;
 	}
 
+	set_state(dev, HAL_EV_HANDSFREE_CONN_STATE_CONNECTING);
+
 	status = HAL_STATUS_SUCCESS;
 
 failed:
@@ -1717,7 +1726,7 @@ static void handle_disconnect(const void *buf, uint16_t len)
 	}
 
 	if (dev->state == HAL_EV_HANDSFREE_CONN_STATE_CONNECTING) {
-		device_cleanup(dev);
+		device_destroy(dev);
 	} else {
 		set_state(dev, HAL_EV_HANDSFREE_CONN_STATE_DISCONNECTING);
 		hfp_gw_disconnect(dev->gw);
@@ -2845,13 +2854,15 @@ bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 
 	bacpy(&adapter_addr, addr);
 
-	if (!enable_hsp_ag())
+	devices = queue_new();
+	if (!devices)
 		return false;
 
-	if (!enable_sco_server()) {
-		cleanup_hsp_ag();
-		return false;
-	}
+	if (!enable_hsp_ag())
+		goto failed_queue;
+
+	if (!enable_sco_server())
+		goto failed_hsp;
 
 	if (mode == HAL_MODE_HANDSFREE_HSP_ONLY)
 		goto done;
@@ -2864,9 +2875,14 @@ bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 	if (enable_hfp_ag())
 		goto done;
 
-	cleanup_hsp_ag();
 	disable_sco_server();
 	hfp_ag_features = 0;
+failed_hsp:
+	cleanup_hsp_ag();
+failed_queue:
+	queue_destroy(devices, NULL);
+	devices = NULL;
+
 	return false;
 
 done:
@@ -2892,4 +2908,7 @@ void bt_handsfree_unregister(void)
 	disable_sco_server();
 
 	hfp_ag_features = 0;
+
+	queue_destroy(devices, (queue_destroy_func_t) device_destroy);
+	devices = NULL;
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux