123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- /*
- * vkbd.c
- */
- #include <linux/init.h>
- #include <linux/input.h>
- #include <linux/module.h>
- #include <linux/spinlock.h>
- #include "vinput.h"
- #define VINPUT_KBD "vkbd"
- #define VINPUT_RELEASE 0
- #define VINPUT_PRESS 1
- static unsigned short vkeymap[KEY_MAX];
- static int vinput_vkbd_init(struct vinput *vinput)
- {
- int i;
- /* Set up the input bitfield */
- vinput->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
- vinput->input->keycodesize = sizeof(unsigned short);
- vinput->input->keycodemax = KEY_MAX;
- vinput->input->keycode = vkeymap;
- for (i = 0; i < KEY_MAX; i++)
- set_bit(vkeymap[i], vinput->input->keybit);
- /* vinput will help us allocate new input device structure via
- * input_allocate_device(). So, we can register it straightforwardly.
- */
- return input_register_device(vinput->input);
- }
- static int vinput_vkbd_read(struct vinput *vinput, char *buff, int len)
- {
- spin_lock(&vinput->lock);
- len = snprintf(buff, len, "%+ld\n", vinput->last_entry);
- spin_unlock(&vinput->lock);
- return len;
- }
- static int vinput_vkbd_send(struct vinput *vinput, char *buff, int len)
- {
- int ret;
- long key = 0;
- short type = VINPUT_PRESS;
- /* Determine which event was received (press or release)
- * and store the state.
- */
- if (buff[0] == '+')
- ret = kstrtol(buff + 1, 10, &key);
- else
- ret = kstrtol(buff, 10, &key);
- if (ret)
- dev_err(&vinput->dev, "error during kstrtol: -%d\n", ret);
- spin_lock(&vinput->lock);
- vinput->last_entry = key;
- spin_unlock(&vinput->lock);
- if (key < 0) {
- type = VINPUT_RELEASE;
- key = -key;
- }
- dev_info(&vinput->dev, "Event %s code %ld\n",
- (type == VINPUT_RELEASE) ? "VINPUT_RELEASE" : "VINPUT_PRESS", key);
- /* Report the state received to input subsystem. */
- input_report_key(vinput->input, key, type);
- /* Tell input subsystem that it finished the report. */
- input_sync(vinput->input);
- return len;
- }
- static struct vinput_ops vkbd_ops = {
- .init = vinput_vkbd_init,
- .send = vinput_vkbd_send,
- .read = vinput_vkbd_read,
- };
- static struct vinput_device vkbd_dev = {
- .name = VINPUT_KBD,
- .ops = &vkbd_ops,
- };
- static int __init vkbd_init(void)
- {
- int i;
- for (i = 0; i < KEY_MAX; i++)
- vkeymap[i] = i;
- return vinput_register(&vkbd_dev);
- }
- static void __exit vkbd_end(void)
- {
- vinput_unregister(&vkbd_dev);
- }
- module_init(vkbd_init);
- module_exit(vkbd_end);
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("Emulate keyboard input events through /dev/vinput");
|