diff options
Diffstat (limited to 'audio/manager.c')
| -rw-r--r-- | audio/manager.c | 369 | 
1 files changed, 72 insertions, 297 deletions
| diff --git a/audio/manager.c b/audio/manager.c index 7faa0490..d8872968 100644 --- a/audio/manager.c +++ b/audio/manager.c @@ -42,12 +42,11 @@  #include <dbus/dbus.h> -#include "dbus.h"  #include "dbus-helper.h"  #include "logging.h" -#include "headset.h"  #include "manager.h" +#include "error.h"  typedef enum {  	HEADSET	= 1 << 0, @@ -67,7 +66,7 @@ typedef enum {  } audio_sdp_state_t;  struct audio_sdp_data { -	audio_device_t *device; +	struct device *device;  	DBusMessage *msg;	/* Method call or NULL */ @@ -79,7 +78,7 @@ struct audio_sdp_data {  static DBusConnection *connection = NULL; -static audio_device_t *default_dev = NULL; +static struct device *default_dev = NULL;  static GSList *devices = NULL; @@ -87,80 +86,12 @@ static void get_next_record(struct audio_sdp_data *data);  static DBusHandlerResult get_handles(const char *uuid,  					struct audio_sdp_data *data); -/* FIXME: Remove these once global error functions exist */ -static DBusHandlerResult error_reply(DBusConnection *conn, DBusMessage *msg, -					const char *name, const char *descr) -{ -	DBusMessage *derr; - -	if (!conn || !msg) -		return DBUS_HANDLER_RESULT_HANDLED; - -	derr = dbus_message_new_error(msg, name, descr); -	if (!derr) { -		error("Unable to allocate new error return"); -		return DBUS_HANDLER_RESULT_NEED_MEMORY; -	} - -	return send_message_and_unref(conn, derr); -} - -DBusHandlerResult err_invalid_args(DBusConnection *conn, DBusMessage *msg, -						const char *descr) -{ -	return error_reply(conn, msg, "org.bluez.audio.Error.InvalidArguments", -			descr ? descr : "Invalid arguments in method call"); -} - -DBusHandlerResult err_already_connected(DBusConnection *conn, DBusMessage *msg) -{ -	return error_reply(conn, msg, "org.bluez.audio.Error.AlreadyConnected", -				"Already connected to a device"); -} - -DBusHandlerResult err_not_connected(DBusConnection *conn, DBusMessage *msg) -{ -	return error_reply(conn, msg, "org.bluez.audio.Error.NotConnected", -				"Not connected to any device"); -} - -DBusHandlerResult err_not_supported(DBusConnection *conn, DBusMessage *msg) -{ -	return error_reply(conn, msg, "org.bluez.audio.Error.NotSupported", -			"The service is not supported by the remote device"); -} - -DBusHandlerResult err_connect_failed(DBusConnection *conn, -					DBusMessage *msg, int err) -{ -	return error_reply(conn, msg, "org.bluez.audio.Error.ConnectFailed", -				strerror(err)); -} - -DBusHandlerResult err_does_not_exist(DBusConnection *conn, DBusMessage *msg) -{ -	return error_reply(conn, msg, "org.bluez.audio.Error.DoesNotExist", -				"Does not exist"); -} - -DBusHandlerResult err_not_available(DBusConnection *conn, DBusMessage *msg) -{ -	return error_reply(conn, msg, "org.bluez.audio.Error.NotAvailable", -				"Not available"); -} - -DBusHandlerResult err_failed(DBusConnection *conn, DBusMessage *msg, -				const char *dsc) -{ -	return error_reply(conn, msg, "org.bluez.audio.Error.Failed", dsc); -} - -static audio_device_t *find_device(bdaddr_t *bda) +static struct device *find_device(bdaddr_t *bda)  {  	GSList *l;  	for (l = devices; l != NULL; l = l->next) { -		audio_device_t *device = l->data; +		struct device *device = l->data;  		if (bacmp(&device->bda, bda) == 0)  			return device;  	} @@ -168,113 +99,25 @@ static audio_device_t *find_device(bdaddr_t *bda)  	return NULL;  } -static DBusHandlerResult device_get_address(DBusConnection *conn, -						DBusMessage *msg, -						void *data) -{ -	audio_device_t *device = data; -	DBusMessage *reply; -	char address[18], *ptr = address; - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return DBUS_HANDLER_RESULT_NEED_MEMORY; - -	ba2str(&device->bda, address); - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &ptr, -					DBUS_TYPE_INVALID); - -	return send_message_and_unref(conn, reply); -} - -static DBusHandlerResult device_get_connected(DBusConnection *conn, -						DBusMessage *msg, -						void *data) -{ -	DBusMessageIter iter, array_iter; -	audio_device_t *device = data; -	DBusMessage *reply; -	const char *iface; - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return DBUS_HANDLER_RESULT_NEED_MEMORY; - -	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_is_connected(device->headset)) { -		iface = AUDIO_HEADSET_INTERFACE; -		dbus_message_iter_append_basic(&array_iter, -						DBUS_TYPE_STRING, &iface); -	} - -	dbus_message_iter_close_container(&iter, &array_iter); - -	return send_message_and_unref(conn, reply); -} - -static DBusMethodVTable device_methods[] = { -	{ "GetAddress",			device_get_address, -		"",	"s"	}, -	{ "GetConnectedInterfaces",	device_get_connected, -		"",	"s"	}, -	{ NULL, NULL, NULL, NULL } -}; - -static void free_device(audio_device_t *device) -{ -	g_free(device); -} - -static audio_device_t *create_device(bdaddr_t *bda) +static struct device *create_device(bdaddr_t *bda)  {  	static int device_id = 0; -	audio_device_t *device; - -	device = g_new0(audio_device_t, 1); +	char path[128]; -	bacpy(&device->bda, bda); - -	snprintf(device->object_path, sizeof(device->object_path) - 1, +	snprintf(path, sizeof(path) - 1,  			"%s/device%d", AUDIO_MANAGER_PATH, device_id++); -	return device; +	return device_register(connection, path, bda);  } -static void remove_device(audio_device_t *device) +static void remove_device(struct device *device)  {  	devices = g_slist_remove(devices, device); -	if (device->headset) -		headset_free(device->object_path); -	dbus_connection_destroy_object_path(connection, device->object_path); -	g_free(device); +	dbus_connection_destroy_object_path(connection, device->path);  } - -static gboolean add_device(audio_device_t *device) +static gboolean add_device(struct device *device)  { -	if (!dbus_connection_create_object_path(connection, -						device->object_path, -						device, NULL)) { -		error("D-Bus failed to register %s path", device->object_path); -		return FALSE; -	} - -	if (!dbus_connection_register_interface(connection, -						device->object_path, -						AUDIO_DEVICE_INTERFACE, -						device_methods, NULL, NULL)) { -		error("Failed to register %s interface to %s", -				AUDIO_DEVICE_INTERFACE, device->object_path); -		dbus_connection_destroy_object_path(connection, -							device->object_path); -		return FALSE; -	} -  	/* First device became default */  	if (g_slist_length(devices) == 0)  		default_dev = device; @@ -296,7 +139,7 @@ static uint16_t get_service_uuid(const sdp_record_t *record)  	}  	memcpy(&uuid, classes->data, sizeof(uuid)); -	 +  	if (!sdp_uuid128_to_uuid(&uuid)) {  		error("Not a 16 bit UUID");  		sdp_list_free(classes, free); @@ -304,7 +147,7 @@ static uint16_t get_service_uuid(const sdp_record_t *record)  	}  	if (uuid.type == SDP_UUID32) { -	       	if (uuid.value.uuid32 > 0xFFFF) { +		if (uuid.value.uuid32 > 0xFFFF) {  			error("Not a 16 bit UUID");  			goto done;  		} @@ -318,43 +161,7 @@ done:  	return uuid16;  } -void finish_sdp_transaction(DBusConnection *conn, bdaddr_t *dba)  -{ -	char address[18], *addr_ptr = address; -	DBusMessage *msg, *reply; -	DBusError derr; - -	ba2str(dba, address); - -	msg = dbus_message_new_method_call("org.bluez", "/org/bluez/hci0", -						"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_error_init(&derr); -	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, -								&derr); - -	dbus_message_unref(msg); - -	if (dbus_error_is_set(&derr) || -			dbus_set_error_from_message(&derr, reply)) { -		error("FinishRemoteServiceTransaction(%s) failed: %s", -				address, derr.message); -		dbus_error_free(&derr); -		return; -	} - -	dbus_message_unref(reply); -} - -static void handle_record(sdp_record_t *record, audio_device_t *device) +static void handle_record(sdp_record_t *record, struct device *device)  {  	uint16_t uuid16; @@ -364,9 +171,9 @@ static void handle_record(sdp_record_t *record, audio_device_t *device)  	case HEADSET_SVCLASS_ID:  		debug("Found Headset record");  		if (device->headset) -			headset_update(device->headset, record, uuid16); +			headset_update(device, record, uuid16);  		else -			device->headset = headset_init(device->object_path, +			device->headset = headset_init(device,  							record, uuid16);  		break;  	case HEADSET_AGW_SVCLASS_ID: @@ -375,9 +182,9 @@ static void handle_record(sdp_record_t *record, audio_device_t *device)  	case HANDSFREE_SVCLASS_ID:  		debug("Found Hansfree record");  		if (device->headset) -			headset_update(device->headset, record, uuid16); +			headset_update(device, record, uuid16);  		else -			device->headset = headset_init(device->object_path, +			device->headset = headset_init(device,  							record, uuid16);  		break;  	case HANDSFREE_AGW_SVCLASS_ID: @@ -434,8 +241,8 @@ static gint record_iface_cmp(gconstpointer a, gconstpointer b)  static void finish_sdp(struct audio_sdp_data *data, gboolean success)  { -	const char *path, *addr; -	char **required; +	const char *addr; +	char **required = NULL;  	int required_len, i;  	DBusMessage *reply = NULL;  	DBusError derr; @@ -443,7 +250,7 @@ static void finish_sdp(struct audio_sdp_data *data, gboolean success)  	debug("Audio service discovery completed with %s",  			success ? "success" : "failure"); -	finish_sdp_transaction(connection, &data->device->bda); +	device_finish_sdp_transaction(data->device);  	if (!success)  		goto done; @@ -508,14 +315,9 @@ static void finish_sdp(struct audio_sdp_data *data, gboolean success)  		debug("Required interface %s not supported", iface);  		success = FALSE;  		err_not_supported(connection, data->msg); -		dbus_free_string_array(required);  		goto done;  	} -	dbus_free_string_array(required); - -	path = data->device->object_path; -  	reply = dbus_message_new_method_return(data->msg);  	if (!reply) {  		success = FALSE; @@ -532,24 +334,27 @@ update:  		dbus_connection_emit_signal(connection, AUDIO_MANAGER_PATH,  						AUDIO_MANAGER_INTERFACE,  						"DeviceCreated", -						DBUS_TYPE_STRING, &path, +						DBUS_TYPE_STRING, +						&data->device->path,  						DBUS_TYPE_INVALID);  		if (data->device->headset) -			dbus_connection_emit_signal(connection, AUDIO_MANAGER_PATH, +			dbus_connection_emit_signal(connection, +							AUDIO_MANAGER_PATH,  							AUDIO_MANAGER_INTERFACE,  							"HeadsetCreated", -							DBUS_TYPE_STRING, &path, +							DBUS_TYPE_STRING, +							&data->device->path,  							DBUS_TYPE_INVALID); -		dbus_message_append_args(reply, DBUS_TYPE_STRING, &path, -				DBUS_TYPE_INVALID); +		dbus_message_append_args(reply, DBUS_TYPE_STRING, +					&data->device->path, +					DBUS_TYPE_INVALID);  		send_message_and_unref(connection, reply);  	}  done: -	if (required) -		dbus_free_string_array(required); +	dbus_free_string_array(required);  	if (!success) -		free_device(data->device); +		remove_device(data->device);  	if (data->msg)  		dbus_message_unref(data->msg);  	g_slist_foreach(data->handles, (GFunc) g_free, NULL); @@ -575,7 +380,8 @@ static void get_record_reply(DBusPendingCall *call,  		error("GetRemoteServiceRecord failed: %s", derr.message);  		if (dbus_error_has_name(&derr,  					"org.bluez.Error.ConnectionAttemptFailed")) -			err_connect_failed(connection, data->msg, EHOSTDOWN); +			err_connect_failed(connection, data->msg, +				strerror(EHOSTDOWN));  		else  			err_failed(connection, data->msg, derr.message);  		dbus_error_free(&derr); @@ -625,12 +431,13 @@ static void get_next_record(struct audio_sdp_data *data)  	char address[18], *ptr = address;  	dbus_uint32_t *handle; -	msg = dbus_message_new_method_call("org.bluez", "/org/bluez/hci0", +	msg = dbus_message_new_method_call("org.bluez", +						data->device->adapter_path,  						"org.bluez.Adapter",  						"GetRemoteServiceRecord");  	if (!msg) {  		error("Unable to allocate new method call"); -		err_connect_failed(connection, data->msg, ENOMEM); +		err_connect_failed(connection, data->msg, strerror(ENOMEM));  		finish_sdp(data, FALSE);  		return;  	} @@ -649,7 +456,7 @@ static void get_next_record(struct audio_sdp_data *data)  	if (!dbus_connection_send_with_reply(connection, msg, &pending, -1)) {  		error("Sending GetRemoteServiceRecord failed"); -		err_connect_failed(connection, data->msg, EIO); +		err_connect_failed(connection, data->msg, strerror(EIO));  		finish_sdp(data, FALSE);  		return;  	} @@ -687,7 +494,7 @@ static void get_handles_reply(DBusPendingCall *call,  		error("GetRemoteServiceHandles failed: %s", derr.message);  		if (dbus_error_has_name(&derr,  					"org.bluez.Error.ConnectionAttemptFailed")) -			err_connect_failed(connection, data->msg, EHOSTDOWN); +			err_connect_failed(connection, data->msg, strerror(EHOSTDOWN));  		else  			err_failed(connection, data->msg, derr.message);  		dbus_error_free(&derr); @@ -744,7 +551,8 @@ static DBusHandlerResult get_handles(const char *uuid,  	const char *ptr = address;  	DBusMessage *msg; -	msg = dbus_message_new_method_call("org.bluez", "/org/bluez/hci0", +	msg = dbus_message_new_method_call("org.bluez", +						data->device->adapter_path,  						"org.bluez.Adapter",  						"GetRemoteServiceHandles");  	if (!msg) { @@ -781,7 +589,7 @@ failed:  }  static DBusHandlerResult resolve_services(DBusMessage *msg, -						audio_device_t *device) +						struct device *device)  {  	struct audio_sdp_data *sdp_data; @@ -793,9 +601,9 @@ static DBusHandlerResult resolve_services(DBusMessage *msg,  	return get_handles(GENERIC_AUDIO_UUID, sdp_data);  } -audio_device_t *manager_headset_connected(bdaddr_t *bda) +struct device *manager_device_connected(bdaddr_t *bda)  { -	audio_device_t *device; +	struct device *device;  	const char *path;  	gboolean created = FALSE; @@ -806,19 +614,19 @@ audio_device_t *manager_headset_connected(bdaddr_t *bda)  	if (!device) {  		device = create_device(bda);  		if (!add_device(device)) { -			free_device(device); +			remove_device(device);  			return NULL;  		}  		created = TRUE;  	}  	if (!device->headset) -		device->headset = headset_init(device->object_path, NULL, 0); +		device->headset = headset_init(device, NULL, 0);  	if (!device->headset)  		return NULL; -	path = device->object_path; +	path = device->path;  	if (created) {  		dbus_connection_emit_signal(connection, AUDIO_MANAGER_PATH, @@ -847,7 +655,7 @@ audio_device_t *manager_headset_connected(bdaddr_t *bda)  	return device;  } -static gboolean device_supports_interface(audio_device_t *device, +static gboolean device_supports_interface(struct device *device,  						const char *iface)  {  		if (strcmp(iface, AUDIO_HEADSET_INTERFACE) == 0) @@ -873,7 +681,7 @@ static gboolean device_supports_interface(audio_device_t *device,  		return FALSE;  } -static gboolean device_matches(audio_device_t *device, char **interfaces) +static gboolean device_matches(struct device *device, char **interfaces)  {  	int i; @@ -895,7 +703,7 @@ static DBusHandlerResult am_create_device(DBusConnection *conn,  	char **required;  	int required_len;  	bdaddr_t bda; -	audio_device_t *device; +	struct device *device;  	DBusMessage *reply;  	DBusError derr; @@ -950,7 +758,7 @@ static DBusHandlerResult am_create_device(DBusConnection *conn,  	dbus_free_string_array(required); -	path = device->object_path; +	path = device->path;  	reply = dbus_message_new_method_return(msg);  	if (!reply) @@ -1015,16 +823,13 @@ static DBusHandlerResult am_list_devices(DBusConnection *conn,  				DBUS_TYPE_STRING_AS_STRING, &array_iter);  	for (l = devices; l != NULL; l = l->next) { -		audio_device_t *device = l->data; -		const char *path; +		struct device *device = l->data;  		if (!device_matches(device, required))  			continue; -		path = device->object_path; -  		dbus_message_iter_append_basic(&array_iter, -						DBUS_TYPE_STRING, &path); +						DBUS_TYPE_STRING, &device->path);  	}  	dbus_message_iter_close_container(&iter, &array_iter); @@ -1036,10 +841,10 @@ static DBusHandlerResult am_list_devices(DBusConnection *conn,  static gint device_path_cmp(gconstpointer a, gconstpointer b)  { -	const audio_device_t *device = a; +	const struct device *device = a;  	const char *path = b; -	return strcmp(device->object_path, path); +	return strcmp(device->path, path);  }  static DBusHandlerResult am_remove_device(DBusConnection *conn, @@ -1050,7 +855,7 @@ static DBusHandlerResult am_remove_device(DBusConnection *conn,  	DBusMessage *reply;  	GSList *match;  	const char *path; -	audio_device_t *device; +	struct device *device;  	dbus_error_init(&derr);  	if (!dbus_message_get_args(msg, &derr, @@ -1067,9 +872,7 @@ static DBusHandlerResult am_remove_device(DBusConnection *conn,  	match = g_slist_find_custom(devices, path, device_path_cmp);  	if (!match) -		return error_reply(connection, msg, -					"org.bluez.audio.Error.DoesNotExist", -					"The device does not exist"); +		return err_does_not_exist(connection, msg);  	reply = dbus_message_new_method_return(msg);  	if (!reply) @@ -1092,7 +895,7 @@ static DBusHandlerResult am_remove_device(DBusConnection *conn,  				default_dev = device;  		} -		param = default_dev ? default_dev->object_path : ""; +		param = default_dev ? default_dev->path : "";  		dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH,  						AUDIO_MANAGER_INTERFACE, @@ -1120,10 +923,10 @@ static DBusHandlerResult am_find_by_addr(DBusConnection *conn,  						DBusMessage *msg,  						void *data)  { -	const char *path, *address; +	const char *address;  	DBusMessage *reply;  	DBusError derr; -	audio_device_t *device; +	struct device *device;  	bdaddr_t bda;  	dbus_error_init(&derr); @@ -1147,9 +950,7 @@ static DBusHandlerResult am_find_by_addr(DBusConnection *conn,  	if (!reply)  		return DBUS_HANDLER_RESULT_NEED_MEMORY; -	path = device->object_path; - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &path, +	dbus_message_append_args(reply, DBUS_TYPE_STRING, &device->path,  					DBUS_TYPE_INVALID);  	return send_message_and_unref(conn, reply); @@ -1160,27 +961,20 @@ static DBusHandlerResult am_default_device(DBusConnection *conn,  						void *data)  {  	DBusMessage *reply; -	const char *path;  	if (!default_dev) -		return error_reply(connection, msg, -					"org.bluez.audio.Error.DoesNotExist", -					"There is no default device"); +		return err_does_not_exist(connection, msg);  	if (default_dev->headset == NULL &&  		dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE,  		"DefaultHeadset")) -		return error_reply(connection, msg, -					"org.bluez.audio.Error.DoesNotExist", -					"There is no default headset"); +		return err_does_not_exist(connection, msg);  	reply = dbus_message_new_method_return(msg);  	if (!reply)  		return DBUS_HANDLER_RESULT_NEED_MEMORY; -	path = default_dev->object_path; - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &path, +	dbus_message_append_args(reply, DBUS_TYPE_STRING, &default_dev->path,  					DBUS_TYPE_INVALID);  	return send_message_and_unref(connection, reply); @@ -1194,7 +988,7 @@ static DBusHandlerResult am_change_default_device(DBusConnection *conn,  	DBusMessage *reply;  	GSList *match;  	const char *path; -	audio_device_t *device; +	struct device *device;  	dbus_error_init(&derr);  	if (!dbus_message_get_args(msg, &derr, @@ -1211,9 +1005,7 @@ static DBusHandlerResult am_change_default_device(DBusConnection *conn,  	match = g_slist_find_custom(devices, path, device_path_cmp);  	if (!match) -		return error_reply(connection, msg, -					"org.bluez.audio.Error.DoesNotExist", -					"The device does not exist"); +		return err_does_not_exist(connection, msg);  	reply = dbus_message_new_method_return(msg);  	if (!reply) @@ -1221,25 +1013,21 @@ static DBusHandlerResult am_change_default_device(DBusConnection *conn,  	device = match->data; -	path = device->object_path; -  	if (!dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE,  		"ChangeDefaultHeadset"))  		dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH,  						AUDIO_MANAGER_INTERFACE,  						"DefaultDeviceChanged", -						DBUS_TYPE_STRING, &path, +						DBUS_TYPE_STRING, &device->path,  						DBUS_TYPE_INVALID);  	else if (device->headset)  		dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH,  						AUDIO_MANAGER_INTERFACE,  						"DefaultHeadsetChanged", -						DBUS_TYPE_STRING, &path, +						DBUS_TYPE_STRING, &device->path,  						DBUS_TYPE_INVALID);  	else -		return error_reply(connection, msg, -					"org.bluez.audio.Error.DoesNotExist", -					"The headset does not exist"); +		return err_does_not_exist(connection, msg);  	default_dev = device;  	return send_message_and_unref(connection, reply); @@ -1316,20 +1104,7 @@ void audio_exit(void)  	connection = NULL;  } -int manager_get_device(int sock, uint8_t role, struct ipc_data_cfg *cfg) +struct device * manager_default_device()  { -	GSList *l; - -	if (default_dev && default_dev->headset && -			headset_is_connected(default_dev->headset)) -		return headset_get_config(default_dev->headset, sock, cfg); - -	for (l = devices; l != NULL; l = l->next) { -		audio_device_t *dev = l->data; - -		if (dev->headset && headset_is_connected(dev->headset)) -			return headset_get_config(dev->headset, sock, cfg); -	} - -	return -1; +	return default_dev;  } | 
