⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcm_bluetooth.c

📁 实现bluez蓝牙profile需要的库
💻 C
📖 第 1 页 / 共 3 页
字号:
					struct pollfd *pfd, unsigned int space){	struct bluetooth_data *data = io->private_data;	assert(io);	if (space < 1)		return 0;	pfd[0].fd = data->stream.fd;	pfd[0].events = POLLIN;	pfd[0].revents = 0;	return 1;}static int bluetooth_poll_revents(snd_pcm_ioplug_t *io ATTRIBUTE_UNUSED,					struct pollfd *pfds, unsigned int nfds,							unsigned short *revents){	assert(pfds && nfds == 1 && revents);	*revents = pfds[0].revents;	return 0;}static int bluetooth_playback_poll_descriptors(snd_pcm_ioplug_t *io,					struct pollfd *pfd, unsigned int space){	struct bluetooth_data *data = io->private_data;	DBG("");	assert(data->pipefd[0] >= 0);	if (space < 1)		return 0;	pfd[0].fd = data->pipefd[0];	pfd[0].events = POLLIN;	pfd[0].revents = 0;	return 1;}static int bluetooth_playback_poll_revents(snd_pcm_ioplug_t *io,					struct pollfd *pfds, unsigned int nfds,							unsigned short *revents){	static char buf[1];	int ret;	DBG("");	assert(pfds);	assert(nfds == 1);	assert(revents);	assert(pfds[0].fd >= 0);	if (io->state != SND_PCM_STATE_PREPARED)		ret = read(pfds[0].fd, buf, 1);	*revents = (pfds[0].revents & ~POLLIN) | POLLOUT;	return 0;}static snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io,				const snd_pcm_channel_area_t *areas,				snd_pcm_uframes_t offset, snd_pcm_uframes_t size){	struct bluetooth_data *data = io->private_data;	struct ipc_data_cfg cfg = data->cfg;	snd_pcm_uframes_t frames_to_write, ret;	unsigned char *buff;	int nrecv, frame_size = 0;	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu io->nonblock=%u",			areas->step, areas->first, offset, size, io->nonblock);	if (data->count > 0)		goto proceed;	frame_size = areas->step / 8;	nrecv = recv(data->stream.fd, data->buffer, cfg.pkt_len,			MSG_WAITALL | (io->nonblock ? MSG_DONTWAIT : 0));	if (nrecv < 0) {		ret = (errno == EPIPE) ? -EIO : -errno;		goto done;	}	if (nrecv != cfg.pkt_len) {		ret = -EIO;		SNDERR(strerror(-ret));		goto done;	}	/* Increment hardware transmition pointer */	data->hw_ptr = (data->hw_ptr + cfg.pkt_len / cfg.sample_size) %								io->buffer_size;proceed:	buff = (unsigned char *) areas->addr +			(areas->first + areas->step * offset) / 8;	if ((data->count + size * frame_size) <= cfg.pkt_len)		frames_to_write = size;	else		frames_to_write = (cfg.pkt_len - data->count) / frame_size;	memcpy(buff, data->buffer + data->count, frame_size * frames_to_write);	data->count += (frame_size * frames_to_write);	data->count %= cfg.pkt_len;	/* Return written frames count */	ret = frames_to_write;done:	DBG("returning %lu", ret);	return ret;}static snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io,				const snd_pcm_channel_area_t *areas,				snd_pcm_uframes_t offset, snd_pcm_uframes_t size){	struct bluetooth_data *data = io->private_data;	struct ipc_data_cfg cfg = data->cfg;	snd_pcm_sframes_t ret = 0;	snd_pcm_uframes_t frames_to_read;	uint8_t *buff;	int rsend, frame_size;	DBG("areas->step=%u areas->first=%u offset=%lu, size=%lu io->nonblock=%u",			areas->step, areas->first, offset, size, io->nonblock);	if (io->hw_ptr > io->appl_ptr) {		ret = bluetooth_playback_stop(io);		if (ret == 0)			ret = -EPIPE;		goto done;	}	frame_size = areas->step / 8;	if ((data->count + size * frame_size) <= cfg.pkt_len)		frames_to_read = size;	else		frames_to_read = (cfg.pkt_len - data->count) / frame_size;	DBG("count=%d frames_to_read=%lu", data->count, frames_to_read);	/* Ready for more data */	buff = (uint8_t *) areas->addr +			(areas->first + areas->step * offset) / 8;	memcpy(data->buffer + data->count, buff, frame_size * frames_to_read);	/* Remember we have some frames in the pipe now */	data->count += frames_to_read * frame_size;	if (data->count != cfg.pkt_len) {		ret = frames_to_read;		goto done;	}	rsend = send(data->stream.fd, data->buffer, cfg.pkt_len,			io->nonblock ? MSG_DONTWAIT : 0);	if (rsend > 0) {		/* Reset count pointer */		data->count = 0;		ret = frames_to_read;	} else if (rsend < 0)		ret = (errno == EPIPE) ? -EIO : -errno;	else		ret = -EIO;done:	DBG("returning %ld", ret);	return ret;}static snd_pcm_sframes_t bluetooth_a2dp_read(snd_pcm_ioplug_t *io,				const snd_pcm_channel_area_t *areas,				snd_pcm_uframes_t offset, snd_pcm_uframes_t size){	snd_pcm_uframes_t ret = 0;	return ret;}static int avdtp_write(struct bluetooth_data *data){	int ret = 0;	struct rtp_header *header;	struct rtp_payload *payload;	struct bluetooth_a2dp *a2dp = &data->a2dp;	header = (void *) a2dp->buffer;	payload = (void *) (a2dp->buffer + sizeof(*header));	memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));	payload->frame_count = a2dp->frame_count;	header->v = 2;	header->pt = 1;	header->sequence_number = htons(a2dp->seq_num);	header->timestamp = htonl(a2dp->nsamples);	header->ssrc = htonl(1);	ret = send(data->stream.fd, a2dp->buffer, a2dp->count, MSG_DONTWAIT);	if (ret == -1)		ret = -errno;	/* Reset buffer of data to send */	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);	a2dp->frame_count = 0;	a2dp->samples = 0;	a2dp->seq_num++;	return ret;}static snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io,				const snd_pcm_channel_area_t *areas,				snd_pcm_uframes_t offset, snd_pcm_uframes_t size){	struct bluetooth_data *data = io->private_data;	struct bluetooth_a2dp *a2dp = &data->a2dp;	snd_pcm_sframes_t ret = 0;	snd_pcm_uframes_t frames_to_read;	int frame_size, encoded;	uint8_t *buff;	DBG("areas->step=%u areas->first=%u offset=%lu size=%lu",				areas->step, areas->first, offset, size);	DBG("hw_ptr=%lu appl_ptr=%lu", io->hw_ptr, io->appl_ptr);	if (io->hw_ptr > io->appl_ptr) {		ret = bluetooth_playback_stop(io);		if (ret == 0)			ret = -EPIPE;		goto done;	}	/* Check if we should autostart */	if (io->state == SND_PCM_STATE_PREPARED) {		snd_pcm_sw_params_t *swparams;		snd_pcm_uframes_t threshold;		snd_pcm_sw_params_malloc(&swparams);		if (!snd_pcm_sw_params_current(io->pcm, swparams) &&				!snd_pcm_sw_params_get_start_threshold(swparams, &threshold)) {			if (io->appl_ptr >= threshold) {				ret = snd_pcm_start(io->pcm);				if (ret != 0)					goto done;			}		}		snd_pcm_sw_params_free(swparams);	}	frame_size = areas->step / 8;	if ((data->count + size * frame_size) <= a2dp->codesize)		frames_to_read = size;	else		frames_to_read = (a2dp->codesize - data->count) / frame_size;	DBG("count=%d frames_to_read=%lu", data->count, frames_to_read);	DBG("a2dp.count=%d cfg.pkt_len=%d", a2dp->count, data->cfg.pkt_len);	/* FIXME: If state is not streaming then return */	/* Ready for more data */	buff = (uint8_t *) areas->addr +				(areas->first + areas->step * offset) / 8;	memcpy(data->buffer + data->count, buff, frame_size * frames_to_read);	/* Remember we have some frames in the pipe now */	data->count += frames_to_read * frame_size;	if (data->count != a2dp->codesize) {		ret = frames_to_read;		goto done;	}	/* Enough data to encode (sbc wants 1k blocks) */	encoded = sbc_encode(&(a2dp->sbc), data->buffer, a2dp->codesize);	if (encoded <= 0) {		DBG("Encoding error %d", encoded);		goto done;	}	data->count -= encoded;	DBG("encoded=%d  a2dp.sbc.len=%d", encoded, a2dp->sbc.len);	if (a2dp->count + a2dp->sbc.len >= data->cfg.pkt_len) {		ret = avdtp_write(data);		if (ret < 0) {			if (-ret == EPIPE)				ret = -EIO;			goto done;		}	}	memcpy(a2dp->buffer + a2dp->count, a2dp->sbc.data, a2dp->sbc.len);	a2dp->count += a2dp->sbc.len;	a2dp->frame_count++;	a2dp->samples += encoded / frame_size;	a2dp->nsamples += encoded / frame_size;	ret = frames_to_read;done:	DBG("returning %ld", ret);	return ret;}static snd_pcm_ioplug_callback_t bluetooth_hsp_playback = {	.start			= bluetooth_playback_start,	.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,	.poll_revents		= bluetooth_playback_poll_revents,};static snd_pcm_ioplug_callback_t bluetooth_hsp_capture = {	.start			= bluetooth_start,	.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,	.poll_revents		= bluetooth_poll_revents,};static snd_pcm_ioplug_callback_t bluetooth_a2dp_playback = {	.start			= bluetooth_playback_start,	.stop			= bluetooth_playback_stop,	.pointer		= bluetooth_pointer,	.close			= bluetooth_close,	.hw_params		= bluetooth_a2dp_hw_params,	.prepare		= bluetooth_prepare,	.transfer		= bluetooth_a2dp_write,	.poll_descriptors	= bluetooth_playback_poll_descriptors,	.poll_revents		= bluetooth_playback_poll_revents,};static snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = {	.start			= bluetooth_start,	.stop			= bluetooth_stop,	.pointer		= bluetooth_pointer,	.close			= bluetooth_close,	.hw_params		= bluetooth_a2dp_hw_params,	.prepare		= bluetooth_prepare,	.transfer		= bluetooth_a2dp_read,	.poll_descriptors	= bluetooth_poll_descriptors,	.poll_revents		= bluetooth_poll_revents,};#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0]))static int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io){	struct bluetooth_data *data = io->private_data;	struct ipc_data_cfg cfg = data->cfg;	snd_pcm_access_t access_list[] = {		SND_PCM_ACCESS_RW_INTERLEAVED,		/* Mmap access is really useless fo this driver, but we		 * support it because some pieces of software out there		 * insist on using it */		SND_PCM_ACCESS_MMAP_INTERLEAVED	};	unsigned int format_list[] = {		SND_PCM_FORMAT_S16_LE	};	int err, channels;	/* access type */	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,					ARRAY_NELEMS(access_list), access_list);	if (err < 0)		return err;	/* supported formats */	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,					ARRAY_NELEMS(format_list), format_list);	if (err < 0)		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,							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);	if (err < 0)		return err;	/* supported block size */	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,						cfg.pkt_len, cfg.pkt_len);	if (err < 0)		return err;	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS,									2, 200);	if (err < 0)		return err;	return 0;}static int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io){	struct bluetooth_data *data = io->private_data;	struct bluetooth_a2dp *a2dp = &data->a2dp;	struct ipc_data_cfg cfg = data->cfg;	snd_pcm_access_t access_list[] = {		SND_PCM_ACCESS_RW_INTERLEAVED,		/* Mmap access is really useless fo this driver, but we		 * support it because some pieces of software out there		 * insist on using it */		SND_PCM_ACCESS_MMAP_INTERLEAVED	};	unsigned int format_list[] = {		SND_PCM_FORMAT_S16_LE	};	int err, channels;	/* access type */	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,					ARRAY_NELEMS(access_list), access_list);	if (err < 0)		return err;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -