下面bmp18x sensor为例进行分析。
我们以打开bmp180为例,代码为hardware\qcom\sensors\Bmp180.cpp:
1 PressureSensor::PressureSensor(char *name)
2 : SensorBase(NULL, "bmp18x"),
3 mInputReader(4),
4 mHasPendingEvent(false),
5 mEnabledTime(0)
6 {
7 mPendingEvent.version = sizeof(sensors_event_t);
8 mPendingEvent.sensor = SENSORS_PRESSURE_HANDLE;
9 mPendingEvent.type = SENSOR_TYPE_PRESSURE;
10 memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
11
12 if (data_fd) {
13 strlcpy(input_sysfs_path, SYSFS_CLASS, sizeof(input_sysfs_path));
14 strlcat(input_sysfs_path, name, sizeof(input_sysfs_path));
15 strlcat(input_sysfs_path, "/", sizeof(input_sysfs_path));
16 input_sysfs_path_len = strlen(input_sysfs_path);
17 ALOGI("The pressure sensor path is %s",input_sysfs_path);
18 enable(0, 1);
19 }
20 }
21
22
23 PressureSensor::PressureSensor(char *name)
24 : SensorBase(NULL, "bmp18x"),
25 mInputReader(4),
26 mHasPendingEvent(false),
27 mEnabledTime(0)
28 {
29 mPendingEvent.version = sizeof(sensors_event_t);
30 mPendingEvent.sensor = SENSORS_PRESSURE_HANDLE;
31 mPendingEvent.type = SENSOR_TYPE_PRESSURE;
32 memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
33
34 if (data_fd) {
35 strlcpy(input_sysfs_path, SYSFS_CLASS, sizeof(input_sysfs_path));
36 strlcat(input_sysfs_path, name, sizeof(input_sysfs_path));
37 strlcat(input_sysfs_path, "/", sizeof(input_sysfs_path));
38 input_sysfs_path_len = strlen(input_sysfs_path);
39 ALOGI("The pressure sensor path is %s",input_sysfs_path);
40 enable(0, 1);
41 }
42 }
mPendingEvent是一个sensors_event_t结构体,首先对sensor、type等赋值,然后调用enable打开;
1 /**
2 * @brief This function will enable/disable sensor.
3 * @param[in] handle
4 * which sensor to enable/disable.
5 * @param[in] en
6 * en=1, enable;
7 * en=0, disable
8 * @return if the operation is successful.
9 */
10 int PressureSensor::enable(int32_t handle, int en)
11 {
12 VFUNC_LOG;
13
14 int res = 0;
15
16 LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
17 en, pressureSysFs.pressure_enable, getTimestamp());
18 res = write_sysfs_int(pressureSysFs.pressure_enable, en);
19
20 return res;
21 }
其实就是对SYSFS_CLASS路径下的文件的enable节点写值“1”;
SYSFS_CLASS的路径为(hardware\qcom\sensors\sensors.h):
1 #define SYSFS_CLASS "/sys/class/sensors/"
注意,不要忽略了SensorBase(NULL, "bmp18x"),我们看一下它做了什么?
1 /*****************************************************************************/
2
3 SensorBase::SensorBase(
4 const char* dev_name,
5 const char* data_name,
6 const struct SensorContext* context /* = NULL */)
7 : dev_name(dev_name), data_name(data_name), algo(NULL),
8 dev_fd(-1), data_fd(-1), mEnabled(0), mHasPendingMetadata(0)
9 {
10 if (context != NULL) {
11 CalibrationManager& cm(CalibrationManager::getInstance());
12 algo = cm.getCalAlgo(context->sensor);
13
14 /* Set up the sensors_meta_data_event_t event*/
15 meta_data.version = META_DATA_VERSION;
16 meta_data.sensor = context->sensor->handle;
17 meta_data.type = SENSOR_TYPE_META_DATA;
18 meta_data.reserved0 = 0;
19 meta_data.timestamp = 0LL;
20 meta_data.meta_data.what = META_DATA_FLUSH_COMPLETE;
21 meta_data.meta_data.sensor = context->sensor->handle;
22 }
23
24 if (data_name) {
25 data_fd = openInput(data_name);
26 }
27 }
这里的dev_name为NULL,data_name为bmp18x,设置dev_name和data_name后调用openInput打开设备:
SensorBase::openInput
再继续看一下getInput:
getInput
这个函数的作用就是打开"/dev/input",查找其中的输入设备名字与传入参数匹配的那一个,这里是"bmp18x",并返回相应的打开句柄。
到这里sensor就打开了;
Activate、setDelay都是直接调用相应的sensor接口直接调用相应sensor的接口,主要是readEvents:
1 int PressureSensor::readEvents(sensors_event_t* data, int count)
2 {
3 if (count < 1)
4 return -EINVAL;
5
6 if (mHasPendingEvent) {
7 mHasPendingEvent = false;
8 mPendingEvent.timestamp = getTimestamp();
9 *data = mPendingEvent;
10 return mEnabled ? 1 : 0;
11 }
12
13 if (mHasPendingMetadata) {
14 mHasPendingMetadata--;
15 meta_data.timestamp = getTimestamp();
16 *data = meta_data;
17 return mEnabled ? 1 : 0;
18 }
19
20 ssize_t n = mInputReader.fill(data_fd); //从输入设备中读取数据
21 if (n < 0)
22 return n;
23
24 int numEventReceived = 0;
25 input_event const* event;
26
27 #if FETCH_FULL_EVENT_BEFORE_RETURN
28 again:
29 #endif
30 while (count && mInputReader.readEvent(&event)) {//读取当前一个event,返回还有的数据大小
31 int type = event->type;
32 if (type == EV_ABS) {//根据kernel上报的input事件来确定相应的数据值
33 float value = event->value;
34 mPendingEvent.pressure = value * CONVERT_PRESSURE;
35 } else if (type == EV_SYN) {
36 switch (event->code) {
37 case SYN_TIME_SEC:
38 mUseAbsTimeStamp = true;
39 report_time = event->value*1000000000LL;
40 break;
41 case SYN_TIME_NSEC:
42 mUseAbsTimeStamp = true;
43 mPendingEvent.timestamp = report_time+event->value;
44 break;
45 case SYN_REPORT:
46 if(mUseAbsTimeStamp != true) {
47 mPendingEvent.timestamp = timevalToNano(event->time);
48 }
49 if (mEnabled) {
50 if (mPendingEvent.timestamp >= mEnabledTime) {
51 *data++ = mPendingEvent;
52 numEventReceived++;
53 }
54 count--;
55 }
56 break;
57 }
58 } else {
59 ALOGE("PressureSensor: unknown event (type=%d, code=%d)",
60 type, event->code);
61 }
62 mInputReader.next();
63 }
64
65 #if FETCH_FULL_EVENT_BEFORE_RETURN
66 /* if we didn't read a complete event, see if we can fill and
67 try again instead of returning with nothing and redoing poll. */
68 if (numEventReceived == 0 && mEnabled == 1) {
69 n = mInputReader.fill(data_fd);
70 if (n)
71 goto again;
72 }
73 #endif
74
75 return numEventReceived;
76 }
这里看一下mInputReader,是一个InputEventCircularReader结构,表示的是一个环形的读入数据缓冲区:
1 ssize_t InputEventCircularReader::fill(int fd)
2 {
3 size_t numEventsRead = 0;
4 if (mFreeSpace) {
5 const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event));//读取数据
6 if (nread<0 || nread % sizeof(input_event)) {
7 // we got a partial event!!
8 return nread<0 ? -errno : -EINVAL;
9 }
10
11 numEventsRead = nread / sizeof(input_event);
12 // dumpEvents(mHead, numEventsRead);
13 D("nread = %ld, numEventsRead = %d.", nread, numEventsRead);
14 if (numEventsRead) {
15 mHead += numEventsRead;
16 mFreeSpace -= numEventsRead;
17 if (mHead > mBufferEnd) {
18 size_t s = mHead - mBufferEnd;
19 memcpy(mBuffer, mBufferEnd, s * sizeof(input_event));
20 mHead = mBuffer + s;
21 }
22 }
23 }
24
25 return numEventsRead;
26 }
mCurr表示未读事件的第一个,初始为缓冲区首部;
Fill函数是把调用read从相应的输入设备读入数据mHead位置;
readEvent函数返回mCurr和剩余的数据大小;
next函数让mCurr移一个input_event;