#include #include #include #include #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");