继续上一个链接内容所讲:http://www.cnblogs.com/linhaostudy/p/8430583.html

下面bmp18x sensor为例进行分析。

BMP18x Sensor:

我们以打开bmp180为例,代码为hardware\qcom\sensors\Bmp180.cpp:

 PressureSensor::PressureSensor(char *name)
: SensorBase(NULL, "bmp18x"),
mInputReader(),
mHasPendingEvent(false),
mEnabledTime()
{
mPendingEvent.version = sizeof(sensors_event_t);
mPendingEvent.sensor = SENSORS_PRESSURE_HANDLE;
mPendingEvent.type = SENSOR_TYPE_PRESSURE;
memset(mPendingEvent.data, , sizeof(mPendingEvent.data)); if (data_fd) {
strlcpy(input_sysfs_path, SYSFS_CLASS, sizeof(input_sysfs_path));
strlcat(input_sysfs_path, name, sizeof(input_sysfs_path));
strlcat(input_sysfs_path, "/", sizeof(input_sysfs_path));
input_sysfs_path_len = strlen(input_sysfs_path);
ALOGI("The pressure sensor path is %s",input_sysfs_path);
enable(, );
}
} PressureSensor::PressureSensor(char *name)
: SensorBase(NULL, "bmp18x"),
mInputReader(),
mHasPendingEvent(false),
mEnabledTime()
{
mPendingEvent.version = sizeof(sensors_event_t);
mPendingEvent.sensor = SENSORS_PRESSURE_HANDLE;
mPendingEvent.type = SENSOR_TYPE_PRESSURE;
memset(mPendingEvent.data, , sizeof(mPendingEvent.data)); if (data_fd) {
strlcpy(input_sysfs_path, SYSFS_CLASS, sizeof(input_sysfs_path));
strlcat(input_sysfs_path, name, sizeof(input_sysfs_path));
strlcat(input_sysfs_path, "/", sizeof(input_sysfs_path));
input_sysfs_path_len = strlen(input_sysfs_path);
ALOGI("The pressure sensor path is %s",input_sysfs_path);
enable(, );
}
}

mPendingEvent是一个sensors_event_t结构体,首先对sensor、type等赋值,然后调用enable打开;

 /**
* @brief This function will enable/disable sensor.
* @param[in] handle
* which sensor to enable/disable.
* @param[in] en
* en=1, enable;
* en=0, disable
* @return if the operation is successful.
*/
int PressureSensor::enable(int32_t handle, int en)
{
VFUNC_LOG; int res = ; LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
en, pressureSysFs.pressure_enable, getTimestamp());
res = write_sysfs_int(pressureSysFs.pressure_enable, en); return res;
}

其实就是对SYSFS_CLASS路径下的文件的enable节点写值“1”;

SYSFS_CLASS的路径为(hardware\qcom\sensors\sensors.h):

1 #define SYSFS_CLASS        "/sys/class/sensors/"

注意,不要忽略了SensorBase(NULL, "bmp18x"),我们看一下它做了什么?

 /*****************************************************************************/

 SensorBase::SensorBase(
const char* dev_name,
const char* data_name,
const struct SensorContext* context /* = NULL */)
: dev_name(dev_name), data_name(data_name), algo(NULL),
dev_fd(-), data_fd(-), mEnabled(), mHasPendingMetadata()
{
if (context != NULL) {
CalibrationManager& cm(CalibrationManager::getInstance());
algo = cm.getCalAlgo(context->sensor); /* Set up the sensors_meta_data_event_t event*/
meta_data.version = META_DATA_VERSION;
meta_data.sensor = context->sensor->handle;
meta_data.type = SENSOR_TYPE_META_DATA;
meta_data.reserved0 = ;
meta_data.timestamp = 0LL;
meta_data.meta_data.what = META_DATA_FLUSH_COMPLETE;
meta_data.meta_data.sensor = context->sensor->handle;
} if (data_name) {
data_fd = openInput(data_name);
}
}

这里的dev_name为NULL,data_name为bmp18x,设置dev_name和data_name后调用openInput打开设备:

 int SensorBase::openInput(const char* inputName) {
int fd = -;
const char *dirname = "/dev/input";
char devname[PATH_MAX];
char *filename;
DIR *dir;
struct dirent *de;
dir = opendir(dirname);
if(dir == NULL)
return -;
strlcpy(devname, dirname, PATH_MAX);
filename = devname + strlen(dirname);
*filename++ = '/';
while((de = readdir(dir))) {
if(de->d_name[] == '.' &&
(de->d_name[] == '\0' ||
(de->d_name[] == '.' && de->d_name[] == '\0')))
continue;
strlcpy(filename, de->d_name, PATH_MAX - strlen(SYSFS_CLASS));
fd = open(devname, O_RDONLY);
if (fd>=) {
char name[];
if (ioctl(fd, EVIOCGNAME(sizeof(name) - ), &name) < ) {
name[] = '\0';
}
if (!strcmp(name, inputName)) {
strlcpy(input_name, filename, PATH_MAX);
break;
} else {
close(fd);
fd = -;
}
}
}
closedir(dir);
ALOGE_IF(fd<, "couldn't find '%s' input device", inputName);
return fd;
}

再继续看一下getInput:

getInput

这个函数的作用就是打开"/dev/input",查找其中的输入设备名字与传入参数匹配的那一个,这里是"bmp18x",并返回相应的打开句柄。

到这里sensor就打开了;

Activate、setDelay都是直接调用相应的sensor接口直接调用相应sensor的接口,主要是readEvents:

 int PressureSensor::readEvents(sensors_event_t* data, int count)
{
if (count < )
return -EINVAL;
  //这里两个判断都不会进来
if (mHasPendingEvent) {
mHasPendingEvent = false;
mPendingEvent.timestamp = getTimestamp();
*data = mPendingEvent;
return mEnabled ? : ;
} if (mHasPendingMetadata) {
mHasPendingMetadata--;
meta_data.timestamp = getTimestamp();
*data = meta_data;
return mEnabled ? : ;
} ssize_t n = mInputReader.fill(data_fd);  //从输入设备中读取数据  
21 if (n < 0)
return n; int numEventReceived = ;
input_event const* event; #if FETCH_FULL_EVENT_BEFORE_RETURN
again:
#endif
while (count && mInputReader.readEvent(&event)) {//读取当前一个event,返回还有的数据大小  
int type = event->type;
if (type == EV_ABS) {//根据kernel上报的input事件来确定相应的数据值
float value = event->value;
mPendingEvent.pressure = value * CONVERT_PRESSURE;
} else if (type == EV_SYN) {
switch (event->code) {
case SYN_TIME_SEC:
mUseAbsTimeStamp = true;
report_time = event->value*1000000000LL;
break;
case SYN_TIME_NSEC:
mUseAbsTimeStamp = true;
mPendingEvent.timestamp = report_time+event->value;
break;
case SYN_REPORT:
if(mUseAbsTimeStamp != true) {
mPendingEvent.timestamp = timevalToNano(event->time);
}
if (mEnabled) {
if (mPendingEvent.timestamp >= mEnabledTime) {
*data++ = mPendingEvent;
numEventReceived++;
}
count--;
}
break;
}
} else {
ALOGE("PressureSensor: unknown event (type=%d, code=%d)",
type, event->code);
}
mInputReader.next();
} #if FETCH_FULL_EVENT_BEFORE_RETURN
/* if we didn't read a complete event, see if we can fill and
try again instead of returning with nothing and redoing poll. */
if (numEventReceived == && mEnabled == ) {
n = mInputReader.fill(data_fd);
if (n)
goto again;
}
#endif return numEventReceived;
}

这里看一下mInputReader,是一个InputEventCircularReader结构,表示的是一个环形的读入数据缓冲区:

 ssize_t InputEventCircularReader::fill(int fd)
{
size_t numEventsRead = ;
if (mFreeSpace) {
const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event));//读取数据
if (nread< || nread % sizeof(input_event)) {
// we got a partial event!!
return nread< ? -errno : -EINVAL;
} numEventsRead = nread / sizeof(input_event);
// dumpEvents(mHead, numEventsRead);
D("nread = %ld, numEventsRead = %d.", nread, numEventsRead);
if (numEventsRead) {
mHead += numEventsRead;
mFreeSpace -= numEventsRead;
if (mHead > mBufferEnd) {
size_t s = mHead - mBufferEnd;
memcpy(mBuffer, mBufferEnd, s * sizeof(input_event));
mHead = mBuffer + s;
}
}
} return numEventsRead;
}

mCurr表示未读事件的第一个,初始为缓冲区首部;

Fill函数是把调用read从相应的输入设备读入数据mHead位置;

readEvent函数返回mCurr和剩余的数据大小;

next函数让mCurr移一个input_event;

 

高通HAL层之bmp18x.cpp的更多相关文章

  1. 高通HAL层之Sensor HAL

    高通的HAL层其实分为两种,一种是直接从kernel这边报数据上来的,由sensor HAL层来监听,另一种是走ADSP的模式,HAL层是通过qmi的形式进行监听的: 走ADSP架构的可以看下面的博客 ...

  2. 高通非adsp 架构下的sensor的bug调试

    高通 sensor 从native到HAL 高通HAL层之Sensor HAL 高通HAL层之bmp18x.cpp 问题现象: 当休眠后,再次打开preesure sensor的时候,会出现隔一段时候 ...

  3. 高通 sensor 从native到HAL

    app注册传感器监听 Android Sensor Framework 的整体架构如下图所示: 前几篇sensor相关的文章介绍了sensor的hal的知识,以press_sensor实时显示气压坐标 ...

  4. android 6.0 高通平台sensor 工作机制及流程(原创)

    最近工作上有碰到sensor的相关问题,正好分析下其流程作个笔记. 这个笔记分三个部分: sensor硬件和驱动的工作机制 sensor 上层app如何使用 从驱动到上层app这中间的流程是如何 Se ...

  5. Android图形合成和显示系统---基于高通MSM8k MDP4平台

    介绍了Android SurfaceFlinger层次以下的图形合成和显示系统,主要基于高通MSM8k MDP4x平台. 做为Android Display专题.SurfaceFlinger的详细介绍 ...

  6. 【转】高通平台android 环境配置编译及开发经验总结

    原文网址:http://blog.csdn.net/dongwuming/article/details/12784535 1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通 ...

  7. 高通Android display架构分析

    目录(?)[-] Kernel Space Display架构介绍 函数和数据结构介绍 函数和数据结构介绍 函数和数据结构介绍 数据流分析 初始化过程分析 User Space display接口 K ...

  8. Android上HDMI介绍(基于高通平台)

    本文重点针对HDMI在android上的应用,而比较相关的就是overlay机制.overlay在这里只是简单的介绍,后续会有文章再专门详述. 我没记错的话,高通从7X30开始,平台就可以支持HDMI ...

  9. 高通camera结构【转】

    本文转载自:http://www.cnblogs.com/whw19818/p/5853407.html 摄像头基础介绍 一.摄像头结构和工作原理. 拍摄景物通过镜头,将生成的光学图像投射到传感器上, ...

随机推荐

  1. bootstrap-paginator分页插件的两种使用方式

    分页有两种方式: 1. 前台分页:ajax一次请求获取全部数据,适合少量数据(万条数据以下): $.ajax({ type: "GET", url: "",// ...

  2. bzoj:3730: 震波

    Description 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着时 ...

  3. a*b(mod m)的实现过程

    /*a*b (mod m) 的实现过程*/ /*当a,b很大的时候mod m就会产生溢出, 故运用乘法原理转换为加法求解*/ LL multi(LL a, LL b, LL m) { LL exp = ...

  4. Centos/Rhel7部署Zabbix监控(部署篇之服务器篇)

    Zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案. Zabbix能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让系统管理员快速定位/解决 ...

  5. Thinking in Java学习笔记-泛型和类型安全的容器

    示例: public class Apple { private static long counter; private final long id = counter++; public long ...

  6. [国嵌笔记][005][Linux命令详解]

    用户管理类命令 添加用户:useradd name 删除用户:userdel -r name "-r"表示删除对应用户的目录 修改密码:passwd name 切换用户:su - ...

  7. xshell连接虚拟机Ubuntu问题

    近期为了学习数据库的操作,准备在虚拟机中搭建环境以便操作(为什么在虚拟机搭建学习环境?),系统刚装好第一步就被阻止了. 总是会提示Could not connect to.原因是虚拟机没有安装ssh服 ...

  8. 从零开始学习前端开发 — 1、HTML基础

    一.web标准 web标准-网页制作的标准,它是由一系列标准组成的,主要包含三个方面:结构(html,xhtml),表现(css),行为(javascript) 注:结构和表现的标准由w3c(万维网联 ...

  9. PhpStorm中报 “Cannot run program git.exe, 系统找不到指定的文件” 

    http://blog.csdn.net/lamp_yang_3533/article/details/52003021 在使用PhpStorm的GitHub或Git功能时,经常会出现以下错误信息: ...

  10. Win7如何解决telnet不是内部或外部命令的方案!听语音

    Telnet用于远程操作互联网中的设备或终端计算机服务器,可以有效的减少现场操作的麻烦.因为设备或终端是遍布整个省或市,有的甚至是国外,如何高效的处理问题是当务之急,除了telnet还可以ssh使用c ...