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

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

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
Loading
Loading
Loading
Loading
+14 −3
Original line number Original line Diff line number Diff line
@@ -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);
+0 −2
Original line number Original line Diff line number Diff line
@@ -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)
{
{
+16 −9
Original line number Original line Diff line number Diff line
@@ -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);
+3 −6
Original line number Original line Diff line number Diff line
@@ -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;
+14 −6
Original line number Original line Diff line number Diff line
@@ -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,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;