继续上一个链接内容所讲:http://www.cnblogs.com/linhaostudy/p/8430583.html
下面bmp18x sensor为例进行分析。
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打开设备:
再继续看一下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;