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

📄 lirc_parallel.c

📁 很少见的linux下的红外口的工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/*      $Id: lirc_parallel.c,v 5.15 2002/03/06 12:40:59 lirc Exp $      *//**************************************************************************** ** lirc_parallel.c ********************************************************* **************************************************************************** *  * lirc_parallel - device driver for infra-red signal receiving and *                 transmitting unit built by the author *  * Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de> * *  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 * */ /*********************************************************************** *************************       Includes        *********************** ***********************************************************************/#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <linux/version.h>#if LINUX_VERSION_CODE >= 0x020100 && LINUX_VERSION_CODE < 0x020200#error "--- Sorry, 2.1.x kernels are not supported. ---"#elif LINUX_VERSION_CODE >= 0x020200#define KERNEL_2_2#include <linux/config.h>#endif#if LINUX_VERSION_CODE >= 0x020400#define KERNEL_2_4#endif#ifdef CONFIG_SMP#error "--- Sorry, this driver is not SMP safe. ---"#endif#include <linux/module.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/signal.h>#include <linux/config.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/time.h>#include <linux/mm.h>#include <linux/delay.h>#include <asm/io.h>#include <asm/signal.h>#include <asm/irq.h>#ifdef KERNEL_2_2#include <asm/uaccess.h>#include <linux/poll.h>#include <linux/parport.h>#endif#include "drivers/lirc.h"#include "lirc_parallel.h"#define LIRC_DRIVER_NAME "lirc_parallel"/*********************************************************************** *************************   Globale Variablen   *********************** ***********************************************************************/unsigned int irq = LIRC_IRQ;unsigned int io = LIRC_PORT;#ifdef LIRC_TIMERunsigned int timer = 0;unsigned int default_timer = LIRC_TIMER;#endif#define WBUF_SIZE (256)#define RBUF_SIZE (256) /* this must be a power of 2 larger than 1 */static lirc_t wbuf[WBUF_SIZE];static lirc_t rbuf[RBUF_SIZE];#ifdef KERNEL_2_4DECLARE_WAIT_QUEUE_HEAD(lirc_wait);#elsestatic struct wait_queue *lirc_wait=NULL;#endifunsigned int rptr=0,wptr=0;unsigned int lost_irqs=0;int is_open=0;#ifdef KERNEL_2_2struct parport *pport;struct pardevice *ppdevice;int is_claimed=0;#endif/*********************************************************************** *************************   Interne Funktionen  *********************** ***********************************************************************/unsigned int __inline__ in(int offset){#ifdef KERNEL_2_2	switch(offset)	{	case LIRC_LP_BASE:		return(parport_read_data(pport));	case LIRC_LP_STATUS:		return(parport_read_status(pport));	case LIRC_LP_CONTROL:		return(parport_read_control(pport));	}	return(0); /* make compiler happy */#else	return(inb(io+offset));#endif}void __inline__ out(int offset, int value){#ifdef KERNEL_2_2	switch(offset)	{	case LIRC_LP_BASE:		parport_write_data(pport,value);		break;	case LIRC_LP_CONTROL:		parport_write_control(pport,value);		break;	case LIRC_LP_STATUS:		printk(KERN_INFO "%s: attempt to write to status register\n",		       LIRC_DRIVER_NAME);		break;	}#else	outb(value,io+offset);#endif}unsigned int __inline__ lirc_get_timer(void){	return(in(LIRC_PORT_TIMER)&LIRC_PORT_TIMER_BIT);}unsigned int __inline__  lirc_get_signal(void){	return(in(LIRC_PORT_SIGNAL)&LIRC_PORT_SIGNAL_BIT);}void __inline__ lirc_on(void){	out(LIRC_PORT_DATA,LIRC_PORT_DATA_BIT);}void __inline__ lirc_off(void){	out(LIRC_PORT_DATA,0);}unsigned int init_lirc_timer(void){	struct timeval tv,now;	unsigned int level,newlevel,timeelapsed,newtimer;	int count=0;		do_gettimeofday(&tv);	tv.tv_sec++;                     /* wait max. 1 sec. */	level=lirc_get_timer();	do	{		newlevel=lirc_get_timer();		if(level==0 && newlevel!=0) count++;		level=newlevel;		do_gettimeofday(&now);	}	while(count<1000 && (now.tv_sec<tv.tv_sec 			     || (now.tv_sec==tv.tv_sec 				 && now.tv_usec<tv.tv_usec)));	timeelapsed=((now.tv_sec+1-tv.tv_sec)*1000000		     +(now.tv_usec-tv.tv_usec));	if(count>=1000 && timeelapsed>0)	{		if(default_timer==0)                    /* autodetect timer */		{			newtimer=(1000000*count)/timeelapsed;			printk(KERN_INFO "%s: %u Hz timer detected\n",			       LIRC_DRIVER_NAME,newtimer);			return(newtimer);		}		else		{			newtimer=(1000000*count)/timeelapsed;			if(abs(newtimer-default_timer)>			   default_timer/10) /* bad timer */			{				printk(KERN_NOTICE "%s: bad timer: %u Hz\n",				       LIRC_DRIVER_NAME,newtimer);				printk(KERN_NOTICE "%s: using default timer: "				       "%u Hz\n",				       LIRC_DRIVER_NAME,default_timer);				return(default_timer);			}			else			{				printk(KERN_INFO "%s: %u Hz timer detected\n",				       LIRC_DRIVER_NAME,newtimer);				return(newtimer); /* use detected value */			}		}	}	else	{		printk(KERN_NOTICE "%s: no timer detected\n",LIRC_DRIVER_NAME);		return(0);	}}#ifdef KERNEL_2_2int lirc_claim(void){	if(parport_claim(ppdevice)!=0)	{		printk(KERN_WARNING "%s: could not claim port\n",		       LIRC_DRIVER_NAME);		printk(KERN_WARNING "%s: waiting for port becoming available"		       "\n",LIRC_DRIVER_NAME);		if(parport_claim_or_block(ppdevice)<0)		{			printk(KERN_NOTICE "%s: could not claim port, giving"			       " up\n",LIRC_DRIVER_NAME);			return(0);		}	}	out(LIRC_LP_CONTROL,LP_PSELECP|LP_PINITP);	is_claimed=1;	return(1);}#endif/*********************************************************************** *************************   interrupt handler  ************************ ***********************************************************************/static inline void rbuf_write(lirc_t signal){	unsigned int nwptr;	nwptr=(wptr+1) & (RBUF_SIZE-1);	if(nwptr==rptr) /* no new signals will be accepted */	{		lost_irqs++;		printk(KERN_NOTICE "%s: buffer overrun\n",LIRC_DRIVER_NAME);		return;	}		rbuf[wptr]=signal;	wptr=nwptr;}void irq_handler(int i,void *blah,struct pt_regs * regs){	struct timeval tv;	static struct timeval lasttv;	static int init=0;	long signal;	lirc_t data;	unsigned int level,newlevel;	unsigned int timeout;	if(!MOD_IN_USE)		return;#ifdef KERNEL_2_2	if(!is_claimed)	{		return;	}#endif	/* disable interrupt */	/*	  disable_irq(irq);	  out(LIRC_PORT_IRQ,in(LIRC_PORT_IRQ)&(~LP_PINTEN));	*/	if(in(1)&LP_PSELECD)	{		return;	}#ifdef LIRC_TIMER	if(init)	{		do_gettimeofday(&tv);			        signal=tv.tv_sec-lasttv.tv_sec;		if(signal>15)		{			data=PULSE_MASK;  /* really long time */		}		else		{			data=(lirc_t) (signal*1000000+				       tv.tv_usec-lasttv.tv_usec+				       LIRC_SFH506_DELAY);		};		rbuf_write(data); /* space */	}	else	{		if(timer==0) /* wake up; we'll lose this signal 				but it will be garbage if the device 				is turned on anyway			      */		{			timer=init_lirc_timer();			/* enable_irq(irq); */			return;		}		init=1;	}	timeout=timer/10;           /* timeout after 1/10 sec. */	signal=1;	level=lirc_get_timer();	do{		newlevel=lirc_get_timer();		if(level==0 && newlevel!=0) signal++;		level=newlevel;		/* giving up */		if(signal>timeout || (in(1)&LP_PSELECD))		{			signal=0;			printk(KERN_NOTICE "%s: timeout\n",LIRC_DRIVER_NAME);			break;		}	}	while(lirc_get_signal());	if(signal!=0)	{		/* ajust value to usecs */		signal=(long) (((unsigned long long) signal)*1000000)/timer;		if(signal>LIRC_SFH506_DELAY)		{			data=signal-LIRC_SFH506_DELAY;		}		else		{			data=1;		}		rbuf_write(PULSE_BIT|data); /* pulse */	}	do_gettimeofday(&lasttv);#else	/* add your code here */#endif		wake_up_interruptible(&lirc_wait);	/* enable interrupt */	/*	  enable_irq(irq);	  out(LIRC_PORT_IRQ,in(LIRC_PORT_IRQ)|LP_PINTEN);	*/}/*********************************************************************** **************************   file_operations   ************************ ***********************************************************************/#ifdef KERNEL_2_2static loff_t lirc_lseek(struct file *filep,loff_t offset,int orig){	return(-ESPIPE);}#elsestatic int lirc_lseek(struct inode *inode,struct file *filep,off_t offset,int orig){	return(-ESPIPE);}#endif#ifdef KERNEL_2_2static ssize_t lirc_read(struct file *filep,char *buf,size_t n,loff_t *ppos){#elsestatic int lirc_read(struct inode *node,struct file *filep,char *buf,int n){#endif	int result;	int count=0;#ifdef KERNEL_2_4	DECLARE_WAITQUEUE(wait, current);#else	struct wait_queue wait={current,NULL};#endif		if(n%sizeof(lirc_t)) return(-EINVAL);		result=verify_area(VERIFY_WRITE,buf,n);	if(result) return(result);		add_wait_queue(&lirc_wait,&wait);	current->state=TASK_INTERRUPTIBLE;	while(count<n)	{		if(rptr!=wptr)		{#ifdef KERNEL_2_2			copy_to_user(buf+count,(char *) &rbuf[rptr],				     sizeof(lirc_t));#else			memcpy_tofs(buf+count,(char *) &rbuf[rptr],				    sizeof(lirc_t));#endif			rptr=(rptr+1)&(RBUF_SIZE-1);			count+=sizeof(lirc_t);		}		else		{			if(filep->f_flags & O_NONBLOCK)			{				result=-EAGAIN;				break;			}#ifdef KERNEL_2_2			if (signal_pending(current))			{				result=-ERESTARTSYS;				break;			}#else			if(current->signal & ~current->blocked)			{				result=-EINTR;				break;			}#endif

⌨️ 快捷键说明

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