本身動手 從android硬件驅動到APP---(1)硬件驅動層

1:node

joe@joe-Aspire-Z3730:~$ cd /media/sdb4/aosp/kernel/goldfish/drivers/

2:linux

joe@joe-Aspire-Z3730:/media/sdb4/aosp/kernel/goldfish/drivers$ mkdir hello

3:在hello 目錄中增長hello.h 文件 參考 Android驅動開發全過程(有圖有真相)的hello.handroid

#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;
};
#endif

4:在hello 目錄中增長hello.c 文件 參考 https://blog.csdn.net/eliot_shao/article/details/51864811 帖子中的連接 http://blog.csdn.net/eliot_shao/article/details/51860229shell

也參考了 http://www.javashuo.com/article/p-gisynhty-bk.htmlapp

/*
 * 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 1

static 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;
        }
        else
            printk("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中增長一行:dom

obj-$(CONFIG_HELLO)		+= hello/

6:/media/sdb4/aosp/kernel/goldfish/drivers目錄下的Kconfig中增長一行(注意位置):socket

menu "Device Drivers"
。。。。。
source "drivers/hello/Kconfig"
。。。
endmenu

7:/media/sdb4/aosp/kernel/goldfish/drivers/hello目錄下增長Makefile文件,內容爲:oop

obj-$(CONFIG_HELLO)	+= hello.o

8:/media/sdb4/aosp/kernel/goldfish/drivers/hello目錄下增長Kconfig文件,內容爲測試

config HELLO
tristate "First Android Driver"
default n
help
This is first Android Deiver for demo

9:ui

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=arm

10:

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 Kconfig
  CHK     include/linux/version.h
  CHK     include/generated/utsrelease.h
make[1]: `include/generated/mach-types.h' is up to date.
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  GZIP    kernel/config_data.gz
  CHK     kernel/config_data.h
  UPD     kernel/config_data.h
  CC      kernel/configs.o
  LD      kernel/built-in.o
  LD      vmlinux.o
  MODPOST vmlinux.o
  GEN     .version
  CHK     include/generated/compile.h
  UPD     include/generated/compile.h
  CC      init/version.o
  LD      init/built-in.o
  LD      .tmp_vmlinux1
  KSYM    .tmp_kallsyms1.S
  AS      .tmp_kallsyms1.o
  LD      .tmp_vmlinux2
  KSYM    .tmp_kallsyms2.S
  AS      .tmp_kallsyms2.o
  LD      vmlinux
  SYSMAP  System.map
  SYSMAP  .tmp_System.map
  OBJCOPY arch/arm/boot/Image
  Kernel: arch/arm/boot/Image is ready
  GZIP    arch/arm/boot/compressed/piggy.gzip
  AS      arch/arm/boot/compressed/piggy.gzip.o
  LD      arch/arm/boot/compressed/vmlinux
  OBJCOPY arch/arm/boot/zImage
  Kernel: 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/zImage

13:雖然用新的內核啓動了模擬器,但我在/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
zoneinfo

15:/media/sdb4/aosp/kernel/goldfish/drivers/hello目錄下修改Kconfig文件

config HELLO
tristate "First Android Driver"
default m
help
This is first Android Deiver for demo

16:從新執行第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 demo

19:從新執行第10和第11步

20:

joe@joe-Aspire-Z3730:/media/sdb4/aosp$  emulator -kernel ./kernel/goldfish/arch/arm/boot/zImage &

21:參考 http://www.javashuo.com/article/p-gisynhty-bk.html

joe@joe-Aspire-Z3730:/media/sdb4/aosp$ adb shell
root@generic:/ # cd dev
root@generic:/dev # ls
其中就出現了hello,但/proc目錄中卻沒有hello

22:下面的帖子中說明了如何在android源碼中寫應用層程序測試hello驅動

https://blog.csdn.net/lzpdz/article/details/50562366

23:按照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.mk

LOCAL_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: 576716800
    Block size: 4096
    Blocks per group: 32768
    Inodes per group: 7040
    Inode size: 256
    Journal blocks: 2200
    Label: 
    Blocks: 140800
    Block groups: 5
    Reserved 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.img

28:經過adb shell測試應用程序hello

root@generic:/system/bin # ls
-rwxr-xr-x root     shell        5356 2018-04-25 16:29 hello

29:經過下面的測試,說明咱們寫的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

相關文章
相關標籤/搜索