V4L/DVB: ir-nec-decoder: Add sysfs node to enable/disable per irrcv
With the help of raw_register/raw_unregister, adds a sysfs group associated with the decoder, inside the corresponding irrcv node. Writing 1 to nec_decoder/enabled enables the decoder, while writing 0 disables it. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Родитель
93c312ff21
Коммит
20d5f116ec
|
@ -39,6 +39,85 @@
|
||||||
|
|
||||||
#define REPEAT_TIME 240 /* ms */
|
#define REPEAT_TIME 240 /* ms */
|
||||||
|
|
||||||
|
/* Used to register nec_decoder clients */
|
||||||
|
static LIST_HEAD(decoder_list);
|
||||||
|
static spinlock_t decoder_lock;
|
||||||
|
|
||||||
|
struct decoder_data {
|
||||||
|
struct list_head list;
|
||||||
|
struct ir_input_dev *ir_dev;
|
||||||
|
int enabled:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get_decoder_data() - gets decoder data
|
||||||
|
* @input_dev: input device
|
||||||
|
*
|
||||||
|
* Returns the struct decoder_data that corresponds to a device
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
||||||
|
{
|
||||||
|
struct decoder_data *data = NULL;
|
||||||
|
|
||||||
|
spin_lock(&decoder_lock);
|
||||||
|
list_for_each_entry(data, &decoder_list, list) {
|
||||||
|
if (data->ir_dev == ir_dev)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
spin_unlock(&decoder_lock);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t store_enabled(struct device *d,
|
||||||
|
struct device_attribute *mattr,
|
||||||
|
const char *buf,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
unsigned long value;
|
||||||
|
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||||
|
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (strict_strtoul(buf, 10, &value) || value > 1)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
data->enabled = value;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_enabled(struct device *d,
|
||||||
|
struct device_attribute *mattr, char *buf)
|
||||||
|
{
|
||||||
|
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||||
|
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (data->enabled)
|
||||||
|
return sprintf(buf, "1\n");
|
||||||
|
else
|
||||||
|
return sprintf(buf, "0\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
|
||||||
|
|
||||||
|
static struct attribute *decoder_attributes[] = {
|
||||||
|
&dev_attr_enabled.attr,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute_group decoder_attribute_group = {
|
||||||
|
.name = "nec_decoder",
|
||||||
|
.attrs = decoder_attributes,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** is_repeat - Check if it is a NEC repeat event
|
/** is_repeat - Check if it is a NEC repeat event
|
||||||
* @input_dev: the struct input_dev descriptor of the device
|
* @input_dev: the struct input_dev descriptor of the device
|
||||||
* @pos: the position of the first event
|
* @pos: the position of the first event
|
||||||
|
@ -184,9 +263,15 @@ static int ir_nec_decode(struct input_dev *input_dev,
|
||||||
struct ir_raw_event *evs,
|
struct ir_raw_event *evs,
|
||||||
int len)
|
int len)
|
||||||
{
|
{
|
||||||
|
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||||
|
struct decoder_data *data;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
data = get_decoder_data(ir_dev);
|
||||||
|
if (!data || !data->enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
while (pos < len) {
|
while (pos < len) {
|
||||||
if (__ir_nec_decode(input_dev, evs, len, &pos) > 0)
|
if (__ir_nec_decode(input_dev, evs, len, &pos) > 0)
|
||||||
rc++;
|
rc++;
|
||||||
|
@ -194,8 +279,54 @@ static int ir_nec_decode(struct input_dev *input_dev,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ir_nec_register(struct input_dev *input_dev)
|
||||||
|
{
|
||||||
|
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||||
|
struct decoder_data *data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||||
|
if (!data) {
|
||||||
|
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->ir_dev = ir_dev;
|
||||||
|
data->enabled = 1;
|
||||||
|
|
||||||
|
spin_lock(&decoder_lock);
|
||||||
|
list_add_tail(&data->list, &decoder_list);
|
||||||
|
spin_unlock(&decoder_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ir_nec_unregister(struct input_dev *input_dev)
|
||||||
|
{
|
||||||
|
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||||
|
static struct decoder_data *data;
|
||||||
|
|
||||||
|
data = get_decoder_data(ir_dev);
|
||||||
|
if (!data)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||||
|
|
||||||
|
spin_lock(&decoder_lock);
|
||||||
|
list_del(&data->list);
|
||||||
|
spin_unlock(&decoder_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct ir_raw_handler nec_handler = {
|
static struct ir_raw_handler nec_handler = {
|
||||||
.decode = ir_nec_decode,
|
.decode = ir_nec_decode,
|
||||||
|
.raw_register = ir_nec_register,
|
||||||
|
.raw_unregister = ir_nec_unregister,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init ir_nec_decode_init(void)
|
static int __init ir_nec_decode_init(void)
|
||||||
|
|
|
@ -223,7 +223,7 @@ static void init_decoders(struct work_struct *work)
|
||||||
void ir_raw_init(void)
|
void ir_raw_init(void)
|
||||||
{
|
{
|
||||||
spin_lock_init(&ir_raw_handler_lock);
|
spin_lock_init(&ir_raw_handler_lock);
|
||||||
|
|
||||||
#ifdef MODULE
|
#ifdef MODULE
|
||||||
INIT_WORK(&wq_load, init_decoders);
|
INIT_WORK(&wq_load, init_decoders);
|
||||||
schedule_work(&wq_load);
|
schedule_work(&wq_load);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче