首先是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层就分析完了