在Linux之中,約定若是設備不屬於任何的總線,則能夠把它註冊爲虛擬的platform設備。 html
下面就簡單來學習一下一個簡單的platform設備是怎麼建立出來的。 node
通常註冊platform驅動的步驟是: linux
1,platform_device_create註冊一個設備 shell
2,platform_driver_create註冊一個驅動。 學習
static struct platform_driver chrdev_platform_driver = {
.probe = chrdev_probe,
.remove = chrdev_remove,
.driver = {
.name = CHRDEV_NAME,
.owner = THIS_MODULE,
},
};
static struct platform_device chrdev_platform_device = {
.name = CHRDEV_NAME,
.id = 0,
.dev = {
}
}; ui
platform_device和platform_driver的名字必須一致 spa
而後在chrdev_probe中完成註冊一個字符設備。通常註冊字符設備的流程以下: .net
1,alloc_chrdev_region分配一個未使用的設備號 orm
2,cdev_init和cdev_add使用(1)分配到的設備號添加一個字符設備 htm
若是到這裏就結束了,咱們就須要使用分配到的設備號手動去創建/dev下面的設備節點,,,
在這裏能夠使用class_create和device_create讓udev deamon自動爲咱們建立設備節點
3,class_create(THIS_MODULE, "chrdev");
4,device_create(chrdev_class, NULL, chrdev_devno, NULL, "chrdev");
當使用insmod把模塊加載到系統以後,www.linuxidc.com 就會在/dev下面自動建立名爲"chrdev"的設備節點,模塊名字應該儘可能跟註冊驅動的名字一致,否則可能會遇到不可測的問題。
源文件:chrdev.c
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/platform_device.h>
- #include <linux/cdev.h>
- #include <linux/fs.h>
- ////////////////////////////////////////////////////////////////////////////////
- /*
- * Yao.GUET
- * http://blog.csdn.net/Yao_GUET
- * a simple platform character driver
- */
- ////////////////////////////////////////////////////////////////////////////////
- MODULE_LICENSE("Dual BSD/GPL");
- ////////////////////////////////////////////////////////////////////////////////
- static int chrdev_open(struct inode *inode, struct file *file) {
- printk(KERN_ALERT "chrdev open!\n");
- return 0;
- }
-
- static int chrdev_release(struct inode *inode, struct file *file) {
- printk(KERN_ALERT "chrdev release!\n");
- return 0;
- }
-
- static int chrdev_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg) {
- printk(KERN_ALERT "chrdev release!\n");
- return 0;
- }
-
- // Kernel interface
- static struct file_operations chrdev_fops = {
- .owner = THIS_MODULE,
- .ioctl = chrdev_ioctl,
- .open = chrdev_open,
- .release = chrdev_release,
- };
-
-
- #define CHRDEV_NAME "chrdev"
- // driver interface
- static struct class *chrdev_class = NULL;
- static struct device *chrdev_device = NULL;
- static dev_t chrdev_devno;
- static struct cdev chrdev_cdev;
-
- static int chrdev_probe(struct platform_device *dev) {
- int ret = 0, err = 0;
-
- printk(KERN_ALERT "chrdev probe!\n");
-
- // alloc character device number
- ret = alloc_chrdev_region(&chrdev_devno, 0, 1, CHRDEV_NAME);
- if (ret) {
- printk(KERN_ALERT " alloc_chrdev_region failed!\n");
- goto PROBE_ERR;
- }
- printk(KERN_ALERT " major:%d minor:%d\n", MAJOR(chrdev_devno), MINOR(chrdev_devno));
-
- cdev_init(&chrdev_cdev, &chrdev_fops);
- chrdev_cdev.owner = THIS_MODULE;
- // add a character device
- err = cdev_add(&chrdev_cdev, chrdev_devno, 1);
- if (err) {
- printk(KERN_ALERT " cdev_add failed!\n");
- goto PROBE_ERR;
- }
-
- // create the device class
- chrdev_class = class_create(THIS_MODULE, CHRDEV_NAME);
- if (IS_ERR(chrdev_class)) {
- printk(KERN_ALERT " class_create failed!\n");
- goto PROBE_ERR;
- }
-
- // create the device node in /dev
- chrdev_device = device_create(chrdev_class, NULL, chrdev_devno,
- NULL, CHRDEV_NAME);
- if (NULL == chrdev_device) {
- printk(KERN_ALERT " device_create failed!\n");
- goto PROBE_ERR;
- }
-
- printk(KERN_ALERT " chrdev probe ok!\n");
- return 0;
-
- PROBE_ERR:
- if (err)
- cdev_del(&chrdev_cdev);
- if (ret)
- unregister_chrdev_region(chrdev_devno, 1);
- return -1;
- }
-
- static int chrdev_remove (struct platform_device *dev) {
- printk(KERN_ALERT " chrdev remove!\n");
-
- cdev_del(&chrdev_cdev);
- unregister_chrdev_region(chrdev_devno, 1);
-
- device_destroy(chrdev_class, chrdev_devno);
- class_destroy(chrdev_class);
- return 0;
- }
-
- // platform_device and platform_driver must has a same name!
- // or it will not work normally
- static struct platform_driver chrdev_platform_driver = {
- .probe = chrdev_probe,
- .remove = chrdev_remove,
- .driver = {
- .name = CHRDEV_NAME,
- .owner = THIS_MODULE,
- },
- };
-
- static struct platform_device chrdev_platform_device = {
- .name = CHRDEV_NAME,
- .id = 0,
- .dev = {
- }
- };
-
-
- static __init int chrdev_init(void) {
- int ret = 0;
- printk(KERN_ALERT "chrdev init!\n");
-
- ret = platform_device_register(&chrdev_platform_device);
- if (ret) {
- printk(KERN_ALERT " platform_device_register failed!\n");
- return ret;
- }
-
- ret = platform_driver_register(&chrdev_platform_driver);
- if (ret) {
- printk(KERN_ALERT " platform_driver_register failed!\n");
- return ret;
- }
- printk(KERN_ALERT " chrdev_init ok!\n");
- return ret;
- }
-
- static __exit void chrdev_exit(void) {
- printk(KERN_ALERT "chrdev exit!\n");
- platform_driver_unregister(&chrdev_platform_driver);
- }
-
- module_init(chrdev_init);
- module_exit(chrdev_exit);
-
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/platform_device.h>
- #include <linux/cdev.h>
- #include <linux/fs.h>
- ////////////////////////////////////////////////////////////////////////////////
- /*
- * Yao.GUET
- * http://blog.csdn.net/Yao_GUET
- * a simple platform character driver
- */
- ////////////////////////////////////////////////////////////////////////////////
- MODULE_LICENSE("Dual BSD/GPL");
- ////////////////////////////////////////////////////////////////////////////////
- static int chrdev_open(struct inode *inode, struct file *file) {
- printk(KERN_ALERT "chrdev open!\n");
- return 0;
- }
-
- static int chrdev_release(struct inode *inode, struct file *file) {
- printk(KERN_ALERT "chrdev release!\n");
- return 0;
- }
-
- static int chrdev_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg) {
- printk(KERN_ALERT "chrdev release!\n");
- return 0;
- }
-
- // Kernel interface
- static struct file_operations chrdev_fops = {
- .owner = THIS_MODULE,
- .ioctl = chrdev_ioctl,
- .open = chrdev_open,
- .release = chrdev_release,
- };
-
-
- #define CHRDEV_NAME "chrdev"
- // driver interface
- static struct class *chrdev_class = NULL;
- static struct device *chrdev_device = NULL;
- static dev_t chrdev_devno;
- static struct cdev chrdev_cdev;
-
- static int chrdev_probe(struct platform_device *dev) {
- int ret = 0, err = 0;
-
- printk(KERN_ALERT "chrdev probe!\n");
-
- // alloc character device number
- ret = alloc_chrdev_region(&chrdev_devno, 0, 1, CHRDEV_NAME);
- if (ret) {
- printk(KERN_ALERT " alloc_chrdev_region failed!\n");
- goto PROBE_ERR;
- }
- printk(KERN_ALERT " major:%d minor:%d\n", MAJOR(chrdev_devno), MINOR(chrdev_devno));
-
- cdev_init(&chrdev_cdev, &chrdev_fops);
- chrdev_cdev.owner = THIS_MODULE;
- // add a character device
- err = cdev_add(&chrdev_cdev, chrdev_devno, 1);
- if (err) {
- printk(KERN_ALERT " cdev_add failed!\n");
- goto PROBE_ERR;
- }
-
- // create the device class
- chrdev_class = class_create(THIS_MODULE, CHRDEV_NAME);
- if (IS_ERR(chrdev_class)) {
- printk(KERN_ALERT " class_create failed!\n");
- goto PROBE_ERR;
- }
-
- // create the device node in /dev
- chrdev_device = device_create(chrdev_class, NULL, chrdev_devno,
- NULL, CHRDEV_NAME);
- if (NULL == chrdev_device) {
- printk(KERN_ALERT " device_create failed!\n");
- goto PROBE_ERR;
- }
-
- printk(KERN_ALERT " chrdev probe ok!\n");
- return 0;
-
- PROBE_ERR:
- if (err)
- cdev_del(&chrdev_cdev);
- if (ret)
- unregister_chrdev_region(chrdev_devno, 1);
- return -1;
- }
-
- static int chrdev_remove (struct platform_device *dev) {
- printk(KERN_ALERT " chrdev remove!\n");
-
- cdev_del(&chrdev_cdev);
- unregister_chrdev_region(chrdev_devno, 1);
-
- device_destroy(chrdev_class, chrdev_devno);
- class_destroy(chrdev_class);
- return 0;
- }
-
- // platform_device and platform_driver must has a same name!
- // or it will not work normally
- static struct platform_driver chrdev_platform_driver = {
- .probe = chrdev_probe,
- .remove = chrdev_remove,
- .driver = {
- .name = CHRDEV_NAME,
- .owner = THIS_MODULE,
- },
- };
-
- static struct platform_device chrdev_platform_device = {
- .name = CHRDEV_NAME,
- .id = 0,
- .dev = {
- }
- };
-
-
- static __init int chrdev_init(void) {
- int ret = 0;
- printk(KERN_ALERT "chrdev init!\n");
-
- ret = platform_device_register(&chrdev_platform_device);
- if (ret) {
- printk(KERN_ALERT " platform_device_register failed!\n");
- return ret;
- }
-
- ret = platform_driver_register(&chrdev_platform_driver);
- if (ret) {
- printk(KERN_ALERT " platform_driver_register failed!\n");
- return ret;
- }
- printk(KERN_ALERT " chrdev_init ok!\n");
- return ret;
- }
-
- static __exit void chrdev_exit(void) {
- printk(KERN_ALERT "chrdev exit!\n");
- platform_driver_unregister(&chrdev_platform_driver);
- }
-
- module_init(chrdev_init);
- module_exit(chrdev_exit);
Makefile:
- ### Makefile
- obj-m := chrdev.o
-
- KERNEL_DIR := /lib/modules/$(shell uname -r)/build
- PWD := $(shell pwd)
-
- default:
- $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
-
- clean:
- $(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
[html]
view plain
copy
print
?
- ### Makefile
- obj-m := chrdev.o
-
- KERNEL_DIR := /lib/modules/$(shell uname -r)/build
- PWD := $(shell pwd)
-
- default:
- $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
-
- clean:
- $(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean