高通HAL層之bmp18x.cpp
繼續上一個鏈接內容所講: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打開設備:
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;
高通HAL層之bmp18x.cpp