高通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 摄像头基础介绍 一.摄像头结构和工作原理. 拍摄景物通过镜头,将生成的光学图像投射到传感器上, ...
随机推荐
- BZOJ 1002: [FJOI2007]轮状病毒【生成树的计数与基尔霍夫矩阵简单讲解+高精度】
1002: [FJOI2007]轮状病毒 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 5577 Solved: 3031[Submit][Statu ...
- [51nod Round15 E ]Danganronpa
AC自动机,树上莫队,树状数组.. 比赛的时候完全看不出来...赛后去膜了一波网上题解才明白= = 离线,先把AC自动机建出来,把fail边反向建出fail树. 发射言弹,就是将言弹结束节点的fail ...
- POJ3258-River Hopscotch-二分
这个题就是排排坐,二分就可以了... River Hopscotch Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 1325 ...
- Codeforces780C
题解:n个气球 从1到n染色,如果a.b和c是不同的正方形,a和b在它们之间有一条直接的路径,b和c之间有一条直接的路径,然后在这三个方块上的气球颜色是不同的. AC代码 #include <s ...
- maven(01)--安装及其介绍
1:下载maven windows下载 2:将下载文件夹解压,然后放在一个安装目录(可任意选择),例如就放在D盘的根目录 然后在设置环境变量,新建一个环境变量,名称为M2_HOME,其设置值为mave ...
- Linux下安装PostgreSQL 转载linux社区
Linux下安装PostgreSQL [日期:2016-12-25] 来源:Linux社区 作者:xiaojian [字体:大 中 小] 在Linux下安装PostgreSQL有二进制格式安装和 ...
- ceph-deploy出错UnableToResolveError Unable to resolve host
背景 ps:在本文中,假设我系统的hostname为node1. 使用ceph-deploy命令搭建Ceph集群,执行ceph new node1时,出现如下错误: [node1][INFO ] Ru ...
- [国嵌攻略][117][LED驱动程序设计]
LED程序设计 1.编写内核模块 2.搭建字符驱动框架 3.实现设备方法 头文件 <linux/io.h> writel() 1.编译/安装驱动 make cp leddev.ko ... ...
- 根据PV统计出前三的热门板块,并统计出热门板块下的用户数--方式一
根据PV统计出前三的热门板块,并统计出热门板块下的用户数--方式一 测试数据 java代码 package com.hzf.spark.study; import java.util.ArrayLis ...
- memcached集群和一致性哈希算法
场景 由于memcached集群各节点之间都是独立的,互不通信,集群的负载均衡是基于客户端来实现的,因此需要客户端用户设计实现负载均衡算法. 取模算法 N个节点,从0->N-1编号,key对N ...