diff --git a/android/handsfree.c b/android/handsfree.c
index 1381929..356dbe0 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
#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"
{ CODEC_ID_MSBC, false, false},
};
-static struct hf_device device;
+static struct queue *devices = NULL;
static uint32_t hfp_ag_features = 0;
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)
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)
DBG("");
- device_cleanup(dev);
+ device_destroy(dev);
}
static void at_cmd_unknown(const char *command, void *user_data)
failed:
g_io_channel_shutdown(chan, TRUE, NULL);
- device_cleanup(dev);
+ device_destroy(dev);
}
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:
return;
fail:
- device_cleanup(dev);
+ device_destroy(dev);
}
static int sdp_search_hsp(struct hf_device *dev)
return;
fail:
- device_cleanup(dev);
+ device_destroy(dev);
}
static int sdp_search_hfp(struct hf_device *dev)
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;
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:
}
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);
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;
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:
disable_sco_server();
hfp_ag_features = 0;
+
+ queue_destroy(devices, (queue_destroy_func_t) device_destroy);
+ devices = NULL;
}