1. 程式人生 > 其它 >LED驅動匯流排裝置驅動模型

LED驅動匯流排裝置驅動模型

匹配規則

 最先比較:platform_device. driver_override和platform_driver.driver.name

可以設定platform_device的driver_override,強制選擇某個platform_driver。

 然後比較:platform_device. name和platform_driver.id_table[i].name

Platform_driver.id_table是“platform_device_id”指標,表示該drv支援若干個device,它裡面列出了各個device的{.name, .driver_data},其中的“name”表示該drv支援的裝置的名字,driver_data是些提供給該device的私有資料。

最後比較:platform_device.name和platform_driver.driver.name

platform_driver.id_table可能為空,

這時可以根據platform_driver.driver.name來尋找同名的platform_device。

怎麼寫程式

分配/設定/註冊platform_device結構體 board檔案

在裡面定義所用資源,指定裝置名字。

分配/設定/註冊platform_driver結構體

在其中的probe函式裡,分配/設定/註冊file_operations結構體,

並從platform_device中確實所用硬體資源。

指定platform_driver的名字。

leddrv為驅動上層檔案。其實中有幾個函式可以匯出來,供其他檔案使用。只需要包含相應的h檔案就好了。

  1 #include <linux/module.h>
  2 
  3 #include <linux/fs.h>
  4 #include <linux/errno.h>
  5 #include <linux/miscdevice.h>
  6 #include <linux/kernel.h>
  7 #include <linux/major.h>
  8 #include <linux/mutex.h>
  9
#include <linux/proc_fs.h> 10 #include <linux/seq_file.h> 11 #include <linux/stat.h> 12 #include <linux/init.h> 13 #include <linux/device.h> 14 #include <linux/tty.h> 15 #include <linux/kmod.h> 16 #include <linux/gfp.h> 17 18 #include "led_opr.h" 19 20 21 /* 1. 確定主裝置號 */ 22 static int major = 0; 23 static struct class *led_class; 24 struct led_operations *p_led_opr; 25 26 27 #define MIN(a, b) (a < b ? a : b) 28 29 /* 2. 定義自己的file_operations結構體 */ 30 static struct file_operations led_drv = { 31 .owner = THIS_MODULE, 32 .open = led_drv_open, 33 .read = led_drv_read, 34 .write = led_drv_write, 35 .release = led_drv_close, 36 }; 37 /* 3. 實現對應的open/read/write等函式,填入file_operations結構體 */ 38 static int led_drv_open (struct inode *node, struct file *file) 39 { 40 int minor = iminor(node); 41 42 printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); 43 /* 根據次裝置號初始化LED */ 44 p_led_opr->init(minor); 45 46 return 0; 47 } 48 static ssize_t led_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset) 49 { 50 printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); 51 return 0; 52 } 53 54 /* write(fd, &val, 1); */ 55 static ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset) 56 { 57 int err; 58 char status; 59 struct inode *inode = file_inode(file); 60 int minor = iminor(inode); 61 62 printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); 63 err = copy_from_user(&status, buf, 1); 64 65 /* 根據次裝置號和status控制LED */ 66 p_led_opr->ctl(minor, status); 67 68 return 1; 69 } 70 static int led_drv_close (struct inode *node, struct file *file) 71 { 72 printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); 73 return 0; 74 } 75 76 void led_class_create_device(int minor) 77 { 78 device_create(led_class, NULL, MKDEV(major, minor), NULL, "100ask_led%d", minor); /* /dev/100ask_led0,1,... */ 79 } 80 81 void led_class_destroy_device(int minor) 82 { 83 device_destroy(led_class, MKDEV(major, minor)); 84 } 85 86 void register_led_operations(struct led_operations *opr) 87 { 88 p_led_opr = opr; 89 } 90 91 EXPORT_SYMBOL(led_class_create_device); 92 EXPORT_SYMBOL(led_class_destroy_device); 93 EXPORT_SYMBOL(register_led_operations); 94 95 96 /* 4. 把file_operations結構體告訴核心:註冊驅動程式 */ 97 /* 5. 誰來註冊驅動程式啊?得有一個入口函式:安裝驅動程式時,就會去呼叫這個入口函式 */ 98 static int __init led_init(void) 99 { 100 int err; 101 102 printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); 103 major = register_chrdev(0, "100ask_led", &led_drv); /* /dev/led */ 104 105 106 led_class = class_create(THIS_MODULE, "100ask_led_class"); 107 err = PTR_ERR(led_class); 108 if (IS_ERR(led_class)) { 109 printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); 110 unregister_chrdev(major, "led"); 111 return -1; 112 } 113 114 return 0; 115 } 116 117 /* 6. 有入口函式就應該有出口函式:解除安裝驅動程式時,就會去呼叫這個出口函式 */ 118 static void __exit led_exit(void) 119 { 120 printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); 121 122 class_destroy(led_class); 123 unregister_chrdev(major, "100ask_led"); 124 } 125 126 127 /* 7. 其他完善:提供裝置資訊,自動建立裝置節點 */ 128 129 module_init(led_init); 130 module_exit(led_exit); 131 132 MODULE_LICENSE("GPL");
 1 #ifndef _LEDDRV_H
 2 #define _LEDDRV_H
 3 
 4 #include "led_opr.h"
 5 
 6 void led_class_create_device(int minor);
 7 void led_class_destroy_device(int minor);
 8 void register_led_operations(struct led_operations *opr);
 9 
10 #endif /* _LEDDRV_H */

接下來我們在board檔案中指定資源,並對platform_device進行分配,設定,註冊。

 1 #include <linux/module.h>
 2 
 3 #include <linux/fs.h>
 4 #include <linux/errno.h>
 5 #include <linux/miscdevice.h>
 6 #include <linux/kernel.h>
 7 #include <linux/major.h>
 8 #include <linux/mutex.h>
 9 #include <linux/proc_fs.h>
10 #include <linux/seq_file.h>
11 #include <linux/stat.h>
12 #include <linux/init.h>
13 #include <linux/device.h>
14 #include <linux/tty.h>
15 #include <linux/kmod.h>
16 #include <linux/gfp.h>
17 #include <linux/platform_device.h>
18 
19 #include "led_resource.h"
20 
21 
22 static void led_dev_release(struct device *dev)
23 {
24 }
25 
26 static struct resource resources[] = {
27         {
28                 .start = GROUP_PIN(3,1),
29                 .flags = IORESOURCE_IRQ,
30                 .name = "100ask_led_pin",
31         },
32         {
33                 .start = GROUP_PIN(5,8),
34                 .flags = IORESOURCE_IRQ,
35                 .name = "100ask_led_pin",
36         },
37 };
38 
39 
40 static struct platform_device board_A_led_dev = {
41         .name = "100ask_led",
42         .num_resources = ARRAY_SIZE(resources),
43         .resource = resources,
44         .dev = {
45                 .release = led_dev_release,
46          },
47 };
48 
49 static int __init led_dev_init(void)
50 {
51     int err;
52     
53     err = platform_device_register(&board_A_led_dev);   
54     
55     return 0;
56 }
57 
58 static void __exit led_dev_exit(void)
59 {
60     platform_device_unregister(&board_A_led_dev);
61 }
62 
63 module_init(led_dev_init);
64 module_exit(led_dev_exit);
65 
66 MODULE_LICENSE("GPL");

接下來我們在晶片相關的檔案中提供led的操作方法給上層,並對platform_driver進行分配,設定,註冊。

  1 #include <linux/module.h>
  2 
  3 #include <linux/fs.h>
  4 #include <linux/errno.h>
  5 #include <linux/miscdevice.h>
  6 #include <linux/kernel.h>
  7 #include <linux/major.h>
  8 #include <linux/mutex.h>
  9 #include <linux/proc_fs.h>
 10 #include <linux/seq_file.h>
 11 #include <linux/stat.h>
 12 #include <linux/init.h>
 13 #include <linux/device.h>
 14 #include <linux/tty.h>
 15 #include <linux/kmod.h>
 16 #include <linux/gfp.h>
 17 #include <linux/platform_device.h>
 18 
 19 #include "led_opr.h"
 20 #include "leddrv.h"
 21 #include "led_resource.h"
 22 
 23 static int g_ledpins[100];
 24 static int g_ledcnt = 0;
 25 
 26 static int board_demo_led_init (int which) /* 初始化LED, which-哪個LED */       
 27 {   
 28     //printk("%s %s line %d, led %d\n", __FILE__, __FUNCTION__, __LINE__, which);
 29     
 30     printk("init gpio: group %d, pin %d\n", GROUP(g_ledpins[which]), PIN(g_ledpins[which]));
 31     switch(GROUP(g_ledpins[which]))
 32     {
 33         case 0:
 34         {
 35             printk("init pin of group 0 ...\n");
 36             break;
 37         }
 38         case 1:
 39         {
 40             printk("init pin of group 1 ...\n");
 41             break;
 42         }
 43         case 2:
 44         {
 45             printk("init pin of group 2 ...\n");
 46             break;
 47         }
 48         case 3:
 49         {
 50             printk("init pin of group 3 ...\n");
 51             break;
 52         }
 53     }
 54     
 55     return 0;
 56 }
 57 
 58 static int board_demo_led_ctl (int which, char status) /* 控制LED, which-哪個LED, status:1-亮,0-滅 */
 59 {
 60     //printk("%s %s line %d, led %d, %s\n", __FILE__, __FUNCTION__, __LINE__, which, status ? "on" : "off");
 61     printk("set led %s: group %d, pin %d\n", status ? "on" : "off", GROUP(g_ledpins[which]), PIN(g_ledpins[which]));
 62 
 63     switch(GROUP(g_ledpins[which]))
 64     {
 65         case 0:
 66         {
 67             printk("set pin of group 0 ...\n");
 68             break;
 69         }
 70         case 1:
 71         {
 72             printk("set pin of group 1 ...\n");
 73             break;
 74         }
 75         case 2:
 76         {
 77             printk("set pin of group 2 ...\n");
 78             break;
 79         }
 80         case 3:
 81         {
 82             printk("set pin of group 3 ...\n");
 83             break;
 84         }
 85     }
 86 
 87     return 0;
 88 }
 89 
 90 static struct led_operations board_demo_led_opr = {
 91     .init = board_demo_led_init,
 92     .ctl  = board_demo_led_ctl,
 93 };
 94 
 95 struct led_operations *get_board_led_opr(void)
 96 {
 97     return &board_demo_led_opr;
 98 }
 99 
100 static int chip_demo_gpio_probe(struct platform_device *pdev)
101 {
102     struct resource *res;
103     int i = 0;
104 
105     while (1)
106     {
107         res = platform_get_resource(pdev, IORESOURCE_IRQ, i++);
108         if (!res)
109             break;
110         
111         g_ledpins[g_ledcnt] = res->start;
112         led_class_create_device(g_ledcnt);
113         g_ledcnt++;
114     }
115     return 0;
116     
117 }
118 
119 static int chip_demo_gpio_remove(struct platform_device *pdev)
120 {
121     struct resource *res;
122     int i = 0;
123 
124     while (1)
125     {
126         res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
127         if (!res)
128             break;
129         
130         led_class_destroy_device(i);
131         i++;
132         g_ledcnt--;
133     }
134     return 0;
135 }
136 
137 
138 static struct platform_driver chip_demo_gpio_driver = {
139     .probe      = chip_demo_gpio_probe,
140     .remove     = chip_demo_gpio_remove,
141     .driver     = {
142         .name   = "100ask_led",
143     },
144 };
145 
146 static int __init chip_demo_gpio_drv_init(void)
147 {
148     int err;
149     
150     err = platform_driver_register(&chip_demo_gpio_driver); 
151     register_led_operations(&board_demo_led_opr);
152     
153     return 0;
154 }
155 
156 static void __exit lchip_demo_gpio_drv_exit(void)
157 {
158     platform_driver_unregister(&chip_demo_gpio_driver);
159 }
160 
161 module_init(chip_demo_gpio_drv_init);
162 module_exit(lchip_demo_gpio_drv_exit);
163 
164 MODULE_LICENSE("GPL");

opr檔案不變

 1 #ifndef _LED_OPR_H
 2 #define _LED_OPR_H
 3 
 4 struct led_operations {
 5     int (*init) (int which); /* 初始化LED, which-哪個LED */       
 6     int (*ctl) (int which, char status); /* 控制LED, which-哪個LED, status:1-亮,0-滅 */
 7 };
 8 
 9 struct led_operations *get_board_led_opr(void);
10 
11 
12 #endif

資原始檔不變

 1 #ifndef _LED_RESOURCE_H
 2 #define _LED_RESOURCE_H
 3 
 4 /* GPIO3_0 */
 5 /* bit[31:16] = group */
 6 /* bit[15:0]  = which pin */
 7 #define GROUP(x) (x>>16)
 8 #define PIN(x)   (x&0xFFFF)
 9 #define GROUP_PIN(g,p) ((g<<16) | (p))
10 
11 
12 #endif

檔案包含關係圖: