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

📄 comedi_fops.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		switch(insn->insn){		case INSN_GTOD:		{			struct timeval tv;			if(insn->n!=2){				ret=-EINVAL;				break;			}			do_gettimeofday(&tv);			data[0]=tv.tv_sec;			data[1]=tv.tv_usec;			ret=2;			break;		}		case INSN_WAIT:			if(insn->n!=1 || data[0]>=100000){				ret=-EINVAL;				break;			}			udelay(data[0]/1000);			ret=1;			break;		case INSN_INTTRIG:			if(insn->n!=1){				ret=-EINVAL;				break;			}			if(insn->subdev>=dev->n_subdevices){				DPRINTK("%d not usable subdevice\n",insn->subdev);				ret=-EINVAL;				break;			}			s=dev->subdevices+insn->subdev;			if(!s->async){				DPRINTK("no async\n");				ret=-EINVAL;				break;			}			if(!s->async->inttrig){				DPRINTK("no inttrig\n");				ret=-EAGAIN;				break;			}			ret = s->async->inttrig(dev,s,insn->data[0]);			if(ret>=0)ret = 1;			break;		default:			DPRINTK("invalid insn\n");			ret=-EINVAL;			break;		}	}else{		/* a subdevice instruction */		if(insn->subdev>=dev->n_subdevices){			DPRINTK("subdevice %d out of range\n",insn->subdev);			ret=-EINVAL;			goto out;		}		s=dev->subdevices+insn->subdev;		if(s->type==COMEDI_SUBD_UNUSED){			DPRINTK("%d not usable subdevice\n",insn->subdev);			ret = -EIO;			goto out;		}			/* are we locked? (ioctl lock) */		if(s->lock && s->lock!=file){			DPRINTK("device locked\n");			ret = -EACCES;			goto out;		}		if((ret=check_chanlist(s,1,&insn->chanspec))<0){			ret=-EINVAL;			DPRINTK("bad chanspec\n");			goto out;		}		if(s->busy){			ret=-EBUSY;			goto out;		}		/* This looks arbitrary.  It is. */		s->busy=&parse_insn;		switch(insn->insn){			case INSN_READ:				ret=s->insn_read(dev,s,insn,data);				break;			case INSN_WRITE:				ret=s->insn_write(dev,s,insn,data);				break;			case INSN_BITS:				ret=s->insn_bits(dev,s,insn,data);				break;			case INSN_CONFIG:				ret=s->insn_config(dev,s,insn,data);				break;			default:				ret=-EINVAL;				break;		}		s->busy=NULL;	}out:	return ret;}/* * 	COMEDI_INSN * 	synchronous instructions * * 	arg: * 		pointer to insn * * 	reads: * 		comedi_insn struct at arg * 		data (for writes) * * 	writes: * 		data (for reads) */static int do_insn_ioctl(comedi_device *dev,void *arg,void *file){	comedi_insn	insn;	lsampl_t	*data = NULL;	int ret=0;	data=kmalloc(sizeof(lsampl_t)*MAX_SAMPLES,GFP_KERNEL);	if(!data){		ret = -ENOMEM;		goto error;	}	if(copy_from_user(&insn,arg,sizeof(comedi_insn))){		ret=-EFAULT;		goto error;	}	/* This is where the behavior of insn and insnlist deviate. */	if(insn.n>MAX_SAMPLES)insn.n=MAX_SAMPLES;	if(insn.insn&INSN_MASK_WRITE){		if(copy_from_user(data,insn.data,insn.n*sizeof(lsampl_t))){			ret=-EFAULT;			goto error;		}	}	ret = parse_insn(dev,&insn,data,file);	if(ret<0)goto error;	if(insn.insn&INSN_MASK_READ){		if(copy_to_user(insn.data,data,insn.n*sizeof(lsampl_t))){			ret=-EFAULT;			goto error;		}	}	ret = insn.n;error:	if(data)kfree(data);	return ret;}/*	COMEDI_CMD	command ioctl	arg:		pointer to cmd structure	reads:		cmd structure at arg		channel/range list	writes:		modified cmd structure at arg*/static int do_cmd_ioctl(comedi_device *dev,void *arg,void *file){	comedi_cmd user_cmd;	comedi_subdevice *s;	comedi_async *async;	int ret=0;	unsigned int *chanlist_saver=NULL;	if(copy_from_user(&user_cmd,arg,sizeof(comedi_cmd))){		DPRINTK("bad cmd address\n");		return -EFAULT;	}	// save user's chanlist pointer so it can be restored later	chanlist_saver = user_cmd.chanlist;	if(user_cmd.subdev>=dev->n_subdevices){		DPRINTK("%d no such subdevice\n",user_cmd.subdev);		return -ENODEV;	}	s=dev->subdevices+user_cmd.subdev;	async = s->async;	if(s->type==COMEDI_SUBD_UNUSED){		DPRINTK("%d not valid subdevice\n",user_cmd.subdev);		return -EIO;	}	if(!s->do_cmd || !s->async){		DPRINTK("subdevice %i does not support commands\n", user_cmd.subdev);		return -EIO;	}	/* are we locked? (ioctl lock) */	if(s->lock && s->lock!=file){		DPRINTK("subdevice locked\n");		return -EACCES;	}	/* are we busy? */	if(s->busy){		DPRINTK("subdevice busy\n");		return -EBUSY;	}	s->busy=file;	/* make sure channel/gain list isn't too long */	if(user_cmd.chanlist_len > s->len_chanlist){		DPRINTK("channel/gain list too long %d > %d\n",user_cmd.chanlist_len,s->len_chanlist);		ret = -EINVAL;		goto cleanup;	}	async->cmd=user_cmd;	async->cmd.chanlist=NULL;	async->cmd.data=NULL;	/* load channel/gain list */	/* we should have this already allocated */	async->cmd.chanlist=kmalloc(async->cmd.chanlist_len*sizeof(int),GFP_KERNEL);	if(!async->cmd.chanlist){		DPRINTK("allocation failed\n");		ret = -ENOMEM;		goto cleanup;	}	if(copy_from_user(async->cmd.chanlist,user_cmd.chanlist,async->cmd.chanlist_len*sizeof(int))){		DPRINTK("fault reading chanlist\n");		ret = -EFAULT;		goto cleanup;	}	/* make sure each element in channel/gain list is valid */	if((ret=check_chanlist(s,async->cmd.chanlist_len,async->cmd.chanlist))<0){		DPRINTK("bad chanlist\n");		goto cleanup;	}	ret=s->do_cmdtest(dev,s,&async->cmd);	if(async->cmd.flags&TRIG_BOGUS || ret){		DPRINTK("test returned %d\n",ret);		user_cmd=async->cmd;		// restore chanlist pointer before copying back		user_cmd.chanlist = chanlist_saver;		user_cmd.data = NULL;		if(copy_to_user(arg,&user_cmd,sizeof(comedi_cmd))){			DPRINTK("fault writing cmd\n");			ret = -EFAULT;			goto cleanup;		}		ret = -EAGAIN;		goto cleanup;	}	if(!async->prealloc_bufsz){		ret=-ENOMEM;		DPRINTK("no buffer (?)\n");		goto cleanup;	}	init_async_buf( async );	async->cb_mask = COMEDI_CB_EOA|COMEDI_CB_BLOCK|COMEDI_CB_ERROR;	if(async->cmd.flags & TRIG_WAKE_EOS){		async->cb_mask |= COMEDI_CB_EOS;	}	async->events = 0;	s->runflags=SRF_USER;	s->subdev_flags|=SDF_RUNNING;#ifdef CONFIG_COMEDI_RT	if(async->cmd.flags&TRIG_RT){		comedi_switch_to_rt(dev);		s->runflags |= SRF_RT;	}#endif	ret=s->do_cmd(dev,s);	if(ret==0)return 0;cleanup:	do_become_nonbusy(dev,s);	return ret;}/*	COMEDI_CMDTEST	command testing ioctl	arg:		pointer to cmd structure	reads:		cmd structure at arg		channel/range list	writes:		modified cmd structure at arg*/static int do_cmdtest_ioctl(comedi_device *dev,void *arg,void *file){	comedi_cmd user_cmd;	comedi_subdevice *s;	int ret=0;	unsigned int *chanlist=NULL;	unsigned int *chanlist_saver=NULL;	if(copy_from_user(&user_cmd,arg,sizeof(comedi_cmd))){		DPRINTK("bad cmd address\n");		return -EFAULT;	}	// save user's chanlist pointer so it can be restored later	chanlist_saver = user_cmd.chanlist;	if(user_cmd.subdev>=dev->n_subdevices){		DPRINTK("%d no such subdevice\n",user_cmd.subdev);		return -ENODEV;	}	s=dev->subdevices+user_cmd.subdev;	if(s->type==COMEDI_SUBD_UNUSED){		DPRINTK("%d not valid subdevice\n",user_cmd.subdev);		return -EIO;	}	if(!s->do_cmd){		DPRINTK("subdevice %i does not support commands\n", user_cmd.subdev);		return -EIO;	}	/* make sure channel/gain list isn't too long */	if(user_cmd.chanlist_len > s->len_chanlist){		DPRINTK("channel/gain list too long %d > %d\n",user_cmd.chanlist_len,s->len_chanlist);		ret = -EINVAL;		goto cleanup;	}	/* load channel/gain list */	if(user_cmd.chanlist){		chanlist=kmalloc(user_cmd.chanlist_len*sizeof(int),GFP_KERNEL);		if(!chanlist){			DPRINTK("allocation failed\n");			ret = -ENOMEM;			goto cleanup;		}		if(copy_from_user(chanlist,user_cmd.chanlist,user_cmd.chanlist_len*sizeof(int))){			DPRINTK("fault reading chanlist\n");			ret = -EFAULT;			goto cleanup;		}		/* make sure each element in channel/gain list is valid */		if((ret=check_chanlist(s,user_cmd.chanlist_len,chanlist))<0){			DPRINTK("bad chanlist\n");			goto cleanup;		}		user_cmd.chanlist=chanlist;	}	ret=s->do_cmdtest(dev,s,&user_cmd);	// restore chanlist pointer before copying back	user_cmd.chanlist = chanlist_saver;	if(copy_to_user(arg,&user_cmd,sizeof(comedi_cmd))){		DPRINTK("bad cmd address\n");		ret=-EFAULT;		goto cleanup;	}cleanup:	if(chanlist)		kfree(chanlist);	return ret;}/*	COMEDI_LOCK	lock subdevice		arg:		subdevice number		reads:		none		writes:		none*/static int do_lock_ioctl(comedi_device *dev,unsigned int arg,void * file){	int ret=0;	unsigned long flags;	comedi_subdevice *s;	if(arg>=dev->n_subdevices)		return -EINVAL;	s=dev->subdevices+arg;	if(s->busy)		return -EBUSY;	comedi_spin_lock_irqsave(&big_comedi_lock, flags);	if(s->lock && s->lock!=file){		ret=-EACCES;	}else{		s->lock=file;	}	comedi_spin_unlock_irqrestore(&big_comedi_lock, flags);	if(ret<0)		return ret;#if 0	if(s->lock_f)		ret=s->lock_f(dev,s);#endif	return ret;}/*	COMEDI_UNLOCK	unlock subdevice	arg:		subdevice number	reads:		none		writes:		none	This function isn't protected by the semaphore, since	we already own the lock.*/static int do_unlock_ioctl(comedi_device *dev,unsigned int arg,void * file){	comedi_subdevice *s;	if(arg>=dev->n_subdevices)		return -EINVAL;	s=dev->subdevices+arg;	if(s->busy)		return -EBUSY;	if(s->lock && s->lock!=file)		return -EACCES;	if(s->lock==file){#if 0		if(s->unlock)			s->unlock(dev,s);#endif		s->lock=NULL;	}	return 0;}/*	COMEDI_CANCEL	cancel acquisition ioctl		arg:		subdevice number		reads:		nothing		writes:		nothing*/static int do_cancel_ioctl(comedi_device *dev,unsigned int arg,void *file){	comedi_subdevice *s;	if(arg>=dev->n_subdevices)		return -EINVAL;	s=dev->subdevices+arg;	if(s->lock && s->lock!=file)		return -EACCES;	if(!s->busy)		return 0;	if(s->busy!=file)		return -EBUSY;	return do_cancel(dev,s);}/*	COMEDI_POLL ioctl	instructs driver to synchronize buffers		arg:		subdevice number		reads:		nothing	writes:		nothing*/static int do_poll_ioctl(comedi_device *dev,unsigned int arg,void *file){	comedi_subdevice *s;	if(arg>=dev->n_subdevices)		return -EINVAL;	s=dev->subdevices+arg;	if(s->lock && s->lock!=file)		return -EACCES;	if(!s->busy)		return 0;	if(s->busy!=file)		return -EBUSY;	if(s->poll)return s->poll(dev,s);	return -EINVAL;}static int do_cancel(comedi_device *dev,comedi_subdevice *s){	int ret=0;	if((s->subdev_flags&SDF_RUNNING) && s->cancel)		ret=s->cancel(dev,s);	do_become_nonbusy(dev,s);	return ret;}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0)  /* XXX */#define RDEV_OF_FILE(x)        ((x)->f_inode->i_rdev)#else#define RDEV_OF_FILE(x)        ((x)->f_dentry->d_inode->i_rdev)#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)void comedi_unmap(struct vm_area_struct *area){	comedi_async *async;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,17)	async = (void *)area->vm_pte;#else	async = area->vm_private_data;#endif	async->mmap_count--;}static struct vm_operations_struct comedi_vm_ops={	close:		comedi_unmap,};/*   comedi_mmap_v22 */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,17)#define page_address(x) x#endifstatic int comedi_mmap_v22(struct file * file, struct vm_area_struct *vma){	kdev_t minor=MINOR(RDEV_OF_FILE(file));	comedi_device *dev=comedi_get_device_by_minor(minor);	comedi_async *async = NULL;	unsigned long start = vma->vm_start;	unsigned long size;	int n_pages;	int i;	if(!dev->attached)	{		DPRINTK("no driver configured on comedi%i\n", dev->minor);		return -ENODEV;	}	if(vma->vm_flags & VM_WRITE){

⌨️ 快捷键说明

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