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

📄 lirc_it87.c

📁 很少见的linux下的红外口的工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * LIRC driver for ITE IT8712/IT8705 CIR port * * Copyright (C) 2001 Hans-G黱ter L黷ke Uphues <hg_lu@web.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 * * ITE IT8705 and IT8712(not tested) CIR-port support for lirc based * via cut and paste from lirc_sir.c (C) 2000 Milan Pikula * * Attention: Sendmode only tested with debugging logs  * * 2001/02/27 Christoph Bartelmus <lirc@bartelmus.de> : *   reimplemented read function */#include <linux/version.h>#include <linux/module.h>#ifdef HAVE_CONFIG_H# include <config.h>#endif #include <linux/config.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/signal.h>#include <linux/fs.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/serial_reg.h>#include <linux/time.h>#include <linux/string.h>#include <linux/types.h>#include <linux/wait.h>#include <linux/mm.h>#include <linux/delay.h>#include <linux/poll.h>#include <asm/system.h>#include <asm/segment.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/fcntl.h>#include <linux/timer.h>#include "drivers/lirc.h"#include "lirc_it87.h"static unsigned long it87_bits_in_byte_out = 0;static unsigned long it87_send_counter = 0;static unsigned char it87_RXEN_mask = IT87_CIR_RCR_RXEN;#define RBUF_LEN 1024#define WBUF_LEN 1024#define LIRC_DRIVER_NAME "lirc_it87"/* timeout for sequences in jiffies (=5/100s) *//* must be longer than TIME_CONST */#define IT87_TIMEOUT	(HZ*5/100)static int major = LIRC_MAJOR;static int io = IT87_CIR_DEFAULT_IOBASE;static int irq = IT87_CIR_DEFAULT_IRQ;static unsigned char it87_freq = 38; /* kHz *//* receiver demodulator default: off */static unsigned char it87_enable_demodulator = 0;static spinlock_t timer_lock = SPIN_LOCK_UNLOCKED;static struct timer_list timerlist;/* time of last signal change detected */static struct timeval last_tv = {0, 0};/* time of last UART data ready interrupt */static struct timeval last_intr_tv = {0, 0};static int last_value = 0;static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue);static spinlock_t hardware_lock = SPIN_LOCK_UNLOCKED;static spinlock_t dev_lock = SPIN_LOCK_UNLOCKED;static lirc_t rx_buf[RBUF_LEN]; unsigned int rx_tail = 0, rx_head = 0;static lirc_t tx_buf[WBUF_LEN];/* SECTION: Prototypes *//* Communication with user-space */static int lirc_open(struct inode * inode,		     struct file * file);static int lirc_close(struct inode * inode,		      struct file *file);static unsigned int lirc_poll(struct file * file,			      poll_table * wait);static ssize_t lirc_read(struct file * file,			 char * buf,			 size_t count,			 loff_t * ppos);static ssize_t lirc_write(struct file * file,			  const char * buf,			  size_t n,			  loff_t * pos);static int lirc_ioctl(struct inode *node,		      struct file *filep,		      unsigned int cmd,		      unsigned long arg);static void add_read_queue(int flag,			   unsigned long val);#ifdef MODULEstatic int init_chrdev(void);static void drop_chrdev(void);#endif	/* Hardware */static void it87_interrupt(int irq,			   void * dev_id,			   struct pt_regs * regs);static void send_space(unsigned long len);static void send_pulse(unsigned long len);static void init_send(void);static void terminate_send(unsigned long len);static int init_hardware(void);static void drop_hardware(void);	/* Initialisation */static int init_port(void);static void drop_port(void);int init_module(void);void cleanup_module(void);/* SECTION: Communication with user-space */static int lirc_open(struct inode * inode,		     struct file * file){	spin_lock(&dev_lock);	if (MOD_IN_USE) {		spin_unlock(&dev_lock);		return -EBUSY;	}	MOD_INC_USE_COUNT;	spin_unlock(&dev_lock);	return 0;}static int lirc_close(struct inode * inode,		      struct file *file){	MOD_DEC_USE_COUNT;	return 0;}static unsigned int lirc_poll(struct file * file,			      poll_table * wait){	poll_wait(file, &lirc_read_queue, wait);	if (rx_head != rx_tail)		return POLLIN | POLLRDNORM;	return 0;}static ssize_t lirc_read(struct file * file,			 char * buf,			 size_t count,			 loff_t * ppos){	int n=0;	int retval=0;		while(n<count)	{		if(file->f_flags & O_NONBLOCK &&		   rx_head==rx_tail)		{			retval = -EAGAIN;			break;		}		retval=wait_event_interruptible(lirc_read_queue,						rx_head!=rx_tail);		if(retval)		{			break;		}				retval=verify_area(VERIFY_WRITE,(void *) buf+n,				   sizeof(lirc_t));		if (retval)		{			return retval;		}		copy_to_user((void *) buf+n,(void *) (rx_buf+rx_head),			     sizeof(lirc_t));		rx_head=(rx_head+1)&(RBUF_LEN-1);		n+=sizeof(lirc_t);	}	if(n)	{		return n;	}	return retval;}static ssize_t lirc_write(struct file * file,			  const char * buf,			  size_t n,			  loff_t * pos){	int i;	int retval;        if(n%sizeof(lirc_t) || (n/sizeof(lirc_t)) > WBUF_LEN)		return(-EINVAL);	retval = verify_area(VERIFY_READ, buf, n);	if (retval)		return retval;	copy_from_user(tx_buf, buf, n);	i = 0;	n/=sizeof(lirc_t);	init_send();	while (1) {		if (i >= n)			break;		if (tx_buf[i])			send_pulse(tx_buf[i]);		i++;		if (i >= n)			break;		if (tx_buf[i])			send_space(tx_buf[i]);		i++;	}	terminate_send(tx_buf[i-1]);	return n;}static int lirc_ioctl(struct inode *node,		      struct file *filep,		      unsigned int cmd,		      unsigned long arg){	int retval = 0;	unsigned long value = 0;	unsigned int ivalue;	if (cmd == LIRC_GET_FEATURES)		value = LIRC_CAN_SEND_PULSE |			LIRC_CAN_SET_SEND_CARRIER |			LIRC_CAN_REC_MODE2;	else if (cmd == LIRC_GET_SEND_MODE)		value = LIRC_MODE_PULSE;	else if (cmd == LIRC_GET_REC_MODE)		value = LIRC_MODE_MODE2;		switch (cmd) {	case LIRC_GET_FEATURES:	case LIRC_GET_SEND_MODE:	case LIRC_GET_REC_MODE:		retval = put_user(value, (unsigned long *) arg);		break;	case LIRC_SET_SEND_MODE:	case LIRC_SET_REC_MODE:		retval = get_user(value, (unsigned long *) arg);		break;	case LIRC_SET_SEND_CARRIER:		retval=get_user(ivalue,(unsigned int *) arg);		if(retval) return(retval);		ivalue /= 1000;		if (ivalue > IT87_CIR_FREQ_MAX ||		    ivalue < IT87_CIR_FREQ_MIN) return(-EINVAL);		it87_freq = ivalue;		{			unsigned long hw_flags;			spin_lock_irqsave(&hardware_lock, hw_flags);			outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) |			      (it87_freq - IT87_CIR_FREQ_MIN) << 3),			     io + IT87_CIR_TCR2);			spin_unlock_irqrestore(&hardware_lock, hw_flags);#ifdef DEBUG			printk(KERN_DEBUG LIRC_DRIVER_NAME 			       " demodulation frequency: %d kHz\n", it87_freq);#endif		}		break;	default:		retval = -ENOIOCTLCMD;	}		if (retval)		return retval;		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;	}	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,	poll:    lirc_poll,	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 it87_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) {		/* 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 it87_interrupt(int irq,			   void * dev_id,			   struct pt_regs * regs){	unsigned char data;	struct timeval curr_tv;	static unsigned long deltv;	unsigned long deltintrtv;	unsigned long flags, hw_flags;	int iir, lsr;	int fifo = 0;	iir = inb(io + IT87_CIR_IIR);	switch (iir & IT87_CIR_IIR_IID) {	case 0x4:	case 0x6:		lsr = inb(io + IT87_CIR_RSR) & (IT87_CIR_RSR_RXFTO |						    IT87_CIR_RSR_RXFBC);		fifo = lsr & IT87_CIR_RSR_RXFBC;#ifdef DEBUG_SIGNAL		printk(KERN_DEBUG LIRC_DRIVER_NAME

⌨️ 快捷键说明

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