linux buttun 按键驱动

使用ioctrl编写按键驱动
1
上层:ioctl 2 #include <sys/ioctl.h> 3 int ioctl(int d, int request, ...); 4 驱动:ioctl 5 struct file_operations文件操作集合 6 7 ioctl命令:32bit的数值 通常分为4部分 8 linux-3.5\Documentation\ioctl\ioctl-number.txt 9 10 If you are adding new ioctl's to the kernel, you should use the _IO 11 macros defined in <linux/ioctl.h>: 12 13 _IO an ioctl with no parameters 14 _IOW an ioctl with write parameters (copy_from_user) 15 _IOR an ioctl with read parameters (copy_to_user) 16 _IOWR an ioctl with both write and read parameters. 17 18 _IO 没有任何参数的ioctl指令 19 _IOW 带有写数据参数的ioctl指令 20 _IOR 带有读数据参数的ioctl指令 21 _IOWR 带有读写数据和方向的ioctl指令 22 23 linux/ioctl.h: 24 #define _IOC(dir,type,nr,size) \ 25 ((unsigned int) \ 26 (((dir) << _IOC_DIRSHIFT) | \ 27 ((type) << _IOC_TYPESHIFT) | \ 28 ((nr) << _IOC_NRSHIFT) | \ 29 ((size) << _IOC_SIZESHIFT))) 30 31 /* used to create numbers */ 32 #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) 33 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) 34 #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) 35 #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) 36 37 /* used to decode them.. */ 38 #define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) 39 #define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) 40 #define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) 41 #define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) 42 43 _IOC(dir,type,nr,size) 44 dir 方向 45 type 类型 幻数/魔数 magic 46 nr 指令编号 47 size 传送数据类型
  1 #include <linux/kernel.h>
  2 #include <linux/module.h>
  3 #include <linux/fs.h>
  4 #include <linux/device.h>
  5 #include <asm/io.h>
  6 #include <asm/uaccess.h>
  7 #include <linux/cdev.h>
  8 #include <linux/ioctl.h>
  9 #include <linux/delay.h>
 10 
 11 #define        GPX3CON_PHY_ADDR                0x11000C60
 12 #define        GPX3DAT_PHY_ADDR                0x11000C64
 13 #define        GPX3PUD_PHY_ADDR                0x11000C68
 14 
 15 static volatile unsigned long* gpx3con;
 16 static volatile unsigned long* gpx3dat;
 17 static volatile unsigned long* gpx3pud;
 18 
 19 static dev_t button_dev;
 20 static struct class* button_class;
 21 static struct cdev* button_cdev;
 22 
 23 static int button_open(struct inode *inod, struct file *fil)
 24 {
 25     return 0;
 26 }
 27 
 28 static int button_release(struct inode *inod, struct file *fil)
 29 {
 30     printk("button release......\n");
 31 
 32     return 0;
 33 }
 34 
 35 static ssize_t button_read(struct file *fil, char __user *buf, size_t count, loff_t * offsets)
 36 {
 37     unsigned char button_status=0;
 38     
 39     if(!(*gpx3dat & (1<<2)))
 40     {
 41         mdelay(100);
 42         if(!(*gpx3dat & (1<<2)))
 43         {
 44             printk("button1 press\n");
 45             button_status = 1;
 46         }
 47     }
 48     else if(!(*gpx3dat & (1<<3)))
 49     {
 50         mdelay(100);
 51         if(!(*gpx3dat & (1<<3)))
 52         {
 53             printk("button2 press\n");
 54             button_status = 2;
 55         }
 56     }        
 57     else if(!(*gpx3dat & (1<<4)))
 58     {
 59         mdelay(100);
 60         if(!(*gpx3dat & (1<<4)))
 61         {
 62             printk("button3 press\n");
 63             button_status = 3;
 64         }
 65     }        
 66     else if(!(*gpx3dat & (1<<5)))
 67     {
 68         mdelay(100);
 69         if(!(*gpx3dat & (1<<5)))
 70         {
 71             printk("button4 press\n");
 72             button_status = 4;
 73         }
 74     }        
 75     else
 76         button_status = 0;
 77 
 78     return  copy_to_user(buf, &button_status,1);
 79 }
 80 
 81 static struct file_operations button_fops =
 82 {
 83         .owner        = THIS_MODULE,
 84         .open        = button_open,
 85         .release    = button_release,
 86         .read        = button_read,
 87 };
 88 
 89 static int __init buttondriver_init(void)
 90 {
 91     alloc_chrdev_region(&button_dev, 0,1, "buttondriver");
 92 
 93     button_cdev   = cdev_alloc();
 94 
 95     button_cdev->count            = 1;
 96     button_cdev->dev            = button_dev;
 97     button_cdev->ops            = &button_fops;
 98     button_cdev->owner            = THIS_MODULE;
 99 
100     cdev_add(button_cdev,button_dev,1);
101 
102     button_class = class_create(THIS_MODULE,"button_class");
103     device_create(button_class,NULL,button_dev,NULL,"button");
104 
105     gpx3con        = ioremap(GPX3CON_PHY_ADDR,12);
106     gpx3dat      = gpx3con + 1;
107     gpx3pud    = gpx3con + 2;
108 
109     *gpx3con &= ~(0xFFFF<<8);
110     *gpx3pud &= ~(0xFF<<4);
111     *gpx3pud |= 0xFF<<4;
112     
113     return 0;
114 }
115 
116 static void __exit buttondriver_exit(void)
117 {
118     iounmap(gpx3con);
119 
120     device_destroy(button_class,button_dev);
121     class_destroy(button_class);
122 
123     cdev_del(button_cdev);
124     unregister_chrdev_region(button_dev, 1);
125 }
126 
127 module_init(buttondriver_init);
128 module_exit(buttondriver_exit);
129 MODULE_LICENSE("GPL");
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc,char *argv[])
{
    int button_fd;
    unsigned char button_status;

    if(argc !=2)
    {
        printf("Usage:<%s> </dev/?node>\n",argv[0]);
        return -1;
    }

    button_fd = open(argv[1],O_RDONLY);    

    while(1)
    {
        read(button_fd,&button_status,1);

        if(button_status!=0)
            printf("button %d\n",button_status);

        // sleep(1);
    }
}
 
按键控制led 上层测试程序

1
#include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <unistd.h> 6 #include <stdlib.h> 7 #include <sys/ioctl.h> 8 #include <string.h> 9 10 #define LED_MAGIC 'L' 11 #define LED_ALL_ON _IO('L',0x0) 12 #define LED_ALL_OFF _IO('L',0x1) 13 #define LED_NUM_ON _IOW('L',0x2,unsigned char) 14 #define LED_NUM_OFF _IOW('L',0x3,unsigned char) 15 16 int main(int argc,char *argv[]) 17 { 18 int led_fd,button_fd; 19 unsigned char button_status; 20 21 if(argc <3) 22 { 23 printf("Usage:<%s> <buttonnode> <lednode>\n",argv[0]); 24 return -1; 25 } 26 27 button_fd = open(argv[1],O_RDONLY); 28 led_fd = open(argv[2],O_WRONLY); 29 30 while(1) 31 { 32 read(button_fd,&button_status,1); 33 34 if(button_status==1) 35 ioctl(led_fd,LED_NUM_ON,0); 36 else if(button_status==2) 37 ioctl(led_fd,LED_NUM_ON,1); 38 else if(button_status==3) 39 ioctl(led_fd,LED_NUM_ON,2); 40 else if(button_status==4) 41 ioctl(led_fd,LED_NUM_ON,3); 42 else 43 ioctl(led_fd,LED_ALL_OFF); 44 // sleep(1); 45 } 46 }
附件led驱动 自己看看修改

#include <linux/kernel.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/device.h> #include <asm/io.h> #include <asm/uaccess.h> #include <linux/cdev.h> #include <linux/ioctl.h> #define LED_MAGIC 'L' #define LED_ALL_ON _IO('L',0x0) #define LED_ALL_OFF _IO('L',0x1) #define LED1_ON _IO('L',0x2) #define LED1_OFF _IO('L',0x3) #define LED2_ON _IO('L',0x4) #define LED2_OFF _IO('L',0x5) #define LED3_ON _IO('L',0x6) #define LED3_OFF _IO('L',0x7) #define LED4_ON _IO('L',0x8) #define LED4_OFF _IO('L',0x9) #define GPM4CON_PHY_ADDR 0x110002E0 #define GPM4DAT_PHY_ADDR 0x110002E4 static volatile unsigned long* gpm4con; static volatile unsigned long* gpm4dat; static dev_t led_dev; static struct class* led_class; static struct cdev* led_cdev; static int led_open(struct inode *inod, struct file *fil) { return 0; } static int led_release(struct inode *inod, struct file *fil) { printk("led release......goodbye!!!!\n"); return 0; } static ssize_t led_write(struct file *fil, const char __user *buf, size_t count, loff_t *offsets) { return 0; } static long led_ioctl(struct file *fil, unsigned int cmd, unsigned long arg) { switch(cmd) { case LED_ALL_ON: *gpm4dat &= ~(0xF<<0);break; case LED_ALL_OFF: *gpm4dat |= 0xF<<0;break; case LED1_ON: *gpm4dat &= ~(0x1<<0);break; case LED1_OFF: *gpm4dat |= 0x1<<0;break; case LED2_ON: *gpm4dat &= ~(0x1<<1);break; case LED2_OFF: *gpm4dat |= 0x1<<1;break; case LED3_ON: *gpm4dat &= ~(0x1<<2);break; case LED3_OFF: *gpm4dat |= 0x1<<2;break; case LED4_ON: *gpm4dat &= ~(0x1<<3);break; case LED4_OFF: *gpm4dat |= 0x1<<3;break; default: printk("cmd is error!!\n"); return -EINVAL; } return 0; } static struct file_operations led_fops = { .owner = THIS_MODULE, .open = led_open, .release = led_release, .write = led_write, .unlocked_ioctl = led_ioctl, }; static int __init leddriver_init(void) { alloc_chrdev_region(&led_dev, 0,1, "leddriver"); led_cdev = cdev_alloc(); led_cdev->count = 1; led_cdev->dev = led_dev; led_cdev->ops = &led_fops; led_cdev->owner = THIS_MODULE; cdev_add(led_cdev,led_dev,1); led_class = class_create(THIS_MODULE,"led_class"); device_create(led_class,NULL,led_dev,NULL,"led"); gpm4con = ioremap(GPM4CON_PHY_ADDR,8); gpm4dat = gpm4con + 1; *gpm4con &= ~(0xFFFF<<0); *gpm4con |= 0x1111<<0; *gpm4dat |= 0xF<<0; return 0; } static void __exit leddriver_exit(void) { iounmap(gpm4con); device_destroy(led_class,led_dev); class_destroy(led_class); cdev_del(led_cdev); unregister_chrdev_region(led_dev, 1); } module_init(leddriver_init); module_exit(leddriver_exit); MODULE_LICENSE("GPL");

 

posted @ 2017-06-09 11:17  root-linux  阅读(431)  评论(0编辑  收藏  举报