diff options
| -rw-r--r-- | audio/a2dp.c | 2 | ||||
| -rw-r--r-- | audio/control.c | 19 | ||||
| -rw-r--r-- | audio/device.c | 332 | ||||
| -rw-r--r-- | audio/device.h | 14 | ||||
| -rw-r--r-- | audio/headset.c | 3 | ||||
| -rw-r--r-- | audio/main.c | 90 | ||||
| -rw-r--r-- | audio/manager.c | 816 | ||||
| -rw-r--r-- | audio/manager.h | 2 | ||||
| -rw-r--r-- | audio/sink.c | 3 | ||||
| -rw-r--r-- | audio/unix.c | 30 | 
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, ¶m, -						DBUS_TYPE_INVALID); - -		g_dbus_emit_signal(conn, AUDIO_MANAGER_PATH, -						AUDIO_MANAGER_INTERFACE, -						"DefaultDeviceChanged", -						DBUS_TYPE_STRING, ¶m, -						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) | 
