/** * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing * @input_dev: the struct input_dev device descriptor * @type: the type of the event that has occurred * * This routine (which may be called from an interrupt context) works * in similiar manner to ir_raw_event_store_edge. * This routine is intended for devices with limited internal buffer * It automerges samples of same type, and handles timeouts */ int ir_raw_event_store_with_filter(struct input_dev *input_dev, struct ir_raw_event *ev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); struct ir_raw_event_ctrl *raw = ir->raw; if (!raw || !ir->props) return -EINVAL; /* Ignore spaces in idle mode */ if (ir->idle && !ev->pulse) return 0; else if (ir->idle) ir_raw_event_set_idle(input_dev, 0); if (!raw->this_ev.duration) { raw->this_ev = *ev; } else if (ev->pulse == raw->this_ev.pulse) { raw->this_ev.duration += ev->duration; } else { ir_raw_event_store(input_dev, &raw->this_ev); raw->this_ev = *ev; } /* Enter idle mode if nessesary */ if (!ev->pulse && ir->props->timeout && raw->this_ev.duration >= ir->props->timeout) ir_raw_event_set_idle(input_dev, 1); return 0; }
static void cx23885_input_process_measurements(struct cx23885_dev *dev, bool overrun) { struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir; ssize_t num; int count, i; bool handle = false; struct ir_raw_event ir_core_event[64]; do { num = 0; v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ir_core_event, sizeof(ir_core_event), &num); count = num / sizeof(struct ir_raw_event); for (i = 0; i < count; i++) { ir_raw_event_store(kernel_ir->inp_dev, &ir_core_event[i]); handle = true; } } while (num != 0); if (overrun) ir_raw_event_reset(kernel_ir->inp_dev); else if (handle) ir_raw_event_handle(kernel_ir->inp_dev); }
static int loop_set_wakeup_filter(struct rc_dev *dev, struct rc_scancode_filter *sc) { static const unsigned int max = 512; struct ir_raw_event *raw; int ret; int i; /* fine to disable filter */ if (!sc->mask) return 0; /* encode the specified filter and loop it back */ raw = kmalloc_array(max, sizeof(*raw), GFP_KERNEL); if (!raw) return -ENOMEM; ret = ir_raw_encode_scancode(dev->wakeup_protocol, sc->data, raw, max); /* still loop back the partial raw IR even if it's incomplete */ if (ret == -ENOBUFS) ret = max; if (ret >= 0) { /* do the loopback */ for (i = 0; i < ret; ++i) ir_raw_event_store(dev, &raw[i]); ir_raw_event_handle(dev); ret = 0; } kfree(raw); return ret; }
/** * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing * @dev: the struct rc_dev device descriptor * @type: the type of the event that has occurred * * This routine (which may be called from an interrupt context) works * in similar manner to ir_raw_event_store_edge. * This routine is intended for devices with limited internal buffer * It automerges samples of same type, and handles timeouts. Returns non-zero * if the event was added, and zero if the event was ignored due to idle * processing. */ int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev) { if (!dev->raw) return -EINVAL; /* Ignore spaces in idle mode */ if (dev->idle && !ev->pulse) return 0; else if (dev->idle) ir_raw_event_set_idle(dev, false); if (!dev->raw->this_ev.duration) dev->raw->this_ev = *ev; else if (ev->pulse == dev->raw->this_ev.pulse) dev->raw->this_ev.duration += ev->duration; else { ir_raw_event_store(dev, &dev->raw->this_ev); dev->raw->this_ev = *ev; } /* Enter idle mode if nessesary */ if (!ev->pulse && dev->timeout && dev->raw->this_ev.duration >= dev->timeout) ir_raw_event_set_idle(dev, true); return 1; }
static void redrat3_process_ir_data(struct redrat3_dev *rr3) { DEFINE_IR_RAW_EVENT(rawir); struct device *dev; unsigned int i, sig_size, single_len, offset, val; u32 mod_freq; dev = rr3->dev; mod_freq = redrat3_val_to_mod_freq(&rr3->irdata); dev_dbg(dev, "Got mod_freq of %u\n", mod_freq); if (mod_freq && rr3->wideband) { DEFINE_IR_RAW_EVENT(ev); ev.carrier_report = 1; ev.carrier = mod_freq; ir_raw_event_store(rr3->rc, &ev); } /* process each rr3 encoded byte into an int */ sig_size = be16_to_cpu(rr3->irdata.sig_size); for (i = 0; i < sig_size; i++) { offset = rr3->irdata.sigdata[i]; val = get_unaligned_be16(&rr3->irdata.lens[offset]); single_len = redrat3_len_to_us(val); /* we should always get pulse/space/pulse/space samples */ if (i % 2) rawir.pulse = false; else rawir.pulse = true; rawir.duration = US_TO_NS(single_len); /* cap the value to IR_MAX_DURATION */ rawir.duration = (rawir.duration > IR_MAX_DURATION) ? IR_MAX_DURATION : rawir.duration; dev_dbg(dev, "storing %s with duration %d (i: %d)\n", rawir.pulse ? "pulse" : "space", rawir.duration, i); ir_raw_event_store_with_filter(rr3->rc, &rawir); } /* add a trailing space */ rawir.pulse = false; rawir.timeout = true; rawir.duration = rr3->rc->timeout; dev_dbg(dev, "storing trailing timeout with duration %d\n", rawir.duration); ir_raw_event_store_with_filter(rr3->rc, &rawir); dev_dbg(dev, "calling ir_raw_event_handle\n"); ir_raw_event_handle(rr3->rc); }
/** * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space * @input_dev: the struct input_dev device descriptor * @type: the type of the event that has occurred * * This routine (which may be called from an interrupt context) is used to * store the beginning of an ir pulse or space (or the start/end of ir * reception) for the raw ir decoding state machines. This is used by * hardware which does not provide durations directly but only interrupts * (or similar events) on state change. */ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type) { struct ir_input_dev *ir = input_get_drvdata(input_dev); ktime_t now; s64 delta; /* ns */ struct ir_raw_event ev; int rc = 0; if (!ir->raw) return -EINVAL; now = ktime_get(); delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); /* Check for a long duration since last event or if we're * being called for the first time, note that delta can't * possibly be negative. */ ev.duration = 0; if (delta > IR_MAX_DURATION || !ir->raw->last_type) type |= IR_START_EVENT; else ev.duration = delta; if (type & IR_START_EVENT) ir_raw_event_reset(input_dev); else if (ir->raw->last_type & IR_SPACE) { ev.pulse = false; rc = ir_raw_event_store(input_dev, &ev); } else if (ir->raw->last_type & IR_PULSE) { ev.pulse = true; rc = ir_raw_event_store(input_dev, &ev); } else return 0; ir->raw->last_event = now; ir->raw->last_type = type; return rc; }
/** * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space * @dev: the struct rc_dev device descriptor * @type: the type of the event that has occurred * * This routine (which may be called from an interrupt context) is used to * store the beginning of an ir pulse or space (or the start/end of ir * reception) for the raw ir decoding state machines. This is used by * hardware which does not provide durations directly but only interrupts * (or similar events) on state change. */ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type) { ktime_t now; s64 delta; /* ns */ DEFINE_IR_RAW_EVENT(ev); int rc = 0; int delay; if (!dev->raw) return -EINVAL; now = ktime_get(); delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event)); delay = MS_TO_NS(dev->input_dev->rep[REP_DELAY]); /* Check for a long duration since last event or if we're * being called for the first time, note that delta can't * possibly be negative. */ if (delta > delay || !dev->raw->last_type) type |= IR_START_EVENT; else ev.duration = delta; if (type & IR_START_EVENT) ir_raw_event_reset(dev); else if (dev->raw->last_type & IR_SPACE) { ev.pulse = false; rc = ir_raw_event_store(dev, &ev); } else if (dev->raw->last_type & IR_PULSE) { ev.pulse = true; rc = ir_raw_event_store(dev, &ev); } else return 0; dev->raw->last_event = now; dev->raw->last_type = type; return rc; }
void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len) { int i; const s32 *samples = (const void *)buf; for (i = 0; i < len >> 2; i++) { struct ir_raw_event ev; ev.duration = abs(samples[i]) * 1000; /* Convert to ns */ ev.pulse = (samples[i] > 0) ? false : true; ir_raw_event_store(coredev->ir.input_dev, &ev); } ir_raw_event_handle(coredev->ir.input_dev); }
void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len) { int i; const s32 *samples = (const void *)buf; for (i = 0; i < len >> 2; i++) { DEFINE_IR_RAW_EVENT(ev); ev.duration = abs(samples[i]) * 1000; ev.pulse = (samples[i] > 0) ? false : true; ir_raw_event_store(coredev->ir.dev, &ev); } ir_raw_event_handle(coredev->ir.dev); }
/** * ir_raw_event_set_idle() - provide hint to rc-core when the device is idle or not * @dev: the struct rc_dev device descriptor * @idle: whether the device is idle or not */ void ir_raw_event_set_idle(struct rc_dev *dev, bool idle) { if (!dev->raw) return; IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave"); if (idle) { dev->raw->this_ev.timeout = true; ir_raw_event_store(dev, &dev->raw->this_ev); init_ir_raw_event(&dev->raw->this_ev); } if (dev->s_idle) dev->s_idle(dev, idle); dev->idle = idle; }
int picolcd_raw_cir(struct picolcd_data *data, struct hid_report *report, u8 *raw_data, int size) { unsigned long flags; int i, w, sz; DEFINE_IR_RAW_EVENT(rawir); /* ignore if rc_dev is NULL or status is shunned */ spin_lock_irqsave(&data->lock, flags); if (!data->rc_dev || (data->status & PICOLCD_CIR_SHUN)) { spin_unlock_irqrestore(&data->lock, flags); return 1; } spin_unlock_irqrestore(&data->lock, flags); /* PicoLCD USB packets contain 16-bit intervals in network order, * with value negated for pulse. Intervals are in microseconds. * * Note: some userspace LIRC code for PicoLCD says negated values * for space - is it a matter of IR chip? (pulse for my TSOP2236) * * In addition, the first interval seems to be around 15000 + base * interval for non-first report of IR data - thus the quirk below * to get RC_CODE to understand Sony and JVC remotes I have at hand */ sz = size > 0 ? min((int)raw_data[0], size-1) : 0; for (i = 0; i+1 < sz; i += 2) { init_ir_raw_event(&rawir); w = (raw_data[i] << 8) | (raw_data[i+1]); rawir.pulse = !!(w & 0x8000); rawir.duration = US_TO_NS(rawir.pulse ? (65536 - w) : w); /* Quirk!! - see above */ if (i == 0 && rawir.duration > 15000000) rawir.duration -= 15000000; ir_raw_event_store(data->rc_dev, &rawir); } ir_raw_event_handle(data->rc_dev); return 1; }
void ir_raw_event_set_idle(struct input_dev *input_dev, int idle) { struct ir_input_dev *ir = input_get_drvdata(input_dev); struct ir_raw_event_ctrl *raw = ir->raw; ktime_t now; u64 delta; if (!ir->props) return; if (!ir->raw) goto out; if (idle) { IR_dprintk(2, "enter idle mode\n"); raw->last_event = ktime_get(); } else { IR_dprintk(2, "exit idle mode\n"); now = ktime_get(); delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); WARN_ON(raw->this_ev.pulse); raw->this_ev.duration = min(raw->this_ev.duration + delta, (u64)IR_MAX_DURATION); ir_raw_event_store(input_dev, &raw->this_ev); if (raw->this_ev.duration == IR_MAX_DURATION) ir_raw_event_reset(input_dev); raw->this_ev.duration = 0; } out: if (ir->props->s_idle) ir->props->s_idle(ir->props->priv, idle); ir->idle = idle; }
/** * ir_raw_event_set_idle() - provide hint to rc-core when the device is idle or not * @dev: the struct rc_dev device descriptor * @idle: whether the device is idle or not */ void ir_raw_event_set_idle(struct rc_dev *dev, bool idle) { if (!dev->raw) return; #ifdef CONFIG_DEBUG_PRINTK IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave"); #else IR_d; #endif if (idle) { dev->raw->this_ev.timeout = true; ir_raw_event_store(dev, &dev->raw->this_ev); init_ir_raw_event(&dev->raw->this_ev); } if (dev->s_idle) dev->s_idle(dev, idle); dev->idle = idle; }
static void wbcir_carrier_report(struct wbcir_data *data) { unsigned counter = inb(data->ebase + WBCIR_REG_ECEIR_CNT_LO) | inb(data->ebase + WBCIR_REG_ECEIR_CNT_HI) << 8; if (counter > 0 && counter < 0xffff) { DEFINE_IR_RAW_EVENT(ev); ev.carrier_report = 1; ev.carrier = DIV_ROUND_CLOSEST(counter * 1000000u, data->pulse_duration); ir_raw_event_store(data->dev, &ev); } /* reset and restart the counter */ data->pulse_duration = 0; wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_R, WBCIR_CNTR_EN | WBCIR_CNTR_R); wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_EN, WBCIR_CNTR_EN | WBCIR_CNTR_R); }
static void ir_raw_event_work(struct work_struct *work) { struct ir_raw_event ev; struct ir_raw_handler *handler; struct ir_raw_event_ctrl *raw = container_of(work, struct ir_raw_event_ctrl, rx_work); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) while (kfifo_get(raw->kfifo, (void *)&ev, sizeof(ev)) == sizeof(ev)) { #else while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) { #endif spin_lock(&ir_raw_handler_lock); list_for_each_entry(handler, &ir_raw_handler_list, list) handler->decode(raw->input_dev, ev); spin_unlock(&ir_raw_handler_lock); raw->prev_ev = ev; } } /** * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders * @input_dev: the struct input_dev device descriptor * @ev: the struct ir_raw_event descriptor of the pulse/space * * This routine (which may be called from an interrupt context) stores a * pulse/space duration for the raw ir decoding state machines. Pulses are * signalled as positive values and spaces as negative values. A zero value * will reset the decoding state machines. */ int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); if (!ir->raw) return -EINVAL; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) if (kfifo_put(ir->raw->kfifo, (void *)ev, sizeof(*ev)) != sizeof(*ev)) return -ENOMEM; #else if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) return -ENOMEM; #endif return 0; } EXPORT_SYMBOL_GPL(ir_raw_event_store); /** * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space * @input_dev: the struct input_dev device descriptor * @type: the type of the event that has occurred * * This routine (which may be called from an interrupt context) is used to * store the beginning of an ir pulse or space (or the start/end of ir * reception) for the raw ir decoding state machines. This is used by * hardware which does not provide durations directly but only interrupts * (or similar events) on state change. */ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type) { struct ir_input_dev *ir = input_get_drvdata(input_dev); ktime_t now; s64 delta; /* ns */ struct ir_raw_event ev; int rc = 0; if (!ir->raw) return -EINVAL; now = ktime_get(); delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); /* Check for a long duration since last event or if we're * being called for the first time, note that delta can't * possibly be negative. */ ev.duration = 0; if (delta > IR_MAX_DURATION || !ir->raw->last_type) type |= IR_START_EVENT; else ev.duration = delta; if (type & IR_START_EVENT) ir_raw_event_reset(input_dev); else if (ir->raw->last_type & IR_SPACE) { ev.pulse = false; rc = ir_raw_event_store(input_dev, &ev); } else if (ir->raw->last_type & IR_PULSE) { ev.pulse = true; rc = ir_raw_event_store(input_dev, &ev); } else return 0; ir->raw->last_event = now; ir->raw->last_type = type; return rc; } EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); /** * ir_raw_event_handle() - schedules the decoding of stored ir data * @input_dev: the struct input_dev device descriptor * * This routine will signal the workqueue to start decoding stored ir data. */ void ir_raw_event_handle(struct input_dev *input_dev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); if (!ir->raw) return; schedule_work(&ir->raw->rx_work); } EXPORT_SYMBOL_GPL(ir_raw_event_handle); /* used internally by the sysfs interface */ u64 ir_raw_get_allowed_protocols() { u64 protocols; spin_lock(&ir_raw_handler_lock); protocols = available_protocols; spin_unlock(&ir_raw_handler_lock); return protocols; } /* * Used to (un)register raw event clients */ int ir_raw_event_register(struct input_dev *input_dev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); int rc; struct ir_raw_handler *handler; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) spinlock_t ir_raw_lock; #endif ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); if (!ir->raw) return -ENOMEM; ir->raw->input_dev = input_dev; INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); ir->raw->enabled_protocols = ~0; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) spin_lock_init(&ir_raw_lock); ir->raw->kfifo = kfifo_alloc(sizeof(s64) * MAX_IR_EVENT_SIZE, GFP_KERNEL, &ir_raw_lock); #else rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, GFP_KERNEL); #endif if (rc < 0) { kfree(ir->raw); ir->raw = NULL; return rc; } spin_lock(&ir_raw_handler_lock); list_add_tail(&ir->raw->list, &ir_raw_client_list); list_for_each_entry(handler, &ir_raw_handler_list, list) if (handler->raw_register) handler->raw_register(ir->raw->input_dev); spin_unlock(&ir_raw_handler_lock); return 0; } void ir_raw_event_unregister(struct input_dev *input_dev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); struct ir_raw_handler *handler; if (!ir->raw) return; cancel_work_sync(&ir->raw->rx_work); spin_lock(&ir_raw_handler_lock); list_del(&ir->raw->list); list_for_each_entry(handler, &ir_raw_handler_list, list) if (handler->raw_unregister) handler->raw_unregister(ir->raw->input_dev); spin_unlock(&ir_raw_handler_lock); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) kfifo_free(ir->raw->kfifo); #else kfifo_free(&ir->raw->kfifo); #endif kfree(ir->raw); ir->raw = NULL; } /* * Extension interface - used to register the IR decoders */ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) { struct ir_raw_event_ctrl *raw; spin_lock(&ir_raw_handler_lock); list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); if (ir_raw_handler->raw_register) list_for_each_entry(raw, &ir_raw_client_list, list) ir_raw_handler->raw_register(raw->input_dev); available_protocols |= ir_raw_handler->protocols; spin_unlock(&ir_raw_handler_lock); return 0; } EXPORT_SYMBOL(ir_raw_handler_register); void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) { struct ir_raw_event_ctrl *raw; spin_lock(&ir_raw_handler_lock); list_del(&ir_raw_handler->list); if (ir_raw_handler->raw_unregister) list_for_each_entry(raw, &ir_raw_client_list, list) ir_raw_handler->raw_unregister(raw->input_dev); available_protocols &= ~ir_raw_handler->protocols; spin_unlock(&ir_raw_handler_lock); } EXPORT_SYMBOL(ir_raw_handler_unregister); #ifdef MODULE static void init_decoders(struct work_struct *work) { /* Load the decoder modules */ load_nec_decode(); load_rc5_decode(); load_rc6_decode(); load_jvc_decode(); load_sony_decode(); load_lirc_codec(); /* If needed, we may later add some init code. In this case, it is needed to change the CONFIG_MODULE test at ir-core.h */ }
static void st_rc_send_lirc_timeout(struct rc_dev *rdev) { DEFINE_IR_RAW_EVENT(ev); ev.timeout = true; ir_raw_event_store(rdev, &ev); }
static irqreturn_t st_rc_rx_interrupt(int irq, void *data) { unsigned int symbol, mark = 0; struct st_rc_device *dev = data; int last_symbol = 0; u32 status; DEFINE_IR_RAW_EVENT(ev); if (dev->irq_wake) pm_wakeup_event(dev->dev, 0); status = readl(dev->rx_base + IRB_RX_STATUS); while (status & (IRB_FIFO_NOT_EMPTY | IRB_OVERFLOW)) { u32 int_status = readl(dev->rx_base + IRB_RX_INT_STATUS); if (unlikely(int_status & IRB_RX_OVERRUN_INT)) { /* discard the entire collection in case of errors! */ ir_raw_event_reset(dev->rdev); dev_info(dev->dev, "IR RX overrun\n"); writel(IRB_RX_OVERRUN_INT, dev->rx_base + IRB_RX_INT_CLEAR); continue; } symbol = readl(dev->rx_base + IRB_RX_SYS); mark = readl(dev->rx_base + IRB_RX_ON); if (symbol == IRB_TIMEOUT) last_symbol = 1; /* Ignore any noise */ if ((mark > 2) && (symbol > 1)) { symbol -= mark; if (dev->overclocking) { /* adjustments to timings */ symbol *= dev->sample_mult; symbol /= dev->sample_div; mark *= dev->sample_mult; mark /= dev->sample_div; } ev.duration = US_TO_NS(mark); ev.pulse = true; ir_raw_event_store(dev->rdev, &ev); if (!last_symbol) { ev.duration = US_TO_NS(symbol); ev.pulse = false; ir_raw_event_store(dev->rdev, &ev); } else { st_rc_send_lirc_timeout(dev->rdev); } } last_symbol = 0; status = readl(dev->rx_base + IRB_RX_STATUS); } writel(IRB_RX_INTS, dev->rx_base + IRB_RX_INT_CLEAR); /* Empty software fifo */ ir_raw_event_handle(dev->rdev); return IRQ_HANDLED; }