Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /* fakekey.c
0003  * Functions for simulating key presses.
0004  *
0005  * Copyright (C) 2010 the Speakup Team
0006  */
0007 #include <linux/types.h>
0008 #include <linux/slab.h>
0009 #include <linux/preempt.h>
0010 #include <linux/percpu.h>
0011 #include <linux/input.h>
0012 
0013 #include "speakup.h"
0014 
0015 #define PRESSED 1
0016 #define RELEASED 0
0017 
0018 static DEFINE_PER_CPU(int, reporting_keystroke);
0019 
0020 static struct input_dev *virt_keyboard;
0021 
0022 int speakup_add_virtual_keyboard(void)
0023 {
0024     int err;
0025 
0026     virt_keyboard = input_allocate_device();
0027 
0028     if (!virt_keyboard)
0029         return -ENOMEM;
0030 
0031     virt_keyboard->name = "Speakup";
0032     virt_keyboard->id.bustype = BUS_VIRTUAL;
0033     virt_keyboard->phys = "speakup/input0";
0034     virt_keyboard->dev.parent = NULL;
0035 
0036     __set_bit(EV_KEY, virt_keyboard->evbit);
0037     __set_bit(KEY_DOWN, virt_keyboard->keybit);
0038 
0039     err = input_register_device(virt_keyboard);
0040     if (err) {
0041         input_free_device(virt_keyboard);
0042         virt_keyboard = NULL;
0043     }
0044 
0045     return err;
0046 }
0047 
0048 void speakup_remove_virtual_keyboard(void)
0049 {
0050     if (virt_keyboard) {
0051         input_unregister_device(virt_keyboard);
0052         virt_keyboard = NULL;
0053     }
0054 }
0055 
0056 /*
0057  * Send a simulated down-arrow to the application.
0058  */
0059 void speakup_fake_down_arrow(void)
0060 {
0061     unsigned long flags;
0062 
0063     /* disable keyboard interrupts */
0064     local_irq_save(flags);
0065     /* don't change CPU */
0066     preempt_disable();
0067 
0068     __this_cpu_write(reporting_keystroke, true);
0069     input_report_key(virt_keyboard, KEY_DOWN, PRESSED);
0070     input_report_key(virt_keyboard, KEY_DOWN, RELEASED);
0071     input_sync(virt_keyboard);
0072     __this_cpu_write(reporting_keystroke, false);
0073 
0074     /* reenable preemption */
0075     preempt_enable();
0076     /* reenable keyboard interrupts */
0077     local_irq_restore(flags);
0078 }
0079 
0080 /*
0081  * Are we handling a simulated key press on the current CPU?
0082  * Returns a boolean.
0083  */
0084 bool speakup_fake_key_pressed(void)
0085 {
0086     return this_cpu_read(reporting_keystroke);
0087 }