From: Mauro Carvalho Chehab <mchehab@redhat.com>
Date: Thu, 8 Apr 2010 04:02:49 +0000 (-0300)
Subject: V4L/DVB: ir-core: properly present the supported and current protocols
X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=b320f80a6a02bbf31f7ed6ab3332f7c4ebaaac2c;p=GitHub%2Fexynos8895%2Fandroid_kernel_samsung_universal8895.git

V4L/DVB: ir-core: properly present the supported and current protocols

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>
---

diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index 81eebd8eae5a..e47a4f102637 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -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,
 };