高通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 摄像头基础介绍 一.摄像头结构和工作原理. 拍摄景物通过镜头,将生成的光学图像投射到传感器上, ...
随机推荐
- React Router 使用教程
一.基本用法 React Router 安装命令如下. $ npm install -S react-router 使用时,路由器Router就是React的一个组件. import { Router ...
- Educational Codeforces Round 21 D.Array Division(二分)
D. Array Division time limit per test:2 seconds memory limit per test:256 megabytes input:standard i ...
- hdu_1698Just a Hook(线段树)
hdu_1698Just a Hook(线段树) 标签: 线段树 题目链接 题意: 一个英雄的技能是发射一个长度为n的金属链,初始的金属链都是铁做的,标记为1,我们可以对于某个区间修改它的金属材质,如 ...
- android组件化方案、二维码扫码、Kotlin新闻客户端、动画特效等源码
Android精选源码 CalendarView日历选择器 android下拉刷新动画效果代码 一个非常方便的fragment页面框架 android组件化方案源码 Zxing实现二维码条形码的扫描和 ...
- Anaconda更新和第三方包更新
更新Anaconda和它所包含的包 1.打开cmd,切换到Anaconda的Scripts目录下:./Anaconda3/Scripts 2.更新Anaconda conda update conda ...
- 如何节省 1TB 图片带宽?解密极致图像压缩
欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:Gophery 本文由 腾讯技术工程官方号 发布在云+社区 图像已经发展成人类沟通的视觉语言.无论传统互联网还是移动互联网,图像一直占据着 ...
- 邓_phpcms_phpcms授课思路复习
思路: 一.目前在企业中使用比较多的cms内容管理有如下几种: 1.dedecms 2.phpcms 二.我们选择学习v9版本的phpcms,主要有以下几点原因: 1.基于MVC模式的内容管理系统 2 ...
- libJPEG-turbo库使用示例代码
libJPEG库是用于编码数据为JPEG格式或者解码JPEG格式图片的常用库,OpenCV读取图像底层实现就是利用libJPEG库,而libJPEG-turbo则效率更高. 具体怎么编译编译libJP ...
- speex库音频降噪(含代码)
speex库中音频降噪效果不错,应该是应用最广泛的吧,speex库下载地址https://www.speex.org/downloads/,可以直接下载二进制代码使用,像配置OpenCV一样配置spe ...
- MySQL改写子查询成Join
有时用别的方式而不是子查询可以获得更高的性能 : For example: SELECT * FROM t1 WHERE id IN (SELECT id FROM t2); 改写: SELECT D ...