代码拉取完成,页面将自动刷新
/*
* linux-3.0.8/drivers/input/keyboard/gt2440_key.c
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <mach/regs-gpio.h>
#include "gt2440_key.h"
/***** data structure *****/
/***** help function *****/
static void gt2440_key_report_event(struct gt2440_key_data *data)
{
struct gt2440_key_button *button = data->button;
struct input_dev *input = data->input;
unsigned int type = button->type ?: EV_KEY;
int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low;
if (type == EV_ABS) {
if (state)
input_event(input, type, button->code, button->value);
} else {
input_event(input, type, button->code, !!state);
}
input_sync(input);
}
/***** input dev ops function *****/
static int gt2440_key_open(struct input_dev *input)
{
struct gt2440_key_info *info = input_get_drvdata(input);
return info->enable ? info->enable(input->dev.parent) : 0;
}
static void gt2440_key_close(struct input_dev *input)
{
struct gt2440_key_info *info = input_get_drvdata(input);
if (info->disable)
info->disable(input->dev.parent);
}
/***** timer and work function *****/
static void gt2440_key_timer(unsigned long _data)
{
struct gt2440_key_data *data = (struct gt2440_key_data *)_data;
schedule_work(&data->work);
}
static void gt2440_key_work(struct work_struct *work)
{
struct gt2440_key_data *data =
container_of(work, struct gt2440_key_data, work);
gt2440_key_report_event(data);
}
/***** interrupt function *****/
static irqreturn_t gt2440_key_irq(int irq, void *dev_id)
{
struct gt2440_key_data *data = dev_id;
struct gt2440_key_button *button = data->button;
BUG_ON(irq != gpio_to_irq(button->gpio));
if (data->timer_debounce)
mod_timer(&data->timer,
jiffies + msecs_to_jiffies(data->timer_debounce));
else
schedule_work(&data->work);
return IRQ_HANDLED;
}
/***** gt2440 board probe and remove function *****/
static int gt2440_key_setup(struct gt2440_key_info *info,
struct gt2440_key_data *data,
struct gt2440_key_button *button)
{
const char *desc = button->desc ? button->desc : "gpio_keys";
unsigned long irqflags;
int ret;
setup_timer(&data->timer, gt2440_key_timer, (unsigned long)data);
INIT_WORK(&data->work, gt2440_key_work);
ret = gpio_request(button->gpio, desc);
if (ret < 0) {
dev_err(info->dev, "failed to request GPIO %d, error %d\n", button->gpio, ret);
return ret;
}
data->gpio = button->gpio;
//ret = gpio_direction_input(button->gpio);
ret = s3c_gpio_cfgpin(data->gpio, S3C2410_GPIO_IRQ);
if (ret < 0) {
dev_err(info->dev, "failed to configure GPIO %d, error %d\n",button->gpio, ret);
goto exit_1;
}
if (button->debounce_interval) {
ret = gpio_set_debounce(button->gpio,
button->debounce_interval * 1000);
if (ret < 0)
data->timer_debounce = button->debounce_interval;
}
data->irq = button->irq;
if (data->irq < 0) {
dev_err(info->dev, "failed to get irq GPIO %d, error %d\n",button->gpio, ret);
goto exit_1;
}
irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
if (!button->can_disable)
irqflags |= IRQF_SHARED;
ret = request_any_context_irq(data->irq, gt2440_key_irq, irqflags, desc, data);
if (ret < 0) {
dev_err(info->dev, "failed to request irq %d, error %d\n",data->irq, ret);
goto exit_1;
}
return 0;
exit_1:
gpio_free(button->gpio);
return ret;
}
static int gt2440_key_probe(struct platform_device *pdev)
{
struct gt2440_key_platdata *pdata ;
struct gt2440_key_info *info;
struct input_dev *input;
int i, ret;
int wakeup = 0;
pdata = pdev->dev.platform_data;
if (pdata == NULL) {
dev_err(&pdev->dev,"failed to get platform data for key\n");
return -EINVAL;
}
info = kzalloc(sizeof(struct gt2440_key_info) +
pdata->nbuttons * sizeof(struct gt2440_key_data),
GFP_KERNEL);
if(info == NULL){
dev_err(&pdev->dev,"failed to allocate struct gt2440_key_info{} for key\n");
return -ENOMEM;
}
info->dev = &pdev->dev;
info->nbuttons = pdata->nbuttons;
info->enable = pdata->enable;
info->disable = pdata->disable;
mutex_init(&info->disable_lock);
platform_set_drvdata(pdev, info);
input = input_allocate_device();
if (input == NULL){
dev_err(&pdev->dev,"failed to allocate struct input_dev{} for ts \n");
ret = -ENOMEM;
goto exit_1;
}
info->input = input;
input->name = pdata->name ? : pdev->name;
input->phys = "gt2440-key/input0";
input->id.bustype = BUS_HOST;
input->id.vendor = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0100;
input->open = gt2440_key_open;
input->close = gt2440_key_close;
input->dev.parent = &pdev->dev;
input_set_drvdata(input, info);
if (pdata->rep)
__set_bit(EV_REP, input->evbit);
for (i = 0; i < pdata->nbuttons; i++) {
struct gt2440_key_button *button = &pdata->buttons[i];
struct gt2440_key_data *data = &info->data[i];
unsigned int type = button->type ?: EV_KEY;
data->input = input;
data->button = button;
ret = gt2440_key_setup(info, data, button);
if (ret){
goto exit_2;
}
if (button->wakeup)
wakeup = 1;
input_set_capability(input, type, button->code);
}
/*
ret = sysfs_create_group(&pdev->dev.kobj, >2440_key_attr_group);
if (ret) {
dev_err(&pdev->dev, "failed to export keys/switches, error: %d\n",ret);
goto exit_2;
}
*/
ret = input_register_device(input);
if (ret) {
dev_err(&pdev->dev, "failed to register input device, error: %d\n",ret);
goto exit_3;
}
for (i = 0; i < pdata->nbuttons; i++)
gt2440_key_report_event(&info->data[i]);
input_sync(input);
device_init_wakeup(&pdev->dev, wakeup);
return 0;
exit_3:
//sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
exit_2:
while (--i >= 0) {
free_irq(info->data[i].irq, &info->data[i]);
if (info->data[i].timer_debounce)
del_timer_sync(&info->data[i].timer);
cancel_work_sync(&info->data[i].work);
gpio_free(info->data[i].gpio);
}
input_free_device(input);
info->input = NULL;
exit_1:
kfree(info);
platform_set_drvdata(pdev, NULL);
return ret;
}
static int gt2440_key_remove(struct platform_device *pdev)
{
struct gt2440_key_info *info = platform_get_drvdata(pdev);
int i;
if(info == NULL)
return 0;
if(info->input != NULL){
input_unregister_device(info->input);
info->input = NULL;
}
device_init_wakeup(&pdev->dev, 0);
//sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
for (i = 0; i < info->nbuttons; i++) {
free_irq(info->data[i].irq, &info->data[i]);
if (info->data[i].timer_debounce)
del_timer_sync(&info->data[i].timer);
cancel_work_sync(&info->data[i].work);
gpio_free(info->data[i].gpio);
}
kfree(info);
platform_set_drvdata(pdev, NULL);
return 0;
}
/***** gt2440 board probe and remove function *****/
static int gt2440_board_key_probe(struct platform_device *pdev)
{ dprintk("gt2440_board_key_probe(id=%d)\n", pdev->id);
return gt2440_key_probe(pdev);
}
static int gt2440_board_key_remove(struct platform_device *pdev)
{ dprintk("gt2440_board_key_remove(id=%d)\n", pdev->id);
return gt2440_key_remove(pdev);
}
static struct platform_driver gt2440_key_platform_driver = {
.probe = gt2440_board_key_probe,
.remove = gt2440_board_key_remove,
.driver = {
.name = PLAT_DEVICE_NAME, /* "gt2440-rtc" */
.owner = THIS_MODULE,
},
};
/***** init and exit ****/
static int __init gt2440_key_init(void)
{ dprintk("gt2440_key_init()\n");
return platform_driver_register(>2440_key_platform_driver);
}
static void __exit gt2440_key_exit(void)
{ dprintk("gt2440_key_exit()\n");
platform_driver_unregister(>2440_key_platform_driver);
}
module_init(gt2440_key_init);
module_exit(gt2440_key_exit);
MODULE_DESCRIPTION("GT2440 Key board Device Driver");
MODULE_AUTHOR("Liguang13579<1659890447@qq.com>");
MODULE_LICENSE("GPL v2");
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。