kwseeker

学编程:找代码,读代码,改代码,写代码;少看书。但少看不是不看,看一本书要限制在一天内。任务是通读书中主要的概念,明白大致是干什么用的,形成一个大概的框架;然后一周内干掉书中全部代码,代码不理解再浏览书中相关章节,注意是浏览。或者刷博客。代码实在刷不懂,可以先刷后面,待日后重新刷;因为书中代码有些部分可能出自后面的章节。代码总是在多次刷过之后,拨开乌云见日月的。。。

导航

Linux驱动设计——字符杂项设备

杂项设备

linux里面的misc杂项设备是主设备号为10的驱动设备,misc设备其实也就是特殊的字符设备,可自动生成设备节点。
定义头文件<linux/miscdevice.h>
 
杂项设备的结构体:
struct miscdevice{
    int minor; //杂项设备的此设备号(如果设置为MISC_DYNAMIC_MINOR,表示系统自动分配未使用的minor)
    const char *name;
    const stuct file_operations *fops;//驱动主题函数入口指针
    struct list_head list;
    struct device *parent;
    struct device *this device;
    const char *nodename;(在/dev下面创建的设备驱动节点)
    mode_t mode;
}; 
注册和释放
注册:int misc_register(struct miscdevice *misc)
释放:int misc_deregister(struct miscdevice *misc)
 
misc_device是特殊字符设备。注册驱动程序时采用misc_register函数注册,此函数中会自动创建设备节点,即设备文件。无需mknod指令创建设备文件。因为misc_register()会调用class_device_creat或者device_creat().
杂项字符设备和一般字符设备的区别:
1.一般字符设备首先申请设备号。  但是杂项字符设备的主设备号为10次设备号通过结构体struct miscdevice中的minor来设置。
2.一般字符设备要创建设备文件。 但是杂项字符设备在注册时会自动创建。
3.一般字符设备要分配一个cdev(字符设备)。  但是杂项字符设备只要创建struct miscdevice结构即可。
4.一般字符设备需要初始化cdev(即给字符设备设置对应的操作函数集struct file_operation). 但是杂项字符设备在结构体truct miscdevice中定义。
5.一般字符设备使用注册函数 int cdev_add struct (cdev *p,devt_t dev, unsigned)(第一个参数为之前初始化的字符设备,第二个参数为设备号,第三个参数为要添加设备的个数) 而杂项字符设备使用int misc_register(struct miscdevice *misc)来注册
 
驱动调用的实质:
就是通过 设备文件找到与之对应设备号的设备,再通过设备初始化时绑定的操作函数硬件进行控制
 
  1 #include <linux/miscdevice.h>
  2 #include <linux/delay.h>
  3 #include <asm/irq.h>
  4 #include <mach/regs-gpio.h>
  5 #include <mach/hardware.h>
  6 #include <linux/kernel.h>
  7 #include <linux/module.h>
  8 #include <linux/init.h>
  9 #include <linux/mm.h>
 10 #include <linux/fs.h>
 11 #include <linux/types.h>
 12 #include <linux/delay.h>
 13 #include <linux/moduleparam.h>
 14 #include <linux/slab.h>
 15 #include <linux/errno.h>
 16 #include <linux/ioctl.h>
 17 #include <linux/cdev.h>
 18 #include <linux/string.h>
 19 #include <linux/list.h>
 20 #include <linux/pci.h>
 21 #include <linux/gpio.h>
 22 #include <asm/uaccess.h>
 23 #include <asm/atomic.h>
 24 #include <asm/unistd.h>
 25  
 26  
 27 #define DEVICE_NAME "leds"
 28  
 29 #define IOCTL_LED_ON 1
 30 #define IOCTL_LED_OFF 0
 31  
 32 static unsigned long led_table [] =
 33 {
 34 S3C2410_GPB(5),
 35 S3C2410_GPB(6),
 36 S3C2410_GPB(7),
 37 S3C2410_GPB(8),
 38 };
 39  
 40 static unsigned int led_cfg_table [] =
 41 {
 42 S3C2410_GPIO_OUTPUT,
 43 S3C2410_GPIO_OUTPUT,
 44 S3C2410_GPIO_OUTPUT,
 45 S3C2410_GPIO_OUTPUT,
 46 };
 47  
 48 static int gt2440_leds_ioctl(
 49 // struct inode *inode, 
 50 struct file *file, 
 51 unsigned int cmd, 
 52 unsigned long arg)
 53 {
 54 if (arg > 4)
 55 {
 56 return -EINVAL;
 57 }
 58  
 59 switch(cmd)
 60 {
 61 case IOCTL_LED_ON:
 62 // 设置指定引脚的输出电平为0
 63 s3c2410_gpio_setpin(led_table[arg], 0);
 64 return 0;
 65  
 66 case IOCTL_LED_OFF:
 67 // 设置指定引脚的输出电平为1
 68 s3c2410_gpio_setpin(led_table[arg], 1);
 69 return 0;
 70  
 71 default:
 72 return -EINVAL;
 73 }
 74 }
 75  
 76 static struct file_operations dev_fops = {
 77 .owner = THIS_MODULE,
 78 .unlocked_ioctl =  gt2440_leds_ioctl,
 79 };
 80  
 81 static struct miscdevice misc = {
 82 .minor = MISC_DYNAMIC_MINOR,
 83 .name = DEVICE_NAME,
 84 .fops = &dev_fops,
 85 };
 86  
 87 static int __init dev_init(void)
 88 {
 89 int ret;
 90  
 91 int i;
 92 for (i = 0; i < 4; i++)
 93 {
 94 s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
 95 s3c2410_gpio_setpin(led_table[i], 0);
 96 }
 97  
 98 ret = misc_register(&misc);
 99  
100 printk (DEVICE_NAME" initialized\n");
101  
102 return ret;
103 }
104  
105 static void __exit dev_exit(void)
106 {
107 misc_deregister(&misc);
108 }
109  
110 module_init(dev_init);
111 module_exit(dev_exit);
112  
113 MODULE_LICENSE("GPL");
114 MODULE_AUTHOR("www.e-online.cc");
115 MODULE_DESCRIPTION("LEDS control for GT2440 Board");
View Code

 

 
 

posted on 2015-05-02 20:11  kwseeker  阅读(429)  评论(0编辑  收藏  举报