aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/lirc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/lirc')
-rw-r--r--drivers/staging/lirc/Kconfig78
-rw-r--r--drivers/staging/lirc/Makefile14
-rw-r--r--drivers/staging/lirc/TODO8
-rw-r--r--drivers/staging/lirc/TODO.lirc_zilog36
-rw-r--r--drivers/staging/lirc/lirc_bt829.c383
-rw-r--r--drivers/staging/lirc/lirc_ene0100.h169
-rw-r--r--drivers/staging/lirc/lirc_igorplugusb.c577
-rw-r--r--drivers/staging/lirc/lirc_imon.c1058
-rw-r--r--drivers/staging/lirc/lirc_parallel.c755
-rw-r--r--drivers/staging/lirc/lirc_parallel.h26
-rw-r--r--drivers/staging/lirc/lirc_sasem.c939
-rw-r--r--drivers/staging/lirc/lirc_serial.c1317
-rw-r--r--drivers/staging/lirc/lirc_sir.c1286
-rw-r--r--drivers/staging/lirc/lirc_ttusbir.c396
-rw-r--r--drivers/staging/lirc/lirc_zilog.c1678
15 files changed, 0 insertions, 8720 deletions
diff --git a/drivers/staging/lirc/Kconfig b/drivers/staging/lirc/Kconfig
deleted file mode 100644
index 526ec0fc2f0..00000000000
--- a/drivers/staging/lirc/Kconfig
+++ /dev/null
@@ -1,78 +0,0 @@
-#
-# LIRC driver(s) configuration
-#
-menuconfig LIRC_STAGING
- bool "Linux Infrared Remote Control IR receiver/transmitter drivers"
- depends on LIRC
- help
- Say Y here, and all supported Linux Infrared Remote Control IR and
- RF receiver and transmitter drivers will be displayed. When paired
- with a remote control and the lirc daemon, the receiver drivers
- allow control of your Linux system via remote control.
-
-if LIRC_STAGING
-
-config LIRC_BT829
- tristate "BT829 based hardware"
- depends on LIRC && PCI
- help
- Driver for the IR interface on BT829-based hardware
-
-config LIRC_IGORPLUGUSB
- tristate "Igor Cesko's USB IR Receiver"
- depends on LIRC && USB
- help
- Driver for Igor Cesko's USB IR Receiver
-
-config LIRC_IMON
- tristate "Legacy SoundGraph iMON Receiver and Display"
- depends on LIRC && USB
- help
- Driver for the original SoundGraph iMON IR Receiver and Display
-
- Current generation iMON devices use the input layer imon driver.
-
-config LIRC_PARALLEL
- tristate "Homebrew Parallel Port Receiver"
- depends on LIRC && PARPORT
- help
- Driver for Homebrew Parallel Port Receivers
-
-config LIRC_SASEM
- tristate "Sasem USB IR Remote"
- depends on LIRC && USB
- help
- Driver for the Sasem OnAir Remocon-V or Dign HV5 HTPC IR/VFD Module
-
-config LIRC_SERIAL
- tristate "Homebrew Serial Port Receiver"
- depends on LIRC
- help
- Driver for Homebrew Serial Port Receivers
-
-config LIRC_SERIAL_TRANSMITTER
- bool "Serial Port Transmitter"
- default y
- depends on LIRC_SERIAL
- help
- Serial Port Transmitter support
-
-config LIRC_SIR
- tristate "Built-in SIR IrDA port"
- depends on LIRC
- help
- Driver for the SIR IrDA port
-
-config LIRC_TTUSBIR
- tristate "Technotrend USB IR Receiver"
- depends on LIRC && USB
- help
- Driver for the Technotrend USB IR Receiver
-
-config LIRC_ZILOG
- tristate "Zilog/Hauppauge IR Transmitter"
- depends on LIRC && I2C
- help
- Driver for the Zilog/Hauppauge IR Transmitter, found on
- PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards
-endif
diff --git a/drivers/staging/lirc/Makefile b/drivers/staging/lirc/Makefile
deleted file mode 100644
index d76b0fa2af5..00000000000
--- a/drivers/staging/lirc/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# Makefile for the lirc drivers.
-#
-
-# Each configuration option enables a list of files.
-
-obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o
-obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o
-obj-$(CONFIG_LIRC_IMON) += lirc_imon.o
-obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o
-obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o
-obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o
-obj-$(CONFIG_LIRC_SIR) += lirc_sir.o
-obj-$(CONFIG_LIRC_TTUSBIR) += lirc_ttusbir.o
-obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o
diff --git a/drivers/staging/lirc/TODO b/drivers/staging/lirc/TODO
deleted file mode 100644
index b6cb593f55c..00000000000
--- a/drivers/staging/lirc/TODO
+++ /dev/null
@@ -1,8 +0,0 @@
-- All drivers should either be ported to ir-core, or dropped entirely
- (see drivers/media/IR/mceusb.c vs. lirc_mceusb.c in lirc cvs for an
- example of a previously completed port).
-
-Please send patches to:
-Jarod Wilson <jarod@wilsonet.com>
-Greg Kroah-Hartman <greg@kroah.com>
-
diff --git a/drivers/staging/lirc/TODO.lirc_zilog b/drivers/staging/lirc/TODO.lirc_zilog
deleted file mode 100644
index a97800a8e12..00000000000
--- a/drivers/staging/lirc/TODO.lirc_zilog
+++ /dev/null
@@ -1,36 +0,0 @@
-1. Both ir-kbd-i2c and lirc_zilog provide support for RX events for
-the chips supported by lirc_zilog. Before moving lirc_zilog out of staging:
-
-a. ir-kbd-i2c needs a module parameter added to allow the user to tell
- ir-kbd-i2c to ignore Z8 IR units.
-
-b. lirc_zilog should provide Rx key presses to the rc core like ir-kbd-i2c
- does.
-
-
-2. lirc_zilog module ref-counting need examination. It has not been
-verified that cdev and lirc_dev will take the proper module references on
-lirc_zilog to prevent removal of lirc_zilog when the /dev/lircN device node
-is open.
-
-(The good news is ref-counting of lirc_zilog internal structures appears to be
-complete. Testing has shown the cx18 module can be unloaded out from under
-irw + lircd + lirc_dev, with the /dev/lirc0 device node open, with no adverse
-effects. The cx18 module could then be reloaded and irw properly began
-receiving button presses again and ir_send worked without error.)
-
-
-3. Bridge drivers, if able, should provide a chip reset() callback
-to lirc_zilog via struct IR_i2c_init_data. cx18 and ivtv already have routines
-to perform Z8 chip resets via GPIO manipulations. This would allow lirc_zilog
-to bring the chip back to normal when it hangs, in the same places the
-original lirc_pvr150 driver code does. This is not strictly needed, so it
-is not required to move lirc_zilog out of staging.
-
-Note: Both lirc_zilog and ir-kbd-i2c support the Zilog Z8 for IR, as programmed
-and installed on Hauppauge products. When working on either module, developers
-must consider at least the following bridge drivers which mention an IR Rx unit
-at address 0x71 (indicative of a Z8):
-
- ivtv cx18 hdpvr pvrusb2 bt8xx cx88 saa7134
-
diff --git a/drivers/staging/lirc/lirc_bt829.c b/drivers/staging/lirc/lirc_bt829.c
deleted file mode 100644
index 33881025426..00000000000
--- a/drivers/staging/lirc/lirc_bt829.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Remote control driver for the TV-card based on bt829
- *
- * by Leonid Froenchenko <lfroen@galileo.co.il>
- *
- * 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
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/threads.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-
-#include <media/lirc_dev.h>
-
-static int poll_main(void);
-static int atir_init_start(void);
-
-static void write_index(unsigned char index, unsigned int value);
-static unsigned int read_index(unsigned char index);
-
-static void do_i2c_start(void);
-static void do_i2c_stop(void);
-
-static void seems_wr_byte(unsigned char al);
-static unsigned char seems_rd_byte(void);
-
-static unsigned int read_index(unsigned char al);
-static void write_index(unsigned char ah, unsigned int edx);
-
-static void cycle_delay(int cycle);
-
-static void do_set_bits(unsigned char bl);
-static unsigned char do_get_bits(void);
-
-#define DATA_PCI_OFF 0x7FFC00
-#define WAIT_CYCLE 20
-
-#define DRIVER_NAME "lirc_bt829"
-
-static int debug;
-#define dprintk(fmt, args...) \
- do { \
- if (debug) \
- printk(KERN_DEBUG DRIVER_NAME ": "fmt, ## args); \
- } while (0)
-
-static int atir_minor;
-static unsigned long pci_addr_phys;
-static unsigned char *pci_addr_lin;
-
-static struct lirc_driver atir_driver;
-
-static struct pci_dev *do_pci_probe(void)
-{
- struct pci_dev *my_dev;
- my_dev = pci_get_device(PCI_VENDOR_ID_ATI,
- PCI_DEVICE_ID_ATI_264VT, NULL);
- if (my_dev) {
- printk(KERN_ERR DRIVER_NAME ": Using device: %s\n",
- pci_name(my_dev));
- pci_addr_phys = 0;
- if (my_dev->resource[0].flags & IORESOURCE_MEM) {
- pci_addr_phys = my_dev->resource[0].start;
- printk(KERN_INFO DRIVER_NAME ": memory at 0x%08X\n",
- (unsigned int)pci_addr_phys);
- }
- if (pci_addr_phys == 0) {
- printk(KERN_ERR DRIVER_NAME ": no memory resource ?\n");
- return NULL;
- }
- } else {
- printk(KERN_ERR DRIVER_NAME ": pci_probe failed\n");
- return NULL;
- }
- return my_dev;
-}
-
-static int atir_add_to_buf(void *data, struct lirc_buffer *buf)
-{
- unsigned char key;
- int status;
- status = poll_main();
- key = (status >> 8) & 0xFF;
- if (status & 0xFF) {
- dprintk("reading key %02X\n", key);
- lirc_buffer_write(buf, &key);
- return 0;
- }
- return -ENODATA;
-}
-
-static int atir_set_use_inc(void *data)
-{
- dprintk("driver is opened\n");
- return 0;
-}
-
-static void atir_set_use_dec(void *data)
-{
- dprintk("driver is closed\n");
-}
-
-int init_module(void)
-{
- struct pci_dev *pdev;
-
- pdev = do_pci_probe();
- if (pdev == NULL)
- return 1;
-
- if (!atir_init_start())
- return 1;
-
- strcpy(atir_driver.name, "ATIR");
- atir_driver.minor = -1;
- atir_driver.code_length = 8;
- atir_driver.sample_rate = 10;
- atir_driver.data = 0;
- atir_driver.add_to_buf = atir_add_to_buf;
- atir_driver.set_use_inc = atir_set_use_inc;
- atir_driver.set_use_dec = atir_set_use_dec;
- atir_driver.dev = &pdev->dev;
- atir_driver.owner = THIS_MODULE;
-
- atir_minor = lirc_register_driver(&atir_driver);
- if (atir_minor < 0) {
- printk(KERN_ERR DRIVER_NAME ": failed to register driver!\n");
- return atir_minor;
- }
- dprintk("driver is registered on minor %d\n", atir_minor);
-
- return 0;
-}
-
-
-void cleanup_module(void)
-{
- lirc_unregister_driver(atir_minor);
-}
-
-
-static int atir_init_start(void)
-{
- pci_addr_lin = ioremap(pci_addr_phys + DATA_PCI_OFF, 0x400);
- if (pci_addr_lin == 0) {
- printk(KERN_INFO DRIVER_NAME ": pci mem must be mapped\n");
- return 0;
- }
- return 1;
-}
-
-static void cycle_delay(int cycle)
-{
- udelay(WAIT_CYCLE*cycle);
-}
-
-
-static int poll_main()
-{
- unsigned char status_high, status_low;
-
- do_i2c_start();
-
- seems_wr_byte(0xAA);
- seems_wr_byte(0x01);
-
- do_i2c_start();
-
- seems_wr_byte(0xAB);
-
- status_low = seems_rd_byte();
- status_high = seems_rd_byte();
-
- do_i2c_stop();
-
- return (status_high << 8) | status_low;
-}
-
-static void do_i2c_start(void)
-{
- do_set_bits(3);
- cycle_delay(4);
-
- do_set_bits(1);
- cycle_delay(7);
-
- do_set_bits(0);
- cycle_delay(2);
-}
-
-static void do_i2c_stop(void)
-{
- unsigned char bits;
- bits = do_get_bits() & 0xFD;
- do_set_bits(bits);
- cycle_delay(1);
-
- bits |= 1;
- do_set_bits(bits);
- cycle_delay(2);
-
- bits |= 2;
- do_set_bits(bits);
- bits = 3;
- do_set_bits(bits);
- cycle_delay(2);
-}
-
-static void seems_wr_byte(unsigned char value)
-{
- int i;
- unsigned char reg;
-
- reg = do_get_bits();
- for (i = 0; i < 8; i++) {
- if (value & 0x80)
- reg |= 0x02;
- else
- reg &= 0xFD;
-
- do_set_bits(reg);
- cycle_delay(1);
-
- reg |= 1;
- do_set_bits(reg);
- cycle_delay(1);
-
- reg &= 0xFE;
- do_set_bits(reg);
- cycle_delay(1);
- value <<= 1;
- }
- cycle_delay(2);
-
- reg |= 2;
- do_set_bits(reg);
-
- reg |= 1;
- do_set_bits(reg);
-
- cycle_delay(1);
- do_get_bits();
-
- reg &= 0xFE;
- do_set_bits(reg);
- cycle_delay(3);
-}
-
-static unsigned char seems_rd_byte(void)
-{
- int i;
- int rd_byte;
- unsigned char bits_2, bits_1;
-
- bits_1 = do_get_bits() | 2;
- do_set_bits(bits_1);
-
- rd_byte = 0;
- for (i = 0; i < 8; i++) {
- bits_1 &= 0xFE;
- do_set_bits(bits_1);
- cycle_delay(2);
-
- bits_1 |= 1;
- do_set_bits(bits_1);
- cycle_delay(1);
-
- bits_2 = do_get_bits();
- if (bits_2 & 2)
- rd_byte |= 1;
-
- rd_byte <<= 1;
- }
-
- bits_1 = 0;
- if (bits_2 == 0)
- bits_1 |= 2;
-
- do_set_bits(bits_1);
- cycle_delay(2);
-
- bits_1 |= 1;
- do_set_bits(bits_1);
- cycle_delay(3);
-
- bits_1 &= 0xFE;
- do_set_bits(bits_1);
- cycle_delay(2);
-
- rd_byte >>= 1;
- rd_byte &= 0xFF;
- return rd_byte;
-}
-
-static void do_set_bits(unsigned char new_bits)
-{
- int reg_val;
- reg_val = read_index(0x34);
- if (new_bits & 2) {
- reg_val &= 0xFFFFFFDF;
- reg_val |= 1;
- } else {
- reg_val &= 0xFFFFFFFE;
- reg_val |= 0x20;
- }
- reg_val |= 0x10;
- write_index(0x34, reg_val);
-
- reg_val = read_index(0x31);
- if (new_bits & 1)
- reg_val |= 0x1000000;
- else
- reg_val &= 0xFEFFFFFF;
-
- reg_val |= 0x8000000;
- write_index(0x31, reg_val);
-}
-
-static unsigned char do_get_bits(void)
-{
- unsigned char bits;
- int reg_val;
-
- reg_val = read_index(0x34);
- reg_val |= 0x10;
- reg_val &= 0xFFFFFFDF;
- write_index(0x34, reg_val);
-
- reg_val = read_index(0x34);
- bits = 0;
- if (reg_val & 8)
- bits |= 2;
- else
- bits &= 0xFD;
-
- reg_val = read_index(0x31);
- if (reg_val & 0x1000000)
- bits |= 1;
- else
- bits &= 0xFE;
-
- return bits;
-}
-
-static unsigned int read_index(unsigned char index)
-{
- unsigned char *addr;
- unsigned int value;
- /* addr = pci_addr_lin + DATA_PCI_OFF + ((index & 0xFF) << 2); */
- addr = pci_addr_lin + ((index & 0xFF) << 2);
- value = readl(addr);
- return value;
-}
-
-static void write_index(unsigned char index, unsigned int reg_val)
-{
- unsigned char *addr;
- addr = pci_addr_lin + ((index & 0xFF) << 2);
- writel(reg_val, addr);
-}
-
-MODULE_AUTHOR("Froenchenko Leonid");
-MODULE_DESCRIPTION("IR remote driver for bt829 based TV cards");
-MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/staging/lirc/lirc_ene0100.h b/drivers/staging/lirc/lirc_ene0100.h
deleted file mode 100644
index 06bebd6acc4..00000000000
--- a/drivers/staging/lirc/lirc_ene0100.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * driver for ENE KB3926 B/C/D CIR (also known as ENE0100)
- *
- * Copyright (C) 2009 Maxim Levitsky <maximlevitsky@gmail.com>
- *
- * 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
- */
-
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-
-/* hardware address */
-#define ENE_STATUS 0 /* hardware status - unused */
-#define ENE_ADDR_HI 1 /* hi byte of register address */
-#define ENE_ADDR_LO 2 /* low byte of register address */
-#define ENE_IO 3 /* read/write window */
-#define ENE_MAX_IO 4
-
-/* 8 bytes of samples, divided in 2 halfs*/
-#define ENE_SAMPLE_BUFFER 0xF8F0 /* regular sample buffer */
-#define ENE_SAMPLE_SPC_MASK (1 << 7) /* sample is space */
-#define ENE_SAMPLE_VALUE_MASK 0x7F
-#define ENE_SAMPLE_OVERFLOW 0x7F
-#define ENE_SAMPLES_SIZE 4
-
-/* fan input sample buffer */
-#define ENE_SAMPLE_BUFFER_FAN 0xF8FB /* this buffer holds high byte of */
- /* each sample of normal buffer */
-
-#define ENE_FAN_SMPL_PULS_MSK 0x8000 /* this bit of combined sample */
- /* if set, says that sample is pulse */
-#define ENE_FAN_VALUE_MASK 0x0FFF /* mask for valid bits of the value */
-
-/* first firmware register */
-#define ENE_FW1 0xF8F8
-#define ENE_FW1_ENABLE (1 << 0) /* enable fw processing */
-#define ENE_FW1_TXIRQ (1 << 1) /* TX interrupt pending */
-#define ENE_FW1_WAKE (1 << 6) /* enable wake from S3 */
-#define ENE_FW1_IRQ (1 << 7) /* enable interrupt */
-
-/* second firmware register */
-#define ENE_FW2 0xF8F9
-#define ENE_FW2_BUF_HIGH (1 << 0) /* which half of the buffer to read */
-#define ENE_FW2_IRQ_CLR (1 << 2) /* clear this on IRQ */
-#define ENE_FW2_GP40_AS_LEARN (1 << 4) /* normal input is used as */
- /* learning input */
-#define ENE_FW2_FAN_AS_NRML_IN (1 << 6) /* fan is used as normal input */
-#define ENE_FW2_LEARNING (1 << 7) /* hardware supports learning and TX */
-
-/* fan as input settings - only if learning capable */
-#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */
-#define ENE_FAN_AS_IN1_EN 0xCD
-#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */
-#define ENE_FAN_AS_IN2_EN 0x03
-#define ENE_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */
-
-/* IRQ registers block (for revision B) */
-#define ENEB_IRQ 0xFD09 /* IRQ number */
-#define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */
-#define ENEB_IRQ_STATUS 0xFD80 /* irq status */
-#define ENEB_IRQ_STATUS_IR (1 << 5) /* IR irq */
-
-/* IRQ registers block (for revision C,D) */
-#define ENEC_IRQ 0xFE9B /* new irq settings register */
-#define ENEC_IRQ_MASK 0x0F /* irq number mask */
-#define ENEC_IRQ_UNK_EN (1 << 4) /* always enabled */
-#define ENEC_IRQ_STATUS (1 << 5) /* irq status and ACK */
-
-/* CIR block settings */
-#define ENE_CIR_CONF1 0xFEC0
-#define ENE_CIR_CONF1_ADC_ON 0x7 /* receiver on gpio40 enabled */
-#define ENE_CIR_CONF1_LEARN1 (1 << 3) /* enabled on learning mode */
-#define ENE_CIR_CONF1_TX_ON 0x30 /* enabled on transmit */
-#define ENE_CIR_CONF1_TX_CARR (1 << 7) /* send TX carrier or not */
-
-#define ENE_CIR_CONF2 0xFEC1 /* unknown setting = 0 */
-#define ENE_CIR_CONF2_LEARN2 (1 << 4) /* set on enable learning */
-#define ENE_CIR_CONF2_GPIO40DIS (1 << 5) /* disable normal input via gpio40 */
-
-#define ENE_CIR_SAMPLE_PERIOD 0xFEC8 /* sample period in us */
-#define ENE_CIR_SAMPLE_OVERFLOW (1 << 7) /* interrupt on overflows if set */
-
-
-/* transmitter - not implemented yet */
-/* KB3926C and higher */
-/* transmission is very similar to receiving, a byte is written to */
-/* ENE_TX_INPUT, in same manner as it is read from sample buffer */
-/* sample period is fixed*/
-
-
-/* transmitter ports */
-#define ENE_TX_PORT1 0xFC01 /* this enables one or both */
-#define ENE_TX_PORT1_EN (1 << 5) /* TX ports */
-#define ENE_TX_PORT2 0xFC08
-#define ENE_TX_PORT2_EN (1 << 1)
-
-#define ENE_TX_INPUT 0xFEC9 /* next byte to transmit */
-#define ENE_TX_SPC_MASK (1 << 7) /* Transmitted sample is space */
-#define ENE_TX_UNK1 0xFECB /* set to 0x63 */
-#define ENE_TX_SMPL_PERIOD 50 /* transmit sample period */
-
-
-#define ENE_TX_CARRIER 0xFECE /* TX carrier * 2 (khz) */
-#define ENE_TX_CARRIER_UNKBIT 0x80 /* This bit set on transmit */
-#define ENE_TX_CARRIER_LOW 0xFECF /* TX carrier / 2 */
-
-/* Hardware versions */
-#define ENE_HW_VERSION 0xFF00 /* hardware revision */
-#define ENE_HW_UNK 0xFF1D
-#define ENE_HW_UNK_CLR (1 << 2)
-#define ENE_HW_VER_MAJOR 0xFF1E /* chip version */
-#define ENE_HW_VER_MINOR 0xFF1F
-#define ENE_HW_VER_OLD 0xFD00
-
-#define same_sign(a, b) ((((a) > 0) && (b) > 0) || ((a) < 0 && (b) < 0))
-
-#define ENE_DRIVER_NAME "enecir"
-#define ENE_MAXGAP 250000 /* this is amount of time we wait
- before turning the sampler, chosen
- arbitry */
-
-#define space(len) (-(len)) /* add a space */
-
-/* software defines */
-#define ENE_IRQ_RX 1
-#define ENE_IRQ_TX 2
-
-#define ENE_HW_B 1 /* 3926B */
-#define ENE_HW_C 2 /* 3926C */
-#define ENE_HW_D 3 /* 3926D */
-
-#define ene_printk(level, text, ...) \
- printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__)
-
-struct ene_device {
- struct pnp_dev *pnp_dev;
- struct lirc_driver *lirc_driver;
-
- /* hw settings */
- unsigned long hw_io;
- int irq;
-
- int hw_revision; /* hardware revision */
- int hw_learning_and_tx_capable; /* learning capable */
- int hw_gpio40_learning; /* gpio40 is learning */
- int hw_fan_as_normal_input; /* fan input is used as regular input */
-
- /* device data */
- int idle;
- int fan_input_inuse;
-
- int sample;
- int in_use;
-
- struct timeval gap_start;
-};
diff --git a/drivers/staging/lirc/lirc_igorplugusb.c b/drivers/staging/lirc/lirc_igorplugusb.c
deleted file mode 100644
index 0dc2c2b22c2..00000000000
--- a/drivers/staging/lirc/lirc_igorplugusb.c
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * lirc_igorplugusb - USB remote support for LIRC
- *
- * Supports the standard homebrew IgorPlugUSB receiver with Igor's firmware.
- * See http://www.cesko.host.sk/IgorPlugUSB/IgorPlug-USB%20(AVR)_eng.htm
- *
- * The device can only record bursts of up to 36 pulses/spaces.
- * Works fine with RC5. Longer commands lead to device buffer overrun.
- * (Maybe a better firmware or a microcontroller with more ram can help?)
- *
- * Version 0.1 [beta status]
- *
- * Copyright (C) 2004 Jan M. Hochstein
- * <hochstein@algo.informatik.tu-darmstadt.de>
- *
- * This driver was derived from:
- * Paul Miller <pmiller9@users.sourceforge.net>
- * "lirc_atiusb" module
- * Vladimir Dergachev <volodya@minspring.com>'s 2002
- * "USB ATI Remote support" (input device)
- * Adrian Dewhurst <sailor-lk@sailorfrag.net>'s 2002
- * "USB StreamZap remote driver" (LIRC)
- * Artur Lipowski <alipowski@kki.net.pl>'s 2002
- * "lirc_dev" and "lirc_gpio" LIRC modules
- */
-
-/*
- * 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
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/kmod.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/usb.h>
-#include <linux/time.h>
-
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-
-
-/* module identification */
-#define DRIVER_VERSION "0.2"
-#define DRIVER_AUTHOR \
- "Jan M. Hochstein <hochstein@algo.informatik.tu-darmstadt.de>"
-#define DRIVER_DESC "Igorplug USB remote driver for LIRC"
-#define DRIVER_NAME "lirc_igorplugusb"
-
-/* debugging support */
-#ifdef CONFIG_USB_DEBUG
-static int debug = 1;
-#else
-static int debug;
-#endif
-
-#define dprintk(fmt, args...) \
- do { \
- if (debug) \
- printk(KERN_DEBUG fmt, ## args); \
- } while (0)
-
-/* One mode2 pulse/space has 4 bytes. */
-#define CODE_LENGTH sizeof(int)
-
-/* Igor's firmware cannot record bursts longer than 36. */
-#define DEVICE_BUFLEN 36
-
-/*
- * Header at the beginning of the device's buffer:
- * unsigned char data_length
- * unsigned char data_start (!=0 means ring-buffer overrun)
- * unsigned char counter (incremented by each burst)
- */
-#define DEVICE_HEADERLEN 3
-
-/* This is for the gap */
-#define ADDITIONAL_LIRC_BYTES 2
-
-/* times to poll per second */
-#define SAMPLE_RATE 100
-static int sample_rate = SAMPLE_RATE;
-
-
-/**** Igor's USB Request Codes */
-
-#define SET_INFRABUFFER_EMPTY 1
-/**
- * Params: none
- * Answer: empty
- */
-
-#define GET_INFRACODE 2
-/**
- * Params:
- * wValue: offset to begin reading infra buffer
- *
- * Answer: infra data
- */
-
-#define SET_DATAPORT_DIRECTION 3
-/**
- * Params:
- * wValue: (byte) 1 bit for each data port pin (0=in, 1=out)
- *
- * Answer: empty
- */
-
-#define GET_DATAPORT_DIRECTION 4
-/**
- * Params: none
- *
- * Answer: (byte) 1 bit for each data port pin (0=in, 1=out)
- */
-
-#define SET_OUT_DATAPORT 5
-/**
- * Params:
- * wValue: byte to write to output data port
- *
- * Answer: empty
- */
-
-#define GET_OUT_DATAPORT 6
-/**
- * Params: none
- *
- * Answer: least significant 3 bits read from output data port
- */
-
-#define GET_IN_DATAPORT 7
-/**
- * Params: none
- *
- * Answer: least significant 3 bits read from input data port
- */
-
-#define READ_EEPROM 8
-/**
- * Params:
- * wValue: offset to begin reading EEPROM
- *
- * Answer: EEPROM bytes
- */
-
-#define WRITE_EEPROM 9
-/**
- * Params:
- * wValue: offset to EEPROM byte
- * wIndex: byte to write
- *
- * Answer: empty
- */
-
-#define SEND_RS232 10
-/**
- * Params:
- * wValue: byte to send
- *
- * Answer: empty
- */
-
-#define RECV_RS232 11
-/**
- * Params: none
- *
- * Answer: byte received
- */
-
-#define SET_RS232_BAUD 12
-/**
- * Params:
- * wValue: byte to write to UART bit rate register (UBRR)
- *
- * Answer: empty
- */
-
-#define GET_RS232_BAUD 13
-/**
- * Params: none
- *
- * Answer: byte read from UART bit rate register (UBRR)
- */
-
-
-/* data structure for each usb remote */
-struct igorplug {
-
- /* usb */
- struct usb_device *usbdev;
- int devnum;
-
- unsigned char *buf_in;
- unsigned int len_in;
- int in_space;
- struct timeval last_time;
-
- dma_addr_t dma_in;
-
- /* lirc */
- struct lirc_driver *d;
-
- /* handle sending (init strings) */
- int send_flags;
-};
-
-static int unregister_from_lirc(struct igorplug *ir)
-{
- struct lirc_driver *d;
- int devnum;
-
- if (!ir) {
- printk(KERN_ERR "%s: called with NULL device struct!\n",
- __func__);
- return -EINVAL;
- }
-
- devnum = ir->devnum;
- d = ir->d;
-
- if (!d) {
- printk(KERN_ERR "%s: called with NULL lirc driver struct!\n",
- __func__);
- return -EINVAL;
- }
-
- dprintk(DRIVER_NAME "[%d]: calling lirc_unregister_driver\n", devnum);
- lirc_unregister_driver(d->minor);
-
- kfree(d);
- ir->d = NULL;
- kfree(ir);
-
- return devnum;
-}
-
-static int set_use_inc(void *data)
-{
- struct igorplug *ir = data;
-
- if (!ir) {
- printk(DRIVER_NAME "[?]: set_use_inc called with no context\n");
- return -EIO;
- }
-
- dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum);
-
- if (!ir->usbdev)
- return -ENODEV;
-
- return 0;
-}
-
-static void set_use_dec(void *data)
-{
- struct igorplug *ir = data;
-
- if (!ir) {
- printk(DRIVER_NAME "[?]: set_use_dec called with no context\n");
- return;
- }
-
- dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum);
-}
-
-static void send_fragment(struct igorplug *ir, struct lirc_buffer *buf,
- int i, int max)
-{
- int code;
-
- /* MODE2: pulse/space (PULSE_BIT) in 1us units */
- while (i < max) {
- /* 1 Igor-tick = 85.333333 us */
- code = (unsigned int)ir->buf_in[i] * 85 +
- (unsigned int)ir->buf_in[i] / 3;
- ir->last_time.tv_usec += code;
- if (ir->in_space)
- code |= PULSE_BIT;
- lirc_buffer_write(buf, (unsigned char *)&code);
- /* 1 chunk = CODE_LENGTH bytes */
- ir->in_space ^= 1;
- ++i;
- }
-}
-
-/**
- * Called in user context.
- * return 0 if data was added to the buffer and
- * -ENODATA if none was available. This should add some number of bits
- * evenly divisible by code_length to the buffer
- */
-static int igorplugusb_remote_poll(void *data, struct lirc_buffer *buf)
-{
- int ret;
- struct igorplug *ir = (struct igorplug *)data;
-
- if (!ir || !ir->usbdev) /* Has the device been removed? */
- return -ENODEV;
-
- memset(ir->buf_in, 0, ir->len_in);
-
- ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
- GET_INFRACODE, USB_TYPE_VENDOR | USB_DIR_IN,
- 0/* offset */, /*unused*/0,
- ir->buf_in, ir->len_in,
- /*timeout*/HZ * USB_CTRL_GET_TIMEOUT);
- if (ret > 0) {
- int code, timediff;
- struct timeval now;
-
- /* ACK packet has 1 byte --> ignore */
- if (ret < DEVICE_HEADERLEN)
- return -ENODATA;
-
- dprintk(DRIVER_NAME ": Got %d bytes. Header: %02x %02x %02x\n",
- ret, ir->buf_in[0], ir->buf_in[1], ir->buf_in[2]);
-
- do_gettimeofday(&now);
- timediff = now.tv_sec - ir->last_time.tv_sec;
- if (timediff + 1 > PULSE_MASK / 1000000)
- timediff = PULSE_MASK;
- else {
- timediff *= 1000000;
- timediff += now.tv_usec - ir->last_time.tv_usec;
- }
- ir->last_time.tv_sec = now.tv_sec;
- ir->last_time.tv_usec = now.tv_usec;
-
- /* create leading gap */
- code = timediff;
- lirc_buffer_write(buf, (unsigned char *)&code);
- ir->in_space = 1; /* next comes a pulse */
-
- if (ir->buf_in[2] == 0)
- send_fragment(ir, buf, DEVICE_HEADERLEN, ret);
- else {
- printk(KERN_WARNING DRIVER_NAME
- "[%d]: Device buffer overrun.\n", ir->devnum);
- /* HHHNNNNNNNNNNNOOOOOOOO H = header
- <---[2]---> N = newer
- <---------ret--------> O = older */
- ir->buf_in[2] %= ret - DEVICE_HEADERLEN; /* sanitize */
- /* keep even-ness to not desync pulse/pause */
- send_fragment(ir, buf, DEVICE_HEADERLEN +
- ir->buf_in[2] - (ir->buf_in[2] & 1), ret);
- send_fragment(ir, buf, DEVICE_HEADERLEN,
- DEVICE_HEADERLEN + ir->buf_in[2]);
- }
-
- ret = usb_control_msg(
- ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
- SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN,
- /*unused*/0, /*unused*/0,
- /*dummy*/ir->buf_in, /*dummy*/ir->len_in,
- /*timeout*/HZ * USB_CTRL_GET_TIMEOUT);
- if (ret < 0)
- printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: "
- "error %d\n", ir->devnum, ret);
- return 0;
- } else if (ret < 0)
- printk(DRIVER_NAME "[%d]: GET_INFRACODE: error %d\n",
- ir->devnum, ret);
-
- return -ENODATA;
-}
-
-
-
-static int igorplugusb_remote_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *dev = NULL;
- struct usb_host_interface *idesc = NULL;
- struct usb_endpoint_descriptor *ep;
- struct igorplug *ir = NULL;
- struct lirc_driver *driver = NULL;
- int devnum, pipe, maxp;
- int minor = 0;
- char buf[63], name[128] = "";
- int mem_failure = 0;
- int ret;
-
- dprintk(DRIVER_NAME ": usb probe called.\n");
-
- dev = interface_to_usbdev(intf);
-
- idesc = intf->cur_altsetting;
-
- if (idesc->desc.bNumEndpoints != 1)
- return -ENODEV;
-
- ep = &idesc->endpoint->desc;
- if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
- != USB_DIR_IN)
- || (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- != USB_ENDPOINT_XFER_CONTROL)
- return -ENODEV;
-
- pipe = usb_rcvctrlpipe(dev, ep->bEndpointAddress);
- devnum = dev->devnum;
- maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
-
- dprintk(DRIVER_NAME "[%d]: bytes_in_key=%zu maxp=%d\n",
- devnum, CODE_LENGTH, maxp);
-
- mem_failure = 0;
- ir = kzalloc(sizeof(struct igorplug), GFP_KERNEL);
- if (!ir) {
- mem_failure = 1;
- goto mem_failure_switch;
- }
- driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
- if (!driver) {
- mem_failure = 2;
- goto mem_failure_switch;
- }
-
- ir->buf_in = usb_alloc_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN,
- GFP_ATOMIC, &ir->dma_in);
- if (!ir->buf_in) {
- mem_failure = 3;
- goto mem_failure_switch;
- }
-
- strcpy(driver->name, DRIVER_NAME " ");
- driver->minor = -1;
- driver->code_length = CODE_LENGTH * 8; /* in bits */
- driver->features = LIRC_CAN_REC_MODE2;
- driver->data = ir;
- driver->chunk_size = CODE_LENGTH;
- driver->buffer_size = DEVICE_BUFLEN + ADDITIONAL_LIRC_BYTES;
- driver->set_use_inc = &set_use_inc;
- driver->set_use_dec = &set_use_dec;
- driver->sample_rate = sample_rate; /* per second */
- driver->add_to_buf = &igorplugusb_remote_poll;
- driver->dev = &intf->dev;
- driver->owner = THIS_MODULE;
-
- minor = lirc_register_driver(driver);
- if (minor < 0)
- mem_failure = 9;
-
-mem_failure_switch:
-
- switch (mem_failure) {
- case 9:
- usb_free_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN,
- ir->buf_in, ir->dma_in);
- case 3:
- kfree(driver);
- case 2:
- kfree(ir);
- case 1:
- printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n",
- devnum, mem_failure);
- return -ENOMEM;
- }
-
- driver->minor = minor;
- ir->d = driver;
- ir->devnum = devnum;
- ir->usbdev = dev;
- ir->len_in = DEVICE_BUFLEN + DEVICE_HEADERLEN;
- ir->in_space = 1; /* First mode2 event is a space. */
- do_gettimeofday(&ir->last_time);
-
- if (dev->descriptor.iManufacturer
- && usb_string(dev, dev->descriptor.iManufacturer,
- buf, sizeof(buf)) > 0)
- strlcpy(name, buf, sizeof(name));
- if (dev->descriptor.iProduct
- && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0)
- snprintf(name + strlen(name), sizeof(name) - strlen(name),
- " %s", buf);
- printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name,
- dev->bus->busnum, devnum);
-
- /* clear device buffer */
- ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
- SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN,
- /*unused*/0, /*unused*/0,
- /*dummy*/ir->buf_in, /*dummy*/ir->len_in,
- /*timeout*/HZ * USB_CTRL_GET_TIMEOUT);
- if (ret < 0)
- printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n",
- devnum, ret);
-
- usb_set_intfdata(intf, ir);
- return 0;
-}
-
-
-static void igorplugusb_remote_disconnect(struct usb_interface *intf)
-{
- struct usb_device *usbdev = interface_to_usbdev(intf);
- struct igorplug *ir = usb_get_intfdata(intf);
- struct device *dev = &intf->dev;
- int devnum;
-
- usb_set_intfdata(intf, NULL);
-
- if (!ir || !ir->d)
- return;
-
- ir->usbdev = NULL;
-
- usb_free_coherent(usbdev, ir->len_in, ir->buf_in, ir->dma_in);
-
- devnum = unregister_from_lirc(ir);
-
- dev_info(dev, DRIVER_NAME "[%d]: %s done\n", devnum, __func__);
-}
-
-static struct usb_device_id igorplugusb_remote_id_table[] = {
- /* Igor Plug USB (Atmel's Manufact. ID) */
- { USB_DEVICE(0x03eb, 0x0002) },
- /* Fit PC2 Infrared Adapter */
- { USB_DEVICE(0x03eb, 0x21fe) },
-
- /* Terminating entry */
- { }
-};
-
-static struct usb_driver igorplugusb_remote_driver = {
- .name = DRIVER_NAME,
- .probe = igorplugusb_remote_probe,
- .disconnect = igorplugusb_remote_disconnect,
- .id_table = igorplugusb_remote_id_table
-};
-
-static int __init igorplugusb_remote_init(void)
-{
- int ret = 0;
-
- dprintk(DRIVER_NAME ": loaded, debug mode enabled\n");
-
- ret = usb_register(&igorplugusb_remote_driver);
- if (ret)
- printk(KERN_ERR DRIVER_NAME ": usb register failed!\n");
-
- return ret;
-}
-
-static void __exit igorplugusb_remote_exit(void)
-{
- usb_deregister(&igorplugusb_remote_driver);
-}
-
-module_init(igorplugusb_remote_init);
-module_exit(igorplugusb_remote_exit);
-
-#include <linux/vermagic.h>
-MODULE_INFO(vermagic, VERMAGIC_STRING);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(usb, igorplugusb_remote_id_table);
-
-module_param(sample_rate, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(sample_rate, "Sampling rate in Hz (default: 100)");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/staging/lirc/lirc_imon.c b/drivers/staging/lirc/lirc_imon.c
deleted file mode 100644
index 4039eda2a15..00000000000
--- a/drivers/staging/lirc/lirc_imon.c
+++ /dev/null
@@ -1,1058 +0,0 @@
-/*
- * lirc_imon.c: LIRC/VFD/LCD driver for SoundGraph iMON IR/VFD/LCD
- * including the iMON PAD model
- *
- * Copyright(C) 2004 Venky Raju(dev@venky.ws)
- * Copyright(C) 2009 Jarod Wilson <jarod@wilsonet.com>
- *
- * lirc_imon 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/usb.h>
-
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-
-
-#define MOD_AUTHOR "Venky Raju <dev@venky.ws>"
-#define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display"
-#define MOD_NAME "lirc_imon"
-#define MOD_VERSION "0.8"
-
-#define DISPLAY_MINOR_BASE 144
-#define DEVICE_NAME "lcd%d"
-
-#define BUF_CHUNK_SIZE 4
-#define BUF_SIZE 128
-
-#define BIT_DURATION 250 /* each bit received is 250us */
-
-/*** P R O T O T Y P E S ***/
-
-/* USB Callback prototypes */
-static int imon_probe(struct usb_interface *interface,
- const struct usb_device_id *id);
-static void imon_disconnect(struct usb_interface *interface);
-static void usb_rx_callback(struct urb *urb);
-static void usb_tx_callback(struct urb *urb);
-
-/* suspend/resume support */
-static int imon_resume(struct usb_interface *intf);
-static int imon_suspend(struct usb_interface *intf, pm_message_t message);
-
-/* Display file_operations function prototypes */
-static int display_open(struct inode *inode, struct file *file);
-static int display_close(struct inode *inode, struct file *file);
-
-/* VFD write operation */
-static ssize_t vfd_write(struct file *file, const char *buf,
- size_t n_bytes, loff_t *pos);
-
-/* LIRC driver function prototypes */
-static int ir_open(void *data);
-static void ir_close(void *data);
-
-/* Driver init/exit prototypes */
-static int __init imon_init(void);
-static void __exit imon_exit(void);
-
-/*** G L O B A L S ***/
-#define IMON_DATA_BUF_SZ 35
-
-struct imon_context {
- struct usb_device *usbdev;
- /* Newer devices have two interfaces */
- int display; /* not all controllers do */
- int display_isopen; /* display port has been opened */
- int ir_isopen; /* IR port open */
- int dev_present; /* USB device presence */
- struct mutex ctx_lock; /* to lock this object */
- wait_queue_head_t remove_ok; /* For unexpected USB disconnects */
-
- int vfd_proto_6p; /* some VFD require a 6th packet */
-
- struct lirc_driver *driver;
- struct usb_endpoint_descriptor *rx_endpoint;
- struct usb_endpoint_descriptor *tx_endpoint;
- struct urb *rx_urb;
- struct urb *tx_urb;
- unsigned char usb_rx_buf[8];
- unsigned char usb_tx_buf[8];
-
- struct rx_data {
- int count; /* length of 0 or 1 sequence */
- int prev_bit; /* logic level of sequence */
- int initial_space; /* initial space flag */
- } rx;
-
- struct tx_t {
- unsigned char data_buf[IMON_DATA_BUF_SZ]; /* user data buffer */
- struct completion finished; /* wait for write to finish */
- atomic_t busy; /* write in progress */
- int status; /* status of tx completion */
- } tx;
-};
-
-static const struct file_operations display_fops = {
- .owner = THIS_MODULE,
- .open = &display_open,
- .write = &vfd_write,
- .release = &display_close,
- .llseek = noop_llseek,
-};
-
-/*
- * USB Device ID for iMON USB Control Boards
- *
- * The Windows drivers contain 6 different inf files, more or less one for
- * each new device until the 0x0034-0x0046 devices, which all use the same
- * driver. Some of the devices in the 34-46 range haven't been definitively
- * identified yet. Early devices have either a TriGem Computer, Inc. or a
- * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later
- * devices use the SoundGraph vendor ID (0x15c2).
- */
-static struct usb_device_id imon_usb_id_table[] = {
- /* TriGem iMON (IR only) -- TG_iMON.inf */
- { USB_DEVICE(0x0aa8, 0x8001) },
-
- /* SoundGraph iMON (IR only) -- sg_imon.inf */
- { USB_DEVICE(0x04e8, 0xff30) },
-
- /* SoundGraph iMON VFD (IR & VFD) -- iMON_VFD.inf */
- { USB_DEVICE(0x0aa8, 0xffda) },
-
- /* SoundGraph iMON SS (IR & VFD) -- iMON_SS.inf */
- { USB_DEVICE(0x15c2, 0xffda) },
-
- {}
-};
-
-/* Some iMON VFD models requires a 6th packet for VFD writes */
-static struct usb_device_id vfd_proto_6p_list[] = {
- { USB_DEVICE(0x15c2, 0xffda) },
- {}
-};
-
-/* Some iMON devices have no lcd/vfd, don't set one up */
-static struct usb_device_id ir_only_list[] = {
- { USB_DEVICE(0x0aa8, 0x8001) },
- { USB_DEVICE(0x04e8, 0xff30) },
- {}
-};
-
-/* USB Device data */
-static struct usb_driver imon_driver = {
- .name = MOD_NAME,
- .probe = imon_probe,
- .disconnect = imon_disconnect,
- .suspend = imon_suspend,
- .resume = imon_resume,
- .id_table = imon_usb_id_table,
-};
-
-static struct usb_class_driver imon_class = {
- .name = DEVICE_NAME,
- .fops = &display_fops,
- .minor_base = DISPLAY_MINOR_BASE,
-};
-
-/* to prevent races between open() and disconnect(), probing, etc */
-static DEFINE_MUTEX(driver_lock);
-
-static int debug;
-
-/*** M O D U L E C O D E ***/
-
-MODULE_AUTHOR(MOD_AUTHOR);
-MODULE_DESCRIPTION(MOD_DESC);
-MODULE_VERSION(MOD_VERSION);
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(usb, imon_usb_id_table);
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)");
-
-static void free_imon_context(struct imon_context *context)
-{
- struct device *dev = context->driver->dev;
- usb_free_urb(context->tx_urb);
- usb_free_urb(context->rx_urb);
- lirc_buffer_free(context->driver->rbuf);
- kfree(context->driver->rbuf);
- kfree(context->driver);
- kfree(context);
-
- dev_dbg(dev, "%s: iMON context freed\n", __func__);
-}
-
-static void deregister_from_lirc(struct imon_context *context)
-{
- int retval;
- int minor = context->driver->minor;
-
- retval = lirc_unregister_driver(minor);
- if (retval)
- err("%s: unable to deregister from lirc(%d)",
- __func__, retval);
- else
- printk(KERN_INFO MOD_NAME ": Deregistered iMON driver "
- "(minor:%d)\n", minor);
-
-}
-
-/**
- * Called when the Display device (e.g. /dev/lcd0)
- * is opened by the application.
- */
-static int display_open(struct inode *inode, struct file *file)
-{
- struct usb_interface *interface;
- struct imon_context *context = NULL;
- int subminor;
- int retval = 0;
-
- /* prevent races with disconnect */
- mutex_lock(&driver_lock);
-
- subminor = iminor(inode);
- interface = usb_find_interface(&imon_driver, subminor);
- if (!interface) {
- err("%s: could not find interface for minor %d",
- __func__, subminor);
- retval = -ENODEV;
- goto exit;
- }
- context = usb_get_intfdata(interface);
-
- if (!context) {
- err("%s: no context found for minor %d",
- __func__, subminor);
- retval = -ENODEV;
- goto exit;
- }
-
- mutex_lock(&context->ctx_lock);
-
- if (!context->display) {
- err("%s: display not supported by device", __func__);
- retval = -ENODEV;
- } else if (context->display_isopen) {
- err("%s: display port is already open", __func__);
- retval = -EBUSY;
- } else {
- context->display_isopen = 1;
- file->private_data = context;
- dev_info(context->driver->dev, "display port opened\n");
- }
-
- mutex_unlock(&context->ctx_lock);
-
-exit:
- mutex_unlock(&driver_lock);
- return retval;
-}
-
-/**
- * Called when the display device (e.g. /dev/lcd0)
- * is closed by the application.
- */
-static int display_close(struct inode *inode, struct file *file)
-{
- struct imon_context *context = NULL;
- int retval = 0;
-
- context = file->private_data;
-
- if (!context) {
- err("%s: no context for device", __func__);
- return -ENODEV;
- }
-
- mutex_lock(&context->ctx_lock);
-
- if (!context->display) {
- err("%s: display not supported by device", __func__);
- retval = -ENODEV;
- } else if (!context->display_isopen) {
- err("%s: display is not open", __func__);
- retval = -EIO;
- } else {
- context->display_isopen = 0;
- dev_info(context->driver->dev, "display port closed\n");
- if (!context->dev_present && !context->ir_isopen) {
- /*
- * Device disconnected before close and IR port is not
- * open. If IR port is open, context will be deleted by
- * ir_close.
- */
- mutex_unlock(&context->ctx_lock);
- free_imon_context(context);
- return retval;
- }
- }
-
- mutex_unlock(&context->ctx_lock);
- return retval;
-}
-
-/**
- * Sends a packet to the device -- this function must be called
- * with context->ctx_lock held.
- */
-static int send_packet(struct imon_context *context)
-{
- unsigned int pipe;
- int interval = 0;
- int retval = 0;
-
- /* Check if we need to use control or interrupt urb */
- pipe = usb_sndintpipe(context->usbdev,
- context->tx_endpoint->bEndpointAddress);
- interval = context->tx_endpoint->bInterval;
-
- usb_fill_int_urb(context->tx_urb, context->usbdev, pipe,
- context->usb_tx_buf,
- sizeof(context->usb_tx_buf),
- usb_tx_callback, context, interval);
-
- context->tx_urb->actual_length = 0;
-
- init_completion(&context->tx.finished);
- atomic_set(&(context->tx.busy), 1);
-
- retval = usb_submit_urb(context->tx_urb, GFP_KERNEL);
- if (retval) {
- atomic_set(&(context->tx.busy), 0);
- err("%s: error submitting urb(%d)", __func__, retval);
- } else {
- /* Wait for transmission to complete (or abort) */
- mutex_unlock(&context->ctx_lock);
- retval = wait_for_completion_interruptible(
- &context->tx.finished);
- if (retval)
- err("%s: task interrupted", __func__);
- mutex_lock(&context->ctx_lock);
-
- retval = context->tx.status;
- if (retval)
- err("%s: packet tx failed (%d)", __func__, retval);
- }
-
- return retval;
-}
-
-/**
- * Writes data to the VFD. The iMON VFD is 2x16 characters
- * and requires data in 5 consecutive USB interrupt packets,
- * each packet but the last carrying 7 bytes.
- *
- * I don't know if the VFD board supports features such as
- * scrolling, clearing rows, blanking, etc. so at
- * the caller must provide a full screen of data. If fewer
- * than 32 bytes are provided spaces will be appended to
- * generate a full screen.
- */
-static ssize_t vfd_write(struct file *file, const char *buf,
- size_t n_bytes, loff_t *pos)
-{
- int i;
- int offset;
- int seq;
- int retval = 0;
- struct imon_context *context;
- const unsigned char vfd_packet6[] = {
- 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
- int *data_buf = NULL;
-
- context = file->private_data;
- if (!context) {
- err("%s: no context for device", __func__);
- return -ENODEV;
- }
-
- mutex_lock(&context->ctx_lock);
-
- if (!context->dev_present) {
- err("%s: no iMON device present", __func__);
- retval = -ENODEV;
- goto exit;
- }
-
- if (n_bytes <= 0 || n_bytes > IMON_DATA_BUF_SZ - 3) {
- err("%s: invalid payload size", __func__);
- retval = -EINVAL;
- goto exit;
- }
-
- data_buf = memdup_user(buf, n_bytes);
- if (IS_ERR(data_buf)) {
- retval = PTR_ERR(data_buf);
- goto exit;
- }
-
- memcpy(context->tx.data_buf, data_buf, n_bytes);
-
- /* Pad with spaces */
- for (i = n_bytes; i < IMON_DATA_BUF_SZ - 3; ++i)
- context->tx.data_buf[i] = ' ';
-
- for (i = IMON_DATA_BUF_SZ - 3; i < IMON_DATA_BUF_SZ; ++i)
- context->tx.data_buf[i] = 0xFF;
-
- offset = 0;
- seq = 0;
-
- do {
- memcpy(context->usb_tx_buf, context->tx.data_buf + offset, 7);
- context->usb_tx_buf[7] = (unsigned char) seq;
-
- retval = send_packet(context);
- if (retval) {
- err("%s: send packet failed for packet #%d",
- __func__, seq/2);
- goto exit;
- } else {
- seq += 2;
- offset += 7;
- }
-
- } while (offset < IMON_DATA_BUF_SZ);
-
- if (context->vfd_proto_6p) {
- /* Send packet #6 */
- memcpy(context->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6));
- context->usb_tx_buf[7] = (unsigned char) seq;
- retval = send_packet(context);
- if (retval)
- err("%s: send packet failed for packet #%d",
- __func__, seq/2);
- }
-
-exit:
- mutex_unlock(&context->ctx_lock);
- kfree(data_buf);
-
- return (!retval) ? n_bytes : retval;
-}
-
-/**
- * Callback function for USB core API: transmit data
- */
-static void usb_tx_callback(struct urb *urb)
-{
- struct imon_context *context;
-
- if (!urb)
- return;
- context = (struct imon_context *)urb->context;
- if (!context)
- return;
-
- context->tx.status = urb->status;
-
- /* notify waiters that write has finished */
- atomic_set(&context->tx.busy, 0);
- complete(&context->tx.finished);
-
- return;
-}
-
-/**
- * Called by lirc_dev when the application opens /dev/lirc
- */
-static int ir_open(void *data)
-{
- int retval = 0;
- struct imon_context *context;
-
- /* prevent races with disconnect */
- mutex_lock(&driver_lock);
-
- context = (struct imon_context *)data;
-
- /* initial IR protocol decode variables */
- context->rx.count = 0;
- context->rx.initial_space = 1;
- context->rx.prev_bit = 0;
-
- context->ir_isopen = 1;
- dev_info(context->driver->dev, "IR port opened\n");
-
- mutex_unlock(&driver_lock);
- return retval;
-}
-
-/**
- * Called by lirc_dev when the application closes /dev/lirc
- */
-static void ir_close(void *data)
-{
- struct imon_context *context;
-
- context = (struct imon_context *)data;
- if (!context) {
- err("%s: no context for device", __func__);
- return;
- }
-
- mutex_lock(&context->ctx_lock);
-
- context->ir_isopen = 0;
- dev_info(context->driver->dev, "IR port closed\n");
-
- if (!context->dev_present) {
- /*
- * Device disconnected while IR port was still open. Driver
- * was not deregistered at disconnect time, so do it now.
- */
- deregister_from_lirc(context);
-
- if (!context->display_isopen) {
- mutex_unlock(&context->ctx_lock);
- free_imon_context(context);
- return;
- }
- /*
- * If display port is open, context will be deleted by
- * display_close
- */
- }
-
- mutex_unlock(&context->ctx_lock);
- return;
-}
-
-/**
- * Convert bit count to time duration (in us) and submit
- * the value to lirc_dev.
- */
-static void submit_data(struct imon_context *context)
-{
- unsigned char buf[4];
- int value = context->rx.count;
- int i;
-
- dev_dbg(context->driver->dev, "submitting data to LIRC\n");
-
- value *= BIT_DURATION;
- value &= PULSE_MASK;
- if (context->rx.prev_bit)
- value |= PULSE_BIT;
-
- for (i = 0; i < 4; ++i)
- buf[i] = value>>(i*8);
-
- lirc_buffer_write(context->driver->rbuf, buf);
- wake_up(&context->driver->rbuf->wait_poll);
- return;
-}
-
-static inline int tv2int(const struct timeval *a, const struct timeval *b)
-{
- int usecs = 0;
- int sec = 0;
-
- if (b->tv_usec > a->tv_usec) {
- usecs = 1000000;
- sec--;
- }
-
- usecs += a->tv_usec - b->tv_usec;
-
- sec += a->tv_sec - b->tv_sec;
- sec *= 1000;
- usecs /= 1000;
- sec += usecs;
-
- if (sec < 0)
- sec = 1000;
-
- return sec;
-}
-
-/**
- * Process the incoming packet
- */
-static void imon_incoming_packet(struct imon_context *context,
- struct urb *urb, int intf)
-{
- int len = urb->actual_length;
- unsigned char *buf = urb->transfer_buffer;
- struct device *dev = context->driver->dev;
- int octet, bit;
- unsigned char mask;
- int i;
-
- /*
- * just bail out if no listening IR client
- */
- if (!context->ir_isopen)
- return;
-
- if (len != 8) {
- dev_warn(dev, "imon %s: invalid incoming packet "
- "size (len = %d, intf%d)\n", __func__, len, intf);
- return;
- }
-
- if (debug) {
- printk(KERN_INFO "raw packet: ");
- for (i = 0; i < len; ++i)
- printk("%02x ", buf[i]);
- printk("\n");
- }
-
- /*
- * Translate received data to pulse and space lengths.
- * Received data is active low, i.e. pulses are 0 and
- * spaces are 1.
- *
- * My original algorithm was essentially similar to
- * Changwoo Ryu's with the exception that he switched
- * the incoming bits to active high and also fed an
- * initial space to LIRC at the start of a new sequence
- * if the previous bit was a pulse.
- *
- * I've decided to adopt his algorithm.
- */
-
- if (buf[7] == 1 && context->rx.initial_space) {
- /* LIRC requires a leading space */
- context->rx.prev_bit = 0;
- context->rx.count = 4;
- submit_data(context);
- context->rx.count = 0;
- }
-
- for (octet = 0; octet < 5; ++octet) {
- mask = 0x80;
- for (bit = 0; bit < 8; ++bit) {
- int curr_bit = !(buf[octet] & mask);
- if (curr_bit != context->rx.prev_bit) {
- if (context->rx.count) {
- submit_data(context);
- context->rx.count = 0;
- }
- context->rx.prev_bit = curr_bit;
- }
- ++context->rx.count;
- mask >>= 1;
- }
- }
-
- if (buf[7] == 10) {
- if (context->rx.count) {
- submit_data(context);
- context->rx.count = 0;
- }
- context->rx.initial_space = context->rx.prev_bit;
- }
-}
-
-/**
- * Callback function for USB core API: receive data
- */
-static void usb_rx_callback(struct urb *urb)
-{
- struct imon_context *context;
- unsigned char *buf;
- int len;
- int intfnum = 0;
-
- if (!urb)
- return;
-
- context = (struct imon_context *)urb->context;
- if (!context)
- return;
-
- buf = urb->transfer_buffer;
- len = urb->actual_length;
-
- switch (urb->status) {
- case -ENOENT: /* usbcore unlink successful! */
- return;
-
- case 0:
- imon_incoming_packet(context, urb, intfnum);
- break;
-
- default:
- dev_warn(context->driver->dev, "imon %s: status(%d): ignored\n",
- __func__, urb->status);
- break;
- }
-
- usb_submit_urb(context->rx_urb, GFP_ATOMIC);
-
- return;
-}
-
-/**
- * Callback function for USB core API: Probe
- */
-static int imon_probe(struct usb_interface *interface,
- const struct usb_device_id *id)
-{
- struct usb_device *usbdev = NULL;
- struct usb_host_interface *iface_desc = NULL;
- struct usb_endpoint_descriptor *rx_endpoint = NULL;
- struct usb_endpoint_descriptor *tx_endpoint = NULL;
- struct urb *rx_urb = NULL;
- struct urb *tx_urb = NULL;
- struct lirc_driver *driver = NULL;
- struct lirc_buffer *rbuf = NULL;
- struct device *dev = &interface->dev;
- int ifnum;
- int lirc_minor = 0;
- int num_endpts;
- int retval = 0;
- int display_ep_found = 0;
- int ir_ep_found = 0;
- int alloc_status = 0;
- int vfd_proto_6p = 0;
- int code_length;
- struct imon_context *context = NULL;
- int i;
- u16 vendor, product;
-
- context = kzalloc(sizeof(struct imon_context), GFP_KERNEL);
- if (!context) {
- err("%s: kzalloc failed for context", __func__);
- alloc_status = 1;
- goto alloc_status_switch;
- }
-
- /*
- * Try to auto-detect the type of display if the user hasn't set
- * it by hand via the display_type modparam. Default is VFD.
- */
- if (usb_match_id(interface, ir_only_list))
- context->display = 0;
- else
- context->display = 1;
-
- code_length = BUF_CHUNK_SIZE * 8;
-
- usbdev = usb_get_dev(interface_to_usbdev(interface));
- iface_desc = interface->cur_altsetting;
- num_endpts = iface_desc->desc.bNumEndpoints;
- ifnum = iface_desc->desc.bInterfaceNumber;
- vendor = le16_to_cpu(usbdev->descriptor.idVendor);
- product = le16_to_cpu(usbdev->descriptor.idProduct);
-
- dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n",
- __func__, vendor, product, ifnum);
-
- /* prevent races probing devices w/multiple interfaces */
- mutex_lock(&driver_lock);
-
- /*
- * Scan the endpoint list and set:
- * first input endpoint = IR endpoint
- * first output endpoint = display endpoint
- */
- for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) {
- struct usb_endpoint_descriptor *ep;
- int ep_dir;
- int ep_type;
- ep = &iface_desc->endpoint[i].desc;
- ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
- ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-
- if (!ir_ep_found &&
- ep_dir == USB_DIR_IN &&
- ep_type == USB_ENDPOINT_XFER_INT) {
-
- rx_endpoint = ep;
- ir_ep_found = 1;
- dev_dbg(dev, "%s: found IR endpoint\n", __func__);
-
- } else if (!display_ep_found && ep_dir == USB_DIR_OUT &&
- ep_type == USB_ENDPOINT_XFER_INT) {
- tx_endpoint = ep;
- display_ep_found = 1;
- dev_dbg(dev, "%s: found display endpoint\n", __func__);
- }
- }
-
- /*
- * Some iMON receivers have no display. Unfortunately, it seems
- * that SoundGraph recycles device IDs between devices both with
- * and without... :\
- */
- if (context->display == 0) {
- display_ep_found = 0;
- dev_dbg(dev, "%s: device has no display\n", __func__);
- }
-
- /* Input endpoint is mandatory */
- if (!ir_ep_found) {
- err("%s: no valid input (IR) endpoint found.", __func__);
- retval = -ENODEV;
- alloc_status = 2;
- goto alloc_status_switch;
- }
-
- /* Determine if display requires 6 packets */
- if (display_ep_found) {
- if (usb_match_id(interface, vfd_proto_6p_list))
- vfd_proto_6p = 1;
-
- dev_dbg(dev, "%s: vfd_proto_6p: %d\n",
- __func__, vfd_proto_6p);
- }
-
- driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
- if (!driver) {
- err("%s: kzalloc failed for lirc_driver", __func__);
- alloc_status = 2;
- goto alloc_status_switch;
- }
- rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
- if (!rbuf) {
- err("%s: kmalloc failed for lirc_buffer", __func__);
- alloc_status = 3;
- goto alloc_status_switch;
- }
- if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) {
- err("%s: lirc_buffer_init failed", __func__);
- alloc_status = 4;
- goto alloc_status_switch;
- }
- rx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!rx_urb) {
- err("%s: usb_alloc_urb failed for IR urb", __func__);
- alloc_status = 5;
- goto alloc_status_switch;
- }
- tx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!tx_urb) {
- err("%s: usb_alloc_urb failed for display urb",
- __func__);
- alloc_status = 6;
- goto alloc_status_switch;
- }
-
- mutex_init(&context->ctx_lock);
- context->vfd_proto_6p = vfd_proto_6p;
-
- strcpy(driver->name, MOD_NAME);
- driver->minor = -1;
- driver->code_length = sizeof(int) * 8;
- driver->sample_rate = 0;
- driver->features = LIRC_CAN_REC_MODE2;
- driver->data = context;
- driver->rbuf = rbuf;
- driver->set_use_inc = ir_open;
- driver->set_use_dec = ir_close;
- driver->dev = &interface->dev;
- driver->owner = THIS_MODULE;
-
- mutex_lock(&context->ctx_lock);
-
- context->driver = driver;
- /* start out in keyboard mode */
-
- lirc_minor = lirc_register_driver(driver);
- if (lirc_minor < 0) {
- err("%s: lirc_register_driver failed", __func__);
- alloc_status = 7;
- goto unlock;
- } else
- dev_info(dev, "Registered iMON driver "
- "(lirc minor: %d)\n", lirc_minor);
-
- /* Needed while unregistering! */
- driver->minor = lirc_minor;
-
- context->usbdev = usbdev;
- context->dev_present = 1;
- context->rx_endpoint = rx_endpoint;
- context->rx_urb = rx_urb;
-
- /*
- * tx is used to send characters to lcd/vfd, associate RF
- * remotes, set IR protocol, and maybe more...
- */
- context->tx_endpoint = tx_endpoint;
- context->tx_urb = tx_urb;
-
- if (display_ep_found)
- context->display = 1;
-
- usb_fill_int_urb(context->rx_urb, context->usbdev,
- usb_rcvintpipe(context->usbdev,
- context->rx_endpoint->bEndpointAddress),
- context->usb_rx_buf, sizeof(context->usb_rx_buf),
- usb_rx_callback, context,
- context->rx_endpoint->bInterval);
-
- retval = usb_submit_urb(context->rx_urb, GFP_KERNEL);
-
- if (retval) {
- err("%s: usb_submit_urb failed for intf0 (%d)",
- __func__, retval);
- mutex_unlock(&context->ctx_lock);
- goto exit;
- }
-
- usb_set_intfdata(interface, context);
-
- if (context->display && ifnum == 0) {
- dev_dbg(dev, "%s: Registering iMON display with sysfs\n",
- __func__);
-
- if (usb_register_dev(interface, &imon_class)) {
- /* Not a fatal error, so ignore */
- dev_info(dev, "%s: could not get a minor number for "
- "display\n", __func__);
- }
- }
-
- dev_info(dev, "iMON device (%04x:%04x, intf%d) on "
- "usb<%d:%d> initialized\n", vendor, product, ifnum,
- usbdev->bus->busnum, usbdev->devnum);
-
-unlock:
- mutex_unlock(&context->ctx_lock);
-alloc_status_switch:
-
- switch (alloc_status) {
- case 7:
- usb_free_urb(tx_urb);
- case 6:
- usb_free_urb(rx_urb);
- case 5:
- if (rbuf)
- lirc_buffer_free(rbuf);
- case 4:
- kfree(rbuf);
- case 3:
- kfree(driver);
- case 2:
- kfree(context);
- context = NULL;
- case 1:
- if (retval != -ENODEV)
- retval = -ENOMEM;
- break;
- case 0:
- retval = 0;
- }
-
-exit:
- mutex_unlock(&driver_lock);
-
- return retval;
-}
-
-/**
- * Callback function for USB core API: disconnect
- */
-static void imon_disconnect(struct usb_interface *interface)
-{
- struct imon_context *context;
- int ifnum;
-
- /* prevent races with ir_open()/display_open() */
- mutex_lock(&driver_lock);
-
- context = usb_get_intfdata(interface);
- ifnum = interface->cur_altsetting->desc.bInterfaceNumber;
-
- mutex_lock(&context->ctx_lock);
-
- usb_set_intfdata(interface, NULL);
-
- /* Abort ongoing write */
- if (atomic_read(&context->tx.busy)) {
- usb_kill_urb(context->tx_urb);
- complete_all(&context->tx.finished);
- }
-
- context->dev_present = 0;
- usb_kill_urb(context->rx_urb);
- if (context->display)
- usb_deregister_dev(interface, &imon_class);
-
- if (!context->ir_isopen && !context->dev_present) {
- deregister_from_lirc(context);
- mutex_unlock(&context->ctx_lock);
- if (!context->display_isopen)
- free_imon_context(context);
- } else
- mutex_unlock(&context->ctx_lock);
-
- mutex_unlock(&driver_lock);
-
- printk(KERN_INFO "%s: iMON device (intf%d) disconnected\n",
- __func__, ifnum);
-}
-
-static int imon_suspend(struct usb_interface *intf, pm_message_t message)
-{
- struct imon_context *context = usb_get_intfdata(intf);
-
- usb_kill_urb(context->rx_urb);
-
- return 0;
-}
-
-static int imon_resume(struct usb_interface *intf)
-{
- int rc = 0;
- struct imon_context *context = usb_get_intfdata(intf);
-
- usb_fill_int_urb(context->rx_urb, context->usbdev,
- usb_rcvintpipe(context->usbdev,
- context->rx_endpoint->bEndpointAddress),
- context->usb_rx_buf, sizeof(context->usb_rx_buf),
- usb_rx_callback, context,
- context->rx_endpoint->bInterval);
-
- rc = usb_submit_urb(context->rx_urb, GFP_ATOMIC);
-
- return rc;
-}
-
-static int __init imon_init(void)
-{
- int rc;
-
- printk(KERN_INFO MOD_NAME ": " MOD_DESC ", v" MOD_VERSION "\n");
-
- rc = usb_register(&imon_driver);
- if (rc) {
- err("%s: usb register failed(%d)", __func__, rc);
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void __exit imon_exit(void)
-{
- usb_deregister(&imon_driver);
- printk(KERN_INFO MOD_NAME ": module removed. Goodbye!\n");
-}
-
-module_init(imon_init);
-module_exit(imon_exit);
diff --git a/drivers/staging/lirc/lirc_parallel.c b/drivers/staging/lirc/lirc_parallel.c
deleted file mode 100644
index 50724c4e248..00000000000
--- a/drivers/staging/lirc/lirc_parallel.c
+++ /dev/null
@@ -1,755 +0,0 @@
-/*
- * lirc_parallel.c
- *
- * lirc_parallel - device driver for infra-red signal receiving and
- * transmitting unit built by the author
- *
- * Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.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
- *
- */
-
-/*** Includes ***/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/time.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/uaccess.h>
-#include <asm/div64.h>
-
-#include <linux/poll.h>
-#include <linux/parport.h>
-#include <linux/platform_device.h>
-
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-
-#include "lirc_parallel.h"
-
-#define LIRC_DRIVER_NAME "lirc_parallel"
-
-#ifndef LIRC_IRQ
-#define LIRC_IRQ 7
-#endif
-#ifndef LIRC_PORT
-#define LIRC_PORT 0x378
-#endif
-#ifndef LIRC_TIMER
-#define LIRC_TIMER 65536
-#endif
-
-/*** Global Variables ***/
-
-static int debug;
-static int check_pselecd;
-
-unsigned int irq = LIRC_IRQ;
-unsigned int io = LIRC_PORT;
-#ifdef LIRC_TIMER
-unsigned int timer;
-unsigned int default_timer = LIRC_TIMER;
-#endif
-
-#define RBUF_SIZE (256) /* this must be a power of 2 larger than 1 */
-
-static int rbuf[RBUF_SIZE];
-
-DECLARE_WAIT_QUEUE_HEAD(lirc_wait);
-
-unsigned int rptr;
-unsigned int wptr;
-unsigned int lost_irqs;
-int is_open;
-
-struct parport *pport;
-struct pardevice *ppdevice;
-int is_claimed;
-
-unsigned int tx_mask = 1;
-
-/*** Internal Functions ***/
-
-static unsigned int in(int offset)
-{
- switch (offset) {
- case LIRC_LP_BASE:
- return parport_read_data(pport);
- case LIRC_LP_STATUS:
- return parport_read_status(pport);
- case LIRC_LP_CONTROL:
- return parport_read_control(pport);
- }
- return 0; /* make compiler happy */
-}
-
-static void out(int offset, int value)
-{
- switch (offset) {
- case LIRC_LP_BASE:
- parport_write_data(pport, value);
- break;
- case LIRC_LP_CONTROL:
- parport_write_control(pport, value);
- break;
- case LIRC_LP_STATUS:
- printk(KERN_INFO "%s: attempt to write to status register\n",
- LIRC_DRIVER_NAME);
- break;
- }
-}
-
-static unsigned int lirc_get_timer(void)
-{
- return in(LIRC_PORT_TIMER) & LIRC_PORT_TIMER_BIT;
-}
-
-static unsigned int lirc_get_signal(void)
-{
- return in(LIRC_PORT_SIGNAL) & LIRC_PORT_SIGNAL_BIT;
-}
-
-static void lirc_on(void)
-{
- out(LIRC_PORT_DATA, tx_mask);
-}
-
-static void lirc_off(void)
-{
- out(LIRC_PORT_DATA, 0);
-}
-
-static unsigned int init_lirc_timer(void)
-{
- struct timeval tv, now;
- unsigned int level, newlevel, timeelapsed, newtimer;
- int count = 0;
-
- do_gettimeofday(&tv);
- tv.tv_sec++; /* wait max. 1 sec. */
- level = lirc_get_timer();
- do {
- newlevel = lirc_get_timer();
- if (level == 0 && newlevel != 0)
- count++;
- level = newlevel;
- do_gettimeofday(&now);
- } while (count < 1000 && (now.tv_sec < tv.tv_sec
- || (now.tv_sec == tv.tv_sec
- && now.tv_usec < tv.tv_usec)));
-
- timeelapsed = ((now.tv_sec + 1 - tv.tv_sec)*1000000
- + (now.tv_usec - tv.tv_usec));
- if (count >= 1000 && timeelapsed > 0) {
- if (default_timer == 0) {
- /* autodetect timer */
- newtimer = (1000000*count)/timeelapsed;
- printk(KERN_INFO "%s: %u Hz timer detected\n",
- LIRC_DRIVER_NAME, newtimer);
- return newtimer;
- } else {
- newtimer = (1000000*count)/timeelapsed;
- if (abs(newtimer - default_timer) > default_timer/10) {
- /* bad timer */
- printk(KERN_NOTICE "%s: bad timer: %u Hz\n",
- LIRC_DRIVER_NAME, newtimer);
- printk(KERN_NOTICE "%s: using default timer: "
- "%u Hz\n",
- LIRC_DRIVER_NAME, default_timer);
- return default_timer;
- } else {
- printk(KERN_INFO "%s: %u Hz timer detected\n",
- LIRC_DRIVER_NAME, newtimer);
- return newtimer; /* use detected value */
- }
- }
- } else {
- printk(KERN_NOTICE "%s: no timer detected\n", LIRC_DRIVER_NAME);
- return 0;
- }
-}
-
-static int lirc_claim(void)
-{
- if (parport_claim(ppdevice) != 0) {
- printk(KERN_WARNING "%s: could not claim port\n",
- LIRC_DRIVER_NAME);
- printk(KERN_WARNING "%s: waiting for port becoming available"
- "\n", LIRC_DRIVER_NAME);
- if (parport_claim_or_block(ppdevice) < 0) {
- printk(KERN_NOTICE "%s: could not claim port, giving"
- " up\n", LIRC_DRIVER_NAME);
- return 0;
- }
- }
- out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP);
- is_claimed = 1;
- return 1;
-}
-
-/*** interrupt handler ***/
-
-static void rbuf_write(int signal)
-{
- unsigned int nwptr;
-
- nwptr = (wptr + 1) & (RBUF_SIZE - 1);
- if (nwptr == rptr) {
- /* no new signals will be accepted */
- lost_irqs++;
- printk(KERN_NOTICE "%s: buffer overrun\n", LIRC_DRIVER_NAME);
- return;
- }
- rbuf[wptr] = signal;
- wptr = nwptr;
-}
-
-static void irq_handler(void *blah)
-{
- struct timeval tv;
- static struct timeval lasttv;
- static int init;
- long signal;
- int data;
- unsigned int level, newlevel;
- unsigned int timeout;
-
- if (!is_open)
- return;
-
- if (!is_claimed)
- return;
-
-#if 0
- /* disable interrupt */
- disable_irq(irq);
- out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ) & (~LP_PINTEN));
-#endif
- if (check_pselecd && (in(1) & LP_PSELECD))
- return;
-
-#ifdef LIRC_TIMER
- if (init) {
- do_gettimeofday(&tv);
-
- signal = tv.tv_sec - lasttv.tv_sec;
- if (signal > 15)
- /* really long time */
- data = PULSE_MASK;
- else
- data = (int) (signal*1000000 +
- tv.tv_usec - lasttv.tv_usec +
- LIRC_SFH506_DELAY);
-
- rbuf_write(data); /* space */
- } else {
- if (timer == 0) {
- /*
- * wake up; we'll lose this signal, but it will be
- * garbage if the device is turned on anyway
- */
- timer = init_lirc_timer();
- /* enable_irq(irq); */
- return;
- }
- init = 1;
- }
-
- timeout = timer/10; /* timeout after 1/10 sec. */
- signal = 1;
- level = lirc_get_timer();
- do {
- newlevel = lirc_get_timer();
- if (level == 0 && newlevel != 0)
- signal++;
- level = newlevel;
-
- /* giving up */
- if (signal > timeout
- || (check_pselecd && (in(1) & LP_PSELECD))) {
- signal = 0;
- printk(KERN_NOTICE "%s: timeout\n", LIRC_DRIVER_NAME);
- break;
- }
- } while (lirc_get_signal());
-
- if (signal != 0) {
- /* adjust value to usecs */
- __u64 helper;
-
- helper = ((__u64) signal)*1000000;
- do_div(helper, timer);
- signal = (long) helper;
-
- if (signal > LIRC_SFH506_DELAY)
- data = signal - LIRC_SFH506_DELAY;
- else
- data = 1;
- rbuf_write(PULSE_BIT|data); /* pulse */
- }
- do_gettimeofday(&lasttv);
-#else
- /* add your code here */
-#endif
-
- wake_up_interruptible(&lirc_wait);
-
- /* enable interrupt */
- /*
- enable_irq(irq);
- out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ)|LP_PINTEN);
- */
-}
-
-/*** file operations ***/
-
-static loff_t lirc_lseek(struct file *filep, loff_t offset, int orig)
-{
- return -ESPIPE;
-}
-
-static ssize_t lirc_read(struct file *filep, char *buf, size_t n, loff_t *ppos)
-{
- int result = 0;
- int count = 0;
- DECLARE_WAITQUEUE(wait, current);
-
- if (n % sizeof(int))
- return -EINVAL;
-
- add_wait_queue(&lirc_wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- while (count < n) {
- if (rptr != wptr) {
- if (copy_to_user(buf+count, (char *) &rbuf[rptr],
- sizeof(int))) {
- result = -EFAULT;
- break;
- }
- rptr = (rptr + 1) & (RBUF_SIZE - 1);
- count += sizeof(int);
- } else {
- if (filep->f_flags & O_NONBLOCK) {
- result = -EAGAIN;
- break;
- }
- if (signal_pending(current)) {
- result = -ERESTARTSYS;
- break;
- }
- schedule();
- set_current_state(TASK_INTERRUPTIBLE);
- }
- }
- remove_wait_queue(&lirc_wait, &wait);
- set_current_state(TASK_RUNNING);
- return count ? count : result;
-}
-
-static ssize_t lirc_write(struct file *filep, const char *buf, size_t n,
- loff_t *ppos)
-{
- int count;
- unsigned int i;
- unsigned int level, newlevel;
- unsigned long flags;
- int counttimer;
- int *wbuf;
- ssize_t ret;
-
- if (!is_claimed)
- return -EBUSY;
-
- count = n / sizeof(int);
-
- if (n % sizeof(int) || count % 2 == 0)
- return -EINVAL;
-
- wbuf = memdup_user(buf, n);
- if (IS_ERR(wbuf))
- return PTR_ERR(wbuf);
-
-#ifdef LIRC_TIMER
- if (timer == 0) {
- /* try again if device is ready */
- timer = init_lirc_timer();
- if (timer == 0) {
- ret = -EIO;
- goto out;
- }
- }
-
- /* adjust values from usecs */
- for (i = 0; i < count; i++) {
- __u64 helper;
-
- helper = ((__u64) wbuf[i])*timer;
- do_div(helper, 1000000);
- wbuf[i] = (int) helper;
- }
-
- local_irq_save(flags);
- i = 0;
- while (i < count) {
- level = lirc_get_timer();
- counttimer = 0;
- lirc_on();
- do {
- newlevel = lirc_get_timer();
- if (level == 0 && newlevel != 0)
- counttimer++;
- level = newlevel;
- if (check_pselecd && (in(1) & LP_PSELECD)) {
- lirc_off();
- local_irq_restore(flags);
- ret = -EIO;
- goto out;
- }
- } while (counttimer < wbuf[i]);
- i++;
-
- lirc_off();
- if (i == count)
- break;
- counttimer = 0;
- do {
- newlevel = lirc_get_timer();
- if (level == 0 && newlevel != 0)
- counttimer++;
- level = newlevel;
- if (check_pselecd && (in(1) & LP_PSELECD)) {
- local_irq_restore(flags);
- ret = -EIO;
- goto out;
- }
- } while (counttimer < wbuf[i]);
- i++;
- }
- local_irq_restore(flags);
-#else
- /* place code that handles write without external timer here */
-#endif
- ret = n;
-out:
- kfree(wbuf);
-
- return ret;
-}
-
-static unsigned int lirc_poll(struct file *file, poll_table *wait)
-{
- poll_wait(file, &lirc_wait, wait);
- if (rptr != wptr)
- return POLLIN | POLLRDNORM;
- return 0;
-}
-
-static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
-{
- int result;
- __u32 features = LIRC_CAN_SET_TRANSMITTER_MASK |
- LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2;
- __u32 mode;
- __u32 value;
-
- switch (cmd) {
- case LIRC_GET_FEATURES:
- result = put_user(features, (__u32 *) arg);
- if (result)
- return result;
- break;
- case LIRC_GET_SEND_MODE:
- result = put_user(LIRC_MODE_PULSE, (__u32 *) arg);
- if (result)
- return result;
- break;
- case LIRC_GET_REC_MODE:
- result = put_user(LIRC_MODE_MODE2, (__u32 *) arg);
- if (result)
- return result;
- break;
- case LIRC_SET_SEND_MODE:
- result = get_user(mode, (__u32 *) arg);
- if (result)
- return result;
- if (mode != LIRC_MODE_PULSE)
- return -EINVAL;
- break;
- case LIRC_SET_REC_MODE:
- result = get_user(mode, (__u32 *) arg);
- if (result)
- return result;
- if (mode != LIRC_MODE_MODE2)
- return -ENOSYS;
- break;
- case LIRC_SET_TRANSMITTER_MASK:
- result = get_user(value, (__u32 *) arg);
- if (result)
- return result;
- if ((value & LIRC_PARALLEL_TRANSMITTER_MASK) != value)
- return LIRC_PARALLEL_MAX_TRANSMITTERS;
- tx_mask = value;
- break;
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
-}
-
-static int lirc_open(struct inode *node, struct file *filep)
-{
- if (is_open || !lirc_claim())
- return -EBUSY;
-
- parport_enable_irq(pport);
-
- /* init read ptr */
- rptr = 0;
- wptr = 0;
- lost_irqs = 0;
-
- is_open = 1;
- return 0;
-}
-
-static int lirc_close(struct inode *node, struct file *filep)
-{
- if (is_claimed) {
- is_claimed = 0;
- parport_release(ppdevice);
- }
- is_open = 0;
- return 0;
-}
-
-static const struct file_operations lirc_fops = {
- .owner = THIS_MODULE,
- .llseek = lirc_lseek,
- .read = lirc_read,
- .write = lirc_write,
- .poll = lirc_poll,
- .unlocked_ioctl = lirc_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = lirc_ioctl,
-#endif
- .open = lirc_open,
- .release = lirc_close
-};
-
-static int set_use_inc(void *data)
-{
- return 0;
-}
-
-static void set_use_dec(void *data)
-{
-}
-
-static struct lirc_driver driver = {
- .name = LIRC_DRIVER_NAME,
- .minor = -1,
- .code_length = 1,
- .sample_rate = 0,
- .data = NULL,
- .add_to_buf = NULL,
- .set_use_inc = set_use_inc,
- .set_use_dec = set_use_dec,
- .fops = &lirc_fops,
- .dev = NULL,
- .owner = THIS_MODULE,
-};
-
-static struct platform_device *lirc_parallel_dev;
-
-static int __devinit lirc_parallel_probe(struct platform_device *dev)
-{
- return 0;
-}
-
-static int __devexit lirc_parallel_remove(struct platform_device *dev)
-{
- return 0;
-}
-
-static int lirc_parallel_suspend(struct platform_device *dev,
- pm_message_t state)
-{
- return 0;
-}
-
-static int lirc_parallel_resume(struct platform_device *dev)
-{
- return 0;
-}
-
-static struct platform_driver lirc_parallel_driver = {
- .probe = lirc_parallel_probe,
- .remove = __devexit_p(lirc_parallel_remove),
- .suspend = lirc_parallel_suspend,
- .resume = lirc_parallel_resume,
- .driver = {
- .name = LIRC_DRIVER_NAME,
- .owner = THIS_MODULE,
- },
-};
-
-static int pf(void *handle);
-static void kf(void *handle);
-
-static int pf(void *handle)
-{
- parport_disable_irq(pport);
- is_claimed = 0;
- return 0;
-}
-
-static void kf(void *handle)
-{
- if (!is_open)
- return;
- if (!lirc_claim())
- return;
- parport_enable_irq(pport);
- lirc_off();
- /* this is a bit annoying when you actually print...*/
- /*
- printk(KERN_INFO "%s: reclaimed port\n", LIRC_DRIVER_NAME);
- */
-}
-
-/*** module initialization and cleanup ***/
-
-static int __init lirc_parallel_init(void)
-{
- int result;
-
- result = platform_driver_register(&lirc_parallel_driver);
- if (result) {
- printk(KERN_NOTICE "platform_driver_register"
- " returned %d\n", result);
- return result;
- }
-
- lirc_parallel_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
- if (!lirc_parallel_dev) {
- result = -ENOMEM;
- goto exit_driver_unregister;
- }
-
- result = platform_device_add(lirc_parallel_dev);
- if (result)
- goto exit_device_put;
-
- pport = parport_find_base(io);
- if (pport == NULL) {
- printk(KERN_NOTICE "%s: no port at %x found\n",
- LIRC_DRIVER_NAME, io);
- result = -ENXIO;
- goto exit_device_put;
- }
- ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME,
- pf, kf, irq_handler, 0, NULL);
- parport_put_port(pport);
- if (ppdevice == NULL) {
- printk(KERN_NOTICE "%s: parport_register_device() failed\n",
- LIRC_DRIVER_NAME);
- result = -ENXIO;
- goto exit_device_put;
- }
- if (parport_claim(ppdevice) != 0)
- goto skip_init;
- is_claimed = 1;
- out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP);
-
-#ifdef LIRC_TIMER
- if (debug)
- out(LIRC_PORT_DATA, tx_mask);
-
- timer = init_lirc_timer();
-
-#if 0 /* continue even if device is offline */
- if (timer == 0) {
- is_claimed = 0;
- parport_release(pport);
- parport_unregister_device(ppdevice);
- result = -EIO;
- goto exit_device_put;
- }
-
-#endif
- if (debug)
- out(LIRC_PORT_DATA, 0);
-#endif
-
- is_claimed = 0;
- parport_release(ppdevice);
- skip_init:
- driver.dev = &lirc_parallel_dev->dev;
- driver.minor = lirc_register_driver(&driver);
- if (driver.minor < 0) {
- printk(KERN_NOTICE "%s: register_chrdev() failed\n",
- LIRC_DRIVER_NAME);
- parport_unregister_device(ppdevice);
- result = -EIO;
- goto exit_device_put;
- }
- printk(KERN_INFO "%s: installed using port 0x%04x irq %d\n",
- LIRC_DRIVER_NAME, io, irq);
- return 0;
-
-exit_device_put:
- platform_device_put(lirc_parallel_dev);
-exit_driver_unregister:
- platform_driver_unregister(&lirc_parallel_driver);
- return result;
-}
-
-static void __exit lirc_parallel_exit(void)
-{
- parport_unregister_device(ppdevice);
- lirc_unregister_driver(driver.minor);
-}
-
-module_init(lirc_parallel_init);
-module_exit(lirc_parallel_exit);
-
-MODULE_DESCRIPTION("Infrared receiver driver for parallel ports.");
-MODULE_AUTHOR("Christoph Bartelmus");
-MODULE_LICENSE("GPL");
-
-module_param(io, int, S_IRUGO);
-MODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)");
-
-module_param(irq, int, S_IRUGO);
-MODULE_PARM_DESC(irq, "Interrupt (7 or 5)");
-
-module_param(tx_mask, int, S_IRUGO);
-MODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
-
-module_param(check_pselecd, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Check for printer (default: 0)");
diff --git a/drivers/staging/lirc/lirc_parallel.h b/drivers/staging/lirc/lirc_parallel.h
deleted file mode 100644
index 4bed6afe063..00000000000
--- a/drivers/staging/lirc/lirc_parallel.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* lirc_parallel.h */
-
-#ifndef _LIRC_PARALLEL_H
-#define _LIRC_PARALLEL_H
-
-#include <linux/lp.h>
-
-#define LIRC_PORT_LEN 3
-
-#define LIRC_LP_BASE 0
-#define LIRC_LP_STATUS 1
-#define LIRC_LP_CONTROL 2
-
-#define LIRC_PORT_DATA LIRC_LP_BASE /* base */
-#define LIRC_PORT_TIMER LIRC_LP_STATUS /* status port */
-#define LIRC_PORT_TIMER_BIT LP_PBUSY /* busy signal */
-#define LIRC_PORT_SIGNAL LIRC_LP_STATUS /* status port */
-#define LIRC_PORT_SIGNAL_BIT LP_PACK /* ack signal */
-#define LIRC_PORT_IRQ LIRC_LP_CONTROL /* control port */
-
-#define LIRC_SFH506_DELAY 0 /* delay t_phl in usecs */
-
-#define LIRC_PARALLEL_MAX_TRANSMITTERS 8
-#define LIRC_PARALLEL_TRANSMITTER_MASK ((1<<LIRC_PARALLEL_MAX_TRANSMITTERS) - 1)
-
-#endif
diff --git a/drivers/staging/lirc/lirc_sasem.c b/drivers/staging/lirc/lirc_sasem.c
deleted file mode 100644
index 7080cdeab5a..00000000000
--- a/drivers/staging/lirc/lirc_sasem.c
+++ /dev/null
@@ -1,939 +0,0 @@
-/*
- * lirc_sasem.c - USB remote support for LIRC
- * Version 0.5
- *
- * Copyright (C) 2004-2005 Oliver Stabel <oliver.stabel@gmx.de>
- * Tim Davies <tim@opensystems.net.au>
- *
- * This driver was derived from:
- * Venky Raju <dev@venky.ws>
- * "lirc_imon - "LIRC/VFD driver for Ahanix/Soundgraph IMON IR/VFD"
- * Paul Miller <pmiller9@users.sourceforge.net>'s 2003-2004
- * "lirc_atiusb - USB remote support for LIRC"
- * Culver Consulting Services <henry@culcon.com>'s 2003
- * "Sasem OnAir VFD/IR USB driver"
- *
- *
- * NOTE - The LCDproc iMon driver should work with this module. More info at
- * http://www.frogstorm.info/sasem
- */
-
-/*
- * 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
- */
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/usb.h>
-
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-
-
-#define MOD_AUTHOR "Oliver Stabel <oliver.stabel@gmx.de>, " \
- "Tim Davies <tim@opensystems.net.au>"
-#define MOD_DESC "USB Driver for Sasem Remote Controller V1.1"
-#define MOD_NAME "lirc_sasem"
-#define MOD_VERSION "0.5"
-
-#define VFD_MINOR_BASE 144 /* Same as LCD */
-#define DEVICE_NAME "lcd%d"
-
-#define BUF_CHUNK_SIZE 8
-#define BUF_SIZE 128
-
-#define IOCTL_LCD_CONTRAST 1
-
-/*** P R O T O T Y P E S ***/
-
-/* USB Callback prototypes */
-static int sasem_probe(struct usb_interface *interface,
- const struct usb_device_id *id);
-static void sasem_disconnect(struct usb_interface *interface);
-static void usb_rx_callback(struct urb *urb);
-static void usb_tx_callback(struct urb *urb);
-
-/* VFD file_operations function prototypes */
-static int vfd_open(struct inode *inode, struct file *file);
-static long vfd_ioctl(struct file *file, unsigned cmd, unsigned long arg);
-static int vfd_close(struct inode *inode, struct file *file);
-static ssize_t vfd_write(struct file *file, const char *buf,
- size_t n_bytes, loff_t *pos);
-
-/* LIRC driver function prototypes */
-static int ir_open(void *data);
-static void ir_close(void *data);
-
-/* Driver init/exit prototypes */
-static int __init sasem_init(void);
-static void __exit sasem_exit(void);
-
-/*** G L O B A L S ***/
-#define SASEM_DATA_BUF_SZ 32
-
-struct sasem_context {
-
- struct usb_device *dev;
- int vfd_isopen; /* VFD port has been opened */
- unsigned int vfd_contrast; /* VFD contrast */
- int ir_isopen; /* IR port has been opened */
- int dev_present; /* USB device presence */
- struct mutex ctx_lock; /* to lock this object */
- wait_queue_head_t remove_ok; /* For unexpected USB disconnects */
-
- struct lirc_driver *driver;
- struct usb_endpoint_descriptor *rx_endpoint;
- struct usb_endpoint_descriptor *tx_endpoint;
- struct urb *rx_urb;
- struct urb *tx_urb;
- unsigned char usb_rx_buf[8];
- unsigned char usb_tx_buf[8];
-
- struct tx_t {
- unsigned char data_buf[SASEM_DATA_BUF_SZ]; /* user data buffer */
- struct completion finished; /* wait for write to finish */
- atomic_t busy; /* write in progress */
- int status; /* status of tx completion */
- } tx;
-
- /* for dealing with repeat codes (wish there was a toggle bit!) */
- struct timeval presstime;
- char lastcode[8];
- int codesaved;
-};
-
-/* VFD file operations */
-static const struct file_operations vfd_fops = {
- .owner = THIS_MODULE,
- .open = &vfd_open,
- .write = &vfd_write,
- .unlocked_ioctl = &vfd_ioctl,
- .release = &vfd_close,
- .llseek = noop_llseek,
-};
-
-/* USB Device ID for Sasem USB Control Board */
-static struct usb_device_id sasem_usb_id_table[] = {
- /* Sasem USB Control Board */
- { USB_DEVICE(0x11ba, 0x0101) },
- /* Terminating entry */
- {}
-};
-
-/* USB Device data */
-static struct usb_driver sasem_driver = {
- .name = MOD_NAME,
- .probe = sasem_probe,
- .disconnect = sasem_disconnect,
- .id_table = sasem_usb_id_table,
-};
-
-static struct usb_class_driver sasem_class = {
- .name = DEVICE_NAME,
- .fops = &vfd_fops,
- .minor_base = VFD_MINOR_BASE,
-};
-
-/* to prevent races between open() and disconnect() */
-static DEFINE_MUTEX(disconnect_lock);
-
-static int debug;
-
-
-/*** M O D U L E C O D E ***/
-
-MODULE_AUTHOR(MOD_AUTHOR);
-MODULE_DESCRIPTION(MOD_DESC);
-MODULE_LICENSE("GPL");
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)");
-
-static void delete_context(struct sasem_context *context)
-{
- usb_free_urb(context->tx_urb); /* VFD */
- usb_free_urb(context->rx_urb); /* IR */
- lirc_buffer_free(context->driver->rbuf);
- kfree(context->driver->rbuf);
- kfree(context->driver);
- kfree(context);
-
- if (debug)
- printk(KERN_INFO "%s: context deleted\n", __func__);
-}
-
-static void deregister_from_lirc(struct sasem_context *context)
-{
- int retval;
- int minor = context->driver->minor;
-
- retval = lirc_unregister_driver(minor);
- if (retval)
- err("%s: unable to deregister from lirc (%d)",
- __func__, retval);
- else
- printk(KERN_INFO "Deregistered Sasem driver (minor:%d)\n",
- minor);
-
-}
-
-/**
- * Called when the VFD device (e.g. /dev/usb/lcd)
- * is opened by the application.
- */
-static int vfd_open(struct inode *inode, struct file *file)
-{
- struct usb_interface *interface;
- struct sasem_context *context = NULL;
- int subminor;
- int retval = 0;
-
- /* prevent races with disconnect */
- mutex_lock(&disconnect_lock);
-
- subminor = iminor(inode);
- interface = usb_find_interface(&sasem_driver, subminor);
- if (!interface) {
- err("%s: could not find interface for minor %d",
- __func__, subminor);
- retval = -ENODEV;
- goto exit;
- }
- context = usb_get_intfdata(interface);
-
- if (!context) {
- err("%s: no context found for minor %d",
- __func__, subminor);
- retval = -ENODEV;
- goto exit;
- }
-
- mutex_lock(&context->ctx_lock);
-
- if (context->vfd_isopen) {
- err("%s: VFD port is already open", __func__);
- retval = -EBUSY;
- } else {
- context->vfd_isopen = 1;
- file->private_data = context;
- printk(KERN_INFO "VFD port opened\n");
- }
-
- mutex_unlock(&context->ctx_lock);
-
-exit:
- mutex_unlock(&disconnect_lock);
- return retval;
-}
-
-/**
- * Called when the VFD device (e.g. /dev/usb/lcd)
- * is closed by the application.
- */
-static long vfd_ioctl(struct file *file, unsigned cmd, unsigned long arg)
-{
- struct sasem_context *context = NULL;
-
- context = (struct sasem_context *) file->private_data;
-
- if (!context) {
- err("%s: no context for device", __func__);
- return -ENODEV;
- }
-
- mutex_lock(&context->ctx_lock);
-
- switch (cmd) {
- case IOCTL_LCD_CONTRAST:
- if (arg > 1000)
- arg = 1000;
- context->vfd_contrast = (unsigned int)arg;
- break;
- default:
- printk(KERN_INFO "Unknown IOCTL command\n");
- mutex_unlock(&context->ctx_lock);
- return -ENOIOCTLCMD; /* not supported */
- }
-
- mutex_unlock(&context->ctx_lock);
- return 0;
-}
-
-/**
- * Called when the VFD device (e.g. /dev/usb/lcd)
- * is closed by the application.
- */
-static int vfd_close(struct inode *inode, struct file *file)
-{
- struct sasem_context *context = NULL;
- int retval = 0;
-
- context = (struct sasem_context *) file->private_data;
-
- if (!context) {
- err("%s: no context for device", __func__);
- return -ENODEV;
- }
-
- mutex_lock(&context->ctx_lock);
-
- if (!context->vfd_isopen) {
- err("%s: VFD is not open", __func__);
- retval = -EIO;
- } else {
- context->vfd_isopen = 0;
- printk(KERN_INFO "VFD port closed\n");
- if (!context->dev_present && !context->ir_isopen) {
-
- /* Device disconnected before close and IR port is
- * not open. If IR port is open, context will be
- * deleted by ir_close. */
- mutex_unlock(&context->ctx_lock);
- delete_context(context);
- return retval;
- }
- }
-
- mutex_unlock(&context->ctx_lock);
- return retval;
-}
-
-/**
- * Sends a packet to the VFD.
- */
-static int send_packet(struct sasem_context *context)
-{
- unsigned int pipe;
- int interval = 0;
- int retval = 0;
-
- pipe = usb_sndintpipe(context->dev,
- context->tx_endpoint->bEndpointAddress);
- interval = context->tx_endpoint->bInterval;
-
- usb_fill_int_urb(context->tx_urb, context->dev, pipe,
- context->usb_tx_buf, sizeof(context->usb_tx_buf),
- usb_tx_callback, context, interval);
-
- context->tx_urb->actual_length = 0;
-
- init_completion(&context->tx.finished);
- atomic_set(&(context->tx.busy), 1);
-
- retval = usb_submit_urb(context->tx_urb, GFP_KERNEL);
- if (retval) {
- atomic_set(&(context->tx.busy), 0);
- err("%s: error submitting urb (%d)", __func__, retval);
- } else {
- /* Wait for transmission to complete (or abort) */
- mutex_unlock(&context->ctx_lock);
- wait_for_completion(&context->tx.finished);
- mutex_lock(&context->ctx_lock);
-
- retval = context->tx.status;
- if (retval)
- err("%s: packet tx failed (%d)", __func__, retval);
- }
-
- return retval;
-}
-
-/**
- * Writes data to the VFD. The Sasem VFD is 2x16 characters
- * and requires data in 9 consecutive USB interrupt packets,
- * each packet carrying 8 bytes.
- */
-static ssize_t vfd_write(struct file *file, const char *buf,
- size_t n_bytes, loff_t *pos)
-{
- int i;
- int retval = 0;
- struct sasem_context *context;
- int *data_buf = NULL;
-
- context = (struct sasem_context *) file->private_data;
- if (!context) {
- err("%s: no context for device", __func__);
- return -ENODEV;
- }
-
- mutex_lock(&context->ctx_lock);
-
- if (!context->dev_present) {
- err("%s: no Sasem device present", __func__);
- retval = -ENODEV;
- goto exit;
- }
-
- if (n_bytes <= 0 || n_bytes > SASEM_DATA_BUF_SZ) {
- err("%s: invalid payload size", __func__);
- retval = -EINVAL;
- goto exit;
- }
-
- data_buf = memdup_user(buf, n_bytes);
- if (IS_ERR(data_buf)) {
- retval = PTR_ERR(data_buf);
- goto exit;
- }
-
- memcpy(context->tx.data_buf, data_buf, n_bytes);
-
- /* Pad with spaces */
- for (i = n_bytes; i < SASEM_DATA_BUF_SZ; ++i)
- context->tx.data_buf[i] = ' ';
-
- /* Nine 8 byte packets to be sent */
- /* NOTE: "\x07\x01\0\0\0\0\0\0" or "\x0c\0\0\0\0\0\0\0"
- * will clear the VFD */
- for (i = 0; i < 9; i++) {
- switch (i) {
- case 0:
- memcpy(context->usb_tx_buf, "\x07\0\0\0\0\0\0\0", 8);
- context->usb_tx_buf[1] = (context->vfd_contrast) ?
- (0x2B - (context->vfd_contrast - 1) / 250)
- : 0x2B;
- break;
- case 1:
- memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8);
- break;
- case 2:
- memcpy(context->usb_tx_buf, "\x0b\x01\0\0\0\0\0\0", 8);
- break;
- case 3:
- memcpy(context->usb_tx_buf, context->tx.data_buf, 8);
- break;
- case 4:
- memcpy(context->usb_tx_buf,
- context->tx.data_buf + 8, 8);
- break;
- case 5:
- memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8);
- break;
- case 6:
- memcpy(context->usb_tx_buf, "\x0b\x02\0\0\0\0\0\0", 8);
- break;
- case 7:
- memcpy(context->usb_tx_buf,
- context->tx.data_buf + 16, 8);
- break;
- case 8:
- memcpy(context->usb_tx_buf,
- context->tx.data_buf + 24, 8);
- break;
- }
- retval = send_packet(context);
- if (retval) {
-
- err("%s: send packet failed for packet #%d",
- __func__, i);
- goto exit;
- }
- }
-exit:
-
- mutex_unlock(&context->ctx_lock);
- kfree(data_buf);
-
- return (!retval) ? n_bytes : retval;
-}
-
-/**
- * Callback function for USB core API: transmit data
- */
-static void usb_tx_callback(struct urb *urb)
-{
- struct sasem_context *context;
-
- if (!urb)
- return;
- context = (struct sasem_context *) urb->context;
- if (!context)
- return;
-
- context->tx.status = urb->status;
-
- /* notify waiters that write has finished */
- atomic_set(&context->tx.busy, 0);
- complete(&context->tx.finished);
-
- return;
-}
-
-/**
- * Called by lirc_dev when the application opens /dev/lirc
- */
-static int ir_open(void *data)
-{
- int retval = 0;
- struct sasem_context *context;
-
- /* prevent races with disconnect */
- mutex_lock(&disconnect_lock);
-
- context = (struct sasem_context *) data;
-
- mutex_lock(&context->ctx_lock);
-
- if (context->ir_isopen) {
- err("%s: IR port is already open", __func__);
- retval = -EBUSY;
- goto exit;
- }
-
- usb_fill_int_urb(context->rx_urb, context->dev,
- usb_rcvintpipe(context->dev,
- context->rx_endpoint->bEndpointAddress),
- context->usb_rx_buf, sizeof(context->usb_rx_buf),
- usb_rx_callback, context, context->rx_endpoint->bInterval);
-
- retval = usb_submit_urb(context->rx_urb, GFP_KERNEL);
-
- if (retval)
- err("%s: usb_submit_urb failed for ir_open (%d)",
- __func__, retval);
- else {
- context->ir_isopen = 1;
- printk(KERN_INFO "IR port opened\n");
- }
-
-exit:
- mutex_unlock(&context->ctx_lock);
-
- mutex_unlock(&disconnect_lock);
- return retval;
-}
-
-/**
- * Called by lirc_dev when the application closes /dev/lirc
- */
-static void ir_close(void *data)
-{
- struct sasem_context *context;
-
- context = (struct sasem_context *)data;
- if (!context) {
- err("%s: no context for device", __func__);
- return;
- }
-
- mutex_lock(&context->ctx_lock);
-
- usb_kill_urb(context->rx_urb);
- context->ir_isopen = 0;
- printk(KERN_INFO "IR port closed\n");
-
- if (!context->dev_present) {
-
- /*
- * Device disconnected while IR port was
- * still open. Driver was not deregistered
- * at disconnect time, so do it now.
- */
- deregister_from_lirc(context);
-
- if (!context->vfd_isopen) {
-
- mutex_unlock(&context->ctx_lock);
- delete_context(context);
- return;
- }
- /* If VFD port is open, context will be deleted by vfd_close */
- }
-
- mutex_unlock(&context->ctx_lock);
- return;
-}
-
-/**
- * Process the incoming packet
- */
-static void incoming_packet(struct sasem_context *context,
- struct urb *urb)
-{
- int len = urb->actual_length;
- unsigned char *buf = urb->transfer_buffer;
- long ms;
- struct timeval tv;
- int i;
-
- if (len != 8) {
- printk(KERN_WARNING "%s: invalid incoming packet size (%d)\n",
- __func__, len);
- return;
- }
-
- if (debug) {
- printk(KERN_INFO "Incoming data: ");
- for (i = 0; i < 8; ++i)
- printk(KERN_CONT "%02x ", buf[i]);
- printk(KERN_CONT "\n");
- }
-
- /*
- * Lirc could deal with the repeat code, but we really need to block it
- * if it arrives too late. Otherwise we could repeat the wrong code.
- */
-
- /* get the time since the last button press */
- do_gettimeofday(&tv);
- ms = (tv.tv_sec - context->presstime.tv_sec) * 1000 +
- (tv.tv_usec - context->presstime.tv_usec) / 1000;
-
- if (memcmp(buf, "\x08\0\0\0\0\0\0\0", 8) == 0) {
- /*
- * the repeat code is being sent, so we copy
- * the old code to LIRC
- */
-
- /*
- * NOTE: Only if the last code was less than 250ms ago
- * - no one should be able to push another (undetected) button
- * in that time and then get a false repeat of the previous
- * press but it is long enough for a genuine repeat
- */
- if ((ms < 250) && (context->codesaved != 0)) {
- memcpy(buf, &context->lastcode, 8);
- context->presstime.tv_sec = tv.tv_sec;
- context->presstime.tv_usec = tv.tv_usec;
- }
- } else {
- /* save the current valid code for repeats */
- memcpy(&context->lastcode, buf, 8);
- /*
- * set flag to signal a valid code was save;
- * just for safety reasons
- */
- context->codesaved = 1;
- context->presstime.tv_sec = tv.tv_sec;
- context->presstime.tv_usec = tv.tv_usec;
- }
-
- lirc_buffer_write(context->driver->rbuf, buf);
- wake_up(&context->driver->rbuf->wait_poll);
-}
-
-/**
- * Callback function for USB core API: receive data
- */
-static void usb_rx_callback(struct urb *urb)
-{
- struct sasem_context *context;
-
- if (!urb)
- return;
- context = (struct sasem_context *) urb->context;
- if (!context)
- return;
-
- switch (urb->status) {
-
- case -ENOENT: /* usbcore unlink successful! */
- return;
-
- case 0:
- if (context->ir_isopen)
- incoming_packet(context, urb);
- break;
-
- default:
- printk(KERN_WARNING "%s: status (%d): ignored",
- __func__, urb->status);
- break;
- }
-
- usb_submit_urb(context->rx_urb, GFP_ATOMIC);
- return;
-}
-
-
-
-/**
- * Callback function for USB core API: Probe
- */
-static int sasem_probe(struct usb_interface *interface,
- const struct usb_device_id *id)
-{
- struct usb_device *dev = NULL;
- struct usb_host_interface *iface_desc = NULL;
- struct usb_endpoint_descriptor *rx_endpoint = NULL;
- struct usb_endpoint_descriptor *tx_endpoint = NULL;
- struct urb *rx_urb = NULL;
- struct urb *tx_urb = NULL;
- struct lirc_driver *driver = NULL;
- struct lirc_buffer *rbuf = NULL;
- int lirc_minor = 0;
- int num_endpoints;
- int retval = 0;
- int vfd_ep_found;
- int ir_ep_found;
- int alloc_status;
- struct sasem_context *context = NULL;
- int i;
-
- printk(KERN_INFO "%s: found Sasem device\n", __func__);
-
-
- dev = usb_get_dev(interface_to_usbdev(interface));
- iface_desc = interface->cur_altsetting;
- num_endpoints = iface_desc->desc.bNumEndpoints;
-
- /*
- * Scan the endpoint list and set:
- * first input endpoint = IR endpoint
- * first output endpoint = VFD endpoint
- */
-
- ir_ep_found = 0;
- vfd_ep_found = 0;
-
- for (i = 0; i < num_endpoints && !(ir_ep_found && vfd_ep_found); ++i) {
-
- struct usb_endpoint_descriptor *ep;
- int ep_dir;
- int ep_type;
- ep = &iface_desc->endpoint [i].desc;
- ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
- ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-
- if (!ir_ep_found &&
- ep_dir == USB_DIR_IN &&
- ep_type == USB_ENDPOINT_XFER_INT) {
-
- rx_endpoint = ep;
- ir_ep_found = 1;
- if (debug)
- printk(KERN_INFO "%s: found IR endpoint\n",
- __func__);
-
- } else if (!vfd_ep_found &&
- ep_dir == USB_DIR_OUT &&
- ep_type == USB_ENDPOINT_XFER_INT) {
-
- tx_endpoint = ep;
- vfd_ep_found = 1;
- if (debug)
- printk(KERN_INFO "%s: found VFD endpoint\n",
- __func__);
- }
- }
-
- /* Input endpoint is mandatory */
- if (!ir_ep_found) {
-
- err("%s: no valid input (IR) endpoint found.", __func__);
- retval = -ENODEV;
- goto exit;
- }
-
- if (!vfd_ep_found)
- printk(KERN_INFO "%s: no valid output (VFD) endpoint found.\n",
- __func__);
-
-
- /* Allocate memory */
- alloc_status = 0;
-
- context = kzalloc(sizeof(struct sasem_context), GFP_KERNEL);
- if (!context) {
- err("%s: kzalloc failed for context", __func__);
- alloc_status = 1;
- goto alloc_status_switch;
- }
- driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
- if (!driver) {
- err("%s: kzalloc failed for lirc_driver", __func__);
- alloc_status = 2;
- goto alloc_status_switch;
- }
- rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
- if (!rbuf) {
- err("%s: kmalloc failed for lirc_buffer", __func__);
- alloc_status = 3;
- goto alloc_status_switch;
- }
- if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) {
- err("%s: lirc_buffer_init failed", __func__);
- alloc_status = 4;
- goto alloc_status_switch;
- }
- rx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!rx_urb) {
- err("%s: usb_alloc_urb failed for IR urb", __func__);
- alloc_status = 5;
- goto alloc_status_switch;
- }
- if (vfd_ep_found) {
- tx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!tx_urb) {
- err("%s: usb_alloc_urb failed for VFD urb",
- __func__);
- alloc_status = 6;
- goto alloc_status_switch;
- }
- }
-
- mutex_init(&context->ctx_lock);
-
- strcpy(driver->name, MOD_NAME);
- driver->minor = -1;
- driver->code_length = 64;
- driver->sample_rate = 0;
- driver->features = LIRC_CAN_REC_LIRCCODE;
- driver->data = context;
- driver->rbuf = rbuf;
- driver->set_use_inc = ir_open;
- driver->set_use_dec = ir_close;
- driver->dev = &interface->dev;
- driver->owner = THIS_MODULE;
-
- mutex_lock(&context->ctx_lock);
-
- lirc_minor = lirc_register_driver(driver);
- if (lirc_minor < 0) {
- err("%s: lirc_register_driver failed", __func__);
- alloc_status = 7;
- retval = lirc_minor;
- goto unlock;
- } else
- printk(KERN_INFO "%s: Registered Sasem driver (minor:%d)\n",
- __func__, lirc_minor);
-
-alloc_status_switch:
-
- switch (alloc_status) {
-
- case 7:
- if (vfd_ep_found)
- usb_free_urb(tx_urb);
- case 6:
- usb_free_urb(rx_urb);
- case 5:
- lirc_buffer_free(rbuf);
- case 4:
- kfree(rbuf);
- case 3:
- kfree(driver);
- case 2:
- kfree(context);
- context = NULL;
- case 1:
- retval = -ENOMEM;
- goto unlock;
- }
-
- /* Needed while unregistering! */
- driver->minor = lirc_minor;
-
- context->dev = dev;
- context->dev_present = 1;
- context->rx_endpoint = rx_endpoint;
- context->rx_urb = rx_urb;
- if (vfd_ep_found) {
- context->tx_endpoint = tx_endpoint;
- context->tx_urb = tx_urb;
- context->vfd_contrast = 1000; /* range 0 - 1000 */
- }
- context->driver = driver;
-
- usb_set_intfdata(interface, context);
-
- if (vfd_ep_found) {
-
- if (debug)
- printk(KERN_INFO "Registering VFD with sysfs\n");
- if (usb_register_dev(interface, &sasem_class))
- /* Not a fatal error, so ignore */
- printk(KERN_INFO "%s: could not get a minor number "
- "for VFD\n", __func__);
- }
-
- printk(KERN_INFO "%s: Sasem device on usb<%d:%d> initialized\n",
- __func__, dev->bus->busnum, dev->devnum);
-unlock:
- mutex_unlock(&context->ctx_lock);
-exit:
- return retval;
-}
-
-/**
- * Callback function for USB core API: disonnect
- */
-static void sasem_disconnect(struct usb_interface *interface)
-{
- struct sasem_context *context;
-
- /* prevent races with ir_open()/vfd_open() */
- mutex_lock(&disconnect_lock);
-
- context = usb_get_intfdata(interface);
- mutex_lock(&context->ctx_lock);
-
- printk(KERN_INFO "%s: Sasem device disconnected\n", __func__);
-
- usb_set_intfdata(interface, NULL);
- context->dev_present = 0;
-
- /* Stop reception */
- usb_kill_urb(context->rx_urb);
-
- /* Abort ongoing write */
- if (atomic_read(&context->tx.busy)) {
-
- usb_kill_urb(context->tx_urb);
- wait_for_completion(&context->tx.finished);
- }
-
- /* De-register from lirc_dev if IR port is not open */
- if (!context->ir_isopen)
- deregister_from_lirc(context);
-
- usb_deregister_dev(interface, &sasem_class);
-
- mutex_unlock(&context->ctx_lock);
-
- if (!context->ir_isopen && !context->vfd_isopen)
- delete_context(context);
-
- mutex_unlock(&disconnect_lock);
-}
-
-static int __init sasem_init(void)
-{
- int rc;
-
- printk(KERN_INFO MOD_DESC ", v" MOD_VERSION "\n");
- printk(KERN_INFO MOD_AUTHOR "\n");
-
- rc = usb_register(&sasem_driver);
- if (rc < 0) {
- err("%s: usb register failed (%d)", __func__, rc);
- return -ENODEV;
- }
- return 0;
-}
-
-static void __exit sasem_exit(void)
-{
- usb_deregister(&sasem_driver);
- printk(KERN_INFO "module removed. Goodbye!\n");
-}
-
-
-module_init(sasem_init);
-module_exit(sasem_exit);
diff --git a/drivers/staging/lirc/lirc_serial.c b/drivers/staging/lirc/lirc_serial.c
deleted file mode 100644
index 4a3cca03224..00000000000
--- a/drivers/staging/lirc/lirc_serial.c
+++ /dev/null
@@ -1,1317 +0,0 @@
-/*
- * lirc_serial.c
- *
- * lirc_serial - Device driver that records pulse- and pause-lengths
- * (space-lengths) between DDCD event on a serial port.
- *
- * Copyright (C) 1996,97 Ralph Metzler <rjkm@thp.uni-koeln.de>
- * Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu>
- * Copyright (C) 1998 Ben Pfaff <blp@gnu.org>
- * Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de>
- * Copyright (C) 2007 Andrei Tanas <andrei@tanas.ca> (suspend/resume support)
- * 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
- *
- */
-
-/*
- * Steve's changes to improve transmission fidelity:
- * - for systems with the rdtsc instruction and the clock counter, a
- * send_pule that times the pulses directly using the counter.
- * This means that the LIRC_SERIAL_TRANSMITTER_LATENCY fudge is
- * not needed. Measurement shows very stable waveform, even where
- * PCI activity slows the access to the UART, which trips up other
- * versions.
- * - For other system, non-integer-microsecond pulse/space lengths,
- * done using fixed point binary. So, much more accurate carrier
- * frequency.
- * - fine tuned transmitter latency, taking advantage of fractional
- * microseconds in previous change
- * - Fixed bug in the way transmitter latency was accounted for by
- * tuning the pulse lengths down - the send_pulse routine ignored
- * this overhead as it timed the overall pulse length - so the
- * pulse frequency was right but overall pulse length was too
- * long. Fixed by accounting for latency on each pulse/space
- * iteration.
- *
- * Steve Davies <steve@daviesfam.org> July 2001
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.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 <linux/platform_device.h>
-
-#include <asm/system.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/fcntl.h>
-#include <linux/spinlock.h>
-
-#ifdef CONFIG_LIRC_SERIAL_NSLU2
-#include <asm/hardware.h>
-#endif
-/* From Intel IXP42X Developer's Manual (#252480-005): */
-/* ftp://download.intel.com/design/network/manuals/25248005.pdf */
-#define UART_IE_IXP42X_UUE 0x40 /* IXP42X UART Unit enable */
-#define UART_IE_IXP42X_RTOIE 0x10 /* IXP42X Receiver Data Timeout int.enable */
-
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-
-#define LIRC_DRIVER_NAME "lirc_serial"
-
-struct lirc_serial {
- int signal_pin;
- int signal_pin_change;
- u8 on;
- u8 off;
- long (*send_pulse)(unsigned long length);
- void (*send_space)(long length);
- int features;
- spinlock_t lock;
-};
-
-#define LIRC_HOMEBREW 0
-#define LIRC_IRDEO 1
-#define LIRC_IRDEO_REMOTE 2
-#define LIRC_ANIMAX 3
-#define LIRC_IGOR 4
-#define LIRC_NSLU2 5
-
-/*** module parameters ***/
-static int type;
-static int io;
-static int irq;
-static int iommap;
-static int ioshift;
-static int softcarrier = 1;
-static int share_irq;
-static int debug;
-static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */
-static int txsense; /* 0 = active high, 1 = active low */
-
-#define dprintk(fmt, args...) \
- do { \
- if (debug) \
- printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \
- fmt, ## args); \
- } while (0)
-
-/* forward declarations */
-static long send_pulse_irdeo(unsigned long length);
-static long send_pulse_homebrew(unsigned long length);
-static void send_space_irdeo(long length);
-static void send_space_homebrew(long length);
-
-static struct lirc_serial hardware[] = {
- [LIRC_HOMEBREW] = {
- .signal_pin = UART_MSR_DCD,
- .signal_pin_change = UART_MSR_DDCD,
- .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR),
- .off = (UART_MCR_RTS | UART_MCR_OUT2),
- .send_pulse = send_pulse_homebrew,
- .send_space = send_space_homebrew,
-#ifdef CONFIG_LIRC_SERIAL_TRANSMITTER
- .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE |
- LIRC_CAN_SET_SEND_CARRIER |
- LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2)
-#else
- .features = LIRC_CAN_REC_MODE2
-#endif
- },
-
- [LIRC_IRDEO] = {
- .signal_pin = UART_MSR_DSR,
- .signal_pin_change = UART_MSR_DDSR,
- .on = UART_MCR_OUT2,
- .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
- .send_pulse = send_pulse_irdeo,
- .send_space = send_space_irdeo,
- .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE |
- LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2)
- },
-
- [LIRC_IRDEO_REMOTE] = {
- .signal_pin = UART_MSR_DSR,
- .signal_pin_change = UART_MSR_DDSR,
- .on = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
- .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
- .send_pulse = send_pulse_irdeo,
- .send_space = send_space_irdeo,
- .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE |
- LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2)
- },
-
- [LIRC_ANIMAX] = {
- .signal_pin = UART_MSR_DCD,
- .signal_pin_change = UART_MSR_DDCD,
- .on = 0,
- .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
- .send_pulse = NULL,
- .send_space = NULL,
- .features = LIRC_CAN_REC_MODE2
- },
-
- [LIRC_IGOR] = {
- .signal_pin = UART_MSR_DSR,
- .signal_pin_change = UART_MSR_DDSR,
- .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR),
- .off = (UART_MCR_RTS | UART_MCR_OUT2),
- .send_pulse = send_pulse_homebrew,
- .send_space = send_space_homebrew,
-#ifdef CONFIG_LIRC_SERIAL_TRANSMITTER
- .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE |
- LIRC_CAN_SET_SEND_CARRIER |
- LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2)
-#else
- .features = LIRC_CAN_REC_MODE2
-#endif
- },
-
-#ifdef CONFIG_LIRC_SERIAL_NSLU2
- /*
- * Modified Linksys Network Storage Link USB 2.0 (NSLU2):
- * We receive on CTS of the 2nd serial port (R142,LHS), we
- * transmit with a IR diode between GPIO[1] (green status LED),
- * and ground (Matthias Goebl <matthias.goebl@goebl.net>).
- * See also http://www.nslu2-linux.org for this device
- */
- [LIRC_NSLU2] = {
- .signal_pin = UART_MSR_CTS,
- .signal_pin_change = UART_MSR_DCTS,
- .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR),
- .off = (UART_MCR_RTS | UART_MCR_OUT2),
- .send_pulse = send_pulse_homebrew,
- .send_space = send_space_homebrew,
-#ifdef CONFIG_LIRC_SERIAL_TRANSMITTER
- .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE |
- LIRC_CAN_SET_SEND_CARRIER |
- LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2)
-#else
- .features = LIRC_CAN_REC_MODE2
-#endif
- },
-#endif
-
-};
-
-#define RS_ISR_PASS_LIMIT 256
-
-/*
- * A long pulse code from a remote might take up to 300 bytes. The
- * daemon should read the bytes as soon as they are generated, so take
- * the number of keys you think you can push before the daemon runs
- * and multiply by 300. The driver will warn you if you overrun this
- * buffer. If you have a slow computer or non-busmastering IDE disks,
- * maybe you will need to increase this.
- */
-
-/* This MUST be a power of two! It has to be larger than 1 as well. */
-
-#define RBUF_LEN 256
-
-static struct timeval lasttv = {0, 0};
-
-static struct lirc_buffer rbuf;
-
-static unsigned int freq = 38000;
-static unsigned int duty_cycle = 50;
-
-/* Initialized in init_timing_params() */
-static unsigned long period;
-static unsigned long pulse_width;
-static unsigned long space_width;
-
-#if defined(__i386__)
-/*
- * From:
- * Linux I/O port programming mini-HOWTO
- * Author: Riku Saikkonen <Riku.Saikkonen@hut.fi>
- * v, 28 December 1997
- *
- * [...]
- * Actually, a port I/O instruction on most ports in the 0-0x3ff range
- * takes almost exactly 1 microsecond, so if you're, for example, using
- * the parallel port directly, just do additional inb()s from that port
- * to delay.
- * [...]
- */
-/* transmitter latency 1.5625us 0x1.90 - this figure arrived at from
- * comment above plus trimming to match actual measured frequency.
- * This will be sensitive to cpu speed, though hopefully most of the 1.5us
- * is spent in the uart access. Still - for reference test machine was a
- * 1.13GHz Athlon system - Steve
- */
-
-/*
- * changed from 400 to 450 as this works better on slower machines;
- * faster machines will use the rdtsc code anyway
- */
-#define LIRC_SERIAL_TRANSMITTER_LATENCY 450
-
-#else
-
-/* does anybody have information on other platforms ? */
-/* 256 = 1<<8 */
-#define LIRC_SERIAL_TRANSMITTER_LATENCY 256
-
-#endif /* __i386__ */
-/*
- * FIXME: should we be using hrtimers instead of this
- * LIRC_SERIAL_TRANSMITTER_LATENCY nonsense?
- */
-
-/* fetch serial input packet (1 byte) from register offset */
-static u8 sinp(int offset)
-{
- if (iommap != 0)
- /* the register is memory-mapped */
- offset <<= ioshift;
-
- return inb(io + offset);
-}
-
-/* write serial output packet (1 byte) of value to register offset */
-static void soutp(int offset, u8 value)
-{
- if (iommap != 0)
- /* the register is memory-mapped */
- offset <<= ioshift;
-
- outb(value, io + offset);
-}
-
-static void on(void)
-{
-#ifdef CONFIG_LIRC_SERIAL_NSLU2
- /*
- * On NSLU2, we put the transmit diode between the output of the green
- * status LED and ground
- */
- if (type == LIRC_NSLU2) {
- gpio_line_set(NSLU2_LED_GRN, IXP4XX_GPIO_LOW);
- return;
- }
-#endif
- if (txsense)
- soutp(UART_MCR, hardware[type].off);
- else
- soutp(UART_MCR, hardware[type].on);
-}
-
-static void off(void)
-{
-#ifdef CONFIG_LIRC_SERIAL_NSLU2
- if (type == LIRC_NSLU2) {
- gpio_line_set(NSLU2_LED_GRN, IXP4XX_GPIO_HIGH);
- return;
- }
-#endif
- if (txsense)
- soutp(UART_MCR, hardware[type].on);
- else
- soutp(UART_MCR, hardware[type].off);
-}
-
-#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);
-}
-
-#ifdef USE_RDTSC
-/*
- * This is an overflow/precision juggle, complicated in that we can't
- * do long long divide in the kernel
- */
-
-/*
- * When we use the rdtsc instruction to measure clocks, we keep the
- * pulse and space widths as clock cycles. As this is CPU speed
- * dependent, the widths must be calculated in init_port and ioctl
- * time
- */
-
-/* So send_pulse can quickly convert microseconds to clocks */
-static unsigned long conv_us_to_clocks;
-
-static int init_timing_params(unsigned int new_duty_cycle,
- unsigned int new_freq)
-{
- __u64 loops_per_sec, work;
-
- duty_cycle = new_duty_cycle;
- freq = new_freq;
-
- loops_per_sec = __this_cpu_read(cpu.info.loops_per_jiffy);
- loops_per_sec *= HZ;
-
- /* How many clocks in a microsecond?, avoiding long long divide */
- work = loops_per_sec;
- work *= 4295; /* 4295 = 2^32 / 1e6 */
- conv_us_to_clocks = (work >> 32);
-
- /*
- * Carrier period in clocks, approach good up to 32GHz clock,
- * gets carrier frequency within 8Hz
- */
- period = loops_per_sec >> 3;
- period /= (freq >> 3);
-
- /* Derive pulse and space from the period */
- pulse_width = period * duty_cycle / 100;
- space_width = period - pulse_width;
- dprintk("in init_timing_params, freq=%d, duty_cycle=%d, "
- "clk/jiffy=%ld, pulse=%ld, space=%ld, "
- "conv_us_to_clocks=%ld\n",
- freq, duty_cycle, __this_cpu_read(cpu_info.loops_per_jiffy),
- pulse_width, space_width, conv_us_to_clocks);
- return 0;
-}
-#else /* ! USE_RDTSC */
-static int init_timing_params(unsigned int new_duty_cycle,
- unsigned int new_freq)
-{
-/*
- * period, pulse/space width are kept with 8 binary places -
- * IE multiplied by 256.
- */
- if (256 * 1000000L / new_freq * new_duty_cycle / 100 <=
- LIRC_SERIAL_TRANSMITTER_LATENCY)
- return -EINVAL;
- if (256 * 1000000L / new_freq * (100 - new_duty_cycle) / 100 <=
- LIRC_SERIAL_TRANSMITTER_LATENCY)
- return -EINVAL;
- duty_cycle = new_duty_cycle;
- freq = new_freq;
- period = 256 * 1000000L / freq;
- pulse_width = period * duty_cycle / 100;
- space_width = period - pulse_width;
- dprintk("in init_timing_params, freq=%d pulse=%ld, "
- "space=%ld\n", freq, pulse_width, space_width);
- return 0;
-}
-#endif /* USE_RDTSC */
-
-
-/* return value: space length delta */
-
-static long send_pulse_irdeo(unsigned long length)
-{
- long rawbits, ret;
- int i;
- unsigned char output;
- unsigned char chunk, shifted;
-
- /* how many bits have to be sent ? */
- rawbits = length * 1152 / 10000;
- if (duty_cycle > 50)
- chunk = 3;
- else
- chunk = 1;
- for (i = 0, output = 0x7f; rawbits > 0; rawbits -= 3) {
- shifted = chunk << (i * 3);
- shifted >>= 1;
- output &= (~shifted);
- i++;
- if (i == 3) {
- soutp(UART_TX, output);
- while (!(sinp(UART_LSR) & UART_LSR_THRE))
- ;
- output = 0x7f;
- i = 0;
- }
- }
- if (i != 0) {
- soutp(UART_TX, output);
- while (!(sinp(UART_LSR) & UART_LSR_TEMT))
- ;
- }
-
- if (i == 0)
- ret = (-rawbits) * 10000 / 1152;
- else
- ret = (3 - i) * 3 * 10000 / 1152 + (-rawbits) * 10000 / 1152;
-
- return ret;
-}
-
-#ifdef USE_RDTSC
-/* Version that uses Pentium rdtsc instruction to measure clocks */
-
-/*
- * This version does sub-microsecond timing using rdtsc instruction,
- * and does away with the fudged LIRC_SERIAL_TRANSMITTER_LATENCY
- * Implicitly i586 architecture... - Steve
- */
-
-static long send_pulse_homebrew_softcarrier(unsigned long length)
-{
- int flag;
- unsigned long target, start, now;
-
- /* Get going quick as we can */
- rdtscl(start);
- on();
- /* Convert length from microseconds to clocks */
- length *= conv_us_to_clocks;
- /* And loop till time is up - flipping at right intervals */
- now = start;
- target = pulse_width;
- flag = 1;
- /*
- * FIXME: This looks like a hard busy wait, without even an occasional,
- * polite, cpu_relax() call. There's got to be a better way?
- *
- * The i2c code has the result of a lot of bit-banging work, I wonder if
- * there's something there which could be helpful here.
- */
- while ((now - start) < length) {
- /* Delay till flip time */
- do {
- rdtscl(now);
- } while ((now - start) < target);
-
- /* flip */
- if (flag) {
- rdtscl(now);
- off();
- target += space_width;
- } else {
- rdtscl(now); on();
- target += pulse_width;
- }
- flag = !flag;
- }
- rdtscl(now);
- return ((now - start) - length) / conv_us_to_clocks;
-}
-#else /* ! USE_RDTSC */
-/* Version using udelay() */
-
-/*
- * here we use fixed point arithmetic, with 8
- * fractional bits. that gets us within 0.1% or so of the right average
- * frequency, albeit with some jitter in pulse length - Steve
- */
-
-/* To match 8 fractional bits used for pulse/space length */
-
-static long send_pulse_homebrew_softcarrier(unsigned long length)
-{
- int flag;
- unsigned long actual, target, d;
- length <<= 8;
-
- actual = 0; target = 0; flag = 0;
- while (actual < length) {
- if (flag) {
- off();
- target += space_width;
- } else {
- on();
- target += pulse_width;
- }
- d = (target - actual -
- LIRC_SERIAL_TRANSMITTER_LATENCY + 128) >> 8;
- /*
- * Note - we've checked in ioctl that the pulse/space
- * widths are big enough so that d is > 0
- */
- udelay(d);
- actual += (d << 8) + LIRC_SERIAL_TRANSMITTER_LATENCY;
- flag = !flag;
- }
- return (actual-length) >> 8;
-}
-#endif /* USE_RDTSC */
-
-static long send_pulse_homebrew(unsigned long length)
-{
- if (length <= 0)
- return 0;
-
- if (softcarrier)
- return send_pulse_homebrew_softcarrier(length);
- else {
- on();
- safe_udelay(length);
- return 0;
- }
-}
-
-static void send_space_irdeo(long length)
-{
- if (length <= 0)
- return;
-
- safe_udelay(length);
-}
-
-static void send_space_homebrew(long length)
-{
- off();
- if (length <= 0)
- return;
- safe_udelay(length);
-}
-
-static void rbwrite(int l)
-{
- if (lirc_buffer_full(&rbuf)) {
- /* no new signals will be accepted */
- dprintk("Buffer overrun\n");
- return;
- }
- lirc_buffer_write(&rbuf, (void *)&l);
-}
-
-static void frbwrite(int l)
-{
- /* simple noise filter */
- static int pulse, space;
- static unsigned int ptr;
-
- if (ptr > 0 && (l & PULSE_BIT)) {
- pulse += l & PULSE_MASK;
- if (pulse > 250) {
- rbwrite(space);
- rbwrite(pulse | PULSE_BIT);
- ptr = 0;
- pulse = 0;
- }
- return;
- }
- if (!(l & PULSE_BIT)) {
- if (ptr == 0) {
- if (l > 20000) {
- space = l;
- ptr++;
- return;
- }
- } else {
- if (l > 20000) {
- space += pulse;
- if (space > PULSE_MASK)
- space = PULSE_MASK;
- space += l;
- if (space > PULSE_MASK)
- space = PULSE_MASK;
- pulse = 0;
- return;
- }
- rbwrite(space);
- rbwrite(pulse | PULSE_BIT);
- ptr = 0;
- pulse = 0;
- }
- }
- rbwrite(l);
-}
-
-static irqreturn_t irq_handler(int i, void *blah)
-{
- struct timeval tv;
- int counter, dcd;
- u8 status;
- long deltv;
- int data;
- static int last_dcd = -1;
-
- if ((sinp(UART_IIR) & UART_IIR_NO_INT)) {
- /* not our interrupt */
- return IRQ_NONE;
- }
-
- counter = 0;
- do {
- counter++;
- status = sinp(UART_MSR);
- if (counter > RS_ISR_PASS_LIMIT) {
- printk(KERN_WARNING LIRC_DRIVER_NAME ": AIEEEE: "
- "We're caught!\n");
- break;
- }
- if ((status & hardware[type].signal_pin_change)
- && sense != -1) {
- /* get current time */
- do_gettimeofday(&tv);
-
- /* New mode, written by Trent Piepho
- <xyzzy@u.washington.edu>. */
-
- /*
- * The old format was not very portable.
- * We now use an int to pass pulses
- * and spaces to user space.
- *
- * If PULSE_BIT is set a pulse has been
- * received, otherwise a space has been
- * received. The driver needs to know if your
- * receiver is active high or active low, or
- * the space/pulse sense could be
- * inverted. The bits denoted by PULSE_MASK are
- * the length in microseconds. Lengths greater
- * than or equal to 16 seconds are clamped to
- * PULSE_MASK. All other bits are unused.
- * This is a much simpler interface for user
- * programs, as well as eliminating "out of
- * phase" errors with space/pulse
- * autodetection.
- */
-
- /* calc time since last interrupt in microseconds */
- dcd = (status & hardware[type].signal_pin) ? 1 : 0;
-
- if (dcd == last_dcd) {
- printk(KERN_WARNING LIRC_DRIVER_NAME
- ": ignoring spike: %d %d %lx %lx %lx %lx\n",
- dcd, sense,
- tv.tv_sec, lasttv.tv_sec,
- tv.tv_usec, lasttv.tv_usec);
- continue;
- }
-
- deltv = tv.tv_sec-lasttv.tv_sec;
- if (tv.tv_sec < lasttv.tv_sec ||
- (tv.tv_sec == lasttv.tv_sec &&
- tv.tv_usec < lasttv.tv_usec)) {
- printk(KERN_WARNING LIRC_DRIVER_NAME
- ": AIEEEE: your clock just jumped "
- "backwards\n");
- printk(KERN_WARNING LIRC_DRIVER_NAME
- ": %d %d %lx %lx %lx %lx\n",
- dcd, sense,
- tv.tv_sec, lasttv.tv_sec,
- tv.tv_usec, lasttv.tv_usec);
- data = PULSE_MASK;
- } else if (deltv > 15) {
- data = PULSE_MASK; /* really long time */
- if (!(dcd^sense)) {
- /* sanity check */
- printk(KERN_WARNING LIRC_DRIVER_NAME
- ": AIEEEE: "
- "%d %d %lx %lx %lx %lx\n",
- dcd, sense,
- tv.tv_sec, lasttv.tv_sec,
- tv.tv_usec, lasttv.tv_usec);
- /*
- * detecting pulse while this
- * MUST be a space!
- */
- sense = sense ? 0 : 1;
- }
- } else
- data = (int) (deltv*1000000 +
- tv.tv_usec -
- lasttv.tv_usec);
- frbwrite(dcd^sense ? data : (data|PULSE_BIT));
- lasttv = tv;
- last_dcd = dcd;
- wake_up_interruptible(&rbuf.wait_poll);
- }
- } while (!(sinp(UART_IIR) & UART_IIR_NO_INT)); /* still pending ? */
- return IRQ_HANDLED;
-}
-
-
-static int hardware_init_port(void)
-{
- u8 scratch, scratch2, scratch3;
-
- /*
- * This is a simple port existence test, borrowed from the autoconfig
- * function in drivers/serial/8250.c
- */
- scratch = sinp(UART_IER);
- soutp(UART_IER, 0);
-#ifdef __i386__
- outb(0xff, 0x080);
-#endif
- scratch2 = sinp(UART_IER) & 0x0f;
- soutp(UART_IER, 0x0f);
-#ifdef __i386__
- outb(0x00, 0x080);
-#endif
- scratch3 = sinp(UART_IER) & 0x0f;
- soutp(UART_IER, scratch);
- if (scratch2 != 0 || scratch3 != 0x0f) {
- /* we fail, there's nothing here */
- printk(KERN_ERR LIRC_DRIVER_NAME ": port existence test "
- "failed, cannot continue\n");
- return -EINVAL;
- }
-
-
-
- /* Set DLAB 0. */
- soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
-
- /* First of all, disable all interrupts */
- soutp(UART_IER, sinp(UART_IER) &
- (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));
-
- /* Clear registers. */
- sinp(UART_LSR);
- sinp(UART_RX);
- sinp(UART_IIR);
- sinp(UART_MSR);
-
-#ifdef CONFIG_LIRC_SERIAL_NSLU2
- if (type == LIRC_NSLU2) {
- /* Setup NSLU2 UART */
-
- /* Enable UART */
- soutp(UART_IER, sinp(UART_IER) | UART_IE_IXP42X_UUE);
- /* Disable Receiver data Time out interrupt */
- soutp(UART_IER, sinp(UART_IER) & ~UART_IE_IXP42X_RTOIE);
- /* set out2 = interrupt unmask; off() doesn't set MCR
- on NSLU2 */
- soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2);
- }
-#endif
-
- /* Set line for power source */
- off();
-
- /* Clear registers again to be sure. */
- sinp(UART_LSR);
- sinp(UART_RX);
- sinp(UART_IIR);
- sinp(UART_MSR);
-
- switch (type) {
- case LIRC_IRDEO:
- case LIRC_IRDEO_REMOTE:
- /* setup port to 7N1 @ 115200 Baud */
- /* 7N1+start = 9 bits at 115200 ~ 3 bits at 38kHz */
-
- /* Set DLAB 1. */
- soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
- /* Set divisor to 1 => 115200 Baud */
- soutp(UART_DLM, 0);
- soutp(UART_DLL, 1);
- /* Set DLAB 0 + 7N1 */
- soutp(UART_LCR, UART_LCR_WLEN7);
- /* THR interrupt already disabled at this point */
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static int init_port(void)
-{
- int i, nlow, nhigh;
-
- /* Reserve io region. */
- /*
- * Future MMAP-Developers: Attention!
- * For memory mapped I/O you *might* need to use ioremap() first,
- * for the NSLU2 it's done in boot code.
- */
- if (((iommap != 0)
- && (request_mem_region(iommap, 8 << ioshift,
- LIRC_DRIVER_NAME) == NULL))
- || ((iommap == 0)
- && (request_region(io, 8, LIRC_DRIVER_NAME) == NULL))) {
- printk(KERN_ERR LIRC_DRIVER_NAME
- ": port %04x already in use\n", io);
- printk(KERN_WARNING LIRC_DRIVER_NAME
- ": use 'setserial /dev/ttySX uart none'\n");
- printk(KERN_WARNING LIRC_DRIVER_NAME
- ": or compile the serial port driver as module and\n");
- printk(KERN_WARNING LIRC_DRIVER_NAME
- ": make sure this module is loaded first\n");
- return -EBUSY;
- }
-
- if (hardware_init_port() < 0)
- return -EINVAL;
-
- /* Initialize pulse/space widths */
- init_timing_params(duty_cycle, freq);
-
- /* If pin is high, then this must be an active low receiver. */
- if (sense == -1) {
- /* wait 1/2 sec for the power supply */
- msleep(500);
-
- /*
- * probe 9 times every 0.04s, collect "votes" for
- * active high/low
- */
- nlow = 0;
- nhigh = 0;
- for (i = 0; i < 9; i++) {
- if (sinp(UART_MSR) & hardware[type].signal_pin)
- nlow++;
- else
- nhigh++;
- msleep(40);
- }
- sense = (nlow >= nhigh ? 1 : 0);
- printk(KERN_INFO LIRC_DRIVER_NAME ": auto-detected active "
- "%s receiver\n", sense ? "low" : "high");
- } else
- printk(KERN_INFO LIRC_DRIVER_NAME ": Manually using active "
- "%s receiver\n", sense ? "low" : "high");
-
- return 0;
-}
-
-static int set_use_inc(void *data)
-{
- int result;
- unsigned long flags;
-
- /* initialize timestamp */
- do_gettimeofday(&lasttv);
-
- result = request_irq(irq, irq_handler,
- IRQF_DISABLED | (share_irq ? IRQF_SHARED : 0),
- LIRC_DRIVER_NAME, (void *)&hardware);
-
- switch (result) {
- case -EBUSY:
- printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq);
- return -EBUSY;
- case -EINVAL:
- printk(KERN_ERR LIRC_DRIVER_NAME
- ": Bad irq number or handler\n");
- return -EINVAL;
- default:
- dprintk("Interrupt %d, port %04x obtained\n", irq, io);
- break;
- }
-
- spin_lock_irqsave(&hardware[type].lock, flags);
-
- /* Set DLAB 0. */
- soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
-
- soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI);
-
- spin_unlock_irqrestore(&hardware[type].lock, flags);
-
- return 0;
-}
-
-static void set_use_dec(void *data)
-{ unsigned long flags;
-
- spin_lock_irqsave(&hardware[type].lock, flags);
-
- /* Set DLAB 0. */
- soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
-
- /* First of all, disable all interrupts */
- soutp(UART_IER, sinp(UART_IER) &
- (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));
- spin_unlock_irqrestore(&hardware[type].lock, flags);
-
- free_irq(irq, (void *)&hardware);
-
- dprintk("freed IRQ %d\n", irq);
-}
-
-static ssize_t lirc_write(struct file *file, const char *buf,
- size_t n, loff_t *ppos)
-{
- int i, count;
- unsigned long flags;
- long delta = 0;
- int *wbuf;
-
- if (!(hardware[type].features & LIRC_CAN_SEND_PULSE))
- return -EBADF;
-
- count = n / sizeof(int);
- if (n % sizeof(int) || count % 2 == 0)
- return -EINVAL;
- wbuf = memdup_user(buf, n);
- if (IS_ERR(wbuf))
- return PTR_ERR(wbuf);
- spin_lock_irqsave(&hardware[type].lock, flags);
- if (type == LIRC_IRDEO) {
- /* DTR, RTS down */
- on();
- }
- for (i = 0; i < count; i++) {
- if (i%2)
- hardware[type].send_space(wbuf[i] - delta);
- else
- delta = hardware[type].send_pulse(wbuf[i]);
- }
- off();
- spin_unlock_irqrestore(&hardware[type].lock, flags);
- kfree(wbuf);
- return n;
-}
-
-static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
-{
- int result;
- __u32 value;
-
- switch (cmd) {
- case LIRC_GET_SEND_MODE:
- if (!(hardware[type].features&LIRC_CAN_SEND_MASK))
- return -ENOIOCTLCMD;
-
- result = put_user(LIRC_SEND2MODE
- (hardware[type].features&LIRC_CAN_SEND_MASK),
- (__u32 *) arg);
- if (result)
- return result;
- break;
-
- case LIRC_SET_SEND_MODE:
- if (!(hardware[type].features&LIRC_CAN_SEND_MASK))
- return -ENOIOCTLCMD;
-
- result = get_user(value, (__u32 *) arg);
- if (result)
- return result;
- /* only LIRC_MODE_PULSE supported */
- if (value != LIRC_MODE_PULSE)
- return -ENOSYS;
- break;
-
- case LIRC_GET_LENGTH:
- return -ENOSYS;
- break;
-
- case LIRC_SET_SEND_DUTY_CYCLE:
- dprintk("SET_SEND_DUTY_CYCLE\n");
- if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE))
- return -ENOIOCTLCMD;
-
- result = get_user(value, (__u32 *) arg);
- if (result)
- return result;
- if (value <= 0 || value > 100)
- return -EINVAL;
- return init_timing_params(value, freq);
- break;
-
- case LIRC_SET_SEND_CARRIER:
- dprintk("SET_SEND_CARRIER\n");
- if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER))
- return -ENOIOCTLCMD;
-
- result = get_user(value, (__u32 *) arg);
- if (result)
- return result;
- if (value > 500000 || value < 20000)
- return -EINVAL;
- return init_timing_params(duty_cycle, value);
- break;
-
- default:
- return lirc_dev_fop_ioctl(filep, cmd, arg);
- }
- return 0;
-}
-
-static const struct file_operations lirc_fops = {
- .owner = THIS_MODULE,
- .write = lirc_write,
- .unlocked_ioctl = lirc_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = lirc_ioctl,
-#endif
- .read = lirc_dev_fop_read,
- .poll = lirc_dev_fop_poll,
- .open = lirc_dev_fop_open,
- .release = lirc_dev_fop_close,
- .llseek = no_llseek,
-};
-
-static struct lirc_driver driver = {
- .name = LIRC_DRIVER_NAME,
- .minor = -1,
- .code_length = 1,
- .sample_rate = 0,
- .data = NULL,
- .add_to_buf = NULL,
- .rbuf = &rbuf,
- .set_use_inc = set_use_inc,
- .set_use_dec = set_use_dec,
- .fops = &lirc_fops,
- .dev = NULL,
- .owner = THIS_MODULE,
-};
-
-static struct platform_device *lirc_serial_dev;
-
-static int __devinit lirc_serial_probe(struct platform_device *dev)
-{
- return 0;
-}
-
-static int __devexit lirc_serial_remove(struct platform_device *dev)
-{
- return 0;
-}
-
-static int lirc_serial_suspend(struct platform_device *dev,
- pm_message_t state)
-{
- /* Set DLAB 0. */
- soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
-
- /* Disable all interrupts */
- soutp(UART_IER, sinp(UART_IER) &
- (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));
-
- /* Clear registers. */
- sinp(UART_LSR);
- sinp(UART_RX);
- sinp(UART_IIR);
- sinp(UART_MSR);
-
- return 0;
-}
-
-/* twisty maze... need a forward-declaration here... */
-static void lirc_serial_exit(void);
-
-static int lirc_serial_resume(struct platform_device *dev)
-{
- unsigned long flags;
-
- if (hardware_init_port() < 0) {
- lirc_serial_exit();
- return -EINVAL;
- }
-
- spin_lock_irqsave(&hardware[type].lock, flags);
- /* Enable Interrupt */
- do_gettimeofday(&lasttv);
- soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI);
- off();
-
- lirc_buffer_clear(&rbuf);
-
- spin_unlock_irqrestore(&hardware[type].lock, flags);
-
- return 0;
-}
-
-static struct platform_driver lirc_serial_driver = {
- .probe = lirc_serial_probe,
- .remove = __devexit_p(lirc_serial_remove),
- .suspend = lirc_serial_suspend,
- .resume = lirc_serial_resume,
- .driver = {
- .name = "lirc_serial",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init lirc_serial_init(void)
-{
- int result;
-
- /* Init read buffer. */
- result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN);
- if (result < 0)
- return -ENOMEM;
-
- result = platform_driver_register(&lirc_serial_driver);
- if (result) {
- printk("lirc register returned %d\n", result);
- goto exit_buffer_free;
- }
-
- lirc_serial_dev = platform_device_alloc("lirc_serial", 0);
- if (!lirc_serial_dev) {
- result = -ENOMEM;
- goto exit_driver_unregister;
- }
-
- result = platform_device_add(lirc_serial_dev);
- if (result)
- goto exit_device_put;
-
- return 0;
-
-exit_device_put:
- platform_device_put(lirc_serial_dev);
-exit_driver_unregister:
- platform_driver_unregister(&lirc_serial_driver);
-exit_buffer_free:
- lirc_buffer_free(&rbuf);
- return result;
-}
-
-static void lirc_serial_exit(void)
-{
- platform_device_unregister(lirc_serial_dev);
- platform_driver_unregister(&lirc_serial_driver);
- lirc_buffer_free(&rbuf);
-}
-
-static int __init lirc_serial_init_module(void)
-{
- int result;
-
- result = lirc_serial_init();
- if (result)
- return result;
-
- switch (type) {
- case LIRC_HOMEBREW:
- case LIRC_IRDEO:
- case LIRC_IRDEO_REMOTE:
- case LIRC_ANIMAX:
- case LIRC_IGOR:
- /* if nothing specified, use ttyS0/com1 and irq 4 */
- io = io ? io : 0x3f8;
- irq = irq ? irq : 4;
- break;
-#ifdef CONFIG_LIRC_SERIAL_NSLU2
- case LIRC_NSLU2:
- io = io ? io : IRQ_IXP4XX_UART2;
- irq = irq ? irq : (IXP4XX_UART2_BASE_VIRT + REG_OFFSET);
- iommap = iommap ? iommap : IXP4XX_UART2_BASE_PHYS;
- ioshift = ioshift ? ioshift : 2;
- break;
-#endif
- default:
- result = -EINVAL;
- goto exit_serial_exit;
- }
- if (!softcarrier) {
- switch (type) {
- case LIRC_HOMEBREW:
- case LIRC_IGOR:
-#ifdef CONFIG_LIRC_SERIAL_NSLU2
- case LIRC_NSLU2:
-#endif
- hardware[type].features &=
- ~(LIRC_CAN_SET_SEND_DUTY_CYCLE|
- LIRC_CAN_SET_SEND_CARRIER);
- break;
- }
- }
-
- result = init_port();
- if (result < 0)
- goto exit_serial_exit;
- driver.features = hardware[type].features;
- driver.dev = &lirc_serial_dev->dev;
- driver.minor = lirc_register_driver(&driver);
- if (driver.minor < 0) {
- printk(KERN_ERR LIRC_DRIVER_NAME
- ": register_chrdev failed!\n");
- result = -EIO;
- goto exit_release;
- }
- return 0;
-exit_release:
- release_region(io, 8);
-exit_serial_exit:
- lirc_serial_exit();
- return result;
-}
-
-static void __exit lirc_serial_exit_module(void)
-{
- lirc_serial_exit();
- if (iommap != 0)
- release_mem_region(iommap, 8 << ioshift);
- else
- release_region(io, 8);
- lirc_unregister_driver(driver.minor);
- dprintk("cleaned up module\n");
-}
-
-
-module_init(lirc_serial_init_module);
-module_exit(lirc_serial_exit_module);
-
-MODULE_DESCRIPTION("Infra-red receiver driver for serial ports.");
-MODULE_AUTHOR("Ralph Metzler, Trent Piepho, Ben Pfaff, "
- "Christoph Bartelmus, Andrei Tanas");
-MODULE_LICENSE("GPL");
-
-module_param(type, int, S_IRUGO);
-MODULE_PARM_DESC(type, "Hardware type (0 = home-brew, 1 = IRdeo,"
- " 2 = IRdeo Remote, 3 = AnimaX, 4 = IgorPlug,"
- " 5 = NSLU2 RX:CTS2/TX:GreenLED)");
-
-module_param(io, int, S_IRUGO);
-MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)");
-
-/* some architectures (e.g. intel xscale) have memory mapped registers */
-module_param(iommap, bool, S_IRUGO);
-MODULE_PARM_DESC(iommap, "physical base for memory mapped I/O"
- " (0 = no memory mapped io)");
-
-/*
- * some architectures (e.g. intel xscale) align the 8bit serial registers
- * on 32bit word boundaries.
- * See linux-kernel/serial/8250.c serial_in()/out()
- */
-module_param(ioshift, int, S_IRUGO);
-MODULE_PARM_DESC(ioshift, "shift I/O register offset (0 = no shift)");
-
-module_param(irq, int, S_IRUGO);
-MODULE_PARM_DESC(irq, "Interrupt (4 or 3)");
-
-module_param(share_irq, bool, S_IRUGO);
-MODULE_PARM_DESC(share_irq, "Share interrupts (0 = off, 1 = on)");
-
-module_param(sense, bool, S_IRUGO);
-MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit"
- " (0 = active high, 1 = active low )");
-
-#ifdef CONFIG_LIRC_SERIAL_TRANSMITTER
-module_param(txsense, bool, S_IRUGO);
-MODULE_PARM_DESC(txsense, "Sense of transmitter circuit"
- " (0 = active high, 1 = active low )");
-#endif
-
-module_param(softcarrier, bool, S_IRUGO);
-MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on, default on)");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
diff --git a/drivers/staging/lirc/lirc_sir.c b/drivers/staging/lirc/lirc_sir.c
deleted file mode 100644
index a7b46f24f24..00000000000
--- a/drivers/staging/lirc/lirc_sir.c
+++ /dev/null
@@ -1,1286 +0,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);
- 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;
- DECLARE_WAITQUEUE(wait, current);
-
- if (count % sizeof(int))
- return -EINVAL;
-
- add_wait_queue(&lirc_read_queue, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- while (n < count) {
- if (rx_head != rx_tail) {
- if (copy_to_user((void *) buf + n,
- (void *) (rx_buf + rx_head),
- sizeof(int))) {
- retval = -EFAULT;
- break;
- }
- rx_head = (rx_head + 1) & (RBUF_LEN - 1);
- n += sizeof(int);
- } else {
- if (file->f_flags & O_NONBLOCK) {
- retval = -EAGAIN;
- break;
- }
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- schedule();
- set_current_state(TASK_INTERRUPTIBLE);
- }
- }
- remove_wait_queue(&lirc_read_queue, &wait);
- set_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;
- int i, count;
- int *tx_buf;
-
- count = n / sizeof(int);
- if (n % sizeof(int) || count % 2 == 0)
- return -EINVAL;
- tx_buf = memdup_user(buf, n);
- if (IS_ERR(tx_buf))
- return PTR_ERR(tx_buf);
- i = 0;
-#ifdef LIRC_ON_SA1100
- /* disable receiver */
- Ser2UTCR3 = 0;
-#endif
- local_irq_save(flags);
- while (1) {
- if (i >= count)
- break;
- if (tx_buf[i])
- send_pulse(tx_buf[i]);
- i++;
- if (i >= count)
- break;
- if (tx_buf[i])
- send_space(tx_buf[i]);
- i++;
- }
- local_irq_restore(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
- kfree(tx_buf);
- return count;
-}
-
-static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
-{
- int retval = 0;
- __u32 value = 0;
-#ifdef 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)
- value = LIRC_MODE_MODE2;
-#endif
-
- switch (cmd) {
- case LIRC_GET_FEATURES:
- case LIRC_GET_SEND_MODE:
- case LIRC_GET_REC_MODE:
- retval = put_user(value, (__u32 *) arg);
- break;
-
- case LIRC_SET_SEND_MODE:
- case LIRC_SET_REC_MODE:
- retval = get_user(value, (__u32 *) arg);
- break;
-#ifdef LIRC_ON_SA1100
- case LIRC_SET_SEND_DUTY_CYCLE:
- retval = get_user(value, (__u32 *) arg);
- if (retval)
- return retval;
- if (value <= 0 || value > 100)
- return -EINVAL;
- /* (value/100)*(1000000/freq) */
- duty_cycle = value;
- 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:
- retval = get_user(value, (__u32 *) arg);
- if (retval)
- return retval;
- if (value > 500000 || value < 20000)
- return -EINVAL;
- freq = value;
- 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;
- 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;
- int newval;
-
- dprintk("add flag %d with val %lu\n", flag, val);
-
- newval = val & PULSE_MASK;
-
- /*
- * statistically, pulses are ~TIME_CONST/2 too long. we could
- * maybe make this more exact, 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) {
- dprintk("Buffer overrun.\n");
- return;
- }
- rx_buf[rx_tail] = newval;
- rx_tail = new_rx_tail;
- wake_up_interruptible(&lirc_read_queue);
-}
-
-static const struct file_operations lirc_fops = {
- .owner = THIS_MODULE,
- .read = lirc_read,
- .write = lirc_write,
- .poll = lirc_poll,
- .unlocked_ioctl = lirc_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = lirc_ioctl,
-#endif
- .open = lirc_dev_fop_open,
- .release = lirc_dev_fop_close,
- .llseek = no_llseek,
-};
-
-static int set_use_inc(void *data)
-{
- return 0;
-}
-
-static void set_use_dec(void *data)
-{
-}
-
-static struct lirc_driver driver = {
- .name = LIRC_DRIVER_NAME,
- .minor = -1,
- .code_length = 1,
- .sample_rate = 0,
- .data = NULL,
- .add_to_buf = NULL,
- .set_use_inc = set_use_inc,
- .set_use_dec = set_use_dec,
- .fops = &lirc_fops,
- .dev = NULL,
- .owner = THIS_MODULE,
-};
-
-
-static int init_chrdev(void)
-{
- driver.minor = lirc_register_driver(&driver);
- if (driver.minor < 0) {
- printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n");
- return -EIO;
- }
- return 0;
-}
-
-static void drop_chrdev(void)
-{
- lirc_unregister_driver(driver.minor);
-}
-
-/* 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);
- dprintk("timeout add %d for %lu usec\n", last_value, pulse_end);
- add_read_queue(last_value, pulse_end);
- last_value = 0;
- last_tv = last_intr_tv;
- }
- spin_unlock_irqrestore(&timer_lock, flags);
-}
-
-static irqreturn_t sir_interrupt(int irq, void *dev_id)
-{
- unsigned char data;
- struct timeval curr_tv;
- static unsigned long deltv;
-#ifdef LIRC_ON_SA1100
- int status;
- static int 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;
-
- if (debug) {
- dprintk("EIF\n");
- bstat = Ser2UTSR1;
-
- if (bstat & UTSR1_FRE)
- dprintk("frame error\n");
- if (bstat & UTSR1_ROR)
- dprintk("receive fifo overrun\n");
- if (bstat & UTSR1_PRE)
- dprintk("parity error\n");
- }
-
- bstat = Ser2UTDR;
- n++;
- status = Ser2UTSR0;
- }
-
- if (status & (UTSR0_RFS | UTSR0_RID)) {
- do_gettimeofday(&curr_tv);
- deltv = delta(&last_tv, &curr_tv);
- do {
- data = Ser2UTDR;
- dprintk("%d data: %u\n", n, (unsigned int) 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) {
- 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(KERN_ERR "transmit fifo not full, shouldn't 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);
- dprintk("t %lu, d %d\n", deltintrtv, (int)data);
- /*
- * if nothing came in last X cycles,
- * it was gap
- */
- if (deltintrtv > TIME_CONST * threshold) {
- if (last_value) {
- dprintk("GAP\n");
- /* 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);
- }
-
- lsr = inb(io + UART_LSR);
- } while (lsr & UART_LSR_DR); /* data ready */
- spin_unlock_irqrestore(&timer_lock, flags);
- break;
- default:
- break;
- }
- }
-#endif
- return IRQ_RETVAL(IRQ_HANDLED);
-}
-
-#ifdef LIRC_ON_SA1100
-static void 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();
-}
-
-static void send_space(unsigned long length)
-{
- if (length == 0)
- return;
- off();
- safe_udelay(length);
-}
-#else
-static 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;
-
- time_left = (long)len - (long)bytes_out * (long)TIME_CONST;
- if (bytes_out == 0) {
- bytes_out++;
- time_left = 0;
- }
- while (bytes_out--) {
- outb(PULSE, io + UART_TX);
- /* FIXME treba seriozne cakanie z 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_COLLIE
-static 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,
- TC35143_IODIR_OUTPUT);
- ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_HIGH);
- }
- return 0;
-}
-#endif
-
-static int init_hardware(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&hardware_lock, flags);
- /* reset UART */
-#ifdef LIRC_ON_SA1100
-#ifdef CONFIG_SA1100_BITSY
- if (machine_is_bitsy()) {
- printk(KERN_INFO "Power on IR module\n");
- set_bitsy_egpio(EGPIO_BITSY_IR_ON);
- }
-#endif
-#ifdef CONFIG_SA1100_COLLIE
- sa1100_irda_set_power_collie(3); /* power on */
-#endif
- sr.hscr0 = Ser2HSCR0;
-
- sr.utcr0 = Ser2UTCR0;
- sr.utcr1 = Ser2UTCR1;
- sr.utcr2 = Ser2UTCR2;
- sr.utcr3 = Ser2UTCR3;
- sr.utcr4 = Ser2UTCR4;
-
- sr.utdr = Ser2UTDR;
- sr.utsr0 = Ser2UTSR0;
- sr.utsr1 = Ser2UTSR1;
-
- /* configure GPIO */
- /* output */
- PPDR |= PPC_TXD2;
- PSDR |= PPC_TXD2;
- /* set output to 0 */
- off();
-
- /* Enable HP-SIR modulation, and ensure that the port is disabled. */
- Ser2UTCR3 = 0;
- Ser2HSCR0 = sr.hscr0 & (~HSCR0_HSSP);
-
- /* clear status register to prevent unwanted interrupts */
- Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
-
- /* 7N1 */
- Ser2UTCR0 = UTCR0_1StpBit|UTCR0_7BitData;
- /* 115200 */
- Ser2UTCR1 = 0;
- Ser2UTCR2 = 1;
- /* use HPSIR, 1.6 usec pulses */
- Ser2UTCR4 = UTCR4_HPSIR|UTCR4_Z1_6us;
-
- /* enable receiver, receive fifo interrupt */
- Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE;
-
- /* clear status register to prevent unwanted interrupts */
- Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
-
-#elif defined(LIRC_SIR_TEKRAM)
- /* disable FIFO */
- soutp(UART_FCR,
- UART_FCR_CLEAR_RCVR|
- UART_FCR_CLEAR_XMIT|
- UART_FCR_TRIGGER_1);
-
- /* Set DLAB 0. */
- soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
-
- /* First of all, disable all interrupts */
- soutp(UART_IER, sinp(UART_IER) &
- (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));
-
- /* Set DLAB 1. */
- soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
-
- /* Set divisor to 12 => 9600 Baud */
- soutp(UART_DLM, 0);
- soutp(UART_DLL, 12);
-
- /* Set DLAB 0. */
- soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
-
- /* power supply */
- soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
- safe_udelay(50*1000);
-
- /* -DTR low -> reset PIC */
- soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2);
- udelay(1*1000);
-
- soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
- udelay(100);
-
-
- /* -RTS low -> send control byte */
- soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2);
- udelay(7);
- soutp(UART_TX, TEKRAM_115200|TEKRAM_PW);
-
- /* one byte takes ~1042 usec to transmit at 9600,8N1 */
- udelay(1500);
-
- /* back to normal operation */
- soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
- udelay(50);
-
- udelay(1500);
-
- /* read previous control byte */
- printk(KERN_INFO LIRC_DRIVER_NAME
- ": 0x%02x\n", sinp(UART_RX));
-
- /* Set DLAB 1. */
- soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
-
- /* Set divisor to 1 => 115200 Baud */
- soutp(UART_DLM, 0);
- soutp(UART_DLL, 1);
-
- /* Set DLAB 0, 8 Bit */
- soutp(UART_LCR, UART_LCR_WLEN8);
- /* enable interrupts */
- soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI);
-#else
- outb(0, io + UART_MCR);
- outb(0, io + UART_IER);
- /* init UART */
- /* set DLAB, speed = 115200 */
- outb(UART_LCR_DLAB | UART_LCR_WLEN7, io + UART_LCR);
- outb(1, io + UART_DLL); outb(0, io + UART_DLM);
- /* 7N1+start = 9 bits at 115200 ~ 3 bits at 44000 */
- outb(UART_LCR_WLEN7, io + UART_LCR);
- /* FIFO operation */
- outb(UART_FCR_ENABLE_FIFO, io + UART_FCR);
- /* interrupts */
- /* outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, io + UART_IER); */
- outb(UART_IER_RDI, io + UART_IER);
- /* turn on UART */
- outb(UART_MCR_DTR|UART_MCR_RTS|UART_MCR_OUT2, io + UART_MCR);
-#ifdef LIRC_SIR_ACTISYS_ACT200L
- init_act200();
-#elif defined(LIRC_SIR_ACTISYS_ACT220L)
- init_act220();
-#endif
-#endif
- spin_unlock_irqrestore(&hardware_lock, flags);
- return 0;
-}
-
-static void drop_hardware(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&hardware_lock, flags);
-
-#ifdef LIRC_ON_SA1100
- Ser2UTCR3 = 0;
-
- Ser2UTCR0 = sr.utcr0;
- Ser2UTCR1 = sr.utcr1;
- Ser2UTCR2 = sr.utcr2;
- Ser2UTCR4 = sr.utcr4;
- Ser2UTCR3 = sr.utcr3;
-
- Ser2HSCR0 = sr.hscr0;
-#ifdef CONFIG_SA1100_BITSY
- if (machine_is_bitsy())
- clr_bitsy_egpio(EGPIO_BITSY_IR_ON);
-#endif
-#ifdef CONFIG_SA1100_COLLIE
- sa1100_irda_set_power_collie(0); /* power off */
-#endif
-#else
- /* turn off interrupts */
- outb(0, io + UART_IER);
-#endif
- spin_unlock_irqrestore(&hardware_lock, flags);
-}
-
-/* SECTION: Initialisation */
-
-static int init_port(void)
-{
- int retval;
-
- /* get I/O port access and IRQ line */
-#ifndef LIRC_ON_SA1100
- if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) {
- printk(KERN_ERR LIRC_DRIVER_NAME
- ": i/o port 0x%.4x already in use.\n", io);
- return -EBUSY;
- }
-#endif
- retval = request_irq(irq, sir_interrupt, IRQF_DISABLED,
- LIRC_DRIVER_NAME, NULL);
- if (retval < 0) {
-# ifndef LIRC_ON_SA1100
- release_region(io, 8);
-# endif
- printk(KERN_ERR LIRC_DRIVER_NAME
- ": IRQ %d already in use.\n",
- irq);
- return retval;
- }
-#ifndef LIRC_ON_SA1100
- printk(KERN_INFO LIRC_DRIVER_NAME
- ": I/O port 0x%.4x, IRQ %d.\n",
- io, irq);
-#endif
-
- init_timer(&timerlist);
- timerlist.function = sir_timeout;
- timerlist.data = 0xabadcafe;
-
- return 0;
-}
-
-static void drop_port(void)
-{
- free_irq(irq, NULL);
- del_timer_sync(&timerlist);
-#ifndef LIRC_ON_SA1100
- release_region(io, 8);
-#endif
-}
-
-#ifdef LIRC_SIR_ACTISYS_ACT200L
-/* Crystal/Cirrus CS8130 IR transceiver, used in Actisys Act200L dongle */
-/* some code borrowed from Linux IRDA driver */
-
-/* Register 0: Control register #1 */
-#define ACT200L_REG0 0x00
-#define ACT200L_TXEN 0x01 /* Enable transmitter */
-#define ACT200L_RXEN 0x02 /* Enable receiver */
-#define ACT200L_ECHO 0x08 /* Echo control chars */
-
-/* Register 1: Control register #2 */
-#define ACT200L_REG1 0x10
-#define ACT200L_LODB 0x01 /* Load new baud rate count value */
-#define ACT200L_WIDE 0x04 /* Expand the maximum allowable pulse */
-
-/* Register 3: Transmit mode register #2 */
-#define ACT200L_REG3 0x30
-#define ACT200L_B0 0x01 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P) */
-#define ACT200L_B1 0x02 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P) */
-#define ACT200L_CHSY 0x04 /* StartBit Synced 0=bittime, 1=startbit */
-
-/* Register 4: Output Power register */
-#define ACT200L_REG4 0x40
-#define ACT200L_OP0 0x01 /* Enable LED1C output */
-#define ACT200L_OP1 0x02 /* Enable LED2C output */
-#define ACT200L_BLKR 0x04
-
-/* Register 5: Receive Mode register */
-#define ACT200L_REG5 0x50
-#define ACT200L_RWIDL 0x01 /* fixed 1.6us pulse mode */
- /*.. other various IRDA bit modes, and TV remote modes..*/
-
-/* Register 6: Receive Sensitivity register #1 */
-#define ACT200L_REG6 0x60
-#define ACT200L_RS0 0x01 /* receive threshold bit 0 */
-#define ACT200L_RS1 0x02 /* receive threshold bit 1 */
-
-/* Register 7: Receive Sensitivity register #2 */
-#define ACT200L_REG7 0x70
-#define ACT200L_ENPOS 0x04 /* Ignore the falling edge */
-
-/* Register 8,9: Baud Rate Divider register #1,#2 */
-#define ACT200L_REG8 0x80
-#define ACT200L_REG9 0x90
-
-#define ACT200L_2400 0x5f
-#define ACT200L_9600 0x17
-#define ACT200L_19200 0x0b
-#define ACT200L_38400 0x05
-#define ACT200L_57600 0x03
-#define ACT200L_115200 0x01
-
-/* Register 13: Control register #3 */
-#define ACT200L_REG13 0xd0
-#define ACT200L_SHDW 0x01 /* Enable access to shadow registers */
-
-/* Register 15: Status register */
-#define ACT200L_REG15 0xf0
-
-/* Register 21: Control register #4 */
-#define ACT200L_REG21 0x50
-#define ACT200L_EXCK 0x02 /* Disable clock output driver */
-#define ACT200L_OSCL 0x04 /* oscillator in low power, medium accuracy mode */
-
-static void init_act200(void)
-{
- int i;
- __u8 control[] = {
- ACT200L_REG15,
- ACT200L_REG13 | ACT200L_SHDW,
- ACT200L_REG21 | ACT200L_EXCK | ACT200L_OSCL,
- ACT200L_REG13,
- ACT200L_REG7 | ACT200L_ENPOS,
- ACT200L_REG6 | ACT200L_RS0 | ACT200L_RS1,
- ACT200L_REG5 | ACT200L_RWIDL,
- ACT200L_REG4 | ACT200L_OP0 | ACT200L_OP1 | ACT200L_BLKR,
- ACT200L_REG3 | ACT200L_B0,
- ACT200L_REG0 | ACT200L_TXEN | ACT200L_RXEN,
- ACT200L_REG8 | (ACT200L_115200 & 0x0f),
- ACT200L_REG9 | ((ACT200L_115200 >> 4) & 0x0f),
- ACT200L_REG1 | ACT200L_LODB | ACT200L_WIDE
- };
-
- /* Set DLAB 1. */
- soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8);
-
- /* Set divisor to 12 => 9600 Baud */
- soutp(UART_DLM, 0);
- soutp(UART_DLL, 12);
-
- /* Set DLAB 0. */
- soutp(UART_LCR, UART_LCR_WLEN8);
- /* Set divisor to 12 => 9600 Baud */
-
- /* power supply */
- soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
- for (i = 0; i < 50; i++)
- safe_udelay(1000);
-
- /* Reset the dongle : set RTS low for 25 ms */
- soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2);
- for (i = 0; i < 25; i++)
- udelay(1000);
-
- soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
- udelay(100);
-
- /* Clear DTR and set RTS to enter command mode */
- soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2);
- udelay(7);
-
- /* send out the control register settings for 115K 7N1 SIR operation */
- for (i = 0; i < sizeof(control); i++) {
- soutp(UART_TX, control[i]);
- /* one byte takes ~1042 usec to transmit at 9600,8N1 */
- udelay(1500);
- }
-
- /* back to normal operation */
- soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
- udelay(50);
-
- udelay(1500);
- soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
-
- /* Set DLAB 1. */
- soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN7);
-
- /* Set divisor to 1 => 115200 Baud */
- soutp(UART_DLM, 0);
- soutp(UART_DLL, 1);
-
- /* Set DLAB 0. */
- soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
-
- /* Set DLAB 0, 7 Bit */
- soutp(UART_LCR, UART_LCR_WLEN7);
-
- /* enable interrupts */
- soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI);
-}
-#endif
-
-#ifdef LIRC_SIR_ACTISYS_ACT220L
-/*
- * Derived from linux IrDA driver (net/irda/actisys.c)
- * Drop me a mail for any kind of comment: maxx@spaceboyz.net
- */
-
-void init_act220(void)
-{
- int i;
-
- /* DLAB 1 */
- soutp(UART_LCR, UART_LCR_DLAB|UART_LCR_WLEN7);
-
- /* 9600 baud */
- soutp(UART_DLM, 0);
- soutp(UART_DLL, 12);
-
- /* DLAB 0 */
- soutp(UART_LCR, UART_LCR_WLEN7);
-
- /* reset the dongle, set DTR low for 10us */
- soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2);
- udelay(10);
-
- /* back to normal (still 9600) */
- soutp(UART_MCR, UART_MCR_DTR|UART_MCR_RTS|UART_MCR_OUT2);
-
- /*
- * send RTS pulses until we reach 115200
- * i hope this is really the same for act220l/act220l+
- */
- for (i = 0; i < 3; i++) {
- udelay(10);
- /* set RTS low for 10 us */
- soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2);
- udelay(10);
- /* set RTS high for 10 us */
- soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
- }
-
- /* back to normal operation */
- udelay(1500); /* better safe than sorry ;) */
-
- /* Set DLAB 1. */
- soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN7);
-
- /* Set divisor to 1 => 115200 Baud */
- soutp(UART_DLM, 0);
- soutp(UART_DLL, 1);
-
- /* Set DLAB 0, 7 Bit */
- /* The dongle doesn't seem to have any problems with operation at 7N1 */
- soutp(UART_LCR, UART_LCR_WLEN7);
-
- /* enable interrupts */
- soutp(UART_IER, UART_IER_RDI);
-}
-#endif
-
-static int init_lirc_sir(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;
-}
-
-
-static int __init lirc_sir_init(void)
-{
- int retval;
-
- retval = init_chrdev();
- if (retval < 0)
- return retval;
- retval = init_lirc_sir();
- if (retval) {
- drop_chrdev();
- return retval;
- }
- return 0;
-}
-
-static void __exit lirc_sir_exit(void)
-{
- drop_hardware();
- drop_chrdev();
- drop_port();
- printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n");
-}
-
-module_init(lirc_sir_init);
-module_exit(lirc_sir_exit);
-
-#ifdef LIRC_SIR_TEKRAM
-MODULE_DESCRIPTION("Infrared receiver driver for Tekram Irmate 210");
-MODULE_AUTHOR("Christoph Bartelmus");
-#elif defined(LIRC_ON_SA1100)
-MODULE_DESCRIPTION("LIRC driver for StrongARM SA1100 embedded microprocessor");
-MODULE_AUTHOR("Christoph Bartelmus");
-#elif defined(LIRC_SIR_ACTISYS_ACT200L)
-MODULE_DESCRIPTION("LIRC driver for Actisys Act200L");
-MODULE_AUTHOR("Karl Bongers");
-#elif defined(LIRC_SIR_ACTISYS_ACT220L)
-MODULE_DESCRIPTION("LIRC driver for Actisys Act220L(+)");
-MODULE_AUTHOR("Jan Roemisch");
-#else
-MODULE_DESCRIPTION("Infrared receiver driver for SIR type serial ports");
-MODULE_AUTHOR("Milan Pikula");
-#endif
-MODULE_LICENSE("GPL");
-
-#ifdef LIRC_ON_SA1100
-module_param(irq, int, S_IRUGO);
-MODULE_PARM_DESC(irq, "Interrupt (16)");
-#else
-module_param(io, int, S_IRUGO);
-MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)");
-
-module_param(irq, int, S_IRUGO);
-MODULE_PARM_DESC(irq, "Interrupt (4 or 3)");
-
-module_param(threshold, int, S_IRUGO);
-MODULE_PARM_DESC(threshold, "space detection threshold (3)");
-#endif
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
diff --git a/drivers/staging/lirc/lirc_ttusbir.c b/drivers/staging/lirc/lirc_ttusbir.c
deleted file mode 100644
index e345ab9a004..00000000000
--- a/drivers/staging/lirc/lirc_ttusbir.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * lirc_ttusbir.c
- *
- * lirc_ttusbir - LIRC device driver for the TechnoTrend USB IR Receiver
- *
- * Copyright (C) 2007 Stefan Macher <st_maker-lirc@yahoo.de>
- *
- * This LIRC driver provides access to the TechnoTrend USB IR Receiver.
- * The receiver delivers the IR signal as raw sampled true/false data in
- * isochronous USB packets each of size 128 byte.
- * Currently the driver reduces the sampling rate by factor of 8 as this
- * is still more than enough to decode RC-5 - others should be analyzed.
- * But the driver does not rely on RC-5 it should be able to decode every
- * IR signal that is not too fast.
- */
-
-/*
- * 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
- */
-
-#include <linux/version.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-
-MODULE_DESCRIPTION("TechnoTrend USB IR device driver for LIRC");
-MODULE_AUTHOR("Stefan Macher (st_maker-lirc@yahoo.de)");
-MODULE_LICENSE("GPL");
-
-/* #define DEBUG */
-#ifdef DEBUG
-#define DPRINTK printk
-#else
-#define DPRINTK(_x_, a...)
-#endif
-
-/* function declarations */
-static int probe(struct usb_interface *intf, const struct usb_device_id *id);
-static void disconnect(struct usb_interface *intf);
-static void urb_complete(struct urb *urb);
-static int set_use_inc(void *data);
-static void set_use_dec(void *data);
-
-static int num_urbs = 2;
-module_param(num_urbs, int, S_IRUGO);
-MODULE_PARM_DESC(num_urbs,
- "Number of URBs in queue. Try to increase to 4 in case "
- "of problems (default: 2; minimum: 2)");
-
-/* table of devices that work with this driver */
-static struct usb_device_id device_id_table[] = {
- /* TechnoTrend USB IR Receiver */
- { USB_DEVICE(0x0B48, 0x2003) },
- /* Terminating entry */
- { }
-};
-MODULE_DEVICE_TABLE(usb, device_id_table);
-
-/* USB driver definition */
-static struct usb_driver usb_driver = {
- .name = "TTUSBIR",
- .id_table = &(device_id_table[0]),
- .probe = probe,
- .disconnect = disconnect,
-};
-
-/* USB device definition */
-struct ttusbir_device {
- struct usb_driver *usb_driver;
- struct usb_device *udev;
- struct usb_interface *interf;
- struct usb_class_driver class_driver;
- unsigned int ifnum; /* Interface number to use */
- unsigned int alt_setting; /* alternate setting to use */
- unsigned int endpoint; /* Endpoint to use */
- struct urb **urb; /* num_urb URB pointers*/
- char **buffer; /* 128 byte buffer for each URB */
- struct lirc_buffer rbuf; /* Buffer towards LIRC */
- struct lirc_driver driver;
- int minor;
- int last_pulse; /* remembers if last received byte was pulse or space */
- int last_num; /* remembers how many last bytes appeared */
- int opened;
-};
-
-/*** LIRC specific functions ***/
-static int set_use_inc(void *data)
-{
- int i, retval;
- struct ttusbir_device *ttusbir = data;
-
- DPRINTK("Sending first URBs\n");
- /* @TODO Do I need to check if I am already opened */
- ttusbir->opened = 1;
-
- for (i = 0; i < num_urbs; i++) {
- retval = usb_submit_urb(ttusbir->urb[i], GFP_KERNEL);
- if (retval) {
- err("%s: usb_submit_urb failed on urb %d",
- __func__, i);
- return retval;
- }
- }
- return 0;
-}
-
-static void set_use_dec(void *data)
-{
- struct ttusbir_device *ttusbir = data;
-
- DPRINTK("Device closed\n");
-
- ttusbir->opened = 0;
-}
-
-/*** USB specific functions ***/
-
-/*
- * This mapping table is used to do a very simple filtering of the
- * input signal.
- * For a value with at least 4 bits set it returns 0xFF otherwise
- * 0x00. For faster IR signals this can not be used. But for RC-5 we
- * still have about 14 samples per pulse/space, i.e. we sample with 14
- * times higher frequency than the signal frequency
- */
-const unsigned char map_table[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
- 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
- 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
- 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
- 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-
-static void urb_complete(struct urb *urb)
-{
- struct ttusbir_device *ttusbir;
- unsigned char *buf;
- int i;
- int l;
-
- ttusbir = urb->context;
-
- if (!ttusbir->opened)
- return;
-
- buf = (unsigned char *)urb->transfer_buffer;
-
- for (i = 0; i < 128; i++) {
- /* Here we do the filtering and some kind of down sampling */
- buf[i] = ~map_table[buf[i]];
- if (ttusbir->last_pulse == buf[i]) {
- if (ttusbir->last_num < PULSE_MASK/63)
- ttusbir->last_num++;
- /*
- * else we are in a idle period and do not need to
- * increment any longer
- */
- } else {
- l = ttusbir->last_num * 62; /* about 62 = us/byte */
- if (ttusbir->last_pulse) /* pulse or space? */
- l |= PULSE_BIT;
- if (!lirc_buffer_full(&ttusbir->rbuf)) {
- lirc_buffer_write(&ttusbir->rbuf, (void *)&l);
- wake_up_interruptible(&ttusbir->rbuf.wait_poll);
- }
- ttusbir->last_num = 0;
- ttusbir->last_pulse = buf[i];
- }
- }
- usb_submit_urb(urb, GFP_ATOMIC); /* keep data rolling :-) */
-}
-
-/*
- * Called whenever the USB subsystem thinks we could be the right driver
- * to handle this device
- */
-static int probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
- int alt_set, endp;
- int found = 0;
- int i, j;
- int struct_size;
- struct usb_host_interface *host_interf;
- struct usb_interface_descriptor *interf_desc;
- struct usb_host_endpoint *host_endpoint;
- struct ttusbir_device *ttusbir;
-
- DPRINTK("Module ttusbir probe\n");
-
- /* To reduce memory fragmentation we use only one allocation */
- struct_size = sizeof(struct ttusbir_device) +
- (sizeof(struct urb *) * num_urbs) +
- (sizeof(char *) * num_urbs) +
- (num_urbs * 128);
- ttusbir = kzalloc(struct_size, GFP_KERNEL);
- if (!ttusbir)
- return -ENOMEM;
-
- ttusbir->urb = (struct urb **)((char *)ttusbir +
- sizeof(struct ttusbir_device));
- ttusbir->buffer = (char **)((char *)ttusbir->urb +
- (sizeof(struct urb *) * num_urbs));
- for (i = 0; i < num_urbs; i++)
- ttusbir->buffer[i] = (char *)ttusbir->buffer +
- (sizeof(char *)*num_urbs) + (i * 128);
-
- ttusbir->usb_driver = &usb_driver;
- ttusbir->alt_setting = -1;
- /* @TODO check if error can be returned */
- ttusbir->udev = usb_get_dev(interface_to_usbdev(intf));
- ttusbir->interf = intf;
- ttusbir->last_pulse = 0x00;
- ttusbir->last_num = 0;
-
- /*
- * Now look for interface setting we can handle
- * We are searching for the alt setting where end point
- * 0x82 has max packet size 16
- */
- for (alt_set = 0; alt_set < intf->num_altsetting && !found; alt_set++) {
- host_interf = &intf->altsetting[alt_set];
- interf_desc = &host_interf->desc;
- for (endp = 0; endp < interf_desc->bNumEndpoints; endp++) {
- host_endpoint = &host_interf->endpoint[endp];
- if ((host_endpoint->desc.bEndpointAddress == 0x82) &&
- (host_endpoint->desc.wMaxPacketSize == 0x10)) {
- ttusbir->alt_setting = alt_set;
- ttusbir->endpoint = endp;
- found = 1;
- break;
- }
- }
- }
- if (ttusbir->alt_setting != -1)
- DPRINTK("alt setting: %d\n", ttusbir->alt_setting);
- else {
- err("Could not find alternate setting\n");
- kfree(ttusbir);
- return -EINVAL;
- }
-
- /* OK lets setup this interface setting */
- usb_set_interface(ttusbir->udev, 0, ttusbir->alt_setting);
-
- /* Store device info in interface structure */
- usb_set_intfdata(intf, ttusbir);
-
- /* Register as a LIRC driver */
- if (lirc_buffer_init(&ttusbir->rbuf, sizeof(int), 256) < 0) {
- err("Could not get memory for LIRC data buffer\n");
- usb_set_intfdata(intf, NULL);
- kfree(ttusbir);
- return -ENOMEM;
- }
- strcpy(ttusbir->driver.name, "TTUSBIR");
- ttusbir->driver.minor = -1;
- ttusbir->driver.code_length = 1;
- ttusbir->driver.sample_rate = 0;
- ttusbir->driver.data = ttusbir;
- ttusbir->driver.add_to_buf = NULL;
- ttusbir->driver.rbuf = &ttusbir->rbuf;
- ttusbir->driver.set_use_inc = set_use_inc;
- ttusbir->driver.set_use_dec = set_use_dec;
- ttusbir->driver.dev = &intf->dev;
- ttusbir->driver.owner = THIS_MODULE;
- ttusbir->driver.features = LIRC_CAN_REC_MODE2;
- ttusbir->minor = lirc_register_driver(&ttusbir->driver);
- if (ttusbir->minor < 0) {
- err("Error registering as LIRC driver\n");
- usb_set_intfdata(intf, NULL);
- lirc_buffer_free(&ttusbir->rbuf);
- kfree(ttusbir);
- return -EIO;
- }
-
- /* Allocate and setup the URB that we will use to talk to the device */
- for (i = 0; i < num_urbs; i++) {
- ttusbir->urb[i] = usb_alloc_urb(8, GFP_KERNEL);
- if (!ttusbir->urb[i]) {
- err("Could not allocate memory for the URB\n");
- for (j = i - 1; j >= 0; j--)
- kfree(ttusbir->urb[j]);
- lirc_buffer_free(&ttusbir->rbuf);
- lirc_unregister_driver(ttusbir->minor);
- kfree(ttusbir);
- usb_set_intfdata(intf, NULL);
- return -ENOMEM;
- }
- ttusbir->urb[i]->dev = ttusbir->udev;
- ttusbir->urb[i]->context = ttusbir;
- ttusbir->urb[i]->pipe = usb_rcvisocpipe(ttusbir->udev,
- ttusbir->endpoint);
- ttusbir->urb[i]->interval = 1;
- ttusbir->urb[i]->transfer_flags = URB_ISO_ASAP;
- ttusbir->urb[i]->transfer_buffer = &ttusbir->buffer[i][0];
- ttusbir->urb[i]->complete = urb_complete;
- ttusbir->urb[i]->number_of_packets = 8;
- ttusbir->urb[i]->transfer_buffer_length = 128;
- for (j = 0; j < 8; j++) {
- ttusbir->urb[i]->iso_frame_desc[j].offset = j*16;
- ttusbir->urb[i]->iso_frame_desc[j].length = 16;
- }
- }
- return 0;
-}
-
-/**
- * Called when the driver is unloaded or the device is unplugged
- */
-static void disconnect(struct usb_interface *intf)
-{
- int i;
- struct ttusbir_device *ttusbir;
-
- DPRINTK("Module ttusbir disconnect\n");
-
- ttusbir = (struct ttusbir_device *) usb_get_intfdata(intf);
- usb_set_intfdata(intf, NULL);
- lirc_unregister_driver(ttusbir->minor);
- DPRINTK("unregistered\n");
-
- for (i = 0; i < num_urbs; i++) {
- usb_kill_urb(ttusbir->urb[i]);
- usb_free_urb(ttusbir->urb[i]);
- }
- DPRINTK("URBs killed\n");
- lirc_buffer_free(&ttusbir->rbuf);
- kfree(ttusbir);
-}
-
-static int ttusbir_init_module(void)
-{
- int result;
-
- DPRINTK(KERN_DEBUG "Module ttusbir init\n");
-
- /* register this driver with the USB subsystem */
- result = usb_register(&usb_driver);
- if (result)
- err("usb_register failed. Error number %d", result);
- return result;
-}
-
-static void ttusbir_exit_module(void)
-{
- printk(KERN_DEBUG "Module ttusbir exit\n");
- usb_deregister(&usb_driver);
-}
-
-module_init(ttusbir_init_module);
-module_exit(ttusbir_exit_module);
diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c
deleted file mode 100644
index dd6a57c3c3a..00000000000
--- a/drivers/staging/lirc/lirc_zilog.c
+++ /dev/null
@@ -1,1678 +0,0 @@
-/*
- * i2c IR lirc driver for devices with zilog IR processors
- *
- * Copyright (c) 2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
- * modified for PixelView (BT878P+W/FM) by
- * Michal Kochanowicz <mkochano@pld.org.pl>
- * Christoph Bartelmus <lirc@bartelmus.de>
- * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by
- * Ulrich Mueller <ulrich.mueller42@web.de>
- * modified for Asus TV-Box and Creative/VisionTek BreakOut-Box by
- * Stefan Jahn <stefan@lkcc.org>
- * modified for inclusion into kernel sources by
- * Jerome Brock <jbrock@users.sourceforge.net>
- * modified for Leadtek Winfast PVR2000 by
- * Thomas Reitmayr (treitmayr@yahoo.com)
- * modified for Hauppauge PVR-150 IR TX device by
- * Mark Weaver <mark@npsl.co.uk>
- * changed name from lirc_pvr150 to lirc_zilog, works on more than pvr-150
- * Jarod Wilson <jarod@redhat.com>
- *
- * parts are cut&pasted from the lirc_i2c.c driver
- *
- * Numerous changes updating lirc_zilog.c in kernel 2.6.38 and later are
- * Copyright (C) 2011 Andy Walls <awalls@md.metrocast.net>
- *
- * 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
- *
- */
-
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/completion.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/firmware.h>
-#include <linux/vmalloc.h>
-
-#include <linux/mutex.h>
-#include <linux/kthread.h>
-
-#include <media/lirc_dev.h>
-#include <media/lirc.h>
-
-struct IR;
-
-struct IR_rx {
- struct kref ref;
- struct IR *ir;
-
- /* RX device */
- struct mutex client_lock;
- struct i2c_client *c;
-
- /* RX polling thread data */
- struct task_struct *task;
-
- /* RX read data */
- unsigned char b[3];
- bool hdpvr_data_fmt;
-};
-
-struct IR_tx {
- struct kref ref;
- struct IR *ir;
-
- /* TX device */
- struct mutex client_lock;
- struct i2c_client *c;
-
- /* TX additional actions needed */
- int need_boot;
- bool post_tx_ready_poll;
-};
-
-struct IR {
- struct kref ref;
- struct list_head list;
-
- /* FIXME spinlock access to l.features */
- struct lirc_driver l;
- struct lirc_buffer rbuf;
-
- struct mutex ir_lock;
- atomic_t open_count;
-
- struct i2c_adapter *adapter;
-
- spinlock_t rx_ref_lock; /* struct IR_rx kref get()/put() */
- struct IR_rx *rx;
-
- spinlock_t tx_ref_lock; /* struct IR_tx kref get()/put() */
- struct IR_tx *tx;
-};
-
-/* IR transceiver instance object list */
-/*
- * This lock is used for the following:
- * a. ir_devices_list access, insertions, deletions
- * b. struct IR kref get()s and put()s
- * c. serialization of ir_probe() for the two i2c_clients for a Z8
- */
-static DEFINE_MUTEX(ir_devices_lock);
-static LIST_HEAD(ir_devices_list);
-
-/* Block size for IR transmitter */
-#define TX_BLOCK_SIZE 99
-
-/* Hauppauge IR transmitter data */
-struct tx_data_struct {
- /* Boot block */
- unsigned char *boot_data;
-
- /* Start of binary data block */
- unsigned char *datap;
-
- /* End of binary data block */
- unsigned char *endp;
-
- /* Number of installed codesets */
- unsigned int num_code_sets;
-
- /* Pointers to codesets */
- unsigned char **code_sets;
-
- /* Global fixed data template */
- int fixed[TX_BLOCK_SIZE];
-};
-
-static struct tx_data_struct *tx_data;
-static struct mutex tx_data_lock;
-
-#define zilog_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, \
- ## args)
-#define zilog_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
-#define zilog_info(s, args...) printk(KERN_INFO KBUILD_MODNAME ": " s, ## args)
-
-/* module parameters */
-static int debug; /* debug output */
-static int tx_only; /* only handle the IR Tx function */
-static int minor = -1; /* minor number */
-
-#define dprintk(fmt, args...) \
- do { \
- if (debug) \
- printk(KERN_DEBUG KBUILD_MODNAME ": " fmt, \
- ## args); \
- } while (0)
-
-
-/* struct IR reference counting */
-static struct IR *get_ir_device(struct IR *ir, bool ir_devices_lock_held)
-{
- if (ir_devices_lock_held) {
- kref_get(&ir->ref);
- } else {
- mutex_lock(&ir_devices_lock);
- kref_get(&ir->ref);
- mutex_unlock(&ir_devices_lock);
- }
- return ir;
-}
-
-static void release_ir_device(struct kref *ref)
-{
- struct IR *ir = container_of(ref, struct IR, ref);
-
- /*
- * Things should be in this state by now:
- * ir->rx set to NULL and deallocated - happens before ir->rx->ir put()
- * ir->rx->task kthread stopped - happens before ir->rx->ir put()
- * ir->tx set to NULL and deallocated - happens before ir->tx->ir put()
- * ir->open_count == 0 - happens on final close()
- * ir_lock, tx_ref_lock, rx_ref_lock, all released
- */
- if (ir->l.minor >= 0 && ir->l.minor < MAX_IRCTL_DEVICES) {
- lirc_unregister_driver(ir->l.minor);
- ir->l.minor = MAX_IRCTL_DEVICES;
- }
- if (ir->rbuf.fifo_initialized)
- lirc_buffer_free(&ir->rbuf);
- list_del(&ir->list);
- kfree(ir);
-}
-
-static int put_ir_device(struct IR *ir, bool ir_devices_lock_held)
-{
- int released;
-
- if (ir_devices_lock_held)
- return kref_put(&ir->ref, release_ir_device);
-
- mutex_lock(&ir_devices_lock);
- released = kref_put(&ir->ref, release_ir_device);
- mutex_unlock(&ir_devices_lock);
-
- return released;
-}
-
-/* struct IR_rx reference counting */
-static struct IR_rx *get_ir_rx(struct IR *ir)
-{
- struct IR_rx *rx;
-
- spin_lock(&ir->rx_ref_lock);
- rx = ir->rx;
- if (rx != NULL)
- kref_get(&rx->ref);
- spin_unlock(&ir->rx_ref_lock);
- return rx;
-}
-
-static void destroy_rx_kthread(struct IR_rx *rx, bool ir_devices_lock_held)
-{
- /* end up polling thread */
- if (!IS_ERR_OR_NULL(rx->task)) {
- kthread_stop(rx->task);
- rx->task = NULL;
- /* Put the ir ptr that ir_probe() gave to the rx poll thread */
- put_ir_device(rx->ir, ir_devices_lock_held);
- }
-}
-
-static void release_ir_rx(struct kref *ref)
-{
- struct IR_rx *rx = container_of(ref, struct IR_rx, ref);
- struct IR *ir = rx->ir;
-
- /*
- * This release function can't do all the work, as we want
- * to keep the rx_ref_lock a spinlock, and killing the poll thread
- * and releasing the ir reference can cause a sleep. That work is
- * performed by put_ir_rx()
- */
- ir->l.features &= ~LIRC_CAN_REC_LIRCCODE;
- /* Don't put_ir_device(rx->ir) here; lock can't be freed yet */
- ir->rx = NULL;
- /* Don't do the kfree(rx) here; we still need to kill the poll thread */
- return;
-}
-
-static int put_ir_rx(struct IR_rx *rx, bool ir_devices_lock_held)
-{
- int released;
- struct IR *ir = rx->ir;
-
- spin_lock(&ir->rx_ref_lock);
- released = kref_put(&rx->ref, release_ir_rx);
- spin_unlock(&ir->rx_ref_lock);
- /* Destroy the rx kthread while not holding the spinlock */
- if (released) {
- destroy_rx_kthread(rx, ir_devices_lock_held);
- kfree(rx);
- /* Make sure we're not still in a poll_table somewhere */
- wake_up_interruptible(&ir->rbuf.wait_poll);
- }
- /* Do a reference put() for the rx->ir reference, if we released rx */
- if (released)
- put_ir_device(ir, ir_devices_lock_held);
- return released;
-}
-
-/* struct IR_tx reference counting */
-static struct IR_tx *get_ir_tx(struct IR *ir)
-{
- struct IR_tx *tx;
-
- spin_lock(&ir->tx_ref_lock);
- tx = ir->tx;
- if (tx != NULL)
- kref_get(&tx->ref);
- spin_unlock(&ir->tx_ref_lock);
- return tx;
-}
-
-static void release_ir_tx(struct kref *ref)
-{
- struct IR_tx *tx = container_of(ref, struct IR_tx, ref);
- struct IR *ir = tx->ir;
-
- ir->l.features &= ~LIRC_CAN_SEND_PULSE;
- /* Don't put_ir_device(tx->ir) here, so our lock doesn't get freed */
- ir->tx = NULL;
- kfree(tx);
-}
-
-static int put_ir_tx(struct IR_tx *tx, bool ir_devices_lock_held)
-{
- int released;
- struct IR *ir = tx->ir;
-
- spin_lock(&ir->tx_ref_lock);
- released = kref_put(&tx->ref, release_ir_tx);
- spin_unlock(&ir->tx_ref_lock);
- /* Do a reference put() for the tx->ir reference, if we released tx */
- if (released)
- put_ir_device(ir, ir_devices_lock_held);
- return released;
-}
-
-static int add_to_buf(struct IR *ir)
-{
- __u16 code;
- unsigned char codes[2];
- unsigned char keybuf[6];
- int got_data = 0;
- int ret;
- int failures = 0;
- unsigned char sendbuf[1] = { 0 };
- struct lirc_buffer *rbuf = ir->l.rbuf;
- struct IR_rx *rx;
- struct IR_tx *tx;
-
- if (lirc_buffer_full(rbuf)) {
- dprintk("buffer overflow\n");
- return -EOVERFLOW;
- }
-
- rx = get_ir_rx(ir);
- if (rx == NULL)
- return -ENXIO;
-
- /* Ensure our rx->c i2c_client remains valid for the duration */
- mutex_lock(&rx->client_lock);
- if (rx->c == NULL) {
- mutex_unlock(&rx->client_lock);
- put_ir_rx(rx, false);
- return -ENXIO;
- }
-
- tx = get_ir_tx(ir);
-
- /*
- * service the device as long as it is returning
- * data and we have space
- */
- do {
- if (kthread_should_stop()) {
- ret = -ENODATA;
- break;
- }
-
- /*
- * Lock i2c bus for the duration. RX/TX chips interfere so
- * this is worth it
- */
- mutex_lock(&ir->ir_lock);
-
- if (kthread_should_stop()) {
- mutex_unlock(&ir->ir_lock);
- ret = -ENODATA;
- break;
- }
-
- /*
- * Send random "poll command" (?) Windows driver does this
- * and it is a good point to detect chip failure.
- */
- ret = i2c_master_send(rx->c, sendbuf, 1);
- if (ret != 1) {
- zilog_error("i2c_master_send failed with %d\n", ret);
- if (failures >= 3) {
- mutex_unlock(&ir->ir_lock);
- zilog_error("unable to read from the IR chip "
- "after 3 resets, giving up\n");
- break;
- }
-
- /* Looks like the chip crashed, reset it */
- zilog_error("polling the IR receiver chip failed, "
- "trying reset\n");
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- if (kthread_should_stop()) {
- mutex_unlock(&ir->ir_lock);
- ret = -ENODATA;
- break;
- }
- schedule_timeout((100 * HZ + 999) / 1000);
- if (tx != NULL)
- tx->need_boot = 1;
-
- ++failures;
- mutex_unlock(&ir->ir_lock);
- ret = 0;
- continue;
- }
-
- if (kthread_should_stop()) {
- mutex_unlock(&ir->ir_lock);
- ret = -ENODATA;
- break;
- }
- ret = i2c_master_recv(rx->c, keybuf, sizeof(keybuf));
- mutex_unlock(&ir->ir_lock);
- if (ret != sizeof(keybuf)) {
- zilog_error("i2c_master_recv failed with %d -- "
- "keeping last read buffer\n", ret);
- } else {
- rx->b[0] = keybuf[3];
- rx->b[1] = keybuf[4];
- rx->b[2] = keybuf[5];
- dprintk("key (0x%02x/0x%02x)\n", rx->b[0], rx->b[1]);
- }
-
- /* key pressed ? */
- if (rx->hdpvr_data_fmt) {
- if (got_data && (keybuf[0] == 0x80)) {
- ret = 0;
- break;
- } else if (got_data && (keybuf[0] == 0x00)) {
- ret = -ENODATA;
- break;
- }
- } else if ((rx->b[0] & 0x80) == 0) {
- ret = got_data ? 0 : -ENODATA;
- break;
- }
-
- /* look what we have */
- code = (((__u16)rx->b[0] & 0x7f) << 6) | (rx->b[1] >> 2);
-
- codes[0] = (code >> 8) & 0xff;
- codes[1] = code & 0xff;
-
- /* return it */
- lirc_buffer_write(rbuf, codes);
- ++got_data;
- ret = 0;
- } while (!lirc_buffer_full(rbuf));
-
- mutex_unlock(&rx->client_lock);
- if (tx != NULL)
- put_ir_tx(tx, false);
- put_ir_rx(rx, false);
- return ret;
-}
-
-/*
- * Main function of the polling thread -- from lirc_dev.
- * We don't fit the LIRC model at all anymore. This is horrible, but
- * basically we have a single RX/TX device with a nasty failure mode
- * that needs to be accounted for across the pair. lirc lets us provide
- * fops, but prevents us from using the internal polling, etc. if we do
- * so. Hence the replication. Might be neater to extend the LIRC model
- * to account for this but I'd think it's a very special case of seriously
- * messed up hardware.
- */
-static int lirc_thread(void *arg)
-{
- struct IR *ir = arg;
- struct lirc_buffer *rbuf = ir->l.rbuf;
-
- dprintk("poll thread started\n");
-
- while (!kthread_should_stop()) {
- /* if device not opened, we can sleep half a second */
- if (atomic_read(&ir->open_count) == 0) {
- schedule_timeout(HZ/2);
- continue;
- }
-
- set_current_state(TASK_INTERRUPTIBLE);
-
- /*
- * This is ~113*2 + 24 + jitter (2*repeat gap + code length).
- * We use this interval as the chip resets every time you poll
- * it (bad!). This is therefore just sufficient to catch all
- * of the button presses. It makes the remote much more
- * responsive. You can see the difference by running irw and
- * holding down a button. With 100ms, the old polling
- * interval, you'll notice breaks in the repeat sequence
- * corresponding to lost keypresses.
- */
- schedule_timeout((260 * HZ) / 1000);
- if (kthread_should_stop())
- break;
- if (!add_to_buf(ir))
- wake_up_interruptible(&rbuf->wait_poll);
- }
-
- dprintk("poll thread ended\n");
- return 0;
-}
-
-static int set_use_inc(void *data)
-{
- return 0;
-}
-
-static void set_use_dec(void *data)
-{
- return;
-}
-
-/* safe read of a uint32 (always network byte order) */
-static int read_uint32(unsigned char **data,
- unsigned char *endp, unsigned int *val)
-{
- if (*data + 4 > endp)
- return 0;
- *val = ((*data)[0] << 24) | ((*data)[1] << 16) |
- ((*data)[2] << 8) | (*data)[3];
- *data += 4;
- return 1;
-}
-
-/* safe read of a uint8 */
-static int read_uint8(unsigned char **data,
- unsigned char *endp, unsigned char *val)
-{
- if (*data + 1 > endp)
- return 0;
- *val = *((*data)++);
- return 1;
-}
-
-/* safe skipping of N bytes */
-static int skip(unsigned char **data,
- unsigned char *endp, unsigned int distance)
-{
- if (*data + distance > endp)
- return 0;
- *data += distance;
- return 1;
-}
-
-/* decompress key data into the given buffer */
-static int get_key_data(unsigned char *buf,
- unsigned int codeset, unsigned int key)
-{
- unsigned char *data, *endp, *diffs, *key_block;
- unsigned char keys, ndiffs, id;
- unsigned int base, lim, pos, i;
-
- /* Binary search for the codeset */
- for (base = 0, lim = tx_data->num_code_sets; lim; lim >>= 1) {
- pos = base + (lim >> 1);
- data = tx_data->code_sets[pos];
-
- if (!read_uint32(&data, tx_data->endp, &i))
- goto corrupt;
-
- if (i == codeset)
- break;
- else if (codeset > i) {
- base = pos + 1;
- --lim;
- }
- }
- /* Not found? */
- if (!lim)
- return -EPROTO;
-
- /* Set end of data block */
- endp = pos < tx_data->num_code_sets - 1 ?
- tx_data->code_sets[pos + 1] : tx_data->endp;
-
- /* Read the block header */
- if (!read_uint8(&data, endp, &keys) ||
- !read_uint8(&data, endp, &ndiffs) ||
- ndiffs > TX_BLOCK_SIZE || keys == 0)
- goto corrupt;
-
- /* Save diffs & skip */
- diffs = data;
- if (!skip(&data, endp, ndiffs))
- goto corrupt;
-
- /* Read the id of the first key */
- if (!read_uint8(&data, endp, &id))
- goto corrupt;
-
- /* Unpack the first key's data */
- for (i = 0; i < TX_BLOCK_SIZE; ++i) {
- if (tx_data->fixed[i] == -1) {
- if (!read_uint8(&data, endp, &buf[i]))
- goto corrupt;
- } else {
- buf[i] = (unsigned char)tx_data->fixed[i];
- }
- }
-
- /* Early out key found/not found */
- if (key == id)
- return 0;
- if (keys == 1)
- return -EPROTO;
-
- /* Sanity check */
- key_block = data;
- if (!skip(&data, endp, (keys - 1) * (ndiffs + 1)))
- goto corrupt;
-
- /* Binary search for the key */
- for (base = 0, lim = keys - 1; lim; lim >>= 1) {
- /* Seek to block */
- unsigned char *key_data;
- pos = base + (lim >> 1);
- key_data = key_block + (ndiffs + 1) * pos;
-
- if (*key_data == key) {
- /* skip key id */
- ++key_data;
-
- /* found, so unpack the diffs */
- for (i = 0; i < ndiffs; ++i) {
- unsigned char val;
- if (!read_uint8(&key_data, endp, &val) ||
- diffs[i] >= TX_BLOCK_SIZE)
- goto corrupt;
- buf[diffs[i]] = val;
- }
-
- return 0;
- } else if (key > *key_data) {
- base = pos + 1;
- --lim;
- }
- }
- /* Key not found */
- return -EPROTO;
-
-corrupt:
- zilog_error("firmware is corrupt\n");
- return -EFAULT;
-}
-
-/* send a block of data to the IR TX device */
-static int send_data_block(struct IR_tx *tx, unsigned char *data_block)
-{
- int i, j, ret;
- unsigned char buf[5];
-
- for (i = 0; i < TX_BLOCK_SIZE;) {
- int tosend = TX_BLOCK_SIZE - i;
- if (tosend > 4)
- tosend = 4;
- buf[0] = (unsigned char)(i + 1);
- for (j = 0; j < tosend; ++j)
- buf[1 + j] = data_block[i + j];
- dprintk("%02x %02x %02x %02x %02x",
- buf[0], buf[1], buf[2], buf[3], buf[4]);
- ret = i2c_master_send(tx->c, buf, tosend + 1);
- if (ret != tosend + 1) {
- zilog_error("i2c_master_send failed with %d\n", ret);
- return ret < 0 ? ret : -EFAULT;
- }
- i += tosend;
- }
- return 0;
-}
-
-/* send boot data to the IR TX device */
-static int send_boot_data(struct IR_tx *tx)
-{
- int ret, i;
- unsigned char buf[4];
-
- /* send the boot block */
- ret = send_data_block(tx, tx_data->boot_data);
- if (ret != 0)
- return ret;
-
- /* Hit the go button to activate the new boot data */
- buf[0] = 0x00;
- buf[1] = 0x20;
- ret = i2c_master_send(tx->c, buf, 2);
- if (ret != 2) {
- zilog_error("i2c_master_send failed with %d\n", ret);
- return ret < 0 ? ret : -EFAULT;
- }
-
- /*
- * Wait for zilog to settle after hitting go post boot block upload.
- * Without this delay, the HD-PVR and HVR-1950 both return an -EIO
- * upon attempting to get firmware revision, and tx probe thus fails.
- */
- for (i = 0; i < 10; i++) {
- ret = i2c_master_send(tx->c, buf, 1);
- if (ret == 1)
- break;
- udelay(100);
- }
-
- if (ret != 1) {
- zilog_error("i2c_master_send failed with %d\n", ret);
- return ret < 0 ? ret : -EFAULT;
- }
-
- /* Here comes the firmware version... (hopefully) */
- ret = i2c_master_recv(tx->c, buf, 4);
- if (ret != 4) {
- zilog_error("i2c_master_recv failed with %d\n", ret);
- return 0;
- }
- if ((buf[0] != 0x80) && (buf[0] != 0xa0)) {
- zilog_error("unexpected IR TX init response: %02x\n", buf[0]);
- return 0;
- }
- zilog_notify("Zilog/Hauppauge IR blaster firmware version "
- "%d.%d.%d loaded\n", buf[1], buf[2], buf[3]);
-
- return 0;
-}
-
-/* unload "firmware", lock held */
-static void fw_unload_locked(void)
-{
- if (tx_data) {
- if (tx_data->code_sets)
- vfree(tx_data->code_sets);
-
- if (tx_data->datap)
- vfree(tx_data->datap);
-
- vfree(tx_data);
- tx_data = NULL;
- dprintk("successfully unloaded IR blaster firmware\n");
- }
-}
-
-/* unload "firmware" for the IR TX device */
-static void fw_unload(void)
-{
- mutex_lock(&tx_data_lock);
- fw_unload_locked();
- mutex_unlock(&tx_data_lock);
-}
-
-/* load "firmware" for the IR TX device */
-static int fw_load(struct IR_tx *tx)
-{
- int ret;
- unsigned int i;
- unsigned char *data, version, num_global_fixed;
- const struct firmware *fw_entry;
-
- /* Already loaded? */
- mutex_lock(&tx_data_lock);
- if (tx_data) {
- ret = 0;
- goto out;
- }
-
- /* Request codeset data file */
- ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx->ir->l.dev);
- if (ret != 0) {
- zilog_error("firmware haup-ir-blaster.bin not available "
- "(%d)\n", ret);
- ret = ret < 0 ? ret : -EFAULT;
- goto out;
- }
- dprintk("firmware of size %zu loaded\n", fw_entry->size);
-
- /* Parse the file */
- tx_data = vmalloc(sizeof(*tx_data));
- if (tx_data == NULL) {
- zilog_error("out of memory\n");
- release_firmware(fw_entry);
- ret = -ENOMEM;
- goto out;
- }
- tx_data->code_sets = NULL;
-
- /* Copy the data so hotplug doesn't get confused and timeout */
- tx_data->datap = vmalloc(fw_entry->size);
- if (tx_data->datap == NULL) {
- zilog_error("out of memory\n");
- release_firmware(fw_entry);
- vfree(tx_data);
- ret = -ENOMEM;
- goto out;
- }
- memcpy(tx_data->datap, fw_entry->data, fw_entry->size);
- tx_data->endp = tx_data->datap + fw_entry->size;
- release_firmware(fw_entry); fw_entry = NULL;
-
- /* Check version */
- data = tx_data->datap;
- if (!read_uint8(&data, tx_data->endp, &version))
- goto corrupt;
- if (version != 1) {
- zilog_error("unsupported code set file version (%u, expected"
- "1) -- please upgrade to a newer driver",
- version);
- fw_unload_locked();
- ret = -EFAULT;
- goto out;
- }
-
- /* Save boot block for later */
- tx_data->boot_data = data;
- if (!skip(&data, tx_data->endp, TX_BLOCK_SIZE))
- goto corrupt;
-
- if (!read_uint32(&data, tx_data->endp,
- &tx_data->num_code_sets))
- goto corrupt;
-
- dprintk("%u IR blaster codesets loaded\n", tx_data->num_code_sets);
-
- tx_data->code_sets = vmalloc(
- tx_data->num_code_sets * sizeof(char *));
- if (tx_data->code_sets == NULL) {
- fw_unload_locked();
- ret = -ENOMEM;
- goto out;
- }
-
- for (i = 0; i < TX_BLOCK_SIZE; ++i)
- tx_data->fixed[i] = -1;
-
- /* Read global fixed data template */
- if (!read_uint8(&data, tx_data->endp, &num_global_fixed) ||
- num_global_fixed > TX_BLOCK_SIZE)
- goto corrupt;
- for (i = 0; i < num_global_fixed; ++i) {
- unsigned char pos, val;
- if (!read_uint8(&data, tx_data->endp, &pos) ||
- !read_uint8(&data, tx_data->endp, &val) ||
- pos >= TX_BLOCK_SIZE)
- goto corrupt;
- tx_data->fixed[pos] = (int)val;
- }
-
- /* Filch out the position of each code set */
- for (i = 0; i < tx_data->num_code_sets; ++i) {
- unsigned int id;
- unsigned char keys;
- unsigned char ndiffs;
-
- /* Save the codeset position */
- tx_data->code_sets[i] = data;
-
- /* Read header */
- if (!read_uint32(&data, tx_data->endp, &id) ||
- !read_uint8(&data, tx_data->endp, &keys) ||
- !read_uint8(&data, tx_data->endp, &ndiffs) ||
- ndiffs > TX_BLOCK_SIZE || keys == 0)
- goto corrupt;
-
- /* skip diff positions */
- if (!skip(&data, tx_data->endp, ndiffs))
- goto corrupt;
-
- /*
- * After the diffs we have the first key id + data -
- * global fixed
- */
- if (!skip(&data, tx_data->endp,
- 1 + TX_BLOCK_SIZE - num_global_fixed))
- goto corrupt;
-
- /* Then we have keys-1 blocks of key id+diffs */
- if (!skip(&data, tx_data->endp,
- (ndiffs + 1) * (keys - 1)))
- goto corrupt;
- }
- ret = 0;
- goto out;
-
-corrupt:
- zilog_error("firmware is corrupt\n");
- fw_unload_locked();
- ret = -EFAULT;
-
-out:
- mutex_unlock(&tx_data_lock);
- return ret;
-}
-
-/* copied from lirc_dev */
-static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos)
-{
- struct IR *ir = filep->private_data;
- struct IR_rx *rx;
- struct lirc_buffer *rbuf = ir->l.rbuf;
- int ret = 0, written = 0, retries = 0;
- unsigned int m;
- DECLARE_WAITQUEUE(wait, current);
-
- dprintk("read called\n");
- if (n % rbuf->chunk_size) {
- dprintk("read result = -EINVAL\n");
- return -EINVAL;
- }
-
- rx = get_ir_rx(ir);
- if (rx == NULL)
- return -ENXIO;
-
- /*
- * we add ourselves to the task queue before buffer check
- * to avoid losing scan code (in case when queue is awaken somewhere
- * between while condition checking and scheduling)
- */
- add_wait_queue(&rbuf->wait_poll, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
-
- /*
- * while we didn't provide 'length' bytes, device is opened in blocking
- * mode and 'copy_to_user' is happy, wait for data.
- */
- while (written < n && ret == 0) {
- if (lirc_buffer_empty(rbuf)) {
- /*
- * According to the read(2) man page, 'written' can be
- * returned as less than 'n', instead of blocking
- * again, returning -EWOULDBLOCK, or returning
- * -ERESTARTSYS
- */
- if (written)
- break;
- if (filep->f_flags & O_NONBLOCK) {
- ret = -EWOULDBLOCK;
- break;
- }
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
- break;
- }
- schedule();
- set_current_state(TASK_INTERRUPTIBLE);
- } else {
- unsigned char buf[rbuf->chunk_size];
- m = lirc_buffer_read(rbuf, buf);
- if (m == rbuf->chunk_size) {
- ret = copy_to_user((void *)outbuf+written, buf,
- rbuf->chunk_size);
- written += rbuf->chunk_size;
- } else {
- retries++;
- }
- if (retries >= 5) {
- zilog_error("Buffer read failed!\n");
- ret = -EIO;
- }
- }
- }
-
- remove_wait_queue(&rbuf->wait_poll, &wait);
- put_ir_rx(rx, false);
- set_current_state(TASK_RUNNING);
-
- dprintk("read result = %d (%s)\n", ret, ret ? "Error" : "OK");
-
- return ret ? ret : written;
-}
-
-/* send a keypress to the IR TX device */
-static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
-{
- unsigned char data_block[TX_BLOCK_SIZE];
- unsigned char buf[2];
- int i, ret;
-
- /* Get data for the codeset/key */
- ret = get_key_data(data_block, code, key);
-
- if (ret == -EPROTO) {
- zilog_error("failed to get data for code %u, key %u -- check "
- "lircd.conf entries\n", code, key);
- return ret;
- } else if (ret != 0)
- return ret;
-
- /* Send the data block */
- ret = send_data_block(tx, data_block);
- if (ret != 0)
- return ret;
-
- /* Send data block length? */
- buf[0] = 0x00;
- buf[1] = 0x40;
- ret = i2c_master_send(tx->c, buf, 2);
- if (ret != 2) {
- zilog_error("i2c_master_send failed with %d\n", ret);
- return ret < 0 ? ret : -EFAULT;
- }
-
- /* Give the z8 a moment to process data block */
- for (i = 0; i < 10; i++) {
- ret = i2c_master_send(tx->c, buf, 1);
- if (ret == 1)
- break;
- udelay(100);
- }
-
- if (ret != 1) {
- zilog_error("i2c_master_send failed with %d\n", ret);
- return ret < 0 ? ret : -EFAULT;
- }
-
- /* Send finished download? */
- ret = i2c_master_recv(tx->c, buf, 1);
- if (ret != 1) {
- zilog_error("i2c_master_recv failed with %d\n", ret);
- return ret < 0 ? ret : -EFAULT;
- }
- if (buf[0] != 0xA0) {
- zilog_error("unexpected IR TX response #1: %02x\n",
- buf[0]);
- return -EFAULT;
- }
-
- /* Send prepare command? */
- buf[0] = 0x00;
- buf[1] = 0x80;
- ret = i2c_master_send(tx->c, buf, 2);
- if (ret != 2) {
- zilog_error("i2c_master_send failed with %d\n", ret);
- return ret < 0 ? ret : -EFAULT;
- }
-
- /*
- * The sleep bits aren't necessary on the HD PVR, and in fact, the
- * last i2c_master_recv always fails with a -5, so for now, we're
- * going to skip this whole mess and say we're done on the HD PVR
- */
- if (!tx->post_tx_ready_poll) {
- dprintk("sent code %u, key %u\n", code, key);
- return 0;
- }
-
- /*
- * This bit NAKs until the device is ready, so we retry it
- * sleeping a bit each time. This seems to be what the windows
- * driver does, approximately.
- * Try for up to 1s.
- */
- for (i = 0; i < 20; ++i) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout((50 * HZ + 999) / 1000);
- ret = i2c_master_send(tx->c, buf, 1);
- if (ret == 1)
- break;
- dprintk("NAK expected: i2c_master_send "
- "failed with %d (try %d)\n", ret, i+1);
- }
- if (ret != 1) {
- zilog_error("IR TX chip never got ready: last i2c_master_send "
- "failed with %d\n", ret);
- return ret < 0 ? ret : -EFAULT;
- }
-
- /* Seems to be an 'ok' response */
- i = i2c_master_recv(tx->c, buf, 1);
- if (i != 1) {
- zilog_error("i2c_master_recv failed with %d\n", ret);
- return -EFAULT;
- }
- if (buf[0] != 0x80) {
- zilog_error("unexpected IR TX response #2: %02x\n", buf[0]);
- return -EFAULT;
- }
-
- /* Oh good, it worked */
- dprintk("sent code %u, key %u\n", code, key);
- return 0;
-}
-
-/*
- * Write a code to the device. We take in a 32-bit number (an int) and then
- * decode this to a codeset/key index. The key data is then decompressed and
- * sent to the device. We have a spin lock as per i2c documentation to prevent
- * multiple concurrent sends which would probably cause the device to explode.
- */
-static ssize_t write(struct file *filep, const char *buf, size_t n,
- loff_t *ppos)
-{
- struct IR *ir = filep->private_data;
- struct IR_tx *tx;
- size_t i;
- int failures = 0;
-
- /* Validate user parameters */
- if (n % sizeof(int))
- return -EINVAL;
-
- /* Get a struct IR_tx reference */
- tx = get_ir_tx(ir);
- if (tx == NULL)
- return -ENXIO;
-
- /* Ensure our tx->c i2c_client remains valid for the duration */
- mutex_lock(&tx->client_lock);
- if (tx->c == NULL) {
- mutex_unlock(&tx->client_lock);
- put_ir_tx(tx, false);
- return -ENXIO;
- }
-
- /* Lock i2c bus for the duration */
- mutex_lock(&ir->ir_lock);
-
- /* Send each keypress */
- for (i = 0; i < n;) {
- int ret = 0;
- int command;
-
- if (copy_from_user(&command, buf + i, sizeof(command))) {
- mutex_unlock(&ir->ir_lock);
- mutex_unlock(&tx->client_lock);
- put_ir_tx(tx, false);
- return -EFAULT;
- }
-
- /* Send boot data first if required */
- if (tx->need_boot == 1) {
- /* Make sure we have the 'firmware' loaded, first */
- ret = fw_load(tx);
- if (ret != 0) {
- mutex_unlock(&ir->ir_lock);
- mutex_unlock(&tx->client_lock);
- put_ir_tx(tx, false);
- if (ret != -ENOMEM)
- ret = -EIO;
- return ret;
- }
- /* Prep the chip for transmitting codes */
- ret = send_boot_data(tx);
- if (ret == 0)
- tx->need_boot = 0;
- }
-
- /* Send the code */
- if (ret == 0) {
- ret = send_code(tx, (unsigned)command >> 16,
- (unsigned)command & 0xFFFF);
- if (ret == -EPROTO) {
- mutex_unlock(&ir->ir_lock);
- mutex_unlock(&tx->client_lock);
- put_ir_tx(tx, false);
- return ret;
- }
- }
-
- /*
- * Hmm, a failure. If we've had a few then give up, otherwise
- * try a reset
- */
- if (ret != 0) {
- /* Looks like the chip crashed, reset it */
- zilog_error("sending to the IR transmitter chip "
- "failed, trying reset\n");
-
- if (failures >= 3) {
- zilog_error("unable to send to the IR chip "
- "after 3 resets, giving up\n");
- mutex_unlock(&ir->ir_lock);
- mutex_unlock(&tx->client_lock);
- put_ir_tx(tx, false);
- return ret;
- }
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout((100 * HZ + 999) / 1000);
- tx->need_boot = 1;
- ++failures;
- } else
- i += sizeof(int);
- }
-
- /* Release i2c bus */
- mutex_unlock(&ir->ir_lock);
-
- mutex_unlock(&tx->client_lock);
-
- /* Give back our struct IR_tx reference */
- put_ir_tx(tx, false);
-
- /* All looks good */
- return n;
-}
-
-/* copied from lirc_dev */
-static unsigned int poll(struct file *filep, poll_table *wait)
-{
- struct IR *ir = filep->private_data;
- struct IR_rx *rx;
- struct lirc_buffer *rbuf = ir->l.rbuf;
- unsigned int ret;
-
- dprintk("poll called\n");
-
- rx = get_ir_rx(ir);
- if (rx == NULL) {
- /*
- * Revisit this, if our poll function ever reports writeable
- * status for Tx
- */
- dprintk("poll result = POLLERR\n");
- return POLLERR;
- }
-
- /*
- * Add our lirc_buffer's wait_queue to the poll_table. A wake up on
- * that buffer's wait queue indicates we may have a new poll status.
- */
- poll_wait(filep, &rbuf->wait_poll, wait);
-
- /* Indicate what ops could happen immediately without blocking */
- ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN|POLLRDNORM);
-
- dprintk("poll result = %s\n", ret ? "POLLIN|POLLRDNORM" : "none");
- return ret;
-}
-
-static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
-{
- struct IR *ir = filep->private_data;
- int result;
- unsigned long mode, features;
-
- features = ir->l.features;
-
- switch (cmd) {
- case LIRC_GET_LENGTH:
- result = put_user((unsigned long)13,
- (unsigned long *)arg);
- break;
- case LIRC_GET_FEATURES:
- result = put_user(features, (unsigned long *) arg);
- break;
- case LIRC_GET_REC_MODE:
- if (!(features&LIRC_CAN_REC_MASK))
- return -ENOSYS;
-
- result = put_user(LIRC_REC2MODE
- (features&LIRC_CAN_REC_MASK),
- (unsigned long *)arg);
- break;
- case LIRC_SET_REC_MODE:
- if (!(features&LIRC_CAN_REC_MASK))
- return -ENOSYS;
-
- result = get_user(mode, (unsigned long *)arg);
- if (!result && !(LIRC_MODE2REC(mode) & features))
- result = -EINVAL;
- break;
- case LIRC_GET_SEND_MODE:
- if (!(features&LIRC_CAN_SEND_MASK))
- return -ENOSYS;
-
- result = put_user(LIRC_MODE_PULSE, (unsigned long *) arg);
- break;
- case LIRC_SET_SEND_MODE:
- if (!(features&LIRC_CAN_SEND_MASK))
- return -ENOSYS;
-
- result = get_user(mode, (unsigned long *) arg);
- if (!result && mode != LIRC_MODE_PULSE)
- return -EINVAL;
- break;
- default:
- return -EINVAL;
- }
- return result;
-}
-
-static struct IR *get_ir_device_by_minor(unsigned int minor)
-{
- struct IR *ir;
- struct IR *ret = NULL;
-
- mutex_lock(&ir_devices_lock);
-
- if (!list_empty(&ir_devices_list)) {
- list_for_each_entry(ir, &ir_devices_list, list) {
- if (ir->l.minor == minor) {
- ret = get_ir_device(ir, true);
- break;
- }
- }
- }
-
- mutex_unlock(&ir_devices_lock);
- return ret;
-}
-
-/*
- * Open the IR device. Get hold of our IR structure and
- * stash it in private_data for the file
- */
-static int open(struct inode *node, struct file *filep)
-{
- struct IR *ir;
- unsigned int minor = MINOR(node->i_rdev);
-
- /* find our IR struct */
- ir = get_ir_device_by_minor(minor);
-
- if (ir == NULL)
- return -ENODEV;
-
- atomic_inc(&ir->open_count);
-
- /* stash our IR struct */
- filep->private_data = ir;
-
- nonseekable_open(node, filep);
- return 0;
-}
-
-/* Close the IR device */
-static int close(struct inode *node, struct file *filep)
-{
- /* find our IR struct */
- struct IR *ir = filep->private_data;
- if (ir == NULL) {
- zilog_error("close: no private_data attached to the file!\n");
- return -ENODEV;
- }
-
- atomic_dec(&ir->open_count);
-
- put_ir_device(ir, false);
- return 0;
-}
-
-static int ir_remove(struct i2c_client *client);
-static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id);
-
-#define ID_FLAG_TX 0x01
-#define ID_FLAG_HDPVR 0x02
-
-static const struct i2c_device_id ir_transceiver_id[] = {
- { "ir_tx_z8f0811_haup", ID_FLAG_TX },
- { "ir_rx_z8f0811_haup", 0 },
- { "ir_tx_z8f0811_hdpvr", ID_FLAG_HDPVR | ID_FLAG_TX },
- { "ir_rx_z8f0811_hdpvr", ID_FLAG_HDPVR },
- { }
-};
-
-static struct i2c_driver driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "Zilog/Hauppauge i2c IR",
- },
- .probe = ir_probe,
- .remove = ir_remove,
- .id_table = ir_transceiver_id,
-};
-
-static const struct file_operations lirc_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = read,
- .write = write,
- .poll = poll,
- .unlocked_ioctl = ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = ioctl,
-#endif
- .open = open,
- .release = close
-};
-
-static struct lirc_driver lirc_template = {
- .name = "lirc_zilog",
- .minor = -1,
- .code_length = 13,
- .buffer_size = BUFLEN / 2,
- .sample_rate = 0, /* tell lirc_dev to not start its own kthread */
- .chunk_size = 2,
- .set_use_inc = set_use_inc,
- .set_use_dec = set_use_dec,
- .fops = &lirc_fops,
- .owner = THIS_MODULE,
-};
-
-static int ir_remove(struct i2c_client *client)
-{
- if (strncmp("ir_tx_z8", client->name, 8) == 0) {
- struct IR_tx *tx = i2c_get_clientdata(client);
- if (tx != NULL) {
- mutex_lock(&tx->client_lock);
- tx->c = NULL;
- mutex_unlock(&tx->client_lock);
- put_ir_tx(tx, false);
- }
- } else if (strncmp("ir_rx_z8", client->name, 8) == 0) {
- struct IR_rx *rx = i2c_get_clientdata(client);
- if (rx != NULL) {
- mutex_lock(&rx->client_lock);
- rx->c = NULL;
- mutex_unlock(&rx->client_lock);
- put_ir_rx(rx, false);
- }
- }
- return 0;
-}
-
-
-/* ir_devices_lock must be held */
-static struct IR *get_ir_device_by_adapter(struct i2c_adapter *adapter)
-{
- struct IR *ir;
-
- if (list_empty(&ir_devices_list))
- return NULL;
-
- list_for_each_entry(ir, &ir_devices_list, list)
- if (ir->adapter == adapter) {
- get_ir_device(ir, true);
- return ir;
- }
-
- return NULL;
-}
-
-static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
- struct IR *ir;
- struct IR_tx *tx;
- struct IR_rx *rx;
- struct i2c_adapter *adap = client->adapter;
- int ret;
- bool tx_probe = false;
-
- dprintk("%s: %s on i2c-%d (%s), client addr=0x%02x\n",
- __func__, id->name, adap->nr, adap->name, client->addr);
-
- /*
- * The IR receiver is at i2c address 0x71.
- * The IR transmitter is at i2c address 0x70.
- */
-
- if (id->driver_data & ID_FLAG_TX)
- tx_probe = true;
- else if (tx_only) /* module option */
- return -ENXIO;
-
- zilog_info("probing IR %s on %s (i2c-%d)\n",
- tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
-
- mutex_lock(&ir_devices_lock);
-
- /* Use a single struct IR instance for both the Rx and Tx functions */
- ir = get_ir_device_by_adapter(adap);
- if (ir == NULL) {
- ir = kzalloc(sizeof(struct IR), GFP_KERNEL);
- if (ir == NULL) {
- ret = -ENOMEM;
- goto out_no_ir;
- }
- kref_init(&ir->ref);
-
- /* store for use in ir_probe() again, and open() later on */
- INIT_LIST_HEAD(&ir->list);
- list_add_tail(&ir->list, &ir_devices_list);
-
- ir->adapter = adap;
- mutex_init(&ir->ir_lock);
- atomic_set(&ir->open_count, 0);
- spin_lock_init(&ir->tx_ref_lock);
- spin_lock_init(&ir->rx_ref_lock);
-
- /* set lirc_dev stuff */
- memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver));
- /*
- * FIXME this is a pointer reference to us, but no refcount.
- *
- * This OK for now, since lirc_dev currently won't touch this
- * buffer as we provide our own lirc_fops.
- *
- * Currently our own lirc_fops rely on this ir->l.rbuf pointer
- */
- ir->l.rbuf = &ir->rbuf;
- ir->l.dev = &adap->dev;
- ret = lirc_buffer_init(ir->l.rbuf,
- ir->l.chunk_size, ir->l.buffer_size);
- if (ret)
- goto out_put_ir;
- }
-
- if (tx_probe) {
- /* Get the IR_rx instance for later, if already allocated */
- rx = get_ir_rx(ir);
-
- /* Set up a struct IR_tx instance */
- tx = kzalloc(sizeof(struct IR_tx), GFP_KERNEL);
- if (tx == NULL) {
- ret = -ENOMEM;
- goto out_put_xx;
- }
- kref_init(&tx->ref);
- ir->tx = tx;
-
- ir->l.features |= LIRC_CAN_SEND_PULSE;
- mutex_init(&tx->client_lock);
- tx->c = client;
- tx->need_boot = 1;
- tx->post_tx_ready_poll =
- (id->driver_data & ID_FLAG_HDPVR) ? false : true;
-
- /* An ir ref goes to the struct IR_tx instance */
- tx->ir = get_ir_device(ir, true);
-
- /* A tx ref goes to the i2c_client */
- i2c_set_clientdata(client, get_ir_tx(ir));
-
- /*
- * Load the 'firmware'. We do this before registering with
- * lirc_dev, so the first firmware load attempt does not happen
- * after a open() or write() call on the device.
- *
- * Failure here is not deemed catastrophic, so the receiver will
- * still be usable. Firmware load will be retried in write(),
- * if it is needed.
- */
- fw_load(tx);
-
- /* Proceed only if the Rx client is also ready or not needed */
- if (rx == NULL && !tx_only) {
- zilog_info("probe of IR Tx on %s (i2c-%d) done. Waiting"
- " on IR Rx.\n", adap->name, adap->nr);
- goto out_ok;
- }
- } else {
- /* Get the IR_tx instance for later, if already allocated */
- tx = get_ir_tx(ir);
-
- /* Set up a struct IR_rx instance */
- rx = kzalloc(sizeof(struct IR_rx), GFP_KERNEL);
- if (rx == NULL) {
- ret = -ENOMEM;
- goto out_put_xx;
- }
- kref_init(&rx->ref);
- ir->rx = rx;
-
- ir->l.features |= LIRC_CAN_REC_LIRCCODE;
- mutex_init(&rx->client_lock);
- rx->c = client;
- rx->hdpvr_data_fmt =
- (id->driver_data & ID_FLAG_HDPVR) ? true : false;
-
- /* An ir ref goes to the struct IR_rx instance */
- rx->ir = get_ir_device(ir, true);
-
- /* An rx ref goes to the i2c_client */
- i2c_set_clientdata(client, get_ir_rx(ir));
-
- /*
- * Start the polling thread.
- * It will only perform an empty loop around schedule_timeout()
- * until we register with lirc_dev and the first user open()
- */
- /* An ir ref goes to the new rx polling kthread */
- rx->task = kthread_run(lirc_thread, get_ir_device(ir, true),
- "zilog-rx-i2c-%d", adap->nr);
- if (IS_ERR(rx->task)) {
- ret = PTR_ERR(rx->task);
- zilog_error("%s: could not start IR Rx polling thread"
- "\n", __func__);
- /* Failed kthread, so put back the ir ref */
- put_ir_device(ir, true);
- /* Failure exit, so put back rx ref from i2c_client */
- i2c_set_clientdata(client, NULL);
- put_ir_rx(rx, true);
- ir->l.features &= ~LIRC_CAN_REC_LIRCCODE;
- goto out_put_xx;
- }
-
- /* Proceed only if the Tx client is also ready */
- if (tx == NULL) {
- zilog_info("probe of IR Rx on %s (i2c-%d) done. Waiting"
- " on IR Tx.\n", adap->name, adap->nr);
- goto out_ok;
- }
- }
-
- /* register with lirc */
- ir->l.minor = minor; /* module option: user requested minor number */
- ir->l.minor = lirc_register_driver(&ir->l);
- if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) {
- zilog_error("%s: \"minor\" must be between 0 and %d (%d)!\n",
- __func__, MAX_IRCTL_DEVICES-1, ir->l.minor);
- ret = -EBADRQC;
- goto out_put_xx;
- }
- zilog_info("IR unit on %s (i2c-%d) registered as lirc%d and ready\n",
- adap->name, adap->nr, ir->l.minor);
-
-out_ok:
- if (rx != NULL)
- put_ir_rx(rx, true);
- if (tx != NULL)
- put_ir_tx(tx, true);
- put_ir_device(ir, true);
- zilog_info("probe of IR %s on %s (i2c-%d) done\n",
- tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
- mutex_unlock(&ir_devices_lock);
- return 0;
-
-out_put_xx:
- if (rx != NULL)
- put_ir_rx(rx, true);
- if (tx != NULL)
- put_ir_tx(tx, true);
-out_put_ir:
- put_ir_device(ir, true);
-out_no_ir:
- zilog_error("%s: probing IR %s on %s (i2c-%d) failed with %d\n",
- __func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr,
- ret);
- mutex_unlock(&ir_devices_lock);
- return ret;
-}
-
-static int __init zilog_init(void)
-{
- int ret;
-
- zilog_notify("Zilog/Hauppauge IR driver initializing\n");
-
- mutex_init(&tx_data_lock);
-
- request_module("firmware_class");
-
- ret = i2c_add_driver(&driver);
- if (ret)
- zilog_error("initialization failed\n");
- else
- zilog_notify("initialization complete\n");
-
- return ret;
-}
-
-static void __exit zilog_exit(void)
-{
- i2c_del_driver(&driver);
- /* if loaded */
- fw_unload();
- zilog_notify("Zilog/Hauppauge IR driver unloaded\n");
-}
-
-module_init(zilog_init);
-module_exit(zilog_exit);
-
-MODULE_DESCRIPTION("Zilog/Hauppauge infrared transmitter driver (i2c stack)");
-MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, "
- "Ulrich Mueller, Stefan Jahn, Jerome Brock, Mark Weaver, "
- "Andy Walls");
-MODULE_LICENSE("GPL");
-/* for compat with old name, which isn't all that accurate anymore */
-MODULE_ALIAS("lirc_pvr150");
-
-module_param(minor, int, 0444);
-MODULE_PARM_DESC(minor, "Preferred minor device number");
-
-module_param(debug, bool, 0644);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
-
-module_param(tx_only, bool, 0644);
-MODULE_PARM_DESC(tx_only, "Only handle the IR transmit function");