From 7366646e20f8800433333a7102e3ce488215e33f Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Tue, 1 Jun 2010 17:27:07 -0300 Subject: V4L/DVB: IR: only initially registers protocol that matches loaded keymap Rather than registering all IR protocol decoders as enabled when bringing up a new device, only enable the IR protocol decoder that matches the keymap being loaded. Additional decoders can be enabled on the fly by those that need to, either by twiddling sysfs bits or by using the ir-keytable util from v4l-utils. Functional testing done with the mceusb driver, and it behaves as expected, only the rc6 decoder is enabled, keys are all handled properly, etc. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/IR/ir-nec-decoder.c') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index ba79233112ef..6059a1f1e151 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -260,6 +260,7 @@ 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; + u64 ir_type = ir_dev->rc_tab.ir_type; int rc; rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); @@ -273,7 +274,8 @@ static int ir_nec_register(struct input_dev *input_dev) } data->ir_dev = ir_dev; - data->enabled = 1; + if (ir_type == IR_TYPE_NEC || ir_type == IR_TYPE_UNKNOWN) + data->enabled = 1; spin_lock(&decoder_lock); list_add_tail(&data->list, &decoder_list); -- cgit v1.2.3 From 667c9ebe97f7e5f1e48e7eb321644c6fb1668de5 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 13 Jun 2010 17:29:31 -0300 Subject: V4L/DVB: ir-core: centralize sysfs raw decoder enabling/disabling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the current logic, each raw decoder needs to add a copy of the exact same sysfs code. This is both unnecessary and also means that (re)loading an IR driver after raw decoder modules have been loaded won't work as expected. This patch moves that logic into ir-raw-event and adds a single sysfs file per device. Reading that file returns something like: "rc5 [rc6] nec jvc [sony]" (with enabled protocols in [] brackets) Writing either "+protocol" or "-protocol" to that file will enable or disable the according protocol decoder. An additional benefit is that the disabling of a decoder will be remembered across module removal/insertion so a previously disabled decoder won't suddenly be activated again. The default setting is to enable all decoders. This is also necessary for the next patch which moves even more decoder state into the central raw decoding structs. Signed-off-by: David Härdeman Acked-by: Jarod Wilson Tested-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-core-priv.h | 3 + drivers/media/IR/ir-jvc-decoder.c | 65 +--------- drivers/media/IR/ir-nec-decoder.c | 65 +--------- drivers/media/IR/ir-raw-event.c | 112 ++++++++++------- drivers/media/IR/ir-rc5-decoder.c | 67 +--------- drivers/media/IR/ir-rc6-decoder.c | 65 +--------- drivers/media/IR/ir-sony-decoder.c | 65 +--------- drivers/media/IR/ir-sysfs.c | 252 ++++++++++++++++++++++--------------- 8 files changed, 232 insertions(+), 462 deletions(-) (limited to 'drivers/media/IR/ir-nec-decoder.c') diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h index 9a5e65a471a5..5111dc23909a 100644 --- a/drivers/media/IR/ir-core-priv.h +++ b/drivers/media/IR/ir-core-priv.h @@ -22,6 +22,7 @@ struct ir_raw_handler { struct list_head list; + u64 protocols; /* which are handled by this handler */ int (*decode)(struct input_dev *input_dev, struct ir_raw_event event); int (*raw_register)(struct input_dev *input_dev); int (*raw_unregister)(struct input_dev *input_dev); @@ -33,6 +34,7 @@ struct ir_raw_event_ctrl { ktime_t last_event; /* when last event occurred */ enum raw_event_type last_type; /* last event type */ struct input_dev *input_dev; /* pointer to the parent input_dev */ + u64 enabled_protocols; /* enabled raw protocol decoders */ }; /* macros for IR decoders */ @@ -74,6 +76,7 @@ void ir_unregister_class(struct input_dev *input_dev); /* * Routines from ir-raw-event.c to be used internally and by decoders */ +u64 ir_raw_get_allowed_protocols(void); int ir_raw_event_register(struct input_dev *input_dev); void ir_raw_event_unregister(struct input_dev *input_dev); int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); diff --git a/drivers/media/IR/ir-jvc-decoder.c b/drivers/media/IR/ir-jvc-decoder.c index b02e8013b9bb..b1f935884d30 100644 --- a/drivers/media/IR/ir-jvc-decoder.c +++ b/drivers/media/IR/ir-jvc-decoder.c @@ -41,7 +41,6 @@ enum jvc_state { struct decoder_data { struct list_head list; struct ir_input_dev *ir_dev; - int enabled:1; /* State machine control */ enum jvc_state state; @@ -72,53 +71,6 @@ static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) 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 = "jvc_decoder", - .attrs = decoder_attributes, -}; - /** * ir_jvc_decode() - Decode one JVC pulse or space * @input_dev: the struct input_dev descriptor of the device @@ -135,7 +87,7 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) if (!data) return -EINVAL; - if (!data->enabled) + if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC)) return 0; if (IS_RESET(ev)) { @@ -253,22 +205,12 @@ static int ir_jvc_register(struct input_dev *input_dev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); struct decoder_data *data; - u64 ir_type = ir_dev->rc_tab.ir_type; - 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); + if (!data) return -ENOMEM; - } data->ir_dev = ir_dev; - if (ir_type == IR_TYPE_JVC || ir_type == IR_TYPE_UNKNOWN) - data->enabled = 1; spin_lock(&decoder_lock); list_add_tail(&data->list, &decoder_list); @@ -286,8 +228,6 @@ static int ir_jvc_unregister(struct input_dev *input_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); @@ -296,6 +236,7 @@ static int ir_jvc_unregister(struct input_dev *input_dev) } static struct ir_raw_handler jvc_handler = { + .protocols = IR_TYPE_JVC, .decode = ir_jvc_decode, .raw_register = ir_jvc_register, .raw_unregister = ir_jvc_unregister, diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 6059a1f1e151..db62c652dfc5 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -43,7 +43,6 @@ enum nec_state { struct decoder_data { struct list_head list; struct ir_input_dev *ir_dev; - int enabled:1; /* State machine control */ enum nec_state state; @@ -71,53 +70,6 @@ static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) 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, -}; - /** * ir_nec_decode() - Decode one NEC pulse or space * @input_dev: the struct input_dev descriptor of the device @@ -136,7 +88,7 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) if (!data) return -EINVAL; - if (!data->enabled) + if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC)) return 0; if (IS_RESET(ev)) { @@ -260,22 +212,12 @@ 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; - u64 ir_type = ir_dev->rc_tab.ir_type; - 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); + if (!data) return -ENOMEM; - } data->ir_dev = ir_dev; - if (ir_type == IR_TYPE_NEC || ir_type == IR_TYPE_UNKNOWN) - data->enabled = 1; spin_lock(&decoder_lock); list_add_tail(&data->list, &decoder_list); @@ -293,8 +235,6 @@ static int ir_nec_unregister(struct input_dev *input_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); @@ -303,6 +243,7 @@ static int ir_nec_unregister(struct input_dev *input_dev) } static struct ir_raw_handler nec_handler = { + .protocols = IR_TYPE_NEC, .decode = ir_nec_decode, .raw_register = ir_nec_register, .raw_unregister = ir_nec_unregister, diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index d3bd3f98e008..fb3336c37191 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -21,8 +21,9 @@ #define MAX_IR_EVENT_SIZE 512 /* Used to handle IR raw handler extensions */ -static LIST_HEAD(ir_raw_handler_list); static DEFINE_SPINLOCK(ir_raw_handler_lock); +static LIST_HEAD(ir_raw_handler_list); +static u64 available_protocols; /** * RUN_DECODER() - runs an operation on all IR decoders @@ -64,52 +65,6 @@ static void ir_raw_event_work(struct work_struct *work) RUN_DECODER(decode, raw->input_dev, ev); } -int ir_raw_event_register(struct input_dev *input_dev) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - int rc; - - ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); - if (!ir->raw) - return -ENOMEM; - - ir->raw->input_dev = input_dev; - INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); - - rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, - GFP_KERNEL); - if (rc < 0) { - kfree(ir->raw); - ir->raw = NULL; - return rc; - } - - rc = RUN_DECODER(raw_register, input_dev); - if (rc < 0) { - kfifo_free(&ir->raw->kfifo); - kfree(ir->raw); - ir->raw = NULL; - return rc; - } - - return rc; -} - -void ir_raw_event_unregister(struct input_dev *input_dev) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - - if (!ir->raw) - return; - - cancel_work_sync(&ir->raw->rx_work); - RUN_DECODER(raw_unregister, input_dev); - - kfifo_free(&ir->raw->kfifo); - kfree(ir->raw); - ir->raw = NULL; -} - /** * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders * @input_dev: the struct input_dev device descriptor @@ -203,6 +158,66 @@ void ir_raw_event_handle(struct input_dev *input_dev) } EXPORT_SYMBOL_GPL(ir_raw_event_handle); +/* used internally by the sysfs interface */ +u64 +ir_raw_get_allowed_protocols() +{ + u64 protocols; + spin_lock(&ir_raw_handler_lock); + protocols = available_protocols; + spin_unlock(&ir_raw_handler_lock); + return protocols; +} + +/* + * Used to (un)register raw event clients + */ +int ir_raw_event_register(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + int rc; + + ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); + if (!ir->raw) + return -ENOMEM; + + ir->raw->input_dev = input_dev; + INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); + ir->raw->enabled_protocols = ~0; + rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, + GFP_KERNEL); + if (rc < 0) { + kfree(ir->raw); + ir->raw = NULL; + return rc; + } + + rc = RUN_DECODER(raw_register, input_dev); + if (rc < 0) { + kfifo_free(&ir->raw->kfifo); + kfree(ir->raw); + ir->raw = NULL; + return rc; + } + + return rc; +} + +void ir_raw_event_unregister(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + + if (!ir->raw) + return; + + cancel_work_sync(&ir->raw->rx_work); + RUN_DECODER(raw_unregister, input_dev); + + kfifo_free(&ir->raw->kfifo); + kfree(ir->raw); + ir->raw = NULL; +} + /* * Extension interface - used to register the IR decoders */ @@ -211,7 +226,9 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) { spin_lock(&ir_raw_handler_lock); list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); + available_protocols |= ir_raw_handler->protocols; spin_unlock(&ir_raw_handler_lock); + return 0; } EXPORT_SYMBOL(ir_raw_handler_register); @@ -220,6 +237,7 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) { spin_lock(&ir_raw_handler_lock); list_del(&ir_raw_handler->list); + available_protocols &= ~ir_raw_handler->protocols; spin_unlock(&ir_raw_handler_lock); } EXPORT_SYMBOL(ir_raw_handler_unregister); diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c index 4aa797bc69fd..bdfa404a6537 100644 --- a/drivers/media/IR/ir-rc5-decoder.c +++ b/drivers/media/IR/ir-rc5-decoder.c @@ -45,7 +45,6 @@ enum rc5_state { struct decoder_data { struct list_head list; struct ir_input_dev *ir_dev; - int enabled:1; /* State machine control */ enum rc5_state state; @@ -76,53 +75,6 @@ static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) 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 = "rc5_decoder", - .attrs = decoder_attributes, -}; - /** * ir_rc5_decode() - Decode one RC-5 pulse or space * @input_dev: the struct input_dev descriptor of the device @@ -141,8 +93,8 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev) if (!data) return -EINVAL; - if (!data->enabled) - return 0; + if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5)) + return 0; if (IS_RESET(ev)) { data->state = STATE_INACTIVE; @@ -256,22 +208,12 @@ static int ir_rc5_register(struct input_dev *input_dev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); struct decoder_data *data; - u64 ir_type = ir_dev->rc_tab.ir_type; - 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); + if (!data) return -ENOMEM; - } data->ir_dev = ir_dev; - if (ir_type == IR_TYPE_RC5 || ir_type == IR_TYPE_UNKNOWN) - data->enabled = 1; spin_lock(&decoder_lock); list_add_tail(&data->list, &decoder_list); @@ -289,8 +231,6 @@ static int ir_rc5_unregister(struct input_dev *input_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); @@ -299,6 +239,7 @@ static int ir_rc5_unregister(struct input_dev *input_dev) } static struct ir_raw_handler rc5_handler = { + .protocols = IR_TYPE_RC5, .decode = ir_rc5_decode, .raw_register = ir_rc5_register, .raw_unregister = ir_rc5_unregister, diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c index 9f61da29face..2ebd4ea69538 100644 --- a/drivers/media/IR/ir-rc6-decoder.c +++ b/drivers/media/IR/ir-rc6-decoder.c @@ -61,7 +61,6 @@ enum rc6_state { struct decoder_data { struct list_head list; struct ir_input_dev *ir_dev; - int enabled:1; /* State machine control */ enum rc6_state state; @@ -93,53 +92,6 @@ static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) 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 = "rc6_decoder", - .attrs = decoder_attributes, -}; - static enum rc6_mode rc6_mode(struct decoder_data *data) { switch (data->header & RC6_MODE_MASK) { case 0: @@ -171,7 +123,7 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev) if (!data) return -EINVAL; - if (!data->enabled) + if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6)) return 0; if (IS_RESET(ev)) { @@ -352,22 +304,12 @@ static int ir_rc6_register(struct input_dev *input_dev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); struct decoder_data *data; - u64 ir_type = ir_dev->rc_tab.ir_type; - 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); + if (!data) return -ENOMEM; - } data->ir_dev = ir_dev; - if (ir_type == IR_TYPE_RC6 || ir_type == IR_TYPE_UNKNOWN) - data->enabled = 1; spin_lock(&decoder_lock); list_add_tail(&data->list, &decoder_list); @@ -385,8 +327,6 @@ static int ir_rc6_unregister(struct input_dev *input_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); @@ -395,6 +335,7 @@ static int ir_rc6_unregister(struct input_dev *input_dev) } static struct ir_raw_handler rc6_handler = { + .protocols = IR_TYPE_RC6, .decode = ir_rc6_decode, .raw_register = ir_rc6_register, .raw_unregister = ir_rc6_unregister, diff --git a/drivers/media/IR/ir-sony-decoder.c b/drivers/media/IR/ir-sony-decoder.c index 219075ffd6b7..e15db3334998 100644 --- a/drivers/media/IR/ir-sony-decoder.c +++ b/drivers/media/IR/ir-sony-decoder.c @@ -38,7 +38,6 @@ enum sony_state { struct decoder_data { struct list_head list; struct ir_input_dev *ir_dev; - int enabled:1; /* State machine control */ enum sony_state state; @@ -66,53 +65,6 @@ static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) 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 = "sony_decoder", - .attrs = decoder_attributes, -}; - /** * ir_sony_decode() - Decode one Sony pulse or space * @input_dev: the struct input_dev descriptor of the device @@ -131,7 +83,7 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) if (!data) return -EINVAL; - if (!data->enabled) + if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY)) return 0; if (IS_RESET(ev)) { @@ -245,22 +197,12 @@ static int ir_sony_register(struct input_dev *input_dev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); struct decoder_data *data; - u64 ir_type = ir_dev->rc_tab.ir_type; - 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); + if (!data) return -ENOMEM; - } data->ir_dev = ir_dev; - if (ir_type == IR_TYPE_SONY || ir_type == IR_TYPE_UNKNOWN) - data->enabled = 1; spin_lock(&decoder_lock); list_add_tail(&data->list, &decoder_list); @@ -278,8 +220,6 @@ static int ir_sony_unregister(struct input_dev *input_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); @@ -288,6 +228,7 @@ static int ir_sony_unregister(struct input_dev *input_dev) } static struct ir_raw_handler sony_handler = { + .protocols = IR_TYPE_SONY, .decode = ir_sony_decode, .raw_register = ir_sony_register, .raw_unregister = ir_sony_unregister, diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 2098dd1488e0..005621d067f0 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -34,122 +34,178 @@ static struct class ir_input_class = { }; /** - * show_protocol() - shows the current IR protocol + * show_protocols() - shows the current IR protocol(s) * @d: the device descriptor * @mattr: the device attribute struct (unused) * @buf: a pointer to the output buffer * - * This routine is a callback routine for input read the IR protocol type. - * it is trigged by reading /sys/class/rc/rc?/current_protocol. - * It returns the protocol name, as understood by the driver. + * This routine is a callback routine for input read the IR protocol type(s). + * it is trigged by reading /sys/class/rc/rc?/protocols. + * It returns the protocol names of supported protocols. + * Enabled protocols are printed in brackets. */ -static ssize_t show_protocol(struct device *d, - struct device_attribute *mattr, char *buf) +static ssize_t show_protocols(struct device *d, + struct device_attribute *mattr, char *buf) { - char *s; struct ir_input_dev *ir_dev = dev_get_drvdata(d); - u64 ir_type = ir_dev->rc_tab.ir_type; - - IR_dprintk(1, "Current protocol is %lld\n", (long long)ir_type); - - /* FIXME: doesn't support multiple protocols at the same time */ - if (ir_type == IR_TYPE_UNKNOWN) - s = "Unknown"; - else if (ir_type == IR_TYPE_RC5) - s = "rc-5"; - else if (ir_type == IR_TYPE_NEC) - s = "nec"; - else if (ir_type == IR_TYPE_RC6) - s = "rc6"; - else if (ir_type == IR_TYPE_JVC) - s = "jvc"; - else if (ir_type == IR_TYPE_SONY) - s = "sony"; - else - s = "other"; + u64 allowed, enabled; + char *tmp = buf; + + if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + enabled = ir_dev->rc_tab.ir_type; + allowed = ir_dev->props->allowed_protos; + } else { + enabled = ir_dev->raw->enabled_protocols; + allowed = ir_raw_get_allowed_protocols(); + } - return sprintf(buf, "%s\n", s); + IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", + (long long)allowed, + (long long)enabled); + + if (allowed & enabled & IR_TYPE_UNKNOWN) + tmp += sprintf(tmp, "[unknown] "); + else if (allowed & IR_TYPE_UNKNOWN) + tmp += sprintf(tmp, "unknown "); + + if (allowed & enabled & IR_TYPE_RC5) + tmp += sprintf(tmp, "[rc5] "); + else if (allowed & IR_TYPE_RC5) + tmp += sprintf(tmp, "rc5 "); + + if (allowed & enabled & IR_TYPE_NEC) + tmp += sprintf(tmp, "[nec] "); + else if (allowed & IR_TYPE_NEC) + tmp += sprintf(tmp, "nec "); + + if (allowed & enabled & IR_TYPE_RC6) + tmp += sprintf(tmp, "[rc6] "); + else if (allowed & IR_TYPE_RC6) + tmp += sprintf(tmp, "rc6 "); + + if (allowed & enabled & IR_TYPE_JVC) + tmp += sprintf(tmp, "[jvc] "); + else if (allowed & IR_TYPE_JVC) + tmp += sprintf(tmp, "jvc "); + + if (allowed & enabled & IR_TYPE_SONY) + tmp += sprintf(tmp, "[sony] "); + else if (allowed & IR_TYPE_SONY) + tmp += sprintf(tmp, "sony "); + + if (tmp != buf) + tmp--; + *tmp = '\n'; + return tmp + 1 - buf; } /** - * store_protocol() - shows the current IR protocol + * store_protocols() - changes the current IR protocol(s) * @d: the device descriptor * @mattr: the device attribute struct (unused) * @buf: a pointer to the input buffer * @len: length of the input buffer * * This routine is a callback routine for changing the IR protocol type. - * it is trigged by reading /sys/class/rc/rc?/current_protocol. - * It changes the IR the protocol name, if the IR type is recognized - * by the driver. - * If an unknown protocol name is used, returns -EINVAL. + * It is trigged by writing to /sys/class/rc/rc?/protocols. + * 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". + * Returns -EINVAL if an invalid protocol combination or unknown protocol name + * is used, otherwise @len. */ -static ssize_t store_protocol(struct device *d, - struct device_attribute *mattr, - const char *data, - size_t len) +static ssize_t store_protocols(struct device *d, + struct device_attribute *mattr, + const char *data, + size_t len) { struct ir_input_dev *ir_dev = dev_get_drvdata(d); - u64 ir_type = 0; - int rc = -EINVAL; + bool enable, disable; + const char *tmp; + u64 type; + u64 mask; + int rc; unsigned long flags; - char *buf; - - while ((buf = strsep((char **) &data, " \n")) != NULL) { - if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5")) - ir_type |= IR_TYPE_RC5; - if (!strcasecmp(buf, "nec")) - ir_type |= IR_TYPE_NEC; - if (!strcasecmp(buf, "jvc")) - ir_type |= IR_TYPE_JVC; - if (!strcasecmp(buf, "sony")) - ir_type |= IR_TYPE_SONY; + + tmp = skip_spaces(data); + + if (*tmp == '+') { + enable = true; + disable = false; + tmp++; + } else if (*tmp == '-') { + enable = false; + disable = true; + tmp++; + } else { + enable = false; + disable = false; } - if (!ir_type) { + if (!strncasecmp(tmp, "unknown", 7)) { + tmp += 7; + mask = IR_TYPE_UNKNOWN; + } else if (!strncasecmp(tmp, "rc5", 3)) { + tmp += 3; + mask = IR_TYPE_RC5; + } else if (!strncasecmp(tmp, "nec", 3)) { + tmp += 3; + mask = IR_TYPE_NEC; + } else if (!strncasecmp(tmp, "rc6", 3)) { + tmp += 3; + mask = IR_TYPE_RC6; + } else if (!strncasecmp(tmp, "jvc", 3)) { + tmp += 3; + mask = IR_TYPE_JVC; + } else if (!strncasecmp(tmp, "sony", 4)) { + tmp += 4; + mask = IR_TYPE_SONY; + } else { IR_dprintk(1, "Unknown protocol\n"); return -EINVAL; } - if (ir_dev->props && ir_dev->props->change_protocol) - rc = ir_dev->props->change_protocol(ir_dev->props->priv, - ir_type); - - if (rc < 0) { - IR_dprintk(1, "Error setting protocol to %lld\n", - (long long)ir_type); + tmp = skip_spaces(tmp); + if (*tmp != '\0') { + IR_dprintk(1, "Invalid trailing characters\n"); return -EINVAL; } - spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); - ir_dev->rc_tab.ir_type = ir_type; - spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); + if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) + type = ir_dev->rc_tab.ir_type; + else + type = ir_dev->raw->enabled_protocols; - IR_dprintk(1, "Current protocol(s) is(are) %lld\n", - (long long)ir_type); + if (enable) + type |= mask; + else if (disable) + type &= ~mask; + else + type = mask; - return len; -} + if (ir_dev->props && ir_dev->props->change_protocol) { + rc = ir_dev->props->change_protocol(ir_dev->props->priv, + type); + if (rc < 0) { + IR_dprintk(1, "Error setting protocols to 0x%llx\n", + (long long)type); + return -EINVAL; + } + } -static ssize_t show_supported_protocols(struct device *d, - struct device_attribute *mattr, char *buf) -{ - char *orgbuf = buf; - struct ir_input_dev *ir_dev = dev_get_drvdata(d); + if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); + ir_dev->rc_tab.ir_type = type; + spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); + } else { + ir_dev->raw->enabled_protocols = type; + } - /* FIXME: doesn't support multiple protocols at the same time */ - if (ir_dev->props->allowed_protos == IR_TYPE_UNKNOWN) - buf += sprintf(buf, "unknown "); - if (ir_dev->props->allowed_protos & IR_TYPE_RC5) - buf += sprintf(buf, "rc-5 "); - if (ir_dev->props->allowed_protos & IR_TYPE_NEC) - buf += sprintf(buf, "nec "); - if (buf == orgbuf) - buf += sprintf(buf, "other "); - buf += sprintf(buf - 1, "\n"); + IR_dprintk(1, "Current protocol(s): 0x%llx\n", + (long long)type); - return buf - orgbuf; + return len; } #define ADD_HOTPLUG_VAR(fmt, val...) \ @@ -159,7 +215,7 @@ static ssize_t show_supported_protocols(struct device *d, return err; \ } while (0) -static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) +static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) { struct ir_input_dev *ir_dev = dev_get_drvdata(device); @@ -174,34 +230,26 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) /* * Static device attribute struct with the sysfs attributes for IR's */ -static DEVICE_ATTR(protocol, S_IRUGO | S_IWUSR, - show_protocol, store_protocol); - -static DEVICE_ATTR(supported_protocols, S_IRUGO | S_IWUSR, - show_supported_protocols, NULL); +static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR, + show_protocols, store_protocols); -static struct attribute *ir_hw_dev_attrs[] = { - &dev_attr_protocol.attr, - &dev_attr_supported_protocols.attr, +static struct attribute *rc_dev_attrs[] = { + &dev_attr_protocols.attr, NULL, }; -static struct attribute_group ir_hw_dev_attr_grp = { - .attrs = ir_hw_dev_attrs, +static struct attribute_group rc_dev_attr_grp = { + .attrs = rc_dev_attrs, }; -static const struct attribute_group *ir_hw_dev_attr_groups[] = { - &ir_hw_dev_attr_grp, +static const struct attribute_group *rc_dev_attr_groups[] = { + &rc_dev_attr_grp, NULL }; static struct device_type rc_dev_type = { - .groups = ir_hw_dev_attr_groups, - .uevent = ir_dev_uevent, -}; - -static struct device_type ir_raw_dev_type = { - .uevent = ir_dev_uevent, + .groups = rc_dev_attr_groups, + .uevent = rc_dev_uevent, }; /** @@ -221,11 +269,7 @@ int ir_register_class(struct input_dev *input_dev) if (unlikely(devno < 0)) return devno; - if (ir_dev->props) { - 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.type = &rc_dev_type; ir_dev->dev.class = &ir_input_class; ir_dev->dev.parent = input_dev->dev.parent; -- cgit v1.2.3 From c216369e61fae586cd48c0913cca2a37fbfeb912 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Sun, 13 Jun 2010 17:29:36 -0300 Subject: V4L/DVB: ir-core: move decoding state to ir_raw_event_ctrl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch moves the state from each raw decoder into the ir_raw_event_ctrl struct. This allows the removal of code like this: 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; which is currently run for each decoder on each event in order to get the client-specific decoding state data. In addition, ir decoding modules and ir driver module load order is now independent. Centralizing the data also allows for a nice code reduction of about 30% per raw decoder as client lists and client registration callbacks are no longer necessary (but still kept around for the benefit of the lirc decoder). Out-of-tree modules can still use a similar trick to what the raw decoders did before this patch until they are merged. Signed-off-by: David Härdeman Acked-by: Jarod Wilson Tested-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-core-priv.h | 38 ++++++++++++++ drivers/media/IR/ir-jvc-decoder.c | 91 +++----------------------------- drivers/media/IR/ir-nec-decoder.c | 90 +++----------------------------- drivers/media/IR/ir-raw-event.c | 73 +++++++++++++------------- drivers/media/IR/ir-rc5-decoder.c | 104 +++++-------------------------------- drivers/media/IR/ir-rc6-decoder.c | 92 ++------------------------------ drivers/media/IR/ir-sony-decoder.c | 94 ++++----------------------------- 7 files changed, 118 insertions(+), 464 deletions(-) (limited to 'drivers/media/IR/ir-nec-decoder.c') diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h index 5111dc23909a..0a82b22d3828 100644 --- a/drivers/media/IR/ir-core-priv.h +++ b/drivers/media/IR/ir-core-priv.h @@ -24,17 +24,55 @@ struct ir_raw_handler { u64 protocols; /* which are handled by this handler */ int (*decode)(struct input_dev *input_dev, struct ir_raw_event event); + + /* These two should only be used by the lirc decoder */ int (*raw_register)(struct input_dev *input_dev); int (*raw_unregister)(struct input_dev *input_dev); }; struct ir_raw_event_ctrl { + struct list_head list; /* to keep track of raw clients */ struct work_struct rx_work; /* for the rx decoding workqueue */ struct kfifo kfifo; /* fifo for the pulse/space durations */ ktime_t last_event; /* when last event occurred */ enum raw_event_type last_type; /* last event type */ struct input_dev *input_dev; /* pointer to the parent input_dev */ u64 enabled_protocols; /* enabled raw protocol decoders */ + + /* raw decoder state follows */ + struct ir_raw_event prev_ev; + struct nec_dec { + int state; + unsigned count; + u32 bits; + } nec; + struct rc5_dec { + int state; + u32 bits; + unsigned count; + unsigned wanted_bits; + } rc5; + struct rc6_dec { + int state; + u8 header; + u32 body; + bool toggle; + unsigned count; + unsigned wanted_bits; + } rc6; + struct sony_dec { + int state; + u32 bits; + unsigned count; + } sony; + struct jvc_dec { + int state; + u16 bits; + u16 old_bits; + unsigned count; + bool first; + bool toggle; + } jvc; }; /* macros for IR decoders */ diff --git a/drivers/media/IR/ir-jvc-decoder.c b/drivers/media/IR/ir-jvc-decoder.c index b1f935884d30..8894d8b36048 100644 --- a/drivers/media/IR/ir-jvc-decoder.c +++ b/drivers/media/IR/ir-jvc-decoder.c @@ -25,10 +25,6 @@ #define JVC_TRAILER_PULSE (1 * JVC_UNIT) #define JVC_TRAILER_SPACE (35 * JVC_UNIT) -/* Used to register jvc_decoder clients */ -static LIST_HEAD(decoder_list); -DEFINE_SPINLOCK(decoder_lock); - enum jvc_state { STATE_INACTIVE, STATE_HEADER_SPACE, @@ -38,39 +34,6 @@ enum jvc_state { STATE_TRAILER_SPACE, }; -struct decoder_data { - struct list_head list; - struct ir_input_dev *ir_dev; - - /* State machine control */ - enum jvc_state state; - u16 jvc_bits; - u16 jvc_old_bits; - unsigned count; - bool first; - bool toggle; -}; - - -/** - * 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; -} - /** * ir_jvc_decode() - Decode one JVC pulse or space * @input_dev: the struct input_dev descriptor of the device @@ -80,12 +43,8 @@ static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) */ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) { - struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - - data = get_decoder_data(ir_dev); - if (!data) - return -EINVAL; + struct jvc_dec *data = &ir_dev->raw->jvc; if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC)) return 0; @@ -140,9 +99,9 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) if (ev.pulse) break; - data->jvc_bits <<= 1; + data->bits <<= 1; if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) { - data->jvc_bits |= 1; + data->bits |= 1; decrease_duration(&ev, JVC_BIT_1_SPACE); } else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2)) decrease_duration(&ev, JVC_BIT_0_SPACE); @@ -175,13 +134,13 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) if (data->first) { u32 scancode; - scancode = (bitrev8((data->jvc_bits >> 8) & 0xff) << 8) | - (bitrev8((data->jvc_bits >> 0) & 0xff) << 0); + scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) | + (bitrev8((data->bits >> 0) & 0xff) << 0); IR_dprintk(1, "JVC scancode 0x%04x\n", scancode); ir_keydown(input_dev, scancode, data->toggle); data->first = false; - data->jvc_old_bits = data->jvc_bits; - } else if (data->jvc_bits == data->jvc_old_bits) { + data->old_bits = data->bits; + } else if (data->bits == data->old_bits) { IR_dprintk(1, "JVC repeat\n"); ir_repeat(input_dev); } else { @@ -201,45 +160,9 @@ out: return -EINVAL; } -static int ir_jvc_register(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct decoder_data *data; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->ir_dev = ir_dev; - - spin_lock(&decoder_lock); - list_add_tail(&data->list, &decoder_list); - spin_unlock(&decoder_lock); - - return 0; -} - -static int ir_jvc_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; - - spin_lock(&decoder_lock); - list_del(&data->list); - spin_unlock(&decoder_lock); - - return 0; -} - static struct ir_raw_handler jvc_handler = { .protocols = IR_TYPE_JVC, .decode = ir_jvc_decode, - .raw_register = ir_jvc_register, - .raw_unregister = ir_jvc_unregister, }; static int __init ir_jvc_decode_init(void) diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index db62c652dfc5..52e0f378ae3d 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -27,10 +27,6 @@ #define NEC_TRAILER_PULSE (1 * NEC_UNIT) #define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */ -/* Used to register nec_decoder clients */ -static LIST_HEAD(decoder_list); -static DEFINE_SPINLOCK(decoder_lock); - enum nec_state { STATE_INACTIVE, STATE_HEADER_SPACE, @@ -40,36 +36,6 @@ enum nec_state { STATE_TRAILER_SPACE, }; -struct decoder_data { - struct list_head list; - struct ir_input_dev *ir_dev; - - /* State machine control */ - enum nec_state state; - u32 nec_bits; - unsigned count; -}; - - -/** - * 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; -} - /** * ir_nec_decode() - Decode one NEC pulse or space * @input_dev: the struct input_dev descriptor of the device @@ -79,15 +45,11 @@ static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) */ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) { - struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct nec_dec *data = &ir_dev->raw->nec; u32 scancode; u8 address, not_address, command, not_command; - data = get_decoder_data(ir_dev); - if (!data) - return -EINVAL; - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC)) return 0; @@ -143,9 +105,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) if (ev.pulse) break; - data->nec_bits <<= 1; + data->bits <<= 1; if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2)) - data->nec_bits |= 1; + data->bits |= 1; else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2)) break; data->count++; @@ -174,14 +136,14 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) break; - address = bitrev8((data->nec_bits >> 24) & 0xff); - not_address = bitrev8((data->nec_bits >> 16) & 0xff); - command = bitrev8((data->nec_bits >> 8) & 0xff); - not_command = bitrev8((data->nec_bits >> 0) & 0xff); + address = bitrev8((data->bits >> 24) & 0xff); + not_address = bitrev8((data->bits >> 16) & 0xff); + command = bitrev8((data->bits >> 8) & 0xff); + not_command = bitrev8((data->bits >> 0) & 0xff); if ((command ^ not_command) != 0xff) { IR_dprintk(1, "NEC checksum error: received 0x%08x\n", - data->nec_bits); + data->bits); break; } @@ -208,45 +170,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) return -EINVAL; } -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; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->ir_dev = ir_dev; - - 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; - - spin_lock(&decoder_lock); - list_del(&data->list); - spin_unlock(&decoder_lock); - - return 0; -} - static struct ir_raw_handler nec_handler = { .protocols = IR_TYPE_NEC, .decode = ir_nec_decode, - .raw_register = ir_nec_register, - .raw_unregister = ir_nec_unregister, }; static int __init ir_nec_decode_init(void) diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index fb3336c37191..5f98ab823057 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -20,36 +20,14 @@ /* Define the max number of pulse/space transitions to buffer */ #define MAX_IR_EVENT_SIZE 512 +/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */ +static LIST_HEAD(ir_raw_client_list); + /* Used to handle IR raw handler extensions */ static DEFINE_SPINLOCK(ir_raw_handler_lock); static LIST_HEAD(ir_raw_handler_list); static u64 available_protocols; -/** - * RUN_DECODER() - runs an operation on all IR decoders - * @ops: IR raw handler operation to be called - * @arg: arguments to be passed to the callback - * - * Calls ir_raw_handler::ops for all registered IR handlers. It prevents - * new decode addition/removal while running, by locking ir_raw_handler_lock - * mutex. If an error occurs, we keep going, as in the decode case, each - * decoder must have a crack at decoding the data. We return a sum of the - * return codes, which will be either 0 or negative for current callers. - */ -#define RUN_DECODER(ops, ...) ({ \ - struct ir_raw_handler *_ir_raw_handler; \ - int _sumrc = 0, _rc; \ - spin_lock(&ir_raw_handler_lock); \ - list_for_each_entry(_ir_raw_handler, &ir_raw_handler_list, list) { \ - if (_ir_raw_handler->ops) { \ - _rc = _ir_raw_handler->ops(__VA_ARGS__); \ - _sumrc += _rc; \ - } \ - } \ - spin_unlock(&ir_raw_handler_lock); \ - _sumrc; \ -}) - #ifdef MODULE /* Used to load the decoders */ static struct work_struct wq_load; @@ -58,11 +36,17 @@ static struct work_struct wq_load; static void ir_raw_event_work(struct work_struct *work) { struct ir_raw_event ev; + struct ir_raw_handler *handler; struct ir_raw_event_ctrl *raw = container_of(work, struct ir_raw_event_ctrl, rx_work); - while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) - RUN_DECODER(decode, raw->input_dev, ev); + while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) { + spin_lock(&ir_raw_handler_lock); + list_for_each_entry(handler, &ir_raw_handler_list, list) + handler->decode(raw->input_dev, ev); + spin_unlock(&ir_raw_handler_lock); + raw->prev_ev = ev; + } } /** @@ -176,6 +160,7 @@ int ir_raw_event_register(struct input_dev *input_dev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); int rc; + struct ir_raw_handler *handler; ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); if (!ir->raw) @@ -192,26 +177,32 @@ int ir_raw_event_register(struct input_dev *input_dev) return rc; } - rc = RUN_DECODER(raw_register, input_dev); - if (rc < 0) { - kfifo_free(&ir->raw->kfifo); - kfree(ir->raw); - ir->raw = NULL; - return rc; - } + spin_lock(&ir_raw_handler_lock); + list_add_tail(&ir->raw->list, &ir_raw_client_list); + list_for_each_entry(handler, &ir_raw_handler_list, list) + if (handler->raw_register) + handler->raw_register(ir->raw->input_dev); + spin_unlock(&ir_raw_handler_lock); - return rc; + return 0; } void ir_raw_event_unregister(struct input_dev *input_dev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); + struct ir_raw_handler *handler; if (!ir->raw) return; cancel_work_sync(&ir->raw->rx_work); - RUN_DECODER(raw_unregister, input_dev); + + spin_lock(&ir_raw_handler_lock); + list_del(&ir->raw->list); + list_for_each_entry(handler, &ir_raw_handler_list, list) + if (handler->raw_unregister) + handler->raw_unregister(ir->raw->input_dev); + spin_unlock(&ir_raw_handler_lock); kfifo_free(&ir->raw->kfifo); kfree(ir->raw); @@ -224,8 +215,13 @@ void ir_raw_event_unregister(struct input_dev *input_dev) int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) { + struct ir_raw_event_ctrl *raw; + spin_lock(&ir_raw_handler_lock); list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); + if (ir_raw_handler->raw_register) + list_for_each_entry(raw, &ir_raw_client_list, list) + ir_raw_handler->raw_register(raw->input_dev); available_protocols |= ir_raw_handler->protocols; spin_unlock(&ir_raw_handler_lock); @@ -235,8 +231,13 @@ EXPORT_SYMBOL(ir_raw_handler_register); void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) { + struct ir_raw_event_ctrl *raw; + spin_lock(&ir_raw_handler_lock); list_del(&ir_raw_handler->list); + if (ir_raw_handler->raw_unregister) + list_for_each_entry(raw, &ir_raw_client_list, list) + ir_raw_handler->raw_unregister(raw->input_dev); available_protocols &= ~ir_raw_handler->protocols; spin_unlock(&ir_raw_handler_lock); } diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c index bdfa404a6537..df4770d978ad 100644 --- a/drivers/media/IR/ir-rc5-decoder.c +++ b/drivers/media/IR/ir-rc5-decoder.c @@ -30,10 +30,6 @@ #define RC5_BIT_END (1 * RC5_UNIT) #define RC5X_SPACE (4 * RC5_UNIT) -/* Used to register rc5_decoder clients */ -static LIST_HEAD(decoder_list); -static DEFINE_SPINLOCK(decoder_lock); - enum rc5_state { STATE_INACTIVE, STATE_BIT_START, @@ -42,39 +38,6 @@ enum rc5_state { STATE_FINISHED, }; -struct decoder_data { - struct list_head list; - struct ir_input_dev *ir_dev; - - /* State machine control */ - enum rc5_state state; - u32 rc5_bits; - struct ir_raw_event prev_ev; - unsigned count; - unsigned wanted_bits; -}; - - -/** - * 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; -} - /** * ir_rc5_decode() - Decode one RC-5 pulse or space * @input_dev: the struct input_dev descriptor of the device @@ -84,15 +47,11 @@ static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) */ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev) { - struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct rc5_dec *data = &ir_dev->raw->rc5; u8 toggle; u32 scancode; - data = get_decoder_data(ir_dev); - if (!data) - return -EINVAL; - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5)) return 0; @@ -128,16 +87,15 @@ again: if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2)) break; - data->rc5_bits <<= 1; + data->bits <<= 1; if (!ev.pulse) - data->rc5_bits |= 1; + data->bits |= 1; data->count++; - data->prev_ev = ev; data->state = STATE_BIT_END; return 0; case STATE_BIT_END: - if (!is_transition(&ev, &data->prev_ev)) + if (!is_transition(&ev, &ir_dev->raw->prev_ev)) break; if (data->count == data->wanted_bits) @@ -169,11 +127,11 @@ again: if (data->wanted_bits == RC5X_NBITS) { /* RC5X */ u8 xdata, command, system; - xdata = (data->rc5_bits & 0x0003F) >> 0; - command = (data->rc5_bits & 0x00FC0) >> 6; - system = (data->rc5_bits & 0x1F000) >> 12; - toggle = (data->rc5_bits & 0x20000) ? 1 : 0; - command += (data->rc5_bits & 0x01000) ? 0 : 0x40; + xdata = (data->bits & 0x0003F) >> 0; + command = (data->bits & 0x00FC0) >> 6; + system = (data->bits & 0x1F000) >> 12; + toggle = (data->bits & 0x20000) ? 1 : 0; + command += (data->bits & 0x01000) ? 0 : 0x40; scancode = system << 16 | command << 8 | xdata; IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n", @@ -182,10 +140,10 @@ again: } else { /* RC5 */ u8 command, system; - command = (data->rc5_bits & 0x0003F) >> 0; - system = (data->rc5_bits & 0x007C0) >> 6; - toggle = (data->rc5_bits & 0x00800) ? 1 : 0; - command += (data->rc5_bits & 0x01000) ? 0 : 0x40; + command = (data->bits & 0x0003F) >> 0; + system = (data->bits & 0x007C0) >> 6; + toggle = (data->bits & 0x00800) ? 1 : 0; + command += (data->bits & 0x01000) ? 0 : 0x40; scancode = system << 8 | command; IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n", @@ -204,45 +162,9 @@ out: return -EINVAL; } -static int ir_rc5_register(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct decoder_data *data; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->ir_dev = ir_dev; - - spin_lock(&decoder_lock); - list_add_tail(&data->list, &decoder_list); - spin_unlock(&decoder_lock); - - return 0; -} - -static int ir_rc5_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; - - spin_lock(&decoder_lock); - list_del(&data->list); - spin_unlock(&decoder_lock); - - return 0; -} - static struct ir_raw_handler rc5_handler = { .protocols = IR_TYPE_RC5, .decode = ir_rc5_decode, - .raw_register = ir_rc5_register, - .raw_unregister = ir_rc5_unregister, }; static int __init ir_rc5_decode_init(void) diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c index 2ebd4ea69538..f1624b8279bc 100644 --- a/drivers/media/IR/ir-rc6-decoder.c +++ b/drivers/media/IR/ir-rc6-decoder.c @@ -36,10 +36,6 @@ #define RC6_STARTBIT_MASK 0x08 /* for the header bits */ #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ -/* Used to register rc6_decoder clients */ -static LIST_HEAD(decoder_list); -static DEFINE_SPINLOCK(decoder_lock); - enum rc6_mode { RC6_MODE_0, RC6_MODE_6A, @@ -58,41 +54,8 @@ enum rc6_state { STATE_FINISHED, }; -struct decoder_data { - struct list_head list; - struct ir_input_dev *ir_dev; - - /* State machine control */ - enum rc6_state state; - u8 header; - u32 body; - struct ir_raw_event prev_ev; - bool toggle; - unsigned count; - unsigned wanted_bits; -}; - - -/** - * 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) +static enum rc6_mode rc6_mode(struct rc6_dec *data) { - 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 enum rc6_mode rc6_mode(struct decoder_data *data) { switch (data->header & RC6_MODE_MASK) { case 0: return RC6_MODE_0; @@ -114,15 +77,11 @@ static enum rc6_mode rc6_mode(struct decoder_data *data) { */ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev) { - struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct rc6_dec *data = &ir_dev->raw->rc6; u32 scancode; u8 toggle; - data = get_decoder_data(ir_dev); - if (!data) - return -EINVAL; - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6)) return 0; @@ -175,12 +134,11 @@ again: if (ev.pulse) data->header |= 1; data->count++; - data->prev_ev = ev; data->state = STATE_HEADER_BIT_END; return 0; case STATE_HEADER_BIT_END: - if (!is_transition(&ev, &data->prev_ev)) + if (!is_transition(&ev, &ir_dev->raw->prev_ev)) break; if (data->count == RC6_HEADER_NBITS) @@ -196,12 +154,11 @@ again: break; data->toggle = ev.pulse; - data->prev_ev = ev; data->state = STATE_TOGGLE_END; return 0; case STATE_TOGGLE_END: - if (!is_transition(&ev, &data->prev_ev) || + if (!is_transition(&ev, &ir_dev->raw->prev_ev) || !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2)) break; @@ -211,7 +168,6 @@ again: } data->state = STATE_BODY_BIT_START; - data->prev_ev = ev; decrease_duration(&ev, RC6_TOGGLE_END); data->count = 0; @@ -243,13 +199,11 @@ again: if (ev.pulse) data->body |= 1; data->count++; - data->prev_ev = ev; - data->state = STATE_BODY_BIT_END; return 0; case STATE_BODY_BIT_END: - if (!is_transition(&ev, &data->prev_ev)) + if (!is_transition(&ev, &ir_dev->raw->prev_ev)) break; if (data->count == data->wanted_bits) @@ -300,45 +254,9 @@ out: return -EINVAL; } -static int ir_rc6_register(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct decoder_data *data; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->ir_dev = ir_dev; - - spin_lock(&decoder_lock); - list_add_tail(&data->list, &decoder_list); - spin_unlock(&decoder_lock); - - return 0; -} - -static int ir_rc6_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; - - spin_lock(&decoder_lock); - list_del(&data->list); - spin_unlock(&decoder_lock); - - return 0; -} - static struct ir_raw_handler rc6_handler = { .protocols = IR_TYPE_RC6, .decode = ir_rc6_decode, - .raw_register = ir_rc6_register, - .raw_unregister = ir_rc6_unregister, }; static int __init ir_rc6_decode_init(void) diff --git a/drivers/media/IR/ir-sony-decoder.c b/drivers/media/IR/ir-sony-decoder.c index e15db3334998..b9074f07c7a0 100644 --- a/drivers/media/IR/ir-sony-decoder.c +++ b/drivers/media/IR/ir-sony-decoder.c @@ -23,10 +23,6 @@ #define SONY_BIT_SPACE (1 * SONY_UNIT) #define SONY_TRAILER_SPACE (10 * SONY_UNIT) /* minimum */ -/* Used to register sony_decoder clients */ -static LIST_HEAD(decoder_list); -static DEFINE_SPINLOCK(decoder_lock); - enum sony_state { STATE_INACTIVE, STATE_HEADER_SPACE, @@ -35,36 +31,6 @@ enum sony_state { STATE_FINISHED, }; -struct decoder_data { - struct list_head list; - struct ir_input_dev *ir_dev; - - /* State machine control */ - enum sony_state state; - u32 sony_bits; - unsigned count; -}; - - -/** - * 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; -} - /** * ir_sony_decode() - Decode one Sony pulse or space * @input_dev: the struct input_dev descriptor of the device @@ -74,15 +40,11 @@ static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) */ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) { - struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct sony_dec *data = &ir_dev->raw->sony; u32 scancode; u8 device, subdevice, function; - data = get_decoder_data(ir_dev); - if (!data) - return -EINVAL; - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY)) return 0; @@ -124,9 +86,9 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) if (!ev.pulse) break; - data->sony_bits <<= 1; + data->bits <<= 1; if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2)) - data->sony_bits |= 1; + data->bits |= 1; else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2)) break; @@ -160,19 +122,19 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) switch (data->count) { case 12: - device = bitrev8((data->sony_bits << 3) & 0xF8); + device = bitrev8((data->bits << 3) & 0xF8); subdevice = 0; - function = bitrev8((data->sony_bits >> 4) & 0xFE); + function = bitrev8((data->bits >> 4) & 0xFE); break; case 15: - device = bitrev8((data->sony_bits >> 0) & 0xFF); + device = bitrev8((data->bits >> 0) & 0xFF); subdevice = 0; - function = bitrev8((data->sony_bits >> 7) & 0xFD); + function = bitrev8((data->bits >> 7) & 0xFD); break; case 20: - device = bitrev8((data->sony_bits >> 5) & 0xF8); - subdevice = bitrev8((data->sony_bits >> 0) & 0xFF); - function = bitrev8((data->sony_bits >> 12) & 0xFE); + device = bitrev8((data->bits >> 5) & 0xF8); + subdevice = bitrev8((data->bits >> 0) & 0xFF); + function = bitrev8((data->bits >> 12) & 0xFE); break; default: IR_dprintk(1, "Sony invalid bitcount %u\n", data->count); @@ -193,45 +155,9 @@ out: return -EINVAL; } -static int ir_sony_register(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct decoder_data *data; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->ir_dev = ir_dev; - - spin_lock(&decoder_lock); - list_add_tail(&data->list, &decoder_list); - spin_unlock(&decoder_lock); - - return 0; -} - -static int ir_sony_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; - - spin_lock(&decoder_lock); - list_del(&data->list); - spin_unlock(&decoder_lock); - - return 0; -} - static struct ir_raw_handler sony_handler = { .protocols = IR_TYPE_SONY, .decode = ir_sony_decode, - .raw_register = ir_sony_register, - .raw_unregister = ir_sony_unregister, }; static int __init ir_sony_decode_init(void) -- cgit v1.2.3