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

📄 pcm_oss.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		frames = bytes_to_frames(runtime, bytes);		frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel);		if (frames1 <= 0)			return frames1;		bytes = frames_to_bytes(runtime, frames1);	}	return bytes;}static ssize_t snd_pcm_oss_read1(snd_pcm_substream_t *substream, char __user *buf, size_t bytes){	size_t xfer = 0;	ssize_t tmp;	snd_pcm_runtime_t *runtime = substream->runtime;	if (atomic_read(&runtime->mmap_count))		return -ENXIO;	if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)		return tmp;	while (bytes > 0) {		if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {			if (runtime->oss.buffer_used == 0) {				tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);				if (tmp <= 0)					return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;				runtime->oss.bytes += tmp;				runtime->oss.period_ptr = tmp;				runtime->oss.buffer_used = tmp;			}			tmp = bytes;			if ((size_t) tmp > runtime->oss.buffer_used)				tmp = runtime->oss.buffer_used;			if (copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_ptr - runtime->oss.buffer_used), tmp))				return xfer > 0 ? (snd_pcm_sframes_t)xfer : -EFAULT;			buf += tmp;			bytes -= tmp;			xfer += tmp;			runtime->oss.buffer_used -= tmp;		} else {			tmp = snd_pcm_oss_read2(substream, (char __force *)buf,						runtime->oss.period_bytes, 0);			if (tmp <= 0)				return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;			runtime->oss.bytes += tmp;			buf += tmp;			bytes -= tmp;			xfer += tmp;		}	}	return xfer;}static int snd_pcm_oss_reset(snd_pcm_oss_file_t *pcm_oss_file){	snd_pcm_substream_t *substream;	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];	if (substream != NULL) {		snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);		substream->runtime->oss.prepare = 1;	}	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];	if (substream != NULL) {		snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);		substream->runtime->oss.prepare = 1;	}	return 0;}static int snd_pcm_oss_post(snd_pcm_oss_file_t *pcm_oss_file){	snd_pcm_substream_t *substream;	int err;	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];	if (substream != NULL) {		if ((err = snd_pcm_oss_make_ready(substream)) < 0)			return err;		snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);	}	/* note: all errors from the start action are ignored */	/* OSS apps do not know, how to handle them */	return 0;}static int snd_pcm_oss_sync1(snd_pcm_substream_t *substream, size_t size){	snd_pcm_runtime_t *runtime;	ssize_t result = 0;	long res;	wait_queue_t wait;	runtime = substream->runtime;	init_waitqueue_entry(&wait, current);	add_wait_queue(&runtime->sleep, &wait);#ifdef OSS_DEBUG	printk("sync1: size = %li\n", size);#endif	while (1) {		result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1);		if (result > 0) {			runtime->oss.buffer_used = 0;			result = 0;			break;		}		if (result != 0 && result != -EAGAIN)			break;		result = 0;		set_current_state(TASK_INTERRUPTIBLE);		snd_pcm_stream_lock_irq(substream);		res = runtime->status->state;		snd_pcm_stream_unlock_irq(substream);		if (res != SNDRV_PCM_STATE_RUNNING) {			set_current_state(TASK_RUNNING);			break;		}		res = schedule_timeout(10 * HZ);		if (signal_pending(current)) {			result = -ERESTARTSYS;			break;		}		if (res == 0) {			snd_printk(KERN_ERR "OSS sync error - DMA timeout\n");			result = -EIO;			break;		}	}	remove_wait_queue(&runtime->sleep, &wait);	return result;}static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file){	int err = 0;	unsigned int saved_f_flags;	snd_pcm_substream_t *substream;	snd_pcm_runtime_t *runtime;	snd_pcm_format_t format;	unsigned long width;	size_t size;	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];	if (substream != NULL) {		runtime = substream->runtime;		if (atomic_read(&runtime->mmap_count))			goto __direct;		if ((err = snd_pcm_oss_make_ready(substream)) < 0)			return err;		format = snd_pcm_oss_format_from(runtime->oss.format);		width = snd_pcm_format_physical_width(format);		if (runtime->oss.buffer_used > 0) {#ifdef OSS_DEBUG			printk("sync: buffer_used\n");#endif			size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width;			snd_pcm_format_set_silence(format,						   runtime->oss.buffer + runtime->oss.buffer_used,						   size);			err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes);			if (err < 0)				return err;		} else if (runtime->oss.period_ptr > 0) {#ifdef OSS_DEBUG			printk("sync: period_ptr\n");#endif			size = runtime->oss.period_bytes - runtime->oss.period_ptr;			snd_pcm_format_set_silence(format,						   runtime->oss.buffer,						   size * 8 / width);			err = snd_pcm_oss_sync1(substream, size);			if (err < 0)				return err;		}		/*		 * The ALSA's period might be a bit large than OSS one.		 * Fill the remain portion of ALSA period with zeros.		 */		size = runtime->control->appl_ptr % runtime->period_size;		if (size > 0) {			size = runtime->period_size - size;			if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {				size = (runtime->frame_bits * size) / 8;				while (size > 0) {					mm_segment_t fs;					size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;					size -= size1;					size1 *= 8;					size1 /= runtime->sample_bits;					snd_pcm_format_set_silence(runtime->format,								   runtime->oss.buffer,								   size1);					fs = snd_enter_user();					snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1);					snd_leave_user(fs);				}			} else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {				void __user *buffers[runtime->channels];				memset(buffers, 0, runtime->channels * sizeof(void *));				snd_pcm_lib_writev(substream, buffers, size);			}		}		/*		 * finish sync: drain the buffer		 */	      __direct:		saved_f_flags = substream->ffile->f_flags;		substream->ffile->f_flags &= ~O_NONBLOCK;		err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);		substream->ffile->f_flags = saved_f_flags;		if (err < 0)			return err;		runtime->oss.prepare = 1;	}	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];	if (substream != NULL) {		if ((err = snd_pcm_oss_make_ready(substream)) < 0)			return err;		runtime = substream->runtime;		err = snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);		if (err < 0)			return err;		runtime->oss.buffer_used = 0;		runtime->oss.prepare = 1;	}	return 0;}static int snd_pcm_oss_set_rate(snd_pcm_oss_file_t *pcm_oss_file, int rate){	int idx;	for (idx = 1; idx >= 0; --idx) {		snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];		snd_pcm_runtime_t *runtime;		if (substream == NULL)			continue;		runtime = substream->runtime;		if (rate < 1000)			rate = 1000;		else if (rate > 192000)			rate = 192000;		if (runtime->oss.rate != rate) {			runtime->oss.params = 1;			runtime->oss.rate = rate;		}	}	return snd_pcm_oss_get_rate(pcm_oss_file);}static int snd_pcm_oss_get_rate(snd_pcm_oss_file_t *pcm_oss_file){	snd_pcm_substream_t *substream;	int err;		if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)		return err;	return substream->runtime->oss.rate;}static int snd_pcm_oss_set_channels(snd_pcm_oss_file_t *pcm_oss_file, unsigned int channels){	int idx;	if (channels < 1)		channels = 1;	if (channels > 128)		return -EINVAL;	for (idx = 1; idx >= 0; --idx) {		snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];		snd_pcm_runtime_t *runtime;		if (substream == NULL)			continue;		runtime = substream->runtime;		if (runtime->oss.channels != channels) {			runtime->oss.params = 1;			runtime->oss.channels = channels;		}	}	return snd_pcm_oss_get_channels(pcm_oss_file);}static int snd_pcm_oss_get_channels(snd_pcm_oss_file_t *pcm_oss_file){	snd_pcm_substream_t *substream;	int err;		if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)		return err;	return substream->runtime->oss.channels;}static int snd_pcm_oss_get_block_size(snd_pcm_oss_file_t *pcm_oss_file){	snd_pcm_substream_t *substream;	int err;		if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)		return err;	return substream->runtime->oss.period_bytes;}static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file){	snd_pcm_substream_t *substream;	int err;	int direct;	snd_pcm_hw_params_t *params;	unsigned int formats = 0;	snd_mask_t format_mask;	int fmt;	if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)		return err;	if (atomic_read(&substream->runtime->mmap_count)) {		direct = 1;	} else {		snd_pcm_oss_setup_t *setup = substream->oss.setup;		direct = (setup != NULL && setup->direct);	}	if (!direct)		return AFMT_MU_LAW | AFMT_U8 |		       AFMT_S16_LE | AFMT_S16_BE |		       AFMT_S8 | AFMT_U16_LE |		       AFMT_U16_BE;	params = kmalloc(sizeof(*params), GFP_KERNEL);	if (!params)		return -ENOMEM;	_snd_pcm_hw_params_any(params);	err = snd_pcm_hw_refine(substream, params);	format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 	kfree(params);	snd_assert(err >= 0, return err);	for (fmt = 0; fmt < 32; ++fmt) {		if (snd_mask_test(&format_mask, fmt)) {			int f = snd_pcm_oss_format_to(fmt);			if (f >= 0)				formats |= f;		}	}	return formats;}static int snd_pcm_oss_set_format(snd_pcm_oss_file_t *pcm_oss_file, int format){	int formats, idx;		if (format != AFMT_QUERY) {		formats = snd_pcm_oss_get_formats(pcm_oss_file);		if (!(formats & format))			format = AFMT_U8;		for (idx = 1; idx >= 0; --idx) {			snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];			snd_pcm_runtime_t *runtime;			if (substream == NULL)				continue;			runtime = substream->runtime;			if (runtime->oss.format != format) {				runtime->oss.params = 1;				runtime->oss.format = format;			}		}	}	return snd_pcm_oss_get_format(pcm_oss_file);}static int snd_pcm_oss_get_format(snd_pcm_oss_file_t *pcm_oss_file){	snd_pcm_substream_t *substream;	int err;		if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)		return err;	return substream->runtime->oss.format;}static int snd_pcm_oss_set_subdivide1(snd_pcm_substream_t *substream, int subdivide){	snd_pcm_runtime_t *runtime;	if (substream == NULL)		return 0;	runtime = substream->runtime;	if (subdivide == 0) {		subdivide = runtime->oss.subdivision;		if (subdivide == 0)			subdivide = 1;		return subdivide;	}	if (runtime->oss.subdivision || runtime->oss.fragshift)		return -EINVAL;	if (subdivide != 1 && subdivide != 2 && subdivide != 4 &&	    subdivide != 8 && subdivide != 16)		return -EINVAL;	runtime->oss.subdivision = subdivide;	runtime->oss.params = 1;	return subdivide;}static int snd_pcm_oss_set_subdivide(snd_pcm_oss_file_t *pcm_oss_file, int subdivide){	int err = -EINVAL, idx;	for (idx = 1; idx >= 0; --idx) {		snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];		if (substream == NULL)			continue;		if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0)			return err;	}	return err;}static int snd_pcm_oss_set_fragment1(snd_pcm_substream_t *substream, unsigned int val){	snd_pcm_runtime_t *runtime;	if (substream == NULL)		return 0;	runtime = substream->runtime;	if (runtime->oss.subdivision || runtime->oss.fragshift)		return -EINVAL;	runtime->oss.fragshift = val & 0xffff;	runtime->oss.maxfrags = (val >> 16) & 0xffff;	if (runtime->oss.fragshift < 4)		/* < 16 */		runtime->oss.fragshift = 4;	if (runtime->oss.maxfrags < 2)		runtime->oss.maxfrags = 2;	runtime->oss.params = 1;	return 0;}static int snd_pcm_oss_set_fragment(snd_pcm_oss_file_t *pcm_oss_file, unsigned int val){	int err = -EINVAL, idx;	for (idx = 1; idx >= 0; --idx) {		snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];		if (substream == NULL)			continue;		if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0)			return err;	}	return err;}

⌨️ 快捷键说明

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