Android驱动开发之陀螺仪(一)
四、安卓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(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;
就这样角加速度计成功使能
Android驱动开发之陀螺仪(三)