LIRC currently supports quite a number of ioctl's for getting/setting
various TX and RX parameters. One problem with the one-ioctl-per-parameter
approach is that it might be quite elaborate to reprogram the hardware
(an operation which will have to be done once for every parameter change).

LIRC has approached this problem by providing something similar to
database transactions (ioctl commands LIRC_SETUP_START and LIRC_SETUP_END)
which is one (complicated) way of doing it.

The proposed approach for rc-core instead uses a struct with all known
parameters defined in one go. Drivers are expected to fill in the struct
with all the parameters that apply to them while leaving the rest intact.

I've looked at parameters defined in: LIRC, current rc-core, and in Microsoft
CIRClass drivers. The current struct rc_ir_rx should be a superset of all
three and also has room for further additions. Hopefully this should be fairly
complete and future-proof, please check carefully that you favourite
parameter is supported to satisfy your OCD.

Also, it would be interesting to know if carrier reporting is actually an
expensive operation (which should be explicitly enabled by setting the
appropriate flag as now) or not (in which case it should always be on).

Signed-off-by: David Härdeman <da...@hardeman.nu>
---
 drivers/media/rc/rc-main.c |   28 +++++++++++++++++++
 include/media/rc-core.h    |   65 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 477ad49..c391518 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1649,6 +1649,7 @@ static long rc_do_ioctl(struct rc_dev *dev, unsigned int 
cmd, unsigned long arg)
 {
        void __user *p = (void __user *)arg;
        unsigned int __user *ip = (unsigned int __user *)p;
+       struct rc_ir_rx rx;
 
        switch (cmd) {
 
@@ -1657,6 +1658,33 @@ static long rc_do_ioctl(struct rc_dev *dev, unsigned int 
cmd, unsigned long arg)
 
        case RCIOCGTYPE:
                return put_user(dev->driver_type, ip);
+
+       case RCIOCGIRPSIZE:
+               return put_user(ARRAY_SIZE(rx.protocols_supported), ip);
+
+       case RCIOCGIRRX:
+               memset(&rx, 0, sizeof(rx));
+               rx.rx_supported = 0x1;
+               rx.rx_enabled = 0x1;
+               rx.rx_connected = 0x1;
+               rx.protocols_enabled[0] = dev->enabled_protocols;
+               if (dev->driver_type == RC_DRIVER_SCANCODE)
+                       rx.protocols_supported[0] = dev->allowed_protocols;
+               else
+                       rx.protocols_supported[0] = 
ir_raw_get_allowed_protocols();
+               rx.timeout = dev->timeout;
+               rx.timeout_min = dev->min_timeout;
+               rx.timeout_max = dev->max_timeout;
+               rx.resolution = dev->rx_resolution;
+
+               /* See if the driver wishes to override anything */
+               if (dev->get_ir_rx)
+                       dev->get_ir_rx(dev, &rx);
+
+               if (copy_to_user(p, &rx, sizeof(rx)))
+                       return -EFAULT;
+
+               return 0;
        }
 
        return -EINVAL;
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 660a331..7392258 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -48,6 +48,69 @@ do {                                                         
\
 /* get driver/hardware type */
 #define RCIOCGTYPE     _IOR(RC_IOC_MAGIC, 0x02, unsigned int)
 
+/* get size of protocols array (i.e. multiples of u64) for struct rc_ir_rx */
+#define RCIOCGIRPSIZE  _IOR(RC_IOC_MAGIC, 0x03, unsigned int)
+
+/* get ir rx parameters */
+#define RCIOCGIRRX     _IOC(_IOC_READ, RC_IOC_MAGIC, 0x04, sizeof(struct 
rc_ir_rx))
+
+/**
+ * struct rc_ir_rx - used to get all IR RX parameters in one go
+ * @flags: device specific flags (only %RC_IR_RX_MEASURE_CARRIER is
+ *     currently defined)
+ * @rx_supported: bitmask of supported (i.e. possible) receivers
+ * @rx_enabled: bitmask of enabled receivers
+ * @rx_connected: bitmask of connected receivers
+ * @rx_learning: bitmask of learning receivers
+ * @protocols_supported: bitmask of supported protocols
+ * @protocols_enabled: bitmask of enabled protocols
+ * @freq_min: min carrier frequency
+ * @freq_max: max carrier frequency
+ * @duty_min: min duty cycle
+ * @duty_max: max duty cycle
+ * @timeout: current timeout (i.e. silence-before-idle)
+ * @timeout_min: min timeout
+ * @timeout_max: max timeout
+ * @filter_space: shorter spaces may be filtered
+ * @filter_space_min: min space filter value
+ * @filter_space_max: max space filter value
+ * @filter_pulse: shorter pulses may be filtered
+ * @filter_pulse_min: min pulse filter value
+ * @filter_pulse_max: max pulse filter value
+ * @resolution: current pulse/space resolution
+ * @resolution_min: min resolution
+ * @resolution_max: max resolution
+ * @reserved: for future use, set to zero
+ */
+struct rc_ir_rx {
+       __u32 flags;
+#define RC_IR_RX_MEASURE_CARRIER       0x01
+       __u32 rx_supported;
+       __u32 rx_enabled;
+       __u32 rx_connected;
+       __u32 rx_learning;
+       __u64 protocols_supported[1];
+       __u64 protocols_enabled[1];
+       __u32 freq_min;
+       __u32 freq_max;
+       __u32 duty_min;
+       __u32 duty_max;
+       __u32 timeout;
+       __u32 timeout_min;
+       __u32 timeout_max;
+       __u32 filter_space;
+       __u32 filter_space_min;
+       __u32 filter_space_max;
+       __u32 filter_pulse;
+       __u32 filter_pulse_min;
+       __u32 filter_pulse_max;
+       __u32 resolution;
+       __u32 resolution_min;
+       __u32 resolution_max;
+       __u32 reserved[9];
+} __packed;
+
+
 
 enum rc_driver_type {
        RC_DRIVER_SCANCODE = 0, /* Driver or hardware generates a scancode */
@@ -202,6 +265,7 @@ enum rc_filter_type {
  * @s_carrier_report: enable carrier reports
  * @s_filter: set the scancode filter 
  * @s_wakeup_filter: set the wakeup scancode filter
+ * @get_ir_rx: allow driver to provide rx settings
  */
 struct rc_dev {
        struct device                   dev;
@@ -263,6 +327,7 @@ struct rc_dev {
                                                    struct rc_scancode_filter 
*filter);
        int                             (*s_wakeup_filter)(struct rc_dev *dev,
                                                           struct 
rc_scancode_filter *filter);
+       void                            (*get_ir_rx)(struct rc_dev *dev, struct 
rc_ir_rx *rx);
 };
 
 #define to_rc_dev(d) container_of(d, struct rc_dev, dev)

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to