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

📄 dv1394.c

📁 IEE1394 火线接口驱动 for linux
💻 C
📖 第 1 页 / 共 5 页
字号:
				target_frame = video->first_clear_frame;				spin_unlock_irqrestore(&video->spinlock, flags);		if (video->frames[target_frame]->state == FRAME_CLEAR) {			/* how much room is left in the target frame buffer */			cnt = video->frame_size - (video->write_off - target_frame * video->frame_size);		} else {			/* buffer is already used */			cnt = 0;		}		if (cnt > count)			cnt = count;		if (cnt <= 0) { 			/* no room left, gotta wait */			if (file->f_flags & O_NONBLOCK) {				if (!ret)					ret = -EAGAIN;				break;			}			if (signal_pending(current)) {				if (!ret)					ret = -ERESTARTSYS;				break;			}			schedule();						continue; /* start over from 'while(count > 0)...' */		}		if (copy_from_user(video->dv_buf.kvirt + video->write_off, buffer, cnt)) {			if (!ret)				ret = -EFAULT;			break;		}		video->write_off = (video->write_off + cnt) % (video->n_frames * video->frame_size);		count -= cnt;		buffer += cnt;		ret += cnt;		if (video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames))				frame_prepare(video, target_frame);	}		remove_wait_queue(&video->waitq, &wait);	set_current_state(TASK_RUNNING);	up(&video->sem);	return ret;}static ssize_t dv1394_read(struct file *file,  char *buffer, size_t count, loff_t *ppos){	struct video_card *video = file_to_video_card(file);	DECLARE_WAITQUEUE(wait, current);	ssize_t ret;	size_t cnt;	unsigned long flags;	int target_frame;	/* serialize this to prevent multi-threaded mayhem */	if (file->f_flags & O_NONBLOCK) {		if (down_trylock(&video->sem))			return -EAGAIN;	} else {		if (down_interruptible(&video->sem))			return -ERESTARTSYS;	}	if ( !video_card_initialized(video) ) {		ret = do_dv1394_init_default(video);		if (ret) {			up(&video->sem);			return ret;		}		video->continuity_counter = -1;				receive_packets(video);				start_dma_receive(video);	}	ret = 0;	add_wait_queue(&video->waitq, &wait);	while (count > 0) {		/* must set TASK_INTERRUPTIBLE *before* checking for free		   buffers; otherwise we could miss a wakeup if the interrupt		   fires between the check and the schedule() */				set_current_state(TASK_INTERRUPTIBLE);		spin_lock_irqsave(&video->spinlock, flags);		target_frame = video->first_clear_frame;		spin_unlock_irqrestore(&video->spinlock, flags);		if (target_frame >= 0 &&			video->n_clear_frames > 0 &&			video->frames[target_frame]->state == FRAME_CLEAR) {			/* how much room is left in the target frame buffer */			cnt = video->frame_size - (video->write_off - target_frame * video->frame_size);		} else {			/* buffer is already used */			cnt = 0;		}		if (cnt > count)			cnt = count;		if (cnt <= 0) { 			/* no room left, gotta wait */			if (file->f_flags & O_NONBLOCK) {				if (!ret)					ret = -EAGAIN;				break;			}			if (signal_pending(current)) {				if (!ret)					ret = -ERESTARTSYS;				break;			}			schedule();						continue; /* start over from 'while(count > 0)...' */		}		if (copy_to_user(buffer, video->dv_buf.kvirt + video->write_off, cnt)) {				if (!ret)					ret = -EFAULT;				break;		}		video->write_off = (video->write_off + cnt) % (video->n_frames * video->frame_size);		count -= cnt;		buffer += cnt;		ret += cnt;		if (video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames)) {			spin_lock_irqsave(&video->spinlock, flags);			video->n_clear_frames--;			video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames;			spin_unlock_irqrestore(&video->spinlock, flags);		}	}		remove_wait_queue(&video->waitq, &wait);	set_current_state(TASK_RUNNING);	up(&video->sem);	return ret;}/*** DEVICE IOCTL INTERFACE ************************************************//* I *think* the VFS serializes ioctl() for us, so we don't have to worry   about situations like having two threads in here at once... */static int dv1394_ioctl(struct inode *inode, struct file *file,			   unsigned int cmd, unsigned long arg){	struct video_card *video = file_to_video_card(file);	unsigned long flags;	int ret = -EINVAL;	DECLARE_WAITQUEUE(wait, current);	/* serialize this to prevent multi-threaded mayhem */	if (file->f_flags & O_NONBLOCK) {		if (down_trylock(&video->sem))			return -EAGAIN;	} else {		if (down_interruptible(&video->sem))			return -ERESTARTSYS;	}	switch(cmd)	{	case DV1394_SUBMIT_FRAMES:	case DV1394_IOC_SUBMIT_FRAMES: {		unsigned int n_submit;		if ( !video_card_initialized(video) ) {			ret = do_dv1394_init_default(video);			if (ret)				goto out;		}		n_submit = (unsigned int) arg;		if (n_submit > video->n_frames) {			ret = -EINVAL;			goto out;		}					while (n_submit > 0) {			add_wait_queue(&video->waitq, &wait);			set_current_state(TASK_INTERRUPTIBLE);							spin_lock_irqsave(&video->spinlock, flags);			/* wait until video->first_clear_frame is really CLEAR */			while (video->frames[video->first_clear_frame]->state != FRAME_CLEAR) {				spin_unlock_irqrestore(&video->spinlock, flags);									if (signal_pending(current)) {					remove_wait_queue(&video->waitq, &wait);					set_current_state(TASK_RUNNING);					ret = -EINTR;					goto out;				}				schedule();				set_current_state(TASK_INTERRUPTIBLE);								spin_lock_irqsave(&video->spinlock, flags);			}			spin_unlock_irqrestore(&video->spinlock, flags);			remove_wait_queue(&video->waitq, &wait);			set_current_state(TASK_RUNNING);							frame_prepare(video, video->first_clear_frame);			n_submit--;		}		ret = 0;		break;	}	case DV1394_WAIT_FRAMES:	case DV1394_IOC_WAIT_FRAMES: {		unsigned int n_wait;		if ( !video_card_initialized(video) ) {			ret = -EINVAL;			goto out;		}				n_wait = (unsigned int) arg;		/* since we re-run the last frame on underflow, we will		   never actually have n_frames clear frames; at most only		   n_frames - 1 */		if (n_wait > (video->n_frames-1) ) {			ret = -EINVAL;			goto out;		}					add_wait_queue(&video->waitq, &wait);		set_current_state(TASK_INTERRUPTIBLE);				spin_lock_irqsave(&video->spinlock, flags);		while (video->n_clear_frames < n_wait) {						spin_unlock_irqrestore(&video->spinlock, flags);								if (signal_pending(current)) {				remove_wait_queue(&video->waitq, &wait);				set_current_state(TASK_RUNNING);				ret = -EINTR;				goto out;			}			schedule();			set_current_state(TASK_INTERRUPTIBLE);						spin_lock_irqsave(&video->spinlock, flags);		}		spin_unlock_irqrestore(&video->spinlock, flags);		remove_wait_queue(&video->waitq, &wait);		set_current_state(TASK_RUNNING);		ret = 0;		break;	}	case DV1394_RECEIVE_FRAMES:	case DV1394_IOC_RECEIVE_FRAMES: {		unsigned int n_recv;		if ( !video_card_initialized(video) ) {			ret = -EINVAL;			goto out;		}				n_recv = (unsigned int) arg;		/* at least one frame must be active */		if (n_recv > (video->n_frames-1) ) {			ret = -EINVAL;			goto out;		}					spin_lock_irqsave(&video->spinlock, flags);		/* release the clear frames */		video->n_clear_frames -= n_recv;		/* advance the clear frame cursor */		video->first_clear_frame = (video->first_clear_frame + n_recv) % video->n_frames;		/* reset dropped_frames */		video->dropped_frames = 0;					spin_unlock_irqrestore(&video->spinlock, flags);		ret = 0;		break;	}	case DV1394_START_RECEIVE:	case DV1394_IOC_START_RECEIVE: {		if ( !video_card_initialized(video) ) {			ret = do_dv1394_init_default(video);			if (ret)				goto out;		}			video->continuity_counter = -1;				receive_packets(video);				start_dma_receive(video);		ret = 0;		break;	}	case DV1394_INIT:	case DV1394_IOC_INIT: {		struct dv1394_init init;		if (arg == (unsigned long) NULL) {			ret = do_dv1394_init_default(video);		} else {			if (copy_from_user(&init, (void*)arg, sizeof(init))) {				ret = -EFAULT;				goto out;			}			ret = do_dv1394_init(video, &init);		}		break;	}	case DV1394_SHUTDOWN:	case DV1394_IOC_SHUTDOWN:		do_dv1394_shutdown(video, 0);		ret = 0;		break;	case DV1394_GET_STATUS:        case DV1394_IOC_GET_STATUS: {		struct dv1394_status status;		if ( !video_card_initialized(video) ) {			ret = -EINVAL;			goto out;		}		status.init.api_version = DV1394_API_VERSION;		status.init.channel = video->channel;		status.init.n_frames = video->n_frames;		status.init.format = video->pal_or_ntsc;		status.init.cip_n = video->cip_n;		status.init.cip_d = video->cip_d;		status.init.syt_offset = video->syt_offset;		status.first_clear_frame = video->first_clear_frame;		/* the rest of the fields need to be locked against the interrupt */		spin_lock_irqsave(&video->spinlock, flags);		status.active_frame = video->active_frame;		status.n_clear_frames = video->n_clear_frames;		status.dropped_frames = video->dropped_frames;		/* reset dropped_frames */		video->dropped_frames = 0;					spin_unlock_irqrestore(&video->spinlock, flags);		if (copy_to_user((void*)arg, &status, sizeof(status))) {			ret = -EFAULT;			goto out;		}		ret = 0;		break;	}	default:		break;	} out:	up(&video->sem);	return ret;}/*** DEVICE FILE INTERFACE CONTINUED ***************************************/static int dv1394_open(struct inode *inode, struct file *file){	struct video_card *video = NULL;	/* if the device was opened through devfs, then file->private_data	   has already been set to video by devfs */	if (file->private_data) {		video = (struct video_card*) file->private_data;			} else {		/* look up the card by ID */				struct list_head *lh;		unsigned long flags;				spin_lock_irqsave(&dv1394_cards_lock, flags);		if (!list_empty(&dv1394_cards)) {			struct video_card *p;			list_for_each(lh, &dv1394_cards) {				p = list_entry(lh, struct video_card, list);				if ((p->id) == ieee1394_file_to_instance(file)) {					video = p;					break;				}			}		}		spin_unlock_irqrestore(&dv1394_cards_lock, flags);		if (!video) {			debug_printk("dv1394: OHCI card %d not found", ieee1394_file_to_instance(file));			return -ENODEV;		}				file->private_data = (void*) video;	}	#ifndef DV1394_ALLOW_MORE_THAN_ONE_OPEN	if ( test_and_set_bit(0, &video->open) ) {		/* video is already open by someone else */		return -EBUSY; 	}

⌨️ 快捷键说明

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