diff options
| -rw-r--r-- | audio/pcm_bluetooth.c | 59 | ||||
| -rw-r--r-- | audio/unix.c | 123 | 
2 files changed, 121 insertions, 61 deletions
diff --git a/audio/pcm_bluetooth.c b/audio/pcm_bluetooth.c index 6f67ca57..b0e3838b 100644 --- a/audio/pcm_bluetooth.c +++ b/audio/pcm_bluetooth.c @@ -422,6 +422,49 @@ static int bluetooth_prepare(snd_pcm_ioplug_t *io)  	return write(data->pipefd[1], &c, 1);  } +static int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io, +					snd_pcm_hw_params_t *params) +{ +	struct bluetooth_data *data = io->private_data; +	char buf[BT_AUDIO_IPC_PACKET_SIZE]; +	bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf; +	struct bt_setconfiguration_req *setconf_req = (void*) buf; +	struct bt_setconfiguration_rsp *setconf_rsp = (void*) buf; +	int err; + +	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu", +					io->period_size, io->buffer_size); + +	memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE); +	setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ; +	strncpy(setconf_req->device, data->alsa_config.device, 18); +	setconf_req->transport = BT_CAPABILITIES_TRANSPORT_SCO; +	setconf_req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ? +			BT_CAPABILITIES_ACCESS_MODE_WRITE : +			BT_CAPABILITIES_ACCESS_MODE_READ); + +	err = audioservice_send(data->server.fd, &setconf_req->h); +	if (err < 0) +		return err; + +	err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h, +					BT_SETCONFIGURATION_RSP); +	if (err < 0) +		return err; + +	if (rsp_hdr->posix_errno != 0) { +		SNDERR("BT_SETCONFIGURATION failed : %s(%d)", +					strerror(rsp_hdr->posix_errno), +					rsp_hdr->posix_errno); +		return -rsp_hdr->posix_errno; +	} + +	data->transport = setconf_rsp->transport; +	data->link_mtu = setconf_rsp->link_mtu; + +	return 0; +} +  static uint8_t default_bitpool(uint8_t freq, uint8_t mode)  {  	switch (freq) { @@ -565,6 +608,8 @@ static int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io,  	memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE);  	setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ; +	strncpy(setconf_req->device, data->alsa_config.device, 18); +	setconf_req->transport = BT_CAPABILITIES_TRANSPORT_A2DP;  	setconf_req->sbc_capabilities = active_capabilities;  	setconf_req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ?  			BT_CAPABILITIES_ACCESS_MODE_WRITE : @@ -762,7 +807,7 @@ static snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io,  	/* Increment hardware transmition pointer */  	data->hw_ptr = (data->hw_ptr + data->link_mtu / frame_size) % -								io->buffer_size; +				io->buffer_size;  proceed:  	buff = (unsigned char *) areas->addr + @@ -1020,6 +1065,7 @@ static snd_pcm_ioplug_callback_t bluetooth_hsp_playback = {  	.stop			= bluetooth_playback_stop,  	.pointer		= bluetooth_pointer,  	.close			= bluetooth_close, +	.hw_params		= bluetooth_hsp_hw_params,  	.prepare		= bluetooth_prepare,  	.transfer		= bluetooth_hsp_write,  	.poll_descriptors	= bluetooth_playback_poll_descriptors, @@ -1032,6 +1078,7 @@ static snd_pcm_ioplug_callback_t bluetooth_hsp_capture = {  	.stop			= bluetooth_stop,  	.pointer		= bluetooth_pointer,  	.close			= bluetooth_close, +	.hw_params		= bluetooth_hsp_hw_params,  	.prepare		= bluetooth_prepare,  	.transfer		= bluetooth_hsp_read,  	.poll_descriptors	= bluetooth_poll_descriptors, @@ -1467,11 +1514,7 @@ static int bluetooth_init(struct bluetooth_data *data, snd_pcm_stream_t stream,  		getcaps_req->transport = alsa_conf->transport;  	else  		getcaps_req->transport = BT_CAPABILITIES_TRANSPORT_ANY; -/* -	getcaps_req->access_mode = (stream == SND_PCM_STREAM_PLAYBACK ? -			BT_CAPABILITIES_ACCESS_MODE_WRITE : -			BT_CAPABILITIES_ACCESS_MODE_READ); -*/ +  	err = audioservice_send(data->server.fd, &getcaps_req->h);  	if (err < 0)  		goto failed; @@ -1488,9 +1531,7 @@ static int bluetooth_init(struct bluetooth_data *data, snd_pcm_stream_t stream,  	}  	data->transport = getcaps_rsp->transport; -/* -	data->link_mtu = getcaps_rsp->link_mtu; -*/ +  	if (getcaps_rsp->transport == BT_CAPABILITIES_TRANSPORT_A2DP)  		data->a2dp.sbc_capabilities = getcaps_rsp->sbc_capabilities; diff --git a/audio/unix.c b/audio/unix.c index 8267e895..442dca79 100644 --- a/audio/unix.c +++ b/audio/unix.c @@ -216,55 +216,34 @@ static void stream_state_changed(struct avdtp_stream *stream,  		break;  	}  } -/* +  static void headset_discovery_complete(struct device *dev, void *user_data)  {  	struct unix_client *client = user_data;  	char buf[BT_AUDIO_IPC_PACKET_SIZE];  	struct bt_getcapabilities_rsp *rsp = (void *) buf; -	struct headset_data *hs = &client->d.hs;  	client->req_id = 0; -	if (!dev) { -		unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO); -		client->dev = NULL; -		return; -	} - -	switch (client->access_mode) { -	case BT_CAPABILITIES_ACCESS_MODE_READ: -		hs->lock = HEADSET_LOCK_READ; -		break; -	case BT_CAPABILITIES_ACCESS_MODE_WRITE: -		hs->lock = HEADSET_LOCK_WRITE; -		break; -	case BT_CAPABILITIES_ACCESS_MODE_READWRITE: -		hs->lock = HEADSET_LOCK_READ | HEADSET_LOCK_WRITE; -		break; -	default: -		hs->lock = 0; -		break; -	} - -	if (!headset_lock(dev, hs->lock)) { -		error("Unable to lock headset"); -		unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO); -		client->dev = NULL; -		return; -	} +	if (!dev) +		goto failed;  	memset(buf, 0, sizeof(buf)); -	rsp->h.msg_type = BT_GETCAPABILITIES_RSP; +	rsp->rsp_h.msg_h.msg_type = BT_GETCAPABILITIES_RSP;  	rsp->transport  = BT_CAPABILITIES_TRANSPORT_SCO;  	rsp->sampling_rate = 8000; -	client->data_fd = headset_get_sco_fd(dev); +	unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); -	unix_ipc_sendmsg(client, &rsp->h); +	return; + +failed: +	error("discovery failed"); +	unix_ipc_error(client, BT_SETCONFIGURATION_RSP, EIO); +	client->dev = NULL;  } -*/ +  static void headset_setup_complete(struct device *dev, void *user_data)  {  	struct unix_client *client = user_data; @@ -274,11 +253,8 @@ static void headset_setup_complete(struct device *dev, void *user_data)  	client->req_id = 0; -	if (!dev) { -		unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO); -		client->dev = NULL; -		return; -	} +	if (!dev) +		goto failed;  	switch (client->access_mode) {  	case BT_CAPABILITIES_ACCESS_MODE_READ: @@ -297,9 +273,7 @@ static void headset_setup_complete(struct device *dev, void *user_data)  	if (!headset_lock(dev, hs->lock)) {  		error("Unable to lock headset"); -		unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO); -		client->dev = NULL; -		return; +		goto failed;  	}  	memset(buf, 0, sizeof(buf)); @@ -307,10 +281,55 @@ static void headset_setup_complete(struct device *dev, void *user_data)  	rsp->rsp_h.msg_h.msg_type = BT_SETCONFIGURATION_RSP;  	rsp->transport  = BT_CAPABILITIES_TRANSPORT_SCO;  	rsp->access_mode = client->access_mode; +	rsp->link_mtu = 48;  	client->data_fd = headset_get_sco_fd(dev);  	unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); + +	return; + +failed: +	error("config failed"); +	unix_ipc_error(client, BT_SETCONFIGURATION_RSP, EIO); +	client->dev = NULL; +} + +static void headset_resume_complete(struct device *dev, void *user_data) +{ +	struct unix_client *client = user_data; +	char buf[BT_AUDIO_IPC_PACKET_SIZE]; +	struct bt_streamstart_rsp *rsp = (void *) buf; +	struct bt_streamfd_ind *ind = (void *) buf; + +	client->req_id = 0; + +	if (!dev) +		goto failed; + +	memset(buf, 0, sizeof(buf)); + +	rsp->rsp_h.msg_h.msg_type = BT_STREAMSTART_RSP; + +	unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); + +	memset(buf, 0, sizeof(buf)); +	ind->h.msg_type = BT_STREAMFD_IND; +	unix_ipc_sendmsg(client, &ind->h); + +	client->data_fd = headset_get_sco_fd(dev); + +	if (unix_sendmsg_fd(client->sock, client->data_fd) < 0) { +		error("unix_sendmsg_fd: %s(%d)", strerror(errno), errno); +		goto failed; +	} + +	return; + +failed: +	error("resume failed"); +	unix_ipc_error(client, BT_STREAMSTART_RSP, EIO); +	client->dev = NULL;  }  static void a2dp_discovery_complete(struct avdtp *session, GSList *seps, @@ -421,7 +440,7 @@ static void a2dp_config_complete(struct avdtp *session, struct a2dp_sep *sep,  	return;  failed: -	error("setup failed"); +	error("config failed");  	if (a2dp->sep) {  		a2dp_sep_unlock(a2dp->sep, a2dp->session); @@ -511,7 +530,6 @@ failed:  static void start_discovery(struct device *dev, struct unix_client *client)  {  	struct a2dp_data *a2dp; -	unsigned int id;  	int err = 0;  	client->type = select_service(dev, client->interface); @@ -535,8 +553,7 @@ static void start_discovery(struct device *dev, struct unix_client *client)  		break;  	case TYPE_HEADSET: -		id = headset_request_stream(dev, headset_setup_complete, client); -		client->cancel = headset_cancel_stream; +		headset_discovery_complete(dev, client);  		break;  	default: @@ -544,6 +561,8 @@ static void start_discovery(struct device *dev, struct unix_client *client)  		goto failed;  	} +	client->dev = dev; +  	return;  failed: @@ -625,11 +644,16 @@ static void start_resume(struct device *dev, struct unix_client *client)  		id = a2dp_source_resume(a2dp->session, a2dp->sep,  					a2dp_resume_complete, client);  		client->cancel = a2dp_source_cancel; + +		if (id == 0) { +			error("resume failed"); +			goto failed; +		} +  		break;  	case TYPE_HEADSET: -		id = headset_request_stream(dev, headset_setup_complete, client); -		client->cancel = headset_cancel_stream; +		headset_resume_complete(dev, client);  		break;  	default: @@ -637,11 +661,6 @@ static void start_resume(struct device *dev, struct unix_client *client)  		goto failed;  	} -	if (id == 0) { -		error("resume failed"); -		goto failed; -	} -  	return;  failed:  | 
