lkmpg/examples/vkbd.c
linD026 636c1e702d Introduce Virtual Input Device Driver
Add the new section of input device driver, vinput[1].

Also, update the Acknowledgements.

[1] https://github.com/sysprog21/vinput
2022-04-06 17:13:29 +08:00

107 lines
2.5 KiB
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");