diff options
Diffstat (limited to 'drivers/media/IR/ir-lirc-codec.c')
-rw-r--r-- | drivers/media/IR/ir-lirc-codec.c | 135 |
1 files changed, 95 insertions, 40 deletions
diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c index 1983cd3f399..9fc0db9d344 100644 --- a/drivers/media/IR/ir-lirc-codec.c +++ b/drivers/media/IR/ir-lirc-codec.c @@ -32,6 +32,7 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct lirc_codec *lirc = &ir_dev->raw->lirc; int sample; if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) @@ -40,21 +41,57 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) return -EINVAL; - if (IS_RESET(ev)) + /* Packet start */ + if (ev.reset) return 0; - IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", - TO_US(ev.duration), TO_STR(ev.pulse)); + /* Carrier reports */ + if (ev.carrier_report) { + sample = LIRC_FREQUENCY(ev.carrier); + + /* Packet end */ + } else if (ev.timeout) { + + if (lirc->gap) + return 0; + + lirc->gap_start = ktime_get(); + lirc->gap = true; + lirc->gap_duration = ev.duration; + + if (!lirc->send_timeout_reports) + return 0; + + sample = LIRC_TIMEOUT(ev.duration / 1000); - sample = ev.duration / 1000; - if (ev.pulse) - sample |= PULSE_BIT; + /* Normal sample */ + } else { + + if (lirc->gap) { + int gap_sample; + + lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(), + lirc->gap_start)); + + /* Convert to ms and cap by LIRC_VALUE_MASK */ + do_div(lirc->gap_duration, 1000); + lirc->gap_duration = min(lirc->gap_duration, + (u64)LIRC_VALUE_MASK); + + gap_sample = LIRC_SPACE(lirc->gap_duration); + lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, + (unsigned char *) &gap_sample); + lirc->gap = false; + } + + sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) : + LIRC_SPACE(ev.duration / 1000); + } lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, (unsigned char *) &sample); wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); - return 0; } @@ -102,7 +139,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, struct ir_input_dev *ir_dev; int ret = 0; void *drv_data; - unsigned long val = 0; + __u32 val = 0, tmp; lirc = lirc_get_pdata(filep); if (!lirc) @@ -115,7 +152,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, drv_data = ir_dev->props->priv; if (_IOC_DIR(cmd) & _IOC_WRITE) { - ret = get_user(val, (unsigned long *)arg); + ret = get_user(val, (__u32 *)arg); if (ret) return ret; } @@ -130,22 +167,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, case LIRC_SET_SEND_MODE: if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) return -EINVAL; - break; + return 0; /* TX settings */ case LIRC_SET_TRANSMITTER_MASK: - if (ir_dev->props->s_tx_mask) - ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); - else + if (!ir_dev->props->s_tx_mask) return -EINVAL; - break; + + return ir_dev->props->s_tx_mask(drv_data, val); case LIRC_SET_SEND_CARRIER: - if (ir_dev->props->s_tx_carrier) - ir_dev->props->s_tx_carrier(drv_data, (u32)val); - else + if (!ir_dev->props->s_tx_carrier) return -EINVAL; - break; + + return ir_dev->props->s_tx_carrier(drv_data, val); case LIRC_SET_SEND_DUTY_CYCLE: if (!ir_dev->props->s_tx_duty_cycle) @@ -154,39 +189,42 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, if (val <= 0 || val >= 100) return -EINVAL; - ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val); - break; + return ir_dev->props->s_tx_duty_cycle(drv_data, val); /* RX settings */ case LIRC_SET_REC_CARRIER: - if (ir_dev->props->s_rx_carrier_range) - ret = ir_dev->props->s_rx_carrier_range( - ir_dev->props->priv, - ir_dev->raw->lirc.carrier_low, val); - else + if (!ir_dev->props->s_rx_carrier_range) return -ENOSYS; - if (!ret) - ir_dev->raw->lirc.carrier_low = 0; - break; + if (val <= 0) + return -EINVAL; + + return ir_dev->props->s_rx_carrier_range(drv_data, + ir_dev->raw->lirc.carrier_low, val); case LIRC_SET_REC_CARRIER_RANGE: - if (val >= 0) - ir_dev->raw->lirc.carrier_low = val; - break; + if (val <= 0) + return -EINVAL; + ir_dev->raw->lirc.carrier_low = val; + return 0; case LIRC_GET_REC_RESOLUTION: val = ir_dev->props->rx_resolution; break; case LIRC_SET_WIDEBAND_RECEIVER: - if (ir_dev->props->s_learning_mode) - return ir_dev->props->s_learning_mode( - ir_dev->props->priv, !!val); - else + if (!ir_dev->props->s_learning_mode) return -ENOSYS; + return ir_dev->props->s_learning_mode(drv_data, !!val); + + case LIRC_SET_MEASURE_CARRIER_MODE: + if (!ir_dev->props->s_carrier_report) + return -ENOSYS; + + return ir_dev->props->s_carrier_report(drv_data, !!val); + /* Generic timeout support */ case LIRC_GET_MIN_TIMEOUT: if (!ir_dev->props->max_timeout) @@ -201,10 +239,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, break; case LIRC_SET_REC_TIMEOUT: - if (val < ir_dev->props->min_timeout || - val > ir_dev->props->max_timeout) - return -EINVAL; - ir_dev->props->timeout = val * 1000; + if (!ir_dev->props->max_timeout) + return -ENOSYS; + + tmp = val * 1000; + + if (tmp < ir_dev->props->min_timeout || + tmp > ir_dev->props->max_timeout) + return -EINVAL; + + ir_dev->props->timeout = tmp; + break; + + case LIRC_SET_REC_TIMEOUT_REPORTS: + lirc->send_timeout_reports = !!val; break; default: @@ -212,7 +260,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, } if (_IOC_DIR(cmd) & _IOC_READ) - ret = put_user(val, (unsigned long *)arg); + ret = put_user(val, (__u32 *)arg); return ret; } @@ -231,6 +279,9 @@ static struct file_operations lirc_fops = { .owner = THIS_MODULE, .write = ir_lirc_transmit_ir, .unlocked_ioctl = ir_lirc_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ir_lirc_ioctl, +#endif .read = lirc_dev_fop_read, .poll = lirc_dev_fop_poll, .open = lirc_dev_fop_open, @@ -278,6 +329,10 @@ static int ir_lirc_register(struct input_dev *input_dev) if (ir_dev->props->s_learning_mode) features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; + if (ir_dev->props->s_carrier_report) + features |= LIRC_CAN_MEASURE_CARRIER; + + if (ir_dev->props->max_timeout) features |= LIRC_CAN_SET_REC_TIMEOUT; |