diff options
| author | Johan Hedberg <johan.hedberg@nokia.com> | 2007-08-27 11:31:01 +0000 | 
|---|---|---|
| committer | Johan Hedberg <johan.hedberg@nokia.com> | 2007-08-27 11:31:01 +0000 | 
| commit | e1bfc91de96a38616100cc31db7bdb69f2cfbea6 (patch) | |
| tree | f8e2ce652875076f96b0db575a5daabb10156e66 | |
| parent | ca3ff4f6a27ff2d421a7f8fdd3bd5dd67f1f47df (diff) | |
Convert alsa initiated headset connections to similar callback system that A2DP is already using
| -rw-r--r-- | audio/headset.c | 98 | ||||
| -rw-r--r-- | audio/headset.h | 8 | ||||
| -rw-r--r-- | audio/main.c | 1 | ||||
| -rw-r--r-- | audio/sink.c | 2 | ||||
| -rw-r--r-- | audio/unix.c | 156 | ||||
| -rw-r--r-- | audio/unix.h | 2 | 
6 files changed, 145 insertions, 122 deletions
| diff --git a/audio/headset.c b/audio/headset.c index 5c758db0..da224b8a 100644 --- a/audio/headset.c +++ b/audio/headset.c @@ -51,11 +51,9 @@  #include "dbus.h"  #include "dbus-helper.h"  #include "logging.h" -#include "ipc.h"  #include "device.h"  #include "manager.h"  #include "error.h" -#include "unix.h"  #include "headset.h"  #define RING_INTERVAL 3000 @@ -71,11 +69,12 @@ static char *str_state[] = {"DISCONNECTED", "CONNECTING", "CONNECTED",  struct pending_connect {  	DBusMessage *msg;  	GIOChannel *io; -	struct ipc_packet *pkt; -	int pkt_len;  	guint io_id;  	int sock;  	int err; +	unsigned int id; +	headset_stream_cb_t cb; +	void *cb_data;  };  struct headset { @@ -109,8 +108,6 @@ static int rfcomm_connect(struct device *device, struct pending_connect *c);  static void pending_connect_free(struct pending_connect *c)  { -	if (c->pkt) -		g_free(c->pkt);  	if (c->io) {  		g_io_channel_close(c->io);  		g_io_channel_unref(c->io); @@ -342,6 +339,7 @@ static GIOError headset_send(struct headset *hs, const char *str)  static void pending_connect_ok(struct pending_connect *c, struct device *dev)  { +	struct headset *hs = dev->headset;  	DBusMessage *reply;  	if (c->msg) { @@ -349,29 +347,34 @@ static void pending_connect_ok(struct pending_connect *c, struct device *dev)  		if (reply)  			send_message_and_unref(dev->conn, reply);  	} -	else if (c->pkt) { -		struct ipc_data_cfg *rsp; -		int ret, fd; - -		ret = headset_get_config(dev, c->sock, c->pkt, c->pkt_len, -						&rsp, &fd); -		if (ret == 0) { -			unix_send_cfg(c->sock, rsp, fd); -			g_free(rsp); -		} + +	if (c->cb) { +		if (hs->rfcomm && hs->sco) +			c->cb(dev, c->cb_data);  		else -			unix_send_cfg(c->sock, NULL, -1); +			c->cb(NULL, c->cb_data);  	}  	pending_connect_free(c);  } +static gboolean finalize_stream_setup(struct device *dev) +{ +	struct headset *hs = dev->headset; + +	g_slist_foreach(hs->pending, (GFunc) pending_connect_ok, dev); +	g_slist_free(hs->pending); +	hs->pending = NULL; + +	return FALSE; +} +  static void pending_connect_failed(struct pending_connect *c, struct device *dev)  {  	if (c->msg)  		err_connect_failed(dev->conn, c->msg, strerror(c->err)); -	if (c->pkt) -		unix_send_cfg(c->sock, NULL, -1); +	if (c->cb) +		c->cb(NULL, c->cb_data);  	pending_connect_free(c);  } @@ -537,7 +540,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond,  	g_io_add_watch(chan, G_IO_IN | G_IO_ERR | G_IO_HUP| G_IO_NVAL,  			(GIOFunc) rfcomm_io_cb, device); -	if (c->pkt) { +	if (c->cb) {  		if (sco_connect(device, c) < 0)  			goto failed;  		return FALSE; @@ -1396,50 +1399,38 @@ void headset_free(struct device *dev)  	dev->headset = NULL;  } -int headset_get_config(struct device *dev, int sock, struct ipc_packet *pkt, -			int pkt_len, struct ipc_data_cfg **cfg, int *fd) +unsigned int headset_request_stream(struct device *dev, headset_stream_cb_t cb, +					void *user_data)  {  	struct headset *hs = dev->headset; -	int err = EINVAL;  	struct pending_connect *c; - -	if (hs->rfcomm && hs->sco) -		goto proceed; +	static unsigned int cb_id = 0; +	int err;  	c = g_new0(struct pending_connect, 1); -	c->sock = sock; -	c->pkt = g_malloc(pkt_len); -	memcpy(c->pkt, pkt, pkt_len); +	c->cb = cb; +	c->cb_data = user_data; +	c->id = ++cb_id; + +	if (hs->rfcomm && hs->sco) { +		hs->pending = g_slist_append(hs->pending, c); +		g_idle_add((GSourceFunc) finalize_stream_setup, hs); +		return c->id; +	}  	if (hs->rfcomm == NULL)  		err = rfcomm_connect(dev, c);  	else if (hs->sco == NULL)  		err = sco_connect(dev, c); -	else -		goto error;  	if (err < 0)  		goto error; -	return 1; - -proceed: -	*cfg = g_new0(struct ipc_data_cfg, 1); -	(*cfg)->fd_opt = CFG_FD_OPT_READWRITE; -	(*cfg)->codec = CFG_CODEC_NONE; -	(*cfg)->channels = 1; -	(*cfg)->channel_mode = CFG_CHANNEL_MODE_MONO; -	(*cfg)->pkt_len = 48; -	(*cfg)->sample_size = 2; -	(*cfg)->rate = 8000; -	*fd = g_io_channel_unix_get_fd(hs->sco); - -	return 0; +	return c->id;  error: -	if (c) -		pending_connect_free(c); -	return -err; +	pending_connect_free(c); +	return 0;  }  headset_type_t headset_get_type(struct device *dev) @@ -1607,3 +1598,14 @@ gboolean headset_play(struct device *dev, void *data)  {  	return TRUE;  } + +int headset_get_sco_fd(struct device *dev) +{ +	struct headset *hs = dev->headset; + +	if (!hs->sco) +		return -1; + +	return g_io_channel_unix_get_fd(hs->sco); +} + diff --git a/audio/headset.h b/audio/headset.h index 29e2e496..31486834 100644 --- a/audio/headset.h +++ b/audio/headset.h @@ -46,6 +46,8 @@ typedef enum {  	SVC_HANDSFREE  } headset_type_t; +typedef void (*headset_stream_cb_t) (struct device *dev, void *user_data); +  struct headset *headset_init(struct device *dev, sdp_record_t *record,  				uint16_t svc); @@ -53,8 +55,8 @@ void headset_free(struct device *dev);  void headset_update(struct device *dev, sdp_record_t *record, uint16_t svc); -int headset_get_config(struct device *dev, int sock, struct ipc_packet *pkt, -			int pkt_len, struct ipc_data_cfg **rsp, int *fd); +unsigned int headset_request_stream(struct device *dev, headset_stream_cb_t cb, +					void *user_data);  headset_type_t headset_get_type(struct device *dev);  void headset_set_type(struct device *dev, headset_type_t type); @@ -67,6 +69,8 @@ void headset_set_state(struct device *dev, headset_state_t state);  int headset_get_channel(struct device *dev); +int headset_get_sco_fd(struct device *dev); +  gboolean headset_is_active(struct device *dev);  gboolean headset_lock(struct device *dev, void *data); diff --git a/audio/main.c b/audio/main.c index bd9cd0c5..3ca2ba40 100644 --- a/audio/main.c +++ b/audio/main.c @@ -37,7 +37,6 @@  #include "dbus.h"  #include "logging.h" -#include "ipc.h"  #include "unix.h"  #include "manager.h" diff --git a/audio/sink.c b/audio/sink.c index 0dc12eb3..4bebf738 100644 --- a/audio/sink.c +++ b/audio/sink.c @@ -38,11 +38,9 @@  #include "logging.h"  #include "avdtp.h" -#include "ipc.h"  #include "device.h"  #include "a2dp.h"  #include "error.h" -#include "unix.h"  #include "sink.h"  struct pending_request { diff --git a/audio/unix.c b/audio/unix.c index 246d6813..9fa5fc08 100644 --- a/audio/unix.c +++ b/audio/unix.c @@ -185,6 +185,86 @@ static void stream_state_changed(struct avdtp_stream *stream,  	}  } +static int unix_send_cfg(int sock, struct ipc_data_cfg *cfg, int fd) +{ +	char buf[IPC_MTU]; +	struct ipc_packet *pkt = (void *) buf; +	int len, codec_len; + +	memset(buf, 0, sizeof(buf)); + +	pkt->type = PKT_TYPE_CFG_RSP; + +	if (!cfg) { +		pkt->error = EINVAL; +		len = send(sock, pkt, sizeof(struct ipc_packet), 0); +		if (len < 0) +			error("send: %s (%d)", strerror(errno), errno); +		return len; +	} + +	debug("fd=%d, fd_opt=%u, channels=%u, pkt_len=%u," +		"sample_size=%u, rate=%u", fd, cfg->fd_opt, cfg->channels, +		cfg->pkt_len, cfg->sample_size, cfg->rate); + +	if (cfg->codec == CFG_CODEC_SBC) +		codec_len = sizeof(struct ipc_codec_sbc); +	else +		codec_len = 0; + +	pkt->error = PKT_ERROR_NONE; +	pkt->length = sizeof(struct ipc_data_cfg) + codec_len; +	memcpy(pkt->data, cfg, pkt->length); + +	len = sizeof(struct ipc_packet) + pkt->length; +	len = send(sock, pkt, len, 0); +	if (len < 0) +		error("Error %s(%d)", strerror(errno), errno); + +	debug("%d bytes sent", len); + +	if (fd != -1) { +		len = unix_sendmsg_fd(sock, fd, pkt); +		if (len < 0) +			error("Error %s(%d)", strerror(errno), errno); +		debug("%d bytes sent", len); +	} + +	return 0; +} + + +static void headset_setup_complete(struct device *dev, void *user_data) +{ +	struct unix_client *client = user_data; +	struct ipc_data_cfg cfg; +	int fd; + +	if (!dev) { +		unix_send_cfg(client->sock, NULL, -1); +		client->dev = NULL; +		return; +	} + +	memset(&cfg, 0, sizeof(cfg)); + +	cfg.fd_opt = CFG_FD_OPT_READWRITE; +	cfg.codec = CFG_CODEC_NONE; +	cfg.channels = 1; +	cfg.channel_mode = CFG_CHANNEL_MODE_MONO; +	cfg.pkt_len = 48; +	cfg.sample_size = 2; +	cfg.rate = 8000; + +	fd = headset_get_sco_fd(dev); + +	unix_send_cfg(client->sock, &cfg, fd); + +	client->disconnect = (notify_cb_t) headset_unlock; +	client->suspend = (notify_cb_t) headset_suspend; +	client->play = (notify_cb_t) headset_play; +} +  static void a2dp_setup_complete(struct avdtp *session, struct device *dev,  					struct avdtp_stream *stream,  					void *user_data) @@ -300,9 +380,7 @@ failed:  static void cfg_event(struct unix_client *client, struct ipc_packet *pkt,  			int len)  { -	struct ipc_data_cfg *rsp;  	struct device *dev; -	int ret, fd;  	unsigned int id;  	struct a2dp_data *a2dp;  	bdaddr_t bdaddr; @@ -341,32 +419,24 @@ proceed:  		id = a2dp_source_request_stream(a2dp->session, dev,  						TRUE, a2dp_setup_complete,  						client, &a2dp->sep); -		if (id == 0) { -			error("request_stream failed"); -			goto failed; -		} - -		client->req_id = id; -  		break;  	case TYPE_HEADSET: -		if (!headset_lock(dev, client->d.data)) { -			error("Unable to lock headset"); -			goto failed; -		} - -		ret = headset_get_config(dev, client->sock, pkt, len, &rsp, -						&fd); -		client->disconnect = (notify_cb_t) headset_unlock; -		client->suspend = (notify_cb_t) headset_suspend; -		client->play = (notify_cb_t) headset_play; +		id = headset_request_stream(dev, headset_setup_complete, +						client);  		break;  	default:  		error("No known services for device");  		goto failed;  	} +	if (id == 0) { +		error("request_stream failed"); +		goto failed; +	} + +	client->req_id = id;  	client->dev = dev; +  	return;  failed: @@ -553,54 +623,6 @@ void unix_exit(void)  	unix_sock = -1;  } -int unix_send_cfg(int sock, struct ipc_data_cfg *cfg, int fd) -{ -	char buf[IPC_MTU]; -	struct ipc_packet *pkt = (void *) buf; -	int len, codec_len; - -	memset(buf, 0, sizeof(buf)); - -	pkt->type = PKT_TYPE_CFG_RSP; - -	if (!cfg) { -		pkt->error = EINVAL; -		len = send(sock, pkt, sizeof(struct ipc_packet), 0); -		if (len < 0) -			error("send: %s (%d)", strerror(errno), errno); -		return len; -	} - -	debug("fd=%d, fd_opt=%u, channels=%u, pkt_len=%u," -		"sample_size=%u, rate=%u", fd, cfg->fd_opt, cfg->channels, -		cfg->pkt_len, cfg->sample_size, cfg->rate); - -	if (cfg->codec == CFG_CODEC_SBC) -		codec_len = sizeof(struct ipc_codec_sbc); -	else -		codec_len = 0; - -	pkt->error = PKT_ERROR_NONE; -	pkt->length = sizeof(struct ipc_data_cfg) + codec_len; -	memcpy(pkt->data, cfg, pkt->length); - -	len = sizeof(struct ipc_packet) + pkt->length; -	len = send(sock, pkt, len, 0); -	if (len < 0) -		error("Error %s(%d)", strerror(errno), errno); - -	debug("%d bytes sent", len); - -	if (fd != -1) { -		len = unix_sendmsg_fd(sock, fd, pkt); -		if (len < 0) -			error("Error %s(%d)", strerror(errno), errno); -		debug("%d bytes sent", len); -	} - -	return 0; -} -  #if 0  static int unix_send_state(int sock, struct ipc_packet *pkt)  { diff --git a/audio/unix.h b/audio/unix.h index 7f42688c..feea855f 100644 --- a/audio/unix.h +++ b/audio/unix.h @@ -23,5 +23,3 @@  int unix_init(void);  void unix_exit(void); - -int unix_send_cfg(int sock, struct ipc_data_cfg *cfg, int fd); | 
