From: "David Härdeman" <david@hardeman.nu>
To: linux-media@vger.kernel.org
Cc: m.chehab@samsung.com
Subject: [PATCH 33/49] rc-core: make the keytable of rc_dev an array
Date: Fri, 04 Apr 2014 01:34:02 +0200 [thread overview]
Message-ID: <20140403233402.27099.4423.stgit@zeus.muc.hardeman.nu> (raw)
In-Reply-To: <20140403232420.27099.94872.stgit@zeus.muc.hardeman.nu>
This is another step towards allowing multiple keytables per rc_dev.
struct rc_dev is changed to hold an array of keytables (used later for
indexed access to keytables) as well as a list of the same keytables
(used for iteration in fast paths).
Signed-off-by: David Härdeman <david@hardeman.nu>
---
drivers/media/rc/rc-core-priv.h | 4 +-
drivers/media/rc/rc-keytable.c | 95 ++++++++++++++++++++++++---------------
drivers/media/rc/rc-main.c | 74 ++++++++++++++++++++++++++++--
include/media/rc-core.h | 6 ++
4 files changed, 134 insertions(+), 45 deletions(-)
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 7a7770e..02b538c 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -162,8 +162,8 @@ void rc_keytable_keyup(struct rc_keytable *kt);
void rc_keytable_repeat(struct rc_keytable *kt);
void rc_keytable_keydown(struct rc_keytable *kt, enum rc_type protocol,
u32 scancode, u8 toggle, bool autokeyup);
-int rc_keytable_add(struct rc_dev *dev, struct rc_map *rc_map);
-void rc_keytable_del(struct rc_dev *dev);
+struct rc_keytable *rc_keytable_create(struct rc_dev *dev, struct rc_map *rc_map);
+void rc_keytable_destroy(struct rc_keytable *kt);
/* Only to be used by rc-core and ir-lirc-codec */
void rc_init_ir_rx(struct rc_dev *dev, struct rc_ir_rx *rx);
diff --git a/drivers/media/rc/rc-keytable.c b/drivers/media/rc/rc-keytable.c
index 0f1b817..412d342 100644
--- a/drivers/media/rc/rc-keytable.c
+++ b/drivers/media/rc/rc-keytable.c
@@ -322,7 +322,7 @@ static unsigned int ir_establish_scancode(struct rc_keytable *kt,
*/
static inline enum rc_type guess_protocol(struct rc_dev *rdev)
{
- struct rc_map *rc_map = &rdev->kt->rc_map;
+ struct rc_map *rc_map = &rdev->keytables[0]->rc_map;
if (hweight64(rdev->enabled_protocols) == 1)
return rc_bitmap_to_type(rdev->enabled_protocols);
@@ -604,40 +604,63 @@ out:
return retval;
}
-/**
- * rc_g_keycode_from_table() - gets the keycode that corresponds to a scancode
- * @dev: the struct rc_dev descriptor of the device
- * @protocol: the protocol to look for
- * @scancode: the scancode to look for
- * @return: the corresponding keycode, or KEY_RESERVED
- *
- * This routine is used by drivers which need to convert a scancode to a
- * keycode. Normally it should not be used since drivers should have no
- * interest in keycodes.
- */
-u32 rc_g_keycode_from_table(struct rc_dev *dev,
- enum rc_type protocol, u64 scancode)
+static u32 rc_get_keycode(struct rc_keytable *kt,
+ enum rc_type protocol, u64 scancode)
{
- struct rc_map *rc_map = &dev->kt->rc_map;
- unsigned int keycode;
+ struct rc_map *rc_map;
+ unsigned int keycode = KEY_RESERVED;
unsigned int index;
unsigned long flags;
+ rc_map = &kt->rc_map;
+ if (!rc_map)
+ return KEY_RESERVED;
+
spin_lock_irqsave(&rc_map->lock, flags);
index = ir_lookup_by_scancode(rc_map, protocol, scancode);
- keycode = index < rc_map->len ?
- rc_map->scan[index].keycode : KEY_RESERVED;
+ if (index < rc_map->len)
+ keycode = rc_map->scan[index].keycode;
spin_unlock_irqrestore(&rc_map->lock, flags);
if (keycode != KEY_RESERVED)
IR_dprintk(1, "%s: protocol 0x%04x scancode 0x%08llx keycode 0x%02x\n",
- dev->input_name, protocol,
+ kt->dev->input_name, protocol,
(unsigned long long)scancode, keycode);
return keycode;
}
+
+
+/**
+ * rc_g_keycode_from_table() - gets the keycode that corresponds to a scancode
+ * @dev: the struct rc_dev descriptor of the device
+ * @protocol: the protocol to look for
+ * @scancode: the scancode to look for
+ * @return: the corresponding keycode, or KEY_RESERVED
+ *
+ * This routine is used by drivers which need to convert a scancode to a
+ * keycode. It should not be used since drivers should have no
+ * interest in keycodes. (deprecated)
+ */
+u32 rc_g_keycode_from_table(struct rc_dev *dev,
+ enum rc_type protocol, u64 scancode)
+{
+ struct rc_keytable *kt;
+ unsigned int keycode = KEY_RESERVED;
+
+ /* FIXME: This entire function is a hack. Remove it */
+ rcu_read_lock();
+ kt = rcu_dereference(dev->keytables[0]);
+ if (!kt)
+ goto out;
+ keycode = rc_get_keycode(kt, protocol, scancode);
+
+out:
+ rcu_read_unlock();
+ return keycode;
+}
EXPORT_SYMBOL_GPL(rc_g_keycode_from_table);
/**
@@ -751,7 +774,7 @@ void rc_keytable_keydown(struct rc_keytable *kt, enum rc_type protocol,
spin_lock_irqsave(&kt->keylock, flags);
- keycode = rc_g_keycode_from_table(kt->dev, protocol, scancode);
+ keycode = rc_get_keycode(kt, protocol, scancode);
new_event = (!kt->keypressed ||
kt->last_protocol != protocol ||
kt->last_scancode != scancode ||
@@ -800,16 +823,16 @@ static void rc_input_close(struct input_dev *idev)
}
/**
- * rc_keytable_add() - adds a new keytable
+ * rc_keytable_create() - create a new keytable
* @dev: the struct rc_dev device this keytable should belong to
* @rc_map: the keymap to use for the new keytable
* @return: zero on success or a negative error code
*
- * This function add a new keytable (essentially the combination of a keytable
- * and an input device along with some state (whether a key is currently
- * pressed or not, etc).
+ * This function creates a new keytable (essentially the combination of a
+ * keytable and an input device along with some state (whether a key is
+ * currently pressed or not, etc).
*/
-int rc_keytable_add(struct rc_dev *dev, struct rc_map *rc_map)
+struct rc_keytable *rc_keytable_create(struct rc_dev *dev, struct rc_map *rc_map)
{
struct rc_keytable *kt;
struct input_dev *idev = NULL;
@@ -870,31 +893,29 @@ int rc_keytable_add(struct rc_dev *dev, struct rc_map *rc_map)
*/
idev->rep[REP_PERIOD] = 125;
- dev->kt = kt;
- return 0;
+ return kt;
out:
ir_free_table(&kt->rc_map);
input_free_device(idev);
kfree(kt);
- return err;
+ return ERR_PTR(err);
}
/**
- * rc_keytable_del() - unregisters and deletes a keytable
- * @dev: the struct rc_dev device with the keytable
+ * rc_keytable_del() - unregisters and frees a keytable
+ * @kt: the struct rc_keytable to destroy
*
* This function unregisters and deletes an existing keytable.
*/
-void rc_keytable_del(struct rc_dev *dev)
+void rc_keytable_destroy(struct rc_keytable *kt)
{
- if (!dev->kt)
+ if (!kt)
return;
- del_timer_sync(&dev->kt->timer_keyup);
- ir_free_table(&dev->kt->rc_map);
- input_unregister_device(dev->kt->idev);
- kfree(dev->kt);
- dev->kt = NULL;
+ del_timer_sync(&kt->timer_keyup);
+ ir_free_table(&kt->rc_map);
+ input_unregister_device(kt->idev);
+ kfree(kt);
}
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 23a6701..bc2d479 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -150,8 +150,14 @@ EXPORT_SYMBOL_GPL(rc_close);
void rc_do_keydown(struct rc_dev *dev, enum rc_type protocol,
u32 scancode, u8 toggle, bool autoup)
{
+ struct rc_keytable *kt;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(kt, &dev->keytable_list, node)
+ rc_keytable_keydown(kt, protocol, scancode, toggle, autoup);
+ rcu_read_unlock();
+
led_trigger_event(led_feedback, LED_FULL);
- rc_keytable_keydown(dev->kt, protocol, scancode, toggle, autoup);
rc_event(dev, RC_KEY, RC_KEY_PROTOCOL, protocol);
rc_event(dev, RC_KEY, RC_KEY_SCANCODE, scancode);
rc_event(dev, RC_KEY, RC_KEY_TOGGLE, toggle);
@@ -166,7 +172,12 @@ EXPORT_SYMBOL_GPL(rc_do_keydown);
*/
void rc_keyup(struct rc_dev *dev)
{
- rc_keytable_keyup(dev->kt);
+ struct rc_keytable *kt;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(kt, &dev->keytable_list, node)
+ rc_keytable_keyup(kt);
+ rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(rc_keyup);
@@ -179,11 +190,60 @@ EXPORT_SYMBOL_GPL(rc_keyup);
*/
void rc_repeat(struct rc_dev *dev)
{
- rc_keytable_repeat(dev->kt);
+ struct rc_keytable *kt;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(kt, &dev->keytable_list, node)
+ rc_keytable_repeat(kt);
+ rcu_read_unlock();
+
rc_event(dev, RC_KEY, RC_KEY_REPEAT, 1);
}
EXPORT_SYMBOL_GPL(rc_repeat);
+static int rc_add_keytable(struct rc_dev *dev, struct rc_map *rc_map)
+{
+ struct rc_keytable *kt;
+ unsigned i;
+
+ if (!rc_map)
+ rc_map = rc_map_get(RC_MAP_EMPTY);
+
+ if (!rc_map)
+ return -EFAULT;
+
+ for (i = 0; i < ARRAY_SIZE(dev->keytables); i++)
+ if (!dev->keytables[i])
+ break;
+
+ if (i >= ARRAY_SIZE(dev->keytables))
+ return -ENFILE;
+
+ kt = rc_keytable_create(dev, rc_map);
+ if (IS_ERR(kt))
+ return PTR_ERR(kt);
+
+ rcu_assign_pointer(dev->keytables[i], kt);
+ list_add_rcu(&kt->node, &dev->keytable_list);
+ synchronize_rcu();
+ return 0;
+}
+
+static void rc_remove_keytable(struct rc_dev *dev, unsigned i)
+{
+ struct rc_keytable *kt;
+
+ if (i >= ARRAY_SIZE(dev->keytables))
+ return;
+
+ kt = dev->keytables[i];
+ rcu_assign_pointer(dev->keytables[i], NULL);
+ if (kt)
+ list_del_rcu(&kt->node);
+ synchronize_rcu();
+ rc_keytable_destroy(kt);
+}
+
/* class for /sys/class/rc */
static char *rc_devnode(struct device *dev, umode_t *mode)
{
@@ -1108,6 +1168,7 @@ struct rc_dev *rc_allocate_device(void)
INIT_LIST_HEAD(&dev->client_list);
spin_lock_init(&dev->client_lock);
+ INIT_LIST_HEAD(&dev->keytable_list);
mutex_init(&dev->txmutex);
init_waitqueue_head(&dev->txwait);
init_waitqueue_head(&dev->rxwait);
@@ -1215,7 +1276,7 @@ int rc_register_device(struct rc_dev *dev)
if (rc)
goto out_cdev;
- rc = rc_keytable_add(dev, rc_map);
+ rc = rc_add_keytable(dev, rc_map);
if (rc)
goto out_dev;
@@ -1243,6 +1304,7 @@ EXPORT_SYMBOL_GPL(rc_register_device);
void rc_unregister_device(struct rc_dev *dev)
{
struct rc_client *client;
+ unsigned i;
if (!dev)
return;
@@ -1263,7 +1325,8 @@ void rc_unregister_device(struct rc_dev *dev)
if (dev->driver_type == RC_DRIVER_IR_RAW)
ir_raw_event_unregister(dev);
- rc_keytable_del(dev);
+ for (i = 0; i < ARRAY_SIZE(dev->keytables); i++)
+ rc_remove_keytable(dev, i);
/* dev is marked as dead so no one changes dev->users */
if (dev->users && dev->close)
@@ -1329,3 +1392,4 @@ module_param_named(debug, rc_core_debug, int, 0644);
MODULE_AUTHOR("Mauro Carvalho Chehab");
MODULE_LICENSE("GPL");
+
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index e64d47c..f48d5cd 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -303,6 +303,7 @@ enum rc_filter_type {
* @get_ir_tx: allow driver to provide tx settings
* @set_ir_tx: allow driver to change tx settings
*/
+#define RC_MAX_KEYTABLES 1
struct rc_dev {
struct device dev;
struct cdev cdev;
@@ -312,7 +313,8 @@ struct rc_dev {
struct input_id input_id;
char *driver_name;
const char *map_name;
- struct rc_keytable *kt;
+ struct rc_keytable *keytables[RC_MAX_KEYTABLES];
+ struct list_head keytable_list;
struct mutex lock;
bool dead;
struct list_head client_list;
@@ -362,6 +364,7 @@ struct rc_dev {
/**
* struct rc_keytable - represents one keytable for a rc_dev device
+ * @node: used to iterate over all keytables for a rc_dev device
* @dev: the rc_dev device this keytable belongs to
* @idev: the input_dev device which belongs to this keytable
* @rc_map: holds the scancode <-> keycode mappings
@@ -375,6 +378,7 @@ struct rc_dev {
* @last_toggle: toggle of the last keypress
*/
struct rc_keytable {
+ struct list_head node;
struct rc_dev *dev;
struct input_dev *idev;
struct rc_map rc_map;
next prev parent reply other threads:[~2014-04-03 23:34 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-03 23:31 [PATCH 00/49] rc-core: my current patch queue David Härdeman
2014-04-03 23:31 ` [PATCH 01/49] bt8xx: fixup RC5 decoding David Härdeman
2014-04-03 23:31 ` [PATCH 02/49] rc-core: improve ir-kbd-i2c get_key functions David Härdeman
2014-04-03 23:31 ` [PATCH 03/49] rc-core: document the protocol type David Härdeman
2014-04-03 23:31 ` [PATCH 04/49] rc-core: do not change 32bit NEC scancode format for now David Härdeman
2014-04-04 13:18 ` James Hogan
2014-04-03 23:31 ` [PATCH 05/49] rc-core: split dev->s_filter David Härdeman
2014-04-04 13:08 ` James Hogan
2014-04-03 23:31 ` [PATCH 06/49] rc-core: remove generic scancode filter David Härdeman
2014-04-04 13:30 ` James Hogan
2014-04-03 23:31 ` [PATCH 07/49] dib0700: NEC scancode cleanup David Härdeman
2014-04-03 23:31 ` [PATCH 08/49] lmedm04: " David Härdeman
2014-04-03 23:32 ` [PATCH 09/49] saa7134: NEC scancode fix David Härdeman
2014-04-03 23:32 ` [PATCH 10/49] [RFC] rc-core: use the full 32 bits for NEC scancodes David Härdeman
2014-04-03 23:32 ` [PATCH 11/49] [RFC] rc-core: don't throw away protocol information David Härdeman
2014-04-03 23:32 ` [PATCH 12/49] rc-core: simplify sysfs code David Härdeman
2014-04-03 23:32 ` [PATCH 13/49] rc-core: remove protocol arrays David Härdeman
2014-04-03 23:32 ` [PATCH 14/49] rc-core: rename dev->scanmask to dev->scancode_mask David Härdeman
2014-04-03 23:32 ` [PATCH 15/49] rc-core: merge rc5 and streamzap decoders David Härdeman
2014-04-03 23:32 ` [PATCH 16/49] rc-core: use an IDA rather than a bitmap David Härdeman
2014-07-25 22:39 ` Mauro Carvalho Chehab
2014-04-03 23:32 ` [PATCH 17/49] rc-core: add chardev David Härdeman
2014-04-03 23:32 ` [PATCH 18/49] rc-core: allow chardev to be read David Härdeman
2014-04-03 23:32 ` [PATCH 19/49] rc-core: use a kfifo for TX data David Härdeman
2014-04-03 23:32 ` [PATCH 20/49] rc-core: allow chardev to be written David Härdeman
2014-04-03 23:33 ` [PATCH 21/49] rc-core: add ioctl support to the rc chardev David Härdeman
2014-04-03 23:33 ` [PATCH 22/49] rc-core: add an ioctl for getting IR RX settings David Härdeman
2014-04-03 23:33 ` [PATCH 23/49] rc-loopback: add RCIOCGIRRX ioctl support David Härdeman
2014-04-03 23:33 ` [PATCH 24/49] rc-core: add an ioctl for setting IR RX settings David Härdeman
2014-04-03 23:33 ` [PATCH 25/49] rc-loopback: add RCIOCSIRRX ioctl support David Härdeman
2014-04-03 23:33 ` [PATCH 26/49] rc-core: add an ioctl for getting IR TX settings David Härdeman
2014-04-03 23:33 ` [PATCH 27/49] rc-loopback: add RCIOCGIRTX ioctl support David Härdeman
2014-04-03 23:33 ` [PATCH 28/49] rc-core: add an ioctl for setting IR TX settings David Härdeman
2014-04-03 23:33 ` [PATCH 29/49] rc-loopback: add RCIOCSIRTX ioctl support David Härdeman
2014-04-03 23:33 ` [PATCH 30/49] rc-core: leave the internals of rc_dev alone David Härdeman
2014-07-24 1:50 ` Mauro Carvalho Chehab
2014-04-03 23:33 ` [PATCH 31/49] rc-core: split rc-main.c into rc-main.c and rc-keytable.c David Härdeman
2014-07-25 22:44 ` Mauro Carvalho Chehab
2014-04-03 23:33 ` [PATCH 32/49] rc-core: prepare for multiple keytables David Härdeman
2014-07-25 22:52 ` Mauro Carvalho Chehab
2014-04-03 23:34 ` David Härdeman [this message]
2014-04-03 23:34 ` [PATCH 34/49] rc-core: add ioctls for adding/removing keytables from userspace David Härdeman
2014-04-03 23:34 ` [PATCH 35/49] rc-core: remove redundant spinlock David Härdeman
2014-04-03 23:34 ` [PATCH 36/49] rc-core: make keytable RCU-friendly David Härdeman
2014-04-03 23:34 ` [PATCH 37/49] rc-core: allow empty keymaps David Härdeman
2014-07-25 22:58 ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 38/49] rc-core: rename ir-raw.c David Härdeman
2014-04-03 23:34 ` [PATCH 39/49] rc-core: make IR raw handling a separate module David Härdeman
2014-07-25 23:04 ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 40/49] rc-ir-raw: simplify locking David Härdeman
2014-07-25 23:08 ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 41/49] rc-core: rename mutex David Härdeman
2014-04-10 21:28 ` James Hogan
2014-07-25 23:12 ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 42/49] rc-ir-raw: atomic reads of protocols David Härdeman
2014-07-25 23:13 ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 43/49] rc-core: fix various sparse warnings David Härdeman
2014-04-03 23:34 ` [PATCH 44/49] rc-core: don't report scancodes via input devices David Härdeman
2014-07-25 23:16 ` Mauro Carvalho Chehab
2014-04-03 23:35 ` [PATCH 45/49] rc-ir-raw: add various rc_events David Härdeman
2014-07-25 23:16 ` Mauro Carvalho Chehab
2014-04-03 23:35 ` [PATCH 46/49] rc-core: use struct rc_event for all rc communication David Härdeman
2014-07-25 23:19 ` Mauro Carvalho Chehab
2014-04-03 23:35 ` [PATCH 47/49] rc-core: add keytable events David Härdeman
2014-04-03 23:35 ` [PATCH 48/49] rc-core: move remaining keytable functions David Härdeman
2014-04-03 23:35 ` [PATCH 49/49] rc-core: make rc-core.h userspace friendly David Härdeman
2014-04-04 2:05 ` [PATCH 00/49] rc-core: my current patch queue Mauro Carvalho Chehab
2014-06-26 20:07 ` David Härdeman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140403233402.27099.4423.stgit@zeus.muc.hardeman.nu \
--to=david@hardeman.nu \
--cc=linux-media@vger.kernel.org \
--cc=m.chehab@samsung.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox