diff options
Diffstat (limited to 'drivers/media/IR/streamzap.c')
-rw-r--r-- | drivers/media/IR/streamzap.c | 376 |
1 files changed, 102 insertions, 274 deletions
diff --git a/drivers/media/IR/streamzap.c b/drivers/media/IR/streamzap.c index 058e29f..548381c 100644 --- a/drivers/media/IR/streamzap.c +++ b/drivers/media/IR/streamzap.c @@ -38,7 +38,7 @@ #include <linux/input.h> #include <media/ir-core.h> -#define DRIVER_VERSION "1.60" +#define DRIVER_VERSION "1.61" #define DRIVER_NAME "streamzap" #define DRIVER_DESC "Streamzap Remote Control driver" @@ -61,14 +61,21 @@ static struct usb_device_id streamzap_table[] = { MODULE_DEVICE_TABLE(usb, streamzap_table); -#define STREAMZAP_PULSE_MASK 0xf0 -#define STREAMZAP_SPACE_MASK 0x0f -#define STREAMZAP_TIMEOUT 0xff -#define STREAMZAP_RESOLUTION 256 +#define SZ_PULSE_MASK 0xf0 +#define SZ_SPACE_MASK 0x0f +#define SZ_TIMEOUT 0xff +#define SZ_RESOLUTION 256 /* number of samples buffered */ #define SZ_BUF_LEN 128 +/* from ir-rc5-sz-decoder.c */ +#ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE +#define load_rc5_sz_decode() request_module("ir-rc5-sz-decoder") +#else +#define load_rc5_sz_decode() 0 +#endif + enum StreamzapDecoderState { PulseSpace, FullPulse, @@ -81,7 +88,6 @@ struct streamzap_ir { /* ir-core */ struct ir_dev_props *props; - struct ir_raw_event rawir; /* core device info */ struct device *dev; @@ -98,17 +104,6 @@ struct streamzap_ir { dma_addr_t dma_in; unsigned int buf_in_len; - /* timer used to support delay buffering */ - struct timer_list delay_timer; - bool timer_running; - spinlock_t timer_lock; - struct timer_list flush_timer; - bool flush; - - /* delay buffer */ - struct kfifo fifo; - bool fifo_initialized; - /* track what state we're in */ enum StreamzapDecoderState decoder_state; /* tracks whether we are currently receiving some signal */ @@ -118,7 +113,7 @@ struct streamzap_ir { /* start time of signal; necessary for gap tracking */ struct timeval signal_last; struct timeval signal_start; - /* bool timeout_enabled; */ + bool timeout_enabled; char name[128]; char phys[64]; @@ -143,122 +138,16 @@ static struct usb_driver streamzap_driver = { .id_table = streamzap_table, }; -static void streamzap_stop_timer(struct streamzap_ir *sz) -{ - unsigned long flags; - - spin_lock_irqsave(&sz->timer_lock, flags); - if (sz->timer_running) { - sz->timer_running = false; - spin_unlock_irqrestore(&sz->timer_lock, flags); - del_timer_sync(&sz->delay_timer); - } else { - spin_unlock_irqrestore(&sz->timer_lock, flags); - } -} - -static void streamzap_flush_timeout(unsigned long arg) -{ - struct streamzap_ir *sz = (struct streamzap_ir *)arg; - - dev_info(sz->dev, "%s: callback firing\n", __func__); - - /* finally start accepting data */ - sz->flush = false; -} - -static void streamzap_delay_timeout(unsigned long arg) -{ - struct streamzap_ir *sz = (struct streamzap_ir *)arg; - struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; - unsigned long flags; - int len, ret; - static unsigned long delay; - bool wake = false; - - /* deliver data every 10 ms */ - delay = msecs_to_jiffies(10); - - spin_lock_irqsave(&sz->timer_lock, flags); - - if (kfifo_len(&sz->fifo) > 0) { - ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir)); - if (ret != sizeof(rawir)) - dev_err(sz->dev, "Problem w/kfifo_out...\n"); - ir_raw_event_store(sz->idev, &rawir); - wake = true; - } - - len = kfifo_len(&sz->fifo); - if (len > 0) { - while ((len < SZ_BUF_LEN / 2) && - (len < SZ_BUF_LEN * sizeof(int))) { - ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir)); - if (ret != sizeof(rawir)) - dev_err(sz->dev, "Problem w/kfifo_out...\n"); - ir_raw_event_store(sz->idev, &rawir); - wake = true; - len = kfifo_len(&sz->fifo); - } - if (sz->timer_running) - mod_timer(&sz->delay_timer, jiffies + delay); - - } else { - sz->timer_running = false; - } - - if (wake) - ir_raw_event_handle(sz->idev); - - spin_unlock_irqrestore(&sz->timer_lock, flags); -} - -static void streamzap_flush_delay_buffer(struct streamzap_ir *sz) +static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir) { - struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; - bool wake = false; - int ret; - - while (kfifo_len(&sz->fifo) > 0) { - ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir)); - if (ret != sizeof(rawir)) - dev_err(sz->dev, "Problem w/kfifo_out...\n"); - ir_raw_event_store(sz->idev, &rawir); - wake = true; - } - - if (wake) - ir_raw_event_handle(sz->idev); -} - -static void sz_push(struct streamzap_ir *sz) -{ - struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; - unsigned long flags; - int ret; - - spin_lock_irqsave(&sz->timer_lock, flags); - if (kfifo_len(&sz->fifo) >= sizeof(int) * SZ_BUF_LEN) { - ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir)); - if (ret != sizeof(rawir)) - dev_err(sz->dev, "Problem w/kfifo_out...\n"); - ir_raw_event_store(sz->idev, &rawir); - } - - kfifo_in(&sz->fifo, &sz->rawir, sizeof(rawir)); - - if (!sz->timer_running) { - sz->delay_timer.expires = jiffies + (HZ / 10); - add_timer(&sz->delay_timer); - sz->timer_running = true; - } - - spin_unlock_irqrestore(&sz->timer_lock, flags); + ir_raw_event_store(sz->idev, &rawir); } static void sz_push_full_pulse(struct streamzap_ir *sz, unsigned char value) { + DEFINE_IR_RAW_EVENT(rawir); + if (sz->idle) { long deltv; @@ -266,57 +155,59 @@ static void sz_push_full_pulse(struct streamzap_ir *sz, do_gettimeofday(&sz->signal_start); deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec; - sz->rawir.pulse = false; + rawir.pulse = false; if (deltv > 15) { /* really long time */ - sz->rawir.duration = IR_MAX_DURATION; + rawir.duration = IR_MAX_DURATION; } else { - sz->rawir.duration = (int)(deltv * 1000000 + + rawir.duration = (int)(deltv * 1000000 + sz->signal_start.tv_usec - sz->signal_last.tv_usec); - sz->rawir.duration -= sz->sum; - sz->rawir.duration *= 1000; - sz->rawir.duration &= IR_MAX_DURATION; + rawir.duration -= sz->sum; + rawir.duration *= 1000; + rawir.duration &= IR_MAX_DURATION; } - dev_dbg(sz->dev, "ls %u\n", sz->rawir.duration); - sz_push(sz); + dev_dbg(sz->dev, "ls %u\n", rawir.duration); + sz_push(sz, rawir); - sz->idle = 0; + sz->idle = false; sz->sum = 0; } - sz->rawir.pulse = true; - sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION; - sz->rawir.duration += STREAMZAP_RESOLUTION / 2; - sz->sum += sz->rawir.duration; - sz->rawir.duration *= 1000; - sz->rawir.duration &= IR_MAX_DURATION; - dev_dbg(sz->dev, "p %u\n", sz->rawir.duration); - sz_push(sz); + rawir.pulse = true; + rawir.duration = ((int) value) * SZ_RESOLUTION; + rawir.duration += SZ_RESOLUTION / 2; + sz->sum += rawir.duration; + rawir.duration *= 1000; + rawir.duration &= IR_MAX_DURATION; + dev_dbg(sz->dev, "p %u\n", rawir.duration); + sz_push(sz, rawir); } static void sz_push_half_pulse(struct streamzap_ir *sz, unsigned char value) { - sz_push_full_pulse(sz, (value & STREAMZAP_PULSE_MASK) >> 4); + sz_push_full_pulse(sz, (value & SZ_PULSE_MASK) >> 4); } static void sz_push_full_space(struct streamzap_ir *sz, unsigned char value) { - sz->rawir.pulse = false; - sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION; - sz->rawir.duration += STREAMZAP_RESOLUTION / 2; - sz->sum += sz->rawir.duration; - sz->rawir.duration *= 1000; - dev_dbg(sz->dev, "s %u\n", sz->rawir.duration); - sz_push(sz); + DEFINE_IR_RAW_EVENT(rawir); + + rawir.pulse = false; + rawir.duration = ((int) value) * SZ_RESOLUTION; + rawir.duration += SZ_RESOLUTION / 2; + sz->sum += rawir.duration; + rawir.duration *= 1000; + dev_dbg(sz->dev, "s %u\n", rawir.duration); + sz_push(sz, rawir); } static void sz_push_half_space(struct streamzap_ir *sz, unsigned long value) { - sz_push_full_space(sz, value & STREAMZAP_SPACE_MASK); + sz_push_full_space(sz, value & SZ_SPACE_MASK); } /** @@ -330,10 +221,8 @@ static void streamzap_callback(struct urb *urb) struct streamzap_ir *sz; unsigned int i; int len; - #if 0 - static int timeout = (((STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION) & + static int timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) & IR_MAX_DURATION) | 0x03000000); - #endif if (!urb) return; @@ -356,57 +245,53 @@ static void streamzap_callback(struct urb *urb) } dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len); - if (!sz->flush) { - for (i = 0; i < urb->actual_length; i++) { - dev_dbg(sz->dev, "%d: %x\n", i, - (unsigned char)sz->buf_in[i]); - switch (sz->decoder_state) { - case PulseSpace: - if ((sz->buf_in[i] & STREAMZAP_PULSE_MASK) == - STREAMZAP_PULSE_MASK) { - sz->decoder_state = FullPulse; - continue; - } else if ((sz->buf_in[i] & STREAMZAP_SPACE_MASK) - == STREAMZAP_SPACE_MASK) { - sz_push_half_pulse(sz, sz->buf_in[i]); - sz->decoder_state = FullSpace; - continue; - } else { - sz_push_half_pulse(sz, sz->buf_in[i]); - sz_push_half_space(sz, sz->buf_in[i]); - } - break; - case FullPulse: - sz_push_full_pulse(sz, sz->buf_in[i]); - sz->decoder_state = IgnorePulse; - break; - case FullSpace: - if (sz->buf_in[i] == STREAMZAP_TIMEOUT) { - sz->idle = 1; - streamzap_stop_timer(sz); - #if 0 - if (sz->timeout_enabled) { - sz->rawir.pulse = false; - sz->rawir.duration = timeout; - sz->rawir.duration *= 1000; - sz_push(sz); - } - #endif - streamzap_flush_delay_buffer(sz); - } else - sz_push_full_space(sz, sz->buf_in[i]); - sz->decoder_state = PulseSpace; - break; - case IgnorePulse: - if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) == - STREAMZAP_SPACE_MASK) { - sz->decoder_state = FullSpace; - continue; - } + for (i = 0; i < len; i++) { + dev_dbg(sz->dev, "sz idx %d: %x\n", + i, (unsigned char)sz->buf_in[i]); + switch (sz->decoder_state) { + case PulseSpace: + if ((sz->buf_in[i] & SZ_PULSE_MASK) == + SZ_PULSE_MASK) { + sz->decoder_state = FullPulse; + continue; + } else if ((sz->buf_in[i] & SZ_SPACE_MASK) + == SZ_SPACE_MASK) { + sz_push_half_pulse(sz, sz->buf_in[i]); + sz->decoder_state = FullSpace; + continue; + } else { + sz_push_half_pulse(sz, sz->buf_in[i]); sz_push_half_space(sz, sz->buf_in[i]); - sz->decoder_state = PulseSpace; - break; } + break; + case FullPulse: + sz_push_full_pulse(sz, sz->buf_in[i]); + sz->decoder_state = IgnorePulse; + break; + case FullSpace: + if (sz->buf_in[i] == SZ_TIMEOUT) { + DEFINE_IR_RAW_EVENT(rawir); + + rawir.pulse = false; + rawir.duration = timeout; + sz->idle = true; + if (sz->timeout_enabled) + sz_push(sz, rawir); + ir_raw_event_handle(sz->idev); + } else { + sz_push_full_space(sz, sz->buf_in[i]); + } + sz->decoder_state = PulseSpace; + break; + case IgnorePulse: + if ((sz->buf_in[i] & SZ_SPACE_MASK) == + SZ_SPACE_MASK) { + sz->decoder_state = FullSpace; + continue; + } + sz_push_half_space(sz, sz->buf_in[i]); + sz->decoder_state = PulseSpace; + break; } } @@ -446,12 +331,11 @@ static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz) props->priv = sz; props->driver_type = RC_DRIVER_IR_RAW; - /* FIXME: not sure about supported protocols, check on this */ - props->allowed_protos = IR_TYPE_RC5 | IR_TYPE_RC6; + props->allowed_protos = IR_TYPE_ALL; sz->props = props; - ret = ir_input_register(idev, RC_MAP_RC5_STREAMZAP, props, DRIVER_NAME); + ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME); if (ret < 0) { dev_err(dev, "remote input device register failed\n"); goto irdev_failed; @@ -467,29 +351,6 @@ idev_alloc_failed: return NULL; } -static int streamzap_delay_buf_init(struct streamzap_ir *sz) -{ - int ret; - - ret = kfifo_alloc(&sz->fifo, sizeof(int) * SZ_BUF_LEN, - GFP_KERNEL); - if (ret == 0) - sz->fifo_initialized = 1; - - return ret; -} - -static void streamzap_start_flush_timer(struct streamzap_ir *sz) -{ - sz->flush_timer.expires = jiffies + HZ; - sz->flush = true; - add_timer(&sz->flush_timer); - - sz->urb_in->dev = sz->usbdev; - if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) - dev_err(sz->dev, "urb submit failed\n"); -} - /** * streamzap_probe * @@ -575,35 +436,21 @@ static int __devinit streamzap_probe(struct usb_interface *intf, snprintf(name + strlen(name), sizeof(name) - strlen(name), " %s", buf); - retval = streamzap_delay_buf_init(sz); - if (retval) { - dev_err(&intf->dev, "%s: delay buffer init failed\n", __func__); - goto free_urb_in; - } - sz->idev = streamzap_init_input_dev(sz); if (!sz->idev) goto input_dev_fail; sz->idle = true; sz->decoder_state = PulseSpace; + /* FIXME: don't yet have a way to set this */ + sz->timeout_enabled = true; #if 0 /* not yet supported, depends on patches from maxim */ /* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */ - sz->timeout_enabled = false; - sz->min_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000; - sz->max_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000; + sz->min_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000; + sz->max_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000; #endif - init_timer(&sz->delay_timer); - sz->delay_timer.function = streamzap_delay_timeout; - sz->delay_timer.data = (unsigned long)sz; - spin_lock_init(&sz->timer_lock); - - init_timer(&sz->flush_timer); - sz->flush_timer.function = streamzap_flush_timeout; - sz->flush_timer.data = (unsigned long)sz; - do_gettimeofday(&sz->signal_start); /* Complete final initialisations */ @@ -615,16 +462,18 @@ static int __devinit streamzap_probe(struct usb_interface *intf, usb_set_intfdata(intf, sz); - streamzap_start_flush_timer(sz); + if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) + dev_err(sz->dev, "urb submit failed\n"); dev_info(sz->dev, "Registered %s on usb%d:%d\n", name, usbdev->bus->busnum, usbdev->devnum); + /* Load the streamzap not-quite-rc5 decoder too */ + load_rc5_sz_decode(); + return 0; input_dev_fail: - kfifo_free(&sz->fifo); -free_urb_in: usb_free_urb(sz->urb_in); free_buf_in: usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in); @@ -654,13 +503,6 @@ static void streamzap_disconnect(struct usb_interface *interface) if (!sz) return; - if (sz->flush) { - sz->flush = false; - del_timer_sync(&sz->flush_timer); - } - - streamzap_stop_timer(sz); - sz->usbdev = NULL; ir_input_unregister(sz->idev); usb_kill_urb(sz->urb_in); @@ -674,13 +516,6 @@ static int streamzap_suspend(struct usb_interface *intf, pm_message_t message) { struct streamzap_ir *sz = usb_get_intfdata(intf); - if (sz->flush) { - sz->flush = false; - del_timer_sync(&sz->flush_timer); - } - - streamzap_stop_timer(sz); - usb_kill_urb(sz->urb_in); return 0; @@ -690,13 +525,6 @@ static int streamzap_resume(struct usb_interface *intf) { struct streamzap_ir *sz = usb_get_intfdata(intf); - if (sz->fifo_initialized) - kfifo_reset(&sz->fifo); - - sz->flush_timer.expires = jiffies + HZ; - sz->flush = true; - add_timer(&sz->flush_timer); - if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { dev_err(sz->dev, "Error sumbiting urb\n"); return -EIO; |