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

📄 lirc_dev.c

📁 很少见的linux下的红外口的工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * LIRC base driver *  * (L) by Artur Lipowski <alipowski@kki.net.pl> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * $Id: lirc_dev.c,v 1.18 2001/12/12 20:26:01 ranty Exp $ * */#ifdef HAVE_CONFIG_H# include <config.h>#endif #include <linux/version.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)#define LIRC_HAVE_DEVFS#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 4)#error "********************************************************"#error " Sorry, this driver needs kernel version 2.2.4 or higher"#error "********************************************************"#endif#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/ioctl.h>#include <linux/fs.h>#include <linux/poll.h>#ifdef LIRC_HAVE_DEVFS#include <linux/devfs_fs_kernel.h>#endif#include <linux/smp_lock.h>#include <asm/uaccess.h>#include <asm/semaphore.h>#include <asm/errno.h>#include <linux/wrapper.h>#define __KERNEL_SYSCALLS__#include <linux/unistd.h>#include "drivers/lirc.h"#include "lirc_dev.h"static int debug = 0;MODULE_PARM(debug,"i");#define IRCTL_DEV_NAME    "BaseRemoteCtl"#define IRLOCK            down_interruptible(&ir->lock)#define IRUNLOCK          up(&ir->lock)#define SUCCESS           0#define NOPLUG            -1#define dprintk           if (debug) printk#define LOGHEAD           "lirc_dev (%s[%d]): "struct irctl{	struct lirc_plugin p;	int open;	unsigned long features;	unsigned int buf_len;	int bytes_in_key;	unsigned char buffer[BUFLEN];	unsigned int in_buf;	int head, tail;	int tpid;	struct semaphore *t_notify;	int shutdown;	long jiffies_to_wait;	wait_queue_head_t wait_poll;	struct semaphore lock;#ifdef LIRC_HAVE_DEVFS	devfs_handle_t devfs_handle;#endif};DECLARE_MUTEX(plugin_lock);static struct irctl irctls[MAX_IRCTL_DEVICES];static struct file_operations fops;/*  helper function *  initializes the irctl structure */static inline void init_irctl(struct irctl *ir){	memset(&ir->p, 0, sizeof(struct lirc_plugin));	ir->p.minor = NOPLUG;	ir->buf_len = 0;	ir->bytes_in_key = 0;	ir->features = 0;	ir->tpid = -1;	ir->t_notify = NULL;	ir->shutdown = 0;	ir->jiffies_to_wait = 0;	memset(&ir->buffer, 0, BUFLEN);	ir->in_buf = 0;	ir->head = ir->tail = 0;	ir->open = 0;}/*  helper function *  reads key codes from plugin and puts them into buffer *  buffer free space is checked and locking performed *  returns 0 on success */inline static int add_to_buf(struct irctl *ir){	unsigned char buf[BUFLEN];	unsigned int i;	if (ir->in_buf == ir->buf_len) {		dprintk(LOGHEAD "buffer overflow\n",			ir->p.name, ir->p.minor);		return -EOVERFLOW;	}	for (i=0; i < ir->bytes_in_key; i++) {		if (ir->p.get_key(ir->p.data, &buf[i], i)) {			return -ENODATA;		}		dprintk(LOGHEAD "remote code (0x%x) now in buffer\n",			ir->p.name, ir->p.minor, buf[i]);	}	/* here is the only point at which we add key codes to the buffer */	IRLOCK;	memcpy(&ir->buffer[ir->tail], buf, ir->bytes_in_key);	ir->tail += ir->bytes_in_key;	ir->tail %= ir->buf_len;	ir->in_buf += ir->bytes_in_key;	IRUNLOCK;	return SUCCESS;}/* main function of the polling thread */static int lirc_thread(void *irctl){	struct irctl *ir = irctl;		lock_kernel();		/* This thread doesn't need any user-level access,	 * so get rid of all our resources	 */	exit_mm(current);	exit_files(current);	exit_fs(current);	current->session = 1;	current->pgrp = 1;	current->euid = 0;	current->tty = NULL;	sigfillset(&current->blocked);		strcpy(current->comm, "lirc_dev");		unlock_kernel();		if (ir->t_notify != NULL) {		up(ir->t_notify);	}		dprintk(LOGHEAD "poll thread started\n", ir->p.name, ir->p.minor);		do {		if (ir->open) {			if (ir->jiffies_to_wait) {				current->state = TASK_INTERRUPTIBLE;				schedule_timeout(ir->jiffies_to_wait);			} else {				interruptible_sleep_on(ir->p.get_queue(ir->p.data));			}			if (signal_pending(current)) {				break;			}			if (!add_to_buf(ir)) {				wake_up_interruptible(&ir->wait_poll);			}		} else {			/* if device not opened so we can sleep half a second */			current->state = TASK_INTERRUPTIBLE;			schedule_timeout(HZ/2);		}	} while (!ir->shutdown && !signal_pending(current));		ir->tpid = -1;	if (ir->t_notify != NULL) {		up(ir->t_notify);	}		dprintk(LOGHEAD "poll thread ended\n", ir->p.name, ir->p.minor);		return 0;}/* * */int lirc_register_plugin(struct lirc_plugin *p){	struct irctl *ir;	int minor;#ifdef LIRC_HAVE_DEVFS	char name[16];#endif	DECLARE_MUTEX_LOCKED(tn);	if (!p) {		printk("lirc_dev: lirc_register_plugin:"		       "plugin pointer must be not NULL!\n");		return -EBADRQC;	}	if (MAX_IRCTL_DEVICES <= p->minor) {		printk("lirc_dev: lirc_register_plugin:"		       "\" minor\" must be beetween 0 and %d (%d)!\n",		       MAX_IRCTL_DEVICES-1, p->minor);		return -EBADRQC;	}	if (1 > p->code_length || (BUFLEN*8) < p->code_length) {		printk("lirc_dev: lirc_register_plugin:"		       "code length in bits for minor (%d) "		       "must be less than %d!\n",		       p->minor, BUFLEN*8);		return -EBADRQC;	}	if (p->sample_rate) {		if (2 > p->sample_rate || 50 < p->sample_rate) {			printk("lirc_dev: lirc_register_plugin:"			       "sample_rate must be beetween 2 and 50!\n");			return -EBADRQC;		}	} else {		if (!p->get_queue) {			printk("lirc_dev: lirc_register_plugin:"			       "get_queue cannot be NULL!\n");			return -EBADRQC;		}	}	down_interruptible(&plugin_lock);	minor = p->minor;	if (0 > minor) {		/* find first free slot for plugin */		for (minor=0; minor<MAX_IRCTL_DEVICES; minor++)			if (irctls[minor].p.minor == NOPLUG)				break;		if (MAX_IRCTL_DEVICES == minor) {			printk("lirc_dev: lirc_register_plugin: "			       "no free slots for plugins!\n");			up(&plugin_lock);			return -ENOMEM;		}	} else if (irctls[minor].p.minor != NOPLUG) {		printk("lirc_dev: lirc_register_plugin:"		       "minor (%d) just registerd!\n", minor);		up(&plugin_lock);		return -EBUSY;	}	ir = &irctls[minor];	if (p->sample_rate) {		ir->jiffies_to_wait = HZ / p->sample_rate;	} else {                /* it means - wait for externeal event in task queue */		ir->jiffies_to_wait = 0;	} 	/* some safety check 8-) */	p->name[sizeof(p->name)-1] = '\0';	ir->bytes_in_key = p->code_length/8 + (p->code_length%8 ? 1 : 0);		/* this simplifies boundary checking during buffer access */	ir->buf_len = BUFLEN - (BUFLEN%ir->bytes_in_key);	ir->features = (p->code_length > 8) ?		       LIRC_CAN_REC_LIRCCODE : LIRC_CAN_REC_CODE;	ir->p = *p;	ir->p.minor = minor;#ifdef LIRC_HAVE_DEVFS	sprintf (name, DEV_LIRC "/%d", ir->p.minor);	ir->devfs_handle = devfs_register(NULL, name, DEVFS_FL_DEFAULT,					  IRCTL_DEV_MAJOR, ir->p.minor,					  S_IFCHR | S_IRUSR | S_IWUSR,					  &fops, NULL);#endif	/* try to fire up polling thread */	ir->t_notify = &tn;	ir->tpid = kernel_thread(lirc_thread, (void*)ir, 0);	if (ir->tpid < 0) {		IRUNLOCK;		up(&plugin_lock);		printk("lirc_dev: lirc_register_plugin:"		       "cannot run poll thread for minor = %d\n", p->minor);		return -ECHILD;	}	down(&tn);	ir->t_notify = NULL;	up(&plugin_lock);	MOD_INC_USE_COUNT;	dprintk("lirc_dev: plugin %s registered at minor number = %d\n",		ir->p.name, ir->p.minor);	return minor;}/* * */int lirc_unregister_plugin(int minor){	struct irctl *ir;

⌨️ 快捷键说明

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