Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit da6e162d authored by David Härdeman's avatar David Härdeman Committed by Mauro Carvalho Chehab
Browse files

[media] rc-core: simplify sysfs code



Simplify and cleanup the sysfs code a bit.

[m.chehab@samsung.com: rebased and fixed a CodingStyle issue]
Signed-off-by: default avatarDavid Härdeman <david@hardeman.nu>

Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent 0bc56cbe
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -240,6 +240,12 @@ ir_raw_get_allowed_protocols(void)
	return protocols;
}

static int change_protocol(struct rc_dev *dev, u64 *rc_type)
{
	/* the caller will update dev->enabled_protocols */
	return 0;
}

/*
 * Used to (un)register raw event clients
 */
@@ -257,6 +263,7 @@ int ir_raw_event_register(struct rc_dev *dev)

	dev->raw->dev = dev;
	rc_set_enabled_protocols(dev, ~0);
	dev->change_protocol = change_protocol;
	rc = kfifo_alloc(&dev->raw->kfifo,
			 sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
			 GFP_KERNEL);
+144 −121
Original line number Diff line number Diff line
@@ -830,7 +830,7 @@ struct rc_filter_attribute {
/**
 * show_protocols() - shows the current/wakeup IR protocol(s)
 * @device:	the device descriptor
 * @mattr:	the device attribute struct (unused)
 * @mattr:	the device attribute struct
 * @buf:	a pointer to the output buffer
 *
 * This routine is a callback routine for input read the IR protocol type(s).
@@ -856,20 +856,21 @@ static ssize_t show_protocols(struct device *device,

	mutex_lock(&dev->lock);

	enabled = dev->enabled_protocols[fattr->type];
	if (dev->driver_type == RC_DRIVER_SCANCODE ||
	    fattr->type == RC_FILTER_WAKEUP)
		allowed = dev->allowed_protocols[fattr->type];
	else if (dev->raw)
	if (fattr->type == RC_FILTER_NORMAL) {
		enabled = dev->enabled_protocols[RC_FILTER_NORMAL];
		if (dev->raw)
			allowed = ir_raw_get_allowed_protocols();
	else {
		mutex_unlock(&dev->lock);
		return -ENODEV;
		else
			allowed = dev->allowed_protocols[RC_FILTER_NORMAL];
	} else {
		enabled = dev->enabled_protocols[RC_FILTER_WAKEUP];
		allowed = dev->allowed_protocols[RC_FILTER_WAKEUP];
	}

	IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
		   (long long)allowed,
		   (long long)enabled);
	mutex_unlock(&dev->lock);

	IR_dprintk(1, "%s: allowed - 0x%llx, enabled - 0x%llx\n",
		   __func__, (long long)allowed, (long long)enabled);

	for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
		if (allowed & enabled & proto_names[i].type)
@@ -885,62 +886,29 @@ static ssize_t show_protocols(struct device *device,
		tmp--;
	*tmp = '\n';

	mutex_unlock(&dev->lock);

	return tmp + 1 - buf;
}

/**
 * store_protocols() - changes the current/wakeup IR protocol(s)
 * @device:	the device descriptor
 * @mattr:	the device attribute struct (unused)
 * @buf:	a pointer to the input buffer
 * @len:	length of the input buffer
 * parse_protocol_change() - parses a protocol change request
 * @protocols:	pointer to the bitmask of current protocols
 * @buf:	pointer to the buffer with a list of changes
 *
 * This routine is for changing the IR protocol type.
 * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]protocols.
 * Writing "+proto" will add a protocol to the list of enabled protocols.
 * Writing "-proto" will remove a protocol from the list of enabled protocols.
 * Writing "+proto" will add a protocol to the protocol mask.
 * Writing "-proto" will remove a protocol from protocol mask.
 * Writing "proto" will enable only "proto".
 * Writing "none" will disable all protocols.
 * Returns -EINVAL if an invalid protocol combination or unknown protocol name
 * is used, otherwise @len.
 *
 * dev->lock is taken to guard against races between device
 * registration, store_protocols and show_protocols.
 * Returns the number of changes performed or a negative error code.
 */
static ssize_t store_protocols(struct device *device,
			       struct device_attribute *mattr,
			       const char *data,
			       size_t len)
static int parse_protocol_change(u64 *protocols, const char *buf)
{
	struct rc_dev *dev = to_rc_dev(device);
	struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
	bool enable, disable;
	const char *tmp;
	u64 old_type, type;
	unsigned count = 0;
	bool enable, disable;
	u64 mask;
	int rc, i, count = 0;
	ssize_t ret;
	int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
	int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
	struct rc_scancode_filter local_filter, *filter;

	/* Device is being removed */
	if (!dev)
		return -EINVAL;

	mutex_lock(&dev->lock);

	if (dev->driver_type != RC_DRIVER_SCANCODE && !dev->raw) {
		IR_dprintk(1, "Protocol switching not supported\n");
		ret = -EINVAL;
		goto out;
	}
	old_type = dev->enabled_protocols[fattr->type];
	type = old_type;
	int i;

	while ((tmp = strsep((char **) &data, " \n")) != NULL) {
	while ((tmp = strsep((char **)&buf, " \n")) != NULL) {
		if (!*tmp)
			break;

@@ -966,76 +934,124 @@ static ssize_t store_protocols(struct device *device,

		if (i == ARRAY_SIZE(proto_names)) {
			IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
			ret = -EINVAL;
			goto out;
			return -EINVAL;
		}

		count++;

		if (enable)
			type |= mask;
			*protocols |= mask;
		else if (disable)
			type &= ~mask;
			*protocols &= ~mask;
		else
			type = mask;
			*protocols = mask;
	}

	if (!count) {
		IR_dprintk(1, "Protocol not specified\n");
		ret = -EINVAL;
		goto out;
		return -EINVAL;
	}

	return count;
}

/**
 * store_protocols() - changes the current/wakeup IR protocol(s)
 * @device:	the device descriptor
 * @mattr:	the device attribute struct
 * @buf:	a pointer to the input buffer
 * @len:	length of the input buffer
 *
 * This routine is for changing the IR protocol type.
 * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]protocols.
 * See parse_protocol_change() for the valid commands.
 * Returns @len on success or a negative error code.
 *
 * dev->lock is taken to guard against races between device
 * registration, store_protocols and show_protocols.
 */
static ssize_t store_protocols(struct device *device,
			       struct device_attribute *mattr,
			       const char *buf, size_t len)
{
	struct rc_dev *dev = to_rc_dev(device);
	struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
	u64 *current_protocols;
	int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
	struct rc_scancode_filter *filter;
	int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
	u64 old_protocols, new_protocols;
	ssize_t rc;

	/* Device is being removed */
	if (!dev)
		return -EINVAL;

	if (fattr->type == RC_FILTER_NORMAL) {
		IR_dprintk(1, "Normal protocol change requested\n");
		current_protocols = &dev->enabled_protocols[RC_FILTER_NORMAL];
		change_protocol = dev->change_protocol;
		filter = &dev->scancode_filters[RC_FILTER_NORMAL];
		set_filter = dev->s_filter;
	} else {
		IR_dprintk(1, "Wakeup protocol change requested\n");
		current_protocols = &dev->enabled_protocols[RC_FILTER_WAKEUP];
		change_protocol = dev->change_wakeup_protocol;
		filter = &dev->scancode_filters[RC_FILTER_WAKEUP];
		set_filter = dev->s_wakeup_filter;
	}

	change_protocol = (fattr->type == RC_FILTER_NORMAL)
		? dev->change_protocol : dev->change_wakeup_protocol;
	if (change_protocol) {
		rc = change_protocol(dev, &type);
	if (!change_protocol) {
		IR_dprintk(1, "Protocol switching not supported\n");
		return -EINVAL;
	}

	mutex_lock(&dev->lock);

	old_protocols = *current_protocols;
	new_protocols = old_protocols;
	rc = parse_protocol_change(&new_protocols, buf);
	if (rc < 0)
		goto out;

	rc = change_protocol(dev, &new_protocols);
	if (rc < 0) {
		IR_dprintk(1, "Error setting protocols to 0x%llx\n",
				   (long long)type);
			ret = -EINVAL;
			   (long long)new_protocols);
		goto out;
	}

	if (new_protocols == old_protocols) {
		rc = len;
		goto out;
	}

	dev->enabled_protocols[fattr->type] = type;
	IR_dprintk(1, "Current protocol(s): 0x%llx\n",
		   (long long)type);
	*current_protocols = new_protocols;
	IR_dprintk(1, "Protocols changed to 0x%llx\n", (long long)new_protocols);

	/*
	 * If the protocol is changed the filter needs updating.
	 * Try setting the same filter with the new protocol (if any).
	 * Fall back to clearing the filter.
	 */
	filter = &dev->scancode_filters[fattr->type];
	set_filter = (fattr->type == RC_FILTER_NORMAL)
		? dev->s_filter : dev->s_wakeup_filter;

	if (set_filter && old_type != type && filter->mask) {
		local_filter = *filter;
		if (!type) {
			/* no protocol => clear filter */
			ret = -1;
		} else {
			/* hardware filtering => try setting, otherwise clear */
			ret = set_filter(dev, &local_filter);
		}
		if (ret < 0) {
			/* clear the filter */
			local_filter.data = 0;
			local_filter.mask = 0;
			set_filter(dev, &local_filter);
		}
	if (set_filter && filter->mask) {
		if (new_protocols)
			rc = set_filter(dev, filter);
		else
			rc = -1;

		/* commit the new filter */
		*filter = local_filter;
		if (rc < 0) {
			filter->data = 0;
			filter->mask = 0;
			set_filter(dev, filter);
		}
	}

	ret = len;
	rc = len;

out:
	mutex_unlock(&dev->lock);
	return ret;
	return rc;
}

/**
@@ -1061,20 +1077,23 @@ static ssize_t show_filter(struct device *device,
{
	struct rc_dev *dev = to_rc_dev(device);
	struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
	struct rc_scancode_filter *filter;
	u32 val;

	/* Device is being removed */
	if (!dev)
		return -EINVAL;

	if (fattr->type == RC_FILTER_NORMAL)
		filter = &dev->scancode_filters[RC_FILTER_NORMAL];
	else
		filter = &dev->scancode_filters[RC_FILTER_WAKEUP];

	mutex_lock(&dev->lock);
	if ((fattr->type == RC_FILTER_NORMAL && !dev->s_filter) ||
	    (fattr->type == RC_FILTER_WAKEUP && !dev->s_wakeup_filter))
		val = 0;
	else if (fattr->mask)
		val = dev->scancode_filters[fattr->type].mask;
	if (fattr->mask)
		val = filter->mask;
	else
		val = dev->scancode_filters[fattr->type].data;
		val = filter->data;
	mutex_unlock(&dev->lock);

	return sprintf(buf, "%#x\n", val);
@@ -1101,15 +1120,15 @@ static ssize_t show_filter(struct device *device,
 */
static ssize_t store_filter(struct device *device,
			    struct device_attribute *attr,
			    const char *buf,
			    size_t count)
			    const char *buf, size_t len)
{
	struct rc_dev *dev = to_rc_dev(device);
	struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
	struct rc_scancode_filter local_filter, *filter;
	struct rc_scancode_filter new_filter, *filter;
	int ret;
	unsigned long val;
	int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
	u64 *enabled_protocols;

	/* Device is being removed */
	if (!dev)
@@ -1119,38 +1138,42 @@ static ssize_t store_filter(struct device *device,
	if (ret < 0)
		return ret;

	/* Can the scancode filter be set? */
	set_filter = (fattr->type == RC_FILTER_NORMAL) ? dev->s_filter :
							 dev->s_wakeup_filter;
	if (fattr->type == RC_FILTER_NORMAL) {
		set_filter = dev->s_filter;
		enabled_protocols = &dev->enabled_protocols[RC_FILTER_NORMAL];
		filter = &dev->scancode_filters[RC_FILTER_NORMAL];
	} else {
		set_filter = dev->s_wakeup_filter;
		enabled_protocols = &dev->enabled_protocols[RC_FILTER_WAKEUP];
		filter = &dev->scancode_filters[RC_FILTER_WAKEUP];
	}

	if (!set_filter)
		return -EINVAL;

	mutex_lock(&dev->lock);

	/* Tell the driver about the new filter */
	filter = &dev->scancode_filters[fattr->type];
	local_filter = *filter;
	new_filter = *filter;
	if (fattr->mask)
		local_filter.mask = val;
		new_filter.mask = val;
	else
		local_filter.data = val;
		new_filter.data = val;

	if (!dev->enabled_protocols[fattr->type] && local_filter.mask) {
	if (!*enabled_protocols && val) {
		/* refuse to set a filter unless a protocol is enabled */
		ret = -EINVAL;
		goto unlock;
	}

	ret = set_filter(dev, &local_filter);
	ret = set_filter(dev, &new_filter);
	if (ret < 0)
		goto unlock;

	/* Success, commit the new filter */
	*filter = local_filter;
	*filter = new_filter;

unlock:
	mutex_unlock(&dev->lock);
	return (ret < 0) ? ret : count;
	return (ret < 0) ? ret : len;
}

static void rc_dev_release(struct device *device)