Commit 626cf697 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

V4L/DVB: ir-core: Distinguish sysfs attributes for in-hardware and raw decoders

Some devices have in-hardware Remote Controller decoder, while others
need a software decoder to get the IR code. As each software decoder
can be enabled/disabled individually, allowing multiple protocol
decoding capability.

On the other hand, hardware decoders have a limited protocol
support, often being able of decoding just one protocol each time.
So, each type needs a different set of capabilities to control the
supported protocol(s).
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent de88f31c
...@@ -488,11 +488,19 @@ int __ir_input_register(struct input_dev *input_dev, ...@@ -488,11 +488,19 @@ int __ir_input_register(struct input_dev *input_dev,
if (rc < 0) if (rc < 0)
goto out_table; goto out_table;
if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) {
rc = ir_raw_event_register(input_dev);
if (rc < 0)
goto out_event;
}
IR_dprintk(1, "Registered input device on %s for %s remote.\n", IR_dprintk(1, "Registered input device on %s for %s remote.\n",
driver_name, rc_tab->name); driver_name, rc_tab->name);
return 0; return 0;
out_event:
ir_unregister_class(input_dev);
out_table: out_table:
kfree(ir_dev->rc_tab.scan); kfree(ir_dev->rc_tab.scan);
out_name: out_name:
...@@ -509,22 +517,25 @@ EXPORT_SYMBOL_GPL(__ir_input_register); ...@@ -509,22 +517,25 @@ EXPORT_SYMBOL_GPL(__ir_input_register);
* This routine is used to free memory and de-register interfaces. * This routine is used to free memory and de-register interfaces.
*/ */
void ir_input_unregister(struct input_dev *dev) void ir_input_unregister(struct input_dev *input_dev)
{ {
struct ir_input_dev *ir_dev = input_get_drvdata(dev); struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
struct ir_scancode_table *rc_tab; struct ir_scancode_table *rc_tab;
if (!ir_dev) if (!ir_dev)
return; return;
IR_dprintk(1, "Freed keycode table\n"); IR_dprintk(1, "Freed keycode table\n");
del_timer_sync(&ir_dev->timer_keyup); del_timer_sync(&ir_dev->timer_keyup);
if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
ir_raw_event_unregister(input_dev);
rc_tab = &ir_dev->rc_tab; rc_tab = &ir_dev->rc_tab;
rc_tab->size = 0; rc_tab->size = 0;
kfree(rc_tab->scan); kfree(rc_tab->scan);
rc_tab->scan = NULL; rc_tab->scan = NULL;
ir_unregister_class(dev); ir_unregister_class(input_dev);
kfree(ir_dev->driver_name); kfree(ir_dev->driver_name);
kfree(ir_dev); kfree(ir_dev);
......
...@@ -82,7 +82,6 @@ int ir_raw_event_register(struct input_dev *input_dev) ...@@ -82,7 +82,6 @@ int ir_raw_event_register(struct input_dev *input_dev)
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(ir_raw_event_register);
void ir_raw_event_unregister(struct input_dev *input_dev) void ir_raw_event_unregister(struct input_dev *input_dev)
{ {
...@@ -97,7 +96,6 @@ void ir_raw_event_unregister(struct input_dev *input_dev) ...@@ -97,7 +96,6 @@ void ir_raw_event_unregister(struct input_dev *input_dev)
kfree(ir->raw); kfree(ir->raw);
ir->raw = NULL; ir->raw = NULL;
} }
EXPORT_SYMBOL_GPL(ir_raw_event_unregister);
int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type) int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type)
{ {
......
...@@ -152,22 +152,26 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) ...@@ -152,22 +152,26 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env)
static DEVICE_ATTR(current_protocol, S_IRUGO | S_IWUSR, static DEVICE_ATTR(current_protocol, S_IRUGO | S_IWUSR,
show_protocol, store_protocol); show_protocol, store_protocol);
static struct attribute *ir_dev_attrs[] = { static struct attribute *ir_hw_dev_attrs[] = {
&dev_attr_current_protocol.attr, &dev_attr_current_protocol.attr,
NULL, NULL,
}; };
static struct attribute_group ir_dev_attr_grp = { static struct attribute_group ir_hw_dev_attr_grp = {
.attrs = ir_dev_attrs, .attrs = ir_hw_dev_attrs,
}; };
static const struct attribute_group *ir_dev_attr_groups[] = { static const struct attribute_group *ir_hw_dev_attr_groups[] = {
&ir_dev_attr_grp, &ir_hw_dev_attr_grp,
NULL NULL
}; };
static struct device_type ir_dev_type = { static struct device_type rc_dev_type = {
.groups = ir_dev_attr_groups, .groups = ir_hw_dev_attr_groups,
.uevent = ir_dev_uevent,
};
static struct device_type ir_raw_dev_type = {
.uevent = ir_dev_uevent, .uevent = ir_dev_uevent,
}; };
...@@ -181,7 +185,6 @@ int ir_register_class(struct input_dev *input_dev) ...@@ -181,7 +185,6 @@ int ir_register_class(struct input_dev *input_dev)
{ {
int rc; int rc;
const char *path; const char *path;
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
int devno = find_first_zero_bit(&ir_core_dev_number, int devno = find_first_zero_bit(&ir_core_dev_number,
IRRCV_NUM_DEVICES); IRRCV_NUM_DEVICES);
...@@ -189,7 +192,11 @@ int ir_register_class(struct input_dev *input_dev) ...@@ -189,7 +192,11 @@ int ir_register_class(struct input_dev *input_dev)
if (unlikely(devno < 0)) if (unlikely(devno < 0))
return devno; return devno;
ir_dev->dev.type = &ir_dev_type; if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
ir_dev->dev.type = &rc_dev_type;
else
ir_dev->dev.type = &ir_raw_dev_type;
ir_dev->dev.class = &ir_input_class; ir_dev->dev.class = &ir_input_class;
ir_dev->dev.parent = input_dev->dev.parent; ir_dev->dev.parent = input_dev->dev.parent;
dev_set_name(&ir_dev->dev, "rc%d", devno); dev_set_name(&ir_dev->dev, "rc%d", devno);
......
...@@ -855,6 +855,9 @@ int saa7134_input_init1(struct saa7134_dev *dev) ...@@ -855,6 +855,9 @@ int saa7134_input_init1(struct saa7134_dev *dev)
ir->props.open = saa7134_ir_open; ir->props.open = saa7134_ir_open;
ir->props.close = saa7134_ir_close; ir->props.close = saa7134_ir_close;
if (raw_decode)
ir->props.driver_type = RC_DRIVER_IR_RAW;
if (!raw_decode && allow_protocol_change) { if (!raw_decode && allow_protocol_change) {
ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC;
ir->props.change_protocol = saa7134_ir_change_protocol; ir->props.change_protocol = saa7134_ir_change_protocol;
...@@ -880,11 +883,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) ...@@ -880,11 +883,6 @@ int saa7134_input_init1(struct saa7134_dev *dev)
err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME);
if (err) if (err)
goto err_out_free; goto err_out_free;
if (raw_decode) {
err = ir_raw_event_register(ir->dev);
if (err)
goto err_out_free;
}
/* the remote isn't as bouncy as a keyboard */ /* the remote isn't as bouncy as a keyboard */
ir->dev->rep[REP_DELAY] = repeat_delay; ir->dev->rep[REP_DELAY] = repeat_delay;
...@@ -904,7 +902,6 @@ void saa7134_input_fini(struct saa7134_dev *dev) ...@@ -904,7 +902,6 @@ void saa7134_input_fini(struct saa7134_dev *dev)
return; return;
saa7134_ir_stop(dev); saa7134_ir_stop(dev);
ir_raw_event_unregister(dev->remote->dev);
ir_input_unregister(dev->remote->dev); ir_input_unregister(dev->remote->dev);
kfree(dev->remote); kfree(dev->remote);
dev->remote = NULL; dev->remote = NULL;
......
...@@ -26,6 +26,11 @@ extern int ir_core_debug; ...@@ -26,6 +26,11 @@ extern int ir_core_debug;
#define IR_dprintk(level, fmt, arg...) if (ir_core_debug >= level) \ #define IR_dprintk(level, fmt, arg...) if (ir_core_debug >= level) \
printk(KERN_DEBUG "%s: " fmt , __func__, ## arg) printk(KERN_DEBUG "%s: " fmt , __func__, ## arg)
enum rc_driver_type {
RC_DRIVER_SCANCODE = 0, /* Driver or hardware generates a scancode */
RC_DRIVER_IR_RAW, /* Needs a Infra-Red pulse/space decoder */
};
enum raw_event_type { enum raw_event_type {
IR_SPACE = (1 << 0), IR_SPACE = (1 << 0),
IR_PULSE = (1 << 1), IR_PULSE = (1 << 1),
...@@ -35,6 +40,8 @@ enum raw_event_type { ...@@ -35,6 +40,8 @@ enum raw_event_type {
/** /**
* struct ir_dev_props - Allow caller drivers to set special properties * struct ir_dev_props - Allow caller drivers to set special properties
* @driver_type: specifies if the driver or hardware have already a decoder,
* or if it needs to use the IR raw event decoders to produce a scancode
* @allowed_protos: bitmask with the supported IR_TYPE_* protocols * @allowed_protos: bitmask with the supported IR_TYPE_* protocols
* @scanmask: some hardware decoders are not capable of providing the full * @scanmask: some hardware decoders are not capable of providing the full
* scancode to the application. As this is a hardware limit, we can't do * scancode to the application. As this is a hardware limit, we can't do
...@@ -49,6 +56,7 @@ enum raw_event_type { ...@@ -49,6 +56,7 @@ enum raw_event_type {
* is opened. * is opened.
*/ */
struct ir_dev_props { struct ir_dev_props {
enum rc_driver_type driver_type;
unsigned long allowed_protos; unsigned long allowed_protos;
u32 scanmask; u32 scanmask;
void *priv; void *priv;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment