blob: d0fb87d38221eda37b3e5add852d5cc73afed484 [file] [log] [blame]
/*
* Copyright 2012 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation (the "GPL").
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* A copy of the GPL is available at
* http://www.broadcom.com/licenses/GPLv2.php, or by writing to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/debugfs.h>
#include <linux/input.h>
#if defined(CONFIG_RTC_DRV_KONA)
#include <linux/alarmtimer.h>
#endif
struct virtual_key {
unsigned key;
unsigned delay;
struct input_dev *input;
struct dentry *root;
#if defined(CONFIG_RTC_DRV_KONA)
struct alarm alarm;
#endif
};
static struct virtual_key virtual_key;
#if defined(CONFIG_RTC_DRV_KONA)
static enum alarmtimer_restart
virtual_key_alarm_callback(struct alarm *alarm, ktime_t now)
{
printk(KERN_INFO "vkey_alarm_cb key: %d, delay: %d\n",
virtual_key.key, virtual_key.delay);
if (unlikely(virtual_key.key) && likely(virtual_key.input)) {
ktime_t interval = ktime_set(virtual_key.delay, 0);
ktime_t next = ktime_add(ktime_get_real(), interval);
alarm_start(&virtual_key.alarm, next);
input_report_key(virtual_key.input, virtual_key.key, 1);
input_sync(virtual_key.input);
input_report_key(virtual_key.input, virtual_key.key, 0);
input_sync(virtual_key.input);
}
return ALARMTIMER_NORESTART;
}
#endif
static int key_get(void *data, u64 *val)
{
*val = virtual_key.key;
return 0;
}
static int key_set(void *data, u64 val)
{
if (!virtual_key.input)
return 0;
virtual_key.key = val;
__set_bit(virtual_key.key & KEY_MAX,
virtual_key.input->keybit);
printk(KERN_INFO "virtual_key: %d\n", virtual_key.key);
printk(KERN_INFO "delay: %d\n", virtual_key.delay);
#if defined(CONFIG_RTC_DRV_KONA)
if (virtual_key.key) {
ktime_t interval = ktime_set(virtual_key.delay, 0);
ktime_t next = ktime_add(ktime_get_real(), interval);
alarm_start(&virtual_key.alarm, next);
}
#endif
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(dbg_key, key_get, key_set, "%llu\n");
static int __init virtual_key_init(void)
{
int ret = 0;
virtual_key.key = 0;
virtual_key.input = input_allocate_device();
if (!virtual_key.input)
return -ENOMEM;
virtual_key.input->name = "virtual_key";
virtual_key.input->phys = "virtual_key/input0";
set_bit(EV_KEY, virtual_key.input->evbit);
__set_bit(KEY_POWER & KEY_MAX,
virtual_key.input->keybit);
ret = input_register_device(virtual_key.input);
if (ret) {
input_free_device(virtual_key.input);
return ret;
}
virtual_key.root = debugfs_create_dir("virtual_key", 0);
if (virtual_key.root) {
debugfs_create_file("key", 0644,
virtual_key.root, NULL, &dbg_key);
debugfs_create_u32("delay", 0644,
virtual_key.root, &virtual_key.delay);
}
#if defined(CONFIG_RTC_DRV_KONA)
alarm_init(&virtual_key.alarm, ALARM_REALTIME,
virtual_key_alarm_callback);
#endif
return 0;
}
module_init(virtual_key_init);
MODULE_AUTHOR("Broadcom");
MODULE_DESCRIPTION("Broadcom Simulator Keypad Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION("1.0");