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");