自己动手 从android硬件驱动到APP---(1)硬件驱动层

1:

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

2:

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

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

4:在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 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中增加一行:

obj-$(CONFIG_HELLO)		+= hello/

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

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

7:/media/sdb4/aosp/kernel/goldfish/drivers/hello目录下增加Makefile文件,内容为:

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:

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:参考 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目录中却没有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

转载于:https://my.oschina.net/u/2963604/blog/1784981

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值