HAL

Posted zzss-feature

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HAL相关的知识,希望对你有一定的参考价值。

分析hardware/akm/AK8975_FS
大致有4类文件,有着不同的分工
1:hardware\akm\ak8975_fs\libsensors\Sensors.cpp
hal中一般支持多类设备,起框架作用,主要关注poll方法
2:AkmSensor.cpp
具体sensor的驱动代码
3:SensorBase.cpp
sensor的共有方法,比如open /dev/input/eventx...
4:InputEventReader.cpp
读取数据等方法

  • hardware\akm\ak8975_fs\libsensors\Sensors.cpp
    起总领作用

    static int open_sensors(const struct hw_module_t* module, const char* id,
                        struct hw_device_t** device)
    {
    sensors_poll_context_t *dev = new sensors_poll_context_t();
        // sensors_poll_context_t::sensors_poll_context_t
        mSensors[akm] = new AkmSensor();
        mPollFds[akm].fd = mSensors[akm]->getFd();
    
    // 填充回调函数
    dev->device.common.module   = const_cast<hw_module_t*>(module);
    dev->device.common.close    = poll__close;
    dev->device.activate        = poll__activate;
    dev->device.setDelay        = poll__setDelay;
    dev->device.poll            = poll__poll;
    
    *device = &dev->device.common;
    }
    static struct hw_module_methods_t sensors_module_methods = {
    .open = open_sensors
    };
    // HAL入口
    struct sensors_module_t HAL_MODULE_INFO_SYM = {
    .common = {
        .id = SENSORS_HARDWARE_MODULE_ID,
        .methods = &sensors_module_methods,
    },
    .get_sensors_list = sensors__get_sensors_list,
    };

    重点分析一下poll方法:对每个sensor使用sensor->readEvents读取数据

    static int poll__poll(struct sensors_poll_device_t *dev, sensors_event_t* data, int count) {
    sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
    return ctx->pollEvents(data, count);    // sensors_poll_context_t::pollEvents
        do {
            for (int i=0 ; count && i<numSensorDrivers ; i++) {
                SensorBase* const sensor(mSensors[i]);  // 转化为基类
                if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {
                    int nb = sensor->readEvents(data, count);   // 多态机制,读取数据
    
                    count -= nb;
                    nbEvents += nb;
                    data += nb;
                }
            }
        } while (n && count);
    }
  • hardware\akm\ak8975_fs\libsensors\AkmSensor.cpp
    具体sensor驱动

    // 得到指定设备的fd
    AkmSensor::AkmSensor()
    : SensorBase(NULL, "compass"),  // 对/dev/input/eventx进行ioctl(EVIOCGNAME)得到name,如果是"compass",则能使用该HAL code
    {
    mPendingEvents[MagneticField].version = sizeof(sensors_event_t);
    mPendingEvents[MagneticField].sensor = ID_M;
    mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD;    // 上报的数据类型
    mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
    }

再看数据读取函数,对接上Sensors.cpp

int AkmSensor::readEvents(sensors_event_t* data, int count)
    // 读取数据
    ssize_t n = mInputReader.fill(data_fd); // 
    // 处理数据
    while (count && mInputReader.readEvent(&event)) {
        int type = event->type;
        if (type == EV_ABS) {
            processEvent(event->code, event->value);    // 稍加处理
                case EVENT_TYPE_MAGV_X:
                    mPendingMask |= 1<<MagneticField;
                    mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M;
                    break;
            mInputReader.next();
        }
    }
  • hardware\akm\ak8975_fs\libsensors\SensorBase.cpp
    sensor的共有部分抽象

    // 遍历"/dev/input"下的所有节点,使用ioctl(EVIOCGNAME)得到name,看能否匹配上,匹配上则记录fd
    SensorBase::SensorBase(
    const char* dev_name,
    const char* data_name)
    : dev_name(dev_name), data_name(data_name),
      dev_fd(-1), data_fd(-1)
    data_fd = openInput(data_name);
        const char *dirname = "/dev/input";
        dir = opendir(dirname);
        strcpy(devname, dirname);
        filename = devname + strlen(devname);
        *filename++ = ‘/‘;
        while((de = readdir(dir))) {
            strcpy(filename, de->d_name);
            fd = open(devname, O_RDONLY);
            if (fd>=0) {
                char name[80];
                if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
                    name[0] = ‘\0‘;
                }
                if (!strcmp(name, inputName)) {
                    strcpy(input_name, filename);
                    break;
                }
            }
        }
        closedir(dir);
        return fd;
  • hardware\akm\ak8975_fs\libsensors\InputEventReader.cpp
    维护sensor数据
    ```
    // 读取"/dev/input/eventx"数据
    ssize_t InputEventCircularReader::fill(int fd)
    {
    // read name为compass的"/dev/input/eventx"
    const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event));

    numEventsRead = nread / sizeof(input_event);
    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;
    }

// 更新数据指针位置
ssize_t InputEventCircularReader::readEvent(input_event const** events)
{
*events = mCurr;
}
void InputEventCircularReader::next()
{
mCurr++;
}
```

以上是关于HAL的主要内容,如果未能解决你的问题,请参考以下文章

HAL

第1课第4.4节_Android硬件访问服务编写HAL代码

Android硬件抽象层(HAL)深入剖析

高通8155 GPS HAL层代码移植

Android深度探索(卷1)HAL与驱动开发 第九章 硬件抽象层:HAL 读书笔记

第九章 硬件抽象层:HAL