Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-2.6-microblaze.git] / drivers / input / sparse-keymap.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Generic support for sparse keymaps
4  *
5  * Copyright (c) 2009 Dmitry Torokhov
6  *
7  * Derived from wistron button driver:
8  * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
9  * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
10  * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
11  */
12
13 #include <linux/input.h>
14 #include <linux/input/sparse-keymap.h>
15 #include <linux/module.h>
16 #include <linux/slab.h>
17
18 MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
19 MODULE_DESCRIPTION("Generic support for sparse keymaps");
20 MODULE_LICENSE("GPL v2");
21
22 static unsigned int sparse_keymap_get_key_index(struct input_dev *dev,
23                                                 const struct key_entry *k)
24 {
25         struct key_entry *key;
26         unsigned int idx = 0;
27
28         for (key = dev->keycode; key->type != KE_END; key++) {
29                 if (key->type == KE_KEY) {
30                         if (key == k)
31                                 break;
32                         idx++;
33                 }
34         }
35
36         return idx;
37 }
38
39 static struct key_entry *sparse_keymap_entry_by_index(struct input_dev *dev,
40                                                       unsigned int index)
41 {
42         struct key_entry *key;
43         unsigned int key_cnt = 0;
44
45         for (key = dev->keycode; key->type != KE_END; key++)
46                 if (key->type == KE_KEY)
47                         if (key_cnt++ == index)
48                                 return key;
49
50         return NULL;
51 }
52
53 /**
54  * sparse_keymap_entry_from_scancode - perform sparse keymap lookup
55  * @dev: Input device using sparse keymap
56  * @code: Scan code
57  *
58  * This function is used to perform &struct key_entry lookup in an
59  * input device using sparse keymap.
60  */
61 struct key_entry *sparse_keymap_entry_from_scancode(struct input_dev *dev,
62                                                     unsigned int code)
63 {
64         struct key_entry *key;
65
66         for (key = dev->keycode; key->type != KE_END; key++)
67                 if (code == key->code)
68                         return key;
69
70         return NULL;
71 }
72 EXPORT_SYMBOL(sparse_keymap_entry_from_scancode);
73
74 /**
75  * sparse_keymap_entry_from_keycode - perform sparse keymap lookup
76  * @dev: Input device using sparse keymap
77  * @keycode: Key code
78  *
79  * This function is used to perform &struct key_entry lookup in an
80  * input device using sparse keymap.
81  */
82 struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev,
83                                                    unsigned int keycode)
84 {
85         struct key_entry *key;
86
87         for (key = dev->keycode; key->type != KE_END; key++)
88                 if (key->type == KE_KEY && keycode == key->keycode)
89                         return key;
90
91         return NULL;
92 }
93 EXPORT_SYMBOL(sparse_keymap_entry_from_keycode);
94
95 static struct key_entry *sparse_keymap_locate(struct input_dev *dev,
96                                         const struct input_keymap_entry *ke)
97 {
98         struct key_entry *key;
99         unsigned int scancode;
100
101         if (ke->flags & INPUT_KEYMAP_BY_INDEX)
102                 key = sparse_keymap_entry_by_index(dev, ke->index);
103         else if (input_scancode_to_scalar(ke, &scancode) == 0)
104                 key = sparse_keymap_entry_from_scancode(dev, scancode);
105         else
106                 key = NULL;
107
108         return key;
109 }
110
111 static int sparse_keymap_getkeycode(struct input_dev *dev,
112                                     struct input_keymap_entry *ke)
113 {
114         const struct key_entry *key;
115
116         if (dev->keycode) {
117                 key = sparse_keymap_locate(dev, ke);
118                 if (key && key->type == KE_KEY) {
119                         ke->keycode = key->keycode;
120                         if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
121                                 ke->index =
122                                         sparse_keymap_get_key_index(dev, key);
123                         ke->len = sizeof(key->code);
124                         memcpy(ke->scancode, &key->code, sizeof(key->code));
125                         return 0;
126                 }
127         }
128
129         return -EINVAL;
130 }
131
132 static int sparse_keymap_setkeycode(struct input_dev *dev,
133                                     const struct input_keymap_entry *ke,
134                                     unsigned int *old_keycode)
135 {
136         struct key_entry *key;
137
138         if (dev->keycode) {
139                 key = sparse_keymap_locate(dev, ke);
140                 if (key && key->type == KE_KEY) {
141                         *old_keycode = key->keycode;
142                         key->keycode = ke->keycode;
143                         set_bit(ke->keycode, dev->keybit);
144                         if (!sparse_keymap_entry_from_keycode(dev, *old_keycode))
145                                 clear_bit(*old_keycode, dev->keybit);
146                         return 0;
147                 }
148         }
149
150         return -EINVAL;
151 }
152
153 /**
154  * sparse_keymap_setup - set up sparse keymap for an input device
155  * @dev: Input device
156  * @keymap: Keymap in form of array of &key_entry structures ending
157  *      with %KE_END type entry
158  * @setup: Function that can be used to adjust keymap entries
159  *      depending on device's needs, may be %NULL
160  *
161  * The function calculates size and allocates copy of the original
162  * keymap after which sets up input device event bits appropriately.
163  * The allocated copy of the keymap is automatically freed when it
164  * is no longer needed.
165  */
166 int sparse_keymap_setup(struct input_dev *dev,
167                         const struct key_entry *keymap,
168                         int (*setup)(struct input_dev *, struct key_entry *))
169 {
170         size_t map_size = 1; /* to account for the last KE_END entry */
171         const struct key_entry *e;
172         struct key_entry *map, *entry;
173         int i;
174         int error;
175
176         for (e = keymap; e->type != KE_END; e++)
177                 map_size++;
178
179         map = devm_kmemdup(&dev->dev, keymap, map_size * sizeof(*map),
180                            GFP_KERNEL);
181         if (!map)
182                 return -ENOMEM;
183
184         for (i = 0; i < map_size; i++) {
185                 entry = &map[i];
186
187                 if (setup) {
188                         error = setup(dev, entry);
189                         if (error)
190                                 return error;
191                 }
192
193                 switch (entry->type) {
194                 case KE_KEY:
195                         __set_bit(EV_KEY, dev->evbit);
196                         __set_bit(entry->keycode, dev->keybit);
197                         break;
198
199                 case KE_SW:
200                 case KE_VSW:
201                         __set_bit(EV_SW, dev->evbit);
202                         __set_bit(entry->sw.code, dev->swbit);
203                         break;
204                 }
205         }
206
207         if (test_bit(EV_KEY, dev->evbit)) {
208                 __set_bit(KEY_UNKNOWN, dev->keybit);
209                 __set_bit(EV_MSC, dev->evbit);
210                 __set_bit(MSC_SCAN, dev->mscbit);
211         }
212
213         dev->keycode = map;
214         dev->keycodemax = map_size;
215         dev->getkeycode = sparse_keymap_getkeycode;
216         dev->setkeycode = sparse_keymap_setkeycode;
217
218         return 0;
219 }
220 EXPORT_SYMBOL(sparse_keymap_setup);
221
222 /**
223  * sparse_keymap_report_entry - report event corresponding to given key entry
224  * @dev: Input device for which event should be reported
225  * @ke: key entry describing event
226  * @value: Value that should be reported (ignored by %KE_SW entries)
227  * @autorelease: Signals whether release event should be emitted for %KE_KEY
228  *      entries right after reporting press event, ignored by all other
229  *      entries
230  *
231  * This function is used to report input event described by given
232  * &struct key_entry.
233  */
234 void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *ke,
235                                 unsigned int value, bool autorelease)
236 {
237         switch (ke->type) {
238         case KE_KEY:
239                 input_event(dev, EV_MSC, MSC_SCAN, ke->code);
240                 input_report_key(dev, ke->keycode, value);
241                 input_sync(dev);
242                 if (value && autorelease) {
243                         input_report_key(dev, ke->keycode, 0);
244                         input_sync(dev);
245                 }
246                 break;
247
248         case KE_SW:
249                 value = ke->sw.value;
250                 fallthrough;
251
252         case KE_VSW:
253                 input_report_switch(dev, ke->sw.code, value);
254                 input_sync(dev);
255                 break;
256         }
257 }
258 EXPORT_SYMBOL(sparse_keymap_report_entry);
259
260 /**
261  * sparse_keymap_report_event - report event corresponding to given scancode
262  * @dev: Input device using sparse keymap
263  * @code: Scan code
264  * @value: Value that should be reported (ignored by %KE_SW entries)
265  * @autorelease: Signals whether release event should be emitted for %KE_KEY
266  *      entries right after reporting press event, ignored by all other
267  *      entries
268  *
269  * This function is used to perform lookup in an input device using sparse
270  * keymap and report corresponding event. Returns %true if lookup was
271  * successful and %false otherwise.
272  */
273 bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code,
274                                 unsigned int value, bool autorelease)
275 {
276         const struct key_entry *ke =
277                 sparse_keymap_entry_from_scancode(dev, code);
278         struct key_entry unknown_ke;
279
280         if (ke) {
281                 sparse_keymap_report_entry(dev, ke, value, autorelease);
282                 return true;
283         }
284
285         /* Report an unknown key event as a debugging aid */
286         unknown_ke.type = KE_KEY;
287         unknown_ke.code = code;
288         unknown_ke.keycode = KEY_UNKNOWN;
289         sparse_keymap_report_entry(dev, &unknown_ke, value, true);
290
291         return false;
292 }
293 EXPORT_SYMBOL(sparse_keymap_report_event);
294