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