linux/drivers/staging/speakup/fakekey.c
<<
>>
Prefs
   1/* fakekey.c
   2 * Functions for simulating keypresses.
   3 *
   4 * Copyright (C) 2010 the Speakup Team
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 */
  16#include <linux/types.h>
  17#include <linux/slab.h>
  18#include <linux/preempt.h>
  19#include <linux/percpu.h>
  20#include <linux/input.h>
  21
  22#include "speakup.h"
  23
  24#define PRESSED 1
  25#define RELEASED 0
  26
  27static DEFINE_PER_CPU(int, reporting_keystroke);
  28
  29static struct input_dev *virt_keyboard;
  30
  31int speakup_add_virtual_keyboard(void)
  32{
  33        int err;
  34
  35        virt_keyboard = input_allocate_device();
  36
  37        if (!virt_keyboard)
  38                return -ENOMEM;
  39
  40        virt_keyboard->name = "Speakup";
  41        virt_keyboard->id.bustype = BUS_VIRTUAL;
  42        virt_keyboard->phys = "speakup/input0";
  43        virt_keyboard->dev.parent = NULL;
  44
  45        __set_bit(EV_KEY, virt_keyboard->evbit);
  46        __set_bit(KEY_DOWN, virt_keyboard->keybit);
  47
  48        err = input_register_device(virt_keyboard);
  49        if (err) {
  50                input_free_device(virt_keyboard);
  51                virt_keyboard = NULL;
  52        }
  53
  54        return err;
  55}
  56
  57void speakup_remove_virtual_keyboard(void)
  58{
  59        if (virt_keyboard != NULL) {
  60                input_unregister_device(virt_keyboard);
  61                virt_keyboard = NULL;
  62        }
  63}
  64
  65/*
  66         * Send a simulated down-arrow to the application.
  67         */
  68void speakup_fake_down_arrow(void)
  69{
  70        unsigned long flags;
  71
  72        /* disable keyboard interrupts */
  73        local_irq_save(flags);
  74        /* don't change CPU */
  75        preempt_disable();
  76
  77        __this_cpu_write(reporting_keystroke, true);
  78        input_report_key(virt_keyboard, KEY_DOWN, PRESSED);
  79        input_report_key(virt_keyboard, KEY_DOWN, RELEASED);
  80        input_sync(virt_keyboard);
  81        __this_cpu_write(reporting_keystroke, false);
  82
  83        /* reenable preemption */
  84        preempt_enable();
  85        /* reenable keyboard interrupts */
  86        local_irq_restore(flags);
  87}
  88
  89/*
  90         * Are we handling a simulated keypress on the current CPU?
  91         * Returns a boolean.
  92         */
  93bool speakup_fake_key_pressed(void)
  94{
  95        return this_cpu_read(reporting_keystroke);
  96}
  97