diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
commit | 2c3c1048746a4622d8c89a29670120dc8fab93c4 (patch) | |
tree | 848558de17fb3008cdf4d861b01ac7781903ce39 /drivers/accessibility/speakup/fakekey.c | |
parent | Initial commit. (diff) | |
download | linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.tar.xz linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.zip |
Adding upstream version 6.1.76.upstream/6.1.76upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/accessibility/speakup/fakekey.c')
-rw-r--r-- | drivers/accessibility/speakup/fakekey.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/drivers/accessibility/speakup/fakekey.c b/drivers/accessibility/speakup/fakekey.c new file mode 100644 index 000000000..868c47b2a --- /dev/null +++ b/drivers/accessibility/speakup/fakekey.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* fakekey.c + * Functions for simulating key presses. + * + * Copyright (C) 2010 the Speakup Team + */ +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/preempt.h> +#include <linux/percpu.h> +#include <linux/input.h> + +#include "speakup.h" + +#define PRESSED 1 +#define RELEASED 0 + +static DEFINE_PER_CPU(int, reporting_keystroke); + +static struct input_dev *virt_keyboard; + +int speakup_add_virtual_keyboard(void) +{ + int err; + + virt_keyboard = input_allocate_device(); + + if (!virt_keyboard) + return -ENOMEM; + + virt_keyboard->name = "Speakup"; + virt_keyboard->id.bustype = BUS_VIRTUAL; + virt_keyboard->phys = "speakup/input0"; + virt_keyboard->dev.parent = NULL; + + __set_bit(EV_KEY, virt_keyboard->evbit); + __set_bit(KEY_DOWN, virt_keyboard->keybit); + + err = input_register_device(virt_keyboard); + if (err) { + input_free_device(virt_keyboard); + virt_keyboard = NULL; + } + + return err; +} + +void speakup_remove_virtual_keyboard(void) +{ + if (virt_keyboard) { + input_unregister_device(virt_keyboard); + virt_keyboard = NULL; + } +} + +/* + * Send a simulated down-arrow to the application. + */ +void speakup_fake_down_arrow(void) +{ + unsigned long flags; + + /* disable keyboard interrupts */ + local_irq_save(flags); + /* don't change CPU */ + preempt_disable(); + + __this_cpu_write(reporting_keystroke, true); + input_report_key(virt_keyboard, KEY_DOWN, PRESSED); + input_report_key(virt_keyboard, KEY_DOWN, RELEASED); + input_sync(virt_keyboard); + __this_cpu_write(reporting_keystroke, false); + + /* reenable preemption */ + preempt_enable(); + /* reenable keyboard interrupts */ + local_irq_restore(flags); +} + +/* + * Are we handling a simulated key press on the current CPU? + * Returns a boolean. + */ +bool speakup_fake_key_pressed(void) +{ + return this_cpu_read(reporting_keystroke); +} |