summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2007-08-27 12:05:10 +0000
committerJohan Hedberg <johan.hedberg@nokia.com>2007-08-27 12:05:10 +0000
commit296dcf42cf8a4f4d6f0192cac58a28887be38552 (patch)
treebd763ff8a417c9286896b2e53a782681cfae76c8
parente1bfc91de96a38616100cc31db7bdb69f2cfbea6 (diff)
First try at device autocreate support
-rw-r--r--audio/a2dp.c2
-rw-r--r--audio/main.c1
-rw-r--r--audio/manager.c31
-rw-r--r--audio/manager.h5
-rw-r--r--audio/unix.c77
5 files changed, 87 insertions, 29 deletions
diff --git a/audio/a2dp.c b/audio/a2dp.c
index 9dfa2aeb..d3cedefc 100644
--- a/audio/a2dp.c
+++ b/audio/a2dp.c
@@ -35,8 +35,8 @@
#include <bluetooth/sdp_lib.h>
#include "logging.h"
-#include "manager.h"
#include "device.h"
+#include "manager.h"
#include "avdtp.h"
#include "sink.h"
#include "a2dp.h"
diff --git a/audio/main.c b/audio/main.c
index 3ca2ba40..ae43f170 100644
--- a/audio/main.c
+++ b/audio/main.c
@@ -38,6 +38,7 @@
#include "dbus.h"
#include "logging.h"
#include "unix.h"
+#include "device.h"
#include "manager.h"
static gboolean disable_hfp = TRUE;
diff --git a/audio/manager.c b/audio/manager.c
index b918ebba..ac4528f7 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -87,6 +87,9 @@ struct audio_sdp_data {
GSList *records; /* sdp_record_t * */
audio_sdp_state_t state;
+
+ create_dev_cb_t cb;
+ void *cb_data;
};
static DBusConnection *connection = NULL;
@@ -334,8 +337,13 @@ update:
}
done:
- if (!success)
+ if (success) {
+ if (data->cb)
+ data->cb(data->device, data->cb_data);
+ } else {
remove_device(data->device);
+ data->cb(NULL, data->cb_data);
+ }
if (data->msg)
dbus_message_unref(data->msg);
g_slist_foreach(data->handles, (GFunc) g_free, NULL);
@@ -570,7 +578,9 @@ failed:
}
static DBusHandlerResult resolve_services(DBusMessage *msg,
- struct device *device)
+ struct device *device,
+ create_dev_cb_t cb,
+ void *user_data)
{
struct audio_sdp_data *sdp_data;
@@ -578,6 +588,8 @@ static DBusHandlerResult resolve_services(DBusMessage *msg,
if (msg)
sdp_data->msg = dbus_message_ref(msg);
sdp_data->device = device;
+ sdp_data->cb = cb;
+ sdp_data->cb_data = user_data;
return get_handles(GENERIC_AUDIO_UUID, sdp_data);
}
@@ -628,7 +640,7 @@ struct device *manager_device_connected(bdaddr_t *bda, const char *uuid)
"DeviceCreated",
DBUS_TYPE_STRING, &path,
DBUS_TYPE_INVALID);
- resolve_services(NULL, device);
+ resolve_services(NULL, device, NULL, NULL);
}
if (headset)
@@ -699,6 +711,15 @@ static gboolean device_matches(struct device *device, char **interfaces)
return TRUE;
}
+void manager_create_device(bdaddr_t *bda, create_dev_cb_t cb,
+ void *user_data)
+{
+ struct device *dev;
+
+ dev = create_device(bda);
+ resolve_services(NULL, dev, cb, user_data);
+}
+
static DBusHandlerResult am_create_device(DBusConnection *conn,
DBusMessage *msg,
void *data)
@@ -725,7 +746,7 @@ static DBusHandlerResult am_create_device(DBusConnection *conn,
device = manager_find_device(&bda, NULL, FALSE);
if (!device) {
device = create_device(&bda);
- return resolve_services(msg, device);
+ return resolve_services(msg, device, NULL, NULL);
}
path = device->path;
@@ -849,8 +870,8 @@ static DBusHandlerResult am_remove_device(DBusConnection *conn,
return DBUS_HANDLER_RESULT_NEED_MEMORY;
device = match->data;
- remove_device(device);
device_remove_stored(device);
+ remove_device(device);
/* Fallback to a valid default */
if (default_dev == NULL) {
diff --git a/audio/manager.h b/audio/manager.h
index 623a778c..42632d17 100644
--- a/audio/manager.h
+++ b/audio/manager.h
@@ -34,6 +34,8 @@ struct enabled_interfaces {
gboolean target;
};
+typedef void (*create_dev_cb_t) (struct device *dev, void *user_data);
+
int audio_init(DBusConnection *conn, struct enabled_interfaces *enabled,
gboolean no_hfp, gboolean sco_hci);
@@ -47,6 +49,9 @@ struct device *manager_find_device(bdaddr_t *bda, const char *interface,
struct device *manager_device_connected(bdaddr_t *bda, const char *uuid);
+void manager_create_device(bdaddr_t *bda, create_dev_cb_t cb,
+ void *user_data);
+
gboolean manager_authorize(bdaddr_t *dba, const char *uuid,
DBusPendingCallNotifyFunction cb,
void *user_data,
diff --git a/audio/unix.c b/audio/unix.c
index 9fa5fc08..1d1a0b6a 100644
--- a/audio/unix.c
+++ b/audio/unix.c
@@ -68,6 +68,7 @@ struct unix_client {
struct device *dev;
struct avdtp_local_sep *sep;
service_type_t type;
+ char *interface;
union {
struct a2dp_data a2dp;
void *data;
@@ -104,6 +105,7 @@ static void client_free(struct unix_client *client)
if (client->sock >= 0)
close(client->sock);
+ g_free(client->interface);
g_free(client);
}
@@ -377,32 +379,12 @@ failed:
a2dp->stream = NULL;
}
-static void cfg_event(struct unix_client *client, struct ipc_packet *pkt,
- int len)
+static void create_stream(struct device *dev, struct unix_client *client)
{
- struct device *dev;
- unsigned int id;
struct a2dp_data *a2dp;
- bdaddr_t bdaddr;
- const char *interface = NULL;
-
- str2ba(pkt->device, &bdaddr);
-
- if (pkt->role == PKT_ROLE_VOICE)
- interface = AUDIO_HEADSET_INTERFACE;
- else if (pkt->role == PKT_ROLE_HIFI)
- interface = AUDIO_SINK_INTERFACE;
-
- dev = manager_find_device(&bdaddr, interface, TRUE);
- if (dev)
- goto proceed;
-
- dev = manager_find_device(&bdaddr, interface, FALSE);
- if (!dev)
- goto failed;
+ unsigned int id;
-proceed:
- client->type = select_service(dev, interface);
+ client->type = select_service(dev, client->interface);
switch (client->type) {
case TYPE_SINK:
@@ -443,6 +425,55 @@ failed:
unix_send_cfg(client->sock, NULL, -1);
}
+static void create_cb(struct device *dev, void *user_data)
+{
+ struct unix_client *client = user_data;
+
+ if (!dev)
+ unix_send_cfg(client->sock, NULL, -1);
+ else
+ create_stream(dev, client);
+}
+
+static void cfg_event(struct unix_client *client, struct ipc_packet *pkt,
+ int len)
+{
+ struct device *dev;
+ bdaddr_t bdaddr;
+
+ str2ba(pkt->device, &bdaddr);
+
+ if (client->interface) {
+ g_free(client->interface);
+ client->interface = NULL;
+ }
+
+ if (pkt->role == PKT_ROLE_VOICE)
+ client->interface = g_strdup(AUDIO_HEADSET_INTERFACE);
+ else if (pkt->role == PKT_ROLE_HIFI)
+ client->interface = g_strdup(AUDIO_SINK_INTERFACE);
+
+ if (!manager_find_device(&bdaddr, NULL, FALSE)) {
+ if (!bacmp(&bdaddr, BDADDR_ANY))
+ goto failed;
+ manager_create_device(&bdaddr, create_cb, client);
+ return;
+ }
+
+ dev = manager_find_device(&bdaddr, client->interface, TRUE);
+ if (!dev)
+ dev = manager_find_device(&bdaddr, client->interface, FALSE);
+
+ if (!dev)
+ goto failed;
+
+ create_stream(dev, client);
+ return;
+
+failed:
+ unix_send_cfg(client->sock, NULL, -1);
+}
+
static void ctl_event(struct unix_client *client, struct ipc_packet *pkt,
int len)
{