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

📄 lirc_dev.c

📁 很少见的linux下的红外口的工具
💻 C
📖 第 1 页 / 共 2 页
字号:
	DECLARE_MUTEX_LOCKED(tn);	if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {		printk("lirc_dev: lirc_unregister_plugin:"		       "\" minor\" must be beetween 0 and %d!\n",		       MAX_IRCTL_DEVICES-1);		return -EBADRQC;	}	ir = &irctls[minor];	down_interruptible(&plugin_lock);	if (ir->p.minor != minor) {		printk("lirc_dev: lirc_unregister_plugin:"		       "minor (%d) device not registered!", minor);		up(&plugin_lock);		return -ENOENT;	}	if (ir->open) {		printk("lirc_dev: lirc_unregister_plugin:"		       "plugin %s[%d] in use!", ir->p.name, ir->p.minor);		up(&plugin_lock);		return -EBUSY;	}	/* end up polling thread */	if (ir->tpid >= 0) {		ir->t_notify = &tn;		ir->shutdown = 1;		down(&tn);		ir->t_notify = NULL;	}	dprintk("lirc_dev: plugin %s unregistered from minor number = %d\n",		ir->p.name, ir->p.minor);#ifdef LIRC_HAVE_DEVFS	devfs_unregister(ir->devfs_handle);#endif	init_irctl(ir);	up(&plugin_lock);	MOD_DEC_USE_COUNT;	return SUCCESS;}/* * */static int irctl_open(struct inode *inode, struct file *file){	struct irctl *ir;		if (MINOR(inode->i_rdev) >= MAX_IRCTL_DEVICES) {		dprintk("lirc_dev [%d]: open result = -ENODEV\n",			MINOR(inode->i_rdev));		return -ENODEV;	}	ir = &irctls[MINOR(inode->i_rdev)];	dprintk(LOGHEAD "open called\n", ir->p.name, ir->p.minor);	down_interruptible(&plugin_lock);	if (ir->p.minor == NOPLUG) {		up(&plugin_lock);		dprintk(LOGHEAD "open result = -ENODEV\n",			ir->p.name, ir->p.minor);		return -ENODEV;	}	if (ir->open) {		up(&plugin_lock);		dprintk(LOGHEAD "open result = -EBUSY\n",			ir->p.name, ir->p.minor);		return -EBUSY;	}	/* rhere is no need for locking here because ir->open is 0          * and lirc_thread isn't using buffer         */	ir->head = ir->tail;	ir->in_buf = 0;	++ir->open;	ir->p.set_use_inc(ir->p.data);	up(&plugin_lock);	dprintk(LOGHEAD "open result = %d\n", ir->p.name, ir->p.minor, SUCCESS);	return SUCCESS;}/* * */static int irctl_close(struct inode *inode, struct file *file){	struct irctl *ir = &irctls[MINOR(inode->i_rdev)];	dprintk(LOGHEAD "close called\n", ir->p.name, ir->p.minor); 	down_interruptible(&plugin_lock);	--ir->open;	ir->p.set_use_dec(ir->p.data);	up(&plugin_lock);	return SUCCESS;}/* * */static unsigned int irctl_poll(struct file *file, poll_table *wait){	struct irctl *ir = &irctls[MINOR(file->f_dentry->d_inode->i_rdev)];	dprintk(LOGHEAD "poll called\n", ir->p.name, ir->p.minor);	if (!ir->in_buf) {		poll_wait(file, &ir->wait_poll, wait);	}	dprintk(LOGHEAD "poll result = %s\n",		ir->p.name, ir->p.minor, 		ir->in_buf ? "POLLIN|POLLRDNORM" : "SUCCESS");	return ir->in_buf ? (POLLIN|POLLRDNORM) : SUCCESS;}/* * */static int irctl_ioctl(struct inode *inode, struct file *file,                       unsigned int cmd, unsigned long arg){	unsigned long mode;	int result = SUCCESS;	struct irctl *ir = &irctls[MINOR(inode->i_rdev)];	dprintk(LOGHEAD "poll called (%u)\n",		ir->p.name, ir->p.minor, cmd);	if (ir->p.minor == NOPLUG) {		dprintk(LOGHEAD "ioctl result = -ENODEV\n",			ir->p.name, ir->p.minor);		return -ENODEV;	}	switch(cmd)	{	case LIRC_GET_FEATURES:		result = put_user(ir->features, (unsigned long*)arg);		break;	case LIRC_GET_REC_MODE:		result = put_user(LIRC_REC2MODE(ir->features),				  (unsigned long*)arg);		break;	case LIRC_SET_REC_MODE:		result = get_user(mode, (unsigned long*)arg);		if(!result && !(LIRC_MODE2REC(mode) & ir->features)) {			result = -EINVAL;		}		break;	case LIRC_GET_LENGTH:		result = put_user((unsigned long)ir->p.code_length, 				  (unsigned long *)arg);		break;	default:		result = -ENOIOCTLCMD;	}	dprintk(LOGHEAD "ioctl result = %d\n",		ir->p.name, ir->p.minor, result);	return result;}/* * */static ssize_t irctl_read(struct file *file,			  char *buffer,   			  size_t length, 			  loff_t *ppos)     {	unsigned char buf[BUFLEN];	struct irctl *ir = &irctls[MINOR(file->f_dentry->d_inode->i_rdev)];	int ret;	DECLARE_WAITQUEUE(wait, current);	dprintk(LOGHEAD "read called\n", ir->p.name, ir->p.minor);	if (ir->bytes_in_key != length) {		dprintk(LOGHEAD "read result = -EIO\n",			ir->p.name, ir->p.minor);		return -EIO;	}	/* we add ourselves to the task queue before buffer check          * to avoid losing scan code (in case when queue is awaken somewhere 	 * beetwen while condition checking and scheduling)	 */	add_wait_queue(&ir->wait_poll, &wait);	current->state = TASK_INTERRUPTIBLE;	/* while input buffer is empty and device opened in blocking mode, 	 * wait for input 	 */	while (!ir->in_buf) {		if (file->f_flags & O_NONBLOCK) {			dprintk(LOGHEAD "read result = -EWOULDBLOCK\n", 				ir->p.name, ir->p.minor);			remove_wait_queue(&ir->wait_poll, &wait);			current->state = TASK_RUNNING;			return -EWOULDBLOCK;		}		if (signal_pending(current)) {			dprintk(LOGHEAD "read result = -ERESTARTSYS\n", 				ir->p.name, ir->p.minor);			remove_wait_queue(&ir->wait_poll, &wait);			current->state = TASK_RUNNING;			return -ERESTARTSYS;		}		schedule();		current->state = TASK_INTERRUPTIBLE;	}	remove_wait_queue(&ir->wait_poll, &wait);	current->state = TASK_RUNNING;	/* here is the only point at which we remove key codes from 	 * the buffer	 */	IRLOCK;	memcpy(buf, &ir->buffer[ir->head], length);	ir->head += length;	ir->head %= ir->buf_len;	ir->in_buf -= length;	IRUNLOCK;	ret = copy_to_user(buffer, buf, length);	dprintk(LOGHEAD "read result = %s (%d)\n",		ir->p.name, ir->p.minor, ret ? "-EFAULT" : "OK", ret);	return ret ? -EFAULT : length;}static struct file_operations fops = {	read:    irctl_read, 	poll:    irctl_poll,	ioctl:   irctl_ioctl,	open:    irctl_open,	release: irctl_close};EXPORT_SYMBOL(lirc_register_plugin);EXPORT_SYMBOL(lirc_unregister_plugin);/* * */int lirc_dev_init(void){  		int i;	for (i=0; i < MAX_IRCTL_DEVICES; ++i) {		init_irctl(&irctls[i]);			init_MUTEX(&irctls[i].lock);		init_waitqueue_head(&irctls[i].wait_poll);	}#ifndef LIRC_HAVE_DEVFS 	i = register_chrdev(IRCTL_DEV_MAJOR,#else	i = devfs_register_chrdev(IRCTL_DEV_MAJOR,#endif				   IRCTL_DEV_NAME,				   &fops);		if (i < 0) {		printk ("lirc_dev: device registration failed with %d\n", i);		return i;	}		printk("lirc_dev: IR Remote Control driver registered, at major %d \n", 	       IRCTL_DEV_MAJOR);	return SUCCESS;}/* ---------------------------------------------------------------------- *//* For now dont try to use it as a static version !  */#ifdef MODULEMODULE_DESCRIPTION("LIRC base driver module");MODULE_AUTHOR("Artur Lipowski");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endif/* * */int init_module(void){	return lirc_dev_init();}/* * */void cleanup_module(void){	int ret;	#ifndef LIRC_HAVE_DEVFS 	ret = unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME);#else	ret = devfs_unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME);#endif 	if (0 > ret){		printk("lirc_dev: error in module_unregister_chrdev: %d\n",		       ret);	} else {		dprintk("lirc_dev: module successfully unloaded\n");	}}#endif/* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- * Local variables: * c-basic-offset: 8 * End: */

⌨️ 快捷键说明

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