zoukankan      html  css  js  c++  java
  • 高通HAL层之bmp18x.cpp

    继续上一个链接内容所讲:http://www.cnblogs.com/linhaostudy/p/8430583.html

    下面bmp18x sensor为例进行分析。

    BMP18x Sensor:

    我们以打开bmp180为例,代码为hardwareqcomsensorsBmp180.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的路径为(hardwareqcomsensorssensors.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打开设备:

     1 int SensorBase::openInput(const char* inputName) {
     2     int fd = -1;
     3     const char *dirname = "/dev/input";
     4     char devname[PATH_MAX];
     5     char *filename;
     6     DIR *dir;
     7     struct dirent *de;
     8     dir = opendir(dirname);
     9     if(dir == NULL)
    10         return -1;
    11     strlcpy(devname, dirname, PATH_MAX);
    12     filename = devname + strlen(dirname);
    13     *filename++ = '/';
    14     while((de = readdir(dir))) {
    15         if(de->d_name[0] == '.' &&
    16                 (de->d_name[1] == '' ||
    17                         (de->d_name[1] == '.' && de->d_name[2] == '')))
    18             continue;
    19         strlcpy(filename, de->d_name, PATH_MAX - strlen(SYSFS_CLASS));
    20         fd = open(devname, O_RDONLY);
    21         if (fd>=0) {
    22             char name[80];
    23             if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
    24                 name[0] = '';
    25             }
    26             if (!strcmp(name, inputName)) {
    27                 strlcpy(input_name, filename, PATH_MAX);
    28                 break;
    29             } else {
    30                 close(fd);
    31                 fd = -1;
    32             }
    33         }
    34     }
    35     closedir(dir);
    36     ALOGE_IF(fd<0, "couldn't find '%s' input device", inputName);
    37     return fd;
    38 }

      再继续看一下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;

     
  • 相关阅读:
    有关ASP的过程及函数的定义方法及调用
    ASP留言板(在一页里实现所有功能)
    滚动DataGrid
    效果试验
    自己写的身份证号码15位升18位的函数
    [学习笔记]开始学directx了之一
    改写的一个自动生成图片验证码的类asp.net(vb)
    参加了腾讯通RTX客户交流会
    杨伟帆的个人简历
    全国省市县无刷新多级关联菜单
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/8432741.html
Copyright © 2011-2022 走看看