旋转按钮如图所示:
实现功能为上,下和确定
驱动源码如下:
/*
* Driver for keys on GPIO lines capable of generating interrupts.
*
* Copyright 2013 Gzsd Tech
*
* 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.
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/serial_core.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <plat/map-base.h>
#include <plat/gpio-cfg.h>
#include <mach/regs-gpio.h>
#include <mach/regs-irq.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/gzsd_pulley.h>
#define LKEY S5PV210_GPH0(4)
#define RKEY S5PV210_GPH0(3)
#define MKEY S5PV210_GPH0(2)
#define POWER IRQ_EINT(1)
#define PWIRQSTA S5PV210_GPH0(1)
#define MAX_BUTTON_CNT (4)
static int s3c_Keycode[MAX_BUTTON_CNT] = {KEY_UP, KEY_DOWN, KEY_ENTER, KEY_POWER};
static struct input_dev *input;
static int flag_ll = 0;
static int flag_lr = 0;
static int flag_rl = 0;
static int flag_rr = 0;
static irqreturn_t pulley_lkey(int irq, void *dev_id)
{
disable_irq_nosync(irq);
flag_ll = gpio_get_value(LKEY);
flag_lr = gpio_get_value(RKEY);
#if 0
printk("left flag_ll is %d flag_lr is %d\n",flag_ll,flag_lr);
input_report_key(input, s3c_Keycode[1], 0);
if((flag_ll == flag_lr) && (flag_rl != flag_rr)) {
input_report_key(input, s3c_Keycode[0], 1);
printk("left around\n");
}
#else
if((flag_ll == flag_lr) && (flag_rl != flag_rr)) {
input_report_key(input, s3c_Keycode[0], 1);
mdelay(50);
input_report_key(input, s3c_Keycode[0], 0);
//printk("left around\n");
}
#endif
//mdelay(50);
enable_irq(irq);
return IRQ_HANDLED;
}
static irqreturn_t pulley_rkey(int irq, void *dev_id)
{
disable_irq_nosync(irq);
flag_rr = gpio_get_value(RKEY);
flag_rl = gpio_get_value(LKEY);
//printk("right flag_rl is %d flag_rr is %d\n",flag_rl,flag_rr);
#if 0
input_report_key(input, s3c_Keycode[0], 0);
if((flag_rl == flag_rr) && (flag_ll != flag_lr)) {
input_report_key(input, s3c_Keycode[1], 1);
printk("right around\n");
}
#else
if((flag_rl == flag_rr) && (flag_ll != flag_lr)) {
input_report_key(input, s3c_Keycode[1], 1);
mdelay(50);
input_report_key(input, s3c_Keycode[1], 0);
//printk("right around\n");
}
#endif
//mdelay(50);
enable_irq(irq);
return IRQ_HANDLED;
}
static irqreturn_t pulley_mkey(int irq, void *dev_id)
{
int ret;
disable_irq_nosync(irq);
ret = gpio_get_value(MKEY);
if(ret) {
input_report_key(input, s3c_Keycode[2], 0);
}
else {
input_report_key(input, s3c_Keycode[2], 1);
}
enable_irq(irq);
return IRQ_HANDLED;
}
static irqreturn_t syspow_isr(int irq, void *dev_id)
{
int ret;
disable_irq_nosync(irq);
ret = gpio_get_value(PWIRQSTA);
//printk("%s : line is %d\n",__func__,__LINE__);
if(ret)
input_report_key(input, s3c_Keycode[3], 0);
else
input_report_key(input, s3c_Keycode[3], 1);
mdelay(100);
enable_irq(irq);
return IRQ_HANDLED;
}
static int __devinit gzsd_pulley_probe(struct platform_device *pdev)
{
struct gzsd_pulley_platform_data *pdata = pdev->dev.platform_data;
struct device *dev = &pdev->dev;
int err,i;
input = input_allocate_device();
if (!input) {
dev_err(dev, "failed to allocate state\n");
input_free_device(input);
return -1;
}
set_bit(EV_KEY, input->evbit);
for(i = 0; i < MAX_BUTTON_CNT; i++)
set_bit(s3c_Keycode[i], input->keybit);
input->name = "gzsd-pulley";
input->phys = "gzsd-pulley/input0";
input->id.bustype = BUS_HOST;
input->id.vendor = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0100;
input->keycode = s3c_Keycode;
err = input_register_device(input);
if (err) {
dev_err(dev, "Unable to register input device, error: %d\n",
err);
input_free_device(input);
}
if (request_irq(pdata->lkey, pulley_lkey, IRQ_TYPE_EDGE_BOTH,"gzsd-pulley", pdata)) {
dev_err(dev, "Unable to request pulley lkey.\n");
input_unregister_device(input);
input = NULL;
}
if (request_irq(pdata->rkey, pulley_rkey, IRQ_TYPE_EDGE_BOTH,"gzsd-pulley", pdata)) {
dev_err(dev, "Unable to request pulley rkey.\n");
input_unregister_device(input);
input = NULL;
}
if (request_irq(pdata->mkey, pulley_mkey, IRQ_TYPE_EDGE_BOTH,"gzsd-pulley", pdata)) {
dev_err(dev, "Unable to request pulley mkey.\n");
input_unregister_device(input);
input = NULL;
}
if (request_irq(pdata->power, syspow_isr, IRQ_TYPE_EDGE_BOTH,"gzsd-pulley", pdata)) {
dev_err(dev, "Unable to request power key.\n");
input_unregister_device(input);
input = NULL;
}
return 0;
}
static int __devexit gzsd_pulley_remove(struct platform_device *pdev)
{
struct gzsd_pulley_platform_data *pdata = pdev->dev.platform_data;
free_irq(pdata->lkey, pdata);
free_irq(pdata->rkey, pdata);
free_irq(pdata->mkey, pdata);
free_irq(pdata->power, pdata);
input_unregister_device(input);
return 0;
}
static struct platform_driver gzsd_pulley_device_driver = {
.probe = gzsd_pulley_probe,
.remove = __devexit_p(gzsd_pulley_remove),
.driver = {
.name = "gzsd-pulley",
.owner = THIS_MODULE,
}
};
static int __init gzsd_pulley_init(void)
{
return platform_driver_register(&gzsd_pulley_device_driver);
}
static void __exit gzsd_pulley_exit(void)
{
platform_driver_unregister(&gzsd_pulley_device_driver);
}
module_init(gzsd_pulley_init);
module_exit(gzsd_pulley_exit);
MODULE_AUTHOR("gzsdit@gmail.com ");
MODULE_DESCRIPTION("gzsd pulley key driver");
MODULE_LICENSE("GPL");
路径为:drivers/input/keyboard/gzsd_pulley.c
内核版本:2.6.35.7
源码下载地址:点击打开链接