diff --git a/index.html b/index.html index 8cf88a9..7206668 100644 --- a/index.html +++ b/index.html @@ -18,7 +18,7 @@
class_attribute
283 return len;
284
285fail_register_vinput:
-286 device_unregister(&vinput->dev);
-287 /* avoid calling vinput_destroy_vdevice() twice */
-288 return err;
-289fail_register:
-290 vinput_destroy_vdevice(vinput);
-291fail:
-292 return err;
-293}
-294/* This macro generates class_attr_export structure and export_store() */
-295static CLASS_ATTR_WO(export);
-296
-297#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)
-298static ssize_t unexport_store(const struct class *class,
-299 const struct class_attribute *attr,
-300#else
-301static ssize_t unexport_store(struct class *class, struct class_attribute *attr,
-302#endif
-303 const char *buf, size_t len)
-304{
-305 int err;
-306 unsigned long id;
-307 struct vinput *vinput;
-308
-309 err = kstrtol(buf, 10, &id);
-310 if (err) {
-311 err = -EINVAL;
-312 goto failed;
-313 }
-314
-315 vinput = vinput_get_vdevice_by_id(id);
-316 if (IS_ERR(vinput)) {
-317 pr_err("vinput: No such vinput device %ld\n", id);
-318 err = PTR_ERR(vinput);
-319 goto failed;
-320 }
-321
-322 vinput_unregister_vdevice(vinput);
-323 device_unregister(&vinput->dev);
-324
-325 return len;
-326failed:
-327 return err;
-328}
-329/* This macro generates class_attr_unexport structure and unexport_store() */
-330static CLASS_ATTR_WO(unexport);
-331
-332static struct attribute *vinput_class_attrs[] = {
-333 &class_attr_export.attr,
-334 &class_attr_unexport.attr,
-335 NULL,
-336};
-337
-338/* This macro generates vinput_class_groups structure */
-339ATTRIBUTE_GROUPS(vinput_class);
-340
-341static struct class vinput_class = {
-342 .name = "vinput",
-343#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
-344 .owner = THIS_MODULE,
-345#endif
-346 .class_groups = vinput_class_groups,
-347};
-348
-349int vinput_register(struct vinput_device *dev)
-350{
-351 spin_lock(&vinput_lock);
-352 list_add(&dev->list, &vinput_devices);
-353 spin_unlock(&vinput_lock);
-354
-355 pr_info("vinput: registered new virtual input device '%s'\n", dev->name);
+286 input_free_device(vinput->input);
+287 device_unregister(&vinput->dev);
+288 /* avoid calling vinput_destroy_vdevice() twice */
+289 return err;
+290fail_register:
+291 input_free_device(vinput->input);
+292 vinput_destroy_vdevice(vinput);
+293fail:
+294 return err;
+295}
+296/* This macro generates class_attr_export structure and export_store() */
+297static CLASS_ATTR_WO(export);
+298
+299#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)
+300static ssize_t unexport_store(const struct class *class,
+301 const struct class_attribute *attr,
+302#else
+303static ssize_t unexport_store(struct class *class, struct class_attribute *attr,
+304#endif
+305 const char *buf, size_t len)
+306{
+307 int err;
+308 unsigned long id;
+309 struct vinput *vinput;
+310
+311 err = kstrtol(buf, 10, &id);
+312 if (err) {
+313 err = -EINVAL;
+314 goto failed;
+315 }
+316
+317 vinput = vinput_get_vdevice_by_id(id);
+318 if (IS_ERR(vinput)) {
+319 pr_err("vinput: No such vinput device %ld\n", id);
+320 err = PTR_ERR(vinput);
+321 goto failed;
+322 }
+323
+324 vinput_unregister_vdevice(vinput);
+325 device_unregister(&vinput->dev);
+326
+327 return len;
+328failed:
+329 return err;
+330}
+331/* This macro generates class_attr_unexport structure and unexport_store() */
+332static CLASS_ATTR_WO(unexport);
+333
+334static struct attribute *vinput_class_attrs[] = {
+335 &class_attr_export.attr,
+336 &class_attr_unexport.attr,
+337 NULL,
+338};
+339
+340/* This macro generates vinput_class_groups structure */
+341ATTRIBUTE_GROUPS(vinput_class);
+342
+343static struct class vinput_class = {
+344 .name = "vinput",
+345#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
+346 .owner = THIS_MODULE,
+347#endif
+348 .class_groups = vinput_class_groups,
+349};
+350
+351int vinput_register(struct vinput_device *dev)
+352{
+353 spin_lock(&vinput_lock);
+354 list_add(&dev->list, &vinput_devices);
+355 spin_unlock(&vinput_lock);
356
-357 return 0;
-358}
-359EXPORT_SYMBOL(vinput_register);
-360
-361void vinput_unregister(struct vinput_device *dev)
-362{
-363 struct list_head *curr, *next;
-364
-365 /* Remove from the list first */
-366 spin_lock(&vinput_lock);
-367 list_del(&dev->list);
-368 spin_unlock(&vinput_lock);
-369
-370 /* unregister all devices of this type */
-371 list_for_each_safe (curr, next, &vinput_vdevices) {
-372 struct vinput *vinput = list_entry(curr, struct vinput, list);
-373 if (vinput && vinput->type == dev) {
-374 vinput_unregister_vdevice(vinput);
-375 device_unregister(&vinput->dev);
-376 }
-377 }
-378
-379 pr_info("vinput: unregistered virtual input device '%s'\n", dev->name);
-380}
-381EXPORT_SYMBOL(vinput_unregister);
-382
-383static int __init vinput_init(void)
-384{
-385 int err = 0;
-386
-387 pr_info("vinput: Loading virtual input driver\n");
+357 pr_info("vinput: registered new virtual input device '%s'\n", dev->name);
+358
+359 return 0;
+360}
+361EXPORT_SYMBOL(vinput_register);
+362
+363void vinput_unregister(struct vinput_device *dev)
+364{
+365 struct list_head *curr, *next;
+366
+367 /* Remove from the list first */
+368 spin_lock(&vinput_lock);
+369 list_del(&dev->list);
+370 spin_unlock(&vinput_lock);
+371
+372 /* unregister all devices of this type */
+373 list_for_each_safe (curr, next, &vinput_vdevices) {
+374 struct vinput *vinput = list_entry(curr, struct vinput, list);
+375 if (vinput && vinput->type == dev) {
+376 vinput_unregister_vdevice(vinput);
+377 device_unregister(&vinput->dev);
+378 }
+379 }
+380
+381 pr_info("vinput: unregistered virtual input device '%s'\n", dev->name);
+382}
+383EXPORT_SYMBOL(vinput_unregister);
+384
+385static int __init vinput_init(void)
+386{
+387 int err = 0;
388
-389 vinput_dev = register_chrdev(0, DRIVER_NAME, &vinput_fops);
-390 if (vinput_dev < 0) {
-391 pr_err("vinput: Unable to allocate char dev region\n");
-392 err = vinput_dev;
-393 goto failed_alloc;
-394 }
-395
-396 spin_lock_init(&vinput_lock);
+389 pr_info("vinput: Loading virtual input driver\n");
+390
+391 vinput_dev = register_chrdev(0, DRIVER_NAME, &vinput_fops);
+392 if (vinput_dev < 0) {
+393 pr_err("vinput: Unable to allocate char dev region\n");
+394 err = vinput_dev;
+395 goto failed_alloc;
+396 }
397
-398 err = class_register(&vinput_class);
-399 if (err < 0) {
-400 pr_err("vinput: Unable to register vinput class\n");
-401 goto failed_class;
-402 }
-403
-404 return 0;
-405failed_class:
-406 unregister_chrdev(vinput_dev, DRIVER_NAME);
-407failed_alloc:
-408 return err;
-409}
-410
-411static void __exit vinput_end(void)
-412{
-413 pr_info("vinput: Unloading virtual input driver\n");
-414
-415 unregister_chrdev(vinput_dev, DRIVER_NAME);
-416 class_unregister(&vinput_class);
-417}
-418
-419module_init(vinput_init);
-420module_exit(vinput_end);
-421
-422MODULE_LICENSE("GPL");
-423MODULE_DESCRIPTION("Emulate input events");
+398 spin_lock_init(&vinput_lock);
+399
+400 err = class_register(&vinput_class);
+401 if (err < 0) {
+402 pr_err("vinput: Unable to register vinput class\n");
+403 goto failed_class;
+404 }
+405
+406 return 0;
+407failed_class:
+408 unregister_chrdev(vinput_dev, DRIVER_NAME);
+409failed_alloc:
+410 return err;
+411}
+412
+413static void __exit vinput_end(void)
+414{
+415 pr_info("vinput: Unloading virtual input driver\n");
+416
+417 unregister_chrdev(vinput_dev, DRIVER_NAME);
+418 class_unregister(&vinput_class);
+419}
+420
+421module_init(vinput_init);
+422module_exit(vinput_end);
+423
+424MODULE_LICENSE("GPL");
+425MODULE_DESCRIPTION("Emulate input events");
Here the virtual keyboard is one of example to use vinput. It supports all
KEY_MAX
keycodes. The injection format is the KEY_CODE
@@ -6261,7 +6263,7 @@ following demonstrates how simulation work.
= 34):
- 1echo "+34" | sudo tee /dev/vinput0
+ 1echo "+34" | sudo tee /dev/vinput0
Simulate a key release on "g" ( KEY_G
= 34):
@@ -6269,120 +6271,120 @@ following demonstrates how simulation work.
- 1echo "-34" | sudo tee /dev/vinput0
+ 1echo "-34" | sudo tee /dev/vinput0
- 1/*
-2 * vkbd.c
-3 */
-4
-5#include <linux/init.h>
-6#include <linux/input.h>
-7#include <linux/module.h>
-8#include <linux/spinlock.h>
-9
-10#include "vinput.h"
-11
-12#define VINPUT_KBD "vkbd"
-13#define VINPUT_RELEASE 0
-14#define VINPUT_PRESS 1
-15
-16static unsigned short vkeymap[KEY_MAX];
-17
-18static int vinput_vkbd_init(struct vinput *vinput)
-19{
-20 int i;
-21
-22 /* Set up the input bitfield */
-23 vinput->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
-24 vinput->input->keycodesize = sizeof(unsigned short);
-25 vinput->input->keycodemax = KEY_MAX;
-26 vinput->input->keycode = vkeymap;
-27
-28 for (i = 0; i < KEY_MAX; i++)
-29 set_bit(vkeymap[i], vinput->input->keybit);
-30
-31 /* vinput will help us allocate new input device structure via
-32 * input_allocate_device(). So, we can register it straightforwardly.
-33 */
-34 return input_register_device(vinput->input);
-35}
-36
-37static int vinput_vkbd_read(struct vinput *vinput, char *buff, int len)
-38{
-39 spin_lock(&vinput->lock);
-40 len = snprintf(buff, len, "%+ld\n", vinput->last_entry);
-41 spin_unlock(&vinput->lock);
-42
-43 return len;
-44}
-45
-46static int vinput_vkbd_send(struct vinput *vinput, char *buff, int len)
-47{
-48 int ret;
-49 long key = 0;
-50 short type = VINPUT_PRESS;
-51
-52 /* Determine which event was received (press or release)
-53 * and store the state.
-54 */
-55 if (buff[0] == '+')
-56 ret = kstrtol(buff + 1, 10, &key);
-57 else
-58 ret = kstrtol(buff, 10, &key);
-59 if (ret)
-60 dev_err(&vinput->dev, "error during kstrtol: -%d\n", ret);
-61 spin_lock(&vinput->lock);
-62 vinput->last_entry = key;
-63 spin_unlock(&vinput->lock);
-64
-65 if (key < 0) {
-66 type = VINPUT_RELEASE;
-67 key = -key;
-68 }
-69
-70 dev_info(&vinput->dev, "Event %s code %ld\n",
-71 (type == VINPUT_RELEASE) ? "VINPUT_RELEASE" : "VINPUT_PRESS", key);
-72
-73 /* Report the state received to input subsystem. */
-74 input_report_key(vinput->input, key, type);
-75 /* Tell input subsystem that it finished the report. */
-76 input_sync(vinput->input);
-77
-78 return len;
-79}
-80
-81static struct vinput_ops vkbd_ops = {
-82 .init = vinput_vkbd_init,
-83 .send = vinput_vkbd_send,
-84 .read = vinput_vkbd_read,
-85};
-86
-87static struct vinput_device vkbd_dev = {
-88 .name = VINPUT_KBD,
-89 .ops = &vkbd_ops,
-90};
-91
-92static int __init vkbd_init(void)
-93{
-94 int i;
-95
-96 for (i = 0; i < KEY_MAX; i++)
-97 vkeymap[i] = i;
-98 return vinput_register(&vkbd_dev);
-99}
-100
-101static void __exit vkbd_end(void)
-102{
-103 vinput_unregister(&vkbd_dev);
-104}
-105
-106module_init(vkbd_init);
-107module_exit(vkbd_end);
-108
-109MODULE_LICENSE("GPL");
-110MODULE_DESCRIPTION("Emulate keyboard input events through /dev/vinput");
+ 1/*
+2 * vkbd.c
+3 */
+4
+5#include <linux/init.h>
+6#include <linux/input.h>
+7#include <linux/module.h>
+8#include <linux/spinlock.h>
+9
+10#include "vinput.h"
+11
+12#define VINPUT_KBD "vkbd"
+13#define VINPUT_RELEASE 0
+14#define VINPUT_PRESS 1
+15
+16static unsigned short vkeymap[KEY_MAX];
+17
+18static int vinput_vkbd_init(struct vinput *vinput)
+19{
+20 int i;
+21
+22 /* Set up the input bitfield */
+23 vinput->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+24 vinput->input->keycodesize = sizeof(unsigned short);
+25 vinput->input->keycodemax = KEY_MAX;
+26 vinput->input->keycode = vkeymap;
+27
+28 for (i = 0; i < KEY_MAX; i++)
+29 set_bit(vkeymap[i], vinput->input->keybit);
+30
+31 /* vinput will help us allocate new input device structure via
+32 * input_allocate_device(). So, we can register it straightforwardly.
+33 */
+34 return input_register_device(vinput->input);
+35}
+36
+37static int vinput_vkbd_read(struct vinput *vinput, char *buff, int len)
+38{
+39 spin_lock(&vinput->lock);
+40 len = snprintf(buff, len, "%+ld\n", vinput->last_entry);
+41 spin_unlock(&vinput->lock);
+42
+43 return len;
+44}
+45
+46static int vinput_vkbd_send(struct vinput *vinput, char *buff, int len)
+47{
+48 int ret;
+49 long key = 0;
+50 short type = VINPUT_PRESS;
+51
+52 /* Determine which event was received (press or release)
+53 * and store the state.
+54 */
+55 if (buff[0] == '+')
+56 ret = kstrtol(buff + 1, 10, &key);
+57 else
+58 ret = kstrtol(buff, 10, &key);
+59 if (ret)
+60 dev_err(&vinput->dev, "error during kstrtol: -%d\n", ret);
+61 spin_lock(&vinput->lock);
+62 vinput->last_entry = key;
+63 spin_unlock(&vinput->lock);
+64
+65 if (key < 0) {
+66 type = VINPUT_RELEASE;
+67 key = -key;
+68 }
+69
+70 dev_info(&vinput->dev, "Event %s code %ld\n",
+71 (type == VINPUT_RELEASE) ? "VINPUT_RELEASE" : "VINPUT_PRESS", key);
+72
+73 /* Report the state received to input subsystem. */
+74 input_report_key(vinput->input, key, type);
+75 /* Tell input subsystem that it finished the report. */
+76 input_sync(vinput->input);
+77
+78 return len;
+79}
+80
+81static struct vinput_ops vkbd_ops = {
+82 .init = vinput_vkbd_init,
+83 .send = vinput_vkbd_send,
+84 .read = vinput_vkbd_read,
+85};
+86
+87static struct vinput_device vkbd_dev = {
+88 .name = VINPUT_KBD,
+89 .ops = &vkbd_ops,
+90};
+91
+92static int __init vkbd_init(void)
+93{
+94 int i;
+95
+96 for (i = 0; i < KEY_MAX; i++)
+97 vkeymap[i] = i;
+98 return vinput_register(&vkbd_dev);
+99}
+100
+101static void __exit vkbd_end(void)
+102{
+103 vinput_unregister(&vkbd_dev);
+104}
+105
+106module_init(vkbd_init);
+107module_exit(vkbd_end);
+108
+109MODULE_LICENSE("GPL");
+110MODULE_DESCRIPTION("Emulate keyboard input events through /dev/vinput");
17 Standardizing the interfaces: The Device Model
diff --git a/lkmpg-for-ht.html b/lkmpg-for-ht.html
index 8cf88a9..7206668 100644
--- a/lkmpg-for-ht.html
+++ b/lkmpg-for-ht.html
@@ -18,7 +18,7 @@
The Linux Kernel Module Programming Guide
-October 25, 2024
+October 26, 2024
@@ -6111,144 +6111,146 @@ will generate the class_attribute
283 return len;
284
285fail_register_vinput:
-286 device_unregister(&vinput->dev);
-287 /* avoid calling vinput_destroy_vdevice() twice */
-288 return err;
-289fail_register:
-290 vinput_destroy_vdevice(vinput);
-291fail:
-292 return err;
-293}
-294/* This macro generates class_attr_export structure and export_store() */
-295static CLASS_ATTR_WO(export);
-296
-297#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)
-298static ssize_t unexport_store(const struct class *class,
-299 const struct class_attribute *attr,
-300#else
-301static ssize_t unexport_store(struct class *class, struct class_attribute *attr,
-302#endif
-303 const char *buf, size_t len)
-304{
-305 int err;
-306 unsigned long id;
-307 struct vinput *vinput;
-308
-309 err = kstrtol(buf, 10, &id);
-310 if (err) {
-311 err = -EINVAL;
-312 goto failed;
-313 }
-314
-315 vinput = vinput_get_vdevice_by_id(id);
-316 if (IS_ERR(vinput)) {
-317 pr_err("vinput: No such vinput device %ld\n", id);
-318 err = PTR_ERR(vinput);
-319 goto failed;
-320 }
-321
-322 vinput_unregister_vdevice(vinput);
-323 device_unregister(&vinput->dev);
-324
-325 return len;
-326failed:
-327 return err;
-328}
-329/* This macro generates class_attr_unexport structure and unexport_store() */
-330static CLASS_ATTR_WO(unexport);
-331
-332static struct attribute *vinput_class_attrs[] = {
-333 &class_attr_export.attr,
-334 &class_attr_unexport.attr,
-335 NULL,
-336};
-337
-338/* This macro generates vinput_class_groups structure */
-339ATTRIBUTE_GROUPS(vinput_class);
-340
-341static struct class vinput_class = {
-342 .name = "vinput",
-343#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
-344 .owner = THIS_MODULE,
-345#endif
-346 .class_groups = vinput_class_groups,
-347};
-348
-349int vinput_register(struct vinput_device *dev)
-350{
-351 spin_lock(&vinput_lock);
-352 list_add(&dev->list, &vinput_devices);
-353 spin_unlock(&vinput_lock);
-354
-355 pr_info("vinput: registered new virtual input device '%s'\n", dev->name);
+286 input_free_device(vinput->input);
+287 device_unregister(&vinput->dev);
+288 /* avoid calling vinput_destroy_vdevice() twice */
+289 return err;
+290fail_register:
+291 input_free_device(vinput->input);
+292 vinput_destroy_vdevice(vinput);
+293fail:
+294 return err;
+295}
+296/* This macro generates class_attr_export structure and export_store() */
+297static CLASS_ATTR_WO(export);
+298
+299#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)
+300static ssize_t unexport_store(const struct class *class,
+301 const struct class_attribute *attr,
+302#else
+303static ssize_t unexport_store(struct class *class, struct class_attribute *attr,
+304#endif
+305 const char *buf, size_t len)
+306{
+307 int err;
+308 unsigned long id;
+309 struct vinput *vinput;
+310
+311 err = kstrtol(buf, 10, &id);
+312 if (err) {
+313 err = -EINVAL;
+314 goto failed;
+315 }
+316
+317 vinput = vinput_get_vdevice_by_id(id);
+318 if (IS_ERR(vinput)) {
+319 pr_err("vinput: No such vinput device %ld\n", id);
+320 err = PTR_ERR(vinput);
+321 goto failed;
+322 }
+323
+324 vinput_unregister_vdevice(vinput);
+325 device_unregister(&vinput->dev);
+326
+327 return len;
+328failed:
+329 return err;
+330}
+331/* This macro generates class_attr_unexport structure and unexport_store() */
+332static CLASS_ATTR_WO(unexport);
+333
+334static struct attribute *vinput_class_attrs[] = {
+335 &class_attr_export.attr,
+336 &class_attr_unexport.attr,
+337 NULL,
+338};
+339
+340/* This macro generates vinput_class_groups structure */
+341ATTRIBUTE_GROUPS(vinput_class);
+342
+343static struct class vinput_class = {
+344 .name = "vinput",
+345#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
+346 .owner = THIS_MODULE,
+347#endif
+348 .class_groups = vinput_class_groups,
+349};
+350
+351int vinput_register(struct vinput_device *dev)
+352{
+353 spin_lock(&vinput_lock);
+354 list_add(&dev->list, &vinput_devices);
+355 spin_unlock(&vinput_lock);
356
-357 return 0;
-358}
-359EXPORT_SYMBOL(vinput_register);
-360
-361void vinput_unregister(struct vinput_device *dev)
-362{
-363 struct list_head *curr, *next;
-364
-365 /* Remove from the list first */
-366 spin_lock(&vinput_lock);
-367 list_del(&dev->list);
-368 spin_unlock(&vinput_lock);
-369
-370 /* unregister all devices of this type */
-371 list_for_each_safe (curr, next, &vinput_vdevices) {
-372 struct vinput *vinput = list_entry(curr, struct vinput, list);
-373 if (vinput && vinput->type == dev) {
-374 vinput_unregister_vdevice(vinput);
-375 device_unregister(&vinput->dev);
-376 }
-377 }
-378
-379 pr_info("vinput: unregistered virtual input device '%s'\n", dev->name);
-380}
-381EXPORT_SYMBOL(vinput_unregister);
-382
-383static int __init vinput_init(void)
-384{
-385 int err = 0;
-386
-387 pr_info("vinput: Loading virtual input driver\n");
+357 pr_info("vinput: registered new virtual input device '%s'\n", dev->name);
+358
+359 return 0;
+360}
+361EXPORT_SYMBOL(vinput_register);
+362
+363void vinput_unregister(struct vinput_device *dev)
+364{
+365 struct list_head *curr, *next;
+366
+367 /* Remove from the list first */
+368 spin_lock(&vinput_lock);
+369 list_del(&dev->list);
+370 spin_unlock(&vinput_lock);
+371
+372 /* unregister all devices of this type */
+373 list_for_each_safe (curr, next, &vinput_vdevices) {
+374 struct vinput *vinput = list_entry(curr, struct vinput, list);
+375 if (vinput && vinput->type == dev) {
+376 vinput_unregister_vdevice(vinput);
+377 device_unregister(&vinput->dev);
+378 }
+379 }
+380
+381 pr_info("vinput: unregistered virtual input device '%s'\n", dev->name);
+382}
+383EXPORT_SYMBOL(vinput_unregister);
+384
+385static int __init vinput_init(void)
+386{
+387 int err = 0;
388
-389 vinput_dev = register_chrdev(0, DRIVER_NAME, &vinput_fops);
-390 if (vinput_dev < 0) {
-391 pr_err("vinput: Unable to allocate char dev region\n");
-392 err = vinput_dev;
-393 goto failed_alloc;
-394 }
-395
-396 spin_lock_init(&vinput_lock);
+389 pr_info("vinput: Loading virtual input driver\n");
+390
+391 vinput_dev = register_chrdev(0, DRIVER_NAME, &vinput_fops);
+392 if (vinput_dev < 0) {
+393 pr_err("vinput: Unable to allocate char dev region\n");
+394 err = vinput_dev;
+395 goto failed_alloc;
+396 }
397
-398 err = class_register(&vinput_class);
-399 if (err < 0) {
-400 pr_err("vinput: Unable to register vinput class\n");
-401 goto failed_class;
-402 }
-403
-404 return 0;
-405failed_class:
-406 unregister_chrdev(vinput_dev, DRIVER_NAME);
-407failed_alloc:
-408 return err;
-409}
-410
-411static void __exit vinput_end(void)
-412{
-413 pr_info("vinput: Unloading virtual input driver\n");
-414
-415 unregister_chrdev(vinput_dev, DRIVER_NAME);
-416 class_unregister(&vinput_class);
-417}
-418
-419module_init(vinput_init);
-420module_exit(vinput_end);
-421
-422MODULE_LICENSE("GPL");
-423MODULE_DESCRIPTION("Emulate input events");
+398 spin_lock_init(&vinput_lock);
+399
+400 err = class_register(&vinput_class);
+401 if (err < 0) {
+402 pr_err("vinput: Unable to register vinput class\n");
+403 goto failed_class;
+404 }
+405
+406 return 0;
+407failed_class:
+408 unregister_chrdev(vinput_dev, DRIVER_NAME);
+409failed_alloc:
+410 return err;
+411}
+412
+413static void __exit vinput_end(void)
+414{
+415 pr_info("vinput: Unloading virtual input driver\n");
+416
+417 unregister_chrdev(vinput_dev, DRIVER_NAME);
+418 class_unregister(&vinput_class);
+419}
+420
+421module_init(vinput_init);
+422module_exit(vinput_end);
+423
+424MODULE_LICENSE("GPL");
+425MODULE_DESCRIPTION("Emulate input events");
Here the virtual keyboard is one of example to use vinput. It supports all
KEY_MAX
keycodes. The injection format is the KEY_CODE
@@ -6261,7 +6263,7 @@ following demonstrates how simulation work.
= 34):
- 1echo "+34" | sudo tee /dev/vinput0
+ 1echo "+34" | sudo tee /dev/vinput0
Simulate a key release on "g" ( KEY_G
= 34):
@@ -6269,120 +6271,120 @@ following demonstrates how simulation work.
- 1echo "-34" | sudo tee /dev/vinput0
+ 1echo "-34" | sudo tee /dev/vinput0
- 1/*
-2 * vkbd.c
-3 */
-4
-5#include <linux/init.h>
-6#include <linux/input.h>
-7#include <linux/module.h>
-8#include <linux/spinlock.h>
-9
-10#include "vinput.h"
-11
-12#define VINPUT_KBD "vkbd"
-13#define VINPUT_RELEASE 0
-14#define VINPUT_PRESS 1
-15
-16static unsigned short vkeymap[KEY_MAX];
-17
-18static int vinput_vkbd_init(struct vinput *vinput)
-19{
-20 int i;
-21
-22 /* Set up the input bitfield */
-23 vinput->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
-24 vinput->input->keycodesize = sizeof(unsigned short);
-25 vinput->input->keycodemax = KEY_MAX;
-26 vinput->input->keycode = vkeymap;
-27
-28 for (i = 0; i < KEY_MAX; i++)
-29 set_bit(vkeymap[i], vinput->input->keybit);
-30
-31 /* vinput will help us allocate new input device structure via
-32 * input_allocate_device(). So, we can register it straightforwardly.
-33 */
-34 return input_register_device(vinput->input);
-35}
-36
-37static int vinput_vkbd_read(struct vinput *vinput, char *buff, int len)
-38{
-39 spin_lock(&vinput->lock);
-40 len = snprintf(buff, len, "%+ld\n", vinput->last_entry);
-41 spin_unlock(&vinput->lock);
-42
-43 return len;
-44}
-45
-46static int vinput_vkbd_send(struct vinput *vinput, char *buff, int len)
-47{
-48 int ret;
-49 long key = 0;
-50 short type = VINPUT_PRESS;
-51
-52 /* Determine which event was received (press or release)
-53 * and store the state.
-54 */
-55 if (buff[0] == '+')
-56 ret = kstrtol(buff + 1, 10, &key);
-57 else
-58 ret = kstrtol(buff, 10, &key);
-59 if (ret)
-60 dev_err(&vinput->dev, "error during kstrtol: -%d\n", ret);
-61 spin_lock(&vinput->lock);
-62 vinput->last_entry = key;
-63 spin_unlock(&vinput->lock);
-64
-65 if (key < 0) {
-66 type = VINPUT_RELEASE;
-67 key = -key;
-68 }
-69
-70 dev_info(&vinput->dev, "Event %s code %ld\n",
-71 (type == VINPUT_RELEASE) ? "VINPUT_RELEASE" : "VINPUT_PRESS", key);
-72
-73 /* Report the state received to input subsystem. */
-74 input_report_key(vinput->input, key, type);
-75 /* Tell input subsystem that it finished the report. */
-76 input_sync(vinput->input);
-77
-78 return len;
-79}
-80
-81static struct vinput_ops vkbd_ops = {
-82 .init = vinput_vkbd_init,
-83 .send = vinput_vkbd_send,
-84 .read = vinput_vkbd_read,
-85};
-86
-87static struct vinput_device vkbd_dev = {
-88 .name = VINPUT_KBD,
-89 .ops = &vkbd_ops,
-90};
-91
-92static int __init vkbd_init(void)
-93{
-94 int i;
-95
-96 for (i = 0; i < KEY_MAX; i++)
-97 vkeymap[i] = i;
-98 return vinput_register(&vkbd_dev);
-99}
-100
-101static void __exit vkbd_end(void)
-102{
-103 vinput_unregister(&vkbd_dev);
-104}
-105
-106module_init(vkbd_init);
-107module_exit(vkbd_end);
-108
-109MODULE_LICENSE("GPL");
-110MODULE_DESCRIPTION("Emulate keyboard input events through /dev/vinput");
+ 1/*
+2 * vkbd.c
+3 */
+4
+5#include <linux/init.h>
+6#include <linux/input.h>
+7#include <linux/module.h>
+8#include <linux/spinlock.h>
+9
+10#include "vinput.h"
+11
+12#define VINPUT_KBD "vkbd"
+13#define VINPUT_RELEASE 0
+14#define VINPUT_PRESS 1
+15
+16static unsigned short vkeymap[KEY_MAX];
+17
+18static int vinput_vkbd_init(struct vinput *vinput)
+19{
+20 int i;
+21
+22 /* Set up the input bitfield */
+23 vinput->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+24 vinput->input->keycodesize = sizeof(unsigned short);
+25 vinput->input->keycodemax = KEY_MAX;
+26 vinput->input->keycode = vkeymap;
+27
+28 for (i = 0; i < KEY_MAX; i++)
+29 set_bit(vkeymap[i], vinput->input->keybit);
+30
+31 /* vinput will help us allocate new input device structure via
+32 * input_allocate_device(). So, we can register it straightforwardly.
+33 */
+34 return input_register_device(vinput->input);
+35}
+36
+37static int vinput_vkbd_read(struct vinput *vinput, char *buff, int len)
+38{
+39 spin_lock(&vinput->lock);
+40 len = snprintf(buff, len, "%+ld\n", vinput->last_entry);
+41 spin_unlock(&vinput->lock);
+42
+43 return len;
+44}
+45
+46static int vinput_vkbd_send(struct vinput *vinput, char *buff, int len)
+47{
+48 int ret;
+49 long key = 0;
+50 short type = VINPUT_PRESS;
+51
+52 /* Determine which event was received (press or release)
+53 * and store the state.
+54 */
+55 if (buff[0] == '+')
+56 ret = kstrtol(buff + 1, 10, &key);
+57 else
+58 ret = kstrtol(buff, 10, &key);
+59 if (ret)
+60 dev_err(&vinput->dev, "error during kstrtol: -%d\n", ret);
+61 spin_lock(&vinput->lock);
+62 vinput->last_entry = key;
+63 spin_unlock(&vinput->lock);
+64
+65 if (key < 0) {
+66 type = VINPUT_RELEASE;
+67 key = -key;
+68 }
+69
+70 dev_info(&vinput->dev, "Event %s code %ld\n",
+71 (type == VINPUT_RELEASE) ? "VINPUT_RELEASE" : "VINPUT_PRESS", key);
+72
+73 /* Report the state received to input subsystem. */
+74 input_report_key(vinput->input, key, type);
+75 /* Tell input subsystem that it finished the report. */
+76 input_sync(vinput->input);
+77
+78 return len;
+79}
+80
+81static struct vinput_ops vkbd_ops = {
+82 .init = vinput_vkbd_init,
+83 .send = vinput_vkbd_send,
+84 .read = vinput_vkbd_read,
+85};
+86
+87static struct vinput_device vkbd_dev = {
+88 .name = VINPUT_KBD,
+89 .ops = &vkbd_ops,
+90};
+91
+92static int __init vkbd_init(void)
+93{
+94 int i;
+95
+96 for (i = 0; i < KEY_MAX; i++)
+97 vkeymap[i] = i;
+98 return vinput_register(&vkbd_dev);
+99}
+100
+101static void __exit vkbd_end(void)
+102{
+103 vinput_unregister(&vkbd_dev);
+104}
+105
+106module_init(vkbd_init);
+107module_exit(vkbd_end);
+108
+109MODULE_LICENSE("GPL");
+110MODULE_DESCRIPTION("Emulate keyboard input events through /dev/vinput");
17 Standardizing the interfaces: The Device Model