当前位置: 代码迷 >> Android >> Android 驱动跟系统开发 1. 一个简单的例子(原创)
  详细解决方案

Android 驱动跟系统开发 1. 一个简单的例子(原创)

热度:77   发布时间:2016-05-01 18:09:35.0
Android 驱动和系统开发 1. 一个简单的例子(原创)

首先,边学习边记录点自己的代码,希望看了我写的代码觉得不怎么样的,多多提出来,让我也学习学习,我一定会虚心接受大家的指导。

这里我们是来学习android 驱动和android系统框架的,这里我只针对于整个android设备驱动的一个流程,从上到下的调用,而且在这里我们去使用android源码环境,原因是我使用的电脑比较破,编译android会挂,而且android BSP太大了,git下来很麻烦,所以这里我只是选用了ubuntu的环境来学习android 底层和系统层的开发,那么有人会问,没有源代码,如何去学习呢,又如何来演示出来呢?不急,慢慢道来,首先还是来谈一下android的底层和系统层,下图供参考,基本每个设计android的工程师都知道这张图


android使用的是Linux 内核,虽然说稍微改了点东西,增加了些移动嵌入式设备的特性,比如说early suspend、进程间通信(bind)、特有的log机制(logcat)等,但是Linux主流的一些东西都没有改变,所以,这里我们还是使用Linux下得驱动作为底层来学习,具体的android的特性,之后的博客中会做深入。

Linux内核驱动之上应该是android的HAL层,也就是传说中得硬件抽象层,我把这玩意一直理解成是Linux 应用层,虽然,有的厂家的代码写的比较庞大,比较好得还是使用C++的类来封装,典型的设备是传感器模块,一般都会有一个HAL层来衔接,这里我们使用Linux 的应用层编程 c/c++来实现调用驱动来收发数据等操作。

在上面应该是JNI层啦,在我们的学习中,JNI的基础知识在我的另外一个博客专栏中有提到,在这里我们也是使用JNI来实现接口。

然后是framework,我们还是使用java代码封装JNI,然后写一些java的测试代码,当然了,没有android的UI,对于java的UI编程,我也是没玩过,对于java我只是一个初学者,写测试代码还凑合,一般都是一边google一边写的 ^0^

接下来就开始行动吧,首先是我们的驱动部分,这些代码都是我自己写的,所以难免会有很多写的不对的地方,希望大家觉得我哪边写的不好的多提些意见,毕竟我也只是一个小菜鸟。

这个驱动完成的主要任务是从内核空间向用户空间发送一个坐标信息(模拟鼠标的动作),当然了,我们的驱动是虚拟的,当然不会主动的向用户空间poll数据,所以,我们要先自己往文件系统中写数据,然后驱动会通过input 子系统向user space发送数据。

下面是我驱动的一个结构图,一般我写个驱动都会先考虑很多,然后再着手去做,三思而后行嘛,驱动的整体架构如果出了问题,到最后是很难再修正的,只有重新写。


可以看到,我们的思路很清晰,初始化的时候开一个线程,注意这个线程是一个死循环,但是在循环当中有一个试图获得信号量的动作,如果得不到,就会进入休眠,如下是thread的代码:


唤醒这个线程的地方,就是调用up的地方:


可以看到,这个write_position是被注册当position文件被执行写操作的时候执行的。

相信看了结构图就知道我们的代码是如何写的吧,这个驱动比较简单,看下完整的代码


下面是Makefile


然后我们来编译模块再加载

# make

# insmod virtualtouch.ko

然后看下我们生成的文件系统

[email protected]:/sys/devices/platform/virtual-touch# pwd
/sys/devices/platform/virtual-touch
[email protected]:/sys/devices/platform/virtual-touch# tree
.
├── bcolor
├── color
├── modalias
├── position
├── power
│   ├── async
│   ├── autosuspend_delay_ms
│   ├── control
│   ├── runtime_active_kids
│   ├── runtime_active_time
│   ├── runtime_enabled
│   ├── runtime_status
│   ├── runtime_suspended_time
│   └── runtime_usage
├── subsystem -> ../../../bus/platform
└── uevent


2 directories, 14 files

还有我们的input subsystem的文件系统,使用dmesg查看

[  413.650710] input: virtual-touch as /devices/virtual/input/input6
[  413.662695] virtual touch device probe successful.
[  413.663616] work thread running!!

按照log可以知道,我们生成的event6

[email protected]:/dev/input# pwd
/dev/input
[email protected]:/dev/input# ls -l event6 
crw-r----- 1 root root 13, 70 Jul  2 22:07 event6

OK,了解了我们生成的文件系统之后,我们写一个测试程序来测试下,嘿嘿 ^0^

贴代码如下:


这个。。。这个小测试程序就不多说了,open  ---->  read  ---->  show

测试程序的编写一般是参考驱动中report出去的到底是什么类型的数据。

# gcc main -o virtual-touch.c

[email protected]:/home/jay/workspace/virtual/main# ./main 
open done!

read!


这个时候被阻塞在read函数这边,因为没有数据被读出,所以会阻塞在那边得不到返回,当然了,我们也可以使用非阻塞的去读(open的时候标志设置成 | NOBLOCK),接着接着,咱们来出发input 设备

[email protected]:/home/jay/workspace/virtual/main# echo 1 2 > /sys/devices/platform/virtual-touch/position 
[email protected]:/home/jay/workspace/virtual/main# position : (1, 32767)
read!
position : (1, 2)
read!
sync!
read!

看到没,看到没,数据已经打印出来了,具体的流程大家可以自己分析驱动代码,最主要的还是那张驱动架构图。

好了,现在,我们来写一个jni来封装下read函数

。。。等等,咱们还是先看我们的java代码,一般jni是提供接口的,但是接口到底是怎么样的还是取决于java中的需要。

这里我写了一个class来封装open,read等函数。

GetPosition.java


我承认,我写的java代码很烂,好吧,咱不多看了,只要看这里的native函数,这里封装了open、read、close函数,

好,然后咱们使用javah来生成jni的头文件。

# javah -jni GetPosition


然后我们按照这个头文件来完成我们的jni

virtual-touch.c


jni的基础知识,大家可以参考我的一个博客专栏,嘻嘻~~~打广告了

http://blog.csdn.net/column/details/jnijni.html

用命令来生成动态库

这里给大家提供一个shell脚本来使用


好了,最后是我们的java测试程序


继续测试下

可以得到跟之前一样的结果。

OK,现在我们可以再Linux下学习 Linux 驱动还有jni了。




参考:

在Linux下如何使用GCC编译程序、简单生成静态库及动态库。

http://blog.csdn.net/clozxy/article/details/5716227

Linux下JNI实现

http://www.cnblogs.com/xiaoxiaoboke/archive/2012/02/13/2349775.html

2楼zhangjie201412昨天 16:37
自己先顶一个
1楼Wu_Sh_Long昨天 15:38
支持,哈哈!!!
  相关解决方案