sensor__HAl分析(实现)

首先是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 them
		D("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_RETURN
again:
#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层就分析完了

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值