1 /* ir-register.c - handle IR scancode->keycode tables
3 * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 #include <linux/usb/input.h>
8 #include <media/ir-common.h>
10 #define IR_TAB_MIN_SIZE 32
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
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.
22 static int ir_seek_table(struct ir_scancode_table *rc_tab, u32 scancode)
26 struct ir_scancode *keymap = rc_tab->scan;
28 spin_lock_irqsave(&rc_tab->lock, flags);
30 /* FIXME: replace it by a binary search */
32 for (rc = 0; rc < rc_tab->size; rc++)
33 if (keymap[rc].scancode == scancode)
40 spin_unlock_irqrestore(&rc_tab->lock, flags);
45 * ir_roundup_tablesize() - gets an optimum value for the table size
46 * @n_elems: minimum number of entries to store keycodes
48 * This routine is used to choose the keycode table size.
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.
58 int ir_roundup_tablesize(int n_elems)
62 if (n_elems < IR_TAB_MIN_SIZE)
63 n_elems = IR_TAB_MIN_SIZE;
66 * As kmalloc only allocates sizes of power of two, get as
67 * much entries as possible for the allocated memory segment
69 size = roundup_pow_of_two(n_elems * sizeof(struct ir_scancode));
70 n_elems = size / sizeof(struct ir_scancode);
76 * ir_copy_table() - copies a keytable, discarding the unused entries
77 * @destin: destin table
78 * @origin: origin table
80 * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED
83 int ir_copy_table(struct ir_scancode_table *destin,
84 const struct ir_scancode_table *origin)
88 for (i = 0; i < origin->size; i++) {
89 if (origin->scan[i].keycode == KEY_UNKNOWN ||
90 origin->scan[i].keycode == KEY_RESERVED)
93 memcpy(&destin->scan[j], &origin->scan[i], sizeof(struct ir_scancode));
98 IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size);
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.
109 * This routine is used to handle evdev EVIOCGKEY ioctl.
110 * If the key is not found, returns -EINVAL, otherwise, returns 0.
112 static int ir_getkeycode(struct input_dev *dev,
113 int scancode, int *keycode)
116 struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
118 elem = ir_seek_table(rc_tab, scancode);
120 *keycode = rc_tab->scan[elem].keycode;
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.
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.
137 static int ir_setkeycode(struct input_dev *dev,
138 int scancode, int keycode)
141 struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
142 struct ir_scancode *keymap = rc_tab->scan;
145 /* Search if it is replacing an existing keycode */
146 rc = ir_seek_table(rc_tab, scancode);
150 IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n",
151 rc, scancode, keycode);
153 clear_bit(keymap[rc].keycode, dev->keybit);
155 spin_lock_irqsave(&rc_tab->lock, flags);
156 keymap[rc].keycode = keycode;
157 spin_unlock_irqrestore(&rc_tab->lock, flags);
159 set_bit(keycode, dev->keybit);
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
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.
174 u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
176 struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
177 struct ir_scancode *keymap = rc_tab->scan;
180 elem = ir_seek_table(rc_tab, scancode);
182 IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
183 dev->name, scancode, keymap[elem].keycode);
185 return rc_tab->scan[elem].keycode;
188 printk(KERN_INFO "%s: unknown key for scancode 0x%04x\n",
189 dev->name, scancode);
191 /* Reports userspace that an unknown keycode were got */
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
201 * This routine is used to initialize the input infrastructure to work with
203 * It should be called before registering the IR device.
205 int ir_set_keycode_table(struct input_dev *input_dev,
206 struct ir_scancode_table *rc_tab)
208 struct ir_scancode *keymap = rc_tab->scan;
211 spin_lock_init(&rc_tab->lock);
213 if (rc_tab->scan == NULL || !rc_tab->size)
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);
224 input_dev->getkeycode = ir_getkeycode;
225 input_dev->setkeycode = ir_setkeycode;
226 input_set_drvdata(input_dev, rc_tab);
231 void ir_input_free(struct input_dev *dev)
233 struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
235 IR_dprintk(1, "Freed keycode table\n");
241 EXPORT_SYMBOL_GPL(ir_input_free);