0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/input.h>
0014 #include <linux/input/sparse-keymap.h>
0015 #include <linux/module.h>
0016 #include <linux/slab.h>
0017
0018 MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
0019 MODULE_DESCRIPTION("Generic support for sparse keymaps");
0020 MODULE_LICENSE("GPL v2");
0021
0022 static unsigned int sparse_keymap_get_key_index(struct input_dev *dev,
0023 const struct key_entry *k)
0024 {
0025 struct key_entry *key;
0026 unsigned int idx = 0;
0027
0028 for (key = dev->keycode; key->type != KE_END; key++) {
0029 if (key->type == KE_KEY) {
0030 if (key == k)
0031 break;
0032 idx++;
0033 }
0034 }
0035
0036 return idx;
0037 }
0038
0039 static struct key_entry *sparse_keymap_entry_by_index(struct input_dev *dev,
0040 unsigned int index)
0041 {
0042 struct key_entry *key;
0043 unsigned int key_cnt = 0;
0044
0045 for (key = dev->keycode; key->type != KE_END; key++)
0046 if (key->type == KE_KEY)
0047 if (key_cnt++ == index)
0048 return key;
0049
0050 return NULL;
0051 }
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 struct key_entry *sparse_keymap_entry_from_scancode(struct input_dev *dev,
0062 unsigned int code)
0063 {
0064 struct key_entry *key;
0065
0066 for (key = dev->keycode; key->type != KE_END; key++)
0067 if (code == key->code)
0068 return key;
0069
0070 return NULL;
0071 }
0072 EXPORT_SYMBOL(sparse_keymap_entry_from_scancode);
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev,
0083 unsigned int keycode)
0084 {
0085 struct key_entry *key;
0086
0087 for (key = dev->keycode; key->type != KE_END; key++)
0088 if (key->type == KE_KEY && keycode == key->keycode)
0089 return key;
0090
0091 return NULL;
0092 }
0093 EXPORT_SYMBOL(sparse_keymap_entry_from_keycode);
0094
0095 static struct key_entry *sparse_keymap_locate(struct input_dev *dev,
0096 const struct input_keymap_entry *ke)
0097 {
0098 struct key_entry *key;
0099 unsigned int scancode;
0100
0101 if (ke->flags & INPUT_KEYMAP_BY_INDEX)
0102 key = sparse_keymap_entry_by_index(dev, ke->index);
0103 else if (input_scancode_to_scalar(ke, &scancode) == 0)
0104 key = sparse_keymap_entry_from_scancode(dev, scancode);
0105 else
0106 key = NULL;
0107
0108 return key;
0109 }
0110
0111 static int sparse_keymap_getkeycode(struct input_dev *dev,
0112 struct input_keymap_entry *ke)
0113 {
0114 const struct key_entry *key;
0115
0116 if (dev->keycode) {
0117 key = sparse_keymap_locate(dev, ke);
0118 if (key && key->type == KE_KEY) {
0119 ke->keycode = key->keycode;
0120 if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
0121 ke->index =
0122 sparse_keymap_get_key_index(dev, key);
0123 ke->len = sizeof(key->code);
0124 memcpy(ke->scancode, &key->code, sizeof(key->code));
0125 return 0;
0126 }
0127 }
0128
0129 return -EINVAL;
0130 }
0131
0132 static int sparse_keymap_setkeycode(struct input_dev *dev,
0133 const struct input_keymap_entry *ke,
0134 unsigned int *old_keycode)
0135 {
0136 struct key_entry *key;
0137
0138 if (dev->keycode) {
0139 key = sparse_keymap_locate(dev, ke);
0140 if (key && key->type == KE_KEY) {
0141 *old_keycode = key->keycode;
0142 key->keycode = ke->keycode;
0143 set_bit(ke->keycode, dev->keybit);
0144 if (!sparse_keymap_entry_from_keycode(dev, *old_keycode))
0145 clear_bit(*old_keycode, dev->keybit);
0146 return 0;
0147 }
0148 }
0149
0150 return -EINVAL;
0151 }
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166 int sparse_keymap_setup(struct input_dev *dev,
0167 const struct key_entry *keymap,
0168 int (*setup)(struct input_dev *, struct key_entry *))
0169 {
0170 size_t map_size = 1;
0171 const struct key_entry *e;
0172 struct key_entry *map, *entry;
0173 int i;
0174 int error;
0175
0176 for (e = keymap; e->type != KE_END; e++)
0177 map_size++;
0178
0179 map = devm_kmemdup(&dev->dev, keymap, map_size * sizeof(*map),
0180 GFP_KERNEL);
0181 if (!map)
0182 return -ENOMEM;
0183
0184 for (i = 0; i < map_size; i++) {
0185 entry = &map[i];
0186
0187 if (setup) {
0188 error = setup(dev, entry);
0189 if (error)
0190 return error;
0191 }
0192
0193 switch (entry->type) {
0194 case KE_KEY:
0195 __set_bit(EV_KEY, dev->evbit);
0196 __set_bit(entry->keycode, dev->keybit);
0197 break;
0198
0199 case KE_SW:
0200 case KE_VSW:
0201 __set_bit(EV_SW, dev->evbit);
0202 __set_bit(entry->sw.code, dev->swbit);
0203 break;
0204 }
0205 }
0206
0207 if (test_bit(EV_KEY, dev->evbit)) {
0208 __set_bit(KEY_UNKNOWN, dev->keybit);
0209 __set_bit(EV_MSC, dev->evbit);
0210 __set_bit(MSC_SCAN, dev->mscbit);
0211 }
0212
0213 dev->keycode = map;
0214 dev->keycodemax = map_size;
0215 dev->getkeycode = sparse_keymap_getkeycode;
0216 dev->setkeycode = sparse_keymap_setkeycode;
0217
0218 return 0;
0219 }
0220 EXPORT_SYMBOL(sparse_keymap_setup);
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *ke,
0235 unsigned int value, bool autorelease)
0236 {
0237 switch (ke->type) {
0238 case KE_KEY:
0239 input_event(dev, EV_MSC, MSC_SCAN, ke->code);
0240 input_report_key(dev, ke->keycode, value);
0241 input_sync(dev);
0242 if (value && autorelease) {
0243 input_report_key(dev, ke->keycode, 0);
0244 input_sync(dev);
0245 }
0246 break;
0247
0248 case KE_SW:
0249 value = ke->sw.value;
0250 fallthrough;
0251
0252 case KE_VSW:
0253 input_report_switch(dev, ke->sw.code, value);
0254 input_sync(dev);
0255 break;
0256 }
0257 }
0258 EXPORT_SYMBOL(sparse_keymap_report_entry);
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273 bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code,
0274 unsigned int value, bool autorelease)
0275 {
0276 const struct key_entry *ke =
0277 sparse_keymap_entry_from_scancode(dev, code);
0278 struct key_entry unknown_ke;
0279
0280 if (ke) {
0281 sparse_keymap_report_entry(dev, ke, value, autorelease);
0282 return true;
0283 }
0284
0285
0286 unknown_ke.type = KE_KEY;
0287 unknown_ke.code = code;
0288 unknown_ke.keycode = KEY_UNKNOWN;
0289 sparse_keymap_report_entry(dev, &unknown_ke, value, true);
0290
0291 return false;
0292 }
0293 EXPORT_SYMBOL(sparse_keymap_report_event);
0294