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

📄 lirc_serial.c

📁 很少见的linux下的红外口的工具
💻 C
📖 第 1 页 / 共 3 页
字号:
			soutp(UART_TX,output);			while(!(sinp(UART_LSR) & UART_LSR_THRE));			output=0x7f;			i=0;		}	}	if(i!=0)	{		soutp(UART_TX,output);		while(!(sinp(UART_LSR) & UART_LSR_TEMT));	}	if(i==0)	{		return((-rawbits)*10000/1152);	}	else	{		return((3-i)*3*10000/1152+(-rawbits)*10000/1152);	}}long send_pulse_homebrew(unsigned long length){#       ifdef USE_RDTSC	unsigned long target, start, now;#       else	unsigned long actual, target, d;#       endif	int flag;	if(length<=0) return 0;	if(softcarrier)	{#               ifdef USE_RDTSC				/* Version that uses Pentium rdtsc instruction to                   measure clocks */		/* Get going quick as we can */		rdtscl(start);on();		/* Convert length from microseconds to clocks */		length*=conv_us_to_clocks;		/* And loop till time is up - flipping at right intervals */		now=start;		target=pulse_width;		flag=1;		while((now-start)<length)		{			/* Delay till flip time */			do			{				rdtscl(now);			}			while ((now-start)<target);			/* flip */			if(flag)			{				rdtscl(now);off();				target+=space_width;			}			else			{				rdtscl(now);on();				target+=pulse_width;			}			flag=!flag;		}		rdtscl(now);		return(((now-start)-length)/conv_us_to_clocks);		#               else /* ! USE_RDTSC */				/* here we use fixed point arithmetic, with 8		   fractional bits.  that gets us within 0.1% or so of		   the right average frequency, albeit with some		   jitter in pulse length - Steve */		/* To match 8 fractional bits used for pulse/space                   length */		length<<=8;			actual=target=0; flag=0;		while(actual<length)		{			if(flag)			{				off();				target+=space_width;			}			else			{				on();				target+=pulse_width;			}			d=(target-actual-LIRC_SERIAL_TRANSMITTER_LATENCY+128)>>8;			/* Note - we've checked in ioctl that the pulse/space			   widths are big enough so that d is > 0 */			udelay(d);			actual+=(d<<8)+LIRC_SERIAL_TRANSMITTER_LATENCY;			flag=!flag;		}		return((actual-length)>>8);#               endif /* USE_RDTSC */	}	else	{		on();		safe_udelay(length);		return(0);	}}void send_space_irdeo(long length){	if(length<=0) return;	safe_udelay(length);}void send_space_homebrew(long length){        off();	if(length<=0) return;	safe_udelay(length);}static void inline rbwrite(lirc_t l){	unsigned int nrbt;	nrbt=(rbt+1) & (RBUF_LEN-1);	if(nrbt==rbh)      /* no new signals will be accepted */	{#               ifdef DEBUG		printk(KERN_WARNING  LIRC_DRIVER_NAME  ": Buffer overrun\n");#               endif		return;	}	rbuf[rbt]=l;	rbt=nrbt;}static void inline frbwrite(lirc_t l){	/* simple noise filter */	static lirc_t pulse=0L,space=0L;	static unsigned int ptr=0;		if(ptr>0 && (l&PULSE_BIT))	{		pulse+=l&PULSE_MASK;		if(pulse>250)		{			rbwrite(space);			rbwrite(pulse|PULSE_BIT);			ptr=0;			pulse=0;		}		return;	}	if(!(l&PULSE_BIT))	{		if(ptr==0)		{			if(l>20000)			{				space=l;				ptr++;				return;			}		}		else		{			if(l>20000)			{				space+=pulse;				if(space>PULSE_MASK) space=PULSE_MASK;				space+=l;				if(space>PULSE_MASK) space=PULSE_MASK;				pulse=0;				return;			}			rbwrite(space);			rbwrite(pulse|PULSE_BIT);			ptr=0;			pulse=0;		}	}	rbwrite(l);}void irq_handler(int i, void *blah, struct pt_regs *regs){	struct timeval tv;	int status,counter,dcd;	long deltv;	lirc_t data;		counter=0;	do{		counter++;		status=sinp(UART_MSR);		if(counter>RS_ISR_PASS_LIMIT)		{			printk(KERN_WARNING LIRC_DRIVER_NAME ": AIEEEE: "			       "We're caught!\n");			break;		}		if((status&hardware[type].signal_pin_change) && sense!=-1)		{			/* get current time */			do_gettimeofday(&tv);						/* New mode, written by Trent Piepho 			   <xyzzy@u.washington.edu>. */						/* The old format was not very portable.			   We now use the type lirc_t to pass pulses			   and spaces to user space.			   			   If PULSE_BIT is set a pulse has been			   received, otherwise a space has been			   received.  The driver needs to know if your			   receiver is active high or active low, or			   the space/pulse sense could be			   inverted. The bits denoted by PULSE_MASK are			   the length in microseconds. Lengths greater			   than or equal to 16 seconds are clamped to			   PULSE_MASK.  All other bits are unused.			   This is a much simpler interface for user			   programs, as well as eliminating "out of			   phase" errors with space/pulse			   autodetection. */			/* calculate time since last interrupt in			   microseconds */			dcd=(status & hardware[type].signal_pin) ? 1:0;						deltv=tv.tv_sec-lasttv.tv_sec;			if(deltv>15) 			{#ifdef DEBUG				printk(KERN_WARNING LIRC_DRIVER_NAME				       ": AIEEEE: %d %d %lx %lx %lx %lx\n",				       dcd,sense,				       tv.tv_sec,lasttv.tv_sec,				       tv.tv_usec,lasttv.tv_usec);#endif				data=PULSE_MASK; /* really long time */				if(!(dcd^sense)) /* sanity check */				{				        /* detecting pulse while this					   MUST be a space! */				        sense=sense ? 0:1;				}			}			else			{				data=(lirc_t) (deltv*1000000+					       tv.tv_usec-					       lasttv.tv_usec);			};			if(tv.tv_sec<lasttv.tv_sec ||			   (tv.tv_sec==lasttv.tv_sec &&			    tv.tv_usec<lasttv.tv_usec))			{				printk(KERN_WARNING LIRC_DRIVER_NAME				       ": AIEEEE: your clock just jumped "				       "backwards\n");				printk(KERN_WARNING LIRC_DRIVER_NAME				       ": %d %d %lx %lx %lx %lx\n",				       dcd,sense,				       tv.tv_sec,lasttv.tv_sec,				       tv.tv_usec,lasttv.tv_usec);				data=PULSE_MASK;			}			frbwrite(dcd^sense ? data : (data|PULSE_BIT));			lasttv=tv;			wake_up_interruptible(&lirc_wait_in);		}	} while(!(sinp(UART_IIR) & UART_IIR_NO_INT)); /* still pending ? */}#ifdef KERNEL_2_3static DECLARE_WAIT_QUEUE_HEAD(power_supply_queue);#elsestatic struct wait_queue *power_supply_queue = NULL;#endif#ifndef KERNEL_2_1static struct timer_list power_supply_timer;static void power_supply_up(unsigned long ignored){        wake_up(&power_supply_queue);}#endifstatic int init_port(void){	unsigned long flags;        /* Check io region*/	        if((check_region(io,8))==-EBUSY)	{#if 0		/* this is the correct behaviour but many people have                   the serial driver compiled into the kernel... */		printk(KERN_ERR  LIRC_DRIVER_NAME  		       ": port %04x already in use\n", io);		return(-EBUSY);#else		printk(KERN_ERR LIRC_DRIVER_NAME  		       ": port %04x already in use, proceeding anyway\n", io);		printk(KERN_WARNING LIRC_DRIVER_NAME  		       ": compile the serial port driver as module and\n");		printk(KERN_WARNING LIRC_DRIVER_NAME  		       ": make sure this module is loaded first\n");		release_region(io,8);#endif	}		/* Reserve io region. */	request_region(io, 8, LIRC_DRIVER_NAME);		save_flags(flags);cli();		/* Set DLAB 0. */	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));		/* First of all, disable all interrupts */	soutp(UART_IER, sinp(UART_IER)&	      (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));		/* Clear registers. */	sinp(UART_LSR);	sinp(UART_RX);	sinp(UART_IIR);	sinp(UART_MSR);		/* Set line for power source */	soutp(UART_MCR, hardware[type].off);		/* Clear registers again to be sure. */	sinp(UART_LSR);	sinp(UART_RX);	sinp(UART_IIR);	sinp(UART_MSR);	switch(hardware[type].type)	{	case LIRC_IRDEO:	case LIRC_IRDEO_REMOTE:		/* setup port to 7N1 @ 115200 Baud */		/* 7N1+start = 9 bits at 115200 ~ 3 bits at 38kHz */				/* Set DLAB 1. */		soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);		/* Set divisor to 1 => 115200 Baud */		soutp(UART_DLM,0);		soutp(UART_DLL,1);		/* Set DLAB 0 +  7N1 */		soutp(UART_LCR,UART_LCR_WLEN7);		/* THR interrupt already disabled at this point */		break;	default:		break;	}		restore_flags(flags);	#       ifdef USE_RDTSC	/* Initialize pulse/space widths */	calc_pulse_lengths_in_clocks();#       endif	/* If pin is high, then this must be an active low receiver. */	if(sense==-1)	{		/* wait 1 sec for the power supply */		#               ifdef KERNEL_2_1		sleep_on_timeout(&power_supply_queue,HZ);#               else		init_timer(&power_supply_timer);		power_supply_timer.expires=jiffies+HZ;		power_supply_timer.data=(unsigned long) current;		power_supply_timer.function=power_supply_up;		add_timer(&power_supply_timer);		sleep_on(&power_supply_queue);		del_timer(&power_supply_timer);#               endif				sense=(sinp(UART_MSR) & hardware[type].signal_pin) ? 1:0;		printk(KERN_INFO  LIRC_DRIVER_NAME  ": auto-detected active "		       "%s receiver\n",sense ? "low":"high");	}	else	{		printk(KERN_INFO  LIRC_DRIVER_NAME  ": Manually using active "		       "%s receiver\n",sense ? "low":"high");	};		return 0;}static int lirc_open(struct inode *ino, struct file *filep){	int result;	unsigned long flags;	#       ifdef KERNEL_2_1	spin_lock(&lirc_lock);#       endif	if(MOD_IN_USE)	{#               ifdef KERNEL_2_1		spin_unlock(&lirc_lock);#               endif		return -EBUSY;	}		/* initialize timestamp */	do_gettimeofday(&lasttv);		result=request_irq(irq,irq_handler,SA_INTERRUPT,LIRC_DRIVER_NAME,NULL);	switch(result)	{	case -EBUSY:		printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq);#               ifdef KERNEL_2_1		spin_unlock(&lirc_lock);#               endif		return -EBUSY;	case -EINVAL:		printk(KERN_ERR LIRC_DRIVER_NAME		       ": Bad irq number or handler\n");#               ifdef KERNEL_2_1		spin_unlock(&lirc_lock);#               endif		return -EINVAL;	default:#               ifdef DEBUG

⌨️ 快捷键说明

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