diff options
| -rw-r--r-- | audio/headset.c | 5 | ||||
| -rw-r--r-- | audio/main.c | 3 | ||||
| -rw-r--r-- | audio/manager.c | 377 | ||||
| -rw-r--r-- | audio/manager.h | 2 | 
4 files changed, 270 insertions, 117 deletions
| diff --git a/audio/headset.c b/audio/headset.c index bcbc9e8a..c3825851 100644 --- a/audio/headset.c +++ b/audio/headset.c @@ -709,7 +709,8 @@ static void rfcomm_connect_cb(GIOChannel *chan, int err, const bdaddr_t *src,  	hs->rfcomm = chan;  	p->io = NULL; -	if (server_is_enabled(HANDSFREE_SVCLASS_ID) && hs->hfp_handle != 0) +	if (server_is_enabled(&dev->src, HANDSFREE_SVCLASS_ID) && +			hs->hfp_handle != 0)  		hs->hfp_active = TRUE;  	else  		hs->hfp_active = FALSE; @@ -1519,7 +1520,7 @@ struct headset *headset_init(struct audio_device *dev, sdp_record_t *record,  	hs->rfcomm_ch = -1;  	hs->sp_gain = -1;  	hs->mic_gain = -1; -	hs->search_hfp = server_is_enabled(HANDSFREE_SVCLASS_ID); +	hs->search_hfp = server_is_enabled(&dev->src, HANDSFREE_SVCLASS_ID);  	hs->hfp_active = FALSE;  	hs->cli_active = FALSE;  	hs->ph_number = NULL; diff --git a/audio/main.c b/audio/main.c index 0d0257dc..9afc61e6 100644 --- a/audio/main.c +++ b/audio/main.c @@ -78,9 +78,6 @@ static int audio_init(void)  		return -EIO;  	} -	if (config) -		g_key_file_free(config); -  	return 0;  } diff --git a/audio/manager.c b/audio/manager.c index 695c6ba0..8278ee25 100644 --- a/audio/manager.c +++ b/audio/manager.c @@ -85,33 +85,22 @@ typedef enum {  		GET_RECORDS  } audio_sdp_state_t; -struct audio_sdp_data { -	struct audio_device *device; - -	DBusMessage *msg;	/* Method call or NULL */ - -	GSList *records;	/* sdp_record_t * */ - -	audio_sdp_state_t state; - -	create_dev_cb_t cb; -	void *cb_data; +struct audio_adapter { +	bdaddr_t src; +	char	*path; +	uint32_t hsp_ag_record_id; +	uint32_t hfp_ag_record_id; +	uint32_t hsp_hs_record_id; +	GIOChannel *hsp_ag_server; +	GIOChannel *hfp_ag_server; +	GIOChannel *hsp_hs_server;  };  static DBusConnection *connection = NULL; - +static GKeyFile *config = NULL; +static GSList *adapters = NULL;  static GSList *devices = NULL; -static uint32_t hsp_ag_record_id = 0; -static uint32_t hfp_ag_record_id = 0; - -static uint32_t hsp_hs_record_id = 0; - -static GIOChannel *hsp_ag_server = NULL; -static GIOChannel *hfp_ag_server = NULL; - -static GIOChannel *hsp_hs_server = NULL; -  static struct enabled_interfaces enabled = {  	.headset	= TRUE,  	.gateway	= FALSE, @@ -120,6 +109,35 @@ static struct enabled_interfaces enabled = {  	.control	= TRUE,  }; +static struct audio_adapter *find_adapter(GSList *list, const char *path) +{ +	GSList *l; + +	for (l = list; l; l = l->next) { +		struct audio_adapter *adapter = l->data; + +		if (g_str_equal(adapter->path, path)) +			return adapter; +	} + +	return NULL; +} + +static struct audio_adapter *find_adapter_by_address(GSList *list, +						const bdaddr_t *src) +{ +	GSList *l; + +	for (l = list; l; l = l->next) { +		struct audio_adapter *adapter = l->data; + +		if (bacmp(&adapter->src, src) == 0) +			return adapter; +	} + +	return NULL; +} +  static uint16_t get_service_uuid(const sdp_record_t *record)  {  	sdp_list_t *classes; @@ -154,19 +172,24 @@ done:  	return uuid16;  } -gboolean server_is_enabled(uint16_t svc) +gboolean server_is_enabled(bdaddr_t *src, uint16_t svc)  { +	struct audio_adapter *adp;  	gboolean ret; +	adp = find_adapter_by_address(adapters, src); +	if (!adp) +		return FALSE; +  	switch (svc) {  	case HEADSET_SVCLASS_ID: -		ret = (hsp_ag_server != NULL); +		ret = (adp->hsp_ag_server != NULL);  		break;  	case HEADSET_AGW_SVCLASS_ID: -		ret = (hsp_hs_server != NULL); +		ret = (adp->hsp_hs_server != NULL);  		break;  	case HANDSFREE_SVCLASS_ID: -		ret = (hfp_ag_server != NULL); +		ret = (adp->hfp_ag_server != NULL);  		break;  	case HANDSFREE_AGW_SVCLASS_ID:  		ret = FALSE; @@ -190,7 +213,7 @@ static void handle_record(sdp_record_t *record, struct audio_device *device)  	uuid16 = get_service_uuid(record); -	if (!server_is_enabled(uuid16)) +	if (!server_is_enabled(&device->src, uuid16))  		return;  	switch (uuid16) { @@ -455,6 +478,7 @@ static void auth_cb(DBusError *derr, void *user_data)  static void ag_io_cb(GIOChannel *chan, int err, const bdaddr_t *src,  			const bdaddr_t *dst, gpointer data)  { +	struct audio_adapter *adapter = data;  	const char *uuid;  	struct audio_device *device;  	gboolean hfp_active; @@ -464,7 +488,7 @@ static void ag_io_cb(GIOChannel *chan, int err, const bdaddr_t *src,  		return;  	} -	if (chan == hsp_ag_server) { +	if (chan == adapter->hsp_ag_server) {  		hfp_active = FALSE;  		uuid = HSP_AG_UUID;  	} else { @@ -513,7 +537,7 @@ static void hs_io_cb(GIOChannel *chan, int err, const bdaddr_t *src,  	return;  } -static int headset_server_init(DBusConnection *conn, GKeyFile *config) +static int headset_server_init(struct audio_adapter *adapter)  {  	uint8_t chan = DEFAULT_HS_AG_CHANNEL;  	sdp_record_t *record; @@ -521,9 +545,6 @@ static int headset_server_init(DBusConnection *conn, GKeyFile *config)  	GError *err = NULL;  	uint32_t features, flags; -	if (!enabled.headset) -		return 0; -  	if (config) {  		gboolean tmp; @@ -551,9 +572,9 @@ static int headset_server_init(DBusConnection *conn, GKeyFile *config)  	if (master)  		flags |= RFCOMM_LM_MASTER; -	hsp_ag_server = bt_rfcomm_listen(BDADDR_ANY, chan, flags, ag_io_cb, -				NULL); -	if (!hsp_ag_server) +	adapter->hsp_ag_server = bt_rfcomm_listen(&adapter->src, chan, flags, +					ag_io_cb,adapter); +	if (!adapter->hsp_ag_server)  		return -1;  	record = hsp_ag_record(chan); @@ -562,14 +583,14 @@ static int headset_server_init(DBusConnection *conn, GKeyFile *config)  		return -1;  	} -	if (add_record_to_server(BDADDR_ANY, record) < 0) { +	if (add_record_to_server(&adapter->src, record) < 0) {  		error("Unable to register HS AG service record");  		sdp_record_free(record); -		g_io_channel_unref(hsp_ag_server); -		hsp_ag_server = NULL; +		g_io_channel_unref(adapter->hsp_ag_server); +		adapter->hsp_ag_server = NULL;  		return -1;  	} -	hsp_ag_record_id = record->handle; +	adapter->hsp_ag_record_id = record->handle;  	features = headset_config_init(config); @@ -578,9 +599,9 @@ static int headset_server_init(DBusConnection *conn, GKeyFile *config)  	chan = DEFAULT_HF_AG_CHANNEL; -	hfp_ag_server = bt_rfcomm_listen(BDADDR_ANY, chan, flags, ag_io_cb, -				NULL); -	if (!hfp_ag_server) +	adapter->hfp_ag_server = bt_rfcomm_listen(&adapter->src, chan, flags, +					ag_io_cb, adapter); +	if (!adapter->hfp_ag_server)  		return -1;  	record = hfp_ag_record(chan, features); @@ -589,19 +610,19 @@ static int headset_server_init(DBusConnection *conn, GKeyFile *config)  		return -1;  	} -	if (add_record_to_server(BDADDR_ANY, record) < 0) { +	if (add_record_to_server(&adapter->src, record) < 0) {  		error("Unable to register HF AG service record");  		sdp_record_free(record); -		g_io_channel_unref(hfp_ag_server); -		hfp_ag_server = NULL; +		g_io_channel_unref(adapter->hfp_ag_server); +		adapter->hfp_ag_server = NULL;  		return -1;  	} -	hfp_ag_record_id = record->handle; +	adapter->hfp_ag_record_id = record->handle;  	return 0;  } -static int gateway_server_init(DBusConnection *conn, GKeyFile *config) +static int gateway_server_init(struct audio_adapter *adapter)  {  	uint8_t chan = DEFAULT_HSP_HS_CHANNEL;  	sdp_record_t *record; @@ -609,9 +630,6 @@ static int gateway_server_init(DBusConnection *conn, GKeyFile *config)  	GError *err = NULL;  	uint32_t flags; -	if (!enabled.gateway) -		return 0; -  	if (config) {  		gboolean tmp; @@ -630,9 +648,9 @@ static int gateway_server_init(DBusConnection *conn, GKeyFile *config)  	if (master)  		flags |= RFCOMM_LM_MASTER; -	hsp_hs_server = bt_rfcomm_listen(BDADDR_ANY, chan, flags, hs_io_cb, -				NULL); -	if (!hsp_hs_server) +	adapter->hsp_hs_server = bt_rfcomm_listen(&adapter->src, chan, flags, +				hs_io_cb, adapter); +	if (!adapter->hsp_hs_server)  		return -1;  	record = hsp_hs_record(chan); @@ -641,52 +659,19 @@ static int gateway_server_init(DBusConnection *conn, GKeyFile *config)  		return -1;  	} -	if (add_record_to_server(BDADDR_ANY, record) < 0) { +	if (add_record_to_server(&adapter->src, record) < 0) {  		error("Unable to register HSP HS service record");  		sdp_record_free(record); -		g_io_channel_unref(hsp_hs_server); -		hsp_hs_server = NULL; +		g_io_channel_unref(adapter->hsp_hs_server); +		adapter->hsp_hs_server = NULL;  		return -1;  	} -	hsp_hs_record_id = record->handle; +	adapter->hsp_hs_record_id = record->handle;  	return 0;  } -static void server_exit(void) -{ -	if (hsp_ag_record_id) { -		remove_record_from_server(hsp_ag_record_id); -		hsp_ag_record_id = 0; -	} - -	if (hsp_ag_server) { -		g_io_channel_unref(hsp_ag_server); -		hsp_ag_server = NULL; -	} - -	if (hsp_hs_record_id) { -		remove_record_from_server(hsp_hs_record_id); -		hsp_hs_record_id = 0; -	} - -	if (hsp_hs_server) { -		g_io_channel_unref(hsp_hs_server); -		hsp_hs_server = NULL; -	} - -	if (hfp_ag_record_id) { -		remove_record_from_server(hfp_ag_record_id); -		hfp_ag_record_id = 0; -	} - -	if (hfp_ag_server) { -		g_io_channel_unref(hfp_ag_server); -		hfp_ag_server = NULL; -	} -} -  static int audio_probe(struct btd_device_driver *driver,  			struct btd_device *device, GSList *records)  { @@ -733,6 +718,148 @@ static void audio_remove(struct btd_device_driver *driver,  	device_unregister(dev);  } +static struct audio_adapter *create_audio_adapter(const char *path, bdaddr_t *src) +{ +	struct audio_adapter *adp; + +	adp = g_new0(struct audio_adapter, 1); +	adp->path = g_strdup(path); +	bacpy(&adp->src, src); + +	return adp; +} + +static struct audio_adapter *get_audio_adapter(struct adapter *adapter) +{ +	struct audio_adapter *adp; +	const gchar *path = adapter_get_path(adapter); +	const char *source; +	bdaddr_t src; + +	source = adapter_get_address(adapter); +	str2ba(source, &src); + +	adp = find_adapter(adapters, path); +	if (!adp) { +		adp = create_audio_adapter(path, &src); +		if (!adp) +			return NULL; +		adapters = g_slist_append(adapters, adp); +	} + +	return adp; +} + +static int headset_server_probe(struct adapter *adapter) +{ +	struct audio_adapter *adp; +	const gchar *path = adapter_get_path(adapter); + +	DBG("path %s", path); + +	adp = get_audio_adapter(adapter); +	if (!adp) +		return -EINVAL; + +	return headset_server_init(adp); +} + +static void headset_server_remove(struct adapter *adapter) +{ +	struct audio_adapter *adp; +	const gchar *path = adapter_get_path(adapter); + +	DBG("path %s", path); + +	adp = find_adapter(adapters, path); +	if (!adp) +		return; + +	if (adp->hsp_ag_record_id) { +		remove_record_from_server(adp->hsp_ag_record_id); +		adp->hsp_ag_record_id = 0; +	} + +	if (adp->hsp_ag_server) { +		g_io_channel_unref(adp->hsp_ag_server); +		adp->hsp_ag_server = NULL; +	} + +	if (adp->hfp_ag_record_id) { +		remove_record_from_server(adp->hfp_ag_record_id); +		adp->hfp_ag_record_id = 0; +	} + +	if (adp->hfp_ag_server) { +		g_io_channel_unref(adp->hfp_ag_server); +		adp->hfp_ag_server = NULL; +	} +} + +static int gateway_server_probe(struct adapter *adapter) +{ +	struct audio_adapter *adp; +	const gchar *path = adapter_get_path(adapter); + +	DBG("path %s", path); + +	adp = get_audio_adapter(adapter); +	if (!adp) +		return -EINVAL; + +	return gateway_server_init(adp); +} + +static void gateway_server_remove(struct adapter *adapter) +{ +	struct audio_adapter *adp; +	const gchar *path = adapter_get_path(adapter); + +	DBG("path %s", path); + +	adp = find_adapter(adapters, path); +	if (!adp) +		return; + +	if (adp->hsp_hs_record_id) { +		remove_record_from_server(adp->hsp_hs_record_id); +		adp->hsp_hs_record_id = 0; +	} + +	if (adp->hsp_hs_server) { +		g_io_channel_unref(adp->hsp_hs_server); +		adp->hsp_hs_server = NULL; +	} +} + +static int a2dp_server_probe(struct adapter *adapter) +{ +	struct audio_adapter *adp; +	const gchar *path = adapter_get_path(adapter); + +	DBG("path %s", path); + +	adp = get_audio_adapter(adapter); +	if (!adp) +		return -EINVAL; + +	return a2dp_init(connection, config); +} + +static int avrcp_server_probe(struct adapter *adapter) +{ +	struct audio_adapter *adp; +	const gchar *path = adapter_get_path(adapter); + +	DBG("path %s", path); + +	adp = get_audio_adapter(adapter); +	if (!adp) +		return -EINVAL; + +	return avrcp_init(connection, config); +} +  static struct btd_device_driver audio_driver = {  	.name	= "audio",  	.uuids	= BTD_UUIDS(HSP_HS_UUID, HFP_HS_UUID, HSP_AG_UUID, HFP_AG_UUID, @@ -742,16 +869,40 @@ static struct btd_device_driver audio_driver = {  	.remove	= audio_remove,  }; -int audio_manager_init(DBusConnection *conn, GKeyFile *config) +static struct btd_adapter_driver headset_server_driver = { +	.name	= "audio-headset", +	.probe	= headset_server_probe, +	.remove	= headset_server_remove, +}; + +static struct btd_adapter_driver gateway_server_driver = { +	.name	= "audio-gateway", +	.probe	= gateway_server_probe, +	.remove	= gateway_server_remove, +}; + +static struct btd_adapter_driver a2dp_server_driver = { +	.name	= "audio-a2dp", +	.probe	= a2dp_server_probe, +}; + +static struct btd_adapter_driver avrcp_server_driver = { +	.name	= "audio-control", +	.probe	= avrcp_server_probe, +}; + +int audio_manager_init(DBusConnection *conn, GKeyFile *conf)  {  	char **list;  	int i;  	connection = dbus_connection_ref(conn); -	if (!config) +	if (!conf)  		goto proceed; +	config = conf; +  	list = g_key_file_get_string_list(config, "General", "Enable",  						NULL, NULL);  	for (i = 0; list && list[i] != NULL; i++) { @@ -785,38 +936,42 @@ int audio_manager_init(DBusConnection *conn, GKeyFile *config)  	g_strfreev(list);  proceed: -	if (enabled.headset) { -		if (headset_server_init(conn, config) < 0) -			goto failed; -	} +	if (enabled.headset) +		btd_register_adapter_driver(&headset_server_driver); -	if (enabled.gateway) { -		if (gateway_server_init(conn, config) < 0) -			goto failed; -	} +	if (enabled.gateway) +		btd_register_adapter_driver(&gateway_server_driver); -	if (enabled.source || enabled.sink) { -		if (a2dp_init(conn, config) < 0) -			goto failed; -	} +	if (enabled.source || enabled.sink) +		btd_register_adapter_driver(&a2dp_server_driver); -	if (enabled.control && avrcp_init(conn, config) < 0) -		goto failed; +	if (enabled.control) +		btd_register_adapter_driver(&avrcp_server_driver);  	btd_register_device_driver(&audio_driver);  	return 0; -failed: -	audio_manager_exit(); -	return -1;  }  void audio_manager_exit(void)  { -	server_exit(); -  	dbus_connection_unref(connection); +	if (config) +		g_key_file_free(config); + +	if (enabled.headset) +		btd_unregister_adapter_driver(&headset_server_driver); + +	if (enabled.gateway) +		btd_unregister_adapter_driver(&gateway_server_driver); + +	if (enabled.source || enabled.sink) +		btd_unregister_adapter_driver(&a2dp_server_driver); + +	if (enabled.control) +		btd_unregister_adapter_driver(&avrcp_server_driver); +  	btd_unregister_device_driver(&audio_driver);  	connection = NULL; diff --git a/audio/manager.h b/audio/manager.h index 701511a1..209488b0 100644 --- a/audio/manager.h +++ b/audio/manager.h @@ -39,7 +39,7 @@ typedef void (*create_dev_cb_t) (struct audio_device *dev, void *user_data);  int audio_manager_init(DBusConnection *conn, GKeyFile *config);  void audio_manager_exit(void); -gboolean server_is_enabled(uint16_t svc); +gboolean server_is_enabled(bdaddr_t *src, uint16_t svc);  struct audio_device *manager_find_device(const bdaddr_t *bda, const char *interface,  					gboolean connected); | 
