vkbd.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #include <linux/init.h>
  2. #include <linux/input.h>
  3. #include <linux/module.h>
  4. #include <linux/spinlock.h>
  5. #include "vinput.h"
  6. #define VINPUT_KBD "vkbd"
  7. #define VINPUT_RELEASE 0
  8. #define VINPUT_PRESS 1
  9. static unsigned short vkeymap[KEY_MAX];
  10. static int vinput_vkbd_init(struct vinput *vinput)
  11. {
  12. int i;
  13. /* Set up the input bitfield */
  14. vinput->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
  15. vinput->input->keycodesize = sizeof(unsigned short);
  16. vinput->input->keycodemax = KEY_MAX;
  17. vinput->input->keycode = vkeymap;
  18. for (i = 0; i < KEY_MAX; i++)
  19. set_bit(vkeymap[i], vinput->input->keybit);
  20. /* vinput will help us allocate new input device structure via
  21. * input_allocate_device(). So, we can register it straightforwardly.
  22. */
  23. return input_register_device(vinput->input);
  24. }
  25. static int vinput_vkbd_read(struct vinput *vinput, char *buff, int len)
  26. {
  27. spin_lock(&vinput->lock);
  28. len = snprintf(buff, len, "%+ld\n", vinput->last_entry);
  29. spin_unlock(&vinput->lock);
  30. return len;
  31. }
  32. static int vinput_vkbd_send(struct vinput *vinput, char *buff, int len)
  33. {
  34. int ret;
  35. long key = 0;
  36. short type = VINPUT_PRESS;
  37. /* Determine which event was received (press or release)
  38. * and store the state.
  39. */
  40. if (buff[0] == '+')
  41. ret = kstrtol(buff + 1, 10, &key);
  42. else
  43. ret = kstrtol(buff, 10, &key);
  44. if (ret)
  45. dev_err(&vinput->dev, "error during kstrtol: -%d\n", ret);
  46. spin_lock(&vinput->lock);
  47. vinput->last_entry = key;
  48. spin_unlock(&vinput->lock);
  49. if (key < 0) {
  50. type = VINPUT_RELEASE;
  51. key = -key;
  52. }
  53. dev_info(&vinput->dev, "Event %s code %ld\n",
  54. (type == VINPUT_RELEASE) ? "VINPUT_RELEASE" : "VINPUT_PRESS", key);
  55. /* Report the state received to input subsystem. */
  56. input_report_key(vinput->input, key, type);
  57. /* Tell input subsystem that it finished the report. */
  58. input_sync(vinput->input);
  59. return len;
  60. }
  61. static struct vinput_ops vkbd_ops = {
  62. .init = vinput_vkbd_init,
  63. .send = vinput_vkbd_send,
  64. .read = vinput_vkbd_read,
  65. };
  66. static struct vinput_device vkbd_dev = {
  67. .name = VINPUT_KBD,
  68. .ops = &vkbd_ops,
  69. };
  70. static int __init vkbd_init(void)
  71. {
  72. int i;
  73. for (i = 0; i < KEY_MAX; i++)
  74. vkeymap[i] = i;
  75. return vinput_register(&vkbd_dev);
  76. }
  77. static void __exit vkbd_end(void)
  78. {
  79. vinput_unregister(&vkbd_dev);
  80. }
  81. module_init(vkbd_init);
  82. module_exit(vkbd_end);
  83. MODULE_LICENSE("GPL");
  84. MODULE_DESCRIPTION("Emulate keyboard input events through /dev/vinput");