高通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 摄像头基础介绍 一.摄像头结构和工作原理. 拍摄景物通过镜头,将生成的光学图像投射到传感器上, ...
随机推荐
- JavaScript for in的缺陷
for in 语句用来列举对象的属性(成员),如下 1 2 3 4 5 6 7 var obj = { name:"jack", getName:function(){ ...
- (亲测)1分钟破解IDM权限,傻瓜都能学会的破解方法(番外篇:利用破解工具直接破解IDM)
Internet Download Manager (IDM)是比较好用的一款下载工具~ 上一节我讲到一种利用修改防火墙来进行阻止访问服务器,请参看这篇文章(亲测)躺着破解IDM下载权限,治疗不用破解 ...
- bzoj:1700: [Usaco2007 Jan]Problem Solving 解题
Description 过去的日子里,农夫John的牛没有任何题目. 可是现在他们有题目,有很多的题目. 精确地说,他们有P (1 <= P <= 300) 道题目要做. 他们还离开了农场 ...
- codeforces 767A Snacktower(模拟)
A. Snacktower time limit per test:2 seconds memory limit per test:256 megabytes input:standard input ...
- 利用dfs解决规定路程问题
今天继续dfs的训练,遇到了一道神题,不停地TLE,我DD都快碎了.....好在经过本渣不懈努力,还是弄了出来,不容易啊,发上来纪念一下,顺便总结一下关于用dfs解决规定路程的问题. 先上题目: De ...
- Sublime Text 3.0版本的傻瓜式汉化步骤
Sublime text 3是非常好的文本编辑器,在试用过N款文本编辑器(Notepad.Notepad++.Notepad2.Programmer's notepad.EditPlus,Vim, T ...
- 二 @ResponseBody用法
@ResponseBody底层是通过response.getwriter()方法将数据写回前 台 @ResponseBody @RequestMapping (value="/queryLi ...
- Kubernetes volumes简介
容器中的磁盘文件生命周期比较短暂,在一些比较复杂的容器应用中会产生一些问题.一.容器crash后,kubelet会重启该容器,但这些文件会丢失掉.二.pod中的多个容器经常需要共享文件.因此,Kube ...
- Spark性能调优之JVM调优
Spark性能调优之JVM调优 通过一张图让你明白以下四个问题 1.JVM GC机制,堆内存的组成 2.Spark的调优为什么会和JVM的调 ...
- 【自制工具类】struts返回json数据包装格式类
自己写的一个给struts返回的json数据包装格式类,不喜勿喷,原创,需在项目中引入com.alibaba.fastjson的jar包 先看下效果(这里没有使用msg,有兴趣的往下看): 上demo ...