高通HAL层之bmp18x.cpp
继续上一个链接内容所讲: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:
这个函数的作用就是打开"/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的更多相关文章
- 高通HAL层之Sensor HAL
高通的HAL层其实分为两种,一种是直接从kernel这边报数据上来的,由sensor HAL层来监听,另一种是走ADSP的模式,HAL层是通过qmi的形式进行监听的: 走ADSP架构的可以看下面的博客 ...
- 高通非adsp 架构下的sensor的bug调试
高通 sensor 从native到HAL 高通HAL层之Sensor HAL 高通HAL层之bmp18x.cpp 问题现象: 当休眠后,再次打开preesure sensor的时候,会出现隔一段时候 ...
- 高通 sensor 从native到HAL
app注册传感器监听 Android Sensor Framework 的整体架构如下图所示: 前几篇sensor相关的文章介绍了sensor的hal的知识,以press_sensor实时显示气压坐标 ...
- android 6.0 高通平台sensor 工作机制及流程(原创)
最近工作上有碰到sensor的相关问题,正好分析下其流程作个笔记. 这个笔记分三个部分: sensor硬件和驱动的工作机制 sensor 上层app如何使用 从驱动到上层app这中间的流程是如何 Se ...
- Android图形合成和显示系统---基于高通MSM8k MDP4平台
介绍了Android SurfaceFlinger层次以下的图形合成和显示系统,主要基于高通MSM8k MDP4x平台. 做为Android Display专题.SurfaceFlinger的详细介绍 ...
- 【转】高通平台android 环境配置编译及开发经验总结
原文网址:http://blog.csdn.net/dongwuming/article/details/12784535 1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通 ...
- 高通Android display架构分析
目录(?)[-] Kernel Space Display架构介绍 函数和数据结构介绍 函数和数据结构介绍 函数和数据结构介绍 数据流分析 初始化过程分析 User Space display接口 K ...
- Android上HDMI介绍(基于高通平台)
本文重点针对HDMI在android上的应用,而比较相关的就是overlay机制.overlay在这里只是简单的介绍,后续会有文章再专门详述. 我没记错的话,高通从7X30开始,平台就可以支持HDMI ...
- 高通camera结构【转】
本文转载自:http://www.cnblogs.com/whw19818/p/5853407.html 摄像头基础介绍 一.摄像头结构和工作原理. 拍摄景物通过镜头,将生成的光学图像投射到传感器上, ...
随机推荐
- AtCoder Regular Contest 082
我都出了F了……结果并没有出E……atcoder让我差4分上橙是啥意思啊…… C - Together 题意:把每个数加1或减1或不变求最大众数. #include<cstdio> #in ...
- [bzoj1369] [Baltic2003]Gem
结论题...一棵树里用到的颜色数不超过logn.. f[i][j]表示以i为根的子树里,i的颜色是j的方案数. g[i][j]表示max{f[i][k]},(k!=j #include<cstd ...
- [bzoj1700]: [Usaco2007 Jan]Problem Solving 解题
不能贪心!不能贪心!不能贪心! 反正有反例(有的题目月初支付款很少,月末支付款很大,和前面的题凑到一个月的话可能导致下个月写不了= =这时放后一个月,和后面的题一起开始写可能更优) 比如: 50 44 ...
- 状压dp初探
写了几道状压...然后就一直在颓废... 2064: 分裂 http://www.lydsy.com/JudgeOnline/problem.php?id=2064 初始的为正,最后的为负,假设我们能 ...
- bfs学习
今天做到了bfs的练习,顺便写下心得... bfs能解决搜索和最短路径的问题. 下面是学习心得: typedef struct point //定义点 { int x; int y; }P; bfs( ...
- hdu_3483A Very Simple Problem(C(m,n)+快速幂矩阵)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3483 A Very Simple Problem Time Limit: 4000/2000 MS ( ...
- java与C++变量初始化的对比
java尽力保证:所有变量在使用前都能得到恰当的初始化 ①函数/方法局部变量的初始化 在C/C++中,变量的初始化还是得依赖于程序员的自觉性.对于函数局部变量,编译器不会为基本类型赋予默认初始值,新手 ...
- vuex的使用
vue现在越来越火,不单单可以写简单的小项目,也可以写大中型的项目.但是项目大了,项目之间的数据传递就会变得复杂,那么问题来了?在一个大型项目中,多个组件要公用同一个或多个数据,我们如何保证每个组件获 ...
- dedecms后台系统基本参数标题
1,站点设置 2,核心设置 3,附件设置 4,会员设置 6,性能选项 7,其它选项 8,模块设置 在E:\wamp\www\dededln\back\inc\configgroup.txt
- 基于Redis的分布式锁的简单实现
Redis官方给出两种思路 第一种:SET key value [EX seconds] [PX milliseconds] NX 第二种:SETNX+GETSET 首先,分别看一下这几个命令 SET ...