東川印記

一本東川,笑看爭龍斗虎;寰茫兦者,度橫佰昧人生。

android源码编译之06XXXServicesFramework编写之可行性试验01编写Linux内核驱动程序

2015年4月10日星期五



Demo先行。
使用之前所编译Android4.4.2源码Kernel3.4.67版正常运行
  1. senrsl@senrsl-ubuntu:~/android/source/WORKING_DIRECTORY$ emulator -kernel /homsenrsl/android/source/kernel/goldfish/arch/arm/boot/zImage
然后,
1,编写Linux内核驱动程序
①创建定义驱动的目录及文件
  1. senrsl@senrsl-ubuntu:~$ cd android/source/kernel/goldfish/drivers/
  2. senrsl@senrsl-ubuntu:~/android/source/kernel/goldfish/drivers$ mkdir senrsl
  3. senrsl@senrsl-ubuntu:~/android/source/kernel/goldfish/drivers$ cd senrsl
  4. senrsl@senrsl-ubuntu:~/android/source/kernel/goldfish/drivers/senrsl$ touch senrsl.h
  5. senrsl@senrsl-ubuntu:~/android/source/kernel/goldfish/drivers/senrsl$ touch senrsl.c
  6. senrsl@senrsl-ubuntu:~/android/source/kernel/goldfish/drivers/senrsl$ touch Kconfig
  7. senrsl@senrsl-ubuntu:~/android/source/kernel/goldfish/drivers/senrsl$ touch Makefile
②然后挨个编写文件
1)senrsl.h
  1. #ifndef _SENRSL_ANDROID_H_
  2. #define _SENRSL_ANDROID_H_

  3. #include <linux/cdev.h>
  4. #include <linux/semaphore.h>

  5. //定义字符串常量宏
  6. #define SENRSL_DEVICE_NODE_NAME "senrsl"
  7. #define SENRSL_DEVICE_FILE_NAME "senrsl"
  8. #define SENRSL_DEVICE_PROC_NAME "senrsl"
  9. #define SENRSL_DEVICE_CLASS_NAME "senrsl"

  10. //字符设备结构体 senrsl_android_dev,即虚拟设备
  11. struct senrsl_android_dev {
  12.     int val;//代表设备里的寄存器
  13.     struct semaphore sem;//信号量,用于同步访问寄存器val
  14.     struct cdev dev;//内嵌字符设备,Linux驱动程序自定 义字符设备结构体的标准方法
  15. };

  16. #endif
2)senrsl.c
  1. /**
  2. * senrsl.c是驱动程序的实现部分
  3. * 驱动程序的功能主要是向上层提供访问设备的寄存器的值,包括读和写。
  4. * 这里,提供了三种访问设备寄存器的方法,
  5. *     一是通过proc文件系统来访问,
  6. *     二是通过传统的设备文件的方法来访问,
  7. *     三是通过devfs文件系统来访问
  8. */


  9. /*********************** 首先是包含必要的头文件和定义三种访问设备的方法*********************************/
  10. #include <linux/init.h>
  11. #include <linux/module.h>
  12. #include <linux/types.h>
  13. #include <linux/fs.h>
  14. #include <linux/proc_fs.h>
  15. #include <linux/device.h>
  16. #include <asm/uaccess.h>

  17. #include "senrsl.h"

  18. /*主设备和从设备号变量*/
  19. static int senrsl_major = 0;
  20. static int senrsl_minor = 0;

  21. /*设备类别和设备变量*/
  22. static struct class* senrsl_class = NULL;
  23. static struct senrsl_android_dev* senrsl_dev = NULL;

  24. /*传统的设备文件操作方法*/
  25. static int senrsl_open(struct inode* inode, struct file* filp);
  26. static int senrsl_release(struct inode* inode, struct file* filp);
  27. static ssize_t senrsl_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos);
  28. static ssize_t senrsl_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos);

  29. /*设备文件操作方法表*/
  30. static struct file_operations senrsl_fops = {
  31.     .owner = THIS_MODULE,
  32.     .open = senrsl_open,
  33.     .release = senrsl_release,
  34.     .read = senrsl_read,
  35.     .write = senrsl_write,
  36. };

  37. /*访问设置属性方法*/
  38. static ssize_t senrsl_val_show(struct device* dev, struct device_attribute* attr, char* buf);
  39. static ssize_t senrsl_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count);

  40. /*定义设备属性*/
  41. static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, senrsl_val_show, senrsl_val_store);



  42. /******************** 定义传统的设备文件访问方法,主要是定义senrsl_open、senrsl_release、senrsl_read和 senrsl_write这四个打开、释放、读和写设备文件的方法*************************/
  43. /*打开设备方法*/
  44. static int senrsl_open(struct inode* inode, struct file* filp) {
  45.     struct senrsl_android_dev* dev;
  46.     
  47.     /*将自定义设备结构体保存在文件指针的私 有数据域中,以便访问设备时拿来用*/
  48.     dev = container_of(inode->i_cdev, struct senrsl_android_dev, dev);
  49.     filp->private_data = dev;
  50.     
  51.     return 0;
  52. }

  53. /*设备文件释放时调用,空实现*/
  54. static int senrsl_release(struct inode* inode, struct file* filp) {
  55.     return 0;
  56. }

  57. /*读取设备的寄存器val的值*/
  58. static ssize_t senrsl_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos) {
  59.     ssize_t err = 0;
  60.     struct senrsl_android_dev* dev = filp->private_data;

  61.     /*同步访问*/
  62.     if(down_interruptible(&(dev->sem))) {
  63.         return -ERESTARTSYS;
  64.     }

  65.     if(count < sizeof(dev->val)) {
  66.         goto out;
  67.     }

  68.     /*将寄存器val的值拷贝到用户提供的缓 冲区*/
  69.     if(copy_to_user(buf, &(dev->val), sizeof(dev->val))) {
  70.         err = -EFAULT;
  71.         goto out;
  72.     }

  73.     err = sizeof(dev->val);

  74. out:
  75.     up(&(dev->sem));
  76.     return err;
  77. }

  78. /*写设备的寄存器值val*/
  79. static ssize_t senrsl_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos) {
  80.     struct senrsl_android_dev* dev = filp->private_data;
  81.     ssize_t err = 0;

  82.     /*同步访问*/
  83.     if(down_interruptible(&(dev->sem))) {
  84.         return -ERESTARTSYS;
  85.     }

  86.     if(count != sizeof(dev->val)) {
  87.         goto out;
  88.     }

  89.     /*将用户提供的缓冲区的值写到设备寄存器 去*/
  90.     if(copy_from_user(&(dev->val), buf, count)) {
  91.         err = -EFAULT;
  92.         goto out;
  93.     }

  94.     err = sizeof(dev->val);

  95. out:
  96.     up(&(dev->sem));
  97.     return err;
  98. }

  99. /************************** 定义通过devfs文件系统访问方法,这里把设备的寄存器val看成是设备的一个属性,通过读写这个属性来对设备进行访问,主要是实 现senrsl_val_show和senrsl_val_store两个方法,同时定义了两个内部使用的访问val值的方法 __senrsl_get_val和 __senrsl_set_val****************************************/
  100. /*读取寄存器val的值到缓冲区buf 中,内部使用*/
  101. static ssize_t __senrsl_get_val(struct senrsl_android_dev* dev, char* buf) {
  102.     int val = 0;

  103.     /*同步访问*/
  104.     if(down_interruptible(&(dev->sem))) {
  105.         return -ERESTARTSYS;
  106.     }

  107.     val = dev->val;
  108.     up(&(dev->sem));

  109.     return snprintf(buf, PAGE_SIZE, "%d\n", val);
  110. }

  111. /*把缓冲区buf的值写到设备寄存器 val中去,内部使用*/
  112. static ssize_t __senrsl_set_val(struct senrsl_android_dev* dev, const char* buf, size_t count) {
  113.     int val = 0;

  114.     /*将字符串转换成数字*/
  115.     val = simple_strtol(buf, NULL, 10);

  116.     /*同步访问*/
  117.     if(down_interruptible(&(dev->sem))) {
  118.         return -ERESTARTSYS;
  119.     }

  120.     dev->val = val;
  121.     up(&(dev->sem));

  122.     return count;
  123. }

  124. /*读取设备属性val*/
  125. static ssize_t senrsl_val_show(struct device* dev, struct device_attribute* attr, char* buf) {
  126.     struct senrsl_android_dev* hdev = (struct senrsl_android_dev*)dev_get_drvdata(dev);

  127.     return __senrsl_get_val(hdev, buf);
  128. }

  129. /*写设备属性val*/
  130. static ssize_t senrsl_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count) {
  131.     struct senrsl_android_dev* hdev = (struct senrsl_android_dev*)dev_get_drvdata(dev);
  132.     
  133.     return __senrsl_set_val(hdev, buf, count);
  134. }

  135. /***********定义通过proc 文件系统访问方法,主要实现了senrsl_proc_read和senrsl_proc_write两个方法,同时定义了在 proc文件系统创建和删除文件的方法senrsl_create_proc和 senrsl_remove_proc*****************/
  136. /*读取设备寄存器val的值,保存在 page缓冲区中*/
  137. static ssize_t senrsl_proc_read(char* page, char** start, off_t off, int count, int* eof, void* data) {
  138.     if(off > 0) {
  139.         *eof = 1;
  140.         return 0;
  141.     }

  142.     return __senrsl_get_val(senrsl_dev, page);
  143. }

  144. /*把缓冲区的值buff保存到设备寄存器 val中去*/
  145. static ssize_t senrsl_proc_write(struct file* filp, const char __user *buff, unsigned long len, void* data) {
  146.     int err = 0;
  147.     char* page = NULL;

  148.     if(len > PAGE_SIZE) {
  149.         printk(KERN_ALERT"The buff is too large: %lu.\n", len);
  150.         return -EFAULT;
  151.     }

  152.     page = (char*)__get_free_page(GFP_KERNEL);
  153.     if(!page) {
  154.         printk(KERN_ALERT"Failed to alloc page.\n");
  155.         return -ENOMEM;
  156.     }

  157.     /*先把用户提供的缓冲区值拷贝到内核缓冲 区中去*/
  158.     if(copy_from_user(page, buff, len)) {
  159.         printk(KERN_ALERT"Failed to copy buff from user.\n");
  160.         err = -EFAULT;
  161.         goto out;
  162.     }

  163.     err = __senrsl_set_val(senrsl_dev, page, len);

  164. out:
  165.     free_page((unsigned long)page);
  166.     return err;
  167. }

  168. /*创建/proc/senrsl文件*/
  169. static void senrsl_create_proc(void) {
  170.     struct proc_dir_entry* entry;
  171.     
  172.     entry = create_proc_entry(SENRSL_DEVICE_PROC_NAME, 0, NULL);
  173.     if(entry) {
  174.         //drivers/senrsl/senrsl.c:220:8: error: 'struct proc_dir_entry' has no member named 'owner'
  175.         //这个结构成员更新 为:pde_users
  176.         entry->pde_users = THIS_MODULE;
  177.         entry->read_proc = senrsl_proc_read;
  178.         entry->write_proc = senrsl_proc_write;
  179.     }
  180. }

  181. /*删除/proc/senrsl文件*/
  182. static void senrsl_remove_proc(void) {
  183.     remove_proc_entry(SENRSL_DEVICE_PROC_NAME, NULL);
  184. }

  185. /**************最后,定义 模块加载和卸载方法,这里只要是执行设备注册和初始化操作*****************/
  186. /*初始化设备*/
  187. static int __senrsl_setup_dev(struct senrsl_android_dev* dev) {
  188.     int err;
  189.     dev_t devno = MKDEV(senrsl_major, senrsl_minor);

  190.     memset(dev, 0, sizeof(struct senrsl_android_dev));

  191.     cdev_init(&(dev->dev), &senrsl_fops);
  192.     dev->dev.owner = THIS_MODULE;
  193.     dev->dev.ops = &senrsl_fops;

  194.     /*注册字符设备*/
  195.     err = cdev_add(&(dev->dev),devno, 1);
  196.     if(err) {
  197.         return err;
  198.     }

  199.     /*初始化信号量和寄存器val的值*/
  200.     //drivers/senrsl/senrsl.c:252:2: error: implicit declaration of function 'init_MUTEX' [-Werror=implicit-function-declaration]
  201.     //init_MUTEX(&(dev->sem));
  202.     sema_init((&dev->sem),1);
  203.     dev->val = 0;

  204.     return 0;
  205. }

  206. /*模块加载方法*/
  207. static int __init senrsl_init(void){
  208.     int err = -1;
  209.     dev_t dev = 0;
  210.     struct device* temp = NULL;

  211.     printk(KERN_ALERT"Initializing senrsl device.\n");

  212.     /*动态分配主设备和从设备号*/
  213.     err = alloc_chrdev_region(&dev, 0, 1, SENRSL_DEVICE_NODE_NAME);
  214.     if(err < 0) {
  215.         printk(KERN_ALERT"Failed to alloc char dev region.\n");
  216.         goto fail;
  217.     }

  218.     senrsl_major = MAJOR(dev);
  219.     senrsl_minor = MINOR(dev);

  220.     /*分配helo设备结构体变量*/
  221.     senrsl_dev = kmalloc(sizeof(struct senrsl_android_dev), GFP_KERNEL);
  222.     if(!senrsl_dev) {
  223.         err = -ENOMEM;
  224.         printk(KERN_ALERT"Failed to alloc senrsl_dev.\n");
  225.         goto unregister;
  226.     }

  227.     /*初始化设备*/
  228.     err = __senrsl_setup_dev(senrsl_dev);
  229.     if(err) {
  230.         printk(KERN_ALERT"Failed to setup dev: %d.\n", err);
  231.         goto cleanup;
  232.     }

  233.     /*在/sys/class/目录下创建设 备类别目录senrsl*/
  234.     senrsl_class = class_create(THIS_MODULE, SENRSL_DEVICE_CLASS_NAME);
  235.     if(IS_ERR(senrsl_class)) {
  236.         err = PTR_ERR(senrsl_class);
  237.         printk(KERN_ALERT"Failed to create senrsl class.\n");
  238.         goto destroy_cdev;
  239.     }

  240.     /*在/dev/目录和/sys /class/senrsl目录下分别创建设备文件senrsl*/
  241.     temp = device_create(senrsl_class, NULL, dev, "%s", SENRSL_DEVICE_FILE_NAME);
  242.     if(IS_ERR(temp)) {
  243.         err = PTR_ERR(temp);
  244.         printk(KERN_ALERT"Failed to create senrsl device.");
  245.         goto destroy_class;
  246.     }

  247.     /*在/sys/class/senrsl /senrsl目录下创建属性文件val*/
  248.     err = device_create_file(temp, &dev_attr_val);
  249.     if(err < 0) {
  250.         printk(KERN_ALERT"Failed to create attribute val.");
  251.         goto destroy_device;
  252.     }

  253.     dev_set_drvdata(temp, senrsl_dev);

  254.     /*创建/proc/senrsl文件*/
  255.     senrsl_create_proc();

  256.     printk(KERN_ALERT"Succedded to initialize senrsl device.\n");
  257.     return 0;

  258. destroy_device:
  259.     device_destroy(senrsl_class, dev);

  260. destroy_class:
  261.     class_destroy(senrsl_class);

  262. destroy_cdev:
  263.     cdev_del(&(senrsl_dev->dev));

  264. cleanup:
  265.     kfree(senrsl_dev);

  266. unregister:
  267.     unregister_chrdev_region(MKDEV(senrsl_major, senrsl_minor), 1);

  268. fail:
  269.     return err;
  270. }

  271. /*模块卸载方法*/
  272. static void __exit senrsl_exit(void) {
  273.     dev_t devno = MKDEV(senrsl_major, senrsl_minor);

  274.     printk(KERN_ALERT"Destroy senrsl device.\n");

  275.     /*删除/proc/senrsl文件*/
  276.     senrsl_remove_proc();

  277.     /*销毁设备类别和设备*/
  278.     if(senrsl_class) {
  279.         device_destroy(senrsl_class, MKDEV(senrsl_major, senrsl_minor));
  280.         class_destroy(senrsl_class);
  281.     }

  282.     /*删除字符设备和释放设备内存*/
  283.     if(senrsl_dev) {
  284.         cdev_del(&(senrsl_dev->dev));
  285.         kfree(senrsl_dev);
  286.     }

  287.     /*释放设备号*/
  288.     unregister_chrdev_region(devno, 1);
  289. }

  290. MODULE_LICENSE("GPL");
  291. MODULE_DESCRIPTION("First Android Driver");

  292. module_init(senrsl_init);
  293. module_exit(senrsl_exit);


3)Kconfig
  1. config SENRSL
  2. tristate "First Android Driver With senRsl"
  3. default n
  4. help
  5. This is the first android driver whit me.


4)Makefile
  1. obj-$(CONFIG_SENRSL) += senrsl.o
  2. #在Kconfig文件 中,tristate表示编译选项HELLO支持在编译内核时,senrsl模块支持以模块、内建和不编译三种编译方法,默认是不编译, 因此,#在编译内核前,我们还需要执行make menuconfig命令来配置编译选项,使得senrsl可以以模块或者内建的方法进行编译。
  3. # 在Makefile文件 中,根据选项senrsl的值,执行不同的编译方法。

③配置编译选项
修改当前目录下总署的Kconfig和Makefile配置,加上新建的。
目录:/home/senrsl/android/source/kernel/goldfish/drivers
1)Kconfig 最后面加上
  1. menu "Device Drivers"
  2. 这中间有好多
  3. source "drivers/virt/Kconfig"

  4. source "drivers/devfreq/Kconfig"

  5. source "drivers/senrsl/Kconfig"

  6. endmenu

2)Makefile拉到最下面加上
  1. # Virtualization drivers
  2. obj-$(CONFIG_VIRT_DRIVERS)    += virt/
  3. obj-$(CONFIG_HYPERV)        += hv/

  4. obj-$(CONFIG_SENRSL)        += senrsl/

  5. obj-$(CONFIG_PM_DEVFREQ)    += devfreq/

④配置编译
1)配置编译时选项加上
启动图形化配置
  1. senrsl@senrsl-ubuntu:~/android/source/kernel/goldfish$ make menuconfig
Devices Drivers--->First Android Driver With senrsl,按Y选择,保存退出


2)执行编译
  1. senrsl@senrsl-ubuntu:~/android/source/kernel/goldfish$ make
  2. 。。。。。
  3. OBJCOPY arch/arm/boot/zImage
  4. Kernel: arch/arm/boot/zImage is ready

⑤启动验证
使用这个内核启动模拟器
  1. senrsl@senrsl-ubuntu:~/android/source/WORKING_DIRECTORY$ emulator -kernel /home/senrsl/android/source/kernel/goldfish/arch/arm/boot/zImage
验证
  1. senrsl@senrsl-ubuntu:~$ adb shell
  2. root@generic:/ # cd dev/
  3. root@generic:/dev # ls | grep s
  4. __properties__
  5. ashmem
  6. console
  7. fscklogs
  8. fuse
  9. graphics
  10. kmsg
  11. psaux
  12. pts
  13. senrsl
  14. socket
  15. vcs
  16. vcs1
  17. vcsa
  18. vcsa1
  19. root@generic:/dev # cd ..
  20. root@generic:/ # cd proc
  21. root@generic:/proc # ls | grep s
  22. bus
  23. cgroups
  24. consoles
  25. devices
  26. diskstats
  27. dma-mappings
  28. execdomains
  29. filesystems
  30. fs
  31. interrupts
  32. ioports
  33. kallsyms
  34. kmsg
  35. kpageflags
  36. locks
  37. misc
  38. mounts
  39. partitions
  40. sched_debug
  41. schedstat
  42. self
  43. senrsl
  44. slabinfo
  45. softirqs
  46. stat
  47. swaps
  48. sys
  49. sysrq-trigger
  50. sysvipc
  51. timer_list
  52. version
  53. vmstat
  54. yaffs
  55. root@generic:/proc # cat senrsl
  56. 0
  57. root@generic:/proc # echo '5'>senrsl
  58. root@generic:/proc # cat senrsl
  59. 5
  60. root@generic:/proc/sys # cd ..
  61. root@generic:/proc # cd ..
  62. root@generic:/ # cd sy
  63. sys/ system/
  64. root@generic:/ # cd sys/class/
  65. root@generic:/sys/class # ll
  66. drwxr-xr-x root root 2015-04-09 23:18 bdi
  67. drwxr-xr-x root root 2015-04-09 23:18 block
  68. drwxr-xr-x root root 2015-04-09 23:18 firmware
  69. drwxr-xr-x root root 2015-04-09 23:18 graphics
  70. drwxr-xr-x root root 2015-04-09 23:18 input
  71. drwxr-xr-x root root 2015-04-09 23:18 mem
  72. drwxr-xr-x root root 2015-04-09 23:18 misc
  73. drwxr-xr-x root root 2015-04-09 23:18 mmc_host
  74. drwxr-xr-x root root 2015-04-09 23:18 mtd
  75. drwxr-xr-x root root 2015-04-09 23:18 net
  76. drwxr-xr-x root root 2015-04-09 23:18 power_supply
  77. drwxr-xr-x root root 2015-04-09 23:18 rtc
  78. drwxr-xr-x root root 2015-04-09 23:18 senrsl
  79. drwxr-xr-x root root 2015-04-09 23:18 switch
  80. drwxr-xr-x root root 2015-04-09 23:18 timed_output
  81. drwxr-xr-x root root 2015-04-09 23:18 tty
  82. drwxr-xr-x root root 2015-04-09 23:18 vc
  83. drwxr-xr-x root root 2015-04-09 23:18 vtconsole
  84. drwxr-xr-x root root 2015-04-09 23:18 xt_idletimer
  85. root@generic:/sys/class # cd senrsl/
  86. root@generic:/sys/class/senrsl # ll
  87. lrwxrwxrwx root root 2015-04-09 23:18 senrsl -> ../../devices/virtual/senrsl/senrsl
  88. root@generic:/sys/class/senrsl # cd senrsl/
  89. root@generic:/sys/class/senrsl/senrsl # ll
  90. -r--r--r-- root root 4096 2015-04-09 23:18 dev
  91. drwxr-xr-x root root 2015-04-09 23:18 power
  92. lrwxrwxrwx root root 2015-04-09 23:18 subsystem -> ../../../../class/senrsl
  93. -rw-r--r-- root root 4096 2015-04-09 23:18 uevent
  94. -rw-r--r-- root root 4096 2015-04-09 23:18 val
  95. root@generic:/sys/class/senrsl/senrsl # cat val
  96. 5
  97. root@generic:/sys/class/senrsl/senrsl # echo '0' > val
  98. root@generic:/sys/class/senrsl/senrsl # cat val
  99. 0
  100. root@generic:/sys/class/senrsl/senrsl #

搞定!
2015年04月10日13:27:59

--
senRsl
2015年04月08日15:45:13

没有评论 :

发表评论