zoukankan      html  css  js  c++  java
  • 03day03misc_device

      1 #include <linux/module.h>  //MODULE_LICENSE("GPL"); 
      2 #include <linux/init.h>   //module_init  module_exit
      3 #include <linux/kernel.h>  //printk
      4 #include <linux/io.h>    //ioremap  iounremap
      5 #include <linux/ioport.h>  //request_mem_region
      6 #include <mach/regs-gpio.h>
      7 
      8 #include <linux/miscdevice.h>
      9 #include <linux/fs.h>   //file_operations  结构体的定义
     10 
     11 /*
     12 混杂字符设备驱动   
     13 linux/miscdevice.h
     14 
     15 struct miscdevice  
     16 
     17 通过  cat /proc/devices  查看当前系统下所有的设备节点
     18 misc 是字符设备中的一种, 所有的misc设备,主设备都是10,
     19 struct miscdevice  {
     20     int minor;    //字符设备 次设备,次设备号一般交给内核,让内核自行分配
     21     minor  = MISC_DYNAMIC_MINOR
     22     const char *name;  //  设备名称
     23     const struct file_operations *fops;  //文件操作相关,这个结构非常重要
     24     //实现read  open write  close 等一些列文件操作,这些文件操作将和应用层交互
     25 
     26     struct list_head list;
     27     struct device *parent;
     28     struct device *this_device;
     29     const char *nodename;
     30     umode_t mode;
     31 };
     32 
     33 linux/fs.h   头文件中
     34 const struct file_operations *fops; 
     35 
     36 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
     37 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
     38 int (*open) (struct inode *, struct file *);
     39 int (*release) (struct inode *, struct file *);
     40 
     41 
     42 int fd = open("/dev/led");
     43 当应用层调用对应的misc的设备节点时候,那么file_operations 会被自动调用
     44 
     45 close-->release
     46 read-->read
     47 write-->write
     48 */
     49 
     50 /*
     51 input  输入子系统
     52 cdev   字符设备
     53 misc    混杂字符设备  本质就是一个字符设备
     54 /sysfs  /proc
     55 
     56 
     57 
     58 insmod  test.ko之后
     59 那么在 /dev/就会出现对应的节点
     60 
     61 
     62 */
     63 
     64 #define LED_REG_BASE 0x110002e0
     65 #define   DEVNAME  "my_led"
     66 
     67 //static u32  led_reg;
     68 
     69 #define GPM4CON  (*(volatile u32 *)(S5P_VA_GPIO2 + 0x02e0))
     70 #define GPM4DAT   (*(volatile u32 *)(S5P_VA_GPIO2 + 0x02e4))
     71 
     72 struct ldm_info
     73 {
     74     struct  miscdevice dev;       //设备节点
     75     struct  file_operations  ops;  //文件操作
     76 };
     77 
     78 struct ldm_info  ldm;
     79 
     80 static  int ldm_open(struct inode * inode, struct file * file)
     81 {
     82     printk("kernel: ldm_open
    ");
     83     return 0;
     84 }
     85 
     86 
     87 static void led_on(u8   stat)
     88 {
     89     GPM4DAT = (GPM4DAT  & ~0xf) | (stat & 0xf);
     90 }
     91 
     92 //__user  标志 说明 地址是用户地址
     93 /*
     94 用户层
     95     ssize_t write(int fildes, const void *buf, size_t nbyte); 
     96 调用用户层的write 之后, 会进入到内核中,调用file_operations中的write方法
     97 
     98 */
     99 
    100 //file_operations 中的read 和write都是站在 应用层的角度
    101 static  ssize_t ldm_write(struct file * file, const char __user * buf, size_t size, loff_t *   offt)
    102 {
    103     printk("kernel:ldm_write
    ");
    104     led_on(*buf);
    105     return 1;
    106 }
    107 
    108 
    109 //copy_to_user  copy_from_user
    110 //static  ssize_t ldm_read(struct file * file, char __user * buf, size_t, loff_t *);
    111 
    112 
    113 static int test_init(void)
    114 {
    115     int ret = 0;
    116 
    117     printk("%s:%s:%d   init
    ", __FILE__, __FUNCTION__, __LINE__);
    118  //向Linux内核中申请一段地址空间,如果之前已经有了其他的模块对该地址进行了申请,那么本次申请会失败.
    119 //注册成功之后,那么可以在/proc/iomem  看到注册信息
    120 //
    121     if(!request_mem_region(LED_REG_BASE, 8 , DEVNAME)) {
    122         printk("request_mem_region  failed
    ");
    123         ret = -1;
    124         goto err_request_mem_region;
    125     }
    126 
    127     //所谓的静态映射,是三星4412平台,已经做好的把物理地址,映射到的对应当的虚拟地址,所以此时没必要再调用ioremap函数
    128     //led_reg = (u32)ioremap(LED_REG_BASE, 8);
    129 
    130     //配置成输出模式
    131     GPM4CON  = (GPM4CON & ~0xffff) | 0x1111;
    132 
    133     //填充info中的  miscdevice  结构体
    134     //GPM4DAT  = (GPM4DAT & ~0xf) | 0b1001;
    135     ldm.dev.minor  = MISC_DYNAMIC_MINOR;  //系统自动分配次设备
    136     ldm.dev.name = DEVNAME;//该名称将决定节点名称, 成功注册 linux 系统中
    137     //在/dev 能够找一个和DEVNAME一样的节点
    138     ldm.dev.fops = &ldm.ops;  //关联文件操作
    139 
    140     ldm.ops.open = ldm_open;
    141     ldm.ops.write = ldm_write;
    142 
    143     //把这个misc 注册到linux 内核中
    144     ret = misc_register(&ldm.dev);
    145     if(ret < 0) {
    146         printk("misc_register  failed
    ");
    147         goto  err_misc_register;
    148     }
    149 
    150     return 0;
    151 err_misc_register:
    152     release_mem_region(LED_REG_BASE, 8);
    153 err_request_mem_region:
    154     return ret;
    155 
    156 }
    157 
    158 //卸载
    159 static void test_exit(void)
    160 {
    161     printk("%s:%s:%d   init
    ", __FILE__, __FUNCTION__, __LINE__);
    162 
    163     //注销misc 
    164     misc_deregister(&ldm.dev);
    165     //释放映射的虚拟地址
    166 //    iounmap((void *)led_reg);
    167 
    168     release_mem_region(LED_REG_BASE, 8);
    169 }
    170 
    171 module_init(test_init);
    172 module_exit(test_exit);
    173 
    174 
    175 MODULE_LICENSE("GPL");  //加入GPL许可
  • 相关阅读:
    android中textview字数过长解决方法
    Android的EditText无法自动弹出输入法问题 .
    android中dip、dp、px、sp和屏幕密度
    android横竖屏切换 判断activity 是横屏还是竖屏
    设置ListView中图片的大小大方法 Android
    TextView属性详细分析
    ArcGIS API For Silverlight 实例分析
    Visual Studio 2008 里修改数据库表结构报错 解决办法
    未能加载文件或程序集“xxx”或它的某一个依赖项。生成此程序集的运行时比当前加载的运行时新,无法加载此程序集
    SuperMap iClient 6R for Silverlight 产品简介及Beta测试软件下载地址
  • 原文地址:https://www.cnblogs.com/baoshulin/p/6416190.html
Copyright © 2011-2022 走看看