summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/a2dp.c2
-rw-r--r--audio/control.c19
-rw-r--r--audio/device.c332
-rw-r--r--audio/device.h14
-rw-r--r--audio/headset.c3
-rw-r--r--audio/main.c90
-rw-r--r--audio/manager.c816
-rw-r--r--audio/manager.h2
-rw-r--r--audio/sink.c3
-rw-r--r--audio/unix.c30
10 files changed, 99 insertions, 1212 deletions
diff --git a/audio/a2dp.c b/audio/a2dp.c
index 3e89d6b1..5e8cfd85 100644
--- a/audio/a2dp.c
+++ b/audio/a2dp.c
@@ -137,7 +137,7 @@ static struct audio_device *a2dp_get_dev(struct avdtp *session)
avdtp_get_peers(session, NULL, &addr);
- return manager_device_connected(&addr, A2DP_SOURCE_UUID);
+ return manager_find_device(&addr, NULL, FALSE);
}
static gboolean finalize_config(struct a2dp_setup *s)
diff --git a/audio/control.c b/audio/control.c
index 9139213b..02fb8cd1 100644
--- a/audio/control.c
+++ b/audio/control.c
@@ -583,17 +583,15 @@ static int uinput_create(char *name)
static void init_uinput(struct avctp *session)
{
- char address[18], *name;
+ char address[18];
ba2str(&session->dst, address);
- name = session->dev->name ? session->dev->name : address;
-
- session->uinput = uinput_create(name);
+ session->uinput = uinput_create(address);
if (session->uinput < 0)
- error("AVRCP: failed to init uinput for %s", name);
+ error("AVRCP: failed to init uinput for %s", address);
else
- debug("AVRCP: uinput initialized for %s", name);
+ debug("AVRCP: uinput initialized for %s", address);
}
static void avctp_connect_session(struct avctp *session)
@@ -601,8 +599,10 @@ static void avctp_connect_session(struct avctp *session)
GIOChannel *io;
session->state = AVCTP_STATE_CONNECTED;
- session->dev = manager_device_connected(&session->dst,
- AVRCP_TARGET_UUID);
+ session->dev = manager_find_device(&session->dst, NULL, FALSE);
+ if (!session->dev)
+ return;
+
session->dev->control->session = session;
init_uinput(session);
@@ -923,6 +923,9 @@ struct control *control_init(struct audio_device *dev)
dev, NULL))
return NULL;
+ info("Registered interface %s on path %s",
+ AUDIO_CONTROL_INTERFACE, dev->path);
+
return g_new0(struct control, 1);
}
diff --git a/audio/device.c b/audio/device.c
index 2f5f834f..19ce3b41 100644
--- a/audio/device.c
+++ b/audio/device.c
@@ -54,114 +54,6 @@
#include "headset.h"
#include "sink.h"
-static DBusMessage *device_get_address(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct audio_device *device = data;
- DBusMessage *reply;
- char address[18], *ptr = address;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- ba2str(&device->dst, address);
-
- dbus_message_append_args(reply, DBUS_TYPE_STRING, &ptr,
- DBUS_TYPE_INVALID);
-
- return reply;
-}
-
-static char *get_dev_name(DBusConnection *conn, const bdaddr_t *src,
- const bdaddr_t *bda)
-{
- char address[18], filename[PATH_MAX + 1];
-
- ba2str(src, address);
-
- /* check if it is in the cache */
- create_name(filename, PATH_MAX, STORAGEDIR, address, "names");
-
- ba2str(bda, address);
- return textfile_caseget(filename, address);
-}
-
-static DBusMessage *device_get_name(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct audio_device *dev = data;
- DBusMessage *reply;
- const char *name = dev->name ? dev->name : "";
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- dbus_message_append_args(reply, DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INVALID);
-
- return reply;
-}
-
-static DBusMessage *device_get_adapter(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct audio_device *device = data;
- DBusMessage *reply;
- char address[18], *ptr = address;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- ba2str(&device->src, address);
-
- dbus_message_append_args(reply, DBUS_TYPE_STRING, &ptr,
- DBUS_TYPE_INVALID);
-
- return reply;
-}
-
-
-static DBusMessage *device_get_connected(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- DBusMessageIter iter, array_iter;
- struct audio_device *device = data;
- DBusMessage *reply;
- const char *iface;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- dbus_message_iter_init_append(reply, &iter);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_TYPE_STRING_AS_STRING,
- &array_iter);
-
- if (device->headset &&
- headset_get_state(device) >= HEADSET_STATE_CONNECTED) {
- iface = AUDIO_HEADSET_INTERFACE;
- dbus_message_iter_append_basic(&array_iter,
- DBUS_TYPE_STRING, &iface);
- }
-
- dbus_message_iter_close_container(&iter, &array_iter);
-
- return reply;
-}
-
-static GDBusMethodTable device_methods[] = {
- { "GetAddress", "", "s", device_get_address },
- { "GetName", "", "s", device_get_name },
- { "GetAdapter", "", "s", device_get_adapter },
- { "GetConnectedInterfaces", "", "as", device_get_connected },
- { }
-};
-
static void device_free(struct audio_device *dev)
{
if (dev->headset)
@@ -176,238 +68,29 @@ static void device_free(struct audio_device *dev)
if (dev->conn)
dbus_connection_unref(dev->conn);
- g_free(dev->adapter_path);
g_free(dev->path);
- g_free(dev->name);
-
g_free(dev);
}
-static void device_unregister(void *data)
-{
- struct audio_device *device = data;
-
- info("Unregistered device path:%s", device->path);
-
- device_free(device);
-}
-
struct audio_device *device_register(DBusConnection *conn,
- const char *path, const bdaddr_t *bda)
+ const char *path, const bdaddr_t *src,
+ const bdaddr_t *dst)
{
struct audio_device *dev;
- bdaddr_t src;
- int dev_id;
if (!conn || !path)
return NULL;
- bacpy(&src, BDADDR_ANY);
- dev_id = hci_get_route(&src);
- if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0))
- return NULL;
-
dev = g_new0(struct audio_device, 1);
- /* FIXME just to maintain compatibility */
- dev->adapter_path = g_strdup_printf("/org/bluez/hci%d", dev_id);
- if (!dev->adapter_path) {
- device_free(dev);
- return NULL;
- }
-
- if (!g_dbus_register_interface(conn, path,
- AUDIO_DEVICE_INTERFACE,
- device_methods, NULL, NULL,
- dev, device_unregister)) {
- error("Failed to register %s interface to %s",
- AUDIO_DEVICE_INTERFACE, path);
- device_free(dev);
- return NULL;
- }
-
- dev->name = get_dev_name(conn, &src, bda);
dev->path = g_strdup(path);
- bacpy(&dev->dst, bda);
- bacpy(&dev->src, &src);
- bacpy(&dev->store, &src);
+ bacpy(&dev->dst, dst);
+ bacpy(&dev->src, src);
dev->conn = dbus_connection_ref(conn);
return dev;
}
-int device_store(struct audio_device *dev, gboolean is_default)
-{
- char value[64];
- char filename[PATH_MAX + 1];
- char src_addr[18], dst_addr[18];
- int offset = 0;
-
- if (!dev->path)
- return -EINVAL;
-
- ba2str(&dev->dst, dst_addr);
- ba2str(&dev->store, src_addr);
-
- create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "audio");
- create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-
- if (is_default)
- textfile_put(filename, "default", dst_addr);
- if (dev->headset) {
- snprintf(value, 64, "headset ");
- offset += strlen("headset ");
- }
- if (dev->gateway) {
- snprintf(value + offset, 64 - offset, "gateway ");
- offset += strlen("gateway ");
- }
- if (dev->sink) {
- snprintf(value + offset, 64 - offset, "sink ");
- offset += strlen("sink ");
- }
- if (dev->source) {
- snprintf(value + offset, 64 - offset, "source ");
- offset += strlen("source ");
- }
- if (dev->control) {
- snprintf(value + offset, 64 - offset, "control ");
- offset += strlen("control ");
- }
- if (dev->target)
- snprintf(value + offset, 64 - offset, "target");
-
- return textfile_put(filename, dst_addr, value);
-}
-
-int device_remove_stored(struct audio_device *dev)
-{
- char filename[PATH_MAX + 1];
- char src_addr[18], dst_addr[18];
-
- ba2str(&dev->dst, dst_addr);
- ba2str(&dev->store, src_addr);
-
- create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "audio");
-
- return textfile_del(filename, dst_addr);
-}
-
-void device_finish_sdp_transaction(struct audio_device *dev)
-{
- char address[18], *addr_ptr = address;
- DBusMessage *msg;
-
- ba2str(&dev->dst, address);
-
- msg = dbus_message_new_method_call("org.bluez", dev->adapter_path,
- "org.bluez.Adapter",
- "FinishRemoteServiceTransaction");
- if (!msg) {
- error("Unable to allocate new method call");
- return;
- }
-
- dbus_message_append_args(msg, DBUS_TYPE_STRING, &addr_ptr,
- DBUS_TYPE_INVALID);
-
- dbus_connection_send(dev->conn, msg, NULL);
-
- dbus_message_unref(msg);
-}
-
-#if 0
-static avdtp_state_t ipc_to_avdtp_state(uint8_t ipc_state)
-{
- switch (ipc_state) {
- case STATE_DISCONNECTED:
- return AVDTP_STATE_IDLE;
- case STATE_CONNECTING:
- return AVDTP_STATE_CONFIGURED;
- case STATE_CONNECTED:
- return AVDTP_STATE_OPEN;
- case STATE_STREAM_STARTING:
- case STATE_STREAMING:
- return AVDTP_STATE_STREAMING;
- default:
- error("Unknown ipc state");
- return AVDTP_STATE_IDLE;
- }
-}
-
-static headset_state_t ipc_to_hs_state(uint8_t ipc_state)
-{
- switch (ipc_state) {
- case STATE_DISCONNECTED:
- return HEADSET_STATE_DISCONNECTED;
- case STATE_CONNECTING:
- return HEADSET_STATE_CONNECT_IN_PROGRESS;
- case STATE_CONNECTED:
- return HEADSET_STATE_CONNECTED;
- case STATE_STREAM_STARTING:
- return HEADSET_STATE_PLAY_IN_PROGRESS;
- case STATE_STREAMING:
- return HEADSET_STATE_PLAYING;
- default:
- error("Unknown ipc state");
- return HEADSET_STATE_DISCONNECTED;
- }
-}
-
-static uint8_t avdtp_to_ipc_state(avdtp_state_t state)
-{
- switch (state) {
- case AVDTP_STATE_IDLE:
- return STATE_DISCONNECTED;
- case AVDTP_STATE_CONFIGURED:
- return STATE_CONNECTING;
- case AVDTP_STATE_OPEN:
- return STATE_CONNECTED;
- case AVDTP_STATE_STREAMING:
- return STATE_STREAMING;
- default:
- error("Unknown avdt state");
- return AVDTP_STATE_IDLE;
- }
-}
-
-static uint8_t hs_to_ipc_state(headset_state_t state)
-{
- switch (state) {
- case HEADSET_STATE_DISCONNECTED:
- return STATE_DISCONNECTED;
- case HEADSET_STATE_CONNECT_IN_PROGRESS:
- return STATE_CONNECTING;
- case HEADSET_STATE_CONNECTED:
- return STATE_CONNECTED;
- case HEADSET_STATE_PLAY_IN_PROGRESS:
- return STATE_STREAMING;
- default:
- error("Unknown headset state");
- return AVDTP_STATE_IDLE;
- }
-}
-
-uint8_t device_get_state(struct audio_device *dev)
-{
- avdtp_state_t sink_state;
- headset_state_t hs_state;
-
- if (dev->sink && sink_is_active(dev)) {
- sink_state = sink_get_state(dev);
- return avdtp_to_ipc_state(sink_state);
- }
- else if (dev->headset && headset_is_active(dev)) {
- hs_state = headset_get_state(dev);
- return hs_to_ipc_state(hs_state);
- }
- else if (dev->control && control_is_active(dev))
- return STATE_CONNECTED;
-
- return STATE_DISCONNECTED;
-}
-#endif
-
gboolean device_is_connected(struct audio_device *dev, const char *interface)
{
if (!interface) {
@@ -433,3 +116,10 @@ gboolean device_is_connected(struct audio_device *dev, const char *interface)
return FALSE;
}
+
+void device_unregister(struct audio_device *device)
+{
+ g_dbus_unregister_all_interfaces(device->conn, device->path);
+
+ device_free(device);
+}
diff --git a/audio/device.h b/audio/device.h
index 5dc99b9d..96bb0705 100644
--- a/audio/device.h
+++ b/audio/device.h
@@ -54,10 +54,7 @@ struct gateway;
struct audio_device {
DBusConnection *conn;
- char *adapter_path;
char *path;
- char *name;
- bdaddr_t store;
bdaddr_t src;
bdaddr_t dst;
@@ -70,14 +67,9 @@ struct audio_device {
};
struct audio_device *device_register(DBusConnection *conn,
- const char *path, const bdaddr_t *bda);
+ const char *path, const bdaddr_t *src,
+ const bdaddr_t *dst);
-int device_store(struct audio_device *device, gboolean is_default);
-
-int device_remove_stored(struct audio_device *dev);
-
-void device_finish_sdp_transaction(struct audio_device *device);
-
-uint8_t device_get_state(struct audio_device *dev);
+void device_unregister(struct audio_device *device);
gboolean device_is_connected(struct audio_device *dev, const char *interface);
diff --git a/audio/headset.c b/audio/headset.c
index 0adc1e9d..7faab78c 100644
--- a/audio/headset.c
+++ b/audio/headset.c
@@ -1498,6 +1498,9 @@ register_iface:
return NULL;
}
+ info("Registered interface %s on path %s",
+ AUDIO_HEADSET_INTERFACE, dev->path);
+
return hs;
}
diff --git a/audio/main.c b/audio/main.c
index f0301c12..0d0257dc 100644
--- a/audio/main.c
+++ b/audio/main.c
@@ -35,86 +35,11 @@
#include <dbus/dbus.h>
#include "plugin.h"
-#include "../hcid/device.h"
#include "logging.h"
#include "unix.h"
#include "device.h"
#include "manager.h"
-static DBusConnection *conn;
-
-static int headset_probe(struct btd_device_driver *driver,
- struct btd_device *device, GSList *records)
-{
- const gchar *path = device_get_path(device);
- DBG("path %s", path);
-
- return 0;
-}
-
-static void headset_remove(struct btd_device_driver *driver,
- struct btd_device *device)
-{
- const gchar *path = device_get_path(device);
- DBG("path %s", path);
-}
-
-static struct btd_device_driver headset_driver = {
- .name = "headset",
- .uuids = BTD_UUIDS(HSP_HS_UUID, HFP_HS_UUID),
- .probe = headset_probe,
- .remove = headset_remove,
-};
-
-static int a2dp_probe(struct btd_device_driver *driver,
- struct btd_device *device, GSList *records)
-{
- const gchar *path = device_get_path(device);
- DBG("path %s", path);
-
- return 0;
-}
-
-static void a2dp_remove(struct btd_device_driver *driver,
- struct btd_device *device)
-{
- const gchar *path = device_get_path(device);
- DBG("path %s", path);
-}
-
-static struct btd_device_driver a2dp_driver = {
- .name = "sink",
- .uuids = BTD_UUIDS(A2DP_SINK_UUID),
- .probe = a2dp_probe,
- .remove = a2dp_remove,
-};
-
-static int audio_probe(struct btd_device_driver *driver,
- struct btd_device *device, GSList *records)
-{
- const gchar *path = device_get_path(device);
- DBG("path %s", path);
-
- return 0;
-}
-
-static void audio_remove(struct btd_device_driver *driver,
- struct btd_device *device)
-{
- const gchar *path = device_get_path(device);
- DBG("path %s", path);
-}
-
-static struct btd_device_driver audio_driver = {
- .name = "audio",
- .uuids = BTD_UUIDS(HSP_HS_UUID, HFP_HS_UUID, HSP_AG_UUID, HFP_AG_UUID,
- ADVANCED_AUDIO_UUID, A2DP_SOURCE_UUID, A2DP_SINK_UUID,
- AVRCP_TARGET_UUID, AVRCP_REMOTE_UUID),
- .probe = audio_probe,
- .remove = audio_remove,
-};
-
-
static GKeyFile *load_config_file(const char *file)
{
GError *err = NULL;
@@ -134,6 +59,7 @@ static GKeyFile *load_config_file(const char *file)
static int audio_init(void)
{
+ DBusConnection *conn;
GKeyFile *config;
conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
@@ -155,28 +81,14 @@ static int audio_init(void)
if (config)
g_key_file_free(config);
- btd_register_device_driver(&headset_driver);
-
- btd_register_device_driver(&a2dp_driver);
-
- btd_register_device_driver(&audio_driver);
-
return 0;
}
static void audio_exit(void)
{
- btd_unregister_device_driver(&audio_driver);
-
- btd_unregister_device_driver(&a2dp_driver);
-
- btd_unregister_device_driver(&headset_driver);
-
audio_manager_exit();
unix_exit();
-
- dbus_connection_unref(conn);
}
BLUETOOTH_PLUGIN_DEFINE("audio", audio_init, audio_exit)
diff --git a/audio/manager.c b/audio/manager.c
index 18ef9eb4..cb33158a 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -49,6 +49,8 @@
#include <gdbus.h>
#include "glib-helper.h"
+#include "../hcid/adapter.h"
+#include "../hcid/device.h"
#include "dbus-service.h"
#include "logging.h"
@@ -97,9 +99,6 @@ struct audio_sdp_data {
static DBusConnection *connection = NULL;
-static struct audio_device *default_hs = NULL;
-static struct audio_device *default_dev = NULL;
-
static GSList *devices = NULL;
static uint32_t hsp_ag_record_id = 0;
@@ -120,74 +119,6 @@ static struct enabled_interfaces enabled = {
.control = TRUE,
};
-static DBusMessage *get_records(uuid_t *uuid, struct audio_sdp_data *data);
-
-static struct audio_device *create_device(const bdaddr_t *bda)
-{
- static int device_id = 0;
- char path[128];
-
- snprintf(path, sizeof(path) - 1,
- "%s/device%d", AUDIO_MANAGER_PATH, device_id++);
-
- return device_register(connection, path, bda);
-}
-
-static void destroy_device(struct audio_device *device)
-{
- g_dbus_unregister_all_interfaces(connection, device->path);
-}
-
-static void remove_device(struct audio_device *device)
-{
- if (device == default_dev) {
- debug("Removing default device");
- default_dev = NULL;
- }
-
- if (device == default_hs) {
- debug("Removing default headset");
- default_hs = NULL;
- }
-
- devices = g_slist_remove(devices, device);
-
- destroy_device(device);
-}
-
-static gboolean add_device(struct audio_device *device, gboolean send_signals)
-{
- if (!send_signals)
- goto add;
-
- g_dbus_emit_signal(connection, AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE,
- "DeviceCreated",
- DBUS_TYPE_STRING, &device->path,
- DBUS_TYPE_INVALID);
-
- if (device->headset)
- g_dbus_emit_signal(connection,
- AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE,
- "HeadsetCreated",
- DBUS_TYPE_STRING, &device->path,
- DBUS_TYPE_INVALID);
-add:
-
- if (default_dev == NULL && g_slist_length(devices) == 0) {
- debug("Selecting default device");
- default_dev = device;
- }
-
- if (!default_hs && device->headset && !devices)
- default_hs = device;
-
- devices = g_slist_append(devices, device);
-
- return TRUE;
-}
-
static uint16_t get_service_uuid(const sdp_record_t *record)
{
sdp_list_t *classes;
@@ -254,7 +185,6 @@ gboolean server_is_enabled(uint16_t svc)
static void handle_record(sdp_record_t *record, struct audio_device *device)
{
- gboolean is_default;
uint16_t uuid16;
uuid16 = get_service_uuid(record);
@@ -311,666 +241,6 @@ static void handle_record(sdp_record_t *record, struct audio_device *device)
debug("Unrecognized UUID: 0x%04X", uuid16);
break;
}
-
- is_default = (default_dev == device) ? TRUE : FALSE;
-
- device_store(device, is_default);
-}
-
-static void finish_sdp(struct audio_sdp_data *data, gboolean success)
-{
- const char *addr;
- DBusMessage *reply = NULL;
- DBusError derr;
-
- debug("Audio service discovery completed with %s",
- success ? "success" : "failure");
-
- if (!success)
- goto done;
-
- if (!data->msg)
- goto update;
-
- dbus_error_init(&derr);
- dbus_message_get_args(data->msg, &derr,
- DBUS_TYPE_STRING, &addr,
- DBUS_TYPE_INVALID);
-
- if (dbus_error_is_set(&derr)) {
- error("Unable to get message args");
- success = FALSE;
- error_failed(connection, data->msg, derr.message);
- dbus_error_free(&derr);
- goto done;
- }
-
- /* Return error if no audio related service records were found */
- if (!data->records) {
- debug("No audio audio related service records were found");
- success = FALSE;
- error_not_supported(connection, data->msg);
- goto done;
- }
-
- reply = dbus_message_new_method_return(data->msg);
- if (!reply) {
- success = FALSE;
- error_failed(connection, data->msg, "Out of memory");
- goto done;
- }
-
-update:
- g_slist_foreach(data->records, (GFunc) handle_record, data->device);
-
- if (!g_slist_find(devices, data->device))
- add_device(data->device, TRUE);
-
- if (reply) {
- dbus_message_append_args(reply, DBUS_TYPE_STRING,
- &data->device->path,
- DBUS_TYPE_INVALID);
- dbus_connection_send(connection, reply, NULL);
- dbus_message_unref(reply);
- }
-
-done:
- if (success) {
- if (data->cb)
- data->cb(data->device, data->cb_data);
- } else {
- if (data->cb)
- data->cb(NULL, data->cb_data);
- if (!g_slist_find(devices, data->device))
- destroy_device(data->device);
- }
- if (data->msg)
- dbus_message_unref(data->msg);
- g_slist_foreach(data->records, (GFunc) sdp_record_free, NULL);
- g_slist_free(data->records);
- g_free(data);
-}
-
-static void get_records_cb(sdp_list_t *recs, int err, gpointer user_data)
-{
- struct audio_sdp_data *data = user_data;
- sdp_list_t *seq;
- uuid_t uuid;
-
- if (err < 0) {
- error_connection_attempt_failed(connection, data->msg, -err);
- finish_sdp(data, FALSE);
- return;
- }
-
- for (seq = recs; seq; seq = seq->next) {
- sdp_record_t *rec = (sdp_record_t *) seq->data;
-
- if (!rec)
- break;
-
- data->records = g_slist_append(data->records, rec);
- }
-
- sdp_list_free(recs, NULL);
-
- data->state++;
-
- switch (data->state) {
- case ADVANCED_AUDIO:
- sdp_uuid16_create(&uuid, ADVANCED_AUDIO_SVCLASS_ID);
- break;
- case AV_REMOTE:
- sdp_uuid16_create(&uuid, AV_REMOTE_SVCLASS_ID);
- break;
- default:
- finish_sdp(data, TRUE);
- return;
- }
-
- get_records(&uuid, data);
-}
-
-static DBusMessage *get_records(uuid_t *uuid, struct audio_sdp_data *data)
-{
- struct audio_device *device = data->device;
- DBusMessage *reply = NULL;
- int err;
-
- err = bt_search_service(&device->src, &device->dst, uuid,
- get_records_cb, data, NULL);
- if (!err)
- return NULL;
-
- if (data->msg)
- reply = g_dbus_create_error(data->msg,
- ERROR_INTERFACE ".ConnectionAttemptFailed",
- strerror(-err));
-
- finish_sdp(data, FALSE);
-
- return reply;
-}
-
-static DBusMessage *resolve_services(DBusMessage *msg,
- struct audio_device *device,
- create_dev_cb_t cb,
- void *user_data)
-{
- struct audio_sdp_data *sdp_data;
- uuid_t uuid;
-
- sdp_data = g_new0(struct audio_sdp_data, 1);
- if (msg)
- sdp_data->msg = dbus_message_ref(msg);
- sdp_data->device = device;
- sdp_data->cb = cb;
- sdp_data->cb_data = user_data;
-
- sdp_uuid16_create(&uuid, GENERIC_AUDIO_SVCLASS_ID);
-
- return get_records(&uuid, sdp_data);
-}
-
-struct audio_device *manager_device_connected(const bdaddr_t *bda, const char *uuid)
-{
- struct audio_device *device;
- const char *path;
- gboolean headset = FALSE, created = FALSE;
-
- device = manager_find_device(bda, NULL, FALSE);
- if (!device) {
- device = create_device(bda);
- if (!device)
- return NULL;
- if (!add_device(device, TRUE)) {
- destroy_device(device);
- return NULL;
- }
- created = TRUE;
- }
-
- if (!strcmp(uuid, HSP_AG_UUID) || !strcmp(uuid, HFP_AG_UUID)) {
- if (device->headset)
- return device;
-
- device->headset = headset_init(device, NULL, 0);
-
- if (!device->headset)
- return NULL;
-
- headset = TRUE;
- } else if (!strcmp(uuid, A2DP_SOURCE_UUID)) {
- if (device->sink)
- return device;
-
- device->sink = sink_init(device);
-
- if (!device->sink)
- return NULL;
- } else if (!strcmp(uuid, AVRCP_TARGET_UUID)) {
- if (device->control)
- return device;
-
- device->control = control_init(device);
-
- if (!device->control)
- return NULL;
- } else
- return NULL;
-
- path = device->path;
-
- if (created) {
- g_dbus_emit_signal(connection, AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE,
- "DeviceCreated",
- DBUS_TYPE_STRING, &path,
- DBUS_TYPE_INVALID);
- resolve_services(NULL, device, NULL, NULL);
- }
-
- if (headset)
- g_dbus_emit_signal(connection, AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE,
- "HeadsetCreated",
- DBUS_TYPE_STRING, &path,
- DBUS_TYPE_INVALID);
-
- if (headset && !default_hs) {
- default_hs = device;
- g_dbus_emit_signal(connection, AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE,
- "DefaultHeadsetChanged",
- DBUS_TYPE_STRING, &path,
- DBUS_TYPE_INVALID);
- }
-
- if (!default_dev) {
- default_dev = device;
- g_dbus_emit_signal(connection, AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE,
- "DefaultDeviceChanged",
- DBUS_TYPE_STRING, &path,
- DBUS_TYPE_INVALID);
- }
-
- return device;
-}
-
-gboolean manager_create_device(bdaddr_t *bda, create_dev_cb_t cb,
- void *user_data)
-{
- struct audio_device *dev;
-
- dev = create_device(bda);
- if (!dev)
- return FALSE;
-
- resolve_services(NULL, dev, cb, user_data);
-
- return TRUE;
-}
-
-static DBusMessage *am_create_device(DBusConnection *conn,
- DBusMessage *msg,
- void *data)
-{
- const char *address, *path;
- bdaddr_t bda;
- struct audio_device *device;
- DBusMessage *reply;
-
- if (!dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &address,
- DBUS_TYPE_INVALID))
- return NULL;
-
- str2ba(address, &bda);
-
- device = manager_find_device(&bda, NULL, FALSE);
- if (!device) {
- device = create_device(&bda);
- return resolve_services(msg, device, NULL, NULL);
- }
-
- path = device->path;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- dbus_message_append_args(reply, DBUS_TYPE_STRING, &path,
- DBUS_TYPE_INVALID);
-
- return reply;
-}
-
-static DBusMessage *am_list_devices(DBusConnection *conn,
- DBusMessage *msg,
- void *data)
-{
- DBusMessageIter iter, array_iter;
- DBusMessage *reply;
- DBusError derr;
- GSList *l;
- gboolean hs_only = FALSE;
-
- dbus_error_init(&derr);
-
- if (dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE,
- "ListHeadsets"))
- hs_only = TRUE;
- else
- hs_only = FALSE;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- dbus_message_iter_init_append(reply, &iter);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_TYPE_STRING_AS_STRING, &array_iter);
-
- for (l = devices; l != NULL; l = l->next) {
- struct audio_device *device = l->data;
-
- if (hs_only && !device->headset)
- continue;
-
- dbus_message_iter_append_basic(&array_iter,
- DBUS_TYPE_STRING, &device->path);
- }
-
- dbus_message_iter_close_container(&iter, &array_iter);
-
- return reply;
-}
-
-static gint device_path_cmp(gconstpointer a, gconstpointer b)
-{
- const struct audio_device *device = a;
- const char *path = b;
-
- return strcmp(device->path, path);
-}
-
-static DBusMessage *am_remove_device(DBusConnection *conn,
- DBusMessage *msg,
- void *data)
-{
- DBusMessage *reply;
- GSList *match;
- const char *path;
- struct audio_device *device;
-
- if (!dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &path,
- DBUS_TYPE_INVALID))
- return NULL;
-
- match = g_slist_find_custom(devices, path, device_path_cmp);
- if (!match)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExists",
- "Device does not exists");
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- device = match->data;
- device_remove_stored(device);
- remove_device(device);
-
- /* Fallback to a valid default */
- if (default_dev == NULL) {
- const char *param;
- GSList *l;
-
- default_dev = manager_find_device(BDADDR_ANY, NULL, TRUE);
-
- if (!default_dev && devices) {
- l = devices;
- default_dev = (g_slist_last(l))->data;
- }
-
- param = default_dev ? default_dev->path : "";
-
- g_dbus_emit_signal(conn, AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE,
- "DefaultHeadsetChanged",
- DBUS_TYPE_STRING, &param,
- DBUS_TYPE_INVALID);
-
- g_dbus_emit_signal(conn, AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE,
- "DefaultDeviceChanged",
- DBUS_TYPE_STRING, &param,
- DBUS_TYPE_INVALID);
-
- if (default_dev)
- device_store(default_dev, TRUE);
- }
-
- g_dbus_emit_signal(conn, AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE,
- "HeadsetRemoved",
- DBUS_TYPE_STRING, &path,
- DBUS_TYPE_INVALID);
-
- g_dbus_emit_signal(conn, AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE,
- "DeviceRemoved",
- DBUS_TYPE_STRING, &path,
- DBUS_TYPE_INVALID);
-
- return reply;
-}
-
-static DBusMessage *am_find_by_addr(DBusConnection *conn,
- DBusMessage *msg,
- void *data)
-{
- const char *address;
- DBusMessage *reply;
- struct audio_device *device;
- bdaddr_t bda;
-
- if (!dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &address,
- DBUS_TYPE_INVALID))
- return NULL;
-
- str2ba(address, &bda);
- device = manager_find_device(&bda, NULL, FALSE);
-
- if (!device)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExists",
- "Device does not exists");
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- dbus_message_append_args(reply, DBUS_TYPE_STRING, &device->path,
- DBUS_TYPE_INVALID);
-
- return reply;
-}
-
-static DBusMessage *am_default_device(DBusConnection *conn,
- DBusMessage *msg,
- void *data)
-{
- DBusMessage *reply;
-
- if (!default_dev)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExists",
- "Device does not exists");
-
- if (default_dev->headset == NULL &&
- dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE,
- "DefaultHeadset"))
- return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExists",
- "Device does not exists");
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- dbus_message_append_args(reply, DBUS_TYPE_STRING, &default_dev->path,
- DBUS_TYPE_INVALID);
-
- return reply;
-}
-
-static DBusMessage *am_change_default_device(DBusConnection *conn,
- DBusMessage *msg,
- void *data)
-{
- DBusMessage *reply;
- GSList *match;
- const char *path;
- struct audio_device *device;
-
- if (!dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &path,
- DBUS_TYPE_INVALID))
- return NULL;
-
- match = g_slist_find_custom(devices, path, device_path_cmp);
- if (!match)
- return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExists",
- "Device does not exists");
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- device = match->data;
-
- if (!dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE,
- "ChangeDefaultHeadset"))
- g_dbus_emit_signal(conn, AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE,
- "DefaultDeviceChanged",
- DBUS_TYPE_STRING, &device->path,
- DBUS_TYPE_INVALID);
- else if (device->headset)
- g_dbus_emit_signal(conn, AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE,
- "DefaultHeadsetChanged",
- DBUS_TYPE_STRING, &device->path,
- DBUS_TYPE_INVALID);
- else
- return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExists",
- "Device does not exists");
-
- default_dev = device;
- device_store(device, TRUE);
-
- return reply;
-}
-
-static GDBusMethodTable manager_methods[] = {
- { "CreateDevice", "s", "s", am_create_device,
- G_DBUS_METHOD_FLAG_ASYNC },
- { "RemoveDevice", "s", "", am_remove_device },
- { "ListDevices", "", "as", am_list_devices },
- { "DefaultDevice", "", "s", am_default_device },
- { "ChangeDefaultDevice", "s", "", am_change_default_device },
- { "CreateHeadset", "s", "s", am_create_device,
- G_DBUS_METHOD_FLAG_ASYNC },
- { "RemoveHeadset", "s", "", am_remove_device },
- { "ListHeadsets", "", "as", am_list_devices },
- { "FindDeviceByAddress", "s", "s", am_find_by_addr },
- { "DefaultHeadset", "", "s", am_default_device },
- { "ChangeDefaultHeadset", "s", "", am_change_default_device },
- { }
-};
-
-static GDBusSignalTable manager_signals[] = {
- { "DeviceCreated", "s" },
- { "DeviceRemoved", "s" },
- { "HeadsetCreated", "s" },
- { "HeadsetRemoved", "s" },
- { "DefaultDeviceChanged", "s" },
- { "DefaultHeadsetChanged", "s" },
- { }
-};
-
-static void parse_stored_devices(char *key, char *value, void *data)
-{
- bdaddr_t *src = data;
- struct audio_device *device;
- bdaddr_t dst;
-
- if (!key || !value || strcmp(key, "default") == 0)
- return;
-
- str2ba(key, &dst);
- device = manager_find_device(&dst, NULL, FALSE);
-
- if (device)
- return;
-
- info("Loading device %s (%s)", key, value);
-
- device = create_device(&dst);
- if (!device)
- return;
-
- /* Change storage to source adapter */
- bacpy(&device->store, src);
-
- if (enabled.headset && strstr(value, "headset"))
- device->headset = headset_init(device, NULL, 0);
- if (enabled.sink && strstr(value, "sink"))
- device->sink = sink_init(device);
- if (enabled.control && strstr(value, "control"))
- device->control = control_init(device);
- add_device(device, FALSE);
-}
-
-static void register_devices_stored(const char *adapter)
-{
- char filename[PATH_MAX + 1];
- struct stat st;
- struct audio_device *device;
- bdaddr_t default_src;
- bdaddr_t dst;
- bdaddr_t src;
- char *addr;
- int dev_id;
-
- create_name(filename, PATH_MAX, STORAGEDIR, adapter, "audio");
-
- str2ba(adapter, &src);
-
- if (stat(filename, &st) < 0)
- return;
-
- if (!(st.st_mode & __S_IFREG))
- return;
-
- textfile_foreach(filename, parse_stored_devices, &src);
-
- bacpy(&default_src, BDADDR_ANY);
- dev_id = hci_get_route(&default_src);
- if (dev_id < 0 || hci_devba(dev_id, &default_src) < 0)
- return;
-
- if (bacmp(&default_src, &src) != 0)
- return;
-
- addr = textfile_get(filename, "default");
- if (!addr)
- return;
-
- str2ba(addr, &dst);
- device = manager_find_device(&dst, NULL, FALSE);
-
- if (device) {
- info("Setting %s as default device", addr);
- default_dev = device;
- }
-
- free(addr);
-}
-
-static void register_stored(void)
-{
- char dirname[PATH_MAX + 1];
- struct dirent *de;
- DIR *dir;
-
- snprintf(dirname, PATH_MAX, "%s", STORAGEDIR);
-
- dir = opendir(dirname);
- if (!dir)
- return;
-
- while ((de = readdir(dir)) != NULL) {
- if (!isdigit(de->d_name[0]))
- continue;
-
- /* Device objects */
- register_devices_stored(de->d_name);
- }
-
- closedir(dir);
-}
-
-static void manager_unregister(void *data)
-{
- info("Unregistered manager path");
-
- if (devices) {
- g_slist_foreach(devices, (GFunc) remove_device, NULL);
- g_slist_free(devices);
- devices = NULL;
- }
}
static sdp_record_t *hsp_ag_record(uint8_t ch)
@@ -1201,7 +471,7 @@ static void ag_io_cb(GIOChannel *chan, int err, const bdaddr_t *src,
uuid = HFP_AG_UUID;
}
- device = manager_device_connected(dst, uuid);
+ device = manager_find_device(dst, NULL, FALSE);
if (!device)
goto drop;
@@ -1416,6 +686,61 @@ static void server_exit(void)
}
}
+static int audio_probe(struct btd_device_driver *driver,
+ struct btd_device *device, GSList *records)
+{
+ struct adapter *adapter = device_get_adapter(device);
+ const gchar *path = device_get_path(device);
+ const char *source, *destination;
+ bdaddr_t src, dst;
+ struct audio_device *dev;
+
+ source = adapter_get_address(adapter);
+ destination = device_get_address(device);
+
+ str2ba(source, &src);
+ str2ba(destination, &dst);
+
+ dev = manager_find_device(&dst, NULL, FALSE);
+ if (!dev) {
+ dev = device_register(connection, path, &src, &dst);
+ if (!dev)
+ return -EINVAL;
+ devices = g_slist_append(devices, dev);
+ }
+
+ g_slist_foreach(records, (GFunc) handle_record, dev);
+
+ return 0;
+}
+
+static void audio_remove(struct btd_device_driver *driver,
+ struct btd_device *device)
+{
+ struct audio_device *dev;
+ const char *destination = device_get_address(device);
+ bdaddr_t dst;
+
+ str2ba(destination, &dst);
+
+ dev = manager_find_device(&dst, NULL, FALSE);
+ if (!dev)
+ return;
+
+ devices = g_slist_remove(devices, dev);
+
+ device_unregister(dev);
+}
+
+static struct btd_device_driver audio_driver = {
+ .name = "audio",
+ .uuids = BTD_UUIDS(HSP_HS_UUID, HFP_HS_UUID, HSP_AG_UUID, HFP_AG_UUID,
+ ADVANCED_AUDIO_UUID, A2DP_SOURCE_UUID, A2DP_SINK_UUID,
+ AVRCP_TARGET_UUID, AVRCP_REMOTE_UUID),
+ .probe = audio_probe,
+ .remove = audio_remove,
+};
+
int audio_manager_init(DBusConnection *conn, GKeyFile *config)
{
char **list;
@@ -1477,18 +802,7 @@ proceed:
if (enabled.control && avrcp_init(conn, config) < 0)
goto failed;
- if (!g_dbus_register_interface(conn, AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE,
- manager_methods, manager_signals,
- NULL, NULL, manager_unregister)) {
- error("Failed to register %s interface to %s",
- AUDIO_MANAGER_INTERFACE, AUDIO_MANAGER_PATH);
- goto failed;
- }
-
- info("Registered manager path:%s", AUDIO_MANAGER_PATH);
-
- register_stored();
+ btd_register_device_driver(&audio_driver);
return 0;
failed:
@@ -1500,17 +814,11 @@ void audio_manager_exit(void)
{
server_exit();
- g_dbus_unregister_interface(connection, AUDIO_MANAGER_PATH,
- AUDIO_MANAGER_INTERFACE);
-
dbus_connection_unref(connection);
- connection = NULL;
-}
+ btd_unregister_device_driver(&audio_driver);
-struct audio_device *manager_default_device(void)
-{
- return default_dev;
+ connection = NULL;
}
struct audio_device *manager_get_connected_device(void)
@@ -1537,7 +845,7 @@ struct audio_device *manager_find_device(const bdaddr_t *bda, const char *interf
GSList *l;
if (!bacmp(bda, BDADDR_ANY) && !interface && !connected)
- return default_dev;
+ return devices->data;
for (l = devices; l != NULL; l = l->next) {
struct audio_device *dev = l->data;
diff --git a/audio/manager.h b/audio/manager.h
index 8f7f6be3..701511a1 100644
--- a/audio/manager.h
+++ b/audio/manager.h
@@ -44,7 +44,5 @@ gboolean server_is_enabled(uint16_t svc);
struct audio_device *manager_find_device(const bdaddr_t *bda, const char *interface,
gboolean connected);
-struct audio_device *manager_device_connected(const bdaddr_t *bda, const char *uuid);
-
gboolean manager_create_device(bdaddr_t *bda, create_dev_cb_t cb,
void *user_data);
diff --git a/audio/sink.c b/audio/sink.c
index 2af74bb3..0aa14542 100644
--- a/audio/sink.c
+++ b/audio/sink.c
@@ -502,6 +502,9 @@ struct sink *sink_init(struct audio_device *dev)
dev, NULL))
return NULL;
+ info("Registered interface %s on path %s",
+ AUDIO_SINK_INTERFACE, dev->path);
+
return g_new0(struct sink, 1);
}
diff --git a/audio/unix.c b/audio/unix.c
index 93f5788b..10e6021e 100644
--- a/audio/unix.c
+++ b/audio/unix.c
@@ -744,16 +744,6 @@ failed:
unix_ipc_error(client, BT_STREAMSTOP_RSP, EIO);
}
-static void create_cb(struct audio_device *dev, void *user_data)
-{
- struct unix_client *client = user_data;
-
- if (!dev)
- unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO);
- else
- start_discovery(dev, client);
-}
-
static void handle_getcapabilities_req(struct unix_client *client,
struct bt_getcapabilities_req *req)
{
@@ -772,15 +762,8 @@ static void handle_getcapabilities_req(struct unix_client *client,
else if (req->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
client->interface = g_strdup(AUDIO_SINK_INTERFACE);
- if (!manager_find_device(&bdaddr, NULL, FALSE)) {
- if (!(req->flags & BT_FLAG_AUTOCONNECT))
- goto failed;
- if (!bacmp(&bdaddr, BDADDR_ANY))
- goto failed;
- if (!manager_create_device(&bdaddr, create_cb, client))
- goto failed;
- return;
- }
+ if (!manager_find_device(&bdaddr, NULL, FALSE))
+ goto failed;
dev = manager_find_device(&bdaddr, client->interface, TRUE);
if (!dev) {
@@ -918,13 +901,8 @@ static void handle_setconfiguration_req(struct unix_client *client,
}
}
- if (!manager_find_device(&bdaddr, NULL, FALSE)) {
- if (!bacmp(&bdaddr, BDADDR_ANY))
- goto failed;
- if (!manager_create_device(&bdaddr, create_cb, client))
- goto failed;
- return;
- }
+ if (!manager_find_device(&bdaddr, NULL, FALSE))
+ goto failed;
dev = manager_find_device(&bdaddr, client->interface, TRUE);
if (!dev)