android2.3 旋转按钮驱动

 旋转按钮如图所示:

实现功能为上,下和确定

驱动源码如下:

/*
* 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("[email protected] ");
MODULE_DESCRIPTION("gzsd pulley key driver");
MODULE_LICENSE("GPL");
路径为:drivers/input/keyboard/gzsd_pulley.c
内核版本:2.6.35.7

源码下载地址:点击打开链接


你可能感兴趣的:(android2.3 旋转按钮驱动)