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

📄 lirc_it87.c

📁 很少见的linux下的红外口的工具
💻 C
📖 第 1 页 / 共 2 页
字号:
		       "iir: 0x%x fifo: 0x%x\n", iir, lsr);#endif			/* avoid interference with timer */		spin_lock_irqsave(&timer_lock, flags);		spin_lock_irqsave(&hardware_lock, hw_flags);		do {			del_timer(&timerlist);			data = inb(io + IT87_CIR_DR);#ifdef DEBUG_SIGNAL			printk(KERN_DEBUG LIRC_DRIVER_NAME			       ": data=%.2x\n",			       data);#endif			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 + IT87_TIMEOUT;				add_timer(&timerlist);			}			outb((inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN) |			     IT87_CIR_RCR_RXACT,			     io + IT87_CIR_RCR);			if (it87_RXEN_mask) {				outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, 				     io + IT87_CIR_RCR);			}			fifo--;		}		while (fifo != 0);		spin_unlock_irqrestore(&hardware_lock, hw_flags);		spin_unlock_irqrestore(&timer_lock, flags);		break;	default:		/* not our irq */#ifdef DEBUG_SIGNAL		printk(KERN_DEBUG LIRC_DRIVER_NAME		       "unknown IRQ (shouldn't happen) !!\n");#endif		break;	}}static void send_it87(unsigned long len,		      unsigned long stime,		      unsigned char send_byte,		      unsigned int count_bits){        long count = len / stime;	long time_left = 0;	static unsigned char byte_out = 0;#ifdef DEBUG_SIGNAL	printk(KERN_DEBUG LIRC_DRIVER_NAME	       "send_it87: len=%ld, sb=%d\n",	       len,	       send_byte);#endif	time_left = (long)len - (long)count * (long)stime;	count += ((2 * time_left) / stime);	while (count) {		long i=0;		for (i=0; i<count_bits; i++) {			byte_out = (byte_out << 1) | (send_byte & 1);			it87_bits_in_byte_out++;		}		if (it87_bits_in_byte_out == 8) {#ifdef DEBUG_SIGNAL			printk(KERN_DEBUG LIRC_DRIVER_NAME			       "out=0x%x, tsr_txfbc: 0x%x\n",			       byte_out,			       inb(io + IT87_CIR_TSR) &			       IT87_CIR_TSR_TXFBC);#endif			while ((inb(io + IT87_CIR_TSR) &				IT87_CIR_TSR_TXFBC) >= IT87_CIR_FIFO_SIZE);			{				unsigned long hw_flags;				spin_lock_irqsave(&hardware_lock, hw_flags);				outb(byte_out, io + IT87_CIR_DR);				spin_unlock_irqrestore(&hardware_lock, hw_flags);			}			it87_bits_in_byte_out = 0;			it87_send_counter++;			byte_out = 0;		}		count--;	}}/*maybe: exchange space and pulse becauseit8705 only modulates 0-bits*/static void send_space(unsigned long len){	send_it87(len,		  TIME_CONST,		  IT87_CIR_SPACE,		  IT87_CIR_BAUDRATE_DIVISOR);}static void send_pulse(unsigned long len){	send_it87(len,		  TIME_CONST,		  IT87_CIR_PULSE,		  IT87_CIR_BAUDRATE_DIVISOR);}static void init_send(){	unsigned long flags;	spin_lock_irqsave(&hardware_lock, flags);	/* RXEN=0: receiver disable */	it87_RXEN_mask = 0;	outb(inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN,	     io + IT87_CIR_RCR);	spin_unlock_irqrestore(&hardware_lock, flags);	it87_bits_in_byte_out = 0;	it87_send_counter = 0;}static void terminate_send(unsigned long len){	unsigned long flags;	unsigned long last = 0;	last = it87_send_counter;	/* make sure all necessary data has been sent */	while (last == it87_send_counter)		send_space(len);	/* wait until all data sent */	while ((inb(io + IT87_CIR_TSR) & IT87_CIR_TSR_TXFBC) != 0);	/* then reenable receiver */	spin_lock_irqsave(&hardware_lock, flags);	it87_RXEN_mask = IT87_CIR_RCR_RXEN;	outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN,	     io + IT87_CIR_RCR);	spin_unlock_irqrestore(&hardware_lock, flags);}static int init_hardware(void){	unsigned long flags;	unsigned char it87_rcr = 0;		spin_lock_irqsave(&hardware_lock, flags);	/* init cir-port */	/* enable r/w-access to Baudrate-Register */	outb(IT87_CIR_IER_BR, io + IT87_CIR_IER);	outb(IT87_CIR_BAUDRATE_DIVISOR % 0x100, io+IT87_CIR_BDLR);	outb(IT87_CIR_BAUDRATE_DIVISOR / 0x100, io+IT87_CIR_BDHR);	/* Baudrate Register off, define IRQs: Input only */	outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RDAIE, io + IT87_CIR_IER);	/* RX: HCFS=0, RXDCR = 001b (35,6..40,3 kHz), RXEN=1 */	it87_rcr = (IT87_CIR_RCR_RXEN & it87_RXEN_mask) | 0x1;	if (it87_enable_demodulator)		it87_rcr |= IT87_CIR_RCR_RXEND;	outb(it87_rcr, io + IT87_CIR_RCR);	/* TX: 38kHz, 13,3us (pulse-width */	outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x06,	     io + IT87_CIR_TCR2);	spin_unlock_irqrestore(&hardware_lock, flags);	return 0;}static void drop_hardware(void){	unsigned long flags;		spin_lock_irqsave(&hardware_lock, flags);	disable_irq(irq);	/* receiver disable */	it87_RXEN_mask = 0;	outb(0x1, io + IT87_CIR_RCR);	/* turn off irqs */	outb(0, io + IT87_CIR_IER);	/* fifo clear */        outb(IT87_CIR_TCR1_FIFOCLR, io+IT87_CIR_TCR1);        /* reset */        outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER);	enable_irq(irq);	spin_unlock_irqrestore(&hardware_lock, flags);}static unsigned char it87_read(unsigned char port){	outb(port, IT87_ADRPORT);	return inb(IT87_DATAPORT);}static void it87_write(unsigned char port,		       unsigned char data){	outb(port, IT87_ADRPORT);	outb(data, IT87_DATAPORT);}/* SECTION: Initialisation */static int init_port(void){	int retval = 0;		unsigned char init_bytes[4] = {IT87_INIT};	unsigned char it87_chipid = 0;	unsigned char ldn = 0;	unsigned int  it87_io = 0;	unsigned int  it87_irq = 0;		/* Enter MB PnP Mode */	outb(init_bytes[0], IT87_ADRPORT);	outb(init_bytes[1], IT87_ADRPORT);	outb(init_bytes[2], IT87_ADRPORT);	outb(init_bytes[3], IT87_ADRPORT);		/* 8712 or 8705 ? */	it87_chipid = it87_read(IT87_CHIP_ID1);	if (it87_chipid != 0x87) {		retval = -ENXIO;		return retval;	}	it87_chipid = it87_read(IT87_CHIP_ID2);	if ((it87_chipid != 0x12) && (it87_chipid != 0x05)) {		printk(KERN_INFO LIRC_DRIVER_NAME		       ": no IT8705/12 found, exiting..\n");		retval = -ENXIO;		return retval;	}	printk(KERN_INFO LIRC_DRIVER_NAME	       ": found IT87%.2x.\n",	       it87_chipid);	/* get I/O-Port and IRQ */	if (it87_chipid == 0x12)		ldn = IT8712_CIR_LDN;	else		ldn = IT8705_CIR_LDN;	it87_write(IT87_LDN, ldn);		it87_io = it87_read(IT87_CIR_BASE_MSB) * 256 +		it87_read(IT87_CIR_BASE_LSB);	if (it87_io == 0) {		if (io == 0)			io = IT87_CIR_DEFAULT_IOBASE;		printk(KERN_INFO LIRC_DRIVER_NAME		       ": set default io 0x%x\n",		       io);		it87_write(IT87_CIR_BASE_MSB, io / 0x100);		it87_write(IT87_CIR_BASE_LSB, io % 0x100);	}	else		io = it87_io;		it87_irq = it87_read(IT87_CIR_IRQ);	if (it87_irq == 0) {		if (irq == 0)			irq = IT87_CIR_DEFAULT_IRQ;		printk(KERN_INFO LIRC_DRIVER_NAME		       ": set default irq 0x%x\n",		       irq);		it87_write(IT87_CIR_IRQ, irq);	}	else		irq = it87_irq;		{		unsigned long hw_flags;		spin_lock_irqsave(&hardware_lock, hw_flags);		/* reset */		outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER);		/* fifo clear */		outb(IT87_CIR_TCR1_FIFOCLR |		     /*	     IT87_CIR_TCR1_ILE | */		     IT87_CIR_TCR1_TXRLE |		     IT87_CIR_TCR1_TXENDF, io+IT87_CIR_TCR1);		spin_unlock_irqrestore(&hardware_lock, hw_flags);	}		/* get I/O port access and IRQ line */	retval = check_region(io, 8);	if (retval < 0) {		printk(KERN_ERR LIRC_DRIVER_NAME		       ": i/o port 0x%.4x already in use.\n",		       io);		/* Leaving MB PnP Mode */		it87_write(IT87_CFGCTRL, 0x2);		return retval;	}	/* activate CIR-Device */	it87_write(IT87_CIR_ACT, 0x1);	/* Leaving MB PnP Mode */	it87_write(IT87_CFGCTRL, 0x2);	retval = request_irq(irq, it87_interrupt, 0 /*SA_INTERRUPT*/,			     LIRC_DRIVER_NAME, NULL);	if (retval < 0) {		printk(KERN_ERR LIRC_DRIVER_NAME		       ": IRQ %d already in use.\n",		       irq);		return retval;	}	request_region(io, 8, LIRC_DRIVER_NAME);	printk(KERN_INFO LIRC_DRIVER_NAME	       ": I/O port 0x%.4x, IRQ %d.\n",	       io,	       irq);	init_timer(&timerlist);	timerlist.function = it87_timeout;	timerlist.data = 0xabadcafe;		return 0;}static void drop_port(void){/*        unsigned char init_bytes[4] = {IT87_INIT};         / * Enter MB PnP Mode * /        outb(init_bytes[0], IT87_ADRPORT);        outb(init_bytes[1], IT87_ADRPORT);        outb(init_bytes[2], IT87_ADRPORT);        outb(init_bytes[3], IT87_ADRPORT);        / * deactivate CIR-Device * /        it87_write(IT87_CIR_ACT, 0x0);        / * Leaving MB PnP Mode * /        it87_write(IT87_CFGCTRL, 0x2);*/	del_timer_sync(&timerlist);	free_irq(irq, NULL);	release_region(io, 8);}int init_lirc_it87(void){	int retval;		init_waitqueue_head(&lirc_read_queue);	retval = init_port();	if (retval < 0)		return retval;	init_hardware();	printk(KERN_INFO LIRC_DRIVER_NAME	       ": Installed.\n");	return 0;}#ifdef MODULEMODULE_AUTHOR("Hans-G黱ter L黷ke Uphues");MODULE_DESCRIPTION("LIRC driver for ITE IT8712/IT8705 CIR port");MODULE_PARM(io, "i");MODULE_PARM_DESC(io,		 "I/O base address (default: 0x310)");MODULE_PARM(irq, "i");MODULE_PARM_DESC(irq,		 "Interrupt (1,3-12) (default: 7)");MODULE_PARM(it87_enable_demodulator, "i");MODULE_PARM_DESC(it87_enable_demodulator,		 "Receiver demodulator enable/disable (1/0), default: 0");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endifEXPORT_NO_SYMBOLS;int init_module(void){	int retval;		retval=init_chrdev();	if(retval < 0)		return retval;	retval = init_lirc_it87();	if (retval) {		drop_chrdev();		return retval;	}	return 0;}void cleanup_module(void){	drop_hardware();	drop_chrdev();	drop_port();	printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\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 + -