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

📄 lirc_sir.c

📁 很少见的linux下的红外口的工具
💻 C
📖 第 1 页 / 共 3 页
字号:
		value = LIRC_MODE_MODE2;#endif	switch (cmd) {	case LIRC_GET_FEATURES:	case LIRC_GET_SEND_MODE:	case LIRC_GET_REC_MODE:#ifdef KERNEL_2_0		retval = verify_area(VERIFY_WRITE, (unsigned long *) arg,			sizeof(unsigned long));		if (retval)			break;#else		retval =#endif		put_user(value, (unsigned long *) arg);		break;	case LIRC_SET_SEND_MODE:	case LIRC_SET_REC_MODE:#ifdef KERNEL_2_0		retval = verify_area(VERIFY_READ, (unsigned long *) arg,			sizeof(unsigned long));		if (retval)			break;		value = get_user((unsigned long *) arg);#else		retval = get_user(value, (unsigned long *) arg);#endif		break;#ifdef LIRC_ON_SA1100	case LIRC_SET_SEND_DUTY_CYCLE:#               ifdef KERNEL_2_1		retval=get_user(ivalue,(unsigned int *) arg);		if(retval) return(retval);#               else		retval=verify_area(VERIFY_READ,(unsigned int *) arg,				   sizeof(unsigned int));		if(result) return(result);		ivalue=get_user((unsigned int *) arg);#               endif		if(ivalue<=0 || ivalue>100) return(-EINVAL);		/* (ivalue/100)*(1000000/freq) */		duty_cycle=ivalue;		pulse_width=(unsigned long) duty_cycle*10000/freq;		space_width=(unsigned long) 1000000L/freq-pulse_width;		if(pulse_width>=LIRC_ON_SA1100_TRANSMITTER_LATENCY)			pulse_width-=LIRC_ON_SA1100_TRANSMITTER_LATENCY;		if(space_width>=LIRC_ON_SA1100_TRANSMITTER_LATENCY)			space_width-=LIRC_ON_SA1100_TRANSMITTER_LATENCY;		break;	case LIRC_SET_SEND_CARRIER:#               ifdef KERNEL_2_1		retval=get_user(ivalue,(unsigned int *) arg);		if(retval) return(retval);#               else		retval=verify_area(VERIFY_READ,(unsigned int *) arg,				   sizeof(unsigned int));		if(retval) return(retval);		ivalue=get_user((unsigned int *) arg);#               endif		if(ivalue>500000 || ivalue<20000) return(-EINVAL);		freq=ivalue;		pulse_width=(unsigned long) duty_cycle*10000/freq;		space_width=(unsigned long) 1000000L/freq-pulse_width;		if(pulse_width>=LIRC_ON_SA1100_TRANSMITTER_LATENCY)			pulse_width-=LIRC_ON_SA1100_TRANSMITTER_LATENCY;		if(space_width>=LIRC_ON_SA1100_TRANSMITTER_LATENCY)			space_width-=LIRC_ON_SA1100_TRANSMITTER_LATENCY;		break;#endif	default:		retval = -ENOIOCTLCMD;	}		if (retval)		return retval;	#ifdef LIRC_SIR_TEKRAM	if (cmd == LIRC_SET_REC_MODE) {		if (value != LIRC_MODE_MODE2)			retval = -ENOSYS;	} else if (cmd == LIRC_SET_SEND_MODE) {		retval = -ENOSYS;	}#else	if (cmd == LIRC_SET_REC_MODE) {		if (value != LIRC_MODE_MODE2)			retval = -ENOSYS;	} else if (cmd == LIRC_SET_SEND_MODE) {		if (value != LIRC_MODE_PULSE)			retval = -ENOSYS;	}#endif	return retval;}static void add_read_queue(int flag, unsigned long val){	unsigned int new_rx_tail;	lirc_t newval;#ifdef DEBUG_SIGNAL	printk(KERN_DEBUG LIRC_DRIVER_NAME		": add flag %d with val %lu\n",		flag,val);#endif	newval = val & PULSE_MASK;	/* statistically pulses are ~TIME_CONST/2 too long: we could	   maybe make this more exactly but this is good enough */	if(flag) /* pulse */	{		if(newval>TIME_CONST/2)		{			newval-=TIME_CONST/2;		}		else /* should not ever happen */		{			newval=1;		}		newval|=PULSE_BIT;	}	else	{		newval+=TIME_CONST/2;	}	new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1);	if (new_rx_tail == rx_head) {#               ifdef DEBUG		printk(KERN_WARNING LIRC_DRIVER_NAME ": Buffer overrun.\n");#               endif		return;	}	rx_buf[rx_tail] = newval;	rx_tail = new_rx_tail;	wake_up_interruptible(&lirc_read_queue);}static struct file_operations lirc_fops ={	read:    lirc_read,	write:   lirc_write,#ifdef KERNEL_2_1	poll:    lirc_poll,#else	select:  lirc_select,#endif	ioctl:   lirc_ioctl,	open:    lirc_open,	release: lirc_close,};#ifdef MODULEint init_chrdev(void){	int retval;	retval = register_chrdev(major, LIRC_DRIVER_NAME, &lirc_fops);	if (retval < 0) {		printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n");		return retval;	}	return 0;}static void drop_chrdev(void){	unregister_chrdev(major, LIRC_DRIVER_NAME);}#endif/* SECTION: Hardware */static long delta(struct timeval * tv1, struct timeval * tv2){	unsigned long deltv;		deltv = tv2->tv_sec - tv1->tv_sec;	if (deltv > 15)		deltv = 0xFFFFFF;	else		deltv = deltv*1000000 +			tv2->tv_usec -			tv1->tv_usec;	return deltv;}static void sir_timeout(unsigned long data) {	/* if last received signal was a pulse, but receiving stopped	   within the 9 bit frame, we need to finish this pulse and	   simulate a signal change to from pulse to space. Otherwise	   upper layers will receive two sequences next time. */		unsigned long flags;	unsigned long pulse_end;		/* avoid interference with interrupt */ 	spin_lock_irqsave(&timer_lock, flags);	if (last_value)	{#ifndef LIRC_ON_SA1100		/* clear unread bits in UART and restart */		outb(UART_FCR_CLEAR_RCVR, io + UART_FCR);#endif		/* determine 'virtual' pulse end: */	 	pulse_end = delta(&last_tv, &last_intr_tv);#ifdef DEBUG_SIGNAL		printk(KERN_DEBUG LIRC_DRIVER_NAME			": timeout add %d for %lu usec\n",last_value,pulse_end);#endif		add_read_queue(last_value,pulse_end);		last_value = 0;		last_tv=last_intr_tv;	}	spin_unlock_irqrestore(&timer_lock, flags);		}static void sir_interrupt(int irq, void * dev_id, struct pt_regs * regs){	unsigned char data;	struct timeval curr_tv;	static unsigned long deltv;#ifdef LIRC_ON_SA1100	int status;	static int n=0;		//printk("interrupt\n");	status = Ser2UTSR0;	/*	 * Deal with any receive errors first.  The bytes in error may be	 * the only bytes in the receive FIFO, so we do this first.	 */	while (status & UTSR0_EIF)	{		int bstat;		#ifdef DEBUG		printk("EIF\n");		bstat = Ser2UTSR1;				if (bstat & UTSR1_FRE)			printk("frame error\n");		if (bstat & UTSR1_ROR)			printk("receive fifo overrun\n");		if(bstat&UTSR1_PRE)			printk("parity error\n");#endif				bstat = Ser2UTDR;		n++;		status = Ser2UTSR0;	}	if (status & (UTSR0_RFS | UTSR0_RID))	{		do_gettimeofday(&curr_tv);		deltv = delta(&last_tv, &curr_tv);		do		{#ifdef DEBUG_SIGNAL			printk(KERN_DEBUG LIRC_DRIVER_NAME": t %lu , d %d\n",			       deltintrtv,(int)data);#endif			data=Ser2UTDR;			//printk("data: %d\n",data);			n++;		}		while(status&UTSR0_RID && /* do not empty fifo in                                             order to get UTSR0_RID in                                             any case */		      Ser2UTSR1 & UTSR1_RNE); /* data ready */				if(status&UTSR0_RID)		{			//printk("add\n");			add_read_queue(0,deltv-n*TIME_CONST); /*space*/			add_read_queue(1,n*TIME_CONST); /*pulse*/			n=0;			last_tv=curr_tv;		}	}	if (status & UTSR0_TFS) {		printk("transmit fifo not full, shouldn't ever happen\n");	}	/*	 * We must clear certain bits.	 */	status &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);	if (status)		Ser2UTSR0 = status;#else	unsigned long deltintrtv;	unsigned long flags;	int iir, lsr;	while ((iir = inb(io + UART_IIR) & UART_IIR_ID)) {		switch (iir&UART_IIR_ID) { /* FIXME toto treba preriedit */		case UART_IIR_MSI:			(void) inb(io + UART_MSR);			break;		case UART_IIR_RLSI:			(void) inb(io + UART_LSR);			break;		case UART_IIR_THRI:#if 0			if (lsr & UART_LSR_THRE) /* FIFO is empty */				outb(data, io + UART_TX)#endif			break;		case UART_IIR_RDI:			/* avoid interference with timer */		 	spin_lock_irqsave(&timer_lock, flags);			do			{				del_timer(&timerlist);				data = inb(io + UART_RX);				do_gettimeofday(&curr_tv);				deltv = delta(&last_tv, &curr_tv);				deltintrtv = delta(&last_intr_tv, &curr_tv);#ifdef DEBUG_SIGNAL				printk(KERN_DEBUG LIRC_DRIVER_NAME": t %lu , d %d\n",deltintrtv,(int)data);#endif				/* if nothing came in last 2 cycles,				   it was gap */				if (deltintrtv > TIME_CONST * 2) {					if (last_value) {#ifdef DEBUG_SIGNAL						printk(KERN_DEBUG LIRC_DRIVER_NAME ": GAP\n");#endif						/* simulate signal change */						add_read_queue(last_value,							       deltv-							       deltintrtv);						last_value = 0;						last_tv.tv_sec = last_intr_tv.tv_sec;						last_tv.tv_usec = last_intr_tv.tv_usec;						deltv = deltintrtv;					}				}				data = 1;				if (data ^ last_value) {					/* deltintrtv > 2*TIME_CONST,                                           remember ? */					/* the other case is timeout */					add_read_queue(last_value,						       deltv-TIME_CONST);					last_value = data;					last_tv = curr_tv;					if(last_tv.tv_usec>=TIME_CONST)					{						last_tv.tv_usec-=TIME_CONST;					}					else					{						last_tv.tv_sec--;						last_tv.tv_usec+=1000000-							TIME_CONST;					}				}				last_intr_tv = curr_tv;				if (data)				{					/* start timer for end of sequence detection */					timerlist.expires = jiffies + SIR_TIMEOUT;					add_timer(&timerlist);				}			}			while ((lsr = inb(io + UART_LSR))				& UART_LSR_DR); /* data ready */			spin_unlock_irqrestore(&timer_lock, flags);			break;		default:			break;		}	}#endif}#ifdef LIRC_ON_SA1100void send_pulse(unsigned long length){	unsigned long k,delay;	int flag;	if(length==0) return;	/* this won't give us the carrier frequency we really want	   due to integer arithmetic, but we can accept this inaccuracy */	for(k=flag=0;k<length;k+=delay,flag=!flag)	{		if(flag)		{			off();			delay=space_width;		}		else		{			on();			delay=pulse_width;		}		safe_udelay(delay);	}	off();}void send_space(unsigned long length){	if(length==0) return;	off();	safe_udelay(length);}#elif defined(LIRC_SIR_TEKRAM)#elsestatic void send_space(unsigned long len){	safe_udelay(len);}static void send_pulse(unsigned long len){	long bytes_out = len / TIME_CONST;	long time_left;	if (!bytes_out)		bytes_out++;	time_left = (long)len - (long)bytes_out * (long)TIME_CONST;	while (--bytes_out) {		outb(PULSE, io + UART_TX);		/* FIXME treba seriozne cakanie z drivers/char/serial.c */		while (!(inb(io + UART_LSR) & UART_LSR_THRE));	}#if 0	if (time_left > 0)		safe_udelay(time_left);#endif}#endif#ifdef CONFIG_SA1100_COLLIEstatic inline int sa1100_irda_set_power_collie(int state){	if (state) {		/*		 *  0 - off		 *  1 - short range, lowest power		 *  2 - medium range, medium power		 *  3 - maximum range, high power		 */		ucb1200_set_io_direction(TC35143_GPIO_IR_ON,					 TC35143_IODIR_OUTPUT);		ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_LOW);		udelay(100);	}	else {		/* OFF */		ucb1200_set_io_direction(TC35143_GPIO_IR_ON,

⌨️ 快捷键说明

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