]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/media/IR/ir-lirc-codec.c
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[net-next-2.6.git] / drivers / media / IR / ir-lirc-codec.c
index 1983cd3f39945cbbdae6ef3a6b8b6f3618ad1b47..9fc0db9d344d6458f6297cc4e015bc12d9486332 100644 (file)
@@ -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;