From 296dcf42cf8a4f4d6f0192cac58a28887be38552 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 27 Aug 2007 12:05:10 +0000 Subject: First try at device autocreate support --- audio/a2dp.c | 2 +- audio/main.c | 1 + audio/manager.c | 31 +++++++++++++++++++---- audio/manager.h | 5 ++++ audio/unix.c | 77 ++++++++++++++++++++++++++++++++++++++++----------------- 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 #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) { -- cgit