fakekey.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /* fakekey.c
  3. * Functions for simulating keypresses.
  4. *
  5. * Copyright (C) 2010 the Speakup Team
  6. */
  7. #include <linux/types.h>
  8. #include <linux/slab.h>
  9. #include <linux/preempt.h>
  10. #include <linux/percpu.h>
  11. #include <linux/input.h>
  12. #include "speakup.h"
  13. #define PRESSED 1
  14. #define RELEASED 0
  15. static DEFINE_PER_CPU(int, reporting_keystroke);
  16. static struct input_dev *virt_keyboard;
  17. int speakup_add_virtual_keyboard(void)
  18. {
  19. int err;
  20. virt_keyboard = input_allocate_device();
  21. if (!virt_keyboard)
  22. return -ENOMEM;
  23. virt_keyboard->name = "Speakup";
  24. virt_keyboard->id.bustype = BUS_VIRTUAL;
  25. virt_keyboard->phys = "speakup/input0";
  26. virt_keyboard->dev.parent = NULL;
  27. __set_bit(EV_KEY, virt_keyboard->evbit);
  28. __set_bit(KEY_DOWN, virt_keyboard->keybit);
  29. err = input_register_device(virt_keyboard);
  30. if (err) {
  31. input_free_device(virt_keyboard);
  32. virt_keyboard = NULL;
  33. }
  34. return err;
  35. }
  36. void speakup_remove_virtual_keyboard(void)
  37. {
  38. if (virt_keyboard) {
  39. input_unregister_device(virt_keyboard);
  40. virt_keyboard = NULL;
  41. }
  42. }
  43. /*
  44. * Send a simulated down-arrow to the application.
  45. */
  46. void speakup_fake_down_arrow(void)
  47. {
  48. unsigned long flags;
  49. /* disable keyboard interrupts */
  50. local_irq_save(flags);
  51. /* don't change CPU */
  52. preempt_disable();
  53. __this_cpu_write(reporting_keystroke, true);
  54. input_report_key(virt_keyboard, KEY_DOWN, PRESSED);
  55. input_report_key(virt_keyboard, KEY_DOWN, RELEASED);
  56. input_sync(virt_keyboard);
  57. __this_cpu_write(reporting_keystroke, false);
  58. /* reenable preemption */
  59. preempt_enable();
  60. /* reenable keyboard interrupts */
  61. local_irq_restore(flags);
  62. }
  63. /*
  64. * Are we handling a simulated keypress on the current CPU?
  65. * Returns a boolean.
  66. */
  67. bool speakup_fake_key_pressed(void)
  68. {
  69. return this_cpu_read(reporting_keystroke);
  70. }