ok6410增加工作队列的platform按键驱动程序

来源:互联网 发布:美发软件那个好 编辑:程序博客网 时间:2024/06/06 02:54

plat_btn_device.c

#include <linux/module.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/platform_device.h>#include <linux/interrupt.h>#include <linux/device.h>#include <linux/io.h>#define DEVICE_NAME "ok6410_plat_btn"/*平台资源的定义,按键中断*/static struct resource s3c_buttons_resource[] = {[0]={.start = IRQ_EINT(0),.end   = IRQ_EINT(0),.flags = IORESOURCE_IRQ,},[1]={.start = IRQ_EINT(1),.end   = IRQ_EINT(1),.flags = IORESOURCE_IRQ,},[2]={.start = IRQ_EINT(2),.end   = IRQ_EINT(2),.flags = IORESOURCE_IRQ,},[3]={.start = IRQ_EINT(3),.end   = IRQ_EINT(3),.flags = IORESOURCE_IRQ,},[4]={.start = IRQ_EINT(4),.end   = IRQ_EINT(4),.flags = IORESOURCE_IRQ,},[5]={.start = IRQ_EINT(5),.end   = IRQ_EINT(5),.flags = IORESOURCE_IRQ,}};static struct platform_device *s3c_buttons;static int __init platform_init(void){    s3c_buttons = platform_device_alloc(DEVICE_NAME,-1);//为平台设备s3c_buttons添加平台资源    platform_device_add_resources(s3c_buttons,&s3c_buttons_resource,6);    /*平台设备的注册*/    platform_device_add(s3c_buttons);}static void __exit platform_exit(void){    platform_device_unregister(s3c_buttons);}module_init(platform_init);module_exit(platform_exit);MODULE_AUTHOR("Sola");MODULE_LICENSE("GPL");MODULE_ALIAS("platform:mini2440buttons");


 

 

plat_btn_driver.c

#include <linux/module.h>#include <linux/types.h>#include <linux/miscdevice.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/platform_device.h>#include <linux/interrupt.h>#include <linux/clk.h>#include <linux/uaccess.h>#include <linux/io.h>#include <mach/map.h>#include <linux/poll.h>#include <linux/irq.h>#include <asm/unistd.h>#include <linux/device.h>#define DRIVER_NAME "ok6410_plat_btn"//定义并初始化等待队列头static DECLARE_WAIT_QUEUE_HEAD(button_waitq);static volatile int ev_press = 0;static int key_value;static struct device     *buttons_dev;/* platform device attached to */static struct resource   *buttons_irq;int temp_irq;//保存当前按键中断的中断号struct delayed_work dwork;//用于按键中断底半部的延迟工作static int button_irqs[6];//中断号 /*按键中断处理函数*/static irqreturn_t buttons_interrupt(int irq, void *dev_id){temp_irq = irq;//保存当前中断的中断号schedule_delayed_work(&dwork,HZ/50);//延迟20ms,用作按键消斗,然后会自动调用延迟回调函数    return IRQ_RETVAL(IRQ_HANDLED);}/*延迟工作的回调函数*/static void buttons_work_func(struct work_struct *w){int i;for(i=0; i<6; i++){if(temp_irq == button_irqs[i]){//printk("==>interrput number:%d\n",irq);  key_value = i;//获得键值ev_press =1;//键是否被按下//唤醒等待队列wake_up_interruptible(&button_waitq);}}}static int s3c6410_buttons_open(struct inode *inode, struct file *file){int i;int err = 0;/*注册中断*/for(i=0; i<6; i++){if (button_irqs[i] < 0) continue;    /*中断触发方式:下降沿触发,中断接口函数*/        err = request_irq(button_irqs[i],buttons_interrupt,IRQF_TRIGGER_FALLING,NULL,NULL);if(err)  break;}if (err) {i--;for (; i >= 0; i--) {if (button_irqs[i] < 0) {continue;}disable_irq(button_irqs[i]);free_irq(button_irqs[i], NULL);}return -EBUSY;}    ev_press = 0;       return 0;}static int s3c6410_buttons_close(struct inode *inode, struct file *file){    int i;        for (i=0; i<6; i++) {if (button_irqs[i] < 0) {continue;}free_irq(button_irqs[i],NULL);    }    return 0;}static int s3c6410_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)//如果是非阻塞模式,就直接返回return -EAGAIN;else//阻塞,直到按键按下wait_event_interruptible(button_waitq, ev_press);    }        ev_press = 0;//将键值送回到用户空间    err = copy_to_user(buff, &key_value, sizeof(key_value));    return sizeof(key_value);}static unsigned int s3c6410_buttons_poll( struct file *file, struct poll_table_struct *wait){    unsigned int mask = 0;    poll_wait(file, &button_waitq, wait);//添加等待队列头    if (ev_press){        mask |= POLLIN | POLLRDNORM;}//返回掩码    return mask;}static struct file_operations ok6410_buttons_fops = {    .owner   =   THIS_MODULE,    .open    =   s3c6410_buttons_open,.release =   s3c6410_buttons_close,    .read    =   s3c6410_buttons_read,.poll    =   s3c6410_buttons_poll,};//声明一个混杂设备,设备名称为"buttons"static struct miscdevice ok6410_miscdev = {    .minor = MISC_DYNAMIC_MINOR,    .name ="buttons",    .fops = &ok6410_buttons_fops,//操作集};/* device interface ,当发现匹配设备时会调用此函数*/static int ok6410_buttons_probe(struct platform_device *pdev){struct resource *res;struct device *dev;int ret;int size;int i;printk("probe:%s\n", __func__);dev = &pdev->dev;buttons_dev = &pdev->dev;/*平台资源获取*/ /*get irq number*/  for(i=0; i<6; i++){//获取中断号 buttons_irq = platform_get_resource(pdev,IORESOURCE_IRQ,i); if(buttons_irq == NULL){   dev_err(dev,"no irq resource specified\n");  ret = -ENOENT;return ret;}button_irqs[i] = buttons_irq->start;//printk("button_irqs[%d]=%d\n",i,button_irqs[i]);  }//注册混杂设备ret = misc_register(&ok6410_miscdev);return ret;}static int ok6410_buttons_remove(struct platform_device *dev){misc_deregister(&ok6410_miscdev);return 0;}/*平台驱动定义*/static struct platform_driver ok6410_buttons_driver = {.probe= ok6410_buttons_probe,//探针函数.remove= ok6410_buttons_remove,.driver= {.owner= THIS_MODULE,.name= DRIVER_NAME,},};static char banner[] __initdata = "ok6410 Buttons Driver\n";static int __init buttons_init(void){printk(banner);/*平台驱动注册*/platform_driver_register(&ok6410_buttons_driver);/*初始化工作队列*/INIT_DELAYED_WORK(&dwork,buttons_work_func);return 0;}static void __exit buttons_exit(void){//平台驱动的注销platform_driver_unregister(&ok6410_buttons_driver);}module_init(buttons_init);module_exit(buttons_exit);MODULE_AUTHOR("Sola");MODULE_DESCRIPTION("ok6410 Buttons Driver");MODULE_LICENSE("GPL");
 


 

app-button.c

/* *      Buttons Example for Matrix V * *      Copyright (C) 2004 capbily - friendly-arm *capbily@hotmail.com */#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/select.h>#include <sys/time.h>#include <errno.h>int main(void){int buttons_fd;int key_value;buttons_fd = open("/dev/buttons", 0);if (buttons_fd < 0) {perror("open device buttons");exit(1);}for (;;) {fd_set rds;int ret;FD_ZERO(&rds);FD_SET(buttons_fd, &rds);ret = select(buttons_fd + 1, &rds, NULL, NULL, NULL);if (ret < 0) {perror("select");exit(1);}if (ret == 0) {printf("Timeout.\n");} else if (FD_ISSET(buttons_fd, &rds)) {int ret = read(buttons_fd, &key_value, sizeof key_value);if (ret != sizeof key_value) {if (errno != EAGAIN)perror("read buttons\n");continue;} else {printf("buttons_value: %d\n", key_value+1);}}}close(buttons_fd);return 0;}


 

 

 

实验现象:

 

原创粉丝点击