sensor__HAl分析(实现)

来源:互联网 发布:手机淘宝店铺二维码 编辑:程序博客网 时间:2024/05/01 22:07

首先是sensor这个模块的id定义,主要是实现了一个sensors_module_t结构:

struct sensors_module_t HAL_MODULE_INFO_SYM = {    .common = {        .tag = HARDWARE_MODULE_TAG,        .version_major = 1,        .version_minor = 0,        .id = SENSORS_HARDWARE_MODULE_ID,        .name = "MMA8451Q & AK8973A & gyro Sensors Module",        .author = "The RKdroid Project",        .methods = &sensors_module_methods,    },    .get_sensors_list = sensors__get_sensors_list};

sensors__get_sensors_list函数返回这个平台的所有sensor

static int sensors__get_sensors_list(struct sensors_module_t* module,        struct sensor_t const** list){    *list = sSensorList;    return ARRAY_SIZE(sSensorList);}

对应sSensorList是一个sensor_t的结构

static const struct sensor_t sSensorList[] = {        { "MMA8452Q 3-axis Accelerometer",                "Freescale Semiconductor",                1, SENSORS_HANDLE_BASE+ID_A,                SENSOR_TYPE_ACCELEROMETER, 4.0f*9.81f, (4.0f*9.81f)/256.0f, 0.2f, 0, { } },        { "AK8975 3-axis Magnetic field sensor",                "Asahi Kasei",                1, SENSORS_HANDLE_BASE+ID_M,                SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, 1.0f/16.0f, 6.8f, 0, { } },        { "AK8975 Orientation sensor",                "Asahi Kasei",                1, SENSORS_HANDLE_BASE+ID_O,                SENSOR_TYPE_ORIENTATION, 360.0f, 1.0f, 7.0f, 0, { } }, { "ST 3-axis Gyroscope sensor",          "STMicroelectronics",          1, SENSORS_HANDLE_BASE+ID_GY,          SENSOR_TYPE_GYROSCOPE, RANGE_GYRO, CONVERT_GYRO, 6.1f, 1190, { } },{ "AL3006Proximity sensor","Dyna Image Corporation",1, SENSORS_HANDLE_BASE+ID_P,SENSOR_TYPE_PROXIMITY,PROXIMITY_THRESHOLD_CM, PROXIMITY_THRESHOLD_CM,0.5f, 0, { } },        { "AL3006 light sensor",                "Dyna Image Corporation",                1, SENSORS_HANDLE_BASE+ID_L,                SENSOR_TYPE_LIGHT, 10240.0f, 1.0f, 0.5f, 0, { } },};

这个是我手头上的这块板子所提供的sensor

open_sensors用来打开所有的sensor,并返回一个hw_device_t

static int open_sensors(const struct hw_module_t* module, const char* name,        struct hw_device_t** device){    return init_nusensors(module, device);}

对应init_nusensors

int init_nusensors(hw_module_t const* module, hw_device_t** device){D("Entered.");    int status = -EINVAL;    sensors_poll_context_t *dev = new sensors_poll_context_t();    memset(&dev->device, 0, sizeof(sensors_poll_device_t));    dev->device.common.tag = HARDWARE_DEVICE_TAG;    dev->device.common.version  = 0;    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;    status = 0;    return status;}

首先new 了一个sensors_poll_context_t,然后设置device,并返回

对应new  sensors_poll_context_t我们看一下其实现

sensors_poll_context_t::sensors_poll_context_t(){D("Entered.");    mSensors[light] = new LightSensor();    mPollFds[light].fd = mSensors[light]->getFd();    mPollFds[light].events = POLLIN;    mPollFds[light].revents = 0;    mSensors[proximity] = new ProximitySensor();    mPollFds[proximity].fd = mSensors[proximity]->getFd();    mPollFds[proximity].events = POLLIN;    mPollFds[proximity].revents = 0;    mSensors[mma] = new MmaSensor();    mPollFds[mma].fd = mSensors[mma]->getFd();    mPollFds[mma].events = POLLIN;    mPollFds[mma].revents = 0;    mSensors[akm] = new AkmSensor();    mPollFds[akm].fd = mSensors[akm]->getFd();    mPollFds[akm].events = POLLIN;    mPollFds[akm].revents = 0;mSensors[gyro] = new GyroSensor();    mPollFds[gyro].fd = mSensors[gyro]->getFd();    mPollFds[gyro].events = POLLIN;    mPollFds[gyro].revents = 0;    int wakeFds[2];    int result = pipe(wakeFds);    LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));    fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);    fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);    mWritePipeFd = wakeFds[1];    mPollFds[wake].fd = wakeFds[0];    mPollFds[wake].events = POLLIN;    mPollFds[wake].revents = 0;}

mSensors是一个SensorBase类型的类,而mPollFds是一个pollfd的结构。

mSensors保存了各个打开的sensor,mPollFds用来监听sensor的时候用的。

我们以打开陀螺仪为例,看一下其打开过程

GyroSensor::GyroSensor()    : SensorBase(GY_DEVICE_NAME, "gyro"),      mEnabled(0),      mInputReader(32){    mPendingEvent.version = sizeof(sensors_event_t);    mPendingEvent.sensor = ID_GY;    mPendingEvent.type = SENSOR_TYPE_GYROSCOPE;    mPendingEvent.gyro.status = SENSOR_STATUS_ACCURACY_HIGH;    memset(mPendingEvent.data, 0x00, sizeof(mPendingEvent.data));int err = 0;    err = open_device();err = err<0 ? -errno : 0;if(err){LOGD("%s:%s\n",__func__,strerror(-err));return;}    int flags = 0;    if (!ioctl(dev_fd, L3G4200D_IOCTL_GET_ENABLE, &flags)) {        if (flags)  {            mEnabled = 1;        }    }    if (!mEnabled) {        close_device();    }}

mPendingEvent是一个  sensors_event_t结构,首先对其sensor、type等赋值,然后调用open_device打开陀螺仪设备,然后调用ioctlL3G4200D_IOCTL_GET_ENABLE查看sensor是否启用

注意这里不要忽略了SensorBase(GY_DEVICE_NAME, "gyro")

我们看一下它做了什么。

这里GY_DEVICE_NAME对应"/dev/gyrosensor"

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);}

设置dev_name和data_name后调用openInput打开设备

int SensorBase::openInput(const char* inputName) {    int fd = -1;    const char *dirname = "/dev/input";    char devname[PATH_MAX];    char *filename;    DIR *dir;    struct dirent *de;    return getInput(inputName);}

再继续看一下getInput

static int getInput(const char *inputName){    int fd = -1;    unsigned i;    static bool first = true;    static struct input_dev dev[255];    if (first) {        int fd = -1;        const char *dirname = "/dev/input";        char devname[PATH_MAX];        char *filename;        DIR *dir;        struct dirent *de;        first = false;        for (i = 0; i < sizeof(dev)/sizeof(dev[0]); i++) {            dev[i].fd = -1;            dev[i].name[0] = '\0';        }        i = 0;        dir = opendir(dirname);        if (dir == NULL)            return -1;        strcpy(devname, dirname);        filename = devname + strlen(devname);        *filename++ = '/';        while ((de = readdir(dir))) {            if (de->d_name[0] == '.' &&                (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))                    continue;            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) {                    dev[i].fd = fd;                    strncpy(dev[i].name, name, sizeof(dev[i].name));                }            }            i++;        }        closedir(dir);    }    for (i = 0; i < sizeof(dev)/sizeof(dev[0]); i++) {        if (!strncmp(inputName, dev[i].name, sizeof(dev[i].name))) {            fd = dev[i].fd;            break;        }    }    LOGE_IF(fd < 0, "couldn't find '%s' input device", inputName);    return fd;}

这个函数的作用就是打开"/dev/input",查找其中的输入设备名字与传入参数匹配的那一个,这里是"gyro",并返回相应的打开句柄。

再回到open_device

int SensorBase::open_device() {    if (dev_fd<0 && dev_name) {        dev_fd = open(dev_name, O_RDONLY);        if(dev_fd<0)        {LOGD("Couldn't open %s (%s)", dev_name, strerror(errno));return -errno;        }            }    return 0;}

这里只是简单的打开设备,对应"/dev/gyrosensor"

 

这样,再回到sensors_poll_context_t的构造函数,就把各个sensor设备都打开了,注意这里的mPollFds. Fd是data_fd,即打开“/dev/input/*”设备的句柄

到这里,sensor就已经打开了。

再看一下其它的函数。

Activate、setDelay都是直接调用相应的sensor接口直接调用相应sensor的接口,主要是pollEvents

int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count){D("Entered : count = %d", count);    int nbEvents = 0;    int n = 0;    do {        // see if we have some leftover from the last poll()        for (int i=0 ; count && i<numSensorDrivers ; i++) {//调用各个sensor的readEvents读取数据            SensorBase* const sensor(mSensors[i]);            if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {                int nb = sensor->readEvents(data, count);// num of evens received.D("nb = %d.", nb);                if (nb < count) {                    // no more data for this sensor                    mPollFds[i].revents = 0;                }                count -= nb;                nbEvents += nb;                data += nb;D("count = %d, nbEvents = %d, data = 0x%p.", count, nbEvents, data);            }        }        if (count) {            // we still have some room, so try to see if we can get            // some events immediately or just wait if we don't have            // anything to return            n = poll(mPollFds, numFds, nbEvents ? 0 : -1);            if (n<0) {                LOGE("poll() failed (%s)", strerror(errno));                return -errno;            }            if (mPollFds[wake].revents & POLLIN) {                char msg;                int result = read(mPollFds[wake].fd, &msg, 1);                LOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));                LOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));                mPollFds[wake].revents = 0;            }        }        // if we have events and space, go read themD("n =0x%x, count = 0x%x.", n, count);    } while (n && count);D("to return : nbEvents = %d", nbEvents);    return nbEvents;}

我们这里看一下GyroSensor的readEvents

int GyroSensor::readEvents(sensors_event_t* data, int count){    //LOGD("*******************Gyro readEvents");    //LOGD("count: %d, mHasPendingEvent: %d", count, mHasPendingEvent);    static int64_t prev_time;    int64_t time;    if (count < 1)        return -EINVAL;    if (mHasPendingEvent) {        mHasPendingEvent = false;        mPendingEvent.timestamp = getTimestamp();        *data = mPendingEvent;        return mEnabled ? 1 : 0;    }    ssize_t n = mInputReader.fill(data_fd);//从输入设备中读取数据    if (n < 0)        return n;    int numEventReceived = 0;    input_event const* event;    float gyrox = 0, gyroy = 0, gyroz = 0;#if FETCH_FULL_EVENT_BEFORE_RETURNagain:#endif    while (count && mInputReader.readEvent(&event)) {//读取当前一个event,返回还有的数据大小        //LOGD("GyroSensor::readEvents() coutn = %d, event->value = %f", count, event->value);        int type = event->type;        if (type == EV_REL) {//为事件相对坐标            float value = event->value;            if (event->code == EVENT_TYPE_GYRO_X) {                gyrox = value;            } else if (event->code == EVENT_TYPE_GYRO_Y) {                gyroy = value;            } else if (event->code == EVENT_TYPE_GYRO_Z) {                gyroz = value;            }    NineAxisTypeDef nineInput;            nineInput.ax =  1;            nineInput.ay =  1;            nineInput.az =  1000;            nineInput.mx =  300;            nineInput.my =  300;            nineInput.mz =  300;            nineInput.gx =  gyrox;            nineInput.gy =  gyroy;            nineInput.gz =  gyroz;            nineInput.time = getTimestamp()/1000000;            FusionTypeDef fusionData = MEMSAlgLib_Fusion_Update(nineInput);            float offx, offy, offz;            MEMSAlgLib_Fusion_Get_GyroOffset(&offx,&offy,&offz);            //LOGD("gyro offset: %f, %f, %f", offx, offy, offz);            mPendingEvent.data[0] = (gyrox-offx) * CONVERT_GYRO_X;            mPendingEvent.data[1] = (gyroy-offy) * CONVERT_GYRO_Y;            mPendingEvent.data[2] = (gyroz-offz) * CONVERT_GYRO_Z;    mPendingEvent.gyro.x =  mPendingEvent.data[0];            mPendingEvent.gyro.y =  mPendingEvent.data[1];            mPendingEvent.gyro.z =  mPendingEvent.data[2];    //LOGD("mPendingEvent: %f, %f, %f", mPendingEvent.gyro.x, mPendingEvent.gyro.y, mPendingEvent.gyro.z);        }else if (type == EV_SYN) {//表示Motion的一系列动作结束                       time = timevalToNano(event->time);            if(mEnabled) {                mPendingEvent.timestamp = time;                *data++ = mPendingEvent;                count--;                numEventReceived++;            }        }else {            LOGE("GyroSensor: unknown event (type=%d, code=%d)", type, event->code);        }        mInputReader.next();    }#if FETCH_FULL_EVENT_BEFORE_RETURN    /* if we didn't read a complete event, see if we can fill and       try again instead of returning with nothing and redoing poll. */    if (numEventReceived == 0 && mEnabled == 1) {        n = mInputReader.fill(data_fd);        if (n)            goto again;    }#endif    return numEventReceived;}

这里看一下mInputReader,是一个InputEventCircularReader结构,表示的是一个环形的读入数据缓冲区

ssize_t InputEventCircularReader::fill(int fd){    size_t numEventsRead = 0;    if (mFreeSpace) {        const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event));//读取数据        if (nread<0 || nread % sizeof(input_event)) {            // we got a partial event!!            return nread<0 ? -errno : -EINVAL;        }        numEventsRead = nread / sizeof(input_event);        // dumpEvents(mHead, numEventsRead);        D("nread = %ld, numEventsRead = %d.", nread, numEventsRead);        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;}

mCurr表示未读事件的第一个,初始为缓冲区首部

Fill函数是把调用read从相应的输入设备读入数据mHead位置

readEvent函数返回mCurr和剩余的数据大小

next函数让mCurr移一个input_event



到这里,sensor HAL层就分析完了