xref: /openbmc/linux/drivers/input/sparse-keymap.c (revision e190bfe5)
1 /*
2  * Generic support for sparse keymaps
3  *
4  * Copyright (c) 2009 Dmitry Torokhov
5  *
6  * Derived from wistron button driver:
7  * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
8  * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
9  * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
10  *
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License version 2 as published by
13  * the Free Software Foundation.
14  */
15 
16 #include <linux/input.h>
17 #include <linux/input/sparse-keymap.h>
18 #include <linux/slab.h>
19 
20 MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
21 MODULE_DESCRIPTION("Generic support for sparse keymaps");
22 MODULE_LICENSE("GPL v2");
23 MODULE_VERSION("0.1");
24 
25 /**
26  * sparse_keymap_entry_from_scancode - perform sparse keymap lookup
27  * @dev: Input device using sparse keymap
28  * @code: Scan code
29  *
30  * This function is used to perform &struct key_entry lookup in an
31  * input device using sparse keymap.
32  */
33 struct key_entry *sparse_keymap_entry_from_scancode(struct input_dev *dev,
34 						    unsigned int code)
35 {
36 	struct key_entry *key;
37 
38 	for (key = dev->keycode; key->type != KE_END; key++)
39 		if (code == key->code)
40 			return key;
41 
42 	return NULL;
43 }
44 EXPORT_SYMBOL(sparse_keymap_entry_from_scancode);
45 
46 /**
47  * sparse_keymap_entry_from_keycode - perform sparse keymap lookup
48  * @dev: Input device using sparse keymap
49  * @keycode: Key code
50  *
51  * This function is used to perform &struct key_entry lookup in an
52  * input device using sparse keymap.
53  */
54 struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev,
55 						   unsigned int keycode)
56 {
57 	struct key_entry *key;
58 
59 	for (key = dev->keycode; key->type != KE_END; key++)
60 		if (key->type == KE_KEY && keycode == key->keycode)
61 			return key;
62 
63 	return NULL;
64 }
65 EXPORT_SYMBOL(sparse_keymap_entry_from_keycode);
66 
67 static int sparse_keymap_getkeycode(struct input_dev *dev,
68 				    unsigned int scancode,
69 				    unsigned int *keycode)
70 {
71 	const struct key_entry *key;
72 
73 	if (dev->keycode) {
74 		key = sparse_keymap_entry_from_scancode(dev, scancode);
75 		if (key && key->type == KE_KEY) {
76 			*keycode = key->keycode;
77 			return 0;
78 		}
79 	}
80 
81 	return -EINVAL;
82 }
83 
84 static int sparse_keymap_setkeycode(struct input_dev *dev,
85 				    unsigned int scancode,
86 				    unsigned int keycode)
87 {
88 	struct key_entry *key;
89 	int old_keycode;
90 
91 	if (dev->keycode) {
92 		key = sparse_keymap_entry_from_scancode(dev, scancode);
93 		if (key && key->type == KE_KEY) {
94 			old_keycode = key->keycode;
95 			key->keycode = keycode;
96 			set_bit(keycode, dev->keybit);
97 			if (!sparse_keymap_entry_from_keycode(dev, old_keycode))
98 				clear_bit(old_keycode, dev->keybit);
99 			return 0;
100 		}
101 	}
102 
103 	return -EINVAL;
104 }
105 
106 /**
107  * sparse_keymap_setup - set up sparse keymap for an input device
108  * @dev: Input device
109  * @keymap: Keymap in form of array of &key_entry structures ending
110  *	with %KE_END type entry
111  * @setup: Function that can be used to adjust keymap entries
112  *	depending on device's deeds, may be %NULL
113  *
114  * The function calculates size and allocates copy of the original
115  * keymap after which sets up input device event bits appropriately.
116  * Before destroying input device allocated keymap should be freed
117  * with a call to sparse_keymap_free().
118  */
119 int sparse_keymap_setup(struct input_dev *dev,
120 			const struct key_entry *keymap,
121 			int (*setup)(struct input_dev *, struct key_entry *))
122 {
123 	size_t map_size = 1; /* to account for the last KE_END entry */
124 	const struct key_entry *e;
125 	struct key_entry *map, *entry;
126 	int i;
127 	int error;
128 
129 	for (e = keymap; e->type != KE_END; e++)
130 		map_size++;
131 
132 	map = kcalloc(map_size, sizeof (struct key_entry), GFP_KERNEL);
133 	if (!map)
134 		return -ENOMEM;
135 
136 	memcpy(map, keymap, map_size * sizeof (struct key_entry));
137 
138 	for (i = 0; i < map_size; i++) {
139 		entry = &map[i];
140 
141 		if (setup) {
142 			error = setup(dev, entry);
143 			if (error)
144 				goto err_out;
145 		}
146 
147 		switch (entry->type) {
148 		case KE_KEY:
149 			__set_bit(EV_KEY, dev->evbit);
150 			__set_bit(entry->keycode, dev->keybit);
151 			break;
152 
153 		case KE_SW:
154 			__set_bit(EV_SW, dev->evbit);
155 			__set_bit(entry->sw.code, dev->swbit);
156 			break;
157 		}
158 	}
159 
160 	dev->keycode = map;
161 	dev->keycodemax = map_size;
162 	dev->getkeycode = sparse_keymap_getkeycode;
163 	dev->setkeycode = sparse_keymap_setkeycode;
164 
165 	return 0;
166 
167  err_out:
168 	kfree(map);
169 	return error;
170 
171 }
172 EXPORT_SYMBOL(sparse_keymap_setup);
173 
174 /**
175  * sparse_keymap_free - free memory allocated for sparse keymap
176  * @dev: Input device using sparse keymap
177  *
178  * This function is used to free memory allocated by sparse keymap
179  * in an input device that was set up by sparse_keymap_setup().
180  * NOTE: It is safe to cal this function while input device is
181  * still registered (however the drivers should care not to try to
182  * use freed keymap and thus have to shut off interrups/polling
183  * before freeing the keymap).
184  */
185 void sparse_keymap_free(struct input_dev *dev)
186 {
187 	unsigned long flags;
188 
189 	/*
190 	 * Take event lock to prevent racing with input_get_keycode()
191 	 * and input_set_keycode() if we are called while input device
192 	 * is still registered.
193 	 */
194 	spin_lock_irqsave(&dev->event_lock, flags);
195 
196 	kfree(dev->keycode);
197 	dev->keycode = NULL;
198 	dev->keycodemax = 0;
199 
200 	spin_unlock_irqrestore(&dev->event_lock, flags);
201 }
202 EXPORT_SYMBOL(sparse_keymap_free);
203 
204 /**
205  * sparse_keymap_report_entry - report event corresponding to given key entry
206  * @dev: Input device for which event should be reported
207  * @ke: key entry describing event
208  * @value: Value that should be reported (ignored by %KE_SW entries)
209  * @autorelease: Signals whether release event should be emitted for %KE_KEY
210  *	entries right after reporting press event, ignored by all other
211  *	entries
212  *
213  * This function is used to report input event described by given
214  * &struct key_entry.
215  */
216 void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *ke,
217 				unsigned int value, bool autorelease)
218 {
219 	switch (ke->type) {
220 	case KE_KEY:
221 		input_report_key(dev, ke->keycode, value);
222 		input_sync(dev);
223 		if (value && autorelease) {
224 			input_report_key(dev, ke->keycode, 0);
225 			input_sync(dev);
226 		}
227 		break;
228 
229 	case KE_SW:
230 		value = ke->sw.value;
231 		/* fall through */
232 
233 	case KE_VSW:
234 		input_report_switch(dev, ke->sw.code, value);
235 		break;
236 	}
237 }
238 EXPORT_SYMBOL(sparse_keymap_report_entry);
239 
240 /**
241  * sparse_keymap_report_event - report event corresponding to given scancode
242  * @dev: Input device using sparse keymap
243  * @code: Scan code
244  * @value: Value that should be reported (ignored by %KE_SW entries)
245  * @autorelease: Signals whether release event should be emitted for %KE_KEY
246  *	entries right after reporting press event, ignored by all other
247  *	entries
248  *
249  * This function is used to perform lookup in an input device using sparse
250  * keymap and report corresponding event. Returns %true if lookup was
251  * successful and %false otherwise.
252  */
253 bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code,
254 				unsigned int value, bool autorelease)
255 {
256 	const struct key_entry *ke =
257 		sparse_keymap_entry_from_scancode(dev, code);
258 
259 	if (ke) {
260 		sparse_keymap_report_entry(dev, ke, value, autorelease);
261 		return true;
262 	}
263 
264 	return false;
265 }
266 EXPORT_SYMBOL(sparse_keymap_report_event);
267 
268