/drivers/staging/lirc/lirc_sir.c
C | 1279 lines | 911 code | 175 blank | 193 comment | 116 complexity | 9b34b3c9cc42ffcc3791b4a0c772cc5e MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- * 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/module.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/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 <linux/io.h>
- #include <asm/irq.h>
- #include <linux/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 <media/lirc.h>
- #include <media/lirc_dev.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 milliseconds = 87ms*/
- #define TIME_CONST (10000000ul/115200ul)
- #endif
- #ifdef LIRC_SIR_ACTISYS_ACT200L
- static void init_act200(void);
- #elif defined(LIRC_SIR_ACTISYS_ACT220L)
- static void init_act220(void);
- #endif
- /*** SA1100 ***/
- #ifdef LIRC_ON_SA1100
- struct 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 */
- static unsigned long pulse_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY);
- /* 1000000/freq-pulse_width */
- static unsigned long space_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY);
- static unsigned int freq = 38000; /* modulation frequency */
- static unsigned int duty_cycle = 50; /* duty cycle of 50% */
- #endif
- #define RBUF_LEN 1024
- #define WBUF_LEN 1024
- #define LIRC_DRIVER_NAME "lirc_sir"
- #define PULSE '['
- #ifndef LIRC_SIR_TEKRAM
- /* 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)
- #ifndef LIRC_ON_SA1100
- #ifndef LIRC_IRQ
- #define LIRC_IRQ 4
- #endif
- #ifndef LIRC_PORT
- /* for external dongles, default to com1 */
- #if defined(LIRC_SIR_ACTISYS_ACT200L) || \
- defined(LIRC_SIR_ACTISYS_ACT220L) || \
- defined(LIRC_SIR_TEKRAM)
- #define LIRC_PORT 0x3f8
- #else
- /* onboard sir ports are typically com3 */
- #define LIRC_PORT 0x3e8
- #endif
- #endif
- static int io = LIRC_PORT;
- static int irq = LIRC_IRQ;
- static int threshold = 3;
- #endif
- static DEFINE_SPINLOCK(timer_lock);
- 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;
- static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue);
- static DEFINE_SPINLOCK(hardware_lock);
- static int rx_buf[RBUF_LEN];
- static unsigned int rx_tail, rx_head;
- static int debug;
- #define dprintk(fmt, args...) \
- do { \
- if (debug) \
- printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \
- fmt, ## args); \
- } while (0)
- /* SECTION: Prototypes */
- /* Communication with user-space */
- 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 long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
- static void add_read_queue(int flag, unsigned long val);
- static int init_chrdev(void);
- static void drop_chrdev(void);
- /* Hardware */
- static irqreturn_t sir_interrupt(int irq, void *dev_id);
- static void send_space(unsigned long len);
- static void send_pulse(unsigned long len);
- static int init_hardware(void);
- static void drop_hardware(void);
- /* Initialisation */
- static int init_port(void);
- static void drop_port(void);
- #ifdef LIRC_ON_SA1100
- static void on(void)
- {
- PPSR |= PPC_TXD2;
- }
- static void off(void)
- {
- PPSR &= ~PPC_TXD2;
- }
- #else
- static 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)
- #endif
- static 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 unsigned int lirc_poll(struct file *file, poll_table *wait)
- {
- poll_wait(file, &lirc_read_queue, wait);
-