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

📄 rawmidi.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	return -ENOIOCTLCMD;}/** * snd_rawmidi_receive - receive the input data from the device * @substream: the rawmidi substream * @buffer: the buffer pointer * @count: the data size to read * * Reads the data from the internal buffer. * * Returns the size of read data, or a negative error code on failure. */int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,			const unsigned char *buffer, int count){	unsigned long flags;	int result = 0, count1;	struct snd_rawmidi_runtime *runtime = substream->runtime;	if (runtime->buffer == NULL) {		snd_printd("snd_rawmidi_receive: input is not active!!!\n");		return -EINVAL;	}	spin_lock_irqsave(&runtime->lock, flags);	if (count == 1) {	/* special case, faster code */		substream->bytes++;		if (runtime->avail < runtime->buffer_size) {			runtime->buffer[runtime->hw_ptr++] = buffer[0];			runtime->hw_ptr %= runtime->buffer_size;			runtime->avail++;			result++;		} else {			runtime->xruns++;		}	} else {		substream->bytes += count;		count1 = runtime->buffer_size - runtime->hw_ptr;		if (count1 > count)			count1 = count;		if (count1 > (int)(runtime->buffer_size - runtime->avail))			count1 = runtime->buffer_size - runtime->avail;		memcpy(runtime->buffer + runtime->hw_ptr, buffer, count1);		runtime->hw_ptr += count1;		runtime->hw_ptr %= runtime->buffer_size;		runtime->avail += count1;		count -= count1;		result += count1;		if (count > 0) {			buffer += count1;			count1 = count;			if (count1 > (int)(runtime->buffer_size - runtime->avail)) {				count1 = runtime->buffer_size - runtime->avail;				runtime->xruns += count - count1;			}			if (count1 > 0) {				memcpy(runtime->buffer, buffer, count1);				runtime->hw_ptr = count1;				runtime->avail += count1;				result += count1;			}		}	}	if (result > 0) {		if (runtime->event)			tasklet_hi_schedule(&runtime->tasklet);		else if (snd_rawmidi_ready(substream))			wake_up(&runtime->sleep);	}	spin_unlock_irqrestore(&runtime->lock, flags);	return result;}static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,				     unsigned char *buf, long count, int kernel){	unsigned long flags;	long result = 0, count1;	struct snd_rawmidi_runtime *runtime = substream->runtime;	while (count > 0 && runtime->avail) {		count1 = runtime->buffer_size - runtime->appl_ptr;		if (count1 > count)			count1 = count;		spin_lock_irqsave(&runtime->lock, flags);		if (count1 > (int)runtime->avail)			count1 = runtime->avail;		if (kernel) {			memcpy(buf + result, runtime->buffer + runtime->appl_ptr, count1);		} else {			spin_unlock_irqrestore(&runtime->lock, flags);			if (copy_to_user((char __user *)buf + result,					 runtime->buffer + runtime->appl_ptr, count1)) {				return result > 0 ? result : -EFAULT;			}			spin_lock_irqsave(&runtime->lock, flags);		}		runtime->appl_ptr += count1;		runtime->appl_ptr %= runtime->buffer_size;		runtime->avail -= count1;		spin_unlock_irqrestore(&runtime->lock, flags);		result += count1;		count -= count1;	}	return result;}long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream,			     unsigned char *buf, long count){	snd_rawmidi_input_trigger(substream, 1);	return snd_rawmidi_kernel_read1(substream, buf, count, 1);}static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t count,				loff_t *offset){	long result;	int count1;	struct snd_rawmidi_file *rfile;	struct snd_rawmidi_substream *substream;	struct snd_rawmidi_runtime *runtime;	rfile = file->private_data;	substream = rfile->input;	if (substream == NULL)		return -EIO;	runtime = substream->runtime;	snd_rawmidi_input_trigger(substream, 1);	result = 0;	while (count > 0) {		spin_lock_irq(&runtime->lock);		while (!snd_rawmidi_ready(substream)) {			wait_queue_t wait;			if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {				spin_unlock_irq(&runtime->lock);				return result > 0 ? result : -EAGAIN;			}			init_waitqueue_entry(&wait, current);			add_wait_queue(&runtime->sleep, &wait);			set_current_state(TASK_INTERRUPTIBLE);			spin_unlock_irq(&runtime->lock);			schedule();			remove_wait_queue(&runtime->sleep, &wait);			if (signal_pending(current))				return result > 0 ? result : -ERESTARTSYS;			if (!runtime->avail)				return result > 0 ? result : -EIO;			spin_lock_irq(&runtime->lock);		}		spin_unlock_irq(&runtime->lock);		count1 = snd_rawmidi_kernel_read1(substream,						  (unsigned char __force *)buf,						  count, 0);		if (count1 < 0)			return result > 0 ? result : count1;		result += count1;		buf += count1;		count -= count1;	}	return result;}/** * snd_rawmidi_transmit_empty - check whether the output buffer is empty * @substream: the rawmidi substream *  * Returns 1 if the internal output buffer is empty, 0 if not. */int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream){	struct snd_rawmidi_runtime *runtime = substream->runtime;	int result;	unsigned long flags;	if (runtime->buffer == NULL) {		snd_printd("snd_rawmidi_transmit_empty: output is not active!!!\n");		return 1;	}	spin_lock_irqsave(&runtime->lock, flags);	result = runtime->avail >= runtime->buffer_size;	spin_unlock_irqrestore(&runtime->lock, flags);	return result;		}/** * snd_rawmidi_transmit_peek - copy data from the internal buffer * @substream: the rawmidi substream * @buffer: the buffer pointer * @count: data size to transfer * * Copies data from the internal output buffer to the given buffer. * * Call this in the interrupt handler when the midi output is ready, * and call snd_rawmidi_transmit_ack() after the transmission is * finished. * * Returns the size of copied data, or a negative error code on failure. */int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,			      unsigned char *buffer, int count){	unsigned long flags;	int result, count1;	struct snd_rawmidi_runtime *runtime = substream->runtime;	if (runtime->buffer == NULL) {		snd_printd("snd_rawmidi_transmit_peek: output is not active!!!\n");		return -EINVAL;	}	result = 0;	spin_lock_irqsave(&runtime->lock, flags);	if (runtime->avail >= runtime->buffer_size) {		/* warning: lowlevel layer MUST trigger down the hardware */		goto __skip;	}	if (count == 1) {	/* special case, faster code */		*buffer = runtime->buffer[runtime->hw_ptr];		result++;	} else {		count1 = runtime->buffer_size - runtime->hw_ptr;		if (count1 > count)			count1 = count;		if (count1 > (int)(runtime->buffer_size - runtime->avail))			count1 = runtime->buffer_size - runtime->avail;		memcpy(buffer, runtime->buffer + runtime->hw_ptr, count1);		count -= count1;		result += count1;		if (count > 0) {			if (count > (int)(runtime->buffer_size - runtime->avail - count1))				count = runtime->buffer_size - runtime->avail - count1;			memcpy(buffer + count1, runtime->buffer, count);			result += count;		}	}      __skip:	spin_unlock_irqrestore(&runtime->lock, flags);	return result;}/** * snd_rawmidi_transmit_ack - acknowledge the transmission * @substream: the rawmidi substream * @count: the tranferred count * * Advances the hardware pointer for the internal output buffer with * the given size and updates the condition. * Call after the transmission is finished. * * Returns the advanced size if successful, or a negative error code on failure. */int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count){	unsigned long flags;	struct snd_rawmidi_runtime *runtime = substream->runtime;	if (runtime->buffer == NULL) {		snd_printd("snd_rawmidi_transmit_ack: output is not active!!!\n");		return -EINVAL;	}	spin_lock_irqsave(&runtime->lock, flags);	snd_assert(runtime->avail + count <= runtime->buffer_size, );	runtime->hw_ptr += count;	runtime->hw_ptr %= runtime->buffer_size;	runtime->avail += count;	substream->bytes += count;	if (count > 0) {		if (runtime->drain || snd_rawmidi_ready(substream))			wake_up(&runtime->sleep);	}	spin_unlock_irqrestore(&runtime->lock, flags);	return count;}/** * snd_rawmidi_transmit - copy from the buffer to the device * @substream: the rawmidi substream * @buffer: the buffer pointer * @count: the data size to transfer *  * Copies data from the buffer to the device and advances the pointer. * * Returns the copied size if successful, or a negative error code on failure. */int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,			 unsigned char *buffer, int count){	count = snd_rawmidi_transmit_peek(substream, buffer, count);	if (count < 0)		return count;	return snd_rawmidi_transmit_ack(substream, count);}static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,				      const unsigned char *buf, long count, int kernel){	unsigned long flags;	long count1, result;	struct snd_rawmidi_runtime *runtime = substream->runtime;	snd_assert(buf != NULL, return -EINVAL);	snd_assert(runtime->buffer != NULL, return -EINVAL);	result = 0;	spin_lock_irqsave(&runtime->lock, flags);	if (substream->append) {		if ((long)runtime->avail < count) {			spin_unlock_irqrestore(&runtime->lock, flags);			return -EAGAIN;		}	}	while (count > 0 && runtime->avail > 0) {		count1 = runtime->buffer_size - runtime->appl_ptr;		if (count1 > count)			count1 = count;		if (count1 > (long)runtime->avail)			count1 = runtime->avail;		if (kernel) {			memcpy(runtime->buffer + runtime->appl_ptr, buf, count1);		} else {			spin_unlock_irqrestore(&runtime->lock, flags);			if (copy_from_user(runtime->buffer + runtime->appl_ptr,					   (char __user *)buf, count1)) {				spin_lock_irqsave(&runtime->lock, flags);				result = result > 0 ? result : -EFAULT;				goto __end;			}			spin_lock_irqsave(&runtime->lock, flags);		}		runtime->appl_ptr += count1;		runtime->appl_ptr %= runtime->buffer_size;		runtime->avail -= count1;		result += count1;		buf += count1;		count -= count1;	}      __end:	count1 = runtime->avail < runtime->buffer_size;	spin_unlock_irqrestore(&runtime->lock, flags);	if (count1)		snd_rawmidi_output_trigger(substream, 1);	return result;}long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream,			      const unsigned char *buf, long count){	return snd_rawmidi_kernel_write1(substream, buf, count, 1);}static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,				 size_t count, loff_t *offset){	long result, timeout;	int count1;	struct snd_rawmidi_file *rfile;	struct snd_rawmidi_runtime *runtime;	struct snd_rawmidi_substream *substream;	rfile = file->private_data;	substream = rfile->output;	runtime = substream->runtime;	/* we cannot put an atomic message to our buffer */	if (substream->append && count > runtime->buffer_size)		return -EIO;	result = 0;	while (count > 0) {		spin_lock_irq(&runtime->lock);		while (!snd_rawmidi_ready_append(substream, count)) {			wait_queue_t wait;			if (file->f_flags & O_NONBLOCK) {				spin_unlock_irq(&runtime->lock);				return result > 0 ? result : -EAGAIN;			}			init_waitqueue_entry(&wait, current);			add_wait_queue(&runtime->sleep, &wait);			set_current_state(TASK_INTERRUPTIBLE);			spin_unlock_irq(&runtime->lock);			timeout = schedule_timeout(30 * HZ);			remove_wait_queue(&runtime->sleep, &wait);			if (signal_pending(current))				return result > 0 ? result : -ERESTARTSYS;			if (!runtime->avail && !timeout)				return result > 0 ? result : -EIO;			spin_lock_irq(&runtime->lock);		}		spin_unlock_irq(&runtime->lock);		count1 = snd_rawmidi_kernel_write1(substream,						   (unsigned char __force *)buf,						   count, 0);		if (count1 < 0)			return result > 0 ? result : count1;		result += count1;		buf += count1;		if ((size_t)count1 < count && (file->f_flags & O_NONBLOCK))			break;		count -= count1;	}	if (file->f_flags & O_SYNC) {		spin_lock_irq(&runtime->lock);		while (runtime->avail != runtime->buffer_size) {			wait_queue_t wait;			unsigned int last_avail = runtime->avail;			init_waitqueue_entry(&wait, current);			add_wait_queue(&runtime->sleep, &wait);			set_current_state(TASK_INTERRUPTIBLE);			spin_unlock_irq(&runtime->lock);			timeout = schedule_timeout(30 * HZ);			remove_wait_queue(&runtime->sleep, &wait);			if (signal_pending(current))				return result > 0 ? result : -ERESTARTSYS;			if (runtime->avail == last_avail && !timeout)				return result > 0 ? result : -EIO;			spin_lock_irq(&runtime->lock);		}		spin_unlock_irq(&runtime->lock);	}	return result;}

⌨️ 快捷键说明

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