Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Generic support for sparse keymaps
0004  *
0005  * Copyright (c) 2009 Dmitry Torokhov
0006  *
0007  * Derived from wistron button driver:
0008  * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
0009  * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
0010  * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
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  * sparse_keymap_entry_from_scancode - perform sparse keymap lookup
0055  * @dev: Input device using sparse keymap
0056  * @code: Scan code
0057  *
0058  * This function is used to perform &struct key_entry lookup in an
0059  * input device using sparse keymap.
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  * sparse_keymap_entry_from_keycode - perform sparse keymap lookup
0076  * @dev: Input device using sparse keymap
0077  * @keycode: Key code
0078  *
0079  * This function is used to perform &struct key_entry lookup in an
0080  * input device using sparse keymap.
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  * sparse_keymap_setup - set up sparse keymap for an input device
0155  * @dev: Input device
0156  * @keymap: Keymap in form of array of &key_entry structures ending
0157  *  with %KE_END type entry
0158  * @setup: Function that can be used to adjust keymap entries
0159  *  depending on device's needs, may be %NULL
0160  *
0161  * The function calculates size and allocates copy of the original
0162  * keymap after which sets up input device event bits appropriately.
0163  * The allocated copy of the keymap is automatically freed when it
0164  * is no longer needed.
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; /* to account for the last KE_END entry */
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  * sparse_keymap_report_entry - report event corresponding to given key entry
0224  * @dev: Input device for which event should be reported
0225  * @ke: key entry describing event
0226  * @value: Value that should be reported (ignored by %KE_SW entries)
0227  * @autorelease: Signals whether release event should be emitted for %KE_KEY
0228  *  entries right after reporting press event, ignored by all other
0229  *  entries
0230  *
0231  * This function is used to report input event described by given
0232  * &struct key_entry.
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  * sparse_keymap_report_event - report event corresponding to given scancode
0262  * @dev: Input device using sparse keymap
0263  * @code: Scan code
0264  * @value: Value that should be reported (ignored by %KE_SW entries)
0265  * @autorelease: Signals whether release event should be emitted for %KE_KEY
0266  *  entries right after reporting press event, ignored by all other
0267  *  entries
0268  *
0269  * This function is used to perform lookup in an input device using sparse
0270  * keymap and report corresponding event. Returns %true if lookup was
0271  * successful and %false otherwise.
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     /* Report an unknown key event as a debugging aid */
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