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

📄 lirc_sir.c

📁 很少见的linux下的红外口的工具
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * LIRC SIR driver, (C) 2000 Milan Pikula <www@fornax.sk> * * lirc_sir - Device driver for use with SIR (serial infra red) * mode of IrDA on many notebooks. * *  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 * * * 2000/09/16 Frank Przybylski <mail@frankprzybylski.de> : *  added timeout and relaxed pulse detection, removed gap bug * * 2000/12/15 Christoph Bartelmus <lirc@bartelmus.de> :  *   added support for Tekram Irmate 210 (sending does not work yet, *   kind of disappointing that nobody was able to implement that *   before), *   major clean-up * * 2001/02/27 Christoph Bartelmus <lirc@bartelmus.de> :  *   added support for StrongARM SA1100 embedded microprocessor *   parts cut'n'pasted from sa1100_ir.c (C) 2000 Russell King */#include <linux/version.h>#if LINUX_VERSION_CODE >= 0x020100#define KERNEL_2_1#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)#define KERNEL_2_3#endif#else#define KERNEL_2_0#endif#include <linux/module.h>#ifdef HAVE_CONFIG_H# include <config.h>#endif #include <linux/config.h>#if !defined(LIRC_ON_SA1100) && !defined(CONFIG_SERIAL_MODULE)#warning "******************************************"#warning " Your serial port driver is compiled into "#warning " the kernel. You will have to release the "#warning " port you want to use for LIRC with:      "#warning "    setserial /dev/ttySx uart none        "#warning "******************************************"#endif#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>#ifdef KERNEL_2_1#include <linux/poll.h>#endif#include <asm/system.h>#include <asm/segment.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/fcntl.h>#ifdef LIRC_ON_SA1100#include <asm/hardware.h>#ifdef CONFIG_SA1100_COLLIE#include <asm/arch/tc35143.h>#include <asm/ucb1200.h>#endif#endif#include <linux/timer.h>#include "drivers/lirc.h"/* SECTION: Definitions *//**************************** Tekram dongle ***************************/#ifdef LIRC_SIR_TEKRAM/* stolen from kernel source *//* definitions for Tekram dongle */#define TEKRAM_115200 0x00#define TEKRAM_57600  0x01#define TEKRAM_38400  0x02#define TEKRAM_19200  0x03#define TEKRAM_9600   0x04#define TEKRAM_2400   0x08#define TEKRAM_PW 0x10 /* Pulse select bit *//* 10bit * 1s/115200bit in milli seconds = 87ms*/#define TIME_CONST (10000000ul/115200ul)#endif#ifdef LIRC_SIR_ACTISYS_ACT200Lstatic void init_act200(void);#endif/******************************* SA1100 ********************************/#ifdef LIRC_ON_SA1100struct sa1100_ser2_registers{	/* HSSP control register */	unsigned char hscr0;	/* UART registers */	unsigned char utcr0;	unsigned char utcr1;	unsigned char utcr2;	unsigned char utcr3;	unsigned char utcr4;	unsigned char utdr;	unsigned char utsr0;	unsigned char utsr1;} sr;static int irq=IRQ_Ser2ICP;#define LIRC_ON_SA1100_TRANSMITTER_LATENCY 0/* pulse/space ratio of 50/50 */unsigned long pulse_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY);/* 1000000/freq-pulse_width */unsigned long space_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY);unsigned int freq = 38000;      /* modulation frequency */unsigned int duty_cycle = 50;   /* duty cycle of 50% */#endif#define RBUF_LEN 1024#define WBUF_LEN 1024#define LIRC_DRIVER_NAME "lirc_sir"#ifndef LIRC_SIR_TEKRAM#define PULSE '['/* 9bit * 1s/115200bit in milli seconds = 78.125ms*/#define TIME_CONST (9000000ul/115200ul)#endif/* timeout for sequences in jiffies (=5/100s) *//* must be longer than TIME_CONST */#define SIR_TIMEOUT	(HZ*5/100)static int major = LIRC_MAJOR;#ifndef LIRC_ON_SA1100static int io = LIRC_PORT;static int irq = LIRC_IRQ;#endifstatic 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;#ifdef KERNEL_2_3static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue);#elsestatic struct wait_queue * lirc_read_queue = NULL;#endifstatic 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;#ifndef LIRC_SIR_TEKRAMstatic lirc_t tx_buf[WBUF_LEN];#endif/* SECTION: Prototypes *//* Communication with user-space */static int lirc_open(struct inode * inode, struct file * file);#ifdef KERNEL_2_1static int lirc_close(struct inode * inode, struct file *file);static unsigned int lirc_poll(struct file * file, poll_table * wait);#elsestatic void lirc_close(struct inode * inode, struct file *file);static int lirc_select(struct inode * inode, struct file * file,		int type, select_table * wait);#endifstatic 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 sir_interrupt(int irq, void * dev_id, struct pt_regs * regs);#ifndef LIRC_SIR_TEKRAMstatic void send_space(unsigned long len);static void send_pulse(unsigned long len);#endifstatic 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);#ifdef LIRC_ON_SA1100void inline on(void){	PPSR|=PPC_TXD2;}  void inline off(void){	PPSR&=~PPC_TXD2;}#elsestatic inline unsigned int sinp(int offset){	return inb(io + offset);}static inline void soutp(int offset, int value){	outb(value, io + offset);}#endif#ifndef MAX_UDELAY_MS#define MAX_UDELAY_US 5000#else#define MAX_UDELAY_US (MAX_UDELAY_MS*1000)#endifstatic inline void safe_udelay(unsigned long usecs){	while(usecs>MAX_UDELAY_US)	{		udelay(MAX_UDELAY_US);		usecs-=MAX_UDELAY_US;	}	udelay(usecs);}/* 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;}#ifdef KERNEL_2_1static int lirc_close(struct inode * inode, struct file *file)#elsestatic void lirc_close(struct inode * inode, struct file *file)#endif{	MOD_DEC_USE_COUNT;#ifdef KERNEL_2_1	return 0;#endif}#ifdef KERNEL_2_1static 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;}#elsestatic int lirc_select(struct inode * inode, struct file * file,		int type, select_table * wait){	if (type != SEL_IN)		return 0;	if (rx_head != rx_tail)		return 1;	select_wait(&lirc_read_queue, wait);	return 0;}#endifstatic ssize_t lirc_read(struct file * file, char * buf, size_t count,		loff_t * ppos){	int n=0;	int retval = 0;#ifdef KERNEL_2_3	DECLARE_WAITQUEUE(wait,current);#else	struct wait_queue wait={current,NULL};#endif		if(n%sizeof(lirc_t)) return(-EINVAL);		add_wait_queue(&lirc_read_queue,&wait);	current->state=TASK_INTERRUPTIBLE;	while(n<count)	{		if(rx_head!=rx_tail)		{			retval=verify_area(VERIFY_WRITE,					   (void *) buf+n,sizeof(lirc_t));			if (retval)			{				return retval;			}#ifdef KERNEL_2_1			copy_to_user((void *) buf+n,(void *) (rx_buf+rx_head),				     sizeof(lirc_t));#else			memcpy_tofs((void *) buf+n,(void *) (rx_buf+rx_head),				    sizeof(lirc_t));#endif			rx_head=(rx_head+1)&(RBUF_LEN-1);			n+=sizeof(lirc_t);		}		else		{			if(file->f_flags & O_NONBLOCK)			{				retval=-EAGAIN;				break;			}#                       ifdef KERNEL_2_1			if(signal_pending(current))			{				retval=-ERESTARTSYS;				break;			}#                       else			if(current->signal & ~current->blocked)			{				retval=-EINTR;				break;			}#                       endif			schedule();			current->state=TASK_INTERRUPTIBLE;		}	}	remove_wait_queue(&lirc_read_queue,&wait);	current->state=TASK_RUNNING;	return (n ? n : retval);}static ssize_t lirc_write(struct file * file, const char * buf, size_t n, loff_t * pos){	unsigned long flags;#ifdef LIRC_SIR_TEKRAM	return(-EBADF);#else	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);#ifdef LIRC_ON_SA1100	/* disable receiver */	Ser2UTCR3=0;#endif	save_flags(flags);cli();	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++;	}	restore_flags(flags);#ifdef LIRC_ON_SA1100	off();	udelay(1000); /* wait 1ms for IR diode to recover */	Ser2UTCR3=0;	/* clear status register to prevent unwanted interrupts */	Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);	/* enable receiver */	Ser2UTCR3=UTCR3_RXE|UTCR3_RIE;#endif	return n;#endif}static int lirc_ioctl(struct inode *node,struct file *filep,unsigned int cmd,		unsigned long arg){	int retval = 0;	unsigned long value = 0;#ifdef LIRC_ON_SA1100	unsigned int ivalue;#endif#ifdef LIRC_SIR_TEKRAM	if (cmd == LIRC_GET_FEATURES)		value = LIRC_CAN_REC_MODE2;	else if (cmd == LIRC_GET_SEND_MODE)		value = 0;	else if (cmd == LIRC_GET_REC_MODE)		value = LIRC_MODE_MODE2;#elif defined(LIRC_ON_SA1100)	if (cmd == LIRC_GET_FEATURES)		value = LIRC_CAN_SEND_PULSE |			LIRC_CAN_SET_SEND_DUTY_CYCLE |			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;#else	if (cmd == LIRC_GET_FEATURES)		value = LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2;	else if (cmd == LIRC_GET_SEND_MODE)		value = LIRC_MODE_PULSE;	else if (cmd == LIRC_GET_REC_MODE)

⌨️ 快捷键说明

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