1 /* 2 long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); 3 4 misc 混杂字符设备 5 6 应用层通过ioctl 函数来 7 int ioctl(int d, unsigned long request, ...); 8 9 底层下 实现file_operations 中的unlocked_ioctl 接口 10 */ 11 #include <linux/module.h> 12 #include <linux/init.h> 13 #include <linux/kernel.h> //printk 14 15 #include <linux/miscdevice.h> //misc_register.... 16 #include <linux/fs.h> //file_operations 17 #include <mach/regs-gpio.h> //S5P_VA_GPIO2 18 #include <linux/ioport.h> //request_mem_region 19 20 #include "led_ctl.h" 21 //ioctl 命令的定义 22 23 #define DEVNAME "ldm" 24 25 #define LED_REG_BASE 0x110002e0 26 27 #define GPM4CON (*(volatile u32 *)(S5P_VA_GPIO2 + 0x02e0)) 28 #define GPM4DAT (*(volatile u8 *)(S5P_VA_GPIO2 + 0x02e4)) 29 30 struct ldm_info 31 { 32 struct miscdevice dev; 33 struct file_operations ops; 34 }; 35 36 struct ldm_info ldm; 37 38 static void led_on(u8 stat) 39 { 40 GPM4DAT = (GPM4DAT & ~0xf) | (stat & 0xf); 41 } 42 43 44 //int ioctl(int d, unsigned long request, ...); 45 long ldm_ioctl(struct file * file, unsigned int cmd, unsigned long arg) 46 { 47 int ret = 0; 48 printk("led_stat = %ld ", arg); 49 //cmd 50 //关于cmd 命令的定义,有四个宏辅助定义_IO, 51 //_IOR, _IOW, _IOWR 52 //底层用于生成的命令,应用层需要知道 53 //通常的做法,把cmd的生成放到.h文件,该头文件也提供给应用层 54 55 switch(cmd) { 56 case LED_STATUS: 57 //GPM4DAT = (GPM4DAT & ~0xf) | (arg & 0xf); 58 led_on(arg); 59 break; 60 case LED1_ON: 61 led_on(0b1110); 62 break; 63 case LED1_OFF: 64 led_on(0b1111); 65 break; 66 case GET_STATUS: 67 ret = (GPM4DAT & 0xf); 68 break; 69 default: 70 break; 71 } 72 73 return ret; 74 75 } 76 77 static int ldm_init(void) 78 { 79 int ret = 0; 80 printk("%s:%s, %d ", __FILE__, __FUNCTION__, __LINE__); 81 82 //向内核中注册使用的地址 83 if(! request_mem_region(LED_REG_BASE, 8 , DEVNAME)) { 84 printk("request_mem_region failed "); 85 ret = -EBUSY; 86 goto err_request_mem_region; 87 } 88 89 //初始化GPIO 把对应的端口设置为输出模式 90 GPM4CON = (GPM4CON & ~0xffff) | 0x1111; 91 92 //misc 93 ldm.dev.minor = MISC_DYNAMIC_MINOR; 94 ldm.dev.name = DEVNAME; 95 ldm.dev.fops = &ldm.ops; 96 ldm.ops.unlocked_ioctl = ldm_ioctl; 97 98 99 ret = misc_register(&ldm.dev); 100 if(ret < 0) { 101 printk("misc_register failed "); 102 goto err_misc_register; 103 } 104 105 106 return 0; 107 err_misc_register: 108 release_mem_region(LED_REG_BASE, 8); 109 err_request_mem_region: 110 return ret; 111 } 112 113 static void ldm_exit(void) 114 { 115 printk("%s:%s, %d ", __FILE__, __FUNCTION__, __LINE__); 116 misc_deregister(&ldm.dev); 117 release_mem_region(LED_REG_BASE, 8); 118 } 119 120 121 module_init(ldm_init); 122 module_exit(ldm_exit); 123 MODULE_LICENSE("GPL");
.h
1 #pragma once 2 3 #include <linux/ioctl.h> 4 //参考下内核文档 linux/linux-3.5/Documentation/ioctl 5 //ioctl-decoding.txt 和 ioctl-number.txt 6 //例如 实现 控制LED灯 7 /* 8 _IO (魔数, 基数); 9 • _IOR (魔数, 基数, 变量型) 10 • _IOW (魔数, 基数, 变量型) 11 • _IOWR (魔数, 基数,变量型 ) 12 */ 13 14 //写 15 #define LED_STATUS _IOW('l', 1, unsigned char) 16 //底层的驱动生成的一系列 命令 这个头文件同样也需要提供给应用层 17 18 #define LED1_ON _IO('l', 2) 19 #define LED1_OFF _IO('l', 3) 20 21 //读 22 #define GET_STATUS _IOR('l', 4, unsigned char) 23
app
1 //应用层 2 #include <stdio.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <unistd.h> 6 #include <sys/ioctl.h> 7 8 #include "led_ctl.h" 9 10 11 int main(int argc, char const *argv[]) 12 { 13 if(argc != 3) { 14 printf("usage: cmd <device file> <led status> "); 15 return -1; 16 } 17 18 int fd = open(argv[1], O_RDWR); 19 if(fd < 0) { 20 perror("open"); 21 goto err_open; 22 } 23 24 unsigned char led_status = atoi(argv[2]); 25 26 //ioctl(fd, LED_STATUS, led_status); 27 ioctl(fd, LED1_ON); 28 29 close(fd); 30 31 return 0; 32 33 err_open: 34 return -1; 35 }