[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: David Härdeman <david@hardeman.nu> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
This commit is contained in:
Родитель
0bc56cbef9
Коммит
da6e162d6a
|
@ -240,6 +240,12 @@ ir_raw_get_allowed_protocols(void)
|
||||||
return protocols;
|
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
|
* Used to (un)register raw event clients
|
||||||
*/
|
*/
|
||||||
|
@ -257,6 +263,7 @@ int ir_raw_event_register(struct rc_dev *dev)
|
||||||
|
|
||||||
dev->raw->dev = dev;
|
dev->raw->dev = dev;
|
||||||
rc_set_enabled_protocols(dev, ~0);
|
rc_set_enabled_protocols(dev, ~0);
|
||||||
|
dev->change_protocol = change_protocol;
|
||||||
rc = kfifo_alloc(&dev->raw->kfifo,
|
rc = kfifo_alloc(&dev->raw->kfifo,
|
||||||
sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
|
sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
|
@ -830,7 +830,7 @@ struct rc_filter_attribute {
|
||||||
/**
|
/**
|
||||||
* show_protocols() - shows the current/wakeup IR protocol(s)
|
* show_protocols() - shows the current/wakeup IR protocol(s)
|
||||||
* @device: the device descriptor
|
* @device: the device descriptor
|
||||||
* @mattr: the device attribute struct (unused)
|
* @mattr: the device attribute struct
|
||||||
* @buf: a pointer to the output buffer
|
* @buf: a pointer to the output buffer
|
||||||
*
|
*
|
||||||
* This routine is a callback routine for input read the IR protocol type(s).
|
* 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);
|
mutex_lock(&dev->lock);
|
||||||
|
|
||||||
enabled = dev->enabled_protocols[fattr->type];
|
if (fattr->type == RC_FILTER_NORMAL) {
|
||||||
if (dev->driver_type == RC_DRIVER_SCANCODE ||
|
enabled = dev->enabled_protocols[RC_FILTER_NORMAL];
|
||||||
fattr->type == RC_FILTER_WAKEUP)
|
if (dev->raw)
|
||||||
allowed = dev->allowed_protocols[fattr->type];
|
allowed = ir_raw_get_allowed_protocols();
|
||||||
else if (dev->raw)
|
else
|
||||||
allowed = ir_raw_get_allowed_protocols();
|
allowed = dev->allowed_protocols[RC_FILTER_NORMAL];
|
||||||
else {
|
} else {
|
||||||
mutex_unlock(&dev->lock);
|
enabled = dev->enabled_protocols[RC_FILTER_WAKEUP];
|
||||||
return -ENODEV;
|
allowed = dev->allowed_protocols[RC_FILTER_WAKEUP];
|
||||||
}
|
}
|
||||||
|
|
||||||
IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
|
mutex_unlock(&dev->lock);
|
||||||
(long long)allowed,
|
|
||||||
(long long)enabled);
|
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++) {
|
for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
|
||||||
if (allowed & enabled & proto_names[i].type)
|
if (allowed & enabled & proto_names[i].type)
|
||||||
|
@ -885,62 +886,29 @@ static ssize_t show_protocols(struct device *device,
|
||||||
tmp--;
|
tmp--;
|
||||||
*tmp = '\n';
|
*tmp = '\n';
|
||||||
|
|
||||||
mutex_unlock(&dev->lock);
|
|
||||||
|
|
||||||
return tmp + 1 - buf;
|
return tmp + 1 - buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* store_protocols() - changes the current/wakeup IR protocol(s)
|
* parse_protocol_change() - parses a protocol change request
|
||||||
* @device: the device descriptor
|
* @protocols: pointer to the bitmask of current protocols
|
||||||
* @mattr: the device attribute struct (unused)
|
* @buf: pointer to the buffer with a list of changes
|
||||||
* @buf: a pointer to the input buffer
|
|
||||||
* @len: length of the input buffer
|
|
||||||
*
|
*
|
||||||
* This routine is for changing the IR protocol type.
|
* Writing "+proto" will add a protocol to the protocol mask.
|
||||||
* It is trigged by writing to /sys/class/rc/rc?/[wakeup_]protocols.
|
* Writing "-proto" will remove a protocol from protocol mask.
|
||||||
* 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 enable only "proto".
|
* Writing "proto" will enable only "proto".
|
||||||
* Writing "none" will disable all protocols.
|
* Writing "none" will disable all protocols.
|
||||||
* Returns -EINVAL if an invalid protocol combination or unknown protocol name
|
* Returns the number of changes performed or a negative error code.
|
||||||
* is used, otherwise @len.
|
|
||||||
*
|
|
||||||
* dev->lock is taken to guard against races between device
|
|
||||||
* registration, store_protocols and show_protocols.
|
|
||||||
*/
|
*/
|
||||||
static ssize_t store_protocols(struct device *device,
|
static int parse_protocol_change(u64 *protocols, const char *buf)
|
||||||
struct device_attribute *mattr,
|
|
||||||
const char *data,
|
|
||||||
size_t len)
|
|
||||||
{
|
{
|
||||||
struct rc_dev *dev = to_rc_dev(device);
|
|
||||||
struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
|
|
||||||
bool enable, disable;
|
|
||||||
const char *tmp;
|
const char *tmp;
|
||||||
u64 old_type, type;
|
unsigned count = 0;
|
||||||
|
bool enable, disable;
|
||||||
u64 mask;
|
u64 mask;
|
||||||
int rc, i, count = 0;
|
int i;
|
||||||
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 */
|
while ((tmp = strsep((char **)&buf, " \n")) != NULL) {
|
||||||
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;
|
|
||||||
|
|
||||||
while ((tmp = strsep((char **) &data, " \n")) != NULL) {
|
|
||||||
if (!*tmp)
|
if (!*tmp)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -966,76 +934,124 @@ static ssize_t store_protocols(struct device *device,
|
||||||
|
|
||||||
if (i == ARRAY_SIZE(proto_names)) {
|
if (i == ARRAY_SIZE(proto_names)) {
|
||||||
IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
|
IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
type |= mask;
|
*protocols |= mask;
|
||||||
else if (disable)
|
else if (disable)
|
||||||
type &= ~mask;
|
*protocols &= ~mask;
|
||||||
else
|
else
|
||||||
type = mask;
|
*protocols = mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!count) {
|
if (!count) {
|
||||||
IR_dprintk(1, "Protocol not specified\n");
|
IR_dprintk(1, "Protocol not specified\n");
|
||||||
ret = -EINVAL;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)new_protocols);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
change_protocol = (fattr->type == RC_FILTER_NORMAL)
|
if (new_protocols == old_protocols) {
|
||||||
? dev->change_protocol : dev->change_wakeup_protocol;
|
rc = len;
|
||||||
if (change_protocol) {
|
goto out;
|
||||||
rc = change_protocol(dev, &type);
|
|
||||||
if (rc < 0) {
|
|
||||||
IR_dprintk(1, "Error setting protocols to 0x%llx\n",
|
|
||||||
(long long)type);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->enabled_protocols[fattr->type] = type;
|
*current_protocols = new_protocols;
|
||||||
IR_dprintk(1, "Current protocol(s): 0x%llx\n",
|
IR_dprintk(1, "Protocols changed to 0x%llx\n", (long long)new_protocols);
|
||||||
(long long)type);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the protocol is changed the filter needs updating.
|
* If the protocol is changed the filter needs updating.
|
||||||
* Try setting the same filter with the new protocol (if any).
|
* Try setting the same filter with the new protocol (if any).
|
||||||
* Fall back to clearing the filter.
|
* Fall back to clearing the filter.
|
||||||
*/
|
*/
|
||||||
filter = &dev->scancode_filters[fattr->type];
|
if (set_filter && filter->mask) {
|
||||||
set_filter = (fattr->type == RC_FILTER_NORMAL)
|
if (new_protocols)
|
||||||
? dev->s_filter : dev->s_wakeup_filter;
|
rc = set_filter(dev, filter);
|
||||||
|
else
|
||||||
|
rc = -1;
|
||||||
|
|
||||||
if (set_filter && old_type != type && filter->mask) {
|
if (rc < 0) {
|
||||||
local_filter = *filter;
|
filter->data = 0;
|
||||||
if (!type) {
|
filter->mask = 0;
|
||||||
/* no protocol => clear filter */
|
set_filter(dev, 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* commit the new filter */
|
|
||||||
*filter = local_filter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = len;
|
rc = len;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&dev->lock);
|
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_dev *dev = to_rc_dev(device);
|
||||||
struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
|
struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
|
||||||
|
struct rc_scancode_filter *filter;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
/* Device is being removed */
|
/* Device is being removed */
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&dev->lock);
|
if (fattr->type == RC_FILTER_NORMAL)
|
||||||
if ((fattr->type == RC_FILTER_NORMAL && !dev->s_filter) ||
|
filter = &dev->scancode_filters[RC_FILTER_NORMAL];
|
||||||
(fattr->type == RC_FILTER_WAKEUP && !dev->s_wakeup_filter))
|
|
||||||
val = 0;
|
|
||||||
else if (fattr->mask)
|
|
||||||
val = dev->scancode_filters[fattr->type].mask;
|
|
||||||
else
|
else
|
||||||
val = dev->scancode_filters[fattr->type].data;
|
filter = &dev->scancode_filters[RC_FILTER_WAKEUP];
|
||||||
|
|
||||||
|
mutex_lock(&dev->lock);
|
||||||
|
if (fattr->mask)
|
||||||
|
val = filter->mask;
|
||||||
|
else
|
||||||
|
val = filter->data;
|
||||||
mutex_unlock(&dev->lock);
|
mutex_unlock(&dev->lock);
|
||||||
|
|
||||||
return sprintf(buf, "%#x\n", val);
|
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,
|
static ssize_t store_filter(struct device *device,
|
||||||
struct device_attribute *attr,
|
struct device_attribute *attr,
|
||||||
const char *buf,
|
const char *buf, size_t len)
|
||||||
size_t count)
|
|
||||||
{
|
{
|
||||||
struct rc_dev *dev = to_rc_dev(device);
|
struct rc_dev *dev = to_rc_dev(device);
|
||||||
struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
|
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;
|
int ret;
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
|
int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
|
||||||
|
u64 *enabled_protocols;
|
||||||
|
|
||||||
/* Device is being removed */
|
/* Device is being removed */
|
||||||
if (!dev)
|
if (!dev)
|
||||||
|
@ -1119,38 +1138,42 @@ static ssize_t store_filter(struct device *device,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Can the scancode filter be set? */
|
if (fattr->type == RC_FILTER_NORMAL) {
|
||||||
set_filter = (fattr->type == RC_FILTER_NORMAL) ? dev->s_filter :
|
set_filter = dev->s_filter;
|
||||||
dev->s_wakeup_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)
|
if (!set_filter)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&dev->lock);
|
mutex_lock(&dev->lock);
|
||||||
|
|
||||||
/* Tell the driver about the new filter */
|
new_filter = *filter;
|
||||||
filter = &dev->scancode_filters[fattr->type];
|
|
||||||
local_filter = *filter;
|
|
||||||
if (fattr->mask)
|
if (fattr->mask)
|
||||||
local_filter.mask = val;
|
new_filter.mask = val;
|
||||||
else
|
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 */
|
/* refuse to set a filter unless a protocol is enabled */
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = set_filter(dev, &local_filter);
|
ret = set_filter(dev, &new_filter);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
/* Success, commit the new filter */
|
*filter = new_filter;
|
||||||
*filter = local_filter;
|
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
mutex_unlock(&dev->lock);
|
mutex_unlock(&dev->lock);
|
||||||
return (ret < 0) ? ret : count;
|
return (ret < 0) ? ret : len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rc_dev_release(struct device *device)
|
static void rc_dev_release(struct device *device)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче