V4L/DVB: ir-core: properly present the supported and current protocols
authorMauro Carvalho Chehab <mchehab@redhat.com>
Thu, 8 Apr 2010 04:02:49 +0000 (01:02 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 19 May 2010 15:57:02 +0000 (12:57 -0300)
Hardware decoders have a more limited set of decoders than software ones.
In general, they support just one protocol at a given time, but allow
changing between a few options.

Rename the previous badly named "current_protocol" as just "protocol",
meaning the current protocol(s) accepted by the driver, and
add a "support_protocols" to represent the entire universe of supported
protocols by that specific hardware.

As commented on http://lwn.net/Articles/378884/, the "one file, one value"
rule doesn't fit nor does make much sense for bitmap or enum values. So, the
supported_protocols will enum all supported protocols, and the protocol
will present all active protocols.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/IR/ir-sysfs.c

index 81eebd8eae5ae48ae4a33ccf4e551c11390ed904..e47a4f1026374d0f33f7b515ef0b8e6ef2e9d595 100644 (file)
@@ -56,13 +56,13 @@ static ssize_t show_protocol(struct device *d,
        if (ir_type == IR_TYPE_UNKNOWN)
                s = "Unknown";
        else if (ir_type == IR_TYPE_RC5)
-               s = "RC-5";
+               s = "rc-5";
        else if (ir_type == IR_TYPE_PD)
-               s = "Pulse/distance";
+               s = "pulse-distance";
        else if (ir_type == IR_TYPE_NEC)
-               s = "NEC";
+               s = "nec";
        else
-               s = "Other";
+               s = "other";
 
        return sprintf(buf, "%s\n", s);
 }
@@ -86,23 +86,22 @@ static ssize_t store_protocol(struct device *d,
                              size_t len)
 {
        struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-       u64 ir_type = IR_TYPE_UNKNOWN;
+       u64 ir_type = 0;
        int rc = -EINVAL;
        unsigned long flags;
        char *buf;
 
-       buf = strsep((char **) &data, "\n");
-
-       if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5"))
-               ir_type = IR_TYPE_RC5;
-       else if (!strcasecmp(buf, "pd"))
-               ir_type = IR_TYPE_PD;
-       else if (!strcasecmp(buf, "nec"))
-               ir_type = IR_TYPE_NEC;
+       while (buf = strsep((char **) &data, " \n")) {
+               if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5"))
+                       ir_type |= IR_TYPE_RC5;
+               if (!strcasecmp(buf, "pd") || !strcasecmp(buf, "pulse-distance"))
+                       ir_type |= IR_TYPE_PD;
+               if (!strcasecmp(buf, "nec"))
+                       ir_type |= IR_TYPE_NEC;
+       }
 
-       if (ir_type == IR_TYPE_UNKNOWN) {
-               IR_dprintk(1, "Error setting protocol to %lld\n",
-                          (long long)ir_type);
+       if (!ir_type) {
+               IR_dprintk(1, "Unknown protocol\n");
                return -EINVAL;
        }
 
@@ -120,12 +119,34 @@ static ssize_t store_protocol(struct device *d,
        ir_dev->rc_tab.ir_type = ir_type;
        spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
 
-       IR_dprintk(1, "Current protocol is %lld\n",
+       IR_dprintk(1, "Current protocol(s) is(are) %lld\n",
                   (long long)ir_type);
 
        return len;
 }
 
+static ssize_t show_supported_protocols(struct device *d,
+                            struct device_attribute *mattr, char *buf)
+{
+       char *orgbuf = buf;
+       struct ir_input_dev *ir_dev = dev_get_drvdata(d);
+
+       /* FIXME: doesn't support multiple protocols at the same time */
+       if (ir_dev->props->allowed_protos == IR_TYPE_UNKNOWN)
+               buf += sprintf(buf, "unknown ");
+       if (ir_dev->props->allowed_protos & IR_TYPE_RC5)
+               buf += sprintf(buf, "rc-5 ");
+       if (ir_dev->props->allowed_protos & IR_TYPE_PD)
+               buf += sprintf(buf, "pulse-distance ");
+       if (ir_dev->props->allowed_protos & IR_TYPE_NEC)
+               buf += sprintf(buf, "nec ");
+       if (buf == orgbuf)
+               buf += sprintf(buf, "other ");
+
+       buf += sprintf(buf - 1, "\n");
+
+       return buf - orgbuf;
+}
 
 #define ADD_HOTPLUG_VAR(fmt, val...)                                   \
        do {                                                            \
@@ -149,11 +170,15 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env)
 /*
  * Static device attribute struct with the sysfs attributes for IR's
  */
-static DEVICE_ATTR(current_protocol, S_IRUGO | S_IWUSR,
+static DEVICE_ATTR(protocol, S_IRUGO | S_IWUSR,
                   show_protocol, store_protocol);
 
+static DEVICE_ATTR(supported_protocols, S_IRUGO | S_IWUSR,
+                  show_supported_protocols, NULL);
+
 static struct attribute *ir_hw_dev_attrs[] = {
-       &dev_attr_current_protocol.attr,
+       &dev_attr_protocol.attr,
+       &dev_attr_supported_protocols.attr,
        NULL,
 };