Path: blob/master/drivers/accessibility/speakup/fakekey.c
26282 views
// SPDX-License-Identifier: GPL-2.0+1/* fakekey.c2* Functions for simulating key presses.3*4* Copyright (C) 2010 the Speakup Team5*/6#include <linux/types.h>7#include <linux/slab.h>8#include <linux/preempt.h>9#include <linux/percpu.h>10#include <linux/input.h>1112#include "speakup.h"1314#define PRESSED 115#define RELEASED 01617static DEFINE_PER_CPU(int, reporting_keystroke);1819static struct input_dev *virt_keyboard;2021int speakup_add_virtual_keyboard(void)22{23int err;2425virt_keyboard = input_allocate_device();2627if (!virt_keyboard)28return -ENOMEM;2930virt_keyboard->name = "Speakup";31virt_keyboard->id.bustype = BUS_VIRTUAL;32virt_keyboard->phys = "speakup/input0";33virt_keyboard->dev.parent = NULL;3435__set_bit(EV_KEY, virt_keyboard->evbit);36__set_bit(KEY_DOWN, virt_keyboard->keybit);3738err = input_register_device(virt_keyboard);39if (err) {40input_free_device(virt_keyboard);41virt_keyboard = NULL;42}4344return err;45}4647void speakup_remove_virtual_keyboard(void)48{49if (virt_keyboard) {50input_unregister_device(virt_keyboard);51virt_keyboard = NULL;52}53}5455/*56* Send a simulated down-arrow to the application.57*/58void speakup_fake_down_arrow(void)59{60unsigned long flags;6162/* disable keyboard interrupts */63local_irq_save(flags);64/* don't change CPU */65preempt_disable();6667__this_cpu_write(reporting_keystroke, true);68input_report_key(virt_keyboard, KEY_DOWN, PRESSED);69input_report_key(virt_keyboard, KEY_DOWN, RELEASED);70input_sync(virt_keyboard);71__this_cpu_write(reporting_keystroke, false);7273/* reenable preemption */74preempt_enable();75/* reenable keyboard interrupts */76local_irq_restore(flags);77}7879/*80* Are we handling a simulated key press on the current CPU?81* Returns a boolean.82*/83bool speakup_fake_key_pressed(void)84{85return this_cpu_read(reporting_keystroke);86}878889