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: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
@@ -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);
|
|||||||
|
|
||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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;
|
|||||||
#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 {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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,12 +56,13 @@ enum raw_event_type {
|
|||||||
* is opened.
|
* is opened.
|
||||||
*/
|
*/
|
||||||
struct ir_dev_props {
|
struct ir_dev_props {
|
||||||
unsigned long allowed_protos;
|
enum rc_driver_type driver_type;
|
||||||
u32 scanmask;
|
unsigned long allowed_protos;
|
||||||
void *priv;
|
u32 scanmask;
|
||||||
int (*change_protocol)(void *priv, u64 ir_type);
|
void *priv;
|
||||||
int (*open)(void *priv);
|
int (*change_protocol)(void *priv, u64 ir_type);
|
||||||
void (*close)(void *priv);
|
int (*open)(void *priv);
|
||||||
|
void (*close)(void *priv);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ir_raw_event {
|
struct ir_raw_event {
|
||||||
|
Reference in New Issue
Block a user