blob: b06f023ca76087cb1df4be684c07b1e7ff41a96c [file] [log] [blame]
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -03001/* ir-register.c - handle IR scancode->keycode tables
2 *
3 * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 */
5
6#include <linux/usb/input.h>
7
8#include <media/ir-common.h>
9
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -030010#define IR_TAB_MIN_SIZE 32
11
12/**
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -030013 * ir_seek_table() - returns the element order on the table
14 * @rc_tab: the ir_scancode_table with the keymap to be used
15 * @scancode: the scancode that we're seeking
16 *
17 * This routine is used by the input routines when a key is pressed at the
18 * IR. The scancode is received and needs to be converted into a keycode.
19 * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the
20 * corresponding keycode from the table.
21 */
22static int ir_seek_table(struct ir_scancode_table *rc_tab, u32 scancode)
23{
24 int rc;
25 unsigned long flags;
26 struct ir_scancode *keymap = rc_tab->scan;
27
28 spin_lock_irqsave(&rc_tab->lock, flags);
29
30 /* FIXME: replace it by a binary search */
31
32 for (rc = 0; rc < rc_tab->size; rc++)
33 if (keymap[rc].scancode == scancode)
34 goto exit;
35
36 /* Not found */
37 rc = -EINVAL;
38
39exit:
40 spin_unlock_irqrestore(&rc_tab->lock, flags);
41 return rc;
42}
43
44/**
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -030045 * ir_roundup_tablesize() - gets an optimum value for the table size
46 * @n_elems: minimum number of entries to store keycodes
47 *
48 * This routine is used to choose the keycode table size.
49 *
50 * In order to have some empty space for new keycodes,
51 * and knowing in advance that kmalloc allocates only power of two
52 * segments, it optimizes the allocated space to have some spare space
53 * for those new keycodes by using the maximum number of entries that
54 * will be effectively be allocated by kmalloc.
55 * In order to reduce the quantity of table resizes, it has a minimum
56 * table size of IR_TAB_MIN_SIZE.
57 */
58int ir_roundup_tablesize(int n_elems)
59{
60 size_t size;
61
62 if (n_elems < IR_TAB_MIN_SIZE)
63 n_elems = IR_TAB_MIN_SIZE;
64
65 /*
66 * As kmalloc only allocates sizes of power of two, get as
67 * much entries as possible for the allocated memory segment
68 */
69 size = roundup_pow_of_two(n_elems * sizeof(struct ir_scancode));
70 n_elems = size / sizeof(struct ir_scancode);
71
72 return n_elems;
73}
74
75/**
76 * ir_copy_table() - copies a keytable, discarding the unused entries
77 * @destin: destin table
78 * @origin: origin table
79 *
80 * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED
81 */
82
83int ir_copy_table(struct ir_scancode_table *destin,
84 const struct ir_scancode_table *origin)
85{
86 int i, j = 0;
87
88 for (i = 0; i < origin->size; i++) {
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -030089 if (origin->scan[i].keycode == KEY_UNKNOWN ||
90 origin->scan[i].keycode == KEY_RESERVED)
91 continue;
92
93 memcpy(&destin->scan[j], &origin->scan[i], sizeof(struct ir_scancode));
94 j++;
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -030095 }
96 destin->size = j;
97
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -030098 IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size);
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -030099
100 return 0;
101}
102
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300103/**
104 * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table
105 * @dev: the struct input_dev device descriptor
106 * @scancode: the desired scancode
107 * @keycode: the keycode to be retorned.
108 *
109 * This routine is used to handle evdev EVIOCGKEY ioctl.
110 * If the key is not found, returns -EINVAL, otherwise, returns 0.
111 */
112static int ir_getkeycode(struct input_dev *dev,
113 int scancode, int *keycode)
114{
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300115 int elem;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300116 struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300117
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300118 elem = ir_seek_table(rc_tab, scancode);
119 if (elem >= 0) {
120 *keycode = rc_tab->scan[elem].keycode;
121 return 0;
122 }
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300123
124 return -EINVAL;
125}
126
127/**
128 * ir_setkeycode() - set a keycode at the evdev scancode ->keycode table
129 * @dev: the struct input_dev device descriptor
130 * @scancode: the desired scancode
131 * @keycode: the keycode to be retorned.
132 *
133 * This routine is used to handle evdev EVIOCSKEY ioctl.
134 * There's one caveat here: how can we increase the size of the table?
135 * If the key is not found, returns -EINVAL, otherwise, returns 0.
136 */
137static int ir_setkeycode(struct input_dev *dev,
138 int scancode, int keycode)
139{
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300140 int rc = 0;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300141 struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
142 struct ir_scancode *keymap = rc_tab->scan;
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300143 unsigned long flags;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300144
145 /* Search if it is replacing an existing keycode */
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300146 rc = ir_seek_table(rc_tab, scancode);
147 if (rc <0)
148 return rc;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300149
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300150 IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n",
151 rc, scancode, keycode);
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300152
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300153 clear_bit(keymap[rc].keycode, dev->keybit);
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300154
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300155 spin_lock_irqsave(&rc_tab->lock, flags);
156 keymap[rc].keycode = keycode;
157 spin_unlock_irqrestore(&rc_tab->lock, flags);
158
159 set_bit(keycode, dev->keybit);
160
161 return 0;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300162}
163
164/**
165 * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300166 * @input_dev: the struct input_dev descriptor of the device
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300167 * @scancode: the scancode that we're seeking
168 *
169 * This routine is used by the input routines when a key is pressed at the
170 * IR. The scancode is received and needs to be converted into a keycode.
171 * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the
172 * corresponding keycode from the table.
173 */
174u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
175{
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300176 struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
177 struct ir_scancode *keymap = rc_tab->scan;
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300178 int elem;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300179
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300180 elem = ir_seek_table(rc_tab, scancode);
181 if (elem >= 0) {
182 IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
183 dev->name, scancode, keymap[elem].keycode);
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300184
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300185 return rc_tab->scan[elem].keycode;
186 }
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300187
188 printk(KERN_INFO "%s: unknown key for scancode 0x%04x\n",
189 dev->name, scancode);
190
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300191 /* Reports userspace that an unknown keycode were got */
192 return KEY_RESERVED;
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300193}
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300194
195/**
196 * ir_set_keycode_table() - sets the IR keycode table and add the handlers
197 * for keymap table get/set
198 * @input_dev: the struct input_dev descriptor of the device
199 * @rc_tab: the struct ir_scancode_table table of scancode/keymap
200 *
201 * This routine is used to initialize the input infrastructure to work with
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300202 * an IR.
203 * It should be called before registering the IR device.
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300204 */
205int ir_set_keycode_table(struct input_dev *input_dev,
206 struct ir_scancode_table *rc_tab)
207{
208 struct ir_scancode *keymap = rc_tab->scan;
209 int i;
210
Mauro Carvalho Chehab7fee03e2009-12-02 15:56:47 -0300211 spin_lock_init(&rc_tab->lock);
212
Mauro Carvalho Chehabef53a112009-11-27 22:01:23 -0300213 if (rc_tab->scan == NULL || !rc_tab->size)
214 return -EINVAL;
215
216 /* set the bits for the keys */
217 IR_dprintk(1, "key map size: %d\n", rc_tab->size);
218 for (i = 0; i < rc_tab->size; i++) {
219 IR_dprintk(1, "#%d: setting bit for keycode 0x%04x\n",
220 i, keymap[i].keycode);
221 set_bit(keymap[i].keycode, input_dev->keybit);
222 }
223
224 input_dev->getkeycode = ir_getkeycode;
225 input_dev->setkeycode = ir_setkeycode;
226 input_set_drvdata(input_dev, rc_tab);
227
228 return 0;
229}
Mauro Carvalho Chehabf6fc5042009-11-29 11:08:02 -0300230
231void ir_input_free(struct input_dev *dev)
232{
233 struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
234
235 IR_dprintk(1, "Freed keycode table\n");
236
237 rc_tab->size = 0;
238 kfree(rc_tab->scan);
239 rc_tab->scan = NULL;
240}
241EXPORT_SYMBOL_GPL(ir_input_free);
242