Android的传感器HAL层的书写

关于传感器,大家在日常的生活中用的很多。比如楼宇的楼梯灯,马路上的路灯等等。那么我们手机里的传感器又可以起到哪些作用呢?现在看下我们的Android中给提供了哪些吧。有加速度传感器,磁场,方向,陀螺仪,光线,压力,温度,接近传感器。

------------------------------文件分布------------------------------

其中的代码的分布如下:

1、传感器系统的JAVA部分

代码路径:frameworks/base/include/core/java/android/hardware

文件为Sensor*.java

2、传感器系统的JNI部分

代码路径:frameworks/base/core/jni/android_hardware_SensorManager.cpp

这部分是android.hardware.Sensor.Manager类的本质支持

3、传感器系统HAL层

头文件路径:hardware/libhardware/include/hardware/sensors.h

传感器系统的硬件抽象层需要具体的实现。

4、驱动层

代码路径:kernel/driver/hwmon/$(PROJECT)/sensor

在这里主要来分析下HAL层和JNI层,驱动层可以参考各个sensor厂商提供的代码 

------------------------------Android.mk------------------------------

下面转入到HAL层,也就是我们的c/cpp代码中,这里的路径一般是在hardware/$(PROJECT)/sensor/

下面我们先看看其中的Android.mk,全文如下:

LOCAL_PATH:= $(call my-dir)

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw

LOCAL_SHARED_LIBRARIES := libcutils libc liblog

LOCAL_SRC_FILES := 适配文件

LOCAL_MODULE := sensors.$(PROJECT)

include $(BUILD_SHARED_LIBRARY)

在这里要看看其中的一个细节LOCAL_MODULE的赋值,这里的模块的名字都是定义的好了的,可以参考下hardware/libhardware/hardware.c

/**

* There are a set of variant filename for modules. The form of the filename

* is "<MODULE_ID>.variant.so" so for the led module the Dream variants 

* of base "ro.product.board", "ro.board.platform" and "ro.arch" would be:

*

* led.trout.so

* led.msm7k.so

* led.ARMV6.so

* led.default.so

*/

这里也就可以看到了加载的顺序,在sensor加载的时候,依次去查找这些so是不是存在,然后就来加载对应到适配。

------------------------------填充的结构体------------------------------

在HAL层,有几个填充的结构体要注意下:

sensor模块的定义:

struct sensor_module_t {

struct hw_module_t common;

int (*get_sensors_list) (struct sensors_module_t *module, struct sensor_t const**list);

};

其中的get_sensors_list()用来获得传感器列表;

struct sensor_t{

const char*name;//传感器名称

const char*vendor;//传感器的Vendor

int version;//传感器的版本

inthandle;//传感器的句柄

int type;//传感器类型

floatmaxRange;//传感器的最大范围

floatresolution;//传感器的解析度

floatpower;//传感器的耗能,单位为mA

void*reserved[9];

}

sensor_t表示一个传感器的描述;

typedef struct{

int sensor;//sensor 标识符

unio{

sensors_vec_t vector;//x,y,z矢量

sensors_vec_torientation;//方向值 单位为角度

sensors_vec_tacceleration;//加速度值, 单位为m/s2

sensors_vec_tmagnetic;//磁矢量,单位uT

floattemperature;//温度,单位℃

floatdistance;//距离,单位cm

floatlight;//光线亮度,单位lux

}

int64_t time;//ns

uint32_treserved;

}sensors_data_t;

在这里还有两个是sensors_control_device_t和sensors_data_device_t两个结构体,其中都是些函数指针的定义;

------------------------------适配层函数接口------------------------------

在HAL层中,我们需要注意的则是这个函数static int s_device_open(const struct hw_module_t* module,

const char* name,

struct hw_device_t** device)

其中注意以下的赋值

if (!strcmp(name, SENSORS_HARDWARE_CONTROL)) {//命令通路

.......

dev->device.common.close = dev_control_close;

dev->device.open_data_source = open_data_source;

dev->device.activate = activate;

dev->device.set_delay = set_delay;

.......

} else if (!strcmp(name, SENSORS_HARDWARE_DATA)) {//数据通路

.......

dev->device.common.close = dev_data_close;

dev->device.data_open = data_open;

dev->device.data_close = data_close;

dev->device.poll = poll;

.......

}

看到这里,就可以发现具体的函数的定义是什么了。也可以根据名字知道了jni应该是采用poll的方式来获取数据的。也就是说我们在驱动中提供的代码要实现file_operation。

注意:

在这里要提醒一下,我们在驱动代码中取到的sensor寄存器中的值并不一定是我们实际要上报给应用的值,比如g-sensor,则各个方向则不应该大于10。其他的也要考虑,我在这个问题上栽过跟头了。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwzyjy.html