uartlirc.ko lirc serial patch (see uartlirc-preliminary-002.shar) extracted as diff against uart(4) for easier review/commenting - known issues: 1. Creates /dev/lircX nodes in addition to tty device nodes for all ports, maybe there should be a flags bit to enable lirc mode only for specific port(s)? Of course this way it's more flexible... (Or a sysctl?) 2. Also doesn't yet check for tty nodes opened in parallel to lirc ones. 3. The #if __FreeBSD_version >= 900000 hunks are only remnants of the out-of-tree uartlirc version so that it builds on 8.x too. 4. Same for the BUS_PROBE_VENDOR change, it's only to be able to load the out-of-tree uartlirc.ko from loader without having to disable uart(4) in the kernel. 4. Makefile diffs missing. (only in out-of-tree uartlirc) 5. Should the sc->sc_lirc* fields be in their own struct? 6. Maybe the PPS code should be extended to buffer fast events and a hw_pps.c lirc "driver" created instead? Tho of course that wouldn't cover sending IR (which isn't in this version but could be added like it's in Linux' lirc_serial driver and supported by lircd.) 7. The lirc.h doesn't have a license header but the ports/comms/lirc package it is from is GPL so maybe this has to stay in ports anyway... Only in src10/src/sys/dev/uart: CVS diff -upr src10/src/sys/dev/uart/uart_bus.h uartlirc/uart/uart_bus.h --- src10/src/sys/dev/uart/uart_bus.h 2012-04-12 20:46:48.000000000 +0200 +++ uartlirc/uart/uart_bus.h 2012-04-27 21:21:54.000000000 +0200 @@ -35,6 +35,9 @@ #include #include +#include +#include +#include /* Drain and flush targets. */ #define UART_DRAIN_RECEIVER 0x0001 @@ -131,6 +134,19 @@ struct uart_softc { struct { } u_kbd; } sc_u; + + /* lirc device node */ + struct cdev *sc_lirc_cdev; + struct mtx sc_lirc_lock; + int sc_lircstate; + int sc_lirc_sigxor; + /* lirc receiver fifo */ + struct buf_ring *sc_lirc_rcv_fifo; + struct mtx sc_lirc_rcv_fifo_lock; + struct selinfo sc_lirc_rsel; + /* time of last received lirc event */ + struct timeval sc_lirc_rcv_time; + uint32_t sc_lirc_lastevent; }; extern devclass_t uart_devclass; diff -upr src10/src/sys/dev/uart/uart_core.c uartlirc/uart/uart_core.c --- src10/src/sys/dev/uart/uart_core.c 2012-04-12 20:46:48.000000000 +0200 +++ uartlirc/uart/uart_core.c 2012-04-27 21:21:54.000000000 +0200 @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD: src/sys/dev/uart/uar #include #include #include +#include #include "uart_if.h" @@ -211,6 +212,9 @@ uart_intr_sigchg(void *arg) } } + if (sc->sc_lircstate) + uart_lircdev_sig(arg, sig); + /* * Keep track of signal changes, even when the device is not * opened. This allows us to inform upper layers about a @@ -382,7 +386,11 @@ uart_bus_probe(device_t dev, int regshft error = UART_PROBE(sc); bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); - return ((error) ? error : BUS_PROBE_DEFAULT); + /* + * XXX use BUS_PROBE_VENDOR so uartlirc.ko loaded via loader + * overrides in-kernel uart(4) driver. + */ + return ((error) ? error : BUS_PROBE_VENDOR); } int Only in uartlirc/uart: uart_cpu_amd64.c Only in uartlirc/uart: uart_cpu_i386.c diff -upr src10/src/sys/dev/uart/uart_cpu_pc98.c uartlirc/uart/uart_cpu_pc98.c --- src10/src/sys/dev/uart/uart_cpu_pc98.c 2010-12-20 17:39:43.000000000 +0100 +++ uartlirc/uart/uart_cpu_pc98.c 2012-04-27 21:21:54.000000000 +0200 @@ -37,8 +37,13 @@ __FBSDID("$FreeBSD: src/sys/dev/uart/uar #include #include +#if __FreeBSD_version >= 900000 bus_space_tag_t uart_bus_space_io = X86_BUS_SPACE_IO; bus_space_tag_t uart_bus_space_mem = X86_BUS_SPACE_MEM; +#else +bus_space_tag_t uart_bus_space_io = I386_BUS_SPACE_IO; +bus_space_tag_t uart_bus_space_mem = I386_BUS_SPACE_MEM; +#endif static struct { u_long iobase; diff -upr src10/src/sys/dev/uart/uart_tty.c uartlirc/uart/uart_tty.c --- src10/src/sys/dev/uart/uart_tty.c 2011-12-17 16:08:43.000000000 +0100 +++ uartlirc/uart/uart_tty.c 2012-04-27 21:21:54.000000000 +0200 @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD: src/sys/dev/uart/uar #include #include #include +#include #include "uart_if.h" @@ -54,8 +55,10 @@ static cn_init_t uart_cninit; static cn_term_t uart_cnterm; static cn_getc_t uart_cngetc; static cn_putc_t uart_cnputc; +#if __FreeBSD_version >= 1000000 static cn_grab_t uart_cngrab; static cn_ungrab_t uart_cnungrab; +#endif CONSOLE_DRIVER(uart); @@ -109,6 +112,7 @@ uart_cnterm(struct consdev *cp) uart_term(cp->cn_arg); } +#if __FreeBSD_version >= 1000000 static void uart_cngrab(struct consdev *cp) { @@ -118,6 +122,7 @@ static void uart_cnungrab(struct consdev *cp) { } +#endif static void uart_cnputc(struct consdev *cp, int c) @@ -388,6 +393,9 @@ uart_tty_attach(struct uart_softc *sc) swi_add(&tty_intr_event, uart_driver_name, uart_tty_intr, sc, SWI_TTY, INTR_TYPE_TTY, &sc->sc_softih); + /* XXX if flags & LIRC? */ + uart_lircdev_attach(sc); + tty_makedev(tp, NULL, "u%r", unit); return (0); @@ -398,6 +406,9 @@ uart_tty_detach(struct uart_softc *sc) { struct tty *tp; + /* XXX if flags & LIRC? */ + uart_lircdev_detach(sc); + tp = sc->sc_u.u_tty.tp; tty_lock(tp); --- /dev/null +++ src/sys/dev/uart/uart_lircdev.h @@ -0,0 +1,3 @@ +void uart_lircdev_sig(void *arg, int sig); +int uart_lircdev_attach(struct uart_softc *sc); +int uart_lircdev_detach(struct uart_softc *sc); --- /dev/null +++ src/sys/dev/uart/uart_lircdev.c @@ -0,0 +1,271 @@ +/*- + * Copyright (c) 2012 Juergen Lock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uartlirc.h" +#include "uartlirc_bus.h" +#include "uartlirc_cpu.h" +#include "uartlirc_lircdev.h" + +#include "uartlirc_if.h" + +#include "lirc.h" + +#define UARTLIRC_LIRCOPEN 1 + +static int +uartlirc_lircdev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) +{ + struct uartlirc_softc *sc = dev->si_drv1; + struct buf_ring *br; + + if (sc == NULL) + return (ENXIO); + + if (sc->sc_lircstate) + return (EBUSY); + + sc->sc_lirc_lastevent = 0; + + /* flush receiver fifo */ + /* XXX locking - is critical_enter() enough? */ + br = sc->sc_lirc_rcv_fifo; + + critical_enter(); + br->br_prod_head = br->br_cons_head = 0; + br->br_prod_tail = br->br_cons_tail = 0; + critical_exit(); + + /* raise RTS to power the IR receiver */ + UARTLIRC_IOCTL(sc, UARTLIRC_IOCTL_IFLOW, 1); + UARTLIRC_SETSIG(sc, SER_DTR | SER_DDTR | SER_DRTS | SER_RTS); + + sc->sc_lircstate = UARTLIRC_LIRCOPEN; + return (0); +} + +static int +uartlirc_lircdev_close(struct cdev *dev, int fflag, int devtype, struct thread *td) +{ + struct uartlirc_softc *sc = dev->si_drv1; + + if (sc == NULL || !sc->sc_lircstate) + return 0; + + sc->sc_lircstate = 0; + + wakeup(&sc->sc_lircstate); + selwakeup(&sc->sc_lirc_rsel); + return 0; +} + +static int +uartlirc_lircdev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) +{ + uint32_t *arg = (uint32_t *)data; + + switch (cmd) { + case LIRC_GET_FEATURES: + *arg = LIRC_CAN_REC_MODE2; + return (0); + default: + return ENOTTY; + } +} + +static int +uartlirc_lircdev_read(struct cdev *dev, struct uio *uio, int ioflag) +{ + struct uartlirc_softc *sc = dev->si_drv1; + + int error = 0, num = 0; + void *entry; + uint32_t data; + + mtx_lock(&sc->sc_lirc_lock); + while (uio->uio_resid) { + if (uio->uio_resid % sizeof(data)) + return EINVAL; + + while ((entry = buf_ring_dequeue_sc(sc->sc_lirc_rcv_fifo)) == NULL) { + if (!num) { + if (ioflag & O_NONBLOCK) { + error = EWOULDBLOCK; + goto end_read; + } + error = msleep(&sc->sc_lircstate, &sc->sc_lirc_lock, PCATCH | PDROP, "rdlirc", 0); + if (error == EINTR) + goto end_read2; + if (sc != dev->si_drv1) + error = ENXIO; + if (error) + goto end_read2; + mtx_lock(&sc->sc_lirc_lock); + } else { + goto end_read; + } + } + data = (uint32_t)(size_t)entry; + error = uiomove(&data, sizeof(data), uio); + if (error) + goto end_read; + ++num; + } + +end_read: + mtx_unlock(&sc->sc_lirc_lock); +end_read2: + return error; +} + +static int +uartlirc_lircdev_poll(struct cdev *dev, int events, struct thread *td) +{ + struct uartlirc_softc *sc = dev->si_drv1; + + if (!sc->sc_lircstate) + return POLLHUP; + + if (events & (POLLIN | POLLRDNORM)) { + if (buf_ring_peek(sc->sc_lirc_rcv_fifo)) + return events & (POLLIN | POLLRDNORM); + else + selrecord(td, &sc->sc_lirc_rsel); + } + return 0; +} + +static void +uartlirc_lircevent(struct uartlirc_softc *sc, uint32_t val); + +static void +uartlirc_lircevent(struct uartlirc_softc *sc, uint32_t val) +{ +#if 0 + if (LIRC_MODE2(val) == LIRC_MODE2(sc->sc_lirc_lastevent)) + /* XXX we were too slow */ + return; +#endif + if (buf_ring_enqueue(sc->sc_lirc_rcv_fifo, (void *)(size_t)val) != 0) + return; + sc->sc_lirc_lastevent = val; + wakeup(&sc->sc_lircstate); + selwakeup(&sc->sc_lirc_rsel); +} + +void +uartlirc_lircdev_sig(void *arg, int sig) +{ + struct uartlirc_softc *sc = arg; + + if (!sc->sc_lircstate) + return; + + if (sig & SER_DDCD) { + struct timeval oldtv = sc->sc_lirc_rcv_time, delta; + + microtime(&sc->sc_lirc_rcv_time); + delta = sc->sc_lirc_rcv_time; + timevalsub(&delta, &oldtv); + if (delta.tv_sec) + delta.tv_usec = (suseconds_t) 1.e6; + if ((sig ^ sc->sc_lirc_sigxor) & SER_DCD) { + /* pulse */ + uartlirc_lircevent(sc, LIRC_PULSE(delta.tv_usec)); + } else { + /* space */ + uartlirc_lircevent(sc, LIRC_SPACE(delta.tv_usec)); + } + } +} + +static struct cdevsw uartlirc_lircdev_cdevsw = { + .d_version = D_VERSION, + .d_open = uartlirc_lircdev_open, + .d_close = uartlirc_lircdev_close, + .d_ioctl = uartlirc_lircdev_ioctl, + .d_read = uartlirc_lircdev_read, + .d_poll = uartlirc_lircdev_poll, +}; + +int +uartlirc_lircdev_attach(struct uartlirc_softc *sc) +{ + int unit; + + unit = device_get_unit(sc->sc_dev); + + /* sc->sc_lircstate = 0; */ + int ivar = 1; + resource_int_value("uartlirc", device_get_unit(sc->sc_dev), + "activelowflag", &ivar); + if (ivar) + sc->sc_lirc_sigxor = 0; + else + sc->sc_lirc_sigxor = -1; + + mtx_init(&sc->sc_lirc_rcv_fifo_lock, "lirc rcv fifo", NULL, MTX_SPIN|MTX_DUPOK); + mtx_init(&sc->sc_lirc_lock, "lirc lock", NULL, MTX_DUPOK); + sc->sc_lirc_rcv_fifo = buf_ring_alloc((1 << 15), M_DEVBUF, M_WAITOK, &sc->sc_lirc_rcv_fifo_lock); + + sc->sc_lirc_cdev = make_dev(&uartlirc_lircdev_cdevsw, unit, UID_ROOT, GID_WHEEL, 0600, "lirc%d", unit); + sc->sc_lirc_cdev->si_drv1 = sc; + + return (0); +} + +int +uartlirc_lircdev_detach(struct uartlirc_softc *sc) +{ + sc->sc_lirc_cdev->si_drv1 = NULL; + wakeup(&sc->sc_lircstate); + selwakeup(&sc->sc_lirc_rsel); + destroy_dev(sc->sc_lirc_cdev); + buf_ring_free(sc->sc_lirc_rcv_fifo, M_DEVBUF); + mtx_destroy(&sc->sc_lirc_rcv_fifo_lock); + + return (0); +} --- /dev/null +++ src/sys/dev/uart/lirc.h @@ -0,0 +1,182 @@ +/* + * lirc.h - linux infrared remote control header file + * last modified 2010/06/03 by Jarod Wilson + */ + +#ifndef _LINUX_LIRC_H +#define _LINUX_LIRC_H + +#if defined(__linux__) +#include +#include +#elif defined(_NetBSD_) || defined(__FreeBSD__) +#if !_KERNEL +#include +#endif +#elif defined(_CYGWIN_) +#define __USE_LINUX_IOCTL_DEFS +#include +#endif +#ifndef __linux__ +#if _KERNEL +#include +#else +#include +#endif +#define __u32 uint32_t +#define __u64 uint64_t +#endif + +#define PULSE_BIT 0x01000000 +#define PULSE_MASK 0x00FFFFFF + +#define LIRC_MODE2_SPACE 0x00000000 +#define LIRC_MODE2_PULSE 0x01000000 +#define LIRC_MODE2_FREQUENCY 0x02000000 +#define LIRC_MODE2_TIMEOUT 0x03000000 + +#define LIRC_VALUE_MASK 0x00FFFFFF +#define LIRC_MODE2_MASK 0xFF000000 + +#define LIRC_SPACE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_SPACE) +#define LIRC_PULSE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_PULSE) +#define LIRC_FREQUENCY(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_FREQUENCY) +#define LIRC_TIMEOUT(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_TIMEOUT) + +#define LIRC_VALUE(val) ((val)&LIRC_VALUE_MASK) +#define LIRC_MODE2(val) ((val)&LIRC_MODE2_MASK) + +#define LIRC_IS_SPACE(val) (LIRC_MODE2(val) == LIRC_MODE2_SPACE) +#define LIRC_IS_PULSE(val) (LIRC_MODE2(val) == LIRC_MODE2_PULSE) +#define LIRC_IS_FREQUENCY(val) (LIRC_MODE2(val) == LIRC_MODE2_FREQUENCY) +#define LIRC_IS_TIMEOUT(val) (LIRC_MODE2(val) == LIRC_MODE2_TIMEOUT) + +#define lirc_t int + +/*** lirc compatible hardware features ***/ + +#define LIRC_MODE2SEND(x) (x) +#define LIRC_SEND2MODE(x) (x) +#define LIRC_MODE2REC(x) ((x) << 16) +#define LIRC_REC2MODE(x) ((x) >> 16) + +#define LIRC_MODE_RAW 0x00000001 +#define LIRC_MODE_PULSE 0x00000002 +#define LIRC_MODE_MODE2 0x00000004 +#define LIRC_MODE_LIRCCODE 0x00000010 + + +#define LIRC_CAN_SEND_RAW LIRC_MODE2SEND(LIRC_MODE_RAW) +#define LIRC_CAN_SEND_PULSE LIRC_MODE2SEND(LIRC_MODE_PULSE) +#define LIRC_CAN_SEND_MODE2 LIRC_MODE2SEND(LIRC_MODE_MODE2) +#define LIRC_CAN_SEND_LIRCCODE LIRC_MODE2SEND(LIRC_MODE_LIRCCODE) + +#define LIRC_CAN_SEND_MASK 0x0000003f + +#define LIRC_CAN_SET_SEND_CARRIER 0x00000100 +#define LIRC_CAN_SET_SEND_DUTY_CYCLE 0x00000200 +#define LIRC_CAN_SET_TRANSMITTER_MASK 0x00000400 + +#define LIRC_CAN_REC_RAW LIRC_MODE2REC(LIRC_MODE_RAW) +#define LIRC_CAN_REC_PULSE LIRC_MODE2REC(LIRC_MODE_PULSE) +#define LIRC_CAN_REC_MODE2 LIRC_MODE2REC(LIRC_MODE_MODE2) +#define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE) + +#define LIRC_CAN_REC_MASK LIRC_MODE2REC(LIRC_CAN_SEND_MASK) + +#define LIRC_CAN_SET_REC_CARRIER (LIRC_CAN_SET_SEND_CARRIER << 16) +#define LIRC_CAN_SET_REC_DUTY_CYCLE (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16) + +#define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000 +#define LIRC_CAN_SET_REC_CARRIER_RANGE 0x80000000 +#define LIRC_CAN_GET_REC_RESOLUTION 0x20000000 +#define LIRC_CAN_SET_REC_TIMEOUT 0x10000000 +#define LIRC_CAN_SET_REC_FILTER 0x08000000 + +#define LIRC_CAN_MEASURE_CARRIER 0x02000000 + +#define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK) +#define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK) + +#define LIRC_CAN_NOTIFY_DECODE 0x01000000 + +/*** IOCTL commands for lirc driver ***/ + +#define LIRC_GET_FEATURES _IOR('i', 0x00000000, __u32) + +#define LIRC_GET_SEND_MODE _IOR('i', 0x00000001, __u32) +#define LIRC_GET_REC_MODE _IOR('i', 0x00000002, __u32) +#define LIRC_GET_SEND_CARRIER _IOR('i', 0x00000003, __u32) +#define LIRC_GET_REC_CARRIER _IOR('i', 0x00000004, __u32) +#define LIRC_GET_SEND_DUTY_CYCLE _IOR('i', 0x00000005, __u32) +#define LIRC_GET_REC_DUTY_CYCLE _IOR('i', 0x00000006, __u32) +#define LIRC_GET_REC_RESOLUTION _IOR('i', 0x00000007, __u32) + +#define LIRC_GET_MIN_TIMEOUT _IOR('i', 0x00000008, __u32) +#define LIRC_GET_MAX_TIMEOUT _IOR('i', 0x00000009, __u32) + +#define LIRC_GET_MIN_FILTER_PULSE _IOR('i', 0x0000000a, __u32) +#define LIRC_GET_MAX_FILTER_PULSE _IOR('i', 0x0000000b, __u32) +#define LIRC_GET_MIN_FILTER_SPACE _IOR('i', 0x0000000c, __u32) +#define LIRC_GET_MAX_FILTER_SPACE _IOR('i', 0x0000000d, __u32) + +/* code length in bits, currently only for LIRC_MODE_LIRCCODE */ +#define LIRC_GET_LENGTH _IOR('i', 0x0000000f, __u32) + +#define LIRC_SET_SEND_MODE _IOW('i', 0x00000011, __u32) +#define LIRC_SET_REC_MODE _IOW('i', 0x00000012, __u32) +/* Note: these can reset the according pulse_width */ +#define LIRC_SET_SEND_CARRIER _IOW('i', 0x00000013, __u32) +#define LIRC_SET_REC_CARRIER _IOW('i', 0x00000014, __u32) +#define LIRC_SET_SEND_DUTY_CYCLE _IOW('i', 0x00000015, __u32) +#define LIRC_SET_REC_DUTY_CYCLE _IOW('i', 0x00000016, __u32) +#define LIRC_SET_TRANSMITTER_MASK _IOW('i', 0x00000017, __u32) + +/* + * when a timeout != 0 is set the driver will send a + * LIRC_MODE2_TIMEOUT data packet, otherwise LIRC_MODE2_TIMEOUT is + * never sent, timeout is disabled by default + */ +#define LIRC_SET_REC_TIMEOUT _IOW('i', 0x00000018, __u32) + +/* 1 enables, 0 disables timeout reports in MODE2 */ +#define LIRC_SET_REC_TIMEOUT_REPORTS _IOW('i', 0x00000019, __u32) + +/* + * pulses shorter than this are filtered out by hardware (software + * emulation in lirc_dev?) + */ +#define LIRC_SET_REC_FILTER_PULSE _IOW('i', 0x0000001a, __u32) +/* + * spaces shorter than this are filtered out by hardware (software + * emulation in lirc_dev?) + */ +#define LIRC_SET_REC_FILTER_SPACE _IOW('i', 0x0000001b, __u32) +/* + * if filter cannot be set independantly for pulse/space, this should + * be used + */ +#define LIRC_SET_REC_FILTER _IOW('i', 0x0000001c, __u32) + +/* + * if enabled from the next key press on the driver will send + * LIRC_MODE2_FREQUENCY packets + */ +#define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32) + +/* + * to set a range use + * LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE with the + * lower bound first and later + * LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER with the upper bound + */ + +#define LIRC_SET_REC_DUTY_CYCLE_RANGE _IOW('i', 0x0000001e, __u32) +#define LIRC_SET_REC_CARRIER_RANGE _IOW('i', 0x0000001f, __u32) + +#define LIRC_NOTIFY_DECODE _IO('i', 0x00000020) + +#define LIRC_SETUP_START _IO('i', 0x00000021) +#define LIRC_SETUP_END _IO('i', 0x00000022) + +#endif