aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-08-29 14:27:29 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-12 11:19:48 -0400
commitb77f0a76304dae754003b0a84fb4f66bf9934c97 (patch)
tree1c77c210a4ad9a70d7b0beccc102dcb7e0d74c86 /drivers/media/dvb
parent2e3658836efad06662968bd6373c72df06c4b2f1 (diff)
V4L/DVB (12599): dvb-usb-remote: Allow dynamically replacing the IR keycodes
Implements handler for EVIOCGKEYCODE/EVIOCSKEYCODE via adding two new callbacks to the input device. Since on dvb-usb a scan code has 16 bits, to fulfill rc5 standard codes, the default getkeycode/setkeycode input methods would require the driver to spend up to 64 Kb of a sparse table. Instead, add two new callbacks to the event device. With this, it is now possible to replace the keycode tables. There are, however, a few implementation details at the current patch: 1) It will replace the existing device keytable, instead of creating an instance of the data. This works. However, if two devices pointing to the same table were connected, changing the IR table of one will also change the IR table for the other (the solution for this one is simple: just kmalloc some memory); 2) In order to change the scan code, you need first to change the key to KEY_RESERVED or KEY_UNKNOWN to free some space at the table (solution: allocate some additional space for newer scan codes or allow dynamic table grow); 3) The table size cannot be extended. It would be easy to allow the table to grow dynamically: just calling kmalloc(size+1); kfree(old). Yet, maybe we can just create a bigger table with a fixed size, like for example a table with 128 entries. This should be enough even for a very big IR. The current issues should be addressed on a later patch. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-remote.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
index 16aec8c88bcc..b6dbc2b538d4 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -8,6 +8,58 @@
8#include "dvb-usb-common.h" 8#include "dvb-usb-common.h"
9#include <linux/usb/input.h> 9#include <linux/usb/input.h>
10 10
11static int dvb_usb_getkeycode(struct input_dev *dev,
12 int scancode, int *keycode)
13{
14 struct dvb_usb_device *d = input_get_drvdata(dev);
15
16 struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
17 int i;
18
19 /* See if we can match the raw key code. */
20 for (i = 0; i < d->props.rc_key_map_size; i++)
21 if (keymap[i].scan == scancode) {
22 *keycode = keymap[i].event;
23 return 0;
24 }
25 return -EINVAL;
26}
27
28static int dvb_usb_setkeycode(struct input_dev *dev,
29 int scancode, int keycode)
30{
31 struct dvb_usb_device *d = input_get_drvdata(dev);
32
33 struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
34 int i;
35
36 /* Search if it is replacing an existing keycode */
37 for (i = 0; i < d->props.rc_key_map_size; i++)
38 if (keymap[i].scan == scancode) {
39 keymap[i].event = keycode;
40 return 0;
41 }
42
43 /* Search if is there a clean entry. If so, use it */
44 for (i = 0; i < d->props.rc_key_map_size; i++)
45 if (keymap[i].event == KEY_RESERVED ||
46 keymap[i].event == KEY_UNKNOWN) {
47 keymap[i].scan = scancode;
48 keymap[i].event = keycode;
49 return 0;
50 }
51
52 /*
53 * FIXME: Currently, it is not possible to increase the size of
54 * scancode table. For it to happen, one possibility
55 * would be to allocate a table with key_map_size + 1,
56 * copying data, appending the new key on it, and freeing
57 * the old one - or maybe just allocating some spare space
58 */
59
60 return -EINVAL;
61}
62
11/* Remote-control poll function - called every dib->rc_query_interval ms to see 63/* Remote-control poll function - called every dib->rc_query_interval ms to see
12 * whether the remote control has received anything. 64 * whether the remote control has received anything.
13 * 65 *
@@ -111,6 +163,8 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
111 input_dev->phys = d->rc_phys; 163 input_dev->phys = d->rc_phys;
112 usb_to_input_id(d->udev, &input_dev->id); 164 usb_to_input_id(d->udev, &input_dev->id);
113 input_dev->dev.parent = &d->udev->dev; 165 input_dev->dev.parent = &d->udev->dev;
166 input_dev->getkeycode = dvb_usb_getkeycode;
167 input_dev->setkeycode = dvb_usb_setkeycode;
114 168
115 /* set the bits for the keys */ 169 /* set the bits for the keys */
116 deb_rc("key map size: %d\n", d->props.rc_key_map_size); 170 deb_rc("key map size: %d\n", d->props.rc_key_map_size);
@@ -128,6 +182,8 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
128 input_dev->rep[REP_PERIOD] = d->props.rc_interval; 182 input_dev->rep[REP_PERIOD] = d->props.rc_interval;
129 input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; 183 input_dev->rep[REP_DELAY] = d->props.rc_interval + 150;
130 184
185 input_set_drvdata(input_dev, d);
186
131 err = input_register_device(input_dev); 187 err = input_register_device(input_dev);
132 if (err) { 188 if (err) {
133 input_free_device(input_dev); 189 input_free_device(input_dev);