歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux下面一個簡單的虛擬platform驅動

Linux下面一個簡單的虛擬platform驅動

日期:2017/3/1 10:39:13   编辑:Linux編程

在Linux之中,約定如果設備不屬於任何的總線,則可以把它注冊為虛擬的platform設備。

下面就簡單來學習一下一個簡單的platform設備是怎麼創建出來的。

一般注冊platform驅動的步驟是:

1,platform_device_create注冊一個設備

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 = {
}
};

platform_device和platform_driver的名字必須一致


然後在chrdev_probe中完成注冊一個字符設備。一般注冊字符設備的流程如下:

1,alloc_chrdev_region分配一個未使用的設備號

2,cdev_init和cdev_add使用(1)分配到的設備號添加一個字符設備


如果到這裡就結束了,我們就需要使用分配到的設備號手動去建立/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

[cpp]
  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/platform_device.h>
  4. #include <linux/cdev.h>
  5. #include <linux/fs.h>
  6. ////////////////////////////////////////////////////////////////////////////////
  7. /*
  8. * Yao.GUET
  9. * http://blog.csdn.net/Yao_GUET
  10. * a simple platform character driver
  11. */
  12. ////////////////////////////////////////////////////////////////////////////////
  13. MODULE_LICENSE("Dual BSD/GPL");
  14. ////////////////////////////////////////////////////////////////////////////////
  15. static int chrdev_open(struct inode *inode, struct file *file) {
  16. printk(KERN_ALERT "chrdev open!\n");
  17. return 0;
  18. }
  19. static int chrdev_release(struct inode *inode, struct file *file) {
  20. printk(KERN_ALERT "chrdev release!\n");
  21. return 0;
  22. }
  23. static int chrdev_ioctl(struct inode *inode, struct file *file,
  24. unsigned int cmd, unsigned long arg) {
  25. printk(KERN_ALERT "chrdev release!\n");
  26. return 0;
  27. }
  28. // Kernel interface
  29. static struct file_operations chrdev_fops = {
  30. .owner = THIS_MODULE,
  31. .ioctl = chrdev_ioctl,
  32. .open = chrdev_open,
  33. .release = chrdev_release,
  34. };
  35. #define CHRDEV_NAME "chrdev"
  36. // driver interface
  37. static struct class *chrdev_class = NULL;
  38. static struct device *chrdev_device = NULL;
  39. static dev_t chrdev_devno;
  40. static struct cdev chrdev_cdev;
  41. static int chrdev_probe(struct platform_device *dev) {
  42. int ret = 0, err = 0;
  43. printk(KERN_ALERT "chrdev probe!\n");
  44. // alloc character device number
  45. ret = alloc_chrdev_region(&chrdev_devno, 0, 1, CHRDEV_NAME);
  46. if (ret) {
  47. printk(KERN_ALERT " alloc_chrdev_region failed!\n");
  48. goto PROBE_ERR;
  49. }
  50. printk(KERN_ALERT " major:%d minor:%d\n", MAJOR(chrdev_devno), MINOR(chrdev_devno));
  51. cdev_init(&chrdev_cdev, &chrdev_fops);
  52. chrdev_cdev.owner = THIS_MODULE;
  53. // add a character device
  54. err = cdev_add(&chrdev_cdev, chrdev_devno, 1);
  55. if (err) {
  56. printk(KERN_ALERT " cdev_add failed!\n");
  57. goto PROBE_ERR;
  58. }
  59. // create the device class
  60. chrdev_class = class_create(THIS_MODULE, CHRDEV_NAME);
  61. if (IS_ERR(chrdev_class)) {
  62. printk(KERN_ALERT " class_create failed!\n");
  63. goto PROBE_ERR;
  64. }
  65. // create the device node in /dev
  66. chrdev_device = device_create(chrdev_class, NULL, chrdev_devno,
  67. NULL, CHRDEV_NAME);
  68. if (NULL == chrdev_device) {
  69. printk(KERN_ALERT " device_create failed!\n");
  70. goto PROBE_ERR;
  71. }
  72. printk(KERN_ALERT " chrdev probe ok!\n");
  73. return 0;
  74. PROBE_ERR:
  75. if (err)
  76. cdev_del(&chrdev_cdev);
  77. if (ret)
  78. unregister_chrdev_region(chrdev_devno, 1);
  79. return -1;
  80. }
  81. static int chrdev_remove (struct platform_device *dev) {
  82. printk(KERN_ALERT " chrdev remove!\n");
  83. cdev_del(&chrdev_cdev);
  84. unregister_chrdev_region(chrdev_devno, 1);
  85. device_destroy(chrdev_class, chrdev_devno);
  86. class_destroy(chrdev_class);
  87. return 0;
  88. }
  89. // platform_device and platform_driver must has a same name!
  90. // or it will not work normally
  91. static struct platform_driver chrdev_platform_driver = {
  92. .probe = chrdev_probe,
  93. .remove = chrdev_remove,
  94. .driver = {
  95. .name = CHRDEV_NAME,
  96. .owner = THIS_MODULE,
  97. },
  98. };
  99. static struct platform_device chrdev_platform_device = {
  100. .name = CHRDEV_NAME,
  101. .id = 0,
  102. .dev = {
  103. }
  104. };
  105. static __init int chrdev_init(void) {
  106. int ret = 0;
  107. printk(KERN_ALERT "chrdev init!\n");
  108. ret = platform_device_register(&chrdev_platform_device);
  109. if (ret) {
  110. printk(KERN_ALERT " platform_device_register failed!\n");
  111. return ret;
  112. }
  113. ret = platform_driver_register(&chrdev_platform_driver);
  114. if (ret) {
  115. printk(KERN_ALERT " platform_driver_register failed!\n");
  116. return ret;
  117. }
  118. printk(KERN_ALERT " chrdev_init ok!\n");
  119. return ret;
  120. }
  121. static __exit void chrdev_exit(void) {
  122. printk(KERN_ALERT "chrdev exit!\n");
  123. platform_driver_unregister(&chrdev_platform_driver);
  124. }
  125. module_init(chrdev_init);
  126. module_exit(chrdev_exit);
Copyright © Linux教程網 All Rights Reserved