88 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/* fakekey.c3 * Functions for simulating key presses.4 *5 * Copyright (C) 2010 the Speakup Team6 */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 13#include "speakup.h"14 15#define PRESSED 116#define RELEASED 017 18static DEFINE_PER_CPU(int, reporting_keystroke);19 20static struct input_dev *virt_keyboard;21 22int speakup_add_virtual_keyboard(void)23{24 int err;25 26 virt_keyboard = input_allocate_device();27 28 if (!virt_keyboard)29 return -ENOMEM;30 31 virt_keyboard->name = "Speakup";32 virt_keyboard->id.bustype = BUS_VIRTUAL;33 virt_keyboard->phys = "speakup/input0";34 virt_keyboard->dev.parent = NULL;35 36 __set_bit(EV_KEY, virt_keyboard->evbit);37 __set_bit(KEY_DOWN, virt_keyboard->keybit);38 39 err = input_register_device(virt_keyboard);40 if (err) {41 input_free_device(virt_keyboard);42 virt_keyboard = NULL;43 }44 45 return err;46}47 48void speakup_remove_virtual_keyboard(void)49{50 if (virt_keyboard) {51 input_unregister_device(virt_keyboard);52 virt_keyboard = NULL;53 }54}55 56/*57 * Send a simulated down-arrow to the application.58 */59void speakup_fake_down_arrow(void)60{61 unsigned long flags;62 63 /* disable keyboard interrupts */64 local_irq_save(flags);65 /* don't change CPU */66 preempt_disable();67 68 __this_cpu_write(reporting_keystroke, true);69 input_report_key(virt_keyboard, KEY_DOWN, PRESSED);70 input_report_key(virt_keyboard, KEY_DOWN, RELEASED);71 input_sync(virt_keyboard);72 __this_cpu_write(reporting_keystroke, false);73 74 /* reenable preemption */75 preempt_enable();76 /* reenable keyboard interrupts */77 local_irq_restore(flags);78}79 80/*81 * Are we handling a simulated key press on the current CPU?82 * Returns a boolean.83 */84bool speakup_fake_key_pressed(void)85{86 return this_cpu_read(reporting_keystroke);87}88