]> git.karo-electronics.de Git - linux-beck.git/blob - drivers/media/common/ir-keytable.c
V4L/DVB (13540): ir-common: Cleanup get key evdev code
[linux-beck.git] / drivers / media / common / ir-keytable.c
1 /* 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
10 #define IR_TAB_MIN_SIZE 32
11
12 /**
13  * 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  */
22 static 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
39 exit:
40         spin_unlock_irqrestore(&rc_tab->lock, flags);
41         return rc;
42 }
43
44 /**
45  * 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  */
58 int 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
83 int 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++) {
89                 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++;
95         }
96         destin->size = j;
97
98         IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size);
99
100         return 0;
101 }
102
103 /**
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  */
112 static int ir_getkeycode(struct input_dev *dev,
113                          int scancode, int *keycode)
114 {
115         int elem;
116         struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
117
118         elem = ir_seek_table(rc_tab, scancode);
119         if (elem >= 0) {
120                 *keycode = rc_tab->scan[elem].keycode;
121                 return 0;
122         }
123
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  */
137 static int ir_setkeycode(struct input_dev *dev,
138                          int scancode, int keycode)
139 {
140         int rc = 0;
141         struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
142         struct ir_scancode *keymap = rc_tab->scan;
143         unsigned long flags;
144
145         /* Search if it is replacing an existing keycode */
146         rc = ir_seek_table(rc_tab, scancode);
147         if (rc <0)
148                 return rc;
149
150         IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n",
151                 rc, scancode, keycode);
152
153         clear_bit(keymap[rc].keycode, dev->keybit);
154
155         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;
162 }
163
164 /**
165  * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode
166  * @input_dev:  the struct input_dev descriptor of the device
167  * @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  */
174 u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
175 {
176         struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
177         struct ir_scancode *keymap = rc_tab->scan;
178         int elem;
179
180         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);
184
185                 return rc_tab->scan[elem].keycode;
186         }
187
188         printk(KERN_INFO "%s: unknown key for scancode 0x%04x\n",
189                dev->name, scancode);
190
191         /* Reports userspace that an unknown keycode were got */
192         return KEY_RESERVED;
193 }
194
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
202  * an IR.
203  * It should be called before registering the IR device.
204  */
205 int 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
211         spin_lock_init(&rc_tab->lock);
212
213         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 }
230
231 void 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 }
241 EXPORT_SYMBOL_GPL(ir_input_free);
242