05day01ioctl_led

  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\n", 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\n", __FILE__, __FUNCTION__, __LINE__);
 81 
 82     //向内核中注册使用的地址
 83     if(! request_mem_region(LED_REG_BASE, 8 , DEVNAME)) {
 84         printk("request_mem_region  failed\n");
 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\n");
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\n", __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>\n");
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 }

 

posted @ 2017-02-27 23:42  小黑·.·  阅读(200)  评论(0编辑  收藏  举报