From: Maxim L. <max...@gm...> - 2009-08-10 01:21:53
|
Hi, This is updated version of my driver. I have cleaned it up a lot (especially overflow handling code) It now reports long gaps correctly. I have added 2 helpers to lirc core to make long gaps reports easy, this I think is shared functionality. This is patch against git tree http://git.wilsonet.com/linux-2.6-lirc.git/ but it should work fine in lirc CVS as well. I will add missing Makefile bits to it and post a patch against lirc CVS as well. (I have fixed small bug in lirc core of this git tree as well) Best regards, Maxim Levitsky |
From: Maxim L. <max...@gm...> - 2009-08-10 22:21:24
|
Hi, This is newer version of my driver for ENE0100 I have put code for long gaps support back to driver, and fixed one stupid bug in this code (it didn't took in account sign of the saved sample) Also added a safety check for sample_period. Hardware can't handle periods less that 5 ms (garbage is received otherwise) And setting it to 0 will cause EC to stall completely (and this can really cause hardware damage....) Few fixes there and there. One importaint note: The hardware seems to truncate the sync pulse, before sending me first interrupt. lirc still works with this truncated signal just fine, but the version of irrecord from CVS doesn't anymore detect my remote correctly (it is JVC protocol based), it thinks it is RC6. thus I have to use enable_idle=0, to make hardware always work. However this results in 80 interrupts/s while lirc is running. Also there is a protocol (I have an universal remote) that consist of very small pulses, separated by long gaps. and has no sync pulse. It isn't detected correctly due to truncation when enable_idle=1 Also, note that this is experimental software, and can cause harm to your system. (It touches critical part of your system, the EC (embedded controller), thus it could make irreversible harm to your system patches against git tree and CVS Best regards, Maxim Levtsky |
From: Maxim L. <max...@gm...> - 2009-08-10 22:22:50
|
Subject: Fix problem with allocating dynamic minors From: Maxim Levitsky <max...@gm...> Signed-off-by: Maxim Levitsky <max...@gm...> --- drivers/input/lirc/lirc_dev.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/input/lirc/lirc_dev.c b/drivers/input/lirc/lirc_dev.c index 0510b4e..d7317c0 100644 --- a/drivers/input/lirc/lirc_dev.c +++ b/drivers/input/lirc/lirc_dev.c @@ -296,6 +296,7 @@ int lirc_register_driver(struct lirc_driver *d) } init_irctl(ir); irctls[minor] = ir; + d->minor = minor; if (d->sample_rate) { ir->jiffies_to_wait = HZ / d->sample_rate; @@ -377,8 +378,8 @@ int lirc_unregister_driver(int minor) if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { printk(KERN_ERR "lirc_dev: lirc_unregister_driver: " - "\"minor\" must be between 0 and %d!\n", - MAX_IRCTL_DEVICES-1); + "\"minor(%d)\" must be between 0 and %d!\n", + minor, MAX_IRCTL_DEVICES-1); return -EBADRQC; } |
From: Maxim L. <max...@gm...> - 2009-08-10 22:24:30
|
Subject: Add driver for ENE KB3924 From: Maxim Levitsky <max...@gm...> This a driver for cir port inside embedded controller found on some aspire notebooks Signed-off-by: Maxim Levitsky <max...@gm...> --- drivers/input/lirc/Kconfig | 7 + drivers/input/lirc/Makefile | 1 drivers/input/lirc/lirc_ene0100.c | 447 +++++++++++++++++++++++++++++++++++++ drivers/input/lirc/lirc_ene0100.h | 97 ++++++++ 4 files changed, 552 insertions(+), 0 deletions(-) create mode 100644 drivers/input/lirc/lirc_ene0100.c create mode 100644 drivers/input/lirc/lirc_ene0100.h diff --git a/drivers/input/lirc/Kconfig b/drivers/input/lirc/Kconfig index 6ef8622..bd9caf0 100644 --- a/drivers/input/lirc/Kconfig +++ b/drivers/input/lirc/Kconfig @@ -109,4 +109,11 @@ config LIRC_ZILOG Driver for the Zilog/Hauppauge IR Transmitter, found on PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards +config LIRC_ENE0100 + tristate "ENE KB3924/ENE0100 CIR Port Reciever" + depends on LIRC_DEV + help + This is a driver for CIR port handled by ENE KB3924 embedded + controller found on some acer aspire notebooks. + It appears on PNP list as ENE0100. endif diff --git a/drivers/input/lirc/Makefile b/drivers/input/lirc/Makefile index 7b1386e..9814dc5 100644 --- a/drivers/input/lirc/Makefile +++ b/drivers/input/lirc/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_LIRC_SIR) += lirc_sir.o obj-$(CONFIG_LIRC_STREAMZAP) += lirc_streamzap.o obj-$(CONFIG_LIRC_TTUSBIR) += lirc_ttusbir.o obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o +obj-$(CONFIG_LIRC_ENE0100) += lirc_ene0100.o diff --git a/drivers/input/lirc/lirc_ene0100.c b/drivers/input/lirc/lirc_ene0100.c new file mode 100644 index 0000000..804702d --- /dev/null +++ b/drivers/input/lirc/lirc_ene0100.c @@ -0,0 +1,447 @@ +/* + * driver for ENE KB3924 CIR (also known as ENE0100) + * + * Copyright (C) 2009 Maxim Levitsky <max...@gm...> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pnp.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include "lirc_ene0100.h" + + +static int sample_period = 50; +static int enable_idle = 1; + +static void ene_set_idle(struct ene_device *dev, int idle); + +/* read a hardware register */ +static u8 ene_hw_read_reg(struct ene_device *dev, u16 reg) +{ + outb(reg >> 8 , dev->hw_io + ENE_ADDR_HI); + outb(reg & 0xFF , dev->hw_io + ENE_ADDR_LO); + return inb(dev->hw_io + ENE_IO); +} + +/* write a hardware register */ +static void ene_hw_write_reg(struct ene_device *dev, u16 reg, u8 value) +{ + outb(reg >> 8 , dev->hw_io + ENE_ADDR_HI); + outb(reg & 0xFF , dev->hw_io + ENE_ADDR_LO); + outb(value, dev->hw_io + ENE_IO); +} + +/* change specific bits in hardware register */ +static void ene_hw_write_reg_mask(struct ene_device *dev, + u16 reg, u8 value, u8 mask) +{ + u8 regvalue; + + outb(reg >> 8 , dev->hw_io + ENE_ADDR_HI); + outb(reg & 0xFF , dev->hw_io + ENE_ADDR_LO); + + regvalue = inb(dev->hw_io + ENE_IO) & ~mask; + regvalue |= (value & mask); + outb(regvalue, dev->hw_io + ENE_IO); +} + + +/* which half of hardware buffer we read now ?*/ +static int hw_get_buf_pointer(struct ene_device *dev) +{ + return 4 * (ene_hw_read_reg(dev, ENE_FW_BUFFER_POINTER) + & ENE_FW_BUFFER_POINTER_HIGH); +} + + +/* read irq status and ack it */ +static int ene_hw_irq_status(struct ene_device *dev) +{ + u8 irq_status = ene_hw_read_reg(dev, ENE_IRQ_STATUS); + + if (!irq_status & ENE_IRQ_STATUS_IR) + return 0; + + ene_hw_write_reg(dev, ENE_IRQ_STATUS, irq_status & ~ENE_IRQ_STATUS_IR); + return 1; +} + + +/* hardware initialization */ +static int ene_hw_init(void *data) +{ + struct ene_device *dev = (struct ene_device *)data; + dev->in_use = 1; + + ene_hw_write_reg(dev, ENE_IRQ, dev->irq << 1); + ene_hw_write_reg(dev, ENE_ADC_UNK2, 0x00); + ene_hw_write_reg(dev, ENE_ADC_SAMPLE_PERIOD, sample_period); + ene_hw_write_reg(dev, ENE_ADC_UNK1, 0x07); + ene_hw_write_reg(dev, ENE_UNK1, 0x01); + ene_hw_write_reg_mask(dev, ENE_FW_SETTINGS, ENE_FW_ENABLE | ENE_FW_IRQ, + ENE_FW_ENABLE | ENE_FW_IRQ); + + /* ack any pending irqs - just in case */ + ene_hw_irq_status(dev); + + /* enter idle mode */ + ene_set_idle(dev, 1); + + /* clear stats */ + dev->sample = 0; + return 0; +} + +/* deinitialization */ +static void ene_hw_deinit(void *data) +{ + struct ene_device *dev = (struct ene_device *)data; + + /* disable hardware IRQ and firmware flag */ + ene_hw_write_reg_mask(dev, ENE_FW_SETTINGS, 0, + ENE_FW_ENABLE | ENE_FW_IRQ); + + ene_set_idle(dev, 1); + dev->in_use = 0; +} + +/* sends current sample to userspace */ +static void send_sample(struct ene_device *dev) +{ + int value = abs(dev->sample) & PULSE_MASK; + + if (dev->sample > 0) + value |= PULSE_BIT; + + if (!lirc_buffer_full(dev->lirc_driver->rbuf)) { + lirc_buffer_write(dev->lirc_driver->rbuf, (void *) &value); + wake_up(&dev->lirc_driver->rbuf->wait_poll); + } + dev->sample = 0; +} + +/* this updates current sample */ +static void update_sample(struct ene_device *dev, int sample) +{ + if (!dev->sample) + dev->sample = sample; + else if (same_sign(dev->sample, sample)) + dev->sample += sample; + else { + send_sample(dev); + dev->sample = sample; + } +} + +/* enable or disable idle mode */ +static void ene_set_idle(struct ene_device *dev, int idle) +{ + struct timeval now; + + ene_hw_write_reg_mask(dev, ENE_ADC_SAMPLE_PERIOD, + idle & enable_idle ? 0 : ENE_ADC_SAMPLE_OVERFLOW, + ENE_ADC_SAMPLE_OVERFLOW); + + dev->idle = idle; + + + /* remember when we have entered the idle mode */ + if (idle) { + do_gettimeofday(&dev->gap_start); + return; + } + + /* send the gap between keypresses now */ + do_gettimeofday(&now); + + if (now.tv_sec - dev->gap_start.tv_sec > 16) + dev->sample = PULSE_MASK; + else + dev->sample -= 1000000ull * (now.tv_sec - dev->gap_start.tv_sec) + + (now.tv_usec - dev->gap_start.tv_usec); + + if (dev->sample > PULSE_MASK) + dev->sample = PULSE_MASK; + send_sample(dev); +} + + +/* interrupt handler */ +static irqreturn_t ene_hw_irq(int irq, void *data) +{ + u16 hw_address; + u8 hw_value; + int i, hw_sample; + int space; + + struct ene_device *dev = (struct ene_device *)data; + + if (!ene_hw_irq_status(dev)) + return IRQ_NONE; + + hw_address = ENE_SAMPLE_BUFFER + hw_get_buf_pointer(dev); + + for (i = 0 ; i < ENE_SAMPLES_SIZE ; i++) { + + hw_value = ene_hw_read_reg(dev, hw_address + i); + space = hw_value & ENE_SAMPLE_LOW_MASK; + hw_value &= ~ENE_SAMPLE_LOW_MASK; + + /* no more data */ + if (!(hw_value)) + break; + + /* calculate hw sample */ + hw_sample = hw_value * sample_period; + + if (space) + hw_sample *= -1; + + /* overflow sample recieved, handle it */ + if (hw_value == ENE_SAMPLE_OVERFLOW) { + + if (dev->idle) + continue; + + if (abs(dev->sample) <= ENE_MAXGAP) + update_sample(dev, hw_sample); + else + ene_set_idle(dev, 1); + + continue; + } + + /* normal first sample recieved*/ + if (dev->idle) { + ene_set_idle(dev, 0); + + /* discard first recieved value, its random since its + the time signal was off before first pulse + if idle mode is enabled, HW does that for us*/ + + if (!enable_idle) + continue; + } + + update_sample(dev, hw_sample); + send_sample(dev); + } + return IRQ_HANDLED; +} + +static int ene_probe(struct pnp_dev *pnp_dev, + const struct pnp_device_id *dev_id) +{ + struct resource *res; + struct ene_device *dev; + struct lirc_driver *lirc_driver; + int error = -ENOMEM; + + dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL); + + if (!dev) + goto err1; + + dev->pnp_dev = pnp_dev; + pnp_set_drvdata(pnp_dev, dev); + + error = -EINVAL; + if (sample_period < 5) { + + printk("sample period must be at least 5 ms, (at least 30" + " recommended)\n"); + + goto err1; + } + + /* validate and read resources */ + error = -ENODEV; + res = pnp_get_resource(pnp_dev, IORESOURCE_IO, 0); + if (!pnp_resource_valid(res)) + goto err2; + + dev->hw_io = res->start; + + if (pnp_resource_len(res) < ENE_MAX_IO) + goto err2; + + + res = pnp_get_resource(pnp_dev, IORESOURCE_IRQ, 0); + if (!pnp_resource_valid(res)) + goto err2; + + dev->irq = res->start; + + /* prepare lirc interface */ + error = -ENOMEM; + lirc_driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); + + if (!lirc_driver) + goto err2; + + dev->lirc_driver = lirc_driver; + + strcpy(lirc_driver->name, DRIVER_NAME); + lirc_driver->minor = -1; + lirc_driver->code_length = sizeof(int) * 8; + lirc_driver->features = LIRC_CAN_REC_MODE2; + lirc_driver->data = dev; + lirc_driver->set_use_inc = ene_hw_init; + lirc_driver->set_use_dec = ene_hw_deinit; + lirc_driver->dev = &pnp_dev->dev; + lirc_driver->owner = THIS_MODULE; + + lirc_driver->rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + + if (!lirc_driver->rbuf) + goto err3; + + if (lirc_buffer_init(lirc_driver->rbuf, + sizeof(int), sizeof(int) * 256)) + goto err4; + + error = -ENODEV; + if (lirc_register_driver(lirc_driver)) + goto err5; + + /* claim the resources */ + error = -EBUSY; + if (!request_region(dev->hw_io, ENE_MAX_IO, DRIVER_NAME)) + goto err6; + + if (request_irq(dev->irq, ene_hw_irq, + IRQF_SHARED, DRIVER_NAME, (void *)dev)) + goto err7; + + + /* check firmware version */ + error = -ENODEV; + if (ene_hw_read_reg(dev, ENE_FW_VERSION) != ENE_FW_VER_SUPP) { + printk(KERN_WARNING + "ENECIR: unsupported firmware found, aborting\n"); + goto err8; + } + + printk(KERN_NOTICE "ENECIR: driver has been succesfully loaded\n"); + return 0; + +err8: + free_irq(dev->irq, dev); +err7: + release_region(dev->hw_io, ENE_MAX_IO); +err6: + lirc_unregister_driver(lirc_driver->minor); +err5: + lirc_buffer_free(lirc_driver->rbuf); +err4: + kfree(lirc_driver->rbuf); +err3: + kfree(lirc_driver); +err2: + kfree(dev); +err1: + return error; +} + + +static void ene_remove(struct pnp_dev *pnp_dev) +{ + struct ene_device *dev = pnp_get_drvdata(pnp_dev); + ene_hw_deinit(dev); + free_irq(dev->irq, dev); + release_region(dev->hw_io, ENE_MAX_IO); + lirc_unregister_driver(dev->lirc_driver->minor); + lirc_buffer_free(dev->lirc_driver->rbuf); + kfree(dev->lirc_driver); + kfree(dev); +} + + +#ifdef CONFIG_PM +static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state) +{ + struct ene_device *dev = pnp_get_drvdata(pnp_dev); + ene_hw_write_reg_mask(dev, ENE_FW_SETTINGS, ENE_FW_WAKE, ENE_FW_WAKE); + return 0; +} + + +static int ene_resume(struct pnp_dev *pnp_dev) +{ + struct ene_device *dev = pnp_get_drvdata(pnp_dev); + if (dev->in_use) + ene_hw_init(dev); + + ene_hw_write_reg_mask(dev, ENE_FW_SETTINGS, 0, ENE_FW_WAKE); + return 0; +} + +#endif + + +static const struct pnp_device_id ene_ids[] = { + { .id = "ENE0100", }, + { }, +}; + +static struct pnp_driver ene_driver = { + .name = DRIVER_NAME, + .id_table = ene_ids, + .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, + + .probe = ene_probe, + .remove = __devexit_p(ene_remove), + +#ifdef CONFIG_PM + .suspend = ene_suspend, + .resume = ene_resume, +#endif +}; + + +static int __init ene_init(void) +{ + return pnp_register_driver(&ene_driver); +} + +static void ene_exit(void) +{ + pnp_unregister_driver(&ene_driver); +} + + +module_param(sample_period, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)"); + + +module_param(enable_idle, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(enable_idle, +"Allow hardware to signal when IR pulse starts, disable if your remote" +"doesn't send a sync pulse"); + + +MODULE_DEVICE_TABLE(pnp, ene_ids); +MODULE_DESCRIPTION("LIRC driver for KB3924/ENE0100 CIR port"); +MODULE_AUTHOR("Maxim Levitsky"); +MODULE_LICENSE("GPL"); + +module_init(ene_init); +module_exit(ene_exit); diff --git a/drivers/input/lirc/lirc_ene0100.h b/drivers/input/lirc/lirc_ene0100.h new file mode 100644 index 0000000..a4c884e --- /dev/null +++ b/drivers/input/lirc/lirc_ene0100.h @@ -0,0 +1,97 @@ +/* + * driver for ENE KB3924 CIR (also known as ENE0100) + * + * Copyright (C) 2009 Maxim Levitsky <max...@gm...> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + +#include "lirc.h" +#include "lirc_dev.h" + +/* hardware address */ +#define ENE_STATUS 0 /* hardware status - unused */ +#define ENE_ADDR_HI 1 /* hi byte of register address */ +#define ENE_ADDR_LO 2 /* low byte of register address */ +#define ENE_IO 3 /* read/write window */ +#define ENE_MAX_IO 3 + + +/* 8 bytes of samples, divided in 2 halfs*/ +#define ENE_SAMPLE_BUFFER 0xF8F0 +#define ENE_SAMPLE_LOW_MASK (1 << 7) +#define ENE_SAMPLE_VALUE_MASK 0x7F +#define ENE_SAMPLE_OVERFLOW 0x7F +#define ENE_SAMPLES_SIZE 4 + + +/* firmware settings */ +#define ENE_FW_SETTINGS 0xF8F8 +#define ENE_FW_ENABLE (1 << 0) /* enable fw processing */ +#define ENE_FW_WAKE (1 << 6) /* enable wake from S3 */ +#define ENE_FW_IRQ (1 << 7) /* enable interrupt */ + + +/* buffer pointer, tells which half of ENE_SAMPLE_BUFFER to read */ +#define ENE_FW_BUFFER_POINTER 0xF8F9 +#define ENE_FW_BUFFER_POINTER_HIGH (1 << 0) + + +/* IRQ registers block */ +#define ENE_IRQ 0xFD09 /* IRQ number */ +#define ENE_UNK1 0xFD17 /* unknown setting = 1 */ +#define ENE_IRQ_STATUS 0xFD80 /* irq status */ +#define ENE_IRQ_STATUS_IR (1 << 5) /* IR irq */ + + +/* ADC settings */ +#define ENE_ADC_UNK1 0xFEC0 /* unknown setting = 7 */ +#define ENE_ADC_UNK2 0xFEC1 /* unknown setting = 0 */ +#define ENE_ADC_SAMPLE_PERIOD 0xFEC8 /* sample period in us */ +#define ENE_ADC_SAMPLE_OVERFLOW (1 << 7) /* interrupt on overflows if*/ + /* set */ + +/* fimware version */ +#define ENE_FW_VERSION 0xFF00 +#define ENE_FW_VER_SUPP 0xC0 + + +#define same_sign(a, b) ((((a) > 0) && (b) > 0) || ((a) < 0 && (b) < 0)) + +#define DRIVER_NAME "enecir" + +#define ENE_MAXGAP 150000 /* this is amount of time */ + /*we wait before turning the */ + /* sampler, chosen arbitry */ + + +struct ene_device { + struct pnp_dev *pnp_dev; + struct lirc_driver *lirc_driver; + + /* hw settings */ + unsigned long hw_io; + int irq; + + /* device data */ + int idle; + int sample; + int in_use; + + struct timeval gap_start; +}; + |
From: Maxim L. <max...@gm...> - 2009-08-10 22:27:56
|
From: Maxim Levitsky <max...@gm...> Date: Tue, 11 Aug 2009 01:14:57 +0300 Subject: [PATCH] add ENE driver --- configure.ac | 12 +- drivers/lirc_ene0100/Makefile.am | 12 + drivers/lirc_ene0100/lirc_ene0100.c | 447 +++++++++++++++++++++++++++++++++++ drivers/lirc_ene0100/lirc_ene0100.h | 98 ++++++++ setup.data | 10 +- 5 files changed, 575 insertions(+), 4 deletions(-) create mode 100644 drivers/lirc_ene0100/Makefile.am create mode 100644 drivers/lirc_ene0100/lirc_ene0100.c create mode 100644 drivers/lirc_ene0100/lirc_ene0100.h diff --git a/configure.ac b/configure.ac index f2c36e9..873083d 100644 --- a/configure.ac +++ b/configure.ac @@ -160,6 +160,7 @@ if test x${no_kernel} != xyes; then (lirc_dev) \ (lirc_dev lirc_atiusb) \ (lirc_dev lirc_bt829) \ + (lirc_dev lirc_ene0100) \ (lirc_dev lirc_gpio) \ (lirc_dev lirc_i2c) \ (lirc_dev lirc_igorplugusb) \ @@ -437,7 +438,7 @@ AC_ARG_WITH(driver, bte, bw6130, caraca, chronos, commandir, comX, cph06x, creative, creative_infracd, devinput, digimatrix, dsp, dvico, ea65, - exaudio, flyvideo, ftdi, gvbctv5pci, + ene0100, exaudio, flyvideo, ftdi, gvbctv5pci, hauppauge, hauppauge_dvb, hercules_smarttv_stereo, i2cuser, igorplugusb, iguanaIR, imon, imon_24g, @@ -587,6 +588,8 @@ if test "$driver" = "userspace" -o "$driver" = "all"; then ;; lirc_dev-lirc_atiusb) ;; + lirc_dev-lirc_ene0100) + ;; lirc_dev-lirc_gpio) #lirc_driver="${lirc_driver} lirc_dev lirc_gpio" ;; @@ -942,6 +945,10 @@ if test "$driver" = "ea65"; then lircd_conf="ea65/lircd.conf.ea65" fi +if test "$driver" = "ene0100"; then + lirc_driver="lirc_dev lirc_ene0100" +fi + if test "$driver" = "exaudio"; then lirc_driver="none" # lircd_conf="creative/lircd.conf.exaudio" @@ -1388,6 +1395,7 @@ if test "$driver" = "wpc8769l"; then lircd_conf="acer/lircd.conf.Aspire_6530G" fi + #END HARDWARE HEURISTIC AC_DEFINE_UNQUOTED(HW_DEFAULT, ${HW_DEFAULT}) @@ -1484,6 +1492,7 @@ elif test "$lirc_driver" = "all"; then lirc_driver="lirc_dev \ lirc_atiusb \ lirc_bt829 \ + lirc_ene0100 \ lirc_gpio \ lirc_i2c \ lirc_igorplugusb \ @@ -1765,6 +1774,7 @@ AC_CONFIG_FILES([ drivers/Makefile drivers/lirc_atiusb/Makefile drivers/lirc_bt829/Makefile + drivers/lirc_ene0100/Makefile drivers/lirc_dev/Makefile drivers/lirc_gpio/Makefile drivers/lirc_i2c/Makefile diff --git a/drivers/lirc_ene0100/Makefile.am b/drivers/lirc_ene0100/Makefile.am new file mode 100644 index 0000000..31b57a3 --- /dev/null +++ b/drivers/lirc_ene0100/Makefile.am @@ -0,0 +1,12 @@ + +## Process this file with automake to produce Makefile.in + +## this is so that Automake includes the C compiling definitions, and +## includes the source files in the distribution. +EXTRA_PROGRAMS = automake_dummy +automake_dummy_SOURCES = lirc_ene0100.c + +## there is no *just* object file support in automake. This is close enough +module_DATA = lirc_ene0100.o + +include ../Makefile.common diff --git a/drivers/lirc_ene0100/lirc_ene0100.c b/drivers/lirc_ene0100/lirc_ene0100.c new file mode 100644 index 0000000..804702d --- /dev/null +++ b/drivers/lirc_ene0100/lirc_ene0100.c @@ -0,0 +1,447 @@ +/* + * driver for ENE KB3924 CIR (also known as ENE0100) + * + * Copyright (C) 2009 Maxim Levitsky <max...@gm...> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pnp.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include "lirc_ene0100.h" + + +static int sample_period = 50; +static int enable_idle = 1; + +static void ene_set_idle(struct ene_device *dev, int idle); + +/* read a hardware register */ +static u8 ene_hw_read_reg(struct ene_device *dev, u16 reg) +{ + outb(reg >> 8 , dev->hw_io + ENE_ADDR_HI); + outb(reg & 0xFF , dev->hw_io + ENE_ADDR_LO); + return inb(dev->hw_io + ENE_IO); +} + +/* write a hardware register */ +static void ene_hw_write_reg(struct ene_device *dev, u16 reg, u8 value) +{ + outb(reg >> 8 , dev->hw_io + ENE_ADDR_HI); + outb(reg & 0xFF , dev->hw_io + ENE_ADDR_LO); + outb(value, dev->hw_io + ENE_IO); +} + +/* change specific bits in hardware register */ +static void ene_hw_write_reg_mask(struct ene_device *dev, + u16 reg, u8 value, u8 mask) +{ + u8 regvalue; + + outb(reg >> 8 , dev->hw_io + ENE_ADDR_HI); + outb(reg & 0xFF , dev->hw_io + ENE_ADDR_LO); + + regvalue = inb(dev->hw_io + ENE_IO) & ~mask; + regvalue |= (value & mask); + outb(regvalue, dev->hw_io + ENE_IO); +} + + +/* which half of hardware buffer we read now ?*/ +static int hw_get_buf_pointer(struct ene_device *dev) +{ + return 4 * (ene_hw_read_reg(dev, ENE_FW_BUFFER_POINTER) + & ENE_FW_BUFFER_POINTER_HIGH); +} + + +/* read irq status and ack it */ +static int ene_hw_irq_status(struct ene_device *dev) +{ + u8 irq_status = ene_hw_read_reg(dev, ENE_IRQ_STATUS); + + if (!irq_status & ENE_IRQ_STATUS_IR) + return 0; + + ene_hw_write_reg(dev, ENE_IRQ_STATUS, irq_status & ~ENE_IRQ_STATUS_IR); + return 1; +} + + +/* hardware initialization */ +static int ene_hw_init(void *data) +{ + struct ene_device *dev = (struct ene_device *)data; + dev->in_use = 1; + + ene_hw_write_reg(dev, ENE_IRQ, dev->irq << 1); + ene_hw_write_reg(dev, ENE_ADC_UNK2, 0x00); + ene_hw_write_reg(dev, ENE_ADC_SAMPLE_PERIOD, sample_period); + ene_hw_write_reg(dev, ENE_ADC_UNK1, 0x07); + ene_hw_write_reg(dev, ENE_UNK1, 0x01); + ene_hw_write_reg_mask(dev, ENE_FW_SETTINGS, ENE_FW_ENABLE | ENE_FW_IRQ, + ENE_FW_ENABLE | ENE_FW_IRQ); + + /* ack any pending irqs - just in case */ + ene_hw_irq_status(dev); + + /* enter idle mode */ + ene_set_idle(dev, 1); + + /* clear stats */ + dev->sample = 0; + return 0; +} + +/* deinitialization */ +static void ene_hw_deinit(void *data) +{ + struct ene_device *dev = (struct ene_device *)data; + + /* disable hardware IRQ and firmware flag */ + ene_hw_write_reg_mask(dev, ENE_FW_SETTINGS, 0, + ENE_FW_ENABLE | ENE_FW_IRQ); + + ene_set_idle(dev, 1); + dev->in_use = 0; +} + +/* sends current sample to userspace */ +static void send_sample(struct ene_device *dev) +{ + int value = abs(dev->sample) & PULSE_MASK; + + if (dev->sample > 0) + value |= PULSE_BIT; + + if (!lirc_buffer_full(dev->lirc_driver->rbuf)) { + lirc_buffer_write(dev->lirc_driver->rbuf, (void *) &value); + wake_up(&dev->lirc_driver->rbuf->wait_poll); + } + dev->sample = 0; +} + +/* this updates current sample */ +static void update_sample(struct ene_device *dev, int sample) +{ + if (!dev->sample) + dev->sample = sample; + else if (same_sign(dev->sample, sample)) + dev->sample += sample; + else { + send_sample(dev); + dev->sample = sample; + } +} + +/* enable or disable idle mode */ +static void ene_set_idle(struct ene_device *dev, int idle) +{ + struct timeval now; + + ene_hw_write_reg_mask(dev, ENE_ADC_SAMPLE_PERIOD, + idle & enable_idle ? 0 : ENE_ADC_SAMPLE_OVERFLOW, + ENE_ADC_SAMPLE_OVERFLOW); + + dev->idle = idle; + + + /* remember when we have entered the idle mode */ + if (idle) { + do_gettimeofday(&dev->gap_start); + return; + } + + /* send the gap between keypresses now */ + do_gettimeofday(&now); + + if (now.tv_sec - dev->gap_start.tv_sec > 16) + dev->sample = PULSE_MASK; + else + dev->sample -= 1000000ull * (now.tv_sec - dev->gap_start.tv_sec) + + (now.tv_usec - dev->gap_start.tv_usec); + + if (dev->sample > PULSE_MASK) + dev->sample = PULSE_MASK; + send_sample(dev); +} + + +/* interrupt handler */ +static irqreturn_t ene_hw_irq(int irq, void *data) +{ + u16 hw_address; + u8 hw_value; + int i, hw_sample; + int space; + + struct ene_device *dev = (struct ene_device *)data; + + if (!ene_hw_irq_status(dev)) + return IRQ_NONE; + + hw_address = ENE_SAMPLE_BUFFER + hw_get_buf_pointer(dev); + + for (i = 0 ; i < ENE_SAMPLES_SIZE ; i++) { + + hw_value = ene_hw_read_reg(dev, hw_address + i); + space = hw_value & ENE_SAMPLE_LOW_MASK; + hw_value &= ~ENE_SAMPLE_LOW_MASK; + + /* no more data */ + if (!(hw_value)) + break; + + /* calculate hw sample */ + hw_sample = hw_value * sample_period; + + if (space) + hw_sample *= -1; + + /* overflow sample recieved, handle it */ + if (hw_value == ENE_SAMPLE_OVERFLOW) { + + if (dev->idle) + continue; + + if (abs(dev->sample) <= ENE_MAXGAP) + update_sample(dev, hw_sample); + else + ene_set_idle(dev, 1); + + continue; + } + + /* normal first sample recieved*/ + if (dev->idle) { + ene_set_idle(dev, 0); + + /* discard first recieved value, its random since its + the time signal was off before first pulse + if idle mode is enabled, HW does that for us*/ + + if (!enable_idle) + continue; + } + + update_sample(dev, hw_sample); + send_sample(dev); + } + return IRQ_HANDLED; +} + +static int ene_probe(struct pnp_dev *pnp_dev, + const struct pnp_device_id *dev_id) +{ + struct resource *res; + struct ene_device *dev; + struct lirc_driver *lirc_driver; + int error = -ENOMEM; + + dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL); + + if (!dev) + goto err1; + + dev->pnp_dev = pnp_dev; + pnp_set_drvdata(pnp_dev, dev); + + error = -EINVAL; + if (sample_period < 5) { + + printk("sample period must be at least 5 ms, (at least 30" + " recommended)\n"); + + goto err1; + } + + /* validate and read resources */ + error = -ENODEV; + res = pnp_get_resource(pnp_dev, IORESOURCE_IO, 0); + if (!pnp_resource_valid(res)) + goto err2; + + dev->hw_io = res->start; + + if (pnp_resource_len(res) < ENE_MAX_IO) + goto err2; + + + res = pnp_get_resource(pnp_dev, IORESOURCE_IRQ, 0); + if (!pnp_resource_valid(res)) + goto err2; + + dev->irq = res->start; + + /* prepare lirc interface */ + error = -ENOMEM; + lirc_driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); + + if (!lirc_driver) + goto err2; + + dev->lirc_driver = lirc_driver; + + strcpy(lirc_driver->name, DRIVER_NAME); + lirc_driver->minor = -1; + lirc_driver->code_length = sizeof(int) * 8; + lirc_driver->features = LIRC_CAN_REC_MODE2; + lirc_driver->data = dev; + lirc_driver->set_use_inc = ene_hw_init; + lirc_driver->set_use_dec = ene_hw_deinit; + lirc_driver->dev = &pnp_dev->dev; + lirc_driver->owner = THIS_MODULE; + + lirc_driver->rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + + if (!lirc_driver->rbuf) + goto err3; + + if (lirc_buffer_init(lirc_driver->rbuf, + sizeof(int), sizeof(int) * 256)) + goto err4; + + error = -ENODEV; + if (lirc_register_driver(lirc_driver)) + goto err5; + + /* claim the resources */ + error = -EBUSY; + if (!request_region(dev->hw_io, ENE_MAX_IO, DRIVER_NAME)) + goto err6; + + if (request_irq(dev->irq, ene_hw_irq, + IRQF_SHARED, DRIVER_NAME, (void *)dev)) + goto err7; + + + /* check firmware version */ + error = -ENODEV; + if (ene_hw_read_reg(dev, ENE_FW_VERSION) != ENE_FW_VER_SUPP) { + printk(KERN_WARNING + "ENECIR: unsupported firmware found, aborting\n"); + goto err8; + } + + printk(KERN_NOTICE "ENECIR: driver has been succesfully loaded\n"); + return 0; + +err8: + free_irq(dev->irq, dev); +err7: + release_region(dev->hw_io, ENE_MAX_IO); +err6: + lirc_unregister_driver(lirc_driver->minor); +err5: + lirc_buffer_free(lirc_driver->rbuf); +err4: + kfree(lirc_driver->rbuf); +err3: + kfree(lirc_driver); +err2: + kfree(dev); +err1: + return error; +} + + +static void ene_remove(struct pnp_dev *pnp_dev) +{ + struct ene_device *dev = pnp_get_drvdata(pnp_dev); + ene_hw_deinit(dev); + free_irq(dev->irq, dev); + release_region(dev->hw_io, ENE_MAX_IO); + lirc_unregister_driver(dev->lirc_driver->minor); + lirc_buffer_free(dev->lirc_driver->rbuf); + kfree(dev->lirc_driver); + kfree(dev); +} + + +#ifdef CONFIG_PM +static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state) +{ + struct ene_device *dev = pnp_get_drvdata(pnp_dev); + ene_hw_write_reg_mask(dev, ENE_FW_SETTINGS, ENE_FW_WAKE, ENE_FW_WAKE); + return 0; +} + + +static int ene_resume(struct pnp_dev *pnp_dev) +{ + struct ene_device *dev = pnp_get_drvdata(pnp_dev); + if (dev->in_use) + ene_hw_init(dev); + + ene_hw_write_reg_mask(dev, ENE_FW_SETTINGS, 0, ENE_FW_WAKE); + return 0; +} + +#endif + + +static const struct pnp_device_id ene_ids[] = { + { .id = "ENE0100", }, + { }, +}; + +static struct pnp_driver ene_driver = { + .name = DRIVER_NAME, + .id_table = ene_ids, + .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, + + .probe = ene_probe, + .remove = __devexit_p(ene_remove), + +#ifdef CONFIG_PM + .suspend = ene_suspend, + .resume = ene_resume, +#endif +}; + + +static int __init ene_init(void) +{ + return pnp_register_driver(&ene_driver); +} + +static void ene_exit(void) +{ + pnp_unregister_driver(&ene_driver); +} + + +module_param(sample_period, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)"); + + +module_param(enable_idle, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(enable_idle, +"Allow hardware to signal when IR pulse starts, disable if your remote" +"doesn't send a sync pulse"); + + +MODULE_DEVICE_TABLE(pnp, ene_ids); +MODULE_DESCRIPTION("LIRC driver for KB3924/ENE0100 CIR port"); +MODULE_AUTHOR("Maxim Levitsky"); +MODULE_LICENSE("GPL"); + +module_init(ene_init); +module_exit(ene_exit); diff --git a/drivers/lirc_ene0100/lirc_ene0100.h b/drivers/lirc_ene0100/lirc_ene0100.h new file mode 100644 index 0000000..09f037c --- /dev/null +++ b/drivers/lirc_ene0100/lirc_ene0100.h @@ -0,0 +1,98 @@ +/* + * driver for ENE KB3924 CIR (also known as ENE0100) + * + * Copyright (C) 2009 Maxim Levitsky <max...@gm...> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "drivers/kcompat.h" +#include "drivers/lirc.h" +#include "drivers/lirc_dev/lirc_dev.h" + + +/* hardware address */ +#define ENE_STATUS 0 /* hardware status - unused */ +#define ENE_ADDR_HI 1 /* hi byte of register address */ +#define ENE_ADDR_LO 2 /* low byte of register address */ +#define ENE_IO 3 /* read/write window */ +#define ENE_MAX_IO 3 + + +/* 8 bytes of samples, divided in 2 halfs*/ +#define ENE_SAMPLE_BUFFER 0xF8F0 +#define ENE_SAMPLE_LOW_MASK (1 << 7) +#define ENE_SAMPLE_VALUE_MASK 0x7F +#define ENE_SAMPLE_OVERFLOW 0x7F +#define ENE_SAMPLES_SIZE 4 + + +/* firmware settings */ +#define ENE_FW_SETTINGS 0xF8F8 +#define ENE_FW_ENABLE (1 << 0) /* enable fw processing */ +#define ENE_FW_WAKE (1 << 6) /* enable wake from S3 */ +#define ENE_FW_IRQ (1 << 7) /* enable interrupt */ + + +/* buffer pointer, tells which half of ENE_SAMPLE_BUFFER to read */ +#define ENE_FW_BUFFER_POINTER 0xF8F9 +#define ENE_FW_BUFFER_POINTER_HIGH (1 << 0) + + +/* IRQ registers block */ +#define ENE_IRQ 0xFD09 /* IRQ number */ +#define ENE_UNK1 0xFD17 /* unknown setting = 1 */ +#define ENE_IRQ_STATUS 0xFD80 /* irq status */ +#define ENE_IRQ_STATUS_IR (1 << 5) /* IR irq */ + + +/* ADC settings */ +#define ENE_ADC_UNK1 0xFEC0 /* unknown setting = 7 */ +#define ENE_ADC_UNK2 0xFEC1 /* unknown setting = 0 */ +#define ENE_ADC_SAMPLE_PERIOD 0xFEC8 /* sample period in us */ +#define ENE_ADC_SAMPLE_OVERFLOW (1 << 7) /* interrupt on overflows if*/ + /* set */ + +/* fimware version */ +#define ENE_FW_VERSION 0xFF00 +#define ENE_FW_VER_SUPP 0xC0 + + +#define same_sign(a, b) ((((a) > 0) && (b) > 0) || ((a) < 0 && (b) < 0)) + +#define DRIVER_NAME "enecir" + +#define ENE_MAXGAP 150000 /* this is amount of time */ + /*we wait before turning the */ + /* sampler, chosen arbitry */ + + +struct ene_device { + struct pnp_dev *pnp_dev; + struct lirc_driver *lirc_driver; + + /* hw settings */ + unsigned long hw_io; + int irq; + + /* device data */ + int idle; + int sample; + int in_use; + + struct timeval gap_start; +}; + diff --git a/setup.data b/setup.data index 2b8fa1e..898ee22 100644 --- a/setup.data +++ b/setup.data @@ -106,6 +106,7 @@ hw_menu_entry: @hw-irda digimatrix: "Asus Digimatrix IT87xx CIR port" act200l: "Actisys Act200L SIR driver support" act220l: "Actisys Act220L(+) SIR driver support" + ene0100: "ENE KB3924/ENE0100 CIR port (e.g. Acer Aspire 5720G)" wpc8769l: "Winbond 8769L CIR port (e.g. Acer Aspire 6530G)" hw_menu_entry: @hw-pda @@ -260,7 +261,8 @@ param_type: \ ttusbir \ tvbox \ udp \ - wpc8769l + wpc8769l \ + ene0100 none: default_param: \ @@ -331,7 +333,8 @@ default_param: \ ttusbir \ tvbox \ udp \ - wpc8769l + wpc8769l \ + ene0100 none: default_param: \ @@ -427,7 +430,8 @@ remote: \ uirt2_raw \ udp \ usb_uirt_raw \ - wpc8769l + wpc8769l \ + ene0100 any: remote: \ -- 1.6.0.4 |
From: <li...@ba...> - 2009-08-11 21:01:48
|
Hi Maxim, on 11 Aug 09 at 01:27, Maxim Levitsky wrote: > From: Maxim Levitsky <max...@gm...> > Date: Tue, 11 Aug 2009 01:14:57 +0300 > Subject: [PATCH] add ENE driver Applied with minor changes. Which kernel version have you tested this with? Christoph |
From: Maxim L. <max...@gm...> - 2009-08-11 21:52:27
|
On Tue, 2009-08-11 at 22:14 +0100, Howard Betsworth wrote: > ------------------------------------------------------------------------------ > Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day > trial. Simplify your report design, integration and deployment - and focus on > what you do best, core application coding. Discover what's new with > Crystal Reports now. http://p.sf.net/sfu/bobj-july What is this? Regards, Maxim Levitsky |
From: Maxim L. <max...@gm...> - 2009-08-11 21:57:14
|
On Tue, 2009-08-11 at 23:01 +0200, Christoph Bartelmus wrote: > Hi Maxim, > > on 11 Aug 09 at 01:27, Maxim Levitsky wrote: > > From: Maxim Levitsky <max...@gm...> > > Date: Tue, 11 Aug 2009 01:14:57 +0300 > > Subject: [PATCH] add ENE driver > > Applied with minor changes. Which kernel version have you tested this > with? Thanks! I use more or less git head of vanilla kernel. More correctly I run here a wireless-testing git tree, git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git f1aa58f92c1dfd16c4a0dbeb4c5fc7e797b5a4dd It is based on 2.6.35-rc5 Best regards, Maxim Levitsky > > Christoph > > ------------------------------------------------------------------------------ > Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day > trial. Simplify your report design, integration and deployment - and focus on > what you do best, core application coding. Discover what's new with > Crystal Reports now. http://p.sf.net/sfu/bobj-july |
From: Maxim L. <max...@gm...> - 2009-08-11 21:58:50
|
On Wed, 2009-08-12 at 00:56 +0300, Maxim Levitsky wrote: > On Tue, 2009-08-11 at 23:01 +0200, Christoph Bartelmus wrote: > > Hi Maxim, > > > > on 11 Aug 09 at 01:27, Maxim Levitsky wrote: > > > From: Maxim Levitsky <max...@gm...> > > > Date: Tue, 11 Aug 2009 01:14:57 +0300 > > > Subject: [PATCH] add ENE driver > > > > Applied with minor changes. Which kernel version have you tested this > > with? > > Thanks! > > I use more or less git head of vanilla kernel. > More correctly I run here a wireless-testing git tree, > > git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git > f1aa58f92c1dfd16c4a0dbeb4c5fc7e797b5a4dd > > It is based on 2.6.35-rc5 :-) 2.6.31-rc5 > > Best regards, > Maxim Levitsky > > > > > > > Christoph > > > > ------------------------------------------------------------------------------ > > Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day > > trial. Simplify your report design, integration and deployment - and focus on > > what you do best, core application coding. Discover what's new with > > Crystal Reports now. http://p.sf.net/sfu/bobj-july > |
From: Maxim L. <max...@gm...> - 2009-08-11 23:51:19
|
Hi, This is small incremental patch for few issues I found in my driver. First, another update for long gap handling. I treat internally spaces as negative numbers, and pulses as positive numbers, but I failed to do so properly in ene_set_idle, I did fix it more or less by replacing += with -=, but it is still incorrect, so here it (I hope) correct version Then, I remove user access from sample_period, as I can't check if it is correct (or I don't know how to do so) And, after thinking a lot about how to handle the fact that device truncates first sync pulse, I came to nice conclusion: I bump the idle timeout to 5 seconds. This on one hand will still ensure that system isn't loaded with useless interrupts (5 seconds of 80 ints/sec isn't that much right?), but on the other hand fix all irrecord problems, since only first button press will be truncated (I assume that users won't have enough patience to wait 5 seconds between a keypress and next one) Best regards, Maxim Levitsky PS: do you have a clue about this 'help' message ? It doesn't appear to be spam, but it is very strange --- >From 394fafe04e3bb81fe51c0756fece7dcd352f149c Mon Sep 17 00:00:00 2001 From: Maxim Levitsky <max...@gm...> Date: Wed, 12 Aug 2009 02:16:57 +0300 Subject: [PATCH] Few fixes to me ENE driver --- drivers/lirc_ene0100/lirc_ene0100.c | 15 ++++++++------- drivers/lirc_ene0100/lirc_ene0100.h | 4 +++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/lirc_ene0100/lirc_ene0100.c b/drivers/lirc_ene0100/lirc_ene0100.c index a41383f..5fdbaba 100644 --- a/drivers/lirc_ene0100/lirc_ene0100.c +++ b/drivers/lirc_ene0100/lirc_ene0100.c @@ -176,13 +176,14 @@ static void ene_set_idle(struct ene_device *dev, int idle) do_gettimeofday(&now); if (now.tv_sec - dev->gap_start.tv_sec > 16) - dev->sample = PULSE_MASK; + dev->sample = space(PULSE_MASK); else - dev->sample -= 1000000ull * (now.tv_sec - dev->gap_start.tv_sec) - + (now.tv_usec - dev->gap_start.tv_usec); + dev->sample = dev->sample + + space(1000000ull * (now.tv_sec - dev->gap_start.tv_sec)) + + space(now.tv_usec - dev->gap_start.tv_usec); - if (dev->sample > PULSE_MASK) - dev->sample = PULSE_MASK; + if (abs(dev->sample) > PULSE_MASK) + dev->sample = space(PULSE_MASK); send_sample(dev); } @@ -228,7 +229,7 @@ static irqreturn_t ene_hw_irq(int irq, void *data, struct pt_regs *regs) if (dev->idle) continue; - if (abs(dev->sample) <= ENE_MAXGAP) + if (dev->sample > 0 || abs(dev->sample) <= ENE_MAXGAP) update_sample(dev, hw_sample); else ene_set_idle(dev, 1); @@ -437,7 +438,7 @@ static void ene_exit(void) } -module_param(sample_period, int, S_IRUGO | S_IWUSR); +module_param(sample_period, int, S_IRUGO); MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)"); diff --git a/drivers/lirc_ene0100/lirc_ene0100.h b/drivers/lirc_ene0100/lirc_ene0100.h index b6b40d7..e5784e5 100644 --- a/drivers/lirc_ene0100/lirc_ene0100.h +++ b/drivers/lirc_ene0100/lirc_ene0100.h @@ -75,12 +75,14 @@ #define ENE_DRIVER_NAME "enecir" -#define ENE_MAXGAP 150000 /* this is amount of +#define ENE_MAXGAP 5000000 /* this is amount of time we wait before turning the sampler, chosen arbitry */ +#define space(len) (-(len)) /* add a space */ + struct ene_device { struct pnp_dev *pnp_dev; -- 1.6.0.4 |
From: Maxim L. <max...@gm...> - 2009-08-14 15:44:56
|
On Wed, 2009-08-12 at 02:51 +0300, Maxim Levitsky wrote: > Hi, > This is small incremental patch for few issues I found in my driver. > > First, another update for long gap handling. I treat internally spaces > as negative numbers, and pulses as positive numbers, but I failed to do > so properly in ene_set_idle, I did fix it more or less by replacing += > with -=, but it is still incorrect, so here it (I hope) correct version > > Then, I remove user access from sample_period, as I can't check if it is > correct (or I don't know how to do so) > > And, after thinking a lot about how to handle the fact that device > truncates first sync pulse, I came to nice conclusion: > I bump the idle timeout to 5 seconds. This on one hand will still ensure > that system isn't loaded with useless interrupts (5 seconds of 80 > ints/sec isn't that much right?), but on the other hand fix all irrecord > problems, since only first button press will be truncated (I assume that > users won't have enough patience to wait 5 seconds between a keypress > and next one) > > Best regards, > Maxim Levitsky Could you give me a word or two about this patch? > > > PS: do you have a clue about this 'help' message ? > It doesn't appear to be spam, but it is very strange > > > --- > > >From 394fafe04e3bb81fe51c0756fece7dcd352f149c Mon Sep 17 00:00:00 2001 > From: Maxim Levitsky <max...@gm...> > Date: Wed, 12 Aug 2009 02:16:57 +0300 > Subject: [PATCH] Few fixes to me ENE driver > > --- > drivers/lirc_ene0100/lirc_ene0100.c | 15 ++++++++------- > drivers/lirc_ene0100/lirc_ene0100.h | 4 +++- > 2 files changed, 11 insertions(+), 8 deletions(-) > > diff --git a/drivers/lirc_ene0100/lirc_ene0100.c b/drivers/lirc_ene0100/lirc_ene0100.c > index a41383f..5fdbaba 100644 > --- a/drivers/lirc_ene0100/lirc_ene0100.c > +++ b/drivers/lirc_ene0100/lirc_ene0100.c > @@ -176,13 +176,14 @@ static void ene_set_idle(struct ene_device *dev, int idle) > do_gettimeofday(&now); > > if (now.tv_sec - dev->gap_start.tv_sec > 16) > - dev->sample = PULSE_MASK; > + dev->sample = space(PULSE_MASK); > else > - dev->sample -= 1000000ull * (now.tv_sec - dev->gap_start.tv_sec) > - + (now.tv_usec - dev->gap_start.tv_usec); > + dev->sample = dev->sample + > + space(1000000ull * (now.tv_sec - dev->gap_start.tv_sec)) > + + space(now.tv_usec - dev->gap_start.tv_usec); > > - if (dev->sample > PULSE_MASK) > - dev->sample = PULSE_MASK; > + if (abs(dev->sample) > PULSE_MASK) > + dev->sample = space(PULSE_MASK); > send_sample(dev); > } > > @@ -228,7 +229,7 @@ static irqreturn_t ene_hw_irq(int irq, void *data, struct pt_regs *regs) > if (dev->idle) > continue; > > - if (abs(dev->sample) <= ENE_MAXGAP) > + if (dev->sample > 0 || abs(dev->sample) <= ENE_MAXGAP) > update_sample(dev, hw_sample); > else > ene_set_idle(dev, 1); > @@ -437,7 +438,7 @@ static void ene_exit(void) > } > > > -module_param(sample_period, int, S_IRUGO | S_IWUSR); > +module_param(sample_period, int, S_IRUGO); > MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)"); > > > diff --git a/drivers/lirc_ene0100/lirc_ene0100.h b/drivers/lirc_ene0100/lirc_ene0100.h > index b6b40d7..e5784e5 100644 > --- a/drivers/lirc_ene0100/lirc_ene0100.h > +++ b/drivers/lirc_ene0100/lirc_ene0100.h > @@ -75,12 +75,14 @@ > > #define ENE_DRIVER_NAME "enecir" > > -#define ENE_MAXGAP 150000 /* this is amount of > +#define ENE_MAXGAP 5000000 /* this is amount of > time we wait before > turning the > sampler, chosen > arbitry */ > > +#define space(len) (-(len)) /* add a space */ > + > > struct ene_device { > struct pnp_dev *pnp_dev; |
From: <li...@ba...> - 2009-08-15 16:51:49
|
Hi! Maxim Levitsky "max...@gm..." wrote: [...] > Then, I remove user access from sample_period, as I can't check if it is > correct (or I don't know how to do so) Then you should remove the module_param althogether. Or is there a reason to have a read-only module parameter? > And, after thinking a lot about how to handle the fact that device > truncates first sync pulse, I came to nice conclusion: In which way is the first sync pulse truncated? How does it look like if you have been in idle mode and how does it look like when you have not been in idle mode? Is there a chance that you can compensate for the difference automatically? > I bump the idle timeout to 5 seconds. This on one hand will still ensure > that system isn't loaded with useless interrupts (5 seconds of 80 > ints/sec isn't that much right?), but on the other hand fix all irrecord > problems, since only first button press will be truncated (I assume that > users won't have enough patience to wait 5 seconds between a keypress > and next one) Making such assumptions is not a good idea. Your code should always work. Christoph |
From: Maxim L. <max...@gm...> - 2009-08-15 22:10:32
|
On Sat, 2009-08-15 at 18:19 +0200, Christoph Bartelmus wrote: > Hi! > > Maxim Levitsky "max...@gm..." wrote: > [...] > > Then, I remove user access from sample_period, as I can't check if it is > > correct (or I don't know how to do so) > > Then you should remove the module_param althogether. Or is there a reason > to have a read-only module parameter? It isn't readonly It can be set by modprobe lirc_ene0100 sample_period=30 I don't want it to be set later, through /sys/module interface, because then I have no way to know what was set. I can check this through, when I sent it to hardware. I probably do that on second thought. > > > And, after thinking a lot about how to handle the fact that device > > truncates first sync pulse, I came to nice conclusion: > > In which way is the first sync pulse truncated? > How does it look like if you have been in idle mode and how does it look > like when you have not been in idle mode? > Is there a chance that you can compensate for the difference > automatically? Nope, here is a dump of mode2 (only a beginning of pulse, to make it shorter, this is JVC protocol, 50 us sample period) 600 1550 600 1550 600 450 600 450 600 450 600 450 600 1550 600 450 600 450 600 450 600 1550 600 1550 600 450 600 450 600 450 ................................................ 8850 4350 550 1600 550 1600 550 500 550 500 550 500 550 500 550 1600 550 500 550 500 550 500 550 1600 550 1600 550 500 550 500 550 500 550 500 550 24750 600 1600 550 1600 550 500 ................................................ If I were to compensate, I would need to know what protocol is used. I can insert dummy 8000 4000, but it won't be correct for all protocols. > > > I bump the idle timeout to 5 seconds. This on one hand will still ensure > > that system isn't loaded with useless interrupts (5 seconds of 80 > > ints/sec isn't that much right?), but on the other hand fix all irrecord > > problems, since only first button press will be truncated (I assume that > > users won't have enough patience to wait 5 seconds between a keypress > > and next one) > > Making such assumptions is not a good idea. Your code should always work. Well, its better that running it always on. Pretty much it does work always. lirc is smart enough, to detect pulses without sync. It is the irrectord that sometimes doesn't work. Best regards, Maxim Levitsky > > Christoph > > ------------------------------------------------------------------------------ > Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day > trial. Simplify your report design, integration and deployment - and focus on > what you do best, core application coding. Discover what's new with > Crystal Reports now. http://p.sf.net/sfu/bobj-july |
From: Maxim L. <max...@gm...> - 2009-08-15 23:18:21
|
From: Maxim Levitsky <max...@gm...> Date: Sun, 16 Aug 2009 02:11:45 +0300 Subject: [PATCH] Few fixes to ENE0100 driver * Update for long gap handling, treats spaces correctly now * Remove ability to runtime set the sample period, won't work properly if device is opened, and dangerous due to missing checks * Bump default idle timeout to 5 sec, to mitigate idle sync truncation * Check for correct sample period on module load --- drivers/lirc_ene0100/lirc_ene0100.c | 29 ++++++++++++++--------------- drivers/lirc_ene0100/lirc_ene0100.h | 4 +++- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/lirc_ene0100/lirc_ene0100.c b/drivers/lirc_ene0100/lirc_ene0100.c index a41383f..79739f4 100644 --- a/drivers/lirc_ene0100/lirc_ene0100.c +++ b/drivers/lirc_ene0100/lirc_ene0100.c @@ -176,13 +176,14 @@ static void ene_set_idle(struct ene_device *dev, int idle) do_gettimeofday(&now); if (now.tv_sec - dev->gap_start.tv_sec > 16) - dev->sample = PULSE_MASK; + dev->sample = space(PULSE_MASK); else - dev->sample -= 1000000ull * (now.tv_sec - dev->gap_start.tv_sec) - + (now.tv_usec - dev->gap_start.tv_usec); + dev->sample = dev->sample + + space(1000000ull * (now.tv_sec - dev->gap_start.tv_sec)) + + space(now.tv_usec - dev->gap_start.tv_usec); - if (dev->sample > PULSE_MASK) - dev->sample = PULSE_MASK; + if (abs(dev->sample) > PULSE_MASK) + dev->sample = space(PULSE_MASK); send_sample(dev); } @@ -228,7 +229,7 @@ static irqreturn_t ene_hw_irq(int irq, void *data, struct pt_regs *regs) if (dev->idle) continue; - if (abs(dev->sample) <= ENE_MAXGAP) + if (dev->sample > 0 || abs(dev->sample) <= ENE_MAXGAP) update_sample(dev, hw_sample); else ene_set_idle(dev, 1); @@ -271,14 +272,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, dev->pnp_dev = pnp_dev; pnp_set_drvdata(pnp_dev, dev); - error = -EINVAL; - if (sample_period < 5) { - - printk(KERN_ERR ENE_DRIVER_NAME ": sample period must be at " - "least 5 ms, (at least 30 recommended)\n"); - - goto err1; - } /* validate and read resources */ error = -ENODEV; @@ -428,6 +421,12 @@ static struct pnp_driver ene_driver = { static int __init ene_init(void) { + if (sample_period < 5) { + printk(KERN_ERR ENE_DRIVER_NAME ": sample period must be at " + "least 5 ms, (at least 30 recommended)\n"); + return -EINVAL; + } + return pnp_register_driver(&ene_driver); } @@ -437,7 +436,7 @@ static void ene_exit(void) } -module_param(sample_period, int, S_IRUGO | S_IWUSR); +module_param(sample_period, int, S_IRUGO); MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)"); diff --git a/drivers/lirc_ene0100/lirc_ene0100.h b/drivers/lirc_ene0100/lirc_ene0100.h index b6b40d7..e5784e5 100644 --- a/drivers/lirc_ene0100/lirc_ene0100.h +++ b/drivers/lirc_ene0100/lirc_ene0100.h @@ -75,12 +75,14 @@ #define ENE_DRIVER_NAME "enecir" -#define ENE_MAXGAP 150000 /* this is amount of +#define ENE_MAXGAP 5000000 /* this is amount of time we wait before turning the sampler, chosen arbitry */ +#define space(len) (-(len)) /* add a space */ + struct ene_device { struct pnp_dev *pnp_dev; -- 1.6.0.4 |
From: <li...@ba...> - 2009-08-16 08:40:37
|
Hi! Maxim Levitsky "max...@gm..." wrote: [...] >>> And, after thinking a lot about how to handle the fact that device >>> truncates first sync pulse, I came to nice conclusion: >> >> In which way is the first sync pulse truncated? >> How does it look like if you have been in idle mode and how does it look >> like when you have not been in idle mode? >> Is there a chance that you can compensate for the difference >> automatically? > Nope, here is a dump of mode2 (only a beginning of pulse, to make it > shorter, this is JVC protocol, 50 us sample period) Are you saying the first pulse is always missing completely? I find this hard to believe. You should be careful when looking at the JVC output. This protocol does not send a header pulse for repeats. So please try this again with e.g. a Sony remote. If the first pulse is missing lircd usually will not recongise a signal and irrecord will be confused too. Christoph |
From: Maxim L. <max...@gm...> - 2009-08-16 10:35:47
|
On Sun, 2009-08-16 at 10:39 +0200, Christoph Bartelmus wrote: > Hi! > > Maxim Levitsky "max...@gm..." wrote: > [...] > >>> And, after thinking a lot about how to handle the fact that device > >>> truncates first sync pulse, I came to nice conclusion: > >> > >> In which way is the first sync pulse truncated? > >> How does it look like if you have been in idle mode and how does it look > >> like when you have not been in idle mode? > >> Is there a chance that you can compensate for the difference > >> automatically? > > Nope, here is a dump of mode2 (only a beginning of pulse, to make it > > shorter, this is JVC protocol, 50 us sample period) > > Are you saying the first pulse is always missing completely? I find this > hard to believe. > You should be careful when looking at the JVC output. This protocol does > not send a header pulse for repeats. So please try this again with e.g. a > Sony remote. > > If the first pulse is missing lircd usually will not recongise a signal > and irrecord will be confused too. You mean sony SIRC? http://www.sbprojects.com/knowledge/ir/sirc.htm I have a vcr remote, but it supports many TVs, so I can try. I also have a NEC remote, from toshiba TV, and it works perfectly. NEC repeats only sync pulse. Best regards, Maxim Levitsky > > Christoph > > ------------------------------------------------------------------------------ > Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day > trial. Simplify your report design, integration and deployment - and focus on > what you do best, core application coding. Discover what's new with > Crystal Reports now. http://p.sf.net/sfu/bobj-july |
From: Maxim L. <max...@gm...> - 2009-08-16 11:35:27
|
On Sun, 2009-08-16 at 13:35 +0300, Maxim Levitsky wrote: > On Sun, 2009-08-16 at 10:39 +0200, Christoph Bartelmus wrote: > > Hi! > > > > Maxim Levitsky "max...@gm..." wrote: > > [...] > > >>> And, after thinking a lot about how to handle the fact that device > > >>> truncates first sync pulse, I came to nice conclusion: > > >> > > >> In which way is the first sync pulse truncated? > > >> How does it look like if you have been in idle mode and how does it look > > >> like when you have not been in idle mode? > > >> Is there a chance that you can compensate for the difference > > >> automatically? > > > Nope, here is a dump of mode2 (only a beginning of pulse, to make it > > > shorter, this is JVC protocol, 50 us sample period) > > > > Are you saying the first pulse is always missing completely? I find this > > hard to believe. > > You should be careful when looking at the JVC output. This protocol does > > not send a header pulse for repeats. So please try this again with e.g. a > > Sony remote. > > > > If the first pulse is missing lircd usually will not recongise a signal > > and irrecord will be confused too. > You mean sony SIRC? > > http://www.sbprojects.com/knowledge/ir/sirc.htm > > I have a vcr remote, but it supports many TVs, so I can try. > I also have a NEC remote, from toshiba TV, and it works perfectly. > > NEC repeats only sync pulse. Great. I tested this with many many remotes (modes of my universal remote) SIRC and RC5 aren't affected at all, signal is passed as is. Pretty much only protocols that are affected, are these that have 'long' sync pulse that causes overflow. for example NEC and JVC (only protocols that I see that are affected, and yet work just fine)) ITT protocol, has its first gap (between two first pulses) shortened (probably to same issue), but it is detected well as well. There are some remotes that aren't detected at all (I guess due to carrier) (especially one protocol, that is shown to me as just one pulse) One remote, which protocol resembles NEC, didn't get detected by irrecord (says something went wrong), but same happened with enable_idle=0 as well, so it isn't the cause. So, I think that everything is OK. Best regards, Maxim Levitsky |
From: <li...@ba...> - 2009-08-16 12:08:51
|
Hi! Maxim Levitsky "max...@gm..." wrote: [...] > Pretty much only protocols that are affected, are these that have 'long' > sync pulse that causes overflow. for example NEC and JVC (only protocols > that I see that are affected, and yet work just fine)) [...] > So, I think that everything is OK. I'm not convinced yet. If you are in idle state and receive ENE_SAMPLE_OVERFLOW, then you just throw it away: --- Schnipp --- /* overflow sample recieved, handle it */ if (hw_value == ENE_SAMPLE_OVERFLOW) { if (dev->idle) continue; --- Schnipp --- Please check this again. Christoph |
From: Maxim L. <max...@gm...> - 2009-08-16 12:18:58
|
On Sun, 2009-08-16 at 14:08 +0200, Christoph Bartelmus wrote: > Hi! > > Maxim Levitsky "max...@gm..." wrote: > [...] > > Pretty much only protocols that are affected, are these that have 'long' > > sync pulse that causes overflow. for example NEC and JVC (only protocols > > that I see that are affected, and yet work just fine)) > [...] > > So, I think that everything is OK. > > I'm not convinced yet. If you are in idle state and receive > ENE_SAMPLE_OVERFLOW, then you just throw it away: > > --- Schnipp --- > /* overflow sample recieved, handle it */ > if (hw_value == ENE_SAMPLE_OVERFLOW) { > if (dev->idle) > continue; > --- Schnipp --- I have tested this. I do throw it away, for enable_idle=0. in enable_idle=1, the sample isn't recieved. I'll test again anyway. Best regards, Maxim Levitsky > > Please check this again. > > Christoph > > ------------------------------------------------------------------------------ > Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day > trial. Simplify your report design, integration and deployment - and focus on > what you do best, core application coding. Discover what's new with > Crystal Reports now. http://p.sf.net/sfu/bobj-july |
From: Maxim L. <max...@gm...> - 2009-08-16 14:00:45
|
On Sun, 2009-08-16 at 15:18 +0300, Maxim Levitsky wrote: > On Sun, 2009-08-16 at 14:08 +0200, Christoph Bartelmus wrote: > > Hi! > > > > Maxim Levitsky "max...@gm..." wrote: > > [...] > > > Pretty much only protocols that are affected, are these that have 'long' > > > sync pulse that causes overflow. for example NEC and JVC (only protocols > > > that I see that are affected, and yet work just fine)) > > [...] > > > So, I think that everything is OK. > > > > I'm not convinced yet. If you are in idle state and receive > > ENE_SAMPLE_OVERFLOW, then you just throw it away: > > > > --- Schnipp --- > > /* overflow sample recieved, handle it */ > > if (hw_value == ENE_SAMPLE_OVERFLOW) { > > if (dev->idle) > > continue; > > --- Schnipp --- > I have tested this. > I do throw it away, for enable_idle=0. in enable_idle=1, the sample > isn't recieved. I'll test again anyway. Yes, have just tested. I have even put a printk there. Best regards Maxim Levitsky |
From: <li...@ba...> - 2009-08-16 13:48:54
|
Hi Maxim, on 16 Aug 09 at 16:31, Maxim Levitsky wrote: [...] >>> I'm not convinced yet. If you are in idle state and receive >>> ENE_SAMPLE_OVERFLOW, then you just throw it away: >>> >>> --- Schnipp --- >>> /* overflow sample recieved, handle it */ >>> if (hw_value == ENE_SAMPLE_OVERFLOW) { >>> if (dev->idle) >>> continue; >>> --- Schnipp --- >> I have tested this. >> I do throw it away, for enable_idle=0. Why?? I still don't understand the code, like this: --- Schnipp --- if (!enable_idle) continue; --- Schnipp --- Shouldn't that be if(enable_idle) ? >> in enable_idle=1, the sample >> isn't recieved. I'll test again anyway. > Yes, have just tested. > I have even put a printk there. How about changing the sample_period to 100. Then there should be no overflow for the protocols in question and everything should be well, right? Christoph |
From: Maxim L. <max...@gm...> - 2009-08-16 14:00:54
|
On Sun, 2009-08-16 at 15:48 +0200, Christoph Bartelmus wrote: > Hi Maxim, > > on 16 Aug 09 at 16:31, Maxim Levitsky wrote: > [...] > >>> I'm not convinced yet. If you are in idle state and receive > >>> ENE_SAMPLE_OVERFLOW, then you just throw it away: > >>> > >>> --- Schnipp --- > >>> /* overflow sample recieved, handle it */ > >>> if (hw_value == ENE_SAMPLE_OVERFLOW) { > >>> if (dev->idle) > >>> continue; > >>> --- Schnipp --- > >> I have tested this. > >> I do throw it away, for enable_idle=0. > > Why?? > I still don't understand the code, like this: > --- Schnipp --- > if (!enable_idle) > continue; > --- Schnipp --- > Shouldn't that be if(enable_idle) ? > > >> in enable_idle=1, the sample > >> isn't recieved. I'll test again anyway. > > Yes, have just tested. > > I have even put a printk there. > > How about changing the sample_period to 100. Then there should be no > overflow for the protocols in question and everything should be well, > right? This indeed helps, but 100 isn't that great precision? Especially files generated with irrecord might be inaccurate. If you think this is ok, then its isn't a problem to bump it to 100 Best regards, Maxim Levitsky > > Christoph > > ------------------------------------------------------------------------------ > Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day > trial. Simplify your report design, integration and deployment - and focus on > what you do best, core application coding. Discover what's new with > Crystal Reports now. http://p.sf.net/sfu/bobj-july |
From: <li...@ba...> - 2009-08-16 14:38:41
|
Hi! Maxim Levitsky "max...@gm..." wrote: [...] >> How about changing the sample_period to 100. Then there should be no >> overflow for the protocols in question and everything should be well, >> right? > This indeed helps, but 100 isn't that great precision? Then let's go down to 75. That should work as well. You should also implement the LIRC_GET_REC_RESOLUTION ioctl in your driver. Take a look at lirc_streamzap.c for sample code. > Especially files generated with irrecord might be inaccurate. > If you think this is ok, then its isn't a problem to bump it to 100 The StreamZap receiver has 256 us resolution. 75 should be good enough. Christoph |
From: Maxim L. <max...@gm...> - 2009-08-16 14:59:24
|
On Sun, 2009-08-16 at 16:33 +0200, Christoph Bartelmus wrote: > Hi! > > Maxim Levitsky "max...@gm..." wrote: > [...] > >> How about changing the sample_period to 100. Then there should be no > >> overflow for the protocols in question and everything should be well, > >> right? > > This indeed helps, but 100 isn't that great precision? > > Then let's go down to 75. That should work as well. > You should also implement the LIRC_GET_REC_RESOLUTION ioctl in your > driver. Take a look at lirc_streamzap.c for sample code. Ok, but I think that recording resolution should be handled by core, like driver sets it in driver structure, and core returns it. like features. Best regards, Maxim Levitsky > > > Especially files generated with irrecord might be inaccurate. > > If you think this is ok, then its isn't a problem to bump it to 100 > > The StreamZap receiver has 256 us resolution. 75 should be good enough. > > Christoph > > ------------------------------------------------------------------------------ > Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day > trial. Simplify your report design, integration and deployment - and focus on > what you do best, core application coding. Discover what's new with > Crystal Reports now. http://p.sf.net/sfu/bobj-july |