高通HAL层之Sensor HAL
高通的HAL层其实分为两种,一种是直接从kernel这边报数据上来的,由sensor HAL层来监听,另一种是走ADSP的模式,HAL层是通过qmi的形式进行监听的;
走ADSP架构的可以看下面的博客:http://blog.csdn.net/u011006622/article/details/54598426
而msm8909架构下的便是以HAL层来监听数据的;
简介:
Google为Sensor提供了统一的HAL接口,不同的硬件厂商需要根据该接口来实现并完成具体的硬件抽象层,Android中Sensor的HAL接口定义在:hardware/libhardware/include/hardware/sensors.h:
为了了解HAL层的sensor,我们必须理解几个结构体:分别是sensor_type,sensor_t,sensors_module_t;
从下面可以看到此文件定义了sensor的type以及string type;
/*
* SENSOR_TYPE_ACCELEROMETER
* reporting-mode: continuous
*
* All values are in SI units (m/s^2) and measure the acceleration of the
* device minus the force of gravity.
*
* Implement the non-wake-up version of this sensor and implement the wake-up
* version if the system possesses a wake up fifo.
*/
#define SENSOR_TYPE_ACCELEROMETER (1)
#define SENSOR_STRING_TYPE_ACCELEROMETER "android.sensor.accelerometer"
sensors_module_t结构体:
该结构体实际上是对标准硬件模块hw_module_t的一个扩展,增加一个get_sensor_list函数,用于获取传感器的列表,以及set_operation_mode设置为相关的mode;
/**
* Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
* and the fields of this data structure must begin with hw_module_t
* followed by module specific information.
*/
struct sensors_module_t {
struct hw_module_t common; /**
* Enumerate all available sensors. The list is returned in "list".
* @return number of sensors in the list
*/
int (*get_sensors_list)(struct sensors_module_t* module,
struct sensor_t const** list); /**
* Place the module in a specific mode. The following modes are defined
*
* 0 - Normal operation. Default state of the module.
* 1 - Loopback mode. Data is injected for the supported
* sensors by the sensor service in this mode.
* @return 0 on success
* -EINVAL if requested mode is not supported
* -EPERM if operation is not allowed
*/
int (*set_operation_mode)(unsigned int mode);
};
sensors_module_t
sensor_t结构体:
struct sensor_t { /* Name of this sensor.
* All sensors of the same "type" must have a different "name".
*/
const char* name; //传感器名字 /* vendor of the hardware part */
const char* vendor; //生产厂家名字 /* version of the hardware part + driver. The value of this field
* must increase when the driver is updated in a way that changes the
* output of this sensor. This is important for fused sensors when the
* fusion algorithm is updated.
*/
int version; /* handle that identifies this sensors. This handle is used to reference
* this sensor throughout the HAL API.
*/
int handle; //传感器handle句柄 /* this sensor's type. */
int type; //传感器类型 /* maximum range of this sensor's value in SI units */
float maxRange; //最大范围 /* smallest difference between two values reported by this sensor */
float resolution; //解析度 /* rough estimate of this sensor's power consumption in mA */
float power; /* this value depends on the reporting mode:
*
* continuous: minimum sample period allowed in microseconds
* on-change : 0
* one-shot :-1
* special : 0, unless otherwise noted
*/
int32_t minDelay; /* number of events reserved for this sensor in the batch mode FIFO.
* If there is a dedicated FIFO for this sensor, then this is the
* size of this FIFO. If the FIFO is shared with other sensors,
* this is the size reserved for that sensor and it can be zero.
*/
uint32_t fifoReservedEventCount; /* maximum number of events of this sensor that could be batched.
* This is especially relevant when the FIFO is shared between
* several sensors; this value is then set to the size of that FIFO.
*/
uint32_t fifoMaxEventCount; /* type of this sensor as a string. Set to corresponding
* SENSOR_STRING_TYPE_*.
* When defining an OEM specific sensor or sensor manufacturer specific
* sensor, use your reserve domain name as a prefix.
* ex: com.google.glass.onheaddetector
* For sensors of known type, the android framework might overwrite this
* string automatically.
*/
const char* stringType; /* permission required to see this sensor, register to it and receive data.
* Set to "" if no permission is required. Some sensor types like the
* heart rate monitor have a mandatory require_permission.
* For sensors that always require a specific permission, like the heart
* rate monitor, the android framework might overwrite this string
* automatically.
*/
const char* requiredPermission; /* This value is defined only for continuous mode and on-change sensors. It is the delay between
* two sensor events corresponding to the lowest frequency that this sensor supports. When lower
* frequencies are requested through batch()/setDelay() the events will be generated at this
* frequency instead. It can be used by the framework or applications to estimate when the batch
* FIFO may be full.
*
* NOTE: 1) period_ns is in nanoseconds where as maxDelay/minDelay are in microseconds.
* continuous, on-change: maximum sampling period allowed in microseconds.
* one-shot, special : 0
* 2) maxDelay should always fit within a 32 bit signed integer. It is declared as 64 bit
* on 64 bit architectures only for binary compatibility reasons.
* Availability: SENSORS_DEVICE_API_VERSION_1_3
*/
#ifdef __LP64__
int64_t maxDelay;
#else
int32_t maxDelay;
#endif /* Flags for sensor. See SENSOR_FLAG_* above. Only the least significant 32 bits are used here.
* It is declared as 64 bit on 64 bit architectures only for binary compatibility reasons.
* Availability: SENSORS_DEVICE_API_VERSION_1_3
*/
#ifdef __LP64__
uint64_t flags;
#else
uint32_t flags;
#endif /* reserved fields, must be zero */
void* reserved[];
};
sensor_t
高通HAL:
现在回到高通定制的sensor HAL层来:(代码位于hardware\qcom\sensors:)
Sensor HAL:
首先sensor这个模块这个id的定义,主要实现了sensors_module_t结构:
struct sensors_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: ,
version_minor: ,
id: SENSORS_HARDWARE_MODULE_ID,
name: "Quic Sensor module",
author: "Quic",
methods: &sensors_module_methods,
dso: NULL,
reserved: {},
},
get_sensors_list: sensors__get_sensors_list,
};
sensors__get_sensors_list函数返回这个平台的所有sensor:
static int sensors__get_sensors_list(struct sensors_module_t*,
struct sensor_t const** list)
{
NativeSensorManager& sm(NativeSensorManager::getInstance()); return sm.getSensorList(list);
}
sensors__get_sensors_list
里面使用了NativeSensorManager,sensors__get_sensors_list函数中调用单例模式创建了一个实例,然后再调用相应的成员函数获取传感器列表,并返回,返回值对应的sensor_t结构体;
NativeSensorManager统一管理着所有的传感器、物理和虚拟传感器。它的软件框架如下:
我们继续看sensors_module_methods:
static struct hw_module_methods_t sensors_module_methods = {
open: open_sensors
};
/*****************************************************************************/ /** Open a new instance of a sensor device using name */
static int open_sensors(const struct hw_module_t* module, const char*,
struct hw_device_t** device)
{
int status = -EINVAL;
sensors_poll_context_t *dev = new sensors_poll_context_t();
NativeSensorManager& sm(NativeSensorManager::getInstance()); memset(&dev->device, , sizeof(sensors_poll_device_1_ext_t)); dev->device.common.tag = HARDWARE_DEVICE_TAG;
#if defined(SENSORS_DEVICE_API_VERSION_1_3)
ALOGI("Sensors device API version 1.3 supported\n");
dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_3;
#else
dev->device.common.version = SENSORS_DEVICE_API_VERSION_0_1;
#endif
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = poll__close;
dev->device.activate = poll__activate;
dev->device.setDelay = poll__setDelay;
dev->device.poll = poll__poll;
dev->device.calibrate = poll_calibrate;
#if defined(SENSORS_DEVICE_API_VERSION_1_3)
dev->device.batch = poll__batch;
dev->device.flush = poll__flush;
#endif *device = &dev->device.common;
status = ; return status;
}
open_sensors用来打开所有的sensor,并返回相应的状态;首先new了一个sensors_poll_context_t ,然后设置device,并返回;
对应的new sensors_poll_context_t,我们来看一下其实现:
struct sensors_poll_context_t {
// extension for sensors_poll_device_1, must be first
struct sensors_poll_device_1_ext_t device;// must be first
sensors_poll_context_t();
~sensors_poll_context_t();
int activate(int handle, int enabled);
int setDelay(int handle, int64_t ns);
int pollEvents(sensors_event_t* data, int count);
int calibrate(int handle, cal_cmd_t *para);
int batch(int handle, int sample_ns, int latency_ns);
int flush(int handle); private:
static const size_t wake = MAX_SENSORS;
static const char WAKE_MESSAGE = 'W';
struct pollfd mPollFds[MAX_SENSORS+];
int mWritePipeFd;
SensorBase* mSensors[MAX_SENSORS];
mutable Mutex mLock;
};
sensors_poll_context_t
/*****************************************************************************/ sensors_poll_context_t::sensors_poll_context_t()
{
int number;
int i;
const struct sensor_t *slist;
const struct SensorContext *context;
NativeSensorManager& sm(NativeSensorManager::getInstance());
//获取sensor列表
number = sm.getSensorList(&slist); /* use the dynamic sensor list */
for (i = ; i < number; i++) {
context = sm.getInfoByHandle(slist[i].handle); mPollFds[i].fd = (context == NULL) ? - : context->data_fd;
mPollFds[i].events = POLLIN;
mPollFds[i].revents = ;
} ALOGI("The avaliable sensor handle number is %d",i);
int wakeFds[];
int result = pipe(wakeFds);
ALOGE_IF(result<, "error creating wake pipe (%s)", strerror(errno));
fcntl(wakeFds[], F_SETFL, O_NONBLOCK);
fcntl(wakeFds[], F_SETFL, O_NONBLOCK);
mWritePipeFd = wakeFds[]; mPollFds[number].fd = wakeFds[];
mPollFds[number].events = POLLIN;
mPollFds[number].revents = ;
}
通过context = sm.getInfoByHandle(slist[i].handle); 维系了一个handle对应的SensorContext对象指针的句柄;
(context是一个SensorContext结构体,SensorContext包含了一个SensorBase *driver指针;注意这个很重要!就是这个与具体的sensor产生相应的关联;而mPollFds是一个pollfd的结构。context保存着各个打开的sensor,mPollFds用来监听sensor的时候用的文件描述符;)
然后继续往下看,由上面代码可见:sensors_poll_device_t的activate、setDelay和poll的实现函数分别为:
(1) poll__activate
(2) poll__setDelay
(3) poll__poll
int sensors_poll_context_t::activate(int handle, int enabled) {
int err = -;
NativeSensorManager& sm(NativeSensorManager::getInstance());
Mutex::Autolock _l(mLock); err = sm.activate(handle, enabled);
if (enabled && !err) {
const char wakeMessage(WAKE_MESSAGE);
int result = write(mWritePipeFd, &wakeMessage, );
ALOGE_IF(result<, "error sending wake message (%s)", strerror(errno));
} return err;
}
sensors_poll_context_t::activate
int sensors_poll_context_t::setDelay(int handle, int64_t ns) {
int err = -;
NativeSensorManager& sm(NativeSensorManager::getInstance());
Mutex::Autolock _l(mLock); err = sm.setDelay(handle, ns); return err;
}
sensors_poll_context_t::setDelay
int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
{
int nbEvents = ;
int n = ;
NativeSensorManager& sm(NativeSensorManager::getInstance());
const sensor_t *slist;
int number = sm.getSensorList(&slist); do {
// see if we have some leftover from the last poll()
for (int i = ; count && i < number ; i++) {
if ((mPollFds[i].revents & POLLIN) || (sm.hasPendingEvents(slist[i].handle))) {
Mutex::Autolock _l(mLock);
int nb = sm.readEvents(slist[i].handle, data, count);
if (nb < ) {
ALOGE("readEvents failed.(%d)", errno);
return nb;
}
if (nb <= count) {
// no more data for this sensor
mPollFds[i].revents = ;
}
count -= nb;
nbEvents += nb;
data += nb;
}
} if (count) {
// we still have some room, so try to see if we can get
// some events immediately or just wait if we don't have
// anything to return
do {
n = poll(mPollFds, number + , nbEvents ? : -);
} while (n < && errno == EINTR);
if (n<) {
ALOGE("poll() failed (%s)", strerror(errno));
return -errno;
}
if (mPollFds[number].revents & POLLIN) {
char msg;
int result = read(mPollFds[number].fd, &msg, );
ALOGE_IF(result<, "error reading from wake pipe (%s)", strerror(errno));
ALOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));
mPollFds[number].revents = ;
}
}
// if we have events and space, go read them
} while (n && count); return nbEvents;
}
sensors_poll_context_t::pollEvents
static int poll__close(struct hw_device_t *dev)
{
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
if (ctx) {
delete ctx;
}
return ;
}
poll__close
static int poll__activate(struct sensors_poll_device_t *dev,
int handle, int enabled) {
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
return ctx->activate(handle, enabled);
}
poll__activate
static int poll__setDelay(struct sensors_poll_device_t *dev,
int handle, int64_t ns) {
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
return ctx->setDelay(handle, ns);
}
poll__setDelay
static int poll__poll(struct sensors_poll_device_t *dev,
sensors_event_t* data, int count) {
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
return ctx->pollEvents(data, count);
}
poll__poll
以poll_poll为例,看看如何与具体的sensor建立连接的:
return ctx->pollEvents(data, count);
ctx->pollEvents函数又调用了NativeSensorManager::readEvents;
int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
{
int nbEvents = ;
int n = ;
NativeSensorManager& sm(NativeSensorManager::getInstance());
const sensor_t *slist;
int number = sm.getSensorList(&slist); do {
// see if we have some leftover from the last poll()
for (int i = ; count && i < number ; i++) {
if ((mPollFds[i].revents & POLLIN) || (sm.hasPendingEvents(slist[i].handle))) {
Mutex::Autolock _l(mLock);
int nb = sm.readEvents(slist[i].handle, data, count);
if (nb < ) {
ALOGE("readEvents failed.(%d)", errno);
return nb;
}
if (nb <= count) {
// no more data for this sensor
mPollFds[i].revents = ;
}
count -= nb;
nbEvents += nb;
data += nb;
}
} if (count) {
// we still have some room, so try to see if we can get
// some events immediately or just wait if we don't have
// anything to return
do {
n = poll(mPollFds, number + , nbEvents ? : -);
} while (n < && errno == EINTR);
if (n<) {
ALOGE("poll() failed (%s)", strerror(errno));
return -errno;
}
if (mPollFds[number].revents & POLLIN) {
char msg;
int result = read(mPollFds[number].fd, &msg, );
ALOGE_IF(result<, "error reading from wake pipe (%s)", strerror(errno));
ALOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));
mPollFds[number].revents = ;
}
}
// if we have events and space, go read them
} while (n && count); return nbEvents;
}
sensors_poll_context_t::pollEvents
NativeSensorManager::readEvents中又调用了:
nb = list->driver->readEvents(data, count);
记得上面说过什么?list->driver是一个SensorBase结构体,于是终于终于我们来到了SensorBase结构体的函数readEvents,接下来就是具体的sensor模块读取的任务了!!
其主要框架如下图所示:
下来继续看具体sensor的处理过程:http://www.cnblogs.com/linhaostudy/p/8432741.html
高通HAL层之Sensor HAL的更多相关文章
- 高通qxdm抓取sensor的log【学习笔记】
高通qxdm抓取sensor的log 打开qxdm,打开设置界面,去掉其他无关的log,打开Log packets .Message packets的SNS的log 之后需要把端口打开,把端口打开之后 ...
- 高通adsp架构下sensor
一.高通sensor架构: linux驱动由浅入深系列:高通sensor架构实例分析之一(整体概览+AP侧代码分析) linux驱动由浅入深系列:高通sensor架构实例分析之二(adsp驱动代码结构 ...
- 高通 8x26 andorid light sensor(TSL258x) 开发【转】
本文转载自:http://www.voidcn.com/blog/u012296694/article/p-1669831.html 前言 8926平台的sensor架构与之前的平台完全不同,实际上已 ...
- 高通(QCOM)sensor bring up
高通7150平台 1.添加驱动文件 2.添加编译 3.配置json文件 4.高通默认配置 5.部分sensor外挂电源 6.遇到的问题 1.添加驱动文件 路径:adsp_proc/ssc/sensor ...
- 高通非adsp 架构下的sensor的bug调试
高通 sensor 从native到HAL 高通HAL层之Sensor HAL 高通HAL层之bmp18x.cpp 问题现象: 当休眠后,再次打开preesure sensor的时候,会出现隔一段时候 ...
- 高通sensor理解
.1.高通为什么引入adsp? 2.adsp sensor 是如何工作起来的? 3.adsp 和ap 是如何通信的? 4.adsp 架构组成 解答: 1.高通在msm8960之前sensor 是挂在p ...
- 高通camera基本代码架构【转】
本文转载自:http://blog.sina.com.cn/s/blog_c0de2be70102vyn1.html 1 camera基本代码架构 高通平台对于camera的代码组织,大体上还是遵循 ...
- 高通msm mdm 总结
1. svn 获取工程代码命令:svn co svn+ssh://10.20.30.18/svn-repos/msm8916/branches/LA1.1-CS-r113502.2 2. 如何确定那些 ...
- 高通 sensor 从native到HAL
app注册传感器监听 Android Sensor Framework 的整体架构如下图所示: 前几篇sensor相关的文章介绍了sensor的hal的知识,以press_sensor实时显示气压坐标 ...
随机推荐
- bzoj:1221;vijos 1552 软件开发
Description 某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员 ...
- Gym 100952H&&2015 HIAST Collegiate Programming Contest H. Special Palindrome【dp预处理+矩阵快速幂/打表解法】
H. Special Palindrome time limit per test:1 second memory limit per test:64 megabytes input:standard ...
- CF 348DTurtles
题目:http://codeforces.com/contest/348/problem/D 如果只走一条路那就直接dp就可以了. 设cal(x1,y1,x2,y2)为(x1,y1)→(x2,y2)的 ...
- HDU-5340 Three Palindromes(字符串哈希)
http://acm.hdu.edu.cn/showproblem.php?pid=5340 orz到了新的字符串hash姿势 #include<cstdio>#include<cs ...
- python笔记一(正则表达式)
#!/usr/bin/env python # -*- coding: utf-8 -*- # 1 如果直接给出字符,则表示精确匹配 # 2 \d 表示数字, \w 表示字母或数字, . 可以匹配任意 ...
- Visual Studio 2017 安装后无法创建c++或MFC项目
话话不多说,直接上图
- .23-浅析webpack源码之事件流compilation(1)
正式开始跑编译,依次解析,首先是: compiler.apply( new JsonpTemplatePlugin(options.output), // start new FunctionModu ...
- Core Animation 文档翻译(第三篇)
Core Animation 文档翻译(第三篇) 设置Layer对象 当我们使用核心动画时,Layer对象是一切的核心.Layers 管理我们APP的可视化content,Layer也提供了conte ...
- 动态查询:getBy字段名
http://www.php.cn/php/php-getBy.html 根据字段名动态查询:getBy字段名( ) 该方法很有意思,手册的说得很简略,我们根据源码来好好说道说道~~ 1. 功能:根据 ...
- YUM常用命令介绍
http://www.cnblogs.com/lostyue/archive/2012/05/06/2485653.html 1.列出所有可更新的软件清单 命令:yum check-update 2. ...