四、安卓hal层驱动初始化
安卓hal层驱动的源码在/ingenicandroid/hardware/invensense/65xx/libsensors_iio/
在sensors_mpl.cpp中有个传感器描述的结构体,包含陀螺仪的信息及获取信息的handler:sensors__get_sensors_list;
在初始化时hw_get_module()会加载这个结构体。
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: "Invensense module", author: "Invensense Inc.", methods: &sensors_module_methods, dso: NULL, reserved: {0} }, get_sensors_list: sensors__get_sensors_list, };
这里是给上层调用的接口
static struct hw_module_methods_t sensors_module_methods = { open: open_sensors }; struct sensors_poll_context_t { sensors_poll_device_1_t device; // must be first sensors_poll_context_t(); ~sensors_poll_context_t(); int activate(int handle, int enabled); //enable sensor int setDelay(int handle, int64_t ns); int pollEvents(sensors_event_t* data, int count); int query(int what, int *value); int batch(int handle, int flags, int64_t period_ns, int64_t timeout); int flush(int handle); ....... };先看open_sensors,这个函数初始化sensors_poll_context这个结构体
static int open_sensors(const struct hw_module_t* module, const char* id, struct hw_device_t** device) { FUNC_LOG; int status = -EINVAL; sensors_poll_context_t *dev = new sensors_poll_context_t(); memset(&dev->device, 0, sizeof(sensors_poll_device_1)); dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_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; /* Batch processing */ dev->device.batch = poll__batch; dev->device.flush = poll__flush; *device = &dev->device.common; status = 0; return status; }
主要关注的是poll__activate、poll__poll、poll__close这三个。
在讨论这三个接口之前,先看下MPLSensor这个对象的构造函数
MPLSensor::MPLSensor(CompassSensor *compass, int (*m_pt2AccelCalLoadFunc)(long *)) : SensorBase(NULL, NULL), mNewData(0), mMasterSensorMask(INV_ALL_SENSORS), mLocalSensorMask(0), mPollTime(-1), mStepCountPollTime(-1), mHaveGoodMpuCal(0), mGyroAccuracy(0), mAccelAccuracy(0), mCompassAccuracy(0), mSampleCount(0), dmp_orient_fd(-1), mDmpOrientationEnabled(0), dmp_sign_motion_fd(-1), mDmpSignificantMotionEnabled(0), dmp_pedometer_fd(-1), mDmpPedometerEnabled(0), mDmpStepCountEnabled(0), mEnabled(0), mBatchEnabled(0), mFlushEnabled(-1), mOldBatchEnabledMask(0), mAccelInputReader(4), mGyroInputReader(32), mTempScale(0), mTempOffset(0), mTempCurrentTime(0), mAccelScale(2), mAccelSelfTestScale(2), mGyroScale(2000), mGyroSelfTestScale(2000), mCompassScale(0), mFactoryGyroBiasAvailable(false), mGyroBiasAvailable(false), mGyroBiasApplied(false), mFactoryAccelBiasAvailable(false), mAccelBiasAvailable(false), mAccelBiasApplied(false), mPendingMask(0), mSensorMask(0), mMplFeatureActiveMask(0), mFeatureActiveMask(0), mDmpOn(0), mPedUpdate(0), mPressureUpdate(0), mQuatSensorTimestamp(0), mStepSensorTimestamp(0), mLastStepCount(0), mLeftOverBufferSize(0), mInitial6QuatValueAvailable(0), mFlushBatchSet(0), mSkipReadEvents(0) { VFUNC_LOG; inv_error_t rv; int i, fd; char *port = NULL; char *ver_str; unsigned long mSensorMask; int res; FILE *fptr; mCompassSensor = compass; LOGI("HAL:MPLSensor constructor : NumSensors = %d", NumSensors); pthread_mutex_init(&mMplMutex, NULL); pthread_mutex_init(&mHALMutex, NULL); memset(mGyroOrientation, 0, sizeof(mGyroOrientation)); memset(mAccelOrientation, 0, sizeof(mAccelOrientation)); /* setup sysfs paths */ inv_init_sysfs_attributes(); /* get chip name */ if (inv_get_chip_name(chip_ID) != INV_SUCCESS) { LOGE("HAL:ERR- Failed to get chip ID\n"); } else { LOGI("HAL:Chip ID= %s\n", chip_ID); } enable_iio_sysfs(); /* reset driver master enable */ masterEnable(0); /* open temperature fd for temp comp */ LOGI("HAL:gyro temperature path: %s", mpu.temperature); gyro_temperature_fd = open(mpu.temperature, O_RDONLY); if (gyro_temperature_fd == -1) { LOGE("HAL:could not open temperature node"); } else { LOGI("HAL:temperature_fd opened: %s", mpu.temperature); } /* read gyro FSR to calculate accel scale later */ char gyroBuf[5]; int count = 0; LOGI("HAL:sysfs:cat %s (%lld)", mpu.gyro_fsr, getTimestamp()); fd = open(mpu.gyro_fsr, O_RDONLY); if(fd < 0) { LOGE("HAL:Error opening gyro FSR"); } else { memset(gyroBuf, 0, sizeof(gyroBuf)); count = read_attribute_sensor(fd, gyroBuf, sizeof(gyroBuf)); if(count < 1) { LOGE("HAL:Error reading gyro FSR"); } else { count = sscanf(gyroBuf, "%ld", &mGyroScale); if(count) LOGI("HAL:Gyro FSR used %ld", mGyroScale); } close(fd); } /* read gyro self test scale used to calculate factory cal bias later */ char gyroScale[5]; LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:cat %s (%lld)", mpu.in_gyro_self_test_scale, getTimestamp()); fd = open(mpu.in_gyro_self_test_scale, O_RDONLY); if(fd < 0) { LOGE("HAL:Error opening gyro self test scale"); } else { memset(gyroBuf, 0, sizeof(gyroBuf)); count = read_attribute_sensor(fd, gyroScale, sizeof(gyroScale)); if(count < 1) { LOGE("HAL:Error reading gyro self test scale"); } else { count = sscanf(gyroScale, "%ld", &mGyroSelfTestScale); if(count) LOGI("HAL:Gyro self test scale used %ld", mGyroSelfTestScale); } close(fd); } /* open Factory Gyro Bias fd */ /* mFactoryGyBias contains bias values that will be used for device offset */ memset(mFactoryGyroBias, 0, sizeof(mFactoryGyroBias)); LOGV_IF(EXTRA_VERBOSE, "HAL:factory gyro x offset path: %s", mpu.in_gyro_x_offset); LOGV_IF(EXTRA_VERBOSE, "HAL:factory gyro y offset path: %s", mpu.in_gyro_y_offset); LOGV_IF(EXTRA_VERBOSE, "HAL:factory gyro z offset path: %s", mpu.in_gyro_z_offset); gyro_x_offset_fd = open(mpu.in_gyro_x_offset, O_RDWR); gyro_y_offset_fd = open(mpu.in_gyro_y_offset, O_RDWR); gyro_z_offset_fd = open(mpu.in_gyro_z_offset, O_RDWR); if (gyro_x_offset_fd == -1 || gyro_y_offset_fd == -1 || gyro_z_offset_fd == -1) { LOGE("HAL:could not open factory gyro calibrated bias"); } else { LOGI("HAL:gyro_offset opened"); } /* read accel FSR to calcuate accel scale later */ if (USE_THIRD_PARTY_ACCEL == 0) { char buf[3]; int count = 0; LOGI("HAL:sysfs:cat %s (%lld)", mpu.accel_fsr, getTimestamp()); fd = open(mpu.accel_fsr, O_RDONLY); if(fd < 0) { LOGE("HAL:Error opening accel FSR"); } else { memset(buf, 0, sizeof(buf)); count = read_attribute_sensor(fd, buf, sizeof(buf)); if(count < 1) { LOGE("HAL:Error reading accel FSR"); } else { count = sscanf(buf, "%d", &mAccelScale); if(count) LOGI("HAL:Accel FSR used %d", mAccelScale); } close(fd); } /* read accel self test scale used to calculate factory cal bias later */ char accelScale[5]; LOGI("HAL:sysfs:cat %s (%lld)", mpu.in_accel_self_test_scale, getTimestamp()); fd = open(mpu.in_accel_self_test_scale, O_RDONLY); if(fd < 0) { LOGE("HAL:Error opening gyro self test scale"); } else { memset(buf, 0, sizeof(buf)); count = read_attribute_sensor(fd, accelScale, sizeof(accelScale)); if(count < 1) { LOGE("HAL:Error reading accel self test scale"); } else { count = sscanf(accelScale, "%ld", &mAccelSelfTestScale); if(count) LOGI("HAL:Accel self test scale used %ld", mAccelSelfTestScale); } close(fd); } /* open Factory Accel Bias fd */ /* mFactoryAccelBias contains bias values that will be used for device offset */ memset(mFactoryAccelBias, 0, sizeof(mFactoryAccelBias)); LOGV_IF(EXTRA_VERBOSE, "HAL:factory accel x offset path: %s", mpu.in_accel_x_offset); LOGV_IF(EXTRA_VERBOSE, "HAL:factory accel y offset path: %s", mpu.in_accel_y_offset); LOGV_IF(EXTRA_VERBOSE, "HAL:factory accel z offset path: %s", mpu.in_accel_z_offset); accel_x_offset_fd = open(mpu.in_accel_x_offset, O_RDWR); accel_y_offset_fd = open(mpu.in_accel_y_offset, O_RDWR); accel_z_offset_fd = open(mpu.in_accel_z_offset, O_RDWR); if (accel_x_offset_fd == -1 || accel_y_offset_fd == -1 || accel_z_offset_fd == -1) { LOGE("HAL:could not open factory accel calibrated bias"); } else { LOGI("HAL:accel_offset opened"); } } (void)inv_get_version(&ver_str); LOGI("%s\n", ver_str); /* setup MPL */ inv_constructor_init(); /* setup orientation matrix and scale */ inv_set_device_properties(); /* initialize sensor data */ memset(mPendingEvents, 0, sizeof(mPendingEvents)); mPendingEvents[RotationVector].version = sizeof(sensors_event_t); mPendingEvents[RotationVector].sensor = ID_RV; mPendingEvents[RotationVector].type = SENSOR_TYPE_ROTATION_VECTOR; mPendingEvents[RotationVector].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH; mPendingEvents[GameRotationVector].version = sizeof(sensors_event_t); mPendingEvents[GameRotationVector].sensor = ID_GRV; mPendingEvents[GameRotationVector].type = SENSOR_TYPE_GAME_ROTATION_VECTOR; mPendingEvents[GameRotationVector].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH; mPendingEvents[LinearAccel].version = sizeof(sensors_event_t); mPendingEvents[LinearAccel].sensor = ID_LA; mPendingEvents[LinearAccel].type = SENSOR_TYPE_LINEAR_ACCELERATION; mPendingEvents[LinearAccel].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH; mPendingEvents[Gravity].version = sizeof(sensors_event_t); mPendingEvents[Gravity].sensor = ID_GR; mPendingEvents[Gravity].type = SENSOR_TYPE_GRAVITY; mPendingEvents[Gravity].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH; mPendingEvents[Gyro].version = sizeof(sensors_event_t); mPendingEvents[Gyro].sensor = ID_GY; mPendingEvents[Gyro].type = SENSOR_TYPE_GYROSCOPE; mPendingEvents[Gyro].gyro.status = SENSOR_STATUS_ACCURACY_HIGH; mPendingEvents[RawGyro].version = sizeof(sensors_event_t); mPendingEvents[RawGyro].sensor = ID_RG; mPendingEvents[RawGyro].type = SENSOR_TYPE_GYROSCOPE_UNCALIBRATED; mPendingEvents[RawGyro].gyro.status = SENSOR_STATUS_ACCURACY_HIGH; mPendingEvents[Accelerometer].version = sizeof(sensors_event_t); mPendingEvents[Accelerometer].sensor = ID_A; mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER; mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH; /* Invensense compass calibration */ 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; mPendingEvents[RawMagneticField].version = sizeof(sensors_event_t); mPendingEvents[RawMagneticField].sensor = ID_RM; mPendingEvents[RawMagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED; mPendingEvents[RawMagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH; mPendingEvents[Pressure].version = sizeof(sensors_event_t); mPendingEvents[Pressure].sensor = ID_PS; mPendingEvents[Pressure].type = SENSOR_TYPE_PRESSURE; mPendingEvents[Pressure].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH; mPendingEvents[Orientation].version = sizeof(sensors_event_t); mPendingEvents[Orientation].sensor = ID_O; mPendingEvents[Orientation].type = SENSOR_TYPE_ORIENTATION; mPendingEvents[Orientation].orientation.status = SENSOR_STATUS_ACCURACY_HIGH; mPendingEvents[GeomagneticRotationVector].version = sizeof(sensors_event_t); mPendingEvents[GeomagneticRotationVector].sensor = ID_GMRV; mPendingEvents[GeomagneticRotationVector].type = SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR; mPendingEvents[GeomagneticRotationVector].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH; #ifndef KLP mHandlers[RotationVector] = &MPLSensor::rvHandler; #else mHandlers[RotationVector] = &MPLSensor::grvHandler; #endif mHandlers[GameRotationVector] = &MPLSensor::grvHandler; mHandlers[LinearAccel] = &MPLSensor::laHandler; mHandlers[Gravity] = &MPLSensor::gravHandler; #ifndef KLP mHandlers[Gyro] = &MPLSensor::gyroHandler; #else mHandlers[Gyro] = &MPLSensor::rawGyroHandler; #endif mHandlers[RawGyro] = &MPLSensor::rawGyroHandler; mHandlers[Accelerometer] = &MPLSensor::accelHandler; #ifndef KLP mHandlers[MagneticField] = &MPLSensor::compassHandler; #else mHandlers[MagneticField] = &MPLSensor::rawCompassHandler; #endif mHandlers[RawMagneticField] = &MPLSensor::rawCompassHandler; mHandlers[Orientation] = &MPLSensor::orienHandler; mHandlers[GeomagneticRotationVector] = &MPLSensor::gmHandler; // mHandlers[Pressure] = &MPLSensor::psHandler; for (int i = 0; i < NumSensors; i++) { mDelays[i] = 1000000000LL; mBatchDelays[i] = 1000000000LL; mBatchTimeouts[i] = 100000000000LL; } /* initialize Compass Bias */ memset(mCompassBias, 0, sizeof(mCompassBias)); /* initialize Factory Accel Bias */ memset(mFactoryAccelBias, 0, sizeof(mFactoryAccelBias)); /* initialize Gyro Bias */ memset(mGyroBias, 0, sizeof(mGyroBias)); memset(mGyroChipBias, 0, sizeof(mGyroChipBias)); /* takes external accel calibration load workflow */ if( m_pt2AccelCalLoadFunc != NULL) { long accel_offset[3]; long tmp_offset[3]; int result = m_pt2AccelCalLoadFunc(accel_offset); if(result) LOGW("HAL:Vendor accelerometer calibration file load failed %d\n", result); else { LOGW("HAL:Vendor accelerometer calibration file successfully " "loaded"); inv_get_mpl_accel_bias(tmp_offset, NULL); LOGI("HAL:Original accel offset, %ld, %ld, %ld\n", tmp_offset[0], tmp_offset[1], tmp_offset[2]); inv_set_accel_bias_mask(accel_offset, mAccelAccuracy,4); inv_get_mpl_accel_bias(tmp_offset, NULL); LOGI("HAL:Set accel offset, %ld, %ld, %ld\n", tmp_offset[0], tmp_offset[1], tmp_offset[2]); } } /* end of external accel calibration load workflow */ /* disable driver master enable the first sensor goes on */ masterEnable(0); enableGyro(0); enableLowPowerAccel(0); enableAccel(0); enableCompass(0,0); enableBatch(0); if (isLowPowerQuatEnabled()) { enableLPQuaternion(0); } if (isDmpDisplayOrientationOn()) { // open DMP Orient Fd openDmpOrientFd(); enableDmpOrientation(!isDmpScreenAutoRotationEnabled()); } }这个构造函数做了些各个对象初始化
poll__activate调用流程:
static int poll__activate(struct sensors_poll_device_t *dev, int handle, int enabled) { LOGI("HAL: dev->poll__activate start\n"); sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; return ctx->activate(handle, enabled); }
int sensors_poll_context_t::activate(int handle, int enabled) { FUNC_LOG; int err; err = mSensor->enable(handle, enabled); if (!err) { const char wakeMessage(WAKE_MESSAGE); int result = write(mWritePipeFd, &wakeMessage, 1); LOGE_IF(result < 0, "error sending wake message (%s)", strerror(errno)); } return err; }
int MPLSensor::enable(int32_t handle, int en) { VFUNC_LOG; android::String8 sname; int what = -1, err = 0; int batchMode = 0; LOGI("HAL:enter enable handle:%d,en:%d\n",handle,en); if (write_sysfs_int(mpu.sensor_enable, en) < 0) { LOGE("HAL:sensor_enable err\n"); } switch (handle) { case ID_A: what = Accelerometer; sname = "Accelerometer"; break; case ID_M: what = MagneticField; sname = "MagneticField"; break; case ID_GY: what = Gyro; sname = "Gyro"; break; case ID_GR: what = Gravity; sname = "Gravity"; break; default: //this takes care of all the gestures what = handle; sname = "Others"; break; } if (uint32_t(what) >= NumSensors) return -EINVAL; int newState = en ? 1 : 0; unsigned long sen_mask; LOGV_IF(PROCESS_VERBOSE, "HAL:enable - sensor %s (handle %d) %s -> %s", sname.string(), handle, ((mEnabled & (1 << what)) ? "en" : "dis"), ((uint32_t(newState) << what) ? "en" : "dis")); LOGV_IF(ENG_VERBOSE, "HAL:%s sensor state change what=%d", sname.string(), what); if ((uint32_t(newState) << what) != (mEnabled & (1 << what))) { uint32_t sensor_type; short flags = newState; uint32_t lastEnabled = mEnabled, changed = 0; mEnabled &= ~(1 << what); mEnabled |= (uint32_t(flags) << what); LOGV_IF(ENG_VERBOSE, "HAL:handle = %d", handle); LOGV_IF(ENG_VERBOSE, "HAL:flags = %d", flags); computeLocalSensorMask(mEnabled); LOGV_IF(ENG_VERBOSE, "HAL:enable : mEnabled = %d", mEnabled); LOGV_IF(ENG_VERBOSE, "HAL:last enable : lastEnabled = %d", lastEnabled); sen_mask = mLocalSensorMask & mMasterSensorMask; mSensorMask = sen_mask; LOGV_IF(ENG_VERBOSE, "HAL:sen_mask= 0x%0lx", sen_mask); switch (what) { case Gyro: case Accelerometer: if ((!(mEnabled & VIRTUAL_SENSOR_GYRO_6AXES_MASK) && !(mEnabled & VIRTUAL_SENSOR_9AXES_MASK)) && ((lastEnabled & (1 << what)) != (mEnabled & (1 << what)))) { changed |= (1 << what); } if (mFeatureActiveMask & INV_DMP_6AXIS_QUATERNION) { changed |= (1 << what); } break; case MagneticField: case RawMagneticField: if (!(mEnabled & VIRTUAL_SENSOR_9AXES_MASK) && ((lastEnabled & (1 << what)) != (mEnabled & (1 << what)))) { changed |= (1 << what); } break; } LOGV_IF(ENG_VERBOSE, "HAL:changed = %d", changed); enableSensors(sen_mask, flags, changed); } return err; }
if (write_sysfs_int(mpu.sensor_enable, en) < 0) { LOGE("HAL:sensor_enable err\n"); }
int write_sysfs_int(char *filename, int var) { int res=0; FILE *sysfsfp; sysfsfp = fopen(filename, "w"); if (sysfsfp != NULL) { if (fprintf(sysfsfp, "%d\n", var) < 0 || fclose(sysfsfp) < 0) { res = errno; LOGE("HAL:ERR open file %s to write with error %d", filename, res); } } return -res; }
到这里就可以看到访问sys设备节点了,通过mpu.sensor_enable这个节点访问内核空间
节点文件在构造函数中已经被初始化
int MPLSensor::inv_init_sysfs_attributes(void) { VFUNC_LOG; LOGI("HAL:enter inv_init_sysfs_attributes\n"); unsigned char i = 0; char sysfs_path[MAX_SYSFS_NAME_LEN]; char tbuf[2]; char *sptr; char **dptr; int num; memset(sysfs_path, 0, sizeof(sysfs_path)); sysfs_names_ptr = (char*)malloc(sizeof(char[MAX_SYSFS_ATTRB][MAX_SYSFS_NAME_LEN])); sptr = sysfs_names_ptr; if (sptr != NULL) { dptr = (char**)&mpu; do { *dptr++ = sptr; memset(sptr, 0, sizeof(sptr)); sptr += sizeof(char[MAX_SYSFS_NAME_LEN]); } while (++i < MAX_SYSFS_ATTRB); } else { LOGE("HAL:couldn't alloc mem for sysfs paths"); return -1; } // get proper (in absolute) IIO path & build MPU's sysfs paths inv_get_sysfs_path(sysfs_path); if (strcmp(sysfs_path, "") == 0) return 0; memcpy(mSysfsPath, sysfs_path, sizeof(sysfs_path)); sprintf(mpu.key, "%s%s", sysfs_path, "/key"); sprintf(mpu.chip_enable, "%s%s", sysfs_path, "/buffer/enable"); sprintf(mpu.buffer_length, "%s%s", sysfs_path, "/buffer/length"); sprintf(mpu.master_enable, "%s%s", sysfs_path, "/master_enable"); sprintf(mpu.power_state, "%s%s", sysfs_path, "/power_state"); sprintf(mpu.in_timestamp_en, "%s%s", sysfs_path, "/scan_elements/in_timestamp_en"); sprintf(mpu.in_timestamp_index, "%s%s", sysfs_path, "/scan_elements/in_timestamp_index"); sprintf(mpu.in_timestamp_type, "%s%s", sysfs_path, "/scan_elements/in_timestamp_type"); sprintf(mpu.dmp_firmware, "%s%s", sysfs_path, "/dmp_firmware"); sprintf(mpu.firmware_loaded, "%s%s", sysfs_path, "/firmware_loaded"); sprintf(mpu.dmp_on, "%s%s", sysfs_path, "/dmp_on"); sprintf(mpu.dmp_int_on, "%s%s", sysfs_path, "/dmp_int_on"); sprintf(mpu.dmp_event_int_on, "%s%s", sysfs_path, "/dmp_event_int_on"); sprintf(mpu.tap_on, "%s%s", sysfs_path, "/tap_on"); sprintf(mpu.self_test, "%s%s", sysfs_path, "/self_test"); sprintf(mpu.temperature, "%s%s", sysfs_path, "/temperature"); sprintf(mpu.gyro_enable, "%s%s", sysfs_path, "/gyro_enable"); sprintf(mpu.sensor_enable, "%s%s", sysfs_path, "/sensor_enable"); sprintf(mpu.gyro_fifo_rate, "%s%s", sysfs_path, "/sampling_frequency"); sprintf(mpu.gyro_orient, "%s%s", sysfs_path, "/gyro_matrix"); sprintf(mpu.gyro_fifo_enable, "%s%s", sysfs_path, "/gyro_fifo_enable"); sprintf(mpu.gyro_fsr, "%s%s", sysfs_path, "/in_anglvel_scale"); sprintf(mpu.gyro_fifo_enable, "%s%s", sysfs_path, "/gyro_fifo_enable"); sprintf(mpu.gyro_rate, "%s%s", sysfs_path, "/gyro_rate"); sprintf(mpu.accel_enable, "%s%s", sysfs_path, "/accel_enable"); sprintf(mpu.accel_fifo_rate, "%s%s", sysfs_path, "/sampling_frequency"); sprintf(mpu.accel_orient, "%s%s", sysfs_path, "/accel_matrix"); sprintf(mpu.accel_fifo_enable, "%s%s", sysfs_path, "/accel_fifo_enable"); sprintf(mpu.accel_rate, "%s%s", sysfs_path, "/accel_rate"); #ifndef THIRD_PARTY_ACCEL //MPUxxxx sprintf(mpu.accel_fsr, "%s%s", sysfs_path, "/in_accel_scale"); // DMP uses these values sprintf(mpu.in_accel_x_dmp_bias, "%s%s", sysfs_path, "/in_accel_x_dmp_bias"); sprintf(mpu.in_accel_y_dmp_bias, "%s%s", sysfs_path, "/in_accel_y_dmp_bias"); sprintf(mpu.in_accel_z_dmp_bias, "%s%s", sysfs_path, "/in_accel_z_dmp_bias"); // MPU uses these values sprintf(mpu.in_accel_x_offset, "%s%s", sysfs_path, "/in_accel_x_offset"); sprintf(mpu.in_accel_y_offset, "%s%s", sysfs_path, "/in_accel_y_offset"); sprintf(mpu.in_accel_z_offset, "%s%s", sysfs_path, "/in_accel_z_offset"); sprintf(mpu.in_accel_self_test_scale, "%s%s", sysfs_path, "/in_accel_self_test_scale"); #endif // DMP uses these bias values sprintf(mpu.in_gyro_x_dmp_bias, "%s%s", sysfs_path, "/in_anglvel_x_dmp_bias"); sprintf(mpu.in_gyro_y_dmp_bias, "%s%s", sysfs_path, "/in_anglvel_y_dmp_bias"); sprintf(mpu.in_gyro_z_dmp_bias, "%s%s", sysfs_path, "/in_anglvel_z_dmp_bias"); // MPU uses these bias values sprintf(mpu.in_gyro_x_offset, "%s%s", sysfs_path, "/in_anglvel_x_offset"); sprintf(mpu.in_gyro_y_offset, "%s%s", sysfs_path, "/in_anglvel_y_offset"); sprintf(mpu.in_gyro_z_offset, "%s%s", sysfs_path, "/in_anglvel_z_offset"); sprintf(mpu.in_gyro_self_test_scale, "%s%s", sysfs_path, "/in_anglvel_self_test_scale"); sprintf(mpu.three_axis_q_on, "%s%s", sysfs_path, "/three_axes_q_on"); //formerly quaternion_on sprintf(mpu.three_axis_q_rate, "%s%s", sysfs_path, "/three_axes_q_rate"); sprintf(mpu.ped_q_on, "%s%s", sysfs_path, "/ped_q_on"); sprintf(mpu.ped_q_rate, "%s%s", sysfs_path, "/ped_q_rate"); sprintf(mpu.six_axis_q_on, "%s%s", sysfs_path, "/six_axes_q_on"); sprintf(mpu.six_axis_q_rate, "%s%s", sysfs_path, "/six_axes_q_rate"); sprintf(mpu.six_axis_q_value, "%s%s", sysfs_path, "/six_axes_q_value"); sprintf(mpu.step_detector_on, "%s%s", sysfs_path, "/step_detector_on"); sprintf(mpu.step_indicator_on, "%s%s", sysfs_path, "/step_indicator_on"); sprintf(mpu.display_orientation_on, "%s%s", sysfs_path, "/display_orientation_on"); sprintf(mpu.event_display_orientation, "%s%s", sysfs_path, "/event_display_orientation"); sprintf(mpu.event_smd, "%s%s", sysfs_path, "/event_smd"); sprintf(mpu.smd_enable, "%s%s", sysfs_path, "/smd_enable"); sprintf(mpu.smd_delay_threshold, "%s%s", sysfs_path, "/smd_delay_threshold"); sprintf(mpu.smd_delay_threshold2, "%s%s", sysfs_path, "/smd_delay_threshold2"); sprintf(mpu.smd_threshold, "%s%s", sysfs_path, "/smd_threshold"); sprintf(mpu.batchmode_timeout, "%s%s", sysfs_path, "/batchmode_timeout"); sprintf(mpu.batchmode_wake_fifo_full_on, "%s%s", sysfs_path, "/batchmode_wake_fifo_full_on"); sprintf(mpu.flush_batch, "%s%s", sysfs_path, "/flush_batch"); sprintf(mpu.pedometer_on, "%s%s", sysfs_path, "/pedometer_on"); sprintf(mpu.pedometer_int_on, "%s%s", sysfs_path, "/pedometer_int_on"); sprintf(mpu.event_pedometer, "%s%s", sysfs_path, "/event_pedometer"); sprintf(mpu.pedometer_steps, "%s%s", sysfs_path, "/pedometer_steps"); sprintf(mpu.motion_lpa_on, "%s%s", sysfs_path, "/motion_lpa_on"); return 0; }
从这里看到masterEnable()访问了/sensor_enable这个设备节点,路径在/sys/bus/iio/devices/iio:device0中
sprintf(mpu.sensor_enable, "%s%s", sysfs_path, "/sensor_enable");
在内核中有这么一段代码,创建了这个设备节点
static IIO_DEVICE_ATTR(sensor_enable, S_IRUGO | S_IWUSR, inv_attr_show, inv_attr_store, ATTR_SENSOR_ENABLE);
其中inv_attr_show为读操作的handler,inv_attr_store为写操作的handler,主要看下写操作的
static ssize_t _attr_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct inv_mpu_state *st = iio_priv(indio_dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int data,en; u8 d, axis; int result; result = 0; if (st->chip_config.enable) return -EBUSY; if (this_attr->address <= ATTR_MOTION_LPA_THRESHOLD) { result = st->set_power_state(st, true); if (result) return result; } /* check the input and validate it's format */ switch (this_attr->address) { /* these inputs are integers */ default: result = kstrtoint(buf, 10, &data); if (result) goto attr_store_fail; break; } switch (this_attr->address) { ...... case ATTR_SENSOR_ENABLE: en = *buf - '0'; if(en){ inv_i2c_single_write(st, REG_FIFO_EN,0x00); if (result){ PRINT_ERR("======REG_FIFO_EN err======\n"); } inv_i2c_single_write(st,REG_PWR_MGMT_1,KR_SENSOR_ON); if (result){ PRINT_ERR("======REG_PWR_MGMT_1 err======\n"); } result = inv_secondary_write(REG_AKM_MODE, DATA_AKM_MODE_SM); if (result){ PRINT_ERR("======REG_AKM_MODE err======\n"); } result = inv_i2c_single_write(st, REG_INT_ENABLE,0x01); if (result){ PRINT_ERR("======REG_INT_ENABLE err======\n"); } } else{ result = inv_i2c_single_write(st, REG_INT_ENABLE,0x00); if (result){ PRINT_ERR("======REG_INT_ENABLE err======\n"); } inv_i2c_single_write(st, REG_FIFO_EN,0x00); if (result){ PRINT_ERR("======REG_FIFO_EN err======\n"); } inv_i2c_single_write(st,REG_PWR_MGMT_1,KR_SENSOR_OFF); if (result){ PRINT_ERR("======REG_PWR_MGMT_1 err======\n"); } result = inv_secondary_write(REG_AKM_MODE, DATA_AKM_MODE_PD); if (result){ PRINT_ERR("======REG_AKM_MODE err======\n"); } } break; case ATTR_GYRO_ENABLE: st->chip_config.gyro_enable = !!data; PRINT_DBG("----------->st->chip_config.gyro_enable:%d===\n",st->chip_config.gyro_enable); break; ...... default: result = -EINVAL; goto attr_store_fail; }; attr_store_fail: if (this_attr->address <= ATTR_MOTION_LPA_THRESHOLD) result |= st->set_power_state(st, false); if (result) return result; return count; }
在这个函数中给陀螺仪发送启动参数
之前说过陀螺仪分加速度计、角加速度计和磁强计,所以还需要单独开启,这根据app是否开启这三个功能,这里就举例角加速度计的流程
res = enableGyro(!!(sensors & INV_THREE_AXIS_GYRO));
int MPLSensor::enableGyro(int en) { VFUNC_LOG; int res = 0; LOGI("HAL:enter enableGyro : %d\n",en); /* need to also turn on/off the master enable */ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)", en, mpu.gyro_enable, getTimestamp()); res = write_sysfs_int(mpu.gyro_enable, en); LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)", en, mpu.gyro_fifo_enable, getTimestamp()); res += write_sysfs_int(mpu.gyro_fifo_enable, en); if (!en) { LOGV_IF(EXTRA_VERBOSE, "HAL:MPL:inv_gyro_was_turned_off"); inv_gyro_was_turned_off(); } return res; }
同样是通过sys设备节点操作。
static IIO_DEVICE_ATTR(gyro_enable, S_IRUGO | S_IWUSR, inv_attr_show, inv_attr_store, ATTR_GYRO_ENABLE);和sensor_enable调用的是同样的函数,参数为ATTR_GYRO_ENABLE,可以看到下面这句代码
st->chip_config.gyro_enable = !!data;就这样角加速度计成功使能