diff options
| -rw-r--r-- | audio/ipc.h | 40 | ||||
| -rw-r--r-- | audio/pcm_bluetooth.c | 62 | ||||
| -rw-r--r-- | audio/unix.c | 203 | 
3 files changed, 150 insertions, 155 deletions
| diff --git a/audio/ipc.h b/audio/ipc.h index 2043b761..1c26e304 100644 --- a/audio/ipc.h +++ b/audio/ipc.h @@ -60,36 +60,38 @@ struct ipc_packet {  } __attribute__ ((packed));  /* File descriptor options */ -#define CFG_FD_OPT_READ			0 -#define CFG_FD_OPT_WRITE		1 -#define CFG_FD_OPT_READWRITE		2 +#define CFG_FD_OPT_READ		0 +#define CFG_FD_OPT_WRITE	1 +#define CFG_FD_OPT_READWRITE	2  /* Audio channel mode */ -#define CFG_CHANNEL_MODE_MONO		(1 << 3) -#define CFG_CHANNEL_MODE_DUAL_CHANNEL	(1 << 2) -#define CFG_CHANNEL_MODE_STEREO		(1 << 1) -#define CFG_CHANNEL_MODE_JOINT_STEREO	1 +#define CFG_MODE_AUTO		0 +#define CFG_MODE_MONO		1 +#define CFG_MODE_DUAL_CHANNEL	2 +#define CFG_MODE_STEREO		3 +#define CFG_MODE_JOINT_STEREO	4 + +/* Allocation method */ +#define CFG_ALLOCATION_AUTO	0 +#define CFG_ALLOCATION_LOUDNESS	1 +#define CFG_ALLOCATION_SNR	2  /* Codec options */ -#define CFG_CODEC_NONE			0 -#define CFG_CODEC_SBC			1 +#define CFG_CODEC_NONE		0 +#define CFG_CODEC_SCO		1 +#define CFG_CODEC_SBC		2  struct ipc_data_cfg { -	uint8_t fd_opt;		/* Stream file descriptor options: read, +	uint8_t  fd_opt;	/* Stream file descriptor options: read,  				   write or readwrite */ -	uint8_t channels;	/* Number of audio channel */ -	uint8_t channel_mode;	/* Audio channel mode*/  	uint16_t pkt_len;	/* Stream packet length */ -	uint8_t sample_size;	/* Sample size in bytes */ +	uint8_t  sample_size;	/* Sample size in bytes */ +	uint8_t  mode;		/* Audio channel mode */  	uint16_t rate;		/* Stream sample rate */ -	uint8_t codec;		/* Stream codec */ -	uint8_t data[0];	/* Codec payload */ +	uint8_t  codec;		/* Stream codec */ +	uint8_t  data[0];	/* Codec payload */  } __attribute__ ((packed)); -/* SBC codec options */ -#define CODEC_SBC_ALLOCATION_SNR	(1 << 1) -#define CODEC_SBC_ALLOCATION_LOUDNESS	1 -  struct ipc_codec_sbc {  	uint8_t allocation;  	uint8_t subbands; diff --git a/audio/pcm_bluetooth.c b/audio/pcm_bluetooth.c index 92a94fc0..f712bb0f 100644 --- a/audio/pcm_bluetooth.c +++ b/audio/pcm_bluetooth.c @@ -718,7 +718,7 @@ static int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io)  	unsigned int format_list[] = {  		SND_PCM_FORMAT_S16_LE  	}; -	int err; +	int err, channels;  	/* access type */  	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, @@ -733,14 +733,15 @@ static int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io)  		return err;  	/* supported channels */ +	channels = cfg.mode == CFG_MODE_MONO ? 1 : 2;  	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, -						cfg.channels, cfg.channels); +							channels, channels);  	if (err < 0)  		return err;  	/* supported rate */  	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE, -						cfg.rate, cfg.rate); +							cfg.rate, cfg.rate);  	if (err < 0)  		return err; @@ -751,7 +752,7 @@ static int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io)  		return err;  	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, -						2, 200); +									2, 200);  	if (err < 0)  		return err; @@ -773,7 +774,7 @@ static int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io)  	unsigned int format_list[] = {  		SND_PCM_FORMAT_S16_LE  	}; -	int err; +	int err, channels;  	/* access type */  	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, @@ -788,14 +789,15 @@ static int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io)  		return err;  	/* supported channels */ +	channels = cfg.mode = CFG_MODE_MONO ? 1 : 2;  	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, -						cfg.channels, cfg.channels); +							channels, channels);  	if (err < 0)  		return err;  	/* supported rate */  	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE, -						cfg.rate, cfg.rate); +							cfg.rate, cfg.rate);  	if (err < 0)  		return err; @@ -806,7 +808,7 @@ static int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io)  		return err;  	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, -						2, 50); +									2, 50);  	if (err < 0)  		return err; @@ -874,9 +876,8 @@ static int bluetooth_a2dp_init(struct bluetooth_data *data,  	/* FIXME: init using flags? */  	sbc_init(&a2dp->sbc, 0);  	a2dp->sbc.rate = cfg->rate; -	a2dp->sbc.channels = cfg->channels; -	if (cfg->channel_mode == CFG_CHANNEL_MODE_MONO || -			cfg->channel_mode == CFG_CHANNEL_MODE_JOINT_STEREO) +	a2dp->sbc.channels = cfg->mode == CFG_MODE_MONO ? 1 : 2; +	if (cfg->mode == CFG_MODE_MONO || cfg->mode == CFG_MODE_JOINT_STEREO)  		a2dp->sbc.joint = 1;  	a2dp->sbc.allocation = sbc->allocation;  	a2dp->sbc.subbands = sbc->subbands; @@ -898,10 +899,8 @@ static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_config_t *conf)  	struct ipc_data_cfg *cfg = (void *) pkt->data;  	struct ipc_codec_sbc *sbc = (void *) cfg->data;  	snd_config_iterator_t i, next; -	const char *addr, *pref, *mode, *allocation, *rate, *subbands, -		*blocks, *bitpool; - -	cfg->channels = 2; +	const char *addr, *pref; +	const char *mode, *allocation, *rate, *subbands, *blocks, *bitpool;  	snd_config_for_each(i, next, conf) {  		snd_config_t *n = snd_config_iterator_entry(i); @@ -934,9 +933,7 @@ static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_config_t *conf)  			else if (strcmp(pref, "voice") == 0 ||  						strcmp(pref, "hfp") == 0) {  				pkt->role = PKT_ROLE_VOICE; -				cfg->channels = 1; -			} -			else if (strcmp(pref, "hifi") == 0 || +			} else if (strcmp(pref, "hifi") == 0 ||  						strcmp(pref, "a2dp") == 0)  				pkt->role = PKT_ROLE_HIFI;  			continue; @@ -958,17 +955,16 @@ static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_config_t *conf)  				return -EINVAL;  			} -			if (strcmp(pref, "mono") == 0) { -				cfg->channels = 1; -				cfg->channel_mode = CFG_CHANNEL_MODE_MONO; -			} +			if (strcmp(pref, "auto") == 0) +				cfg->mode = CFG_MODE_AUTO; +			else if (strcmp(pref, "mono") == 0) +				cfg->mode = CFG_MODE_MONO;  			else if (strcmp(pref, "dual") == 0) -				cfg->channel_mode = CFG_CHANNEL_MODE_DUAL_CHANNEL; +				cfg->mode = CFG_MODE_DUAL_CHANNEL;  			else if (strcmp(pref, "stereo") == 0) -				cfg->channel_mode = CFG_CHANNEL_MODE_STEREO; +				cfg->mode = CFG_MODE_STEREO;  			else if (strcmp(pref, "joint") == 0) -				cfg->channel_mode = CFG_CHANNEL_MODE_JOINT_STEREO; - +				cfg->mode = CFG_MODE_JOINT_STEREO;  			continue;  		} @@ -978,10 +974,12 @@ static int bluetooth_cfg_init(struct ipc_packet *pkt, snd_config_t *conf)  				return -EINVAL;  			} -			if (strcmp(pref, "snr") == 0) -				sbc->allocation = CODEC_SBC_ALLOCATION_SNR; +			if (strcmp(pref, "auto") == 0) +				sbc->allocation = CFG_ALLOCATION_AUTO;  			else if (strcmp(pref, "loudness") == 0) -				sbc->allocation = CODEC_SBC_ALLOCATION_LOUDNESS; +				sbc->allocation = CFG_ALLOCATION_LOUDNESS; +			else if (strcmp(pref, "snr") == 0) +				sbc->allocation = CFG_ALLOCATION_SNR;  			continue;  		} @@ -1093,9 +1091,9 @@ done:  	DBG("Device configuration:"); -	DBG("\n\tfd=%d\n\tfd_opt=%u\n\tchannels=%u\n\tpkt_len=%u\n\tsample_size=%u\n\trate=%u", -		data->stream_fd, data->cfg.fd_opt, data->cfg.channels, -		data->cfg.pkt_len, data->cfg.sample_size, data->cfg.rate); +	DBG("\n\tfd=%d\n\tfd_opt=%u\n\tpkt_len=%u\n\tsample_size=%u\n\trate=%u", +			data->stream_fd, data->cfg.fd_opt, data->cfg.pkt_len, +					data->cfg.sample_size, data->cfg.rate);  	if (data->cfg.codec == CFG_CODEC_SBC) {  		ret = bluetooth_a2dp_init(data, sbc); diff --git a/audio/unix.c b/audio/unix.c index 7fa2db05..3b9d6d46 100644 --- a/audio/unix.c +++ b/audio/unix.c @@ -209,9 +209,9 @@ static int unix_send_cfg(int sock, struct ipc_data_cfg *cfg, int fd)  		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); +	debug("fd=%d, fd_opt=%u, pkt_len=%u, sample_size=%u, rate=%u", +						fd, cfg->fd_opt, cfg->pkt_len, +						cfg->sample_size, cfg->rate);  	if (cfg->codec == CFG_CODEC_SBC)  		codec_len = sizeof(struct ipc_codec_sbc); @@ -258,9 +258,8 @@ static void headset_setup_complete(struct device *dev, void *user_data)  	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.codec = CFG_CODEC_SCO; +	cfg.mode = CFG_MODE_MONO;  	cfg.pkt_len = 48;  	cfg.sample_size = 2;  	cfg.rate = 8000; @@ -327,24 +326,22 @@ static void a2dp_setup_complete(struct avdtp *session, struct device *dev,  	cfg->fd_opt = CFG_FD_OPT_WRITE;  	sbc_cap = (void *) codec_cap; -	cfg->channels = sbc_cap->channel_mode == A2DP_CHANNEL_MODE_MONO ? -				1 : 2; -	cfg->channel_mode = sbc_cap->channel_mode; +	cfg->mode = sbc_cap->channel_mode;  	cfg->sample_size = 2;  	switch (sbc_cap->frequency) { -		case A2DP_SAMPLING_FREQ_16000: -			cfg->rate = 16000; -			break; -		case A2DP_SAMPLING_FREQ_32000: -			cfg->rate = 32000; -			break; -		case A2DP_SAMPLING_FREQ_44100: -			cfg->rate = 44100; -			break; -		case A2DP_SAMPLING_FREQ_48000: -			cfg->rate = 48000; -			break; +	case A2DP_SAMPLING_FREQ_16000: +		cfg->rate = 16000; +		break; +	case A2DP_SAMPLING_FREQ_32000: +		cfg->rate = 32000; +		break; +	case A2DP_SAMPLING_FREQ_44100: +		cfg->rate = 44100; +		break; +	case A2DP_SAMPLING_FREQ_48000: +		cfg->rate = 48000; +		break;  	}  	cfg->codec = CFG_CODEC_SBC; @@ -353,18 +350,18 @@ static void a2dp_setup_complete(struct avdtp *session, struct device *dev,  	sbc->subbands = sbc_cap->subbands == A2DP_SUBBANDS_4 ? 4 : 8;  	switch (sbc_cap->block_length) { -		case A2DP_BLOCK_LENGTH_4: -			sbc->blocks = 4; -			break; -		case A2DP_BLOCK_LENGTH_8: -			sbc->blocks = 8; -			break; -		case A2DP_BLOCK_LENGTH_12: -			sbc->blocks = 12; -			break; -		case A2DP_BLOCK_LENGTH_16: -			sbc->blocks = 16; -			break; +	case A2DP_BLOCK_LENGTH_4: +		sbc->blocks = 4; +		break; +	case A2DP_BLOCK_LENGTH_8: +		sbc->blocks = 8; +		break; +	case A2DP_BLOCK_LENGTH_12: +		sbc->blocks = 12; +		break; +	case A2DP_BLOCK_LENGTH_16: +		sbc->blocks = 16; +		break;  	}  	sbc->bitpool = sbc_cap->max_bitpool; @@ -454,92 +451,90 @@ static int cfg_to_caps(struct ipc_data_cfg *cfg, struct sbc_codec_cap *sbc_cap)  	sbc_cap->cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;  	sbc_cap->cap.media_codec_type = A2DP_CODEC_SBC; -	if (cfg->rate > 0) { -		switch (cfg->rate) { -		case 48000: -			sbc_cap->frequency = A2DP_SAMPLING_FREQ_48000; -			break; -		case 44100: -			sbc_cap->frequency = A2DP_SAMPLING_FREQ_44100; -			break; -		case 32000: -			sbc_cap->frequency = A2DP_SAMPLING_FREQ_32000; -			break; -		case 16000: -			sbc_cap->frequency = A2DP_SAMPLING_FREQ_16000; -			break; -		default: -			return -EINVAL; -		} -	} else +	switch (cfg->rate) { +	case 48000: +		sbc_cap->frequency = A2DP_SAMPLING_FREQ_48000; +		break; +	case 44100: +		sbc_cap->frequency = A2DP_SAMPLING_FREQ_44100; +		break; +	case 32000: +		sbc_cap->frequency = A2DP_SAMPLING_FREQ_32000; +		break; +	case 16000: +		sbc_cap->frequency = A2DP_SAMPLING_FREQ_16000; +		break; +	default:  		sbc_cap->frequency = A2DP_SAMPLING_FREQ_44100; +		break; +	} -	if (cfg->channel_mode > 0) { -		switch (cfg->channel_mode) { -		case A2DP_CHANNEL_MODE_JOINT_STEREO: -		case A2DP_CHANNEL_MODE_STEREO: -		case A2DP_CHANNEL_MODE_DUAL_CHANNEL: -		case A2DP_CHANNEL_MODE_MONO: -			sbc_cap->channel_mode = cfg->channel_mode; -			break; -		default: -			return -EINVAL; -		} -	} else +	switch (cfg->mode) { +	case CFG_MODE_MONO: +		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_MONO; +		break; +	case CFG_MODE_DUAL_CHANNEL: +		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_DUAL_CHANNEL; +		break; +	case CFG_MODE_STEREO: +		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_STEREO; +		break; +	case CFG_MODE_JOINT_STEREO: +		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_JOINT_STEREO; +		break; +	default:  		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_JOINT_STEREO; +		break; +	} -	if (sbc->allocation > 0) { -		switch (sbc->allocation) { -		case A2DP_ALLOCATION_LOUDNESS: -		case A2DP_ALLOCATION_SNR: -			sbc_cap->allocation_method = sbc->allocation; -			break; -		default: -			return -EINVAL; -		} -	} else +	switch (sbc->allocation) { +	case CFG_ALLOCATION_LOUDNESS: +		sbc_cap->allocation_method = A2DP_ALLOCATION_LOUDNESS; +		break; +	case CFG_ALLOCATION_SNR: +		sbc_cap->allocation_method = A2DP_ALLOCATION_LOUDNESS; +		break; +	default:  		sbc_cap->allocation_method = A2DP_ALLOCATION_LOUDNESS; +		break; +	} -	if (sbc->subbands > 0) { -		switch (sbc->subbands) { -		case 8: -			sbc_cap->subbands = A2DP_SUBBANDS_8; -			break; -		case 4: -			sbc_cap->subbands = A2DP_SUBBANDS_4; -			break; -		default: -			return -EINVAL; -		} -	} else +	switch (sbc->subbands) { +	case 8:  		sbc_cap->subbands = A2DP_SUBBANDS_8; +		break; +	case 4: +		sbc_cap->subbands = A2DP_SUBBANDS_4; +		break; +	default: +		sbc_cap->subbands = A2DP_SUBBANDS_8; +		break; +	} -	if (sbc->blocks > 0) { -		switch (sbc->blocks) { -		case 16: -			sbc_cap->block_length = A2DP_BLOCK_LENGTH_16; -			break; -		case 12: -			sbc_cap->block_length = A2DP_BLOCK_LENGTH_12; -			break; -		case 8: -			sbc_cap->block_length = A2DP_BLOCK_LENGTH_8; -			break; -		case 4: -			sbc_cap->block_length = A2DP_BLOCK_LENGTH_4; -			break; -		default: -			return -EINVAL; -		} -	} else +	switch (sbc->blocks) { +	case 16:  		sbc_cap->block_length = A2DP_BLOCK_LENGTH_16; +		break; +	case 12: +		sbc_cap->block_length = A2DP_BLOCK_LENGTH_12; +		break; +	case 8: +		sbc_cap->block_length = A2DP_BLOCK_LENGTH_8; +		break; +	case 4: +		sbc_cap->block_length = A2DP_BLOCK_LENGTH_4; +		break; +	default: +		sbc_cap->block_length = A2DP_BLOCK_LENGTH_16; +		break; +	}  	if (sbc->bitpool > 250)  		return -EINVAL;  	else if (sbc->bitpool > 0)  		sbc_cap->min_bitpool = sbc_cap->max_bitpool = sbc->bitpool;  	else -		sbc_cap->min_bitpool = 53; +		sbc_cap->min_bitpool = sbc_cap->max_bitpool = 53;  	return 0;  } | 
