]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/media/IR/ir-lirc-codec.c
V4L/DVB: IR: fix duty cycle capability
[mv-sheeva.git] / drivers / media / IR / ir-lirc-codec.c
index 3ba482d96c4b17c388fbf4b75c364879cc51a6b3..e63f757d5d72ca0ba6c1b4e206914c7d7625112a 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);
+       int sample;
 
        if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
                return 0;
@@ -39,18 +40,20 @@ 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))
+               return 0;
+
        IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
                   TO_US(ev.duration), TO_STR(ev.pulse));
 
-       ir_dev->raw->lirc.lircdata += ev.duration / 1000;
+       sample = ev.duration / 1000;
        if (ev.pulse)
-               ir_dev->raw->lirc.lircdata |= PULSE_BIT;
+               sample |= PULSE_BIT;
 
        lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
-                         (unsigned char *) &ir_dev->raw->lirc.lircdata);
+                         (unsigned char *) &sample);
        wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
 
-       ir_dev->raw->lirc.lircdata = 0;
 
        return 0;
 }
@@ -92,13 +95,14 @@ out:
        return ret;
 }
 
-static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
+static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
+                       unsigned long __user arg)
 {
        struct lirc_codec *lirc;
        struct ir_input_dev *ir_dev;
        int ret = 0;
        void *drv_data;
-       unsigned long val;
+       unsigned long val = 0;
 
        lirc = lirc_get_pdata(filep);
        if (!lirc)
@@ -110,47 +114,106 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long ar
 
        drv_data = ir_dev->props->priv;
 
-       switch (cmd) {
-       case LIRC_SET_TRANSMITTER_MASK:
+       if (_IOC_DIR(cmd) & _IOC_WRITE) {
                ret = get_user(val, (unsigned long *)arg);
                if (ret)
                        return ret;
+       }
+
+       switch (cmd) {
 
-               if (ir_dev->props && ir_dev->props->s_tx_mask)
+       /* legacy support */
+       case LIRC_GET_SEND_MODE:
+               val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
+               break;
+
+       case LIRC_SET_SEND_MODE:
+               if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
+                       return -EINVAL;
+               break;
+
+       /* 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
                        return -EINVAL;
                break;
 
        case LIRC_SET_SEND_CARRIER:
-               ret = get_user(val, (unsigned long *)arg);
-               if (ret)
-                       return ret;
-
-               if (ir_dev->props && ir_dev->props->s_tx_carrier)
+               if (ir_dev->props->s_tx_carrier)
                        ir_dev->props->s_tx_carrier(drv_data, (u32)val);
                else
                        return -EINVAL;
                break;
 
-       case LIRC_GET_SEND_MODE:
-               val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
-               ret = put_user(val, (unsigned long *)arg);
+       case LIRC_SET_SEND_DUTY_CYCLE:
+               if (!ir_dev->props->s_tx_duty_cycle)
+                       return -ENOSYS;
+
+               if (val <= 0 || val >= 100)
+                       return -EINVAL;
+
+               ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val);
                break;
 
-       case LIRC_SET_SEND_MODE:
-               ret = get_user(val, (unsigned long *)arg);
-               if (ret)
-                       return ret;
+       /* 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
+                       return -ENOSYS;
 
-               if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
+               if (!ret)
+                       ir_dev->raw->lirc.carrier_low = 0;
+               break;
+
+       case LIRC_SET_REC_CARRIER_RANGE:
+               if (val >= 0)
+                       ir_dev->raw->lirc.carrier_low = val;
+               break;
+
+
+       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
+                       return -ENOSYS;
+
+       /* Generic timeout support */
+       case LIRC_GET_MIN_TIMEOUT:
+               if (!ir_dev->props->max_timeout)
+                       return -ENOSYS;
+               val = ir_dev->props->min_timeout / 1000;
+               break;
+
+       case LIRC_GET_MAX_TIMEOUT:
+               if (!ir_dev->props->max_timeout)
+                       return -ENOSYS;
+               val = ir_dev->props->max_timeout / 1000;
+               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;
                break;
 
        default:
                return lirc_dev_fop_ioctl(filep, cmd, arg);
        }
 
+       if (_IOC_DIR(cmd) & _IOC_READ)
+               ret = put_user(val, (unsigned long *)arg);
+
        return ret;
 }
 
@@ -196,13 +259,28 @@ static int ir_lirc_register(struct input_dev *input_dev)
 
        features = LIRC_CAN_REC_MODE2;
        if (ir_dev->props->tx_ir) {
+
                features |= LIRC_CAN_SEND_PULSE;
                if (ir_dev->props->s_tx_mask)
                        features |= LIRC_CAN_SET_TRANSMITTER_MASK;
                if (ir_dev->props->s_tx_carrier)
                        features |= LIRC_CAN_SET_SEND_CARRIER;
+
+               if (ir_dev->props->s_tx_duty_cycle)
+                       features |= LIRC_CAN_SET_SEND_DUTY_CYCLE;
        }
 
+       if (ir_dev->props->s_rx_carrier_range)
+               features |= LIRC_CAN_SET_REC_CARRIER |
+                       LIRC_CAN_SET_REC_CARRIER_RANGE;
+
+       if (ir_dev->props->s_learning_mode)
+               features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
+
+       if (ir_dev->props->max_timeout)
+               features |= LIRC_CAN_SET_REC_TIMEOUT;
+
+
        snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
                 ir_dev->driver_name);
        drv->minor = -1;
@@ -224,8 +302,6 @@ static int ir_lirc_register(struct input_dev *input_dev)
 
        ir_dev->raw->lirc.drv = drv;
        ir_dev->raw->lirc.ir_dev = ir_dev;
-       ir_dev->raw->lirc.lircdata = PULSE_MASK;
-
        return 0;
 
 lirc_register_failed: