免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1559 | 回复: 0
打印 上一主题 下一主题

linux扫描按键驱动 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-02-22 10:50 |只看该作者 |倒序浏览
linux扫描按键驱动creator
               
               
               
                sz111@126.com(原创作品,转载要注明出处)
    之前写过一篇linux按键驱动,采用的是中断的方式,很多时候,我们没有更多的中断,只能采用扫描的方式了。具体思路就不做详细解释了,比较简单,先上code吧。MAKEFILE如下:obj-m := pic_key.oKERNEL_DIR=/usr/local/src/linux-2.6.21/PWD=$(shell pwd)all:        make -C $(KERNEL_DIR) M=$(PWD) modules
code如下:
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include
/*//GPD0--GPD9==> KEY0--KEY9//GPD10:BOOKMARK//GPD11:T_RIGHT//GPD12:T_LEFT//GPD13:T_ENTER//GPD14:OVERTURN//GPD15:BLOWUP//GPB0:MENU//GPG1:CANCEL//GPG2:UP//GPG3:DOWN//GPG4:LEFT//GPB5:RIGHT//GPB6:OK//GPB9:PLAY/PAUSE*/static struct key_info{    unsigned int pin;    int key_code;    char *name;}key_info_tab[] = {    {S3C2410_GPD0,        0x01,        "Key 01"         },    {S3C2410_GPD1,        0x02,        "Key 02"         },    {S3C2410_GPD2,        0x03,        "Key 03"         },    {S3C2410_GPD3,        0x04,        "Key 04"         },    {S3C2410_GPD4,        0x05,        "Key 05"         },    {S3C2410_GPD5,        0x06,        "Key 06"         },    {S3C2410_GPD6,        0x07,        "Key 07"         },    {S3C2410_GPD7,        0x08,        "Key 08"         },    {S3C2410_GPD8,        0x09,        "Key 09"         },    {S3C2410_GPD9,        0x0A,        "Key 0A"         },    {S3C2410_GPD10,        0x0B,        "Key 0B"         },    {S3C2410_GPD11,        0x0C,        "Key 0C"         },    {S3C2410_GPD12,        0x0D,        "Key 0D"         },    {S3C2410_GPD13,        0x0E,        "Key 0E"         },    {S3C2410_GPD14,        0x0F,        "Key 0F"         },    {S3C2410_GPD15,        0x10,        "Key 10"         },    {S3C2410_GPB0,        0x11,        "Key 11"         },    {S3C2410_GPG1,        0x12,        "Key 12"         },    {S3C2410_GPG2,        0x13,        "Key 13"         },    {S3C2410_GPG3,        0x14,        "Key 14"         },    {S3C2410_GPG4,        0x15,        "Key 15"         },    {S3C2410_GPB5,        0x16,        "Key 16"         },    {S3C2410_GPB6,        0x17,        "Key 17"         },    {S3C2410_GPB9,        0x18,        "Key 18"         },};
#define TRUE 1#define FALSE 0
#define DEVICE_NAME "pic_key"#define MAX_KEY_BUF 16 //KEY BUFFER SIZE#define KEY_NUM  24  //key num #define BUF_HEAD (pic_key_dev.buf[pic_key_dev.head])#define BUF_TAIL (pic_key_dev.buf[pic_key_dev.tail])#define INCBUF(x,mod) ((++(x))&((mod)-1))
#define SCANKEY_TIME 20//50ms
#define PIC_KEY_MAJOR 250static dev_t pic_key_major = PIC_KEY_MAJOR;
typedef unsigned int KEY_RET;
struct pic_key_dev_t{    struct cdev cdev;    unsigned int buf[MAX_KEY_BUF];    unsigned int head,tail;    unsigned int key_value;    wait_queue_head_t wq;    };struct pic_key_dev_t pic_key_dev;struct timer_list key_timer;
#define ISKEY_DOWN(key) (s3c2410_gpio_getpin(key_info_tab[key].pin) == 0)static void pic_key_timer(unsigned long data);static int pic_key_open(struct inode *inode, struct file *filp);static int pic_key_release(struct inode *inode, struct file *filp);static ssize_t pic_key_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);static ssize_t pic_key_read(struct file *file,char __user *buffer, size_t count, loff_t *ppos);
static unsigned int get_key_value(void){        int key;        unsigned int ret=0;                for (key=0;key        {                if (ISKEY_DOWN(key))                {                        ret |= (1                }        }                return ret;}
#define FLGKEY_KEY_MASK                 0x00ffffff//24key#define FLGKEY_PRESSED              0x00000000#define FLGKEY_RELEASED             0x01000000#define FLGKEY_CONTINUE             0x02000000#define FLGKEY_HOLD                 0x02000000#define FLGKEY_LONGPRESSED          0x04000000#define FLGKEY_LONGHOLD             0x04000000#define FLGKEY_ACT_MASK             0x0f000000      // Key action mask
#define KEY_HOLD_COUNT          10#define KEY_HOLD_CONTINUE       1//2#define KEY_LONG_HOLD_COUNT     10//9
static unsigned int               uiLastKeyStatus         = 0;static unsigned int               uiLastMDStatus          = 0;static unsigned int               uiStableKeyStatus       = 0;static unsigned int               uiStableMDStatus        = 0;static unsigned int               uiLastStableKeyStatus   = 0;static unsigned int               uiKeyMaskPress          = FLGKEY_KEY_MASK;static unsigned int               uiKeyMaskRelease        = FLGKEY_KEY_MASK;static unsigned int               uiKeyMaskContinue       = FLGKEY_KEY_MASK;static unsigned int               uiKeyMaskLong           = 0;
static unsigned int               uiKeyHoldCount          = 0;static unsigned int               uiKeyLongHoldCount      = 0;static bool                                        bKeyHoldFlag            = FALSE;static unsigned int                 g_uiKeyScanFlags;static void handle_pic_key_event(unsigned int keycode)  {    BUF_HEAD = keycode;    pic_key_dev.head = INCBUF(pic_key_dev.head,MAX_KEY_BUF);    printk(KERN_ERR "key_value:%x\n",keycode);    wake_up_interruptible(&(pic_key_dev.wq));}
static void pic_key_timer(unsigned long data)  {          unsigned int          uiCurKeyStatus, uiTempKeyStatus;    unsigned int          uiKeyChanged;    unsigned int          uiKeyPressed, uiKeyReleased, uiKeyContinue;
    unsigned int           bKeyCode;
    uiCurKeyStatus          =    uiTempKeyStatus         = get_key_value();
    uiCurKeyStatus         &= (uiLastKeyStatus & FLGKEY_KEY_MASK);        uiKeyChanged            = uiCurKeyStatus ^ uiStableKeyStatus;    uiKeyPressed            = uiKeyChanged & uiCurKeyStatus;    uiKeyReleased           = uiKeyChanged & (~uiCurKeyStatus);    uiKeyContinue           = uiCurKeyStatus & uiStableKeyStatus & uiLastStableKeyStatus;    uiLastStableKeyStatus   = uiStableKeyStatus & ~(uiKeyContinue);    uiStableKeyStatus       = uiCurKeyStatus;    uiLastKeyStatus         = uiTempKeyStatus;   
    if (uiKeyPressed)    {        uiTempKeyStatus = uiKeyPressed & uiKeyMaskPress;
        if (uiTempKeyStatus)        {             g_uiKeyScanFlags |= (FLGKEY_PRESSED | uiTempKeyStatus);        }    }    if (uiKeyReleased)    {        uiTempKeyStatus = uiKeyReleased & uiKeyMaskRelease;
        if (uiTempKeyStatus != 0)        {                        g_uiKeyScanFlags |= (FLGKEY_RELEASED | uiKeyReleased);            bKeyHoldFlag = FALSE;            uiKeyHoldCount = 0;            uiKeyLongHoldCount = 0;        }    }
    if (uiKeyContinue)    {        uiTempKeyStatus = uiKeyContinue & uiKeyMaskContinue;
        if (uiTempKeyStatus)        {            uiKeyHoldCount++;            if (bKeyHoldFlag == FALSE && uiKeyHoldCount > KEY_HOLD_COUNT ||                bKeyHoldFlag == TRUE  && uiKeyHoldCount > KEY_HOLD_CONTINUE)            {                uiKeyHoldCount = 0;
                // Play keypad tone                if (bKeyHoldFlag == FALSE)                {                    bKeyHoldFlag = TRUE;                    g_uiKeyScanFlags |= (FLGKEY_HOLD | uiKeyContinue);                }
                // Continue key pressed event               
                if (bKeyHoldFlag)                {                    uiKeyLongHoldCount++;                    if (uiKeyLongHoldCount > KEY_LONG_HOLD_COUNT)                    {                        uiKeyLongHoldCount = 0;                        g_uiKeyScanFlags &= ~FLGKEY_HOLD;                        g_uiKeyScanFlags |= FLGKEY_LONGHOLD;                    }                }            }        }    }        if (g_uiKeyScanFlags)    {            handle_pic_key_event(g_uiKeyScanFlags);      g_uiKeyScanFlags = 0;    }    init_timer(&key_timer);      key_timer.expires = jiffies + SCANKEY_TIME*HZ/1000;  ;      key_timer.function = (void*)pic_key_timer;      add_timer(&key_timer); }
static const struct file_operations pic_key_fops ={    .owner = THIS_MODULE,    .read  = pic_key_read,    .write = pic_key_write,    .open  = pic_key_open,    .release = pic_key_release,};
static void pic_key_setup_cdev(void){    int i;    int err,devno = MKDEV(pic_key_major,0);    cdev_init(&pic_key_dev.cdev,&pic_key_fops);    pic_key_dev.cdev.owner = THIS_MODULE;    pic_key_dev.cdev.ops = &pic_key_fops;    //pic_key_dev.key_status = 0;    err = cdev_add(&pic_key_dev.cdev, devno, 1);    if (err)    {        printk(KERN_NOTICE "Error %d adding pic_key",err);            }           init_waitqueue_head(&(pic_key_dev.wq));           init_timer(&key_timer);      key_timer.expires = jiffies + HZ;      key_timer.function = (void*)pic_key_timer;      add_timer(&key_timer);
}
static int pic_key_open(struct inode *inode, struct file *filp){    filp->private_data = &pic_key_dev;    printk(KERN_NOTICE "pic_key opened\n");    return 0;}
static int pic_key_release(struct inode *inode, struct file *filp){    printk(KERN_NOTICE "pic_key released\n");    return 0;}
static ssize_t pic_key_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos){    return 0;}
static ssize_t pic_key_read(struct file *filp,char __user *buffer, size_t count, loff_t *ppos){    KEY_RET key_ret;    struct pic_key_dev_t *dev;    dev = (struct pic_key_dev_t*)filp->private_data;retry:    if (pic_key_dev.head != pic_key_dev.tail)    {        key_ret = BUF_TAIL;        dev->tail = INCBUF(dev->tail,MAX_KEY_BUF);        copy_to_user(buffer,(char*)&key_ret,sizeof(KEY_RET));        return sizeof(KEY_RET);    }else    {        if (filp->f_flags & O_NONBLOCK)        {            return -EAGAIN;        }        interruptible_sleep_on(&(dev->wq));        if (signal_pending(current))        {            return -ERESTARTSYS;        }        goto retry;    }        return sizeof(KEY_RET);}
static int __init pic_key_init(void){    int result;    int i;        dev_t devno = MKDEV(pic_key_major,0);    if (pic_key_major)    {        result = register_chrdev_region(devno, 1, DEVICE_NAME);    }else    {        result = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);        pic_key_major = MAJOR(devno);    }    if (result     {        return result;    }    pic_key_setup_cdev();        for (i=0;i    {            s3c2410_gpio_cfgpin(key_info_tab.pin,0);//输入            s3c2410_gpio_pullup(key_info_tab.pin,2);//上拉        }    return 0;}static void __exit pic_key_exit(void){    int i;    cdev_del(&pic_key_dev.cdev);    unregister_chrdev_region(MKDEV(pic_key_major,0),1);    del_timer(&key_timer);}
MODULE_AUTHOR("Creator");MODULE_LICENSE("Dual BSD/GPL");
module_init(pic_key_init);module_exit(pic_key_exit);


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/49088/showart_2183701.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP