This patch series tries to make some headway with dealing with the
lirc staging drivers. Over the last couple of years, I have ported
lirc_serial, lirc_ttusbir and lirc_igorplugusb. I have not been able
to track down the hardware for the remaining drivers.
Note that the remaining lirc staging drivers were merged in 2010, and
other than trival patches, they have not made any progress towards
mainline.
ir-rx51 is not a staging driver, but it should not rely on the lirc
in-kernel API like the staging drivers do.
Sean Young (5):
[media] ir-rx51: port to rc-core
[media] staging: lirc_sir: port to rc-core
[media] staging: lirc_parallel: remove
[media] staging: lirc_bt829: remove
[media] staging: lirc_imon: port remaining usb ids to imon and remove
arch/arm/mach-omap2/pdata-quirks.c | 8 +-
drivers/media/rc/Kconfig | 2 +-
drivers/media/rc/imon.c | 133 +++-
drivers/media/rc/ir-rx51.c | 332 ++++------
drivers/staging/media/lirc/Kconfig | 22 +-
drivers/staging/media/lirc/Makefile | 3 -
drivers/staging/media/lirc/lirc_bt829.c | 401 ------------
drivers/staging/media/lirc/lirc_imon.c | 979 ----------------------------
drivers/staging/media/lirc/lirc_parallel.c | 741 ---------------------
drivers/staging/media/lirc/lirc_parallel.h | 26 -
drivers/staging/media/lirc/lirc_sir.c | 296 ++-------
include/linux/platform_data/media/ir-rx51.h | 6 +-
12 files changed, 322 insertions(+), 2627 deletions(-)
delete mode 100644 drivers/staging/media/lirc/lirc_bt829.c
delete mode 100644 drivers/staging/media/lirc/lirc_imon.c
delete mode 100644 drivers/staging/media/lirc/lirc_parallel.c
delete mode 100644 drivers/staging/media/lirc/lirc_parallel.h
--
2.9.3
The lirc_parallel driver was merged in 2010 and noone has attempted
to do the work necessary to get it out of staging (i.e. port it to
rc-core). I have not been able to find one of these devices, and
a machine with a parallel port is pretty rare too.
Signed-off-by: Sean Young <[email protected]>
Cc: Jarod Wilson <[email protected]>
Cc: Christoph Bartelmus <[email protected]>
---
drivers/staging/media/lirc/Kconfig | 6 -
drivers/staging/media/lirc/Makefile | 1 -
drivers/staging/media/lirc/lirc_parallel.c | 741 -----------------------------
drivers/staging/media/lirc/lirc_parallel.h | 26 -
4 files changed, 774 deletions(-)
delete mode 100644 drivers/staging/media/lirc/lirc_parallel.c
delete mode 100644 drivers/staging/media/lirc/lirc_parallel.h
diff --git a/drivers/staging/media/lirc/Kconfig b/drivers/staging/media/lirc/Kconfig
index 56e5fd7..7923d3f 100644
--- a/drivers/staging/media/lirc/Kconfig
+++ b/drivers/staging/media/lirc/Kconfig
@@ -26,12 +26,6 @@ config LIRC_IMON
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
diff --git a/drivers/staging/media/lirc/Makefile b/drivers/staging/media/lirc/Makefile
index 7f919ea..ed3091e 100644
--- a/drivers/staging/media/lirc/Makefile
+++ b/drivers/staging/media/lirc/Makefile
@@ -5,7 +5,6 @@
obj-$(CONFIG_LIRC_BT829) += lirc_bt829.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_SIR) += lirc_sir.o
obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o
diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c
deleted file mode 100644
index bfb76a4..0000000
--- a/drivers/staging/media/lirc/lirc_parallel.c
+++ /dev/null
@@ -1,741 +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 <[email protected]>
- *
- * 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
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-/*** 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/ktime.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 bool debug;
-static bool check_pselecd;
-
-static unsigned int irq = LIRC_IRQ;
-static unsigned int io = LIRC_PORT;
-#ifdef LIRC_TIMER
-static unsigned int timer;
-static 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];
-
-static DECLARE_WAIT_QUEUE_HEAD(lirc_wait);
-
-static unsigned int rptr;
-static unsigned int wptr;
-static unsigned int lost_irqs;
-static int is_open;
-
-static struct parport *pport;
-static struct pardevice *ppdevice;
-static int is_claimed;
-
-static 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:
- pr_info("attempt to write to status register\n");
- 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)
-{
- ktime_t kt, now, timeout;
- unsigned int level, newlevel, timeelapsed, newtimer;
- int count = 0;
-
- kt = ktime_get();
- /* wait max. 1 sec. */
- timeout = ktime_add_ns(kt, NSEC_PER_SEC);
- level = lirc_get_timer();
- do {
- newlevel = lirc_get_timer();
- if (level == 0 && newlevel != 0)
- count++;
- level = newlevel;
- now = ktime_get();
- } while (count < 1000 && (ktime_before(now, timeout)));
- timeelapsed = ktime_us_delta(now, kt);
- if (count >= 1000 && timeelapsed > 0) {
- if (default_timer == 0) {
- /* autodetect timer */
- newtimer = (1000000 * count) / timeelapsed;
- pr_info("%u Hz timer detected\n", newtimer);
- return newtimer;
- }
- newtimer = (1000000 * count) / timeelapsed;
- if (abs(newtimer - default_timer) > default_timer / 10) {
- /* bad timer */
- pr_notice("bad timer: %u Hz\n", newtimer);
- pr_notice("using default timer: %u Hz\n",
- default_timer);
- return default_timer;
- }
- pr_info("%u Hz timer detected\n", newtimer);
- return newtimer; /* use detected value */
- }
-
- pr_notice("no timer detected\n");
- return 0;
-}
-
-static int lirc_claim(void)
-{
- if (parport_claim(ppdevice) != 0) {
- pr_warn("could not claim port\n");
- pr_warn("waiting for port becoming available\n");
- if (parport_claim_or_block(ppdevice) < 0) {
- pr_notice("could not claim port, giving up\n");
- 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++;
- pr_notice("buffer overrun\n");
- return;
- }
- rbuf[wptr] = signal;
- wptr = nwptr;
-}
-
-static void lirc_lirc_irq_handler(void *blah)
-{
- ktime_t kt, delkt;
- static ktime_t lastkt;
- 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) {
- kt = ktime_get();
-
- delkt = ktime_sub(kt, lastkt);
- if (ktime_compare(delkt, ktime_set(15, 0)) > 0)
- /* really long time */
- data = PULSE_MASK;
- else
- data = (int)(ktime_to_us(delkt) + 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;
- pr_notice("timeout\n");
- 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 */
- }
- lastkt = ktime_get();
-#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 __user *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, &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 __user *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 __user *uptr = (u32 __user *)arg;
- 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, uptr);
- if (result)
- return result;
- break;
- case LIRC_GET_SEND_MODE:
- result = put_user(LIRC_MODE_PULSE, uptr);
- if (result)
- return result;
- break;
- case LIRC_GET_REC_MODE:
- result = put_user(LIRC_MODE_MODE2, uptr);
- if (result)
- return result;
- break;
- case LIRC_SET_SEND_MODE:
- result = get_user(mode, uptr);
- if (result)
- return result;
- if (mode != LIRC_MODE_PULSE)
- return -EINVAL;
- break;
- case LIRC_SET_REC_MODE:
- result = get_user(mode, uptr);
- if (result)
- return result;
- if (mode != LIRC_MODE_MODE2)
- return -ENOSYS;
- break;
- case LIRC_SET_TRANSMITTER_MASK:
- result = get_user(value, uptr);
- 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 lirc_parallel_probe(struct platform_device *dev)
-{
- return 0;
-}
-
-static int 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 = lirc_parallel_remove,
- .suspend = lirc_parallel_suspend,
- .resume = lirc_parallel_resume,
- .driver = {
- .name = LIRC_DRIVER_NAME,
- },
-};
-
-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) {
- pr_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) {
- pr_notice("no port at %x found\n", io);
- result = -ENXIO;
- goto exit_device_del;
- }
- ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME,
- pf, kf, lirc_lirc_irq_handler, 0,
- NULL);
- parport_put_port(pport);
- if (!ppdevice) {
- pr_notice("parport_register_device() failed\n");
- result = -ENXIO;
- goto exit_device_del;
- }
- 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_del;
- }
-
-#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) {
- pr_notice("register_chrdev() failed\n");
- parport_unregister_device(ppdevice);
- result = -EIO;
- goto exit_device_del;
- }
- pr_info("installed using port 0x%04x irq %d\n", io, irq);
- return 0;
-
-exit_device_del:
- platform_device_del(lirc_parallel_dev);
-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);
-
- platform_device_unregister(lirc_parallel_dev);
- platform_driver_unregister(&lirc_parallel_driver);
-}
-
-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_mask, "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(check_pselecd, "Check for printer (default: 0)");
diff --git a/drivers/staging/media/lirc/lirc_parallel.h b/drivers/staging/media/lirc/lirc_parallel.h
deleted file mode 100644
index 4bed6af..0000000
--- a/drivers/staging/media/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
--
2.9.3
The staging lirc_imon driver contains 4 usb ids. Two of those have a VFD
and two don't. The VFD code is exactly the same in the mainline imon
driver, so that part is easily ported.
The staging driver produces raw IR rather than scancodes for the four
devices, so I've ported the raw IR code from staging to mainline imon.
Now that mainline imon can handle these four devices, lirc_imon is no
longer needed.
Compile tested only.
Signed-off-by: Sean Young <[email protected]>
Cc: Venky Raju <[email protected]>
Cc: Jarod Wilson <[email protected]>
Cc: Alexey Khoroshilov <[email protected]>
---
drivers/media/rc/imon.c | 133 ++++-
drivers/staging/media/lirc/Kconfig | 8 -
drivers/staging/media/lirc/Makefile | 1 -
drivers/staging/media/lirc/lirc_imon.c | 979 ---------------------------------
4 files changed, 127 insertions(+), 994 deletions(-)
delete mode 100644 drivers/staging/media/lirc/lirc_imon.c
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 4234ae6..af5926f 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -96,6 +96,7 @@ struct imon_usb_dev_descr {
__u16 flags;
#define IMON_NO_FLAGS 0
#define IMON_NEED_20MS_PKT_DELAY 1
+#define IMON_IR_RAW 2
struct imon_panel_key_table key_table[];
};
@@ -126,6 +127,12 @@ struct imon_context {
unsigned char usb_tx_buf[8];
unsigned int send_packet_delay;
+ 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[35]; /* user data buffer */
struct completion finished; /* wait for write to finish */
@@ -328,6 +335,10 @@ static const struct imon_usb_dev_descr imon_DH102 = {
}
};
+static const struct imon_usb_dev_descr imon_ir_raw = {
+ .flags = IMON_IR_RAW,
+};
+
/*
* USB Device ID for iMON USB Control Boards
*
@@ -411,6 +422,18 @@ static struct usb_device_id imon_usb_id_table[] = {
/* device specifics unknown */
{ USB_DEVICE(0x15c2, 0x0046),
.driver_info = (unsigned long)&imon_default_table},
+ /* TriGem iMON (IR only) -- TG_iMON.inf */
+ { USB_DEVICE(0x0aa8, 0x8001),
+ .driver_info = (unsigned long)&imon_ir_raw},
+ /* SoundGraph iMON (IR only) -- sg_imon.inf */
+ { USB_DEVICE(0x04e8, 0xff30),
+ .driver_info = (unsigned long)&imon_ir_raw},
+ /* SoundGraph iMON VFD (IR & VFD) -- iMON_VFD.inf */
+ { USB_DEVICE(0x0aa8, 0xffda),
+ .driver_info = (unsigned long)&imon_ir_raw},
+ /* SoundGraph iMON SS (IR & VFD) -- iMON_SS.inf */
+ { USB_DEVICE(0x15c2, 0xffda),
+ .driver_info = (unsigned long)&imon_ir_raw},
{}
};
@@ -1577,11 +1600,94 @@ static int imon_parse_press_type(struct imon_context *ictx,
/**
* Process the incoming packet
*/
-static void imon_incoming_packet(struct imon_context *ictx,
+/**
+ * Convert bit count to time duration (in us) and submit
+ * the value to lirc_dev.
+ */
+static void submit_data(struct imon_context *context)
+{
+ DEFINE_IR_RAW_EVENT(ev);
+
+ ev.pulse = context->rx.prev_bit;
+ ev.duration = US_TO_NS(context->rx.count * BIT_DURATION);
+ ir_raw_event_store_with_filter(context->rdev, &ev);
+}
+
+/**
+ * Process the incoming packet
+ */
+static void imon_incoming_ir_raw(struct imon_context *context,
struct urb *urb, int intf)
{
int len = urb->actual_length;
unsigned char *buf = urb->transfer_buffer;
+ struct device *dev = context->dev;
+ int octet, bit;
+ unsigned char mask;
+
+ if (len != 8) {
+ dev_warn(dev, "imon %s: invalid incoming packet size (len = %d, intf%d)\n",
+ __func__, len, intf);
+ return;
+ }
+
+ if (debug)
+ dev_info(dev, "raw packet: %*ph\n", len, buf);
+ /*
+ * 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;
+ }
+
+ ir_raw_event_handle(context->rdev);
+}
+
+static void imon_incoming_scancode(struct imon_context *ictx,
+ struct urb *urb, int intf)
+{
+ int len = urb->actual_length;
+ unsigned char *buf = urb->transfer_buffer;
struct device *dev = ictx->dev;
unsigned long flags;
u32 kc;
@@ -1761,7 +1867,10 @@ static void usb_rx_callback_intf0(struct urb *urb)
break;
case 0:
- imon_incoming_packet(ictx, urb, intfnum);
+ if (ictx->rdev->driver_type == RC_DRIVER_IR_RAW)
+ imon_incoming_ir_raw(ictx, urb, intfnum);
+ else
+ imon_incoming_scancode(ictx, urb, intfnum);
break;
default:
@@ -1802,7 +1911,10 @@ static void usb_rx_callback_intf1(struct urb *urb)
break;
case 0:
- imon_incoming_packet(ictx, urb, intfnum);
+ if (ictx->rdev->driver_type == RC_DRIVER_IR_RAW)
+ imon_incoming_ir_raw(ictx, urb, intfnum);
+ else
+ imon_incoming_scancode(ictx, urb, intfnum);
break;
default:
@@ -1910,11 +2022,14 @@ static void imon_set_display_type(struct imon_context *ictx)
case 0x0041:
case 0x0042:
case 0x0043:
+ case 0x8001:
+ case 0xff30:
configured_display_type = IMON_DISPLAY_TYPE_NONE;
ictx->display_supported = false;
break;
case 0x0036:
case 0x0044:
+ case 0xffda:
default:
configured_display_type = IMON_DISPLAY_TYPE_VFD;
break;
@@ -1939,7 +2054,8 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x88 };
- rdev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ rdev = rc_allocate_device(ictx->dev_descr->flags & IMON_IR_RAW ?
+ RC_DRIVER_IR_RAW : RC_DRIVER_SCANCODE);
if (!rdev) {
dev_err(ictx->dev, "remote control dev allocation failed\n");
goto out;
@@ -1957,7 +2073,11 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
rdev->dev.parent = ictx->dev;
rdev->priv = ictx;
- rdev->allowed_protocols = RC_BIT_OTHER | RC_BIT_RC6_MCE; /* iMON PAD or MCE */
+ if (ictx->dev_descr->flags & IMON_IR_RAW)
+ rdev->allowed_protocols = RC_BIT_ALL_IR_DECODER;
+ else
+ /* iMON PAD or MCE */
+ rdev->allowed_protocols = RC_BIT_OTHER | RC_BIT_RC6_MCE;
rdev->change_protocol = imon_ir_change_protocol;
rdev->driver_name = MOD_NAME;
@@ -1975,7 +2095,8 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
imon_set_display_type(ictx);
- if (ictx->rc_type == RC_BIT_RC6_MCE)
+ if (ictx->rc_type == RC_BIT_RC6_MCE ||
+ ictx->dev_descr->flags & IMON_IR_RAW)
rdev->map_name = RC_MAP_IMON_MCE;
else
rdev->map_name = RC_MAP_IMON_PAD;
diff --git a/drivers/staging/media/lirc/Kconfig b/drivers/staging/media/lirc/Kconfig
index 574ab50..bc67da2 100644
--- a/drivers/staging/media/lirc/Kconfig
+++ b/drivers/staging/media/lirc/Kconfig
@@ -12,14 +12,6 @@ menuconfig LIRC_STAGING
if LIRC_STAGING
-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_SASEM
tristate "Sasem USB IR Remote"
depends on LIRC && USB
diff --git a/drivers/staging/media/lirc/Makefile b/drivers/staging/media/lirc/Makefile
index 3f31116..28740c9 100644
--- a/drivers/staging/media/lirc/Makefile
+++ b/drivers/staging/media/lirc/Makefile
@@ -3,7 +3,6 @@
# Each configuration option enables a list of files.
-obj-$(CONFIG_LIRC_IMON) += lirc_imon.o
obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o
obj-$(CONFIG_LIRC_SIR) += lirc_sir.o
obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o
diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c
deleted file mode 100644
index 1e650fb..0000000
--- a/drivers/staging/media/lirc/lirc_imon.c
+++ /dev/null
@@ -1,979 +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([email protected])
- * Copyright(C) 2009 Jarod Wilson <[email protected]>
- *
- * 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/errno.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 <[email protected]>"
-#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 __user *buf,
- size_t n_bytes, loff_t *pos);
-
-/* LIRC driver function prototypes */
-static int ir_open(void *data);
-static void ir_close(void *data);
-
-/*** 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)
- dev_err(&context->usbdev->dev,
- "unable to deregister from lirc(%d)", retval);
- else
- dev_info(&context->usbdev->dev,
- "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) {
- pr_err("%s: could not find interface for minor %d\n",
- __func__, subminor);
- retval = -ENODEV;
- goto exit;
- }
- context = usb_get_intfdata(interface);
-
- if (!context) {
- dev_err(&interface->dev, "no context found for minor %d\n",
- subminor);
- retval = -ENODEV;
- goto exit;
- }
-
- mutex_lock(&context->ctx_lock);
-
- if (!context->display) {
- dev_err(&interface->dev,
- "%s: display not supported by device\n", __func__);
- retval = -ENODEV;
- } else if (context->display_isopen) {
- dev_err(&interface->dev,
- "%s: display port is already open\n", __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) {
- pr_err("%s: no context for device\n", __func__);
- return -ENODEV;
- }
-
- mutex_lock(&context->ctx_lock);
-
- if (!context->display) {
- dev_err(&context->usbdev->dev,
- "%s: display not supported by device\n", __func__);
- retval = -ENODEV;
- } else if (!context->display_isopen) {
- dev_err(&context->usbdev->dev,
- "%s: display is not open\n", __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;
-
- reinit_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);
- dev_err(&context->usbdev->dev, "error submitting urb(%d)\n",
- retval);
- } else {
- /* Wait for transmission to complete (or abort) */
- mutex_unlock(&context->ctx_lock);
- retval = wait_for_completion_interruptible(
- &context->tx.finished);
- if (retval)
- dev_err(&context->usbdev->dev,
- "%s: task interrupted\n", __func__);
- mutex_lock(&context->ctx_lock);
-
- retval = context->tx.status;
- if (retval)
- dev_err(&context->usbdev->dev,
- "packet tx failed (%d)\n", 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 __user *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) {
- pr_err("%s: no context for device\n", __func__);
- return -ENODEV;
- }
-
- mutex_lock(&context->ctx_lock);
-
- if (!context->dev_present) {
- dev_err(&context->usbdev->dev,
- "%s: no iMON device present\n", __func__);
- retval = -ENODEV;
- goto exit;
- }
-
- if (n_bytes <= 0 || n_bytes > IMON_DATA_BUF_SZ - 3) {
- dev_err(&context->usbdev->dev,
- "%s: invalid payload size\n", __func__);
- retval = -EINVAL;
- goto exit;
- }
-
- data_buf = memdup_user(buf, n_bytes);
- if (IS_ERR(data_buf)) {
- mutex_unlock(&context->ctx_lock);
- return PTR_ERR(data_buf);
- }
-
- 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) {
- dev_err(&context->usbdev->dev,
- "send packet failed for packet #%d\n",
- 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)
- dev_err(&context->usbdev->dev,
- "send packet failed for packet #%d\n",
- 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);
-}
-
-/**
- * Called by lirc_dev when the application opens /dev/lirc
- */
-static int ir_open(void *data)
-{
- struct imon_context *context;
-
- /* prevent races with disconnect */
- mutex_lock(&driver_lock);
-
- context = data;
-
- /* initial IR protocol decode variables */
- context->rx.count = 0;
- context->rx.initial_space = 1;
- context->rx.prev_bit = 0;
-
- init_completion(&context->tx.finished);
-
- context->ir_isopen = 1;
- dev_info(context->driver->dev, "IR port opened\n");
-
- mutex_unlock(&driver_lock);
- return 0;
-}
-
-/**
- * Called by lirc_dev when the application closes /dev/lirc
- */
-static void ir_close(void *data)
-{
- struct imon_context *context;
-
- context = data;
- if (!context) {
- pr_err("%s: no context for device\n", __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);
-}
-
-/**
- * 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);
-}
-
-/**
- * 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;
-
- /*
- * 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)
- dev_info(dev, "raw packet: %*ph\n", len, buf);
- /*
- * 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;
- int intfnum = 0;
-
- if (!urb)
- return;
-
- context = (struct imon_context *)urb->context;
- if (!context)
- return;
-
- 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);
-}
-
-/**
- * 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 = -ENOMEM;
- int display_ep_found = 0;
- int ir_ep_found = 0;
- int vfd_proto_6p = 0;
- struct imon_context *context = NULL;
- int i;
- u16 vendor, product;
-
- /* prevent races probing devices w/multiple interfaces */
- mutex_lock(&driver_lock);
-
- context = kzalloc(sizeof(*context), GFP_KERNEL);
- if (!context)
- goto driver_unlock;
-
- /*
- * 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;
-
- 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);
-
- /*
- * 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 = usb_endpoint_type(ep);
-
- 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) {
- dev_err(dev, "%s: no valid input (IR) endpoint found.\n",
- __func__);
- retval = -ENODEV;
- goto free_context;
- }
-
- /* 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(*driver), GFP_KERNEL);
- if (!driver)
- goto free_context;
-
- rbuf = kmalloc(sizeof(*rbuf), GFP_KERNEL);
- if (!rbuf)
- goto free_driver;
-
- if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) {
- dev_err(dev, "%s: lirc_buffer_init failed\n", __func__);
- goto free_rbuf;
- }
- rx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!rx_urb)
- goto free_lirc_buf;
- tx_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!tx_urb)
- goto free_rx_urb;
-
- mutex_init(&context->ctx_lock);
- context->vfd_proto_6p = vfd_proto_6p;
-
- strcpy(driver->name, MOD_NAME);
- driver->minor = -1;
- driver->code_length = BUF_CHUNK_SIZE * 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) {
- dev_err(dev, "%s: lirc_register_driver failed\n", __func__);
- goto free_tx_urb;
- }
-
- 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) {
- dev_err(dev, "usb_submit_urb failed for intf0 (%d)\n", retval);
- goto unregister_lirc;
- }
-
- 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);
-
- /* Everything went fine. Just unlock and return retval (with is 0) */
- mutex_unlock(&context->ctx_lock);
- goto driver_unlock;
-
-unregister_lirc:
- lirc_unregister_driver(driver->minor);
-
-free_tx_urb:
- mutex_unlock(&context->ctx_lock);
- usb_free_urb(tx_urb);
-
-free_rx_urb:
- usb_free_urb(rx_urb);
-
-free_lirc_buf:
- lirc_buffer_free(rbuf);
-
-free_rbuf:
- kfree(rbuf);
-
-free_driver:
- kfree(driver);
-free_context:
- kfree(context);
- context = NULL;
-
-driver_unlock:
- 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(&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);
-
- dev_info(&interface->dev, "%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)
-{
- 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);
-
- return usb_submit_urb(context->rx_urb, GFP_ATOMIC);
-}
-
-module_usb_driver(imon_driver);
--
2.9.3
This driver is for an old mach64 VT board, which also has a framebuffer
driver (atyfb) and userspace mach64 X driver.
It was merged in 2010 and noone has attempted to port it to rc-core,
which would be necessary to get it out of staging.
I have not been able to track down the hardware either.
Signed-off-by: Sean Young <[email protected]>
Cc: Jarod Wilson <[email protected]>
Cc: Leonid Froenchenko <[email protected]>
---
drivers/staging/media/lirc/Kconfig | 6 -
drivers/staging/media/lirc/Makefile | 1 -
drivers/staging/media/lirc/lirc_bt829.c | 401 --------------------------------
3 files changed, 408 deletions(-)
delete mode 100644 drivers/staging/media/lirc/lirc_bt829.c
diff --git a/drivers/staging/media/lirc/Kconfig b/drivers/staging/media/lirc/Kconfig
index 7923d3f..574ab50 100644
--- a/drivers/staging/media/lirc/Kconfig
+++ b/drivers/staging/media/lirc/Kconfig
@@ -12,12 +12,6 @@ menuconfig LIRC_STAGING
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_IMON
tristate "Legacy SoundGraph iMON Receiver and Display"
depends on LIRC && USB
diff --git a/drivers/staging/media/lirc/Makefile b/drivers/staging/media/lirc/Makefile
index ed3091e..3f31116 100644
--- a/drivers/staging/media/lirc/Makefile
+++ b/drivers/staging/media/lirc/Makefile
@@ -3,7 +3,6 @@
# Each configuration option enables a list of files.
-obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o
obj-$(CONFIG_LIRC_IMON) += lirc_imon.o
obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o
obj-$(CONFIG_LIRC_SIR) += lirc_sir.o
diff --git a/drivers/staging/media/lirc/lirc_bt829.c b/drivers/staging/media/lirc/lirc_bt829.c
deleted file mode 100644
index 04d881b..0000000
--- a/drivers/staging/media/lirc/lirc_bt829.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Remote control driver for the TV-card based on bt829
- *
- * by Leonid Froenchenko <[email protected]>
- *
- * 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
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#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 bool debug;
-
-static int atir_minor;
-static phys_addr_t pci_addr_phys;
-static unsigned char __iomem *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) {
- pr_err("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;
- pr_info("memory at %pa\n", &pci_addr_phys);
- }
- if (pci_addr_phys == 0) {
- pr_err("no memory resource ?\n");
- pci_dev_put(my_dev);
- return NULL;
- }
- } else {
- pr_err("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) {
- dev_dbg(atir_driver.dev, "reading key %02X\n", key);
- lirc_buffer_write(buf, &key);
- return 0;
- }
- return -ENODATA;
-}
-
-static int atir_set_use_inc(void *data)
-{
- dev_dbg(atir_driver.dev, "driver is opened\n");
- return 0;
-}
-
-static void atir_set_use_dec(void *data)
-{
- dev_dbg(atir_driver.dev, "driver is closed\n");
-}
-
-int init_module(void)
-{
- struct pci_dev *pdev;
- int rc;
-
- pdev = do_pci_probe();
- if (!pdev)
- return -ENODEV;
-
- rc = pci_enable_device(pdev);
- if (rc)
- goto err_put_dev;
-
- if (!atir_init_start()) {
- rc = -ENODEV;
- goto err_disable;
- }
-
- strcpy(atir_driver.name, "ATIR");
- atir_driver.minor = -1;
- atir_driver.code_length = 8;
- atir_driver.sample_rate = 10;
- atir_driver.data = NULL;
- 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) {
- pr_err("failed to register driver!\n");
- rc = atir_minor;
- goto err_unmap;
- }
- dev_dbg(atir_driver.dev, "driver is registered on minor %d\n",
- atir_minor);
-
- return 0;
-
-err_unmap:
- iounmap(pci_addr_lin);
-err_disable:
- pci_disable_device(pdev);
-err_put_dev:
- pci_dev_put(pdev);
- return rc;
-}
-
-void cleanup_module(void)
-{
- struct pci_dev *pdev = to_pci_dev(atir_driver.dev);
-
- lirc_unregister_driver(atir_minor);
- iounmap(pci_addr_lin);
- pci_disable_device(pdev);
- pci_dev_put(pdev);
-}
-
-static int atir_init_start(void)
-{
- pci_addr_lin = ioremap(pci_addr_phys + DATA_PCI_OFF, 0x400);
- if (!pci_addr_lin) {
- pr_info("pci mem must be mapped\n");
- return 0;
- }
- return 1;
-}
-
-static void cycle_delay(int cycle)
-{
- udelay(WAIT_CYCLE * cycle);
-}
-
-static int poll_main(void)
-{
- 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 __iomem *addr;
- /* addr = pci_addr_lin + DATA_PCI_OFF + ((index & 0xFF) << 2); */
- addr = pci_addr_lin + ((index & 0xFF) << 2);
- return readl(addr);
-}
-
-static void write_index(unsigned char index, unsigned int reg_val)
-{
- unsigned char __iomem *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");
--
2.9.3
This driver was written using lirc since rc-core did not support
transmitter-only hardware at that time. Now that it does, port
this driver.
Compile tested only.
Signed-off-by: Sean Young <[email protected]>
Cc: Timo Kokkonen <[email protected]>
Cc: Ivaylo Dimitrov <[email protected]>
---
arch/arm/mach-omap2/pdata-quirks.c | 8 +-
drivers/media/rc/Kconfig | 2 +-
drivers/media/rc/ir-rx51.c | 332 ++++++++++------------------
include/linux/platform_data/media/ir-rx51.h | 6 +-
4 files changed, 126 insertions(+), 222 deletions(-)
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index 05e20aa..fdd6e7f 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -485,15 +485,15 @@ static struct pwm_omap_dmtimer_pdata pwm_dmtimer_pdata = {
};
#endif
-static struct lirc_rx51_platform_data __maybe_unused rx51_lirc_data = {
+static struct ir_rx51_platform_data __maybe_unused rx51_ir_data = {
.set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
};
-static struct platform_device __maybe_unused rx51_lirc_device = {
- .name = "lirc_rx51",
+static struct platform_device __maybe_unused rx51_ir_device = {
+ .name = "ir_rx51",
.id = -1,
.dev = {
- .platform_data = &rx51_lirc_data,
+ .platform_data = &rx51_ir_data,
},
};
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 3351e25..d0ddbd3 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -345,7 +345,7 @@ config IR_TTUSBIR
config IR_RX51
tristate "Nokia N900 IR transmitter diode"
- depends on OMAP_DM_TIMER && PWM_OMAP_DMTIMER && ARCH_OMAP2PLUS && LIRC
+ depends on (OMAP_DM_TIMER && PWM_OMAP_DMTIMER && ARCH_OMAP2PLUS || COMPILE_TEST) && RC_CORE
---help---
Say Y or M here if you want to enable support for the IR
transmitter diode built in the Nokia N900 (RX51) device.
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 82fb6f2..e897c15 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -15,32 +15,23 @@
*/
#include <linux/clk.h>
#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/uaccess.h>
#include <linux/platform_device.h>
-#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/pwm.h>
#include <linux/of.h>
#include <linux/hrtimer.h>
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
+#include <media/rc-core.h>
#include <linux/platform_data/media/ir-rx51.h>
-#define LIRC_RX51_DRIVER_FEATURES (LIRC_CAN_SET_SEND_DUTY_CYCLE | \
- LIRC_CAN_SET_SEND_CARRIER | \
- LIRC_CAN_SEND_PULSE)
-
-#define DRIVER_NAME "lirc_rx51"
-
#define WBUF_LEN 256
-struct lirc_rx51 {
+struct ir_rx51 {
+ struct rc_dev *rcdev;
struct pwm_device *pwm;
struct hrtimer timer;
struct device *dev;
- struct lirc_rx51_platform_data *pdata;
+ struct ir_rx51_platform_data *pdata;
wait_queue_head_t wqueue;
unsigned int freq; /* carrier frequency */
@@ -50,38 +41,37 @@ struct lirc_rx51 {
unsigned long device_is_open;
};
-static inline void lirc_rx51_on(struct lirc_rx51 *lirc_rx51)
+static inline void ir_rx51_on(struct ir_rx51 *ir_rx51)
{
- pwm_enable(lirc_rx51->pwm);
+ pwm_enable(ir_rx51->pwm);
}
-static inline void lirc_rx51_off(struct lirc_rx51 *lirc_rx51)
+static inline void ir_rx51_off(struct ir_rx51 *ir_rx51)
{
- pwm_disable(lirc_rx51->pwm);
+ pwm_disable(ir_rx51->pwm);
}
-static int init_timing_params(struct lirc_rx51 *lirc_rx51)
+static int init_timing_params(struct ir_rx51 *ir_rx51)
{
- struct pwm_device *pwm = lirc_rx51->pwm;
- int duty, period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, lirc_rx51->freq);
+ struct pwm_device *pwm = ir_rx51->pwm;
+ int duty, period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, ir_rx51->freq);
- duty = DIV_ROUND_CLOSEST(lirc_rx51->duty_cycle * period, 100);
+ duty = DIV_ROUND_CLOSEST(ir_rx51->duty_cycle * period, 100);
pwm_config(pwm, duty, period);
return 0;
}
-static enum hrtimer_restart lirc_rx51_timer_cb(struct hrtimer *timer)
+static enum hrtimer_restart ir_rx51_timer_cb(struct hrtimer *timer)
{
- struct lirc_rx51 *lirc_rx51 =
- container_of(timer, struct lirc_rx51, timer);
+ struct ir_rx51 *ir_rx51 = container_of(timer, struct ir_rx51, timer);
ktime_t now;
- if (lirc_rx51->wbuf_index < 0) {
- dev_err_ratelimited(lirc_rx51->dev,
- "BUG wbuf_index has value of %i\n",
- lirc_rx51->wbuf_index);
+ if (ir_rx51->wbuf_index < 0) {
+ dev_err_ratelimited(ir_rx51->dev,
+ "BUG wbuf_index has value of %i\n",
+ ir_rx51->wbuf_index);
goto end;
}
@@ -92,20 +82,20 @@ static enum hrtimer_restart lirc_rx51_timer_cb(struct hrtimer *timer)
do {
u64 ns;
- if (lirc_rx51->wbuf_index >= WBUF_LEN)
+ if (ir_rx51->wbuf_index >= WBUF_LEN)
goto end;
- if (lirc_rx51->wbuf[lirc_rx51->wbuf_index] == -1)
+ if (ir_rx51->wbuf[ir_rx51->wbuf_index] == -1)
goto end;
- if (lirc_rx51->wbuf_index % 2)
- lirc_rx51_off(lirc_rx51);
+ if (ir_rx51->wbuf_index % 2)
+ ir_rx51_off(ir_rx51);
else
- lirc_rx51_on(lirc_rx51);
+ ir_rx51_on(ir_rx51);
- ns = 1000 * lirc_rx51->wbuf[lirc_rx51->wbuf_index];
+ ns = US_TO_NS(ir_rx51->wbuf[ir_rx51->wbuf_index]);
hrtimer_add_expires_ns(timer, ns);
- lirc_rx51->wbuf_index++;
+ ir_rx51->wbuf_index++;
now = timer->base->get_time();
@@ -114,203 +104,112 @@ static enum hrtimer_restart lirc_rx51_timer_cb(struct hrtimer *timer)
return HRTIMER_RESTART;
end:
/* Stop TX here */
- lirc_rx51_off(lirc_rx51);
- lirc_rx51->wbuf_index = -1;
+ ir_rx51_off(ir_rx51);
+ ir_rx51->wbuf_index = -1;
- wake_up_interruptible(&lirc_rx51->wqueue);
+ wake_up_interruptible(&ir_rx51->wqueue);
return HRTIMER_NORESTART;
}
-static ssize_t lirc_rx51_write(struct file *file, const char *buf,
- size_t n, loff_t *ppos)
+static int ir_rx51_tx(struct rc_dev *dev, unsigned int *buffer,
+ unsigned int count)
{
- int count, i;
- struct lirc_rx51 *lirc_rx51 = file->private_data;
+ struct ir_rx51 *ir_rx51 = dev->priv;
- if (n % sizeof(int))
+ if (count > WBUF_LEN)
return -EINVAL;
- count = n / sizeof(int);
- if ((count > WBUF_LEN) || (count % 2 == 0))
- return -EINVAL;
+ memcpy(ir_rx51->wbuf, buffer, count * sizeof(unsigned int));
/* Wait any pending transfers to finish */
- wait_event_interruptible(lirc_rx51->wqueue, lirc_rx51->wbuf_index < 0);
-
- if (copy_from_user(lirc_rx51->wbuf, buf, n))
- return -EFAULT;
-
- /* Sanity check the input pulses */
- for (i = 0; i < count; i++)
- if (lirc_rx51->wbuf[i] < 0)
- return -EINVAL;
+ wait_event_interruptible(ir_rx51->wqueue, ir_rx51->wbuf_index < 0);
- init_timing_params(lirc_rx51);
+ init_timing_params(ir_rx51);
if (count < WBUF_LEN)
- lirc_rx51->wbuf[count] = -1; /* Insert termination mark */
+ ir_rx51->wbuf[count] = -1; /* Insert termination mark */
/*
* Adjust latency requirements so the device doesn't go in too
* deep sleep states
*/
- lirc_rx51->pdata->set_max_mpu_wakeup_lat(lirc_rx51->dev, 50);
+ ir_rx51->pdata->set_max_mpu_wakeup_lat(ir_rx51->dev, 50);
- lirc_rx51_on(lirc_rx51);
- lirc_rx51->wbuf_index = 1;
- hrtimer_start(&lirc_rx51->timer,
- ns_to_ktime(1000 * lirc_rx51->wbuf[0]),
+ ir_rx51_on(ir_rx51);
+ ir_rx51->wbuf_index = 1;
+ hrtimer_start(&ir_rx51->timer,
+ ns_to_ktime(US_TO_NS(ir_rx51->wbuf[0])),
HRTIMER_MODE_REL);
/*
* Don't return back to the userspace until the transfer has
* finished
*/
- wait_event_interruptible(lirc_rx51->wqueue, lirc_rx51->wbuf_index < 0);
+ wait_event_interruptible(ir_rx51->wqueue, ir_rx51->wbuf_index < 0);
/* We can sleep again */
- lirc_rx51->pdata->set_max_mpu_wakeup_lat(lirc_rx51->dev, -1);
+ ir_rx51->pdata->set_max_mpu_wakeup_lat(ir_rx51->dev, -1);
- return n;
+ return count;
}
-static long lirc_rx51_ioctl(struct file *filep,
- unsigned int cmd, unsigned long arg)
+static int ir_rx51_open(struct rc_dev *dev)
{
- int result;
- unsigned long value;
- unsigned int ivalue;
- struct lirc_rx51 *lirc_rx51 = filep->private_data;
-
- switch (cmd) {
- case LIRC_GET_SEND_MODE:
- result = put_user(LIRC_MODE_PULSE, (unsigned long *)arg);
- if (result)
- return result;
- break;
-
- case LIRC_SET_SEND_MODE:
- result = get_user(value, (unsigned long *)arg);
- if (result)
- return result;
-
- /* only LIRC_MODE_PULSE supported */
- if (value != LIRC_MODE_PULSE)
- return -ENOSYS;
- break;
-
- case LIRC_GET_REC_MODE:
- result = put_user(0, (unsigned long *) arg);
- if (result)
- return result;
- break;
-
- case LIRC_GET_LENGTH:
- return -ENOSYS;
- break;
-
- case LIRC_SET_SEND_DUTY_CYCLE:
- result = get_user(ivalue, (unsigned int *) arg);
- if (result)
- return result;
-
- if (ivalue <= 0 || ivalue > 100) {
- dev_err(lirc_rx51->dev, ": invalid duty cycle %d\n",
- ivalue);
- return -EINVAL;
- }
-
- lirc_rx51->duty_cycle = ivalue;
- break;
-
- case LIRC_SET_SEND_CARRIER:
- result = get_user(ivalue, (unsigned int *) arg);
- if (result)
- return result;
-
- if (ivalue > 500000 || ivalue < 20000) {
- dev_err(lirc_rx51->dev, ": invalid carrier freq %d\n",
- ivalue);
- return -EINVAL;
- }
-
- lirc_rx51->freq = ivalue;
- break;
-
- case LIRC_GET_FEATURES:
- result = put_user(LIRC_RX51_DRIVER_FEATURES,
- (unsigned long *) arg);
- if (result)
- return result;
- break;
-
- default:
- return -ENOIOCTLCMD;
- }
-
- return 0;
-}
+ struct ir_rx51 *ir_rx51 = dev->priv;
-static int lirc_rx51_open(struct inode *inode, struct file *file)
-{
- struct lirc_rx51 *lirc_rx51 = lirc_get_pdata(file);
- BUG_ON(!lirc_rx51);
-
- file->private_data = lirc_rx51;
-
- if (test_and_set_bit(1, &lirc_rx51->device_is_open))
+ if (test_and_set_bit(1, &ir_rx51->device_is_open))
return -EBUSY;
- lirc_rx51->pwm = pwm_get(lirc_rx51->dev, NULL);
- if (IS_ERR(lirc_rx51->pwm)) {
- int res = PTR_ERR(lirc_rx51->pwm);
+ ir_rx51->pwm = pwm_get(ir_rx51->dev, NULL);
+ if (IS_ERR(ir_rx51->pwm)) {
+ int res = PTR_ERR(ir_rx51->pwm);
- dev_err(lirc_rx51->dev, "pwm_get failed: %d\n", res);
+ dev_err(ir_rx51->dev, "pwm_get failed: %d\n", res);
return res;
}
return 0;
}
-static int lirc_rx51_release(struct inode *inode, struct file *file)
+static void ir_rx51_release(struct rc_dev *dev)
{
- struct lirc_rx51 *lirc_rx51 = file->private_data;
-
- hrtimer_cancel(&lirc_rx51->timer);
- lirc_rx51_off(lirc_rx51);
- pwm_put(lirc_rx51->pwm);
+ struct ir_rx51 *ir_rx51 = dev->priv;
- clear_bit(1, &lirc_rx51->device_is_open);
+ hrtimer_cancel(&ir_rx51->timer);
+ ir_rx51_off(ir_rx51);
+ pwm_put(ir_rx51->pwm);
- return 0;
+ clear_bit(1, &ir_rx51->device_is_open);
}
-static struct lirc_rx51 lirc_rx51 = {
+static struct ir_rx51 ir_rx51 = {
.duty_cycle = 50,
.wbuf_index = -1,
};
-static const struct file_operations lirc_fops = {
- .owner = THIS_MODULE,
- .write = lirc_rx51_write,
- .unlocked_ioctl = lirc_rx51_ioctl,
- .read = lirc_dev_fop_read,
- .poll = lirc_dev_fop_poll,
- .open = lirc_rx51_open,
- .release = lirc_rx51_release,
-};
+static int ir_rx51_set_duty_cycle(struct rc_dev *dev, u32 duty)
+{
+ struct ir_rx51 *ir_rx51 = dev->priv;
-static struct lirc_driver lirc_rx51_driver = {
- .name = DRIVER_NAME,
- .minor = -1,
- .code_length = 1,
- .data = &lirc_rx51,
- .fops = &lirc_fops,
- .owner = THIS_MODULE,
-};
+ ir_rx51->duty_cycle = duty;
+
+ return 0;
+}
+
+static int ir_rx51_set_tx_carrier(struct rc_dev *dev, u32 carrier)
+{
+ struct ir_rx51 *ir_rx51 = dev->priv;
+
+ if (carrier > 500000 || carrier < 20000)
+ return -EINVAL;
+
+ ir_rx51->freq = carrier;
+
+ return 0;
+}
#ifdef CONFIG_PM
-static int lirc_rx51_suspend(struct platform_device *dev, pm_message_t state)
+static int ir_rx51_suspend(struct platform_device *dev, pm_message_t state)
{
/*
* In case the device is still open, do not suspend. Normally
@@ -320,34 +219,34 @@ static int lirc_rx51_suspend(struct platform_device *dev, pm_message_t state)
* were in a middle of a transmit. Thus, we defer any suspend
* actions until transmit has completed.
*/
- if (test_and_set_bit(1, &lirc_rx51.device_is_open))
+ if (test_and_set_bit(1, &ir_rx51.device_is_open))
return -EAGAIN;
- clear_bit(1, &lirc_rx51.device_is_open);
+ clear_bit(1, &ir_rx51.device_is_open);
return 0;
}
-static int lirc_rx51_resume(struct platform_device *dev)
+static int ir_rx51_resume(struct platform_device *dev)
{
return 0;
}
#else
-#define lirc_rx51_suspend NULL
-#define lirc_rx51_resume NULL
+#define ir_rx51_suspend NULL
+#define ir_rx51_resume NULL
#endif /* CONFIG_PM */
-static int lirc_rx51_probe(struct platform_device *dev)
+static int ir_rx51_probe(struct platform_device *dev)
{
struct pwm_device *pwm;
+ struct rc_dev *rcdev;
- lirc_rx51_driver.features = LIRC_RX51_DRIVER_FEATURES;
- lirc_rx51.pdata = dev->dev.platform_data;
+ ir_rx51.pdata = dev->dev.platform_data;
- if (!lirc_rx51.pdata) {
+ if (!ir_rx51.pdata) {
dev_err(&dev->dev, "Platform Data is missing\n");
return -ENXIO;
}
@@ -362,51 +261,56 @@ static int lirc_rx51_probe(struct platform_device *dev)
}
/* Use default, in case userspace does not set the carrier */
- lirc_rx51.freq = DIV_ROUND_CLOSEST(pwm_get_period(pwm), NSEC_PER_SEC);
+ ir_rx51.freq = DIV_ROUND_CLOSEST(pwm_get_period(pwm), NSEC_PER_SEC);
pwm_put(pwm);
- hrtimer_init(&lirc_rx51.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- lirc_rx51.timer.function = lirc_rx51_timer_cb;
+ hrtimer_init(&ir_rx51.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ ir_rx51.timer.function = ir_rx51_timer_cb;
- lirc_rx51.dev = &dev->dev;
- lirc_rx51_driver.dev = &dev->dev;
- lirc_rx51_driver.minor = lirc_register_driver(&lirc_rx51_driver);
- init_waitqueue_head(&lirc_rx51.wqueue);
+ ir_rx51.dev = &dev->dev;
- if (lirc_rx51_driver.minor < 0) {
- dev_err(lirc_rx51.dev, ": lirc_register_driver failed: %d\n",
- lirc_rx51_driver.minor);
- return lirc_rx51_driver.minor;
- }
+ rcdev = devm_rc_allocate_device(&dev->dev, RC_DRIVER_IR_RAW_TX);
+ if (!rcdev)
+ return -ENOMEM;
- return 0;
+ rcdev->priv = &ir_rx51;
+ rcdev->open = ir_rx51_open;
+ rcdev->close = ir_rx51_release;
+ rcdev->tx_ir = ir_rx51_tx;
+ rcdev->s_tx_duty_cycle = ir_rx51_set_duty_cycle;
+ rcdev->s_tx_carrier = ir_rx51_set_tx_carrier;
+ rcdev->driver_name = KBUILD_MODNAME;
+
+ ir_rx51.rcdev = rcdev;
+
+ return devm_rc_register_device(&dev->dev, ir_rx51.rcdev);
}
-static int lirc_rx51_remove(struct platform_device *dev)
+static int ir_rx51_remove(struct platform_device *dev)
{
- return lirc_unregister_driver(lirc_rx51_driver.minor);
+ return 0;
}
-static const struct of_device_id lirc_rx51_match[] = {
+static const struct of_device_id ir_rx51_match[] = {
{
.compatible = "nokia,n900-ir",
},
{},
};
-MODULE_DEVICE_TABLE(of, lirc_rx51_match);
+MODULE_DEVICE_TABLE(of, ir_rx51_match);
-struct platform_driver lirc_rx51_platform_driver = {
- .probe = lirc_rx51_probe,
- .remove = lirc_rx51_remove,
- .suspend = lirc_rx51_suspend,
- .resume = lirc_rx51_resume,
+static struct platform_driver ir_rx51_platform_driver = {
+ .probe = ir_rx51_probe,
+ .remove = ir_rx51_remove,
+ .suspend = ir_rx51_suspend,
+ .resume = ir_rx51_resume,
.driver = {
- .name = DRIVER_NAME,
- .of_match_table = of_match_ptr(lirc_rx51_match),
+ .name = KBUILD_MODNAME,
+ .of_match_table = of_match_ptr(ir_rx51_match),
},
};
-module_platform_driver(lirc_rx51_platform_driver);
+module_platform_driver(ir_rx51_platform_driver);
-MODULE_DESCRIPTION("LIRC TX driver for Nokia RX51");
+MODULE_DESCRIPTION("IR TX driver for Nokia RX51");
MODULE_AUTHOR("Nokia Corporation");
MODULE_LICENSE("GPL");
diff --git a/include/linux/platform_data/media/ir-rx51.h b/include/linux/platform_data/media/ir-rx51.h
index 812d873..2c94ab5 100644
--- a/include/linux/platform_data/media/ir-rx51.h
+++ b/include/linux/platform_data/media/ir-rx51.h
@@ -1,7 +1,7 @@
-#ifndef _LIRC_RX51_H
-#define _LIRC_RX51_H
+#ifndef _IR_RX51_H
+#define _IR_RX51_H
-struct lirc_rx51_platform_data {
+struct ir_rx51_platform_data {
int(*set_max_mpu_wakeup_lat)(struct device *dev, long t);
};
--
2.9.3
Before this driver can be moved out of staging, it should be ported
to rc-core. I've tried to make the minimum changes possible without
upsetting checkpatch.
Compile tested only.
Signed-off-by: Sean Young <[email protected]>
Cc: Jarod Wilson <[email protected]>
Cc: Christoph Bartelmus <[email protected]>
Cc: Milan Pikula <[email protected]>
Cc: Frank Przybylski <[email protected]>
---
drivers/staging/media/lirc/Kconfig | 2 +-
drivers/staging/media/lirc/lirc_sir.c | 296 ++++++++--------------------------
2 files changed, 69 insertions(+), 229 deletions(-)
diff --git a/drivers/staging/media/lirc/Kconfig b/drivers/staging/media/lirc/Kconfig
index 25b7e7c..56e5fd7 100644
--- a/drivers/staging/media/lirc/Kconfig
+++ b/drivers/staging/media/lirc/Kconfig
@@ -40,7 +40,7 @@ config LIRC_SASEM
config LIRC_SIR
tristate "Built-in SIR IrDA port"
- depends on LIRC
+ depends on RC_CORE
help
Driver for the SIR IrDA port
diff --git a/drivers/staging/media/lirc/lirc_sir.c b/drivers/staging/media/lirc/lirc_sir.c
index 4f326e9..c75ae43 100644
--- a/drivers/staging/media/lirc/lirc_sir.c
+++ b/drivers/staging/media/lirc/lirc_sir.c
@@ -1,7 +1,7 @@
/*
* LIRC SIR driver, (C) 2000 Milan Pikula <[email protected]>
*
- * lirc_sir - Device driver for use with SIR (serial infra red)
+ * sir_ir - 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
@@ -58,8 +58,7 @@
#include <linux/timer.h>
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
+#include <media/rc-core.h>
/* SECTION: Definitions */
@@ -87,11 +86,6 @@ static void init_act200(void);
static void init_act220(void);
#endif
-#define RBUF_LEN 1024
-#define WBUF_LEN 1024
-
-#define LIRC_DRIVER_NAME "lirc_sir"
-
#define PULSE '['
#ifndef LIRC_SIR_TEKRAM
@@ -131,28 +125,19 @@ static ktime_t last;
/* time of last UART data ready interrupt */
static ktime_t last_intr_time;
static int last_value;
+static struct rc_dev *rcdev;
-static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue);
+static struct platform_device *sir_ir_dev;
static DEFINE_SPINLOCK(hardware_lock);
-static int rx_buf[RBUF_LEN];
-static unsigned int rx_tail, rx_head;
-
static bool debug;
/* 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 __user *buf, size_t count,
- loff_t *ppos);
-static ssize_t lirc_write(struct file *file, const char __user *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);
@@ -189,72 +174,14 @@ static void safe_udelay(unsigned long 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 __user *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(buf + n,
- 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 __user *buf, size_t n,
- loff_t *pos)
+static int sir_tx_ir(struct rc_dev *dev, unsigned int *tx_buf,
+ unsigned int count)
{
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;
+ int i;
+
local_irq_save(flags);
- while (1) {
- if (i >= count)
- break;
+ for (i = 0; i < count;) {
if (tx_buf[i])
send_pulse(tx_buf[i]);
i++;
@@ -265,138 +192,53 @@ static ssize_t lirc_write(struct file *file, const char __user *buf, size_t n,
i++;
}
local_irq_restore(flags);
- kfree(tx_buf);
- return count;
-}
-
-static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
-{
- u32 __user *uptr = (u32 __user *)arg;
- int retval = 0;
- u32 value = 0;
-
- 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;
-
- switch (cmd) {
- case LIRC_GET_FEATURES:
- case LIRC_GET_SEND_MODE:
- case LIRC_GET_REC_MODE:
- retval = put_user(value, uptr);
- break;
-
- case LIRC_SET_SEND_MODE:
- case LIRC_SET_REC_MODE:
- retval = get_user(value, uptr);
- break;
- default:
- retval = -ENOIOCTLCMD;
-
- }
-
- if (retval)
- return retval;
- if (cmd == LIRC_SET_REC_MODE) {
- if (value != LIRC_MODE_MODE2)
- retval = -ENOSYS;
- } else if (cmd == LIRC_SET_SEND_MODE) {
- if (value != LIRC_MODE_PULSE)
- retval = -ENOSYS;
- }
- return retval;
+ return count;
}
static void add_read_queue(int flag, unsigned long val)
{
- unsigned int new_rx_tail;
- int newval;
+ DEFINE_IR_RAW_EVENT(ev);
pr_debug("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;
+ if (val > TIME_CONST / 2)
+ val -= TIME_CONST / 2;
else /* should not ever happen */
- newval = 1;
- newval |= PULSE_BIT;
+ val = 1;
+ ev.pulse = true;
} else {
- newval += TIME_CONST/2;
+ val += TIME_CONST / 2;
}
- new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1);
- if (new_rx_tail == rx_head) {
- pr_debug("Buffer overrun.\n");
- return;
- }
- rx_buf[rx_tail] = newval;
- rx_tail = new_rx_tail;
- wake_up_interruptible(&lirc_read_queue);
-}
+ ev.duration = US_TO_NS(val);
-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;
+ ir_raw_event_store_with_filter(rcdev, &ev);
}
-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_sir_dev;
-
static int init_chrdev(void)
{
- driver.dev = &lirc_sir_dev->dev;
- driver.minor = lirc_register_driver(&driver);
- if (driver.minor < 0) {
- pr_err("init_chrdev() failed.\n");
- return -EIO;
- }
- return 0;
-}
-
-static void drop_chrdev(void)
-{
- lirc_unregister_driver(driver.minor);
+ rcdev = devm_rc_allocate_device(&sir_ir_dev->dev, RC_DRIVER_IR_RAW);
+ if (!rcdev)
+ return -ENOMEM;
+
+ rcdev->input_phys = KBUILD_MODNAME "/input0";
+ rcdev->input_id.bustype = BUS_HOST;
+ rcdev->input_id.vendor = 0x0001;
+ rcdev->input_id.product = 0x0001;
+ rcdev->input_id.version = 0x0100;
+ rcdev->tx_ir = sir_tx_ir;
+ rcdev->allowed_protocols = RC_BIT_ALL_IR_DECODER;
+ rcdev->map_name = RC_MAP_RC6_MCE;
+ rcdev->timeout = IR_DEFAULT_TIMEOUT;
+ rcdev->dev.parent = &sir_ir_dev->dev;
+
+ return devm_rc_register_device(&sir_ir_dev->dev, rcdev);
}
/* SECTION: Hardware */
@@ -420,14 +262,15 @@ static void sir_timeout(unsigned long data)
/* determine 'virtual' pulse end: */
pulse_end = min_t(unsigned long,
ktime_us_delta(last, last_intr_time),
- PULSE_MASK);
- dev_dbg(driver.dev, "timeout add %d for %lu usec\n",
- last_value, pulse_end);
+ IR_MAX_DURATION);
+ dev_dbg(&sir_ir_dev->dev, "timeout add %d for %lu usec\n",
+ last_value, pulse_end);
add_read_queue(last_value, pulse_end);
last_value = 0;
last = last_intr_time;
}
spin_unlock_irqrestore(&timer_lock, flags);
+ ir_raw_event_handle(rcdev);
}
static irqreturn_t sir_interrupt(int irq, void *dev_id)
@@ -462,20 +305,20 @@ static irqreturn_t sir_interrupt(int irq, void *dev_id)
curr_time = ktime_get();
delt = min_t(unsigned long,
ktime_us_delta(last, curr_time),
- PULSE_MASK);
+ IR_MAX_DURATION);
deltintr = min_t(unsigned long,
ktime_us_delta(last_intr_time,
curr_time),
- PULSE_MASK);
- dev_dbg(driver.dev, "t %lu, d %d\n",
- deltintr, (int)data);
+ IR_MAX_DURATION);
+ dev_dbg(&sir_ir_dev->dev, "t %lu, d %d\n",
+ deltintr, (int)data);
/*
* if nothing came in last X cycles,
* it was gap
*/
if (deltintr > TIME_CONST * threshold) {
if (last_value) {
- dev_dbg(driver.dev, "GAP\n");
+ dev_dbg(&sir_ir_dev->dev, "GAP\n");
/* simulate signal change */
add_read_queue(last_value,
delt -
@@ -517,6 +360,7 @@ static irqreturn_t sir_interrupt(int irq, void *dev_id)
break;
}
}
+ ir_raw_event_handle(rcdev);
return IRQ_RETVAL(IRQ_HANDLED);
}
@@ -655,12 +499,12 @@ static int init_port(void)
int retval;
/* get I/O port access and IRQ line */
- if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) {
+ if (!request_region(io, 8, KBUILD_MODNAME)) {
pr_err("i/o port 0x%.4x already in use.\n", io);
return -EBUSY;
}
retval = request_irq(irq, sir_interrupt, 0,
- LIRC_DRIVER_NAME, NULL);
+ KBUILD_MODNAME, NULL);
if (retval < 0) {
release_region(io, 8);
pr_err("IRQ %d already in use.\n", irq);
@@ -882,11 +726,10 @@ void init_act220(void)
}
#endif
-static int init_lirc_sir(void)
+static int init_sir_ir(void)
{
int retval;
- init_waitqueue_head(&lirc_read_queue);
retval = init_port();
if (retval < 0)
return retval;
@@ -895,42 +738,42 @@ static int init_lirc_sir(void)
return 0;
}
-static int lirc_sir_probe(struct platform_device *dev)
+static int sir_ir_probe(struct platform_device *dev)
{
return 0;
}
-static int lirc_sir_remove(struct platform_device *dev)
+static int sir_ir_remove(struct platform_device *dev)
{
return 0;
}
-static struct platform_driver lirc_sir_driver = {
- .probe = lirc_sir_probe,
- .remove = lirc_sir_remove,
+static struct platform_driver sir_ir_driver = {
+ .probe = sir_ir_probe,
+ .remove = sir_ir_remove,
.driver = {
- .name = "lirc_sir",
+ .name = "sir_ir",
},
};
-static int __init lirc_sir_init(void)
+static int __init sir_ir_init(void)
{
int retval;
- retval = platform_driver_register(&lirc_sir_driver);
+ retval = platform_driver_register(&sir_ir_driver);
if (retval) {
pr_err("Platform driver register failed!\n");
return -ENODEV;
}
- lirc_sir_dev = platform_device_alloc("lirc_dev", 0);
- if (!lirc_sir_dev) {
+ sir_ir_dev = platform_device_alloc("sir_ir", 0);
+ if (!sir_ir_dev) {
pr_err("Platform device alloc failed!\n");
retval = -ENOMEM;
goto pdev_alloc_fail;
}
- retval = platform_device_add(lirc_sir_dev);
+ retval = platform_device_add(sir_ir_dev);
if (retval) {
pr_err("Platform device add failed!\n");
retval = -ENODEV;
@@ -941,35 +784,32 @@ static int __init lirc_sir_init(void)
if (retval < 0)
goto fail;
- retval = init_lirc_sir();
- if (retval) {
- drop_chrdev();
+ retval = init_sir_ir();
+ if (retval)
goto fail;
- }
return 0;
fail:
- platform_device_del(lirc_sir_dev);
+ platform_device_del(sir_ir_dev);
pdev_add_fail:
- platform_device_put(lirc_sir_dev);
+ platform_device_put(sir_ir_dev);
pdev_alloc_fail:
- platform_driver_unregister(&lirc_sir_driver);
+ platform_driver_unregister(&sir_ir_driver);
return retval;
}
-static void __exit lirc_sir_exit(void)
+static void __exit sir_ir_exit(void)
{
drop_hardware();
- drop_chrdev();
drop_port();
- platform_device_unregister(lirc_sir_dev);
- platform_driver_unregister(&lirc_sir_driver);
+ platform_device_unregister(sir_ir_dev);
+ platform_driver_unregister(&sir_ir_driver);
pr_info("Uninstalled.\n");
}
-module_init(lirc_sir_init);
-module_exit(lirc_sir_exit);
+module_init(sir_ir_init);
+module_exit(sir_ir_exit);
#ifdef LIRC_SIR_TEKRAM
MODULE_DESCRIPTION("Infrared receiver driver for Tekram Irmate 210");
--
2.9.3
Hi,
On 20.12.2016 19:50, Sean Young wrote:
> This driver was written using lirc since rc-core did not support
> transmitter-only hardware at that time. Now that it does, port
> this driver.
>
> Compile tested only.
>
I guess after that change, there will be no more /dev/lircN device,
right? Neither will LIRC_XXX IOCTL codes be supported?
That looks to me as a completely new driver, not a port to new API.
Right now there are applications using the current behaviour (pierogi
for example), which will be broken by the change.
Ivo
Hi Ivo,,
On Fri, Dec 30, 2016 at 01:30:01PM +0200, Ivaylo Dimitrov wrote:
> On 20.12.2016 19:50, Sean Young wrote:
> >This driver was written using lirc since rc-core did not support
> >transmitter-only hardware at that time. Now that it does, port
> >this driver.
> >
> >Compile tested only.
> >
>
> I guess after that change, there will be no more /dev/lircN device, right?
> Neither will LIRC_XXX IOCTL codes be supported?
Quite the opposite, /dev/lircN and all the LIRC_XXX ioctls will still be
supported through ir-lirc-codec.c.
By using rc-core, the driver will be more succinct, and some latent bugs
will be fixed. For example, at the moment it is possible to write hours
of IR data and keep the n900 from suspending.
I'm working on lirc scancode sending and receiving using the IR encoders,
and when that is in place, any rc-core driver will get it for free.
> That looks to me as a completely new driver, not a port to new API.
>
> Right now there are applications using the current behaviour (pierogi for
> example), which will be broken by the change.
Nothing should break.
Thanks,
Sean
On Fri, Dec 30, 2016 at 01:07:52PM +0000, Sean Young wrote:
> Hi Ivo,,
>
> On Fri, Dec 30, 2016 at 01:30:01PM +0200, Ivaylo Dimitrov wrote:
> > On 20.12.2016 19:50, Sean Young wrote:
> > >This driver was written using lirc since rc-core did not support
> > >transmitter-only hardware at that time. Now that it does, port
> > >this driver.
> > >
> > >Compile tested only.
> > >
> >
> > I guess after that change, there will be no more /dev/lircN device, right?
> > Neither will LIRC_XXX IOCTL codes be supported?
>
> Quite the opposite, /dev/lircN and all the LIRC_XXX ioctls will still be
> supported through ir-lirc-codec.c.
>
> By using rc-core, the driver will be more succinct, and some latent bugs
> will be fixed. For example, at the moment it is possible to write hours
> of IR data and keep the n900 from suspending.
>
> I'm working on lirc scancode sending and receiving using the IR encoders,
> and when that is in place, any rc-core driver will get it for free.
>
> > That looks to me as a completely new driver, not a port to new API.
> >
> > Right now there are applications using the current behaviour (pierogi for
> > example), which will be broken by the change.
>
> Nothing should break.
Speaking of which, if you would please test this, that would be great. My
N900 died many years ago.
Many thanks,
Sean
On 30.12.2016 15:30, Sean Young wrote:
>
> On Fri, Dec 30, 2016 at 01:07:52PM +0000, Sean Young wrote:
>> Hi Ivo,,
>>
>> On Fri, Dec 30, 2016 at 01:30:01PM +0200, Ivaylo Dimitrov wrote:
>>> On 20.12.2016 19:50, Sean Young wrote:
>>>> This driver was written using lirc since rc-core did not support
>>>> transmitter-only hardware at that time. Now that it does, port
>>>> this driver.
>>>>
>>>> Compile tested only.
>>>>
>>>
>>> I guess after that change, there will be no more /dev/lircN device, right?
>>> Neither will LIRC_XXX IOCTL codes be supported?
>>
>> Quite the opposite, /dev/lircN and all the LIRC_XXX ioctls will still be
>> supported through ir-lirc-codec.c.
>>
>> By using rc-core, the driver will be more succinct, and some latent bugs
>> will be fixed. For example, at the moment it is possible to write hours
>> of IR data and keep the n900 from suspending.
>>
>> I'm working on lirc scancode sending and receiving using the IR encoders,
>> and when that is in place, any rc-core driver will get it for free.
>>
>>> That looks to me as a completely new driver, not a port to new API.
>>>
>>> Right now there are applications using the current behaviour (pierogi for
>>> example), which will be broken by the change.
>>
>> Nothing should break.
>
> Speaking of which, if you would please test this, that would be great. My
> N900 died many years ago.
>
Will do, but next year :) .
Thanks,
Ivo
Hi Ivo,
On Fri, Dec 30, 2016 at 03:50:42PM +0200, Ivaylo Dimitrov wrote:
> On 30.12.2016 15:30, Sean Young wrote:
> >On Fri, Dec 30, 2016 at 01:07:52PM +0000, Sean Young wrote:
> >Speaking of which, if you would please test this, that would be great. My
> >N900 died many years ago.
>
> Will do, but next year :) .
Great, thanks!
Sean