自己动手 从android硬件驱动到APP---(1)硬件驱动层
2019獨角獸企業重金招聘Python工程師標準>>>
1:
joe@joe-Aspire-Z3730:~$ cd /media/sdb4/aosp/kernel/goldfish/drivers/2:
joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish/drivers$ mkdir hello3:在hello 目錄中增加hello.h 文件 參考 Android驅動開發全過程(有圖有真相)的hello.h
#ifndef _HELLO_Android_H_ #define _HELLO_ANDROID_H_ #include <linux/cdev.h> #include <linux/semaphore.h> #define HELLO_DEVICE_NODE_NAME "hello" #define HELLO_DEVICE_FILE_NAME "hello" #define HELLO_DEVICE_PROC_NAME "hello" #define HELLO_DEVICE_CLASS_NAME "hello" struct hello_android_dev {int val;struct semaphore sem;struct cdev dev; }; #endif4:在hello 目錄中增加hello.c 文件 參考 https://blog.csdn.net/eliot_shao/article/details/51864811 帖子中的鏈接 http://blog.csdn.net/eliot_shao/article/details/51860229
也參考了 https://blog.csdn.net/brantyou/article/details/8651385
/** hello.c -- A simple virtual char device driver*/ #include <linux/module.h> #include <linux/types.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/mm.h> #include <linux/sched.h> #include <linux/init.h> #include <linux/cdev.h> #include <linux/slab.h> #include <asm/io.h> #include <linux/device.h> #include <asm/uaccess.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("eliot shao");#define DEVICE_SUM 1static int hello_open(struct inode *inode, struct file *filp); static int hello_release(struct inode *, struct file *filp); static ssize_t hello_read(struct file*, char*, size_t, loff_t*); static ssize_t hello_write(struct file*, const char*, size_t, loff_t*);/* the major device number */ static int hello_major = 0; static int hello_minor = 0;static struct class* hello_class = NULL;/* init the file_operations structure */ struct file_operations hello_fops = {.owner = THIS_MODULE,.open = hello_open,.release = hello_release,.read = hello_read,.write = hello_write, };/* define a cdev device */ struct cdev *cdev;static int global_var = 0; /* global var *//* module init */ static int __init hello_init(void) {int ret = 0;struct device* temp = NULL;dev_t devno = 0;printk("hello:hello_init .\n");/*動態分配主設備和從設備號*/ret = alloc_chrdev_region(&devno, hello_minor, DEVICE_SUM, "hello");if(ret < 0) {printk(KERN_ALERT"hello:Failed to alloc char dev region.\n");goto fail;}hello_major = MAJOR(devno);hello_minor = MINOR(devno);cdev = cdev_alloc();cdev->owner = THIS_MODULE;cdev->ops = &hello_fops;if ((ret = cdev_add(cdev, devno, 1))){printk(KERN_NOTICE "hello:Error %d adding hello.\n", ret);return 0;}elseprintk("hello:hello register success.\n");/*在/sys/class/目錄下創建設備類別目錄hello*/hello_class = class_create(THIS_MODULE, "hello");if(IS_ERR(hello_class)) {ret = PTR_ERR(hello_class);printk(KERN_ALERT"Failed to create hello class.\n");goto destroy_cdev;} /*在/dev/目錄和/sys/class/hello目錄下分別創建設備文件hello*/temp = device_create(hello_class, NULL, devno, "%s", "hello");if(IS_ERR(temp)) {ret = PTR_ERR(temp);printk(KERN_ALERT"Failed to create hello device.");goto destroy_class;} return ret; destroy_class:class_destroy(hello_class); destroy_cdev:cdev_del(cdev); fail:return ret; }/* module exit */ static void __exit hello_exit(void) {dev_t devno = MKDEV(hello_major, 0);/* remove cdev from kernel */cdev_del(cdev);/* unregister the device driver */unregister_chrdev_region(devno, 1);/* free the dev structure */if(cdev)kfree(cdev);cdev = NULL; }/* open device */ static int hello_open(struct inode *inode, struct file *filp) {int ret = 0;printk("KERNEL:open success.\n");return ret; }/* release device */ static int hello_release(struct inode *inode, struct file *filp) {printk("KERNEL:release success.\n");return 0; }/* read device */ static ssize_t hello_read(struct file *filp, char *buf, size_t len, loff_t *off) {printk("KERNEL:reading...\n");if(copy_to_user(buf, &global_var, sizeof(int))){return -EFAULT;}return sizeof(int); }/* write device */ static ssize_t hello_write(struct file *filp, const char *buf, size_t len, loff_t *off) {printk("KERNEL:writing...\n");if(copy_from_user(&global_var, buf, sizeof(int))){return -EFAULT;}return sizeof(int); }/* module register */ module_init(hello_init); module_exit(hello_exit);5:/media/sdb4/aosp/kernel/goldfish/drivers目錄下的Makefile中增加一行:
obj-$(CONFIG_HELLO) += hello/6:/media/sdb4/aosp/kernel/goldfish/drivers目錄下的Kconfig中增加一行(注意位置):
menu "Device Drivers" 。。。。。 source "drivers/hello/Kconfig" 。。。 endmenu7:/media/sdb4/aosp/kernel/goldfish/drivers/hello目錄下增加Makefile文件,內容為:
obj-$(CONFIG_HELLO) += hello.o8:/media/sdb4/aosp/kernel/goldfish/drivers/hello目錄下增加Kconfig文件,內容為
config HELLO tristate "First Android Driver" default n help This is first Android Deiver for demo9:
joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish$ export CROSS_COMPILE=arm-eabi- joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish$ export ARCH=arm joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish$ export SUBARCH=arm10:
joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish$ make goldfish_armv7_defconfig# # configuration written to .config ##### make completed successfully (7 seconds) ####11:
joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish$ make scripts/kconfig/conf --silentoldconfig KconfigCHK include/linux/version.hCHK include/generated/utsrelease.h make[1]: `include/generated/mach-types.h' is up to date.CALL scripts/checksyscalls.shCHK include/generated/compile.hGZIP kernel/config_data.gzCHK kernel/config_data.hUPD kernel/config_data.hCC kernel/configs.oLD kernel/built-in.oLD vmlinux.oMODPOST vmlinux.oGEN .versionCHK include/generated/compile.hUPD include/generated/compile.hCC init/version.oLD init/built-in.oLD .tmp_vmlinux1KSYM .tmp_kallsyms1.SAS .tmp_kallsyms1.oLD .tmp_vmlinux2KSYM .tmp_kallsyms2.SAS .tmp_kallsyms2.oLD vmlinuxSYSMAP System.mapSYSMAP .tmp_System.mapOBJCOPY arch/arm/boot/ImageKernel: arch/arm/boot/Image is readyGZIP arch/arm/boot/compressed/piggy.gzipAS arch/arm/boot/compressed/piggy.gzip.oLD arch/arm/boot/compressed/vmlinuxOBJCOPY arch/arm/boot/zImageKernel: arch/arm/boot/zImage is ready#### make completed successfully (29 seconds) #### 總感覺不可能有這么快的編譯速度?????12:重新進到aosp目錄
joe@joe-Aspire-Z3730:/media/sdb4/aosp$ emulator -kernel ./kernel/goldfish/arch/arm/boot/zImage13:雖然用新的內核啟動了模擬器,但我在/media/sdb4/aosp/kernel/goldfish/drivers/hello目錄中沒有看到 hello.o文件
14:在/dev和/proc中都沒有看到hello設備
joe@joe-Aspire-Z3730:/media/sdb4/aosp$ adb shell root@generic:/ # cd dev root@generic:/dev # ls __properties__ ashmem binder block console cpu_dma_latency cpuctl device-mapper eac fscklogs full fuse graphics input kmem kmsg loop-control mem memcg mtd network_latency network_throughput null psaux ptmx pts qemu_pipe random rtc0 socket tty tty0 tty1 tty10 tty11 tty12 tty13 tty14 tty15 tty16 tty17 tty18 tty19 tty2 tty20 tty21 tty22 tty23 tty24 tty25 tty26 tty27 tty28 tty29 tty3 tty30 tty31 tty32 tty33 tty34 tty35 tty36 tty37 tty38 tty39 tty4 tty40 tty41 tty42 tty43 tty44 tty45 tty46 tty47 tty48 tty49 tty5 tty50 tty51 tty52 tty53 tty54 tty55 tty56 tty57 tty58 tty59 tty6 tty60 tty61 tty62 tty63 tty7 tty8 tty9 ttyS0 ttyS1 ttyS2 tun urandom vcs vcs1 vcsa vcsa1 xt_qtaguid zero root@generic:/dev # cd /proc root@generic:/proc # ls 1 10 1013 1030 1061 1081 1098 11 1125 1162 1178 1186 12 13 139 14 2 25 26 27 28 29 3 30 31 33 337 34 37 39 40 43 447 45 46 47 48 49 5 50 51 52 54 57 58 587 59 6 60 61 62 63 64 646 65 66 663 682 7 709 73 739 783 8 822 839 897 9 923 940 963 995 buddyinfo bus cgroups cmdline config.gz consoles cpu cpuinfo crypto devices diskstats dma-mappings driver execdomains fb filesystems fs interrupts iomem ioports irq kallsyms kmsg kpagecount kpageflags loadavg locks meminfo misc mounts mtd net pagetypeinfo partitions sched_debug schedstat self slabinfo softirqs stat swaps sys sysrq-trigger sysvipc timer_list tty uptime version vmallocinfo vmstat yaffs zoneinfo15:/media/sdb4/aosp/kernel/goldfish/drivers/hello目錄下修改Kconfig文件
config HELLO tristate "First Android Driver" default m help This is first Android Deiver for demo16:重新執行第10和第11步,然后發現hello目錄中出現了hello.o文件,說明驅動程序編譯了
17:
joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish$ cd ../.. joe@joe-Aspire-Z3730:/media/sdb4/aosp$ emulator -kernel ./kernel/goldfish/arch/arm/boot/zImage &18:參考 android-----模擬器加載自己編譯的內核(適用于驅動練習)https://blog.csdn.net/yf210yf/article/details/9901375 不成功。主要是因為權限問題,所以修改hello目錄下的Kconfig,將驅動程序直接編譯進內核中
config HELLO tristate "First Android Driver" default y help This is first Android Deiver for demo19:重新執行第10和第11步
20:
joe@joe-Aspire-Z3730:/media/sdb4/aosp$ emulator -kernel ./kernel/goldfish/arch/arm/boot/zImage &21:參考 https://blog.csdn.net/brantyou/article/details/8651385
joe@joe-Aspire-Z3730:/media/sdb4/aosp$ adb shell root@generic:/ # cd dev root@generic:/dev # ls 其中就出現了hello,但/proc目錄中卻沒有hello22:下面的帖子中說明了如何在android源碼中寫應用層程序測試hello驅動
https://blog.csdn.net/lzpdz/article/details/5056236623:按照22中所說,先進入源碼的external目錄,然后:
joe@joe-Aspire-Z3730:/media/sdb4/aosp/external$ mkdir hello joe@joe-Aspire-Z3730:/media/sdb4/aosp/external$ cd hello joe@joe-Aspire-Z3730:/media/sdb4/aosp/external/hello$ gedit hello.c#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #define DEVICE_NAME "/dev/hello" int main(int argc, char** argv) { int fd = -1; int val = 0; fd = open(DEVICE_NAME, O_RDWR); if(fd == -1) { printf("Failed to open device %s.\n", DEVICE_NAME); return -1; } printf("Read original value:\n"); read(fd, &val, sizeof(val)); printf("%d.\n\n", val); val = 5; printf("Write value %d to %s.\n\n", val, DEVICE_NAME); write(fd, &val, sizeof(val)); printf("Read the value again:\n"); read(fd, &val, sizeof(val)); printf("%d.\n\n", val); close(fd); return 0; }24:在hello目錄中增加Android.mk
joe@joe-Aspire-Z3730:/media/sdb4/aosp/external/hello$ gedit Android.mkLOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_MODULE := hello LOCAL_SRC_FILES := $(call all-subdir-c-files) include $(BUILD_EXECUTABLE)25:在hello目錄中編譯模塊
joe@joe-Aspire-Z3730:/media/sdb4/aosp/external/hello$ mm ============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=5.1.1 TARGET_PRODUCT=aosp_arm TARGET_BUILD_VARIANT=eng TARGET_BUILD_TYPE=release TARGET_BUILD_APPS= TARGET_ARCH=arm TARGET_ARCH_VARIANT=armv7-a TARGET_CPU_VARIANT=generic TARGET_2ND_ARCH= TARGET_2ND_ARCH_VARIANT= TARGET_2ND_CPU_VARIANT= HOST_ARCH=x86_64 HOST_OS=linux HOST_OS_EXTRA=Linux-3.11.0-15-generic-x86_64-with-Ubuntu-12.04-precise HOST_BUILD_TYPE=release BUILD_ID=LMY47Z OUT_DIR=out ============================================ make: Entering directory `/media/46bb100d-2505-4025-8425-34ecf3129209/aosp' Import includes file: out/target/product/generic/obj/EXECUTABLES/hello_intermediates/import_includes target thumb C: hello <= external/hello/hello.c external/hello/hello.c: In function 'main': external/hello/hello.c:5:14: warning: unused parameter 'argc' [-Wunused-parameter]int main(int argc, char** argv) ^ external/hello/hello.c:5:27: warning: unused parameter 'argv' [-Wunused-parameter]int main(int argc, char** argv) ^ target Executable: hello (out/target/product/generic/obj/EXECUTABLES/hello_intermediates/LINKED/hello) target Symbolic: hello (out/target/product/generic/symbols/system/bin/hello) Export includes file: external/hello/Android.mk -- out/target/product/generic/obj/EXECUTABLES/hello_intermediates/export_includes target Strip: hello (out/target/product/generic/obj/EXECUTABLES/hello_intermediates/hello) Install: out/target/product/generic/system/bin/hello make: Leaving directory `/media/46bb100d-2505-4025-8425-34ecf3129209/aosp'#### make completed successfully (4 seconds) ####26:重新打包Android系統文件system.img:
joe@joe-Aspire-Z3730:/media/sdb4/aosp$ make snod ============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=5.1.1 TARGET_PRODUCT=aosp_arm TARGET_BUILD_VARIANT=eng TARGET_BUILD_TYPE=release TARGET_BUILD_APPS= TARGET_ARCH=arm TARGET_ARCH_VARIANT=armv7-a TARGET_CPU_VARIANT=generic TARGET_2ND_ARCH= TARGET_2ND_ARCH_VARIANT= TARGET_2ND_CPU_VARIANT= HOST_ARCH=x86_64 HOST_OS=linux HOST_OS_EXTRA=Linux-3.11.0-15-generic-x86_64-with-Ubuntu-12.04-precise HOST_BUILD_TYPE=release BUILD_ID=LMY47Z OUT_DIR=out ============================================ build/core/Makefile:1013: Warning: with dexpreopt enabled, you may need a full rebuild. make snod: ignoring dependencies Target system fs image: out/target/product/generic/system.img Running: mkuserimg.sh out/target/product/generic/system out/target/product/generic/system.img ext4 system 576716800 out/target/product/generic/root/file_contexts make_ext4fs -T -1 -S out/target/product/generic/root/file_contexts -l 576716800 -a system out/target/product/generic/system.img out/target/product/generic/system Creating filesystem with parameters:Size: 576716800Block size: 4096Blocks per group: 32768Inodes per group: 7040Inode size: 256Journal blocks: 2200Label: Blocks: 140800Block groups: 5Reserved block group size: 39 Created filesystem with 1468/35200 inodes and 109538/140800 blocks out/target/product/generic/system.img maxsize=588791808 blocksize=2112 total=576716800 reserve=5947392#### make completed successfully (19 seconds) ####27:重新啟動模擬器
joe@joe-Aspire-Z3730:/media/sdb4/aosp$ emulator -kernel ./kernel/goldfish/arch/arm/boot/zImage -system out/target/product/generic/system.img28:通過adb shell測試應用程序hello
root@generic:/system/bin # ls -rwxr-xr-x root shell 5356 2018-04-25 16:29 hello29:通過下面的測試,說明我們寫的hello驅動程序和hello應用程序都成功運行了。
root@generic:/system/bin # hello Read original value: 0.Write value 5 to /dev/hello.Read the value again: 5.root@generic:/system/bin # hello //注意這次執行命令與第一次執行的結果 Read original value: 5.Write value 5 to /dev/hello.Read the value again: 5. 默認只有root 用戶可讀寫,而hello_device_open 一般是由上層APP 來調用的,這些APP 一般不具有root 權限,這時候就 導致打開設備文件失敗: Hello Stub: failed to open /dev/hello -- Permission denied. 解決辦法是類似于Linux 的udev 規則,打開Android 源代碼工程目錄下,進入到system/core/rootdir 目錄,里面有一個名為 uevent.rc 文件,往里面添加一行: /dev/hello 0666 root root備注說明:參考 Android驅動開發全過程(有圖有真相)中對此權限操作方面的說明手機未root 查看data/data/某一app文件信息 筆者的小米3沒有root,但是又想方便地查看data/data/目錄下的一些文件,直接進入data會提示沒有權限,查看的方式為進入data/data/后,運行下面的命令,就能直接進入你應用的包下了,可通用cp或者mv拷貝或移動到sdcard目錄進行其他操作
run-as package_name
轉載于:https://my.oschina.net/u/2963604/blog/1784981
總結
以上是生活随笔為你收集整理的自己动手 从android硬件驱动到APP---(1)硬件驱动层的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: React-Native入门(1)-项目
- 下一篇: apt-get could not g