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

📄 forte.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (!rd)			return -EINVAL;		spin_lock_irq (&chip->lock);		if (chip->rec.active) 			cinfo.ptr = chip->rec.hwptr;		else			cinfo.ptr = 0;		cinfo.bytes = chip->rec.bytes;		cinfo.blocks = chip->rec.nr_irqs;		chip->rec.nr_irqs = 0;		spin_unlock_irq (&chip->lock);		return copy_to_user (argp, &cinfo, sizeof (cinfo)) ? -EFAULT : 0;        case SNDCTL_DSP_GETOSPACE:		if (!wr)			return -EINVAL;				spin_lock_irq (&chip->lock);		abi.fragstotal = chip->play.frag_num;		abi.fragsize = chip->play.frag_sz;		if (chip->play.mapped) {			abi.fragments = chip->play.frag_num - 2;			abi.bytes = chip->play.buf_sz;		}		else {			abi.fragments = chip->play.frag_num - 				chip->play.filled_frags;			if (chip->play.residue)				abi.fragments--;			abi.bytes = abi.fragments * abi.fragsize +				chip->play.residue;		}		spin_unlock_irq (&chip->lock);				return copy_to_user (argp, &abi, sizeof (abi)) ? -EFAULT : 0;	case SNDCTL_DSP_GETOPTR:		if (!wr)			return -EINVAL;		spin_lock_irq (&chip->lock);		if (chip->play.active) 			cinfo.ptr = chip->play.hwptr;		else			cinfo.ptr = 0;		cinfo.bytes = chip->play.bytes;		cinfo.blocks = chip->play.nr_irqs;		chip->play.nr_irqs = 0;		spin_unlock_irq (&chip->lock);		return copy_to_user (argp, &cinfo, sizeof (cinfo)) ? -EFAULT : 0;	case SNDCTL_DSP_GETODELAY:		if (!wr)			return -EINVAL;		spin_lock_irq (&chip->lock);		if (!chip->play.active) {			ival = 0;		}		else if (chip->play.mapped) {			count = inw (chip->play.iobase + FORTE_PLY_COUNT) + 1;			ival = chip->play.frag_sz - count;		}		else {			ival = chip->play.filled_frags * chip->play.frag_sz;			if (chip->play.residue)				ival += chip->play.frag_sz - chip->play.residue;		}		spin_unlock_irq (&chip->lock);		return put_user (ival, p);	case SNDCTL_DSP_SETDUPLEX:		DPRINTK ("%s: SETDUPLEX\n", __FUNCTION__);		return -EINVAL;	case SNDCTL_DSP_GETTRIGGER:		DPRINTK ("%s: GETTRIGGER\n", __FUNCTION__);				return put_user (chip->trigger, p);			case SNDCTL_DSP_SETTRIGGER:		if (get_user (ival, p))			return -EFAULT;		DPRINTK ("%s: SETTRIGGER %d\n", __FUNCTION__, ival);		if (wr) {			spin_lock_irq (&chip->lock);			if (ival & PCM_ENABLE_OUTPUT)				forte_channel_start (&chip->play);			else {						chip->trigger = 1;				forte_channel_prep (&chip->play);				forte_channel_stop (&chip->play);			}			spin_unlock_irq (&chip->lock);		}		else if (rd) {			spin_lock_irq (&chip->lock);			if (ival & PCM_ENABLE_INPUT)				forte_channel_start (&chip->rec);			else {						chip->trigger = 1;				forte_channel_prep (&chip->rec);				forte_channel_stop (&chip->rec);			}			spin_unlock_irq (&chip->lock);		}		return 0;			case SOUND_PCM_READ_RATE:		DPRINTK ("%s: PCM_READ_RATE\n", __FUNCTION__);				return put_user (chip->play.rate, p);	case SOUND_PCM_READ_CHANNELS:		DPRINTK ("%s: PCM_READ_CHANNELS\n", __FUNCTION__);		return put_user (chip->play.stereo, p);	case SOUND_PCM_READ_BITS:		DPRINTK ("%s: PCM_READ_BITS\n", __FUNCTION__);				return put_user (chip->play.format, p);	case SNDCTL_DSP_NONBLOCK:		DPRINTK ("%s: DSP_NONBLOCK\n", __FUNCTION__);		                file->f_flags |= O_NONBLOCK;		return 0;	default:		DPRINTK ("Unsupported ioctl: %x (%p)\n", cmd, argp);		break;	}	return -EINVAL;}/** * forte_dsp_open: */static int forte_dsp_open (struct inode *inode, struct file *file){	struct forte_chip *chip = forte; /* FIXME: HACK FROM HELL! */	if (file->f_flags & O_NONBLOCK) {		if (down_trylock (&chip->open_sem)) {			DPRINTK ("%s: returning -EAGAIN\n", __FUNCTION__);			return -EAGAIN;		}	}	else {		if (down_interruptible (&chip->open_sem)) {			DPRINTK ("%s: returning -ERESTARTSYS\n", __FUNCTION__);			return -ERESTARTSYS;		}	}	file->private_data = forte;	DPRINTK ("%s: dsp opened by %d\n", __FUNCTION__, current->pid);	if (file->f_mode & FMODE_WRITE)		forte_channel_init (forte, &forte->play);	if (file->f_mode & FMODE_READ)		forte_channel_init (forte, &forte->rec);	return nonseekable_open(inode, file);}/** * forte_dsp_release: */static int forte_dsp_release (struct inode *inode, struct file *file){	struct forte_chip *chip = file->private_data;	int ret = 0;	DPRINTK ("%s: chip @ %p\n", __FUNCTION__, chip);	if (file->f_mode & FMODE_WRITE) {		forte_channel_drain (&chip->play);		spin_lock_irq (&chip->lock); 		forte_channel_free (chip, &chip->play);		spin_unlock_irq (&chip->lock);        }	if (file->f_mode & FMODE_READ) {		while (chip->rec.filled_frags > 0)			interruptible_sleep_on (&chip->rec.wait);		spin_lock_irq (&chip->lock);		forte_channel_stop (&chip->rec);		forte_channel_free (chip, &chip->rec);		spin_unlock_irq (&chip->lock);	}	up (&chip->open_sem);	return ret;}/** * forte_dsp_poll: * */static unsigned int forte_dsp_poll (struct file *file, struct poll_table_struct *wait){	struct forte_chip *chip;	struct forte_channel *channel;	unsigned int mask = 0;	chip = file->private_data;	if (file->f_mode & FMODE_WRITE) {		channel = &chip->play;		if (channel->active)			poll_wait (file, &channel->wait, wait);		spin_lock_irq (&chip->lock);		if (channel->frag_num - channel->filled_frags > 0)			mask |= POLLOUT | POLLWRNORM;		spin_unlock_irq (&chip->lock);	}	if (file->f_mode & FMODE_READ) {		channel = &chip->rec;		if (channel->active)			poll_wait (file, &channel->wait, wait);		spin_lock_irq (&chip->lock);		if (channel->filled_frags > 0)			mask |= POLLIN | POLLRDNORM;		spin_unlock_irq (&chip->lock);	}	return mask;}/** * forte_dsp_mmap: */static intforte_dsp_mmap (struct file *file, struct vm_area_struct *vma){	struct forte_chip *chip;	struct forte_channel *channel;	unsigned long size;	int ret;	chip = file->private_data;	DPRINTK ("%s: start %lXh, size %ld, pgoff %ld\n", __FUNCTION__,                 vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_pgoff);	spin_lock_irq (&chip->lock);	if (vma->vm_flags & VM_WRITE && chip->play.active) {		ret = -EBUSY;		goto out;	}        if (vma->vm_flags & VM_READ && chip->rec.active) {		ret = -EBUSY;		goto out;        }	if (file->f_mode & FMODE_WRITE)		channel = &chip->play;	else if (file->f_mode & FMODE_READ)		channel = &chip->rec;	else {		ret = -EINVAL;		goto out;	}	forte_channel_prep (channel);	channel->mapped = 1;        if (vma->vm_pgoff != 0) {		ret = -EINVAL;                goto out;	}        size = vma->vm_end - vma->vm_start;        if (size > channel->buf_pages * PAGE_SIZE) {		DPRINTK ("%s: size (%ld) > buf_sz (%d) \n", __FUNCTION__,			 size, channel->buf_sz);		ret = -EINVAL;                goto out;	}        if (remap_page_range (vma, vma->vm_start, virt_to_phys (channel->buf),			      size, vma->vm_page_prot)) {		DPRINTK ("%s: remap el a no worko\n", __FUNCTION__);		ret = -EAGAIN;                goto out;	}        ret = 0; out:	spin_unlock_irq (&chip->lock);        return ret;}/** * forte_dsp_write: */static ssize_t forte_dsp_write (struct file *file, const char __user *buffer, size_t bytes, 		 loff_t *ppos){	struct forte_chip *chip;	struct forte_channel *channel;	unsigned int i = bytes, sz = 0;	unsigned long flags;	if (!access_ok (VERIFY_READ, buffer, bytes))		return -EFAULT;	chip = (struct forte_chip *) file->private_data;	if (!chip)		BUG();	channel = &chip->play;	if (!channel)		BUG();	spin_lock_irqsave (&chip->lock, flags);	/* Set up buffers with the right fragment size */	forte_channel_prep (channel);	while (i) {		/* All fragment buffers in use -> wait */		if (channel->frag_num - channel->filled_frags == 0) {			DECLARE_WAITQUEUE (wait, current);			/* For trigger or non-blocking operation, get out */			if (chip->trigger || file->f_flags & O_NONBLOCK) {				spin_unlock_irqrestore (&chip->lock, flags);				return -EAGAIN;			}			/* Otherwise wait for buffers */			add_wait_queue (&channel->wait, &wait);			for (;;) {				spin_unlock_irqrestore (&chip->lock, flags);				set_current_state (TASK_INTERRUPTIBLE);				schedule();				spin_lock_irqsave (&chip->lock, flags);				if (channel->frag_num - channel->filled_frags)					break;			}			remove_wait_queue (&channel->wait, &wait);			set_current_state (TASK_RUNNING);			if (signal_pending (current)) {				spin_unlock_irqrestore (&chip->lock, flags);				return -ERESTARTSYS;			}		}		if (channel->residue)			sz = channel->residue;		else if (i > channel->frag_sz)			sz = channel->frag_sz;		else			sz = i;		spin_unlock_irqrestore (&chip->lock, flags);		if (copy_from_user ((void *) channel->buf + channel->swptr, buffer, sz))			return -EFAULT;		spin_lock_irqsave (&chip->lock, flags);		/* Advance software pointer */		buffer += sz;		channel->swptr += sz;		channel->swptr %= channel->buf_sz;		i -= sz;		/* Only bump filled_frags if a full fragment has been written */		if (channel->swptr % channel->frag_sz == 0) {			channel->filled_frags++;			channel->residue = 0;		}		else			channel->residue = channel->frag_sz - sz;		/* If playback isn't active, start it */		if (channel->active == 0 && chip->trigger == 0)			forte_channel_start (channel);	}	spin_unlock_irqrestore (&chip->lock, flags);	return bytes - i;}/** * forte_dsp_read: */static ssize_t forte_dsp_read (struct file *file, char __user *buffer, size_t bytes, 		loff_t *ppos){	struct forte_chip *chip;	struct forte_channel *channel;	unsigned int i = bytes, sz;	unsigned long flags;	if (!access_ok (VERIFY_WRITE, buffer, bytes))		return -EFAULT;	chip = (struct forte_chip *) file->private_data;	if (!chip)		BUG();	channel = &chip->rec;	if (!channel)		BUG();	spin_lock_irqsave (&chip->lock, flags);	/* Set up buffers with the right fragment size */	forte_channel_prep (channel);	/* Start recording */	if (!chip->trigger)		forte_channel_start (channel);	while (i) {		/* No fragment buffers in use -> wait */		if (channel->filled_frags == 0) {			DECLARE_WAITQUEUE (wait, current);			/* For trigger mode operation, get out */			if (chip->trigger) {				spin_unlock_irqrestore (&chip->lock, flags);				return -EAGAIN;			}			add_wait_queue (&channel->wait, &wait);			for (;;) {				if (channel->active == 0)					break;				if (channel->filled_frags)					break;										spin_unlock_irqrestore (&chip->lock, flags);				set_current_state (TASK_INTERRUPTIBLE);				schedule();				spin_lock_irqsave (&chip->lock, flags);			}			set_current_state (TASK_RUNNING);			remove_wait_queue (&channel->wait, &wait);		}		if (i > channel->frag_sz)			sz = channel->frag_sz;		else			sz = i;		spin_unlock_irqrestore (&chip->lock, flags);		if (copy_to_user (buffer, (void *)channel->buf+channel->swptr, sz)) {			DPRINTK ("%s: copy_to_user failed\n", __FUNCTION__);			return -EFAULT;

⌨️ 快捷键说明

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