当前位置:操作系统 > 安卓/Android >>

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的代码:


[cpp]
<span style="font-size:16px;">static int work_thread(void *data) 

    int x, y, ret; 
    struct virtual_dev *pvdev = (struct virtual_dev *)data; 
    struct semaphore sema = pvdev->sem; 
    // poll the data into user space  
    printk(KERN_INFO "work thread running!!"); 
     
    while(pvdev->running) { 
        do{ 
            ret = down_interruptible(&sema); 
        } while(ret == -EINTR); 
        //printk("done!\n");  
        //poll the x and y data into user space  
        x = pvdev->x; 
        y = pvdev->y; 
        input_report_abs(pvdev->input, ABS_X, x); 
        input_report_abs(pvdev->input, ABS_Y, y); 
        input_sync(pvdev->input); 
        printk("position: %d | %d\n", x, y);     
    } 
    return 0; 
}</span> 
<span style="font-size:16px;">static int work_thread(void *data)
{
 int x, y, ret;
 struct virtual_dev *pvdev = (struct virtual_dev *)data;
 struct semaphore sema = pvdev->sem;
 // poll the data into user space
 printk(KERN_INFO "work thread running!!");
 
 while(pvdev->running) {
  do{
   ret = down_interruptible(&sema);
  } while(ret == -EINTR);
  //printk("done!\n");
  //poll the x and y data into user space
  x = pvdev->x;
  y = pvdev->y;
  input_report_abs(pvdev->input, ABS_X, x);
  input_report_abs(pvdev->input, ABS_Y, y);
  input_sync(pvdev->input);
  printk("position: %d | %d\n", x, y); 
 }
 return 0;
}</span>
唤醒这个线程的地方,就是调用up的地方:


[cpp]
<span style="font-size:16px;">static ssize_t write_position(struct device *dev, 
        struct device_attribute *attr, const char *buffer, ssize_t count) 

    int x,y; 
    sscanf(buffer, "%d%d", &x, &y); 
    vdev->x = x; 
    vdev->y = y; 
    //do something with x and y ===> poll the data;  
    up(&vdev->sem); 
    return count; 
}</span> 
<span style="font-size:16px;">static ssize_t write_position(struct device *dev,
  struct device_attribute *attr, const char *buffer, ssize_t count)
{
 int x,y;
 sscanf(buffer, "%d%d", &x, &y);
 vdev->x = x;
 vdev->y = y;
 //do something with x and y ===> poll the data;
 up(&vdev->sem);
 return count;
}</span>
可以看到,这个write_position是被注册当position文件被执行写操作的时候执行的。


[cpp]
<span style="font-size:16px;">/* attach the sysfs */ 
DEVICE_ATTR(position, 0666, read_position, write_position); 
DEVICE_ATTR(color, 0666, read_color, write_color); 
DEVICE_ATTR(bcolor, 0666, read_bcolor, write_bcolor);</span> 
<span style="font-size:16px;">/* attach the sysfs */
DEVICE_ATTR(position, 0666, read_position, write_position);
DEVICE_ATTR(color, 0666, read_color, write_color);
DEVICE_ATTR(bcolor, 0666, read_bcolor, write_bcolor);</span>相信看了结构图就知道我们的代码是如何写的吧,这个驱动比较简单,看下完整的代码


[cpp]
<span style="font-size:16px;">/*
 *  This driver is named virtual touch, which can send some message into user space from kernel space,
 *  for this driver just for study Linux device driver...
 *  Jay Zhang 
 *  mail: zhangjie201412@live.com
 */ 
#include <linux/module.h>  
 
#include <linux/err.h>  
#include <linux/input.h>  
#include <linux/hwmon.h>  
#include <linux/kthread.h>  
#include <linux/platform_device.h>  
#include <linux/semaphore.h>  
#include <linux/slab.h>  
struct virtual_dev { 
    struct platform_device *vt_dev; 
    struct task_struct *run_thread; 
    struct

补充:移动开发 , Android ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,