• linux下按键驱动程序


    说明:由于调试的时候minicom出了问题,传送大一点的文件就会失败,所以下面的程序可能会有点问题,请注意

    1.button.c

    #include<linux/module.h>
    #include<linux/kernel.h>
    #include<linux/moduleparam.h>
    #include<linux/init.h>
    #include<linux/kdev_t.h>
    #include<linux/fs.h>
    #include<linux/cdev.h>
    #include<linux/device.h>
    //#include<asm/arch/regs-gpio.h>
    #include <mach/regs-gpio.h>
    //#include<asm/hardware.h>
    #include <mach/hardware.h>
    #include<asm/uaccess.h>
    #include<linux/poll.h>
    #include<linux/interrupt.h>
    #include<asm/irq.h>
    #include<asm/io.h>
    #include<linux/delay.h>

    #define DEV_NAME "linux_buttons"

    #define led_on_1 ~(1<<5)
    #define led_on_2 ~(1<<6)
    #define led_on_3 ~(1<<7)
    #define led_on_4 ~(1<<8)

    static int buttons_major, buttons_minor = 0;
    static struct cdev buttons_cdev;
    static struct class *buttons_class;
    static dev_t dev;

    struct button_irq_desc
    {
    int irq;
    int pin;
    int pin_setting;
    int number;
    char *name;
    };

    static struct button_irq_desc button_irqs[4]=
    {
    {IRQ_EINT1, S3C2410_GPF1, S3C2410_GPF1_EINT1, 0, "KEY1"},
    {IRQ_EINT4, S3C2410_GPF4, S3C2410_GPF4_EINT4, 1, "KEY2"},
    {IRQ_EINT2, S3C2410_GPF2, S3C2410_GPF2_EINT2, 2, "KEY3"},
    {IRQ_EINT0, S3C2410_GPF0, S3C2410_GPF0_EINT0, 3, "KEY4"}
    };

    static volatile int key_values[] = {0, 0, 0, 0};
    static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
    static volatile int ev_press = 0;

    static irqreturn_t buttons_interrupt_1(int irq, void *dev_id);
    static irqreturn_t buttons_interrupt_4(int irq, void *dev_id);
    static irqreturn_t buttons_interrupt_2(int irq, void *dev_id);
    static irqreturn_t buttons_interrupt_0(int irq, void *dev_id);

    void *sequence_int[]={
    buttons_interrupt_1,
    buttons_interrupt_4,
    buttons_interrupt_2,
    buttons_interrupt_0
    };

    static irqreturn_t buttons_interrupt_1(int irq, void *dev_id)
    {
    if (s3c2410_gpio_getpin(S3C2410_GPF1))
    {
    printk("key_1 down and the pin is high ");
    mdelay(20);
    if (s3c2410_gpio_getpin(S3C2410_GPF1))
    printk("Debounce ");
    writel(led_on_1,S3C2410_GPBDAT);
    ev_press = 1;
    key_values[0]++;
    }
    }

    static irqreturn_t buttons_interrupt_4(int irq, void *dev_id)
    {
    if (s3c2410_gpio_getpin(S3C2410_GPF4))
    {
    printk("key_2 down and the pin is high ");
    mdelay(20);
    if (s3c2410_gpio_getpin(S3C2410_GPF4))
    printk("Debounce ");
    writel(led_on_2,S3C2410_GPBDAT);
    ev_press = 1;
    key_values[1]++;
    }
    }

    static irqreturn_t buttons_interrupt_2(int irq, void *dev_id)
    {
    if (s3c2410_gpio_getpin(S3C2410_GPF2))
    {
    printk("key_3 down and the pin is high ");
    mdelay(20);
    if (s3c2410_gpio_getpin(S3C2410_GPF2))
    printk("Debounce ");
    writel(led_on_3,S3C2410_GPBDAT);
    ev_press = 1;
    key_values[2]++;
    }
    }

    static irqreturn_t buttons_interrupt_0(int irq, void *dev_id)
    {
    if (s3c2410_gpio_getpin(S3C2410_GPF0))
    {
    printk("key_4 down and the pin is high ");
    mdelay(20);
    if (s3c2410_gpio_getpin(S3C2410_GPF0))
    printk("Debounce ");
    writel(led_on_4,S3C2410_GPBDAT);
    ev_press = 1;
    key_values[3]++;
    }
    }

    static int buttons_open(struct inode *inode, struct file *filp)
    {
    int i,err;
    unsigned long irq_type;

    writel((1<<10)| (1<<12) | (1<<14) | (1<<16),S3C2410_GPBCON);

    irq_type = ioread32(S3C2410_EXTINT0);
    irq_type &= ~((3<<1) | (3<<5) | (3<<9) | (3<<17));
    irq_type |= ((1<<1) | (1<<5) | (1<<9) | (1<<17));
    iowrite32(irq_type, S3C2410_EXTINT0);

    for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
    {
    s3c2410_gpio_cfgpin(button_irqs[i].pin, button_irqs[i].pin_setting);
    err = request_irq(button_irqs[i].irq, sequence_int[i], NULL, button_irqs[i].name, (void *)&button_irqs[i]);
    if(err)
    break;
    }
    if (err)
    {
    i--;
    for(; i >= 0; i--)
    {
    disable_irq(button_irqs[i].irq);
    free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
    }
    return -EBUSY;
    }
    return 0;
    }

    static int buttons_close(struct inode *inode, struct file* file)
    {
    int i;
    for (i = 0; i< 4; i++)
    {
    disable_irq(button_irqs[i].irq);
    free_irq(button_irqs[i].irq, (void*)&button_irqs[i]);
    }
    return 0;
    }

    static int buttons_read(struct file* filp, char __user *buff, size_t count,loff_t *offp)
    {
    unsigned long err;
    if (!ev_press)
    {
    if (filp->f_flags & O_NONBLOCK)
    {
    printk("process is noblock");
    return -EAGAIN;
    }
    else
    {
    printk("buttons_read read time");
    wait_event_interruptible(button_waitq, ev_press);
    }
    }

    ev_press = 0;
    err = copy_to_user(buff, key_values, count);
    memset(key_values, 0, sizeof(key_values));
    return err? -EFAULT : 4;
    }

    static unsigned int buttons_poll(struct file *filp, poll_table * wait)
    {
    unsigned int mask = 0;
    poll_wait(filp, &button_waitq, wait);
    if(ev_press)
    mask |= POLLIN | POLLRDNORM;
    return mask;
    }

    static struct file_operations buttons_fops =
    {
    .owner = THIS_MODULE,
    .open = buttons_open,
    .release = buttons_close,
    .read = buttons_read,
    .poll = buttons_poll
    };

    static int __init buttons_init(void)
    {
    int result;

    if (buttons_major) //若是已决定好设备号,则静态分配
    {
    dev = MKDEV(buttons_major, buttons_minor);
    result = register_chrdev_region(dev, 1, DEV_NAME);
    }
    else //动态分配设备号
    {
    result = alloc_chrdev_region(&dev, buttons_minor, 1, DEV_NAME);
    buttons_major = MAJOR(dev);
    }

    if (result < 0)
    {
    printk(KERN_WARNING "buttons:can't get major %d ", buttons_major);
    return result;
    }
    else
    {
    printk(KERN_WARNING "registered ok buttons_major = %d ", buttons_major);
    }

    cdev_init(&buttons_cdev, &buttons_fops);//初始化cdev结构
    buttons_cdev.owner = THIS_MODULE; //设置cdev.owner成员为HHIS_MODULE
    //buttons_cdev.ops = &buttons_fops; //设置cdev.ops成员为buttons_fops
    result = cdev_add(&buttons_cdev, dev, 1);//设置cdev.dev以及.count成员

    if (result < 0)
    {
    printk(KERN_WARNING "cdev_add failed! ");
    return result;
    }
    else
    {
    printk(KERN_WARNING "");
    }

    buttons_class = class_create(THIS_MODULE, DEV_NAME);//创建class结构

    if (IS_ERR(buttons_class))
    {
    printk(KERN_ALERT "err:fail in buttons_class! ");
    return -1;
    }
    else
    {
    printk(KERN_WARNING" SUCCESS IN buttons_class! ");
    }

    /*创建相应的设备节点*/
    device_create(buttons_class, NULL, MKDEV(buttons_major, 0), NULL, DEV_NAME);

    printk(KERN_WARNING"SUCCESS IN buttons_CLASS! ");

    return 0;
    }

    static void __exit buttons_exit(void)
    {
    int devno = MKDEV(buttons_major, buttons_minor);
    writel(0xffff, S3C2410_GPBDAT); //关闭LED
    unregister_chrdev_region(devno, 1); //释放设备号
    cdev_del(&buttons_cdev); //删除cdev结构
    device_destroy(buttons_class, devno);//删除设备节点
    class_destroy(buttons_class); ///删除class结构
    printk(KERN_WARNING"buttons module exit! ");
    }

    module_init(buttons_init);
    module_exit(buttons_exit);
    MODULE_LICENSE("Dual BSD/GPL");
    MODULE_AUTHOR("xiaoheng");

    2.buttontest.c

    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<sys/ioctl.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    #include<sys/time.h>
    #include<errno.h>

    int main(void)
    {
    int i;
    int buttons_fd;
    int key_value[4];

    buttons_fd = open("/dev/linux_buttons", 0);

    if (buttons_fd < 0)
    {
    perror("open buttons fail");
    exit(1);
    }

    for (;;)
    {
    printf("test file read time ");
    read(buttons_fd, key_value, sizeof(key_value));

    for (i = 0; i < 4; i++)
    {
    if (key_value[i] != 0)
    printf("K%d pressed, key value = 0x%d ",i++, key_value[i]);
    }
    }
    close(buttons_fd);
    return 0;
    }

    3.Makefile

    obj-m:=button.o

    KDIR:=/home/xiaoheng/Desktop/2.6.30.4/opt/EmbedSky/linux-2.6.30.4
    all:
    make -C $(KDIR) M=$(shell pwd) modules
    clean:
    make -C $(KDIR) M=$(shell pwd) clean

  • 相关阅读:
    软件乘法实现
    矩阵连乘求解优化
    { 控件动态创建的堆与栈 }
    digital clock based C
    C++初探
    C语言语法教程-链表
    EF Core 实现读写分离的最佳方案
    Windows Terminal 安装及美化
    .netcore centos环境搭建实战
    AutoMapper.RegExtension 介绍
  • 原文地址:https://www.cnblogs.com/xiaoheng008/p/3734408.html
Copyright © 2020-2023  润新知