| /* |
| * Copyright (C) 2012 Invensense, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_NDEBUG 0 |
| //see also the EXTRA_VERBOSE define in the MPLSensor.h header file |
| |
| #include <fcntl.h> |
| #include <errno.h> |
| #include <math.h> |
| #include <float.h> |
| #include <poll.h> |
| #include <unistd.h> |
| #include <dirent.h> |
| #include <stdlib.h> |
| #include <sys/select.h> |
| #include <sys/syscall.h> |
| #include <dlfcn.h> |
| #include <pthread.h> |
| #include <cutils/log.h> |
| #include <utils/KeyedVector.h> |
| #include <utils/String8.h> |
| #include <string.h> |
| #include <linux/input.h> |
| #include <utils/Atomic.h> |
| |
| #include "MPLSensor.h" |
| #include "MPLSupport.h" |
| #include "sensor_params.h" |
| #include "local_log_def.h" |
| |
| #include "invensense.h" |
| #include "invensense_adv.h" |
| #include "ml_stored_data.h" |
| #include "ml_load_dmp.h" |
| #include "ml_sysfs_helper.h" |
| |
| // #define TESTING |
| |
| #ifdef THIRD_PARTY_ACCEL |
| # warning "Third party accel" |
| # define USE_THIRD_PARTY_ACCEL (1) |
| #else |
| # define USE_THIRD_PARTY_ACCEL (0) |
| #endif |
| |
| #define MAX_SYSFS_ATTRB (sizeof(struct sysfs_attrbs) / sizeof(char*)) |
| |
| /******************************************************************************/ |
| /* MPL interface misc. */ |
| /******************************************************************************/ |
| static int hertz_request = 200; |
| |
| #define DEFAULT_MPL_GYRO_RATE (20000L) //us |
| #define DEFAULT_MPL_COMPASS_RATE (20000L) //us |
| |
| #define DEFAULT_HW_GYRO_RATE (100) //Hz |
| #define DEFAULT_HW_ACCEL_RATE (20) //ms |
| #define DEFAULT_HW_COMPASS_RATE (20000000L) //ns |
| #define DEFAULT_HW_AKMD_COMPASS_RATE (200000000L) //ns |
| |
| /* convert ns to hardware units */ |
| #define HW_GYRO_RATE_NS (1000000000LL / rate_request) // to Hz |
| #define HW_ACCEL_RATE_NS (rate_request / (1000000L)) // to ms |
| #define HW_COMPASS_RATE_NS (rate_request) // to ns |
| |
| /* convert Hz to hardware units */ |
| #define HW_GYRO_RATE_HZ (hertz_request) |
| #define HW_ACCEL_RATE_HZ (1000 / hertz_request) |
| #define HW_COMPASS_RATE_HZ (1000000000LL / hertz_request) |
| |
| #define RATE_200HZ 5000000LL |
| #define RATE_15HZ 66667000LL |
| #define RATE_5HZ 200000000LL |
| |
| static struct sensor_t sSensorList[] = |
| { |
| {"MPL Gyroscope", "Invensense", 1, |
| SENSORS_GYROSCOPE_HANDLE, |
| SENSOR_TYPE_GYROSCOPE, 2000.0f, 1.0f, 0.5f, 10000, {}}, |
| {"MPL Raw Gyroscope", "Invensense", 1, |
| SENSORS_RAW_GYROSCOPE_HANDLE, |
| SENSOR_TYPE_GYROSCOPE, 2000.0f, 1.0f, 0.5f, 10000, {}}, |
| {"MPL Accelerometer", "Invensense", 1, |
| SENSORS_ACCELERATION_HANDLE, |
| SENSOR_TYPE_ACCELEROMETER, 10240.0f, 1.0f, 0.5f, 10000, {}}, |
| {"MPL Magnetic Field", "Invensense", 1, |
| SENSORS_MAGNETIC_FIELD_HANDLE, |
| SENSOR_TYPE_MAGNETIC_FIELD, 10240.0f, 1.0f, 0.5f, 10000, {}}, |
| {"MPL Orientation", "Invensense", 1, |
| SENSORS_ORIENTATION_HANDLE, |
| SENSOR_TYPE_ORIENTATION, 360.0f, 1.0f, 9.7f, 10000, {}}, |
| {"MPL Rotation Vector", "Invensense", 1, |
| SENSORS_ROTATION_VECTOR_HANDLE, |
| SENSOR_TYPE_ROTATION_VECTOR, 10240.0f, 1.0f, 0.5f, 10000, {}}, |
| {"MPL Linear Acceleration", "Invensense", 1, |
| SENSORS_LINEAR_ACCEL_HANDLE, |
| SENSOR_TYPE_LINEAR_ACCELERATION, 10240.0f, 1.0f, 0.5f, 10000, {}}, |
| {"MPL Gravity", "Invensense", 1, |
| SENSORS_GRAVITY_HANDLE, |
| SENSOR_TYPE_GRAVITY, 10240.0f, 1.0f, 0.5f, 10000, {}}, |
| |
| #ifdef ENABLE_DMP_SCREEN_AUTO_ROTATION |
| {"MPL Screen Orientation", "Invensense ", 1, |
| SENSORS_SCREEN_ORIENTATION_HANDLE, |
| SENSOR_TYPE_SCREEN_ORIENTATION, 100.0f, 1.0f, 1.1f, 0, {}}, |
| #endif |
| }; |
| |
| MPLSensor *MPLSensor::gMPLSensor = NULL; |
| |
| extern "C" { |
| void procData_cb_wrapper() |
| { |
| if(MPLSensor::gMPLSensor) { |
| MPLSensor::gMPLSensor->cbProcData(); |
| } |
| } |
| |
| void setCallbackObject(MPLSensor* gbpt) |
| { |
| MPLSensor::gMPLSensor = gbpt; |
| } |
| |
| MPLSensor* getCallbackObject() { |
| return MPLSensor::gMPLSensor; |
| } |
| |
| } // end of extern C |
| |
| #ifdef INV_PLAYBACK_DBG |
| static FILE *logfile = NULL; |
| #endif |
| |
| pthread_mutex_t GlobalHalMutex = PTHREAD_MUTEX_INITIALIZER; |
| |
| /******************************************************************************* |
| * MPLSensor class implementation |
| ******************************************************************************/ |
| |
| MPLSensor::MPLSensor(CompassSensor *compass, int (*m_pt2AccelCalLoadFunc)(long *)) |
| : SensorBase(NULL, NULL), |
| mNewData(0), |
| mMasterSensorMask(INV_ALL_SENSORS), |
| mLocalSensorMask(0), |
| mPollTime(-1), |
| mHaveGoodMpuCal(0), |
| mGyroAccuracy(0), |
| mAccelAccuracy(0), |
| mCompassAccuracy(0), |
| mSampleCount(0), |
| dmp_orient_fd(-1), |
| mDmpOrientationEnabled(0), |
| mEnabled(0), |
| mOldEnabledMask(0), |
| mAccelInputReader(4), |
| mGyroInputReader(32), |
| mTempScale(0), |
| mTempOffset(0), |
| mTempCurrentTime(0), |
| mAccelScale(2), |
| mPendingMask(0), |
| mSensorMask(0), |
| mFeatureActiveMask(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; |
| |
| LOGV_IF(EXTRA_VERBOSE, |
| "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)); |
| |
| #ifdef INV_PLAYBACK_DBG |
| LOGV_IF(PROCESS_VERBOSE, "HAL:inv_turn_on_data_logging"); |
| logfile = fopen("/data/playback.bin", "wb"); |
| if (logfile) |
| inv_turn_on_data_logging(logfile); |
| #endif |
| |
| /* 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 { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:Chip ID= %s\n", chip_ID); |
| } |
| |
| enable_iio_sysfs(); |
| |
| /* turn on power state */ |
| onPower(1); |
| |
| /* reset driver master enable */ |
| masterEnable(0); |
| |
| if (isLowPowerQuatEnabled() || isDmpDisplayOrientationOn()) { |
| /* Load DMP image if capable, ie. MPU6xxx/9xxx */ |
| loadDMP(); |
| } |
| |
| /* open temperature fd for temp comp */ |
| LOGV_IF(EXTRA_VERBOSE, "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 { |
| LOGV_IF(EXTRA_VERBOSE, |
| "HAL:temperature_fd opened: %s", mpu.temperature); |
| } |
| |
| /* read accel FSR to calcuate accel scale later */ |
| if (!USE_THIRD_PARTY_ACCEL) { |
| char buf[3]; |
| int count = 0; |
| LOGV_IF(SYSFS_VERBOSE, |
| "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) |
| LOGV_IF(EXTRA_VERBOSE, "HAL:Accel FSR used %d", mAccelScale); |
| } |
| close(fd); |
| } |
| } |
| |
| /* 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[LinearAccel].version = sizeof(sensors_event_t); |
| mPendingEvents[LinearAccel].sensor = ID_LA; |
| mPendingEvents[LinearAccel].type = SENSOR_TYPE_LINEAR_ACCELERATION; |
| |
| mPendingEvents[Gravity].version = sizeof(sensors_event_t); |
| mPendingEvents[Gravity].sensor = ID_GR; |
| mPendingEvents[Gravity].type = SENSOR_TYPE_GRAVITY; |
| |
| mPendingEvents[Gyro].version = sizeof(sensors_event_t); |
| mPendingEvents[Gyro].sensor = ID_GY; |
| mPendingEvents[Gyro].type = SENSOR_TYPE_GYROSCOPE; |
| |
| mPendingEvents[RawGyro].version = sizeof(sensors_event_t); |
| mPendingEvents[RawGyro].sensor = ID_RG; |
| mPendingEvents[RawGyro].type = SENSOR_TYPE_GYROSCOPE; |
| |
| mPendingEvents[Accelerometer].version = sizeof(sensors_event_t); |
| mPendingEvents[Accelerometer].sensor = ID_A; |
| mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER; |
| |
| /* 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[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; |
| |
| mHandlers[RotationVector] = &MPLSensor::rvHandler; |
| mHandlers[LinearAccel] = &MPLSensor::laHandler; |
| mHandlers[Gravity] = &MPLSensor::gravHandler; |
| mHandlers[Gyro] = &MPLSensor::gyroHandler; |
| mHandlers[RawGyro] = &MPLSensor::rawGyroHandler; |
| mHandlers[Accelerometer] = &MPLSensor::accelHandler; |
| mHandlers[MagneticField] = &MPLSensor::compassHandler; |
| mHandlers[Orientation] = &MPLSensor::orienHandler; |
| |
| for (int i = 0; i < numSensors; i++) { |
| mDelays[i] = 0; |
| } |
| |
| (void)inv_get_version(&ver_str); |
| LOGV_IF(PROCESS_VERBOSE, "%s\n", ver_str); |
| |
| /* setup MPL */ |
| inv_constructor_init(); |
| |
| /* load calibration file from /data/inv_cal_data.bin */ |
| rv = inv_load_calibration(); |
| if(rv == INV_SUCCESS) |
| LOGV_IF(PROCESS_VERBOSE, "HAL:Calibration file successfully loaded"); |
| else |
| LOGE("HAL:Could not open or load MPL calibration file (%d)", rv); |
| |
| /* Takes external Accel Calibration Load Method */ |
| 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_accel_bias(tmp_offset, NULL); |
| LOGV_IF(PROCESS_VERBOSE, "HAL:Original accel offset, %ld, %ld, %ld\n", |
| tmp_offset[0], tmp_offset[1], tmp_offset[2]); |
| inv_set_accel_bias(accel_offset, mAccelAccuracy); |
| inv_get_accel_bias(tmp_offset, NULL); |
| LOGV_IF(PROCESS_VERBOSE, "HAL:Set accel offset, %ld, %ld, %ld\n", |
| tmp_offset[0], tmp_offset[1], tmp_offset[2]); |
| } |
| } |
| /* End of Accel Calibration Load Method */ |
| |
| inv_set_device_properties(); |
| |
| /* disable driver master enable the first sensor goes on */ |
| masterEnable(0); |
| enableGyro(0); |
| enableAccel(0); |
| enableCompass(0); |
| |
| if (isLowPowerQuatEnabled()) { |
| enableLPQuaternion(0); |
| } |
| |
| onPower(0); |
| |
| if (isDmpDisplayOrientationOn()) { |
| enableDmpOrientation(!isDmpScreenAutoRotationEnabled()); |
| } |
| |
| } |
| |
| void MPLSensor::enable_iio_sysfs() |
| { |
| VFUNC_LOG; |
| |
| char iio_trigger_name[MAX_CHIP_ID_LEN], iio_device_node[MAX_CHIP_ID_LEN]; |
| FILE *tempFp = NULL; |
| |
| /* ignore failures */ |
| write_sysfs_int(mpu.in_timestamp_en, 1); |
| |
| LOGV_IF(SYSFS_VERBOSE, |
| "HAL:sysfs:cat %s (%lld)", |
| mpu.trigger_name, getTimestamp()); |
| tempFp = fopen(mpu.trigger_name, "r"); |
| if (tempFp == NULL) { |
| LOGE("HAL:could not open trigger name"); |
| } else { |
| if (fscanf(tempFp, "%s", iio_trigger_name) < 0) { |
| LOGE("HAL:could not read trigger name"); |
| } |
| fclose(tempFp); |
| } |
| |
| LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %s > %s (%lld)", |
| iio_trigger_name, mpu.current_trigger, getTimestamp()); |
| tempFp = fopen(mpu.current_trigger, "w"); |
| if (tempFp == NULL) { |
| LOGE("HAL:could not open current trigger"); |
| } else { |
| if (fprintf(tempFp, "%s", iio_trigger_name) < 0 || fclose(tempFp) < 0) { |
| LOGE("HAL:could not write current trigger %s err=%d", iio_trigger_name, errno); |
| } |
| } |
| |
| write_sysfs_int(mpu.buffer_length, IIO_BUFFER_LENGTH); |
| |
| if (inv_get_iio_device_node(iio_device_node) < 0) { |
| LOGE("HAL:could retrive the iio device node"); |
| } |
| iio_fd = open(iio_device_node, O_RDONLY); |
| if (iio_fd < 0) { |
| LOGE("HAL:could not open iio device node"); |
| } else { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:iio iio_fd (%s) opened: %d", iio_device_node, iio_fd); |
| } |
| } |
| |
| int MPLSensor::inv_constructor_init() |
| { |
| VFUNC_LOG; |
| |
| inv_error_t result = inv_init_mpl(); |
| if (result) { |
| LOGE("HAL:inv_init_mpl() failed"); |
| return result; |
| } |
| result = inv_constructor_default_enable(); |
| result = inv_start_mpl(); |
| if (result) { |
| LOGE("HAL:inv_start_mpl() failed"); |
| LOG_RESULT_LOCATION(result); |
| return result; |
| } |
| |
| return result; |
| } |
| |
| int MPLSensor::inv_constructor_default_enable() |
| { |
| VFUNC_LOG; |
| |
| inv_error_t result; |
| |
| result = inv_enable_quaternion(); |
| if (result) { |
| LOGE("HAL:Cannot enable quaternion\n"); |
| return result; |
| } |
| |
| result = inv_enable_in_use_auto_calibration(); |
| if (result) { |
| return result; |
| } |
| |
| // result = inv_enable_motion_no_motion(); |
| result = inv_enable_fast_nomot(); |
| if (result) { |
| return result; |
| } |
| |
| result = inv_enable_gyro_tc(); |
| if (result) { |
| return result; |
| } |
| |
| result = inv_enable_hal_outputs(); |
| if (result) { |
| return result; |
| } |
| |
| if (!mCompassSensor->providesCalibration()) { |
| /* Invensense compass calibration */ |
| LOGV_IF(PROCESS_VERBOSE, "HAL:Invensense vector compass cal enabled"); |
| result = inv_enable_vector_compass_cal(); |
| if (result) { |
| LOG_RESULT_LOCATION(result); |
| return result; |
| } else { |
| mFeatureActiveMask |= INV_COMPASS_CAL; |
| } |
| |
| // specify MPL's trust weight, used by compass algorithms |
| inv_vector_compass_cal_sensitivity(3); |
| |
| result = inv_enable_compass_bias_w_gyro(); |
| if (result) { |
| LOG_RESULT_LOCATION(result); |
| return result; |
| } |
| |
| result = inv_enable_heading_from_gyro(); |
| if (result) { |
| LOG_RESULT_LOCATION(result); |
| return result; |
| } |
| |
| result = inv_enable_magnetic_disturbance(); |
| if (result) { |
| LOG_RESULT_LOCATION(result); |
| return result; |
| } |
| } |
| |
| result = inv_enable_9x_sensor_fusion(); |
| if (result) { |
| LOG_RESULT_LOCATION(result); |
| return result; |
| } else { |
| // 9x sensor fusion enables Compass fit |
| mFeatureActiveMask |= INV_COMPASS_FIT; |
| } |
| |
| result = inv_enable_no_gyro_fusion(); |
| if (result) { |
| LOG_RESULT_LOCATION(result); |
| return result; |
| } |
| |
| result = inv_enable_quat_accuracy_monitor(); |
| if (result) { |
| LOG_RESULT_LOCATION(result); |
| return result; |
| } |
| |
| return result; |
| } |
| |
| /* TODO: create function pointers to calculate scale */ |
| void MPLSensor::inv_set_device_properties() |
| { |
| VFUNC_LOG; |
| |
| unsigned short orient; |
| |
| inv_get_sensors_orientation(); |
| |
| inv_set_gyro_sample_rate(DEFAULT_MPL_GYRO_RATE); |
| inv_set_compass_sample_rate(DEFAULT_MPL_COMPASS_RATE); |
| |
| /* gyro setup */ |
| orient = inv_orientation_matrix_to_scalar(mGyroOrientation); |
| inv_set_gyro_orientation_and_scale(orient, 2000L << 15); |
| |
| /* accel setup */ |
| orient = inv_orientation_matrix_to_scalar(mAccelOrientation); |
| /* use for third party accel input subsystem driver |
| inv_set_accel_orientation_and_scale(orient, 1LL << 22); |
| */ |
| inv_set_accel_orientation_and_scale(orient, mAccelScale << 15); |
| |
| /* compass setup */ |
| signed char orientMtx[9]; |
| mCompassSensor->getOrientationMatrix(orientMtx); |
| orient = |
| inv_orientation_matrix_to_scalar(orientMtx); |
| long sensitivity; |
| sensitivity = mCompassSensor->getSensitivity(); |
| inv_set_compass_orientation_and_scale(orient, sensitivity); |
| } |
| |
| void MPLSensor::loadDMP() |
| { |
| int res, fd; |
| FILE *fptr; |
| |
| if (isMpu3050()) { |
| //DMP support only for MPU6xxx/9xxx currently |
| return; |
| } |
| |
| /* load DMP firmware */ |
| LOGV_IF(SYSFS_VERBOSE, |
| "HAL:sysfs:cat %s (%lld)", mpu.firmware_loaded, getTimestamp()); |
| fd = open(mpu.firmware_loaded, O_RDONLY); |
| if(fd < 0) { |
| LOGE("HAL:could not open dmp state"); |
| return; |
| } |
| if(inv_read_dmp_state(fd)) { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:DMP is already loaded"); |
| return; |
| } |
| |
| LOGV_IF(EXTRA_VERBOSE, "HAL:load dmp: %s", mpu.dmp_firmware); |
| fptr = fopen(mpu.dmp_firmware, "w"); |
| if(!fptr) { |
| LOGE("HAL:could open %s for write. %s", mpu.dmp_firmware, strerror(errno)); |
| return; |
| } |
| res = inv_load_dmp(fptr); |
| if(res < 0) { |
| LOGE("HAL:load DMP failed"); |
| } else { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:DMP loaded"); |
| } |
| fclose(fptr); |
| |
| // onDMP(1); //Can't enable here. See note onDMP() |
| } |
| |
| void MPLSensor::inv_get_sensors_orientation() |
| { |
| FILE *fptr; |
| |
| // get gyro orientation |
| LOGV_IF(SYSFS_VERBOSE, |
| "HAL:sysfs:cat %s (%lld)", mpu.gyro_orient, getTimestamp()); |
| fptr = fopen(mpu.gyro_orient, "r"); |
| if (fptr != NULL) { |
| int om[9]; |
| fscanf(fptr, "%d,%d,%d,%d,%d,%d,%d,%d,%d", |
| &om[0], &om[1], &om[2], &om[3], &om[4], &om[5], |
| &om[6], &om[7], &om[8]); |
| fclose(fptr); |
| |
| LOGV_IF(EXTRA_VERBOSE, |
| "HAL:gyro mounting matrix: " |
| "%+d %+d %+d %+d %+d %+d %+d %+d %+d", |
| om[0], om[1], om[2], om[3], om[4], om[5], om[6], om[7], om[8]); |
| |
| mGyroOrientation[0] = om[0]; |
| mGyroOrientation[1] = om[1]; |
| mGyroOrientation[2] = om[2]; |
| mGyroOrientation[3] = om[3]; |
| mGyroOrientation[4] = om[4]; |
| mGyroOrientation[5] = om[5]; |
| mGyroOrientation[6] = om[6]; |
| mGyroOrientation[7] = om[7]; |
| mGyroOrientation[8] = om[8]; |
| } else { |
| LOGE("HAL:Couldn't read gyro mounting matrix"); |
| } |
| |
| // get accel orientation |
| LOGV_IF(SYSFS_VERBOSE, |
| "HAL:sysfs:cat %s (%lld)", mpu.accel_orient, getTimestamp()); |
| fptr = fopen(mpu.accel_orient, "r"); |
| if (fptr != NULL) { |
| int om[9]; |
| fscanf(fptr, "%d,%d,%d,%d,%d,%d,%d,%d,%d", |
| &om[0], &om[1], &om[2], &om[3], &om[4], &om[5], |
| &om[6], &om[7], &om[8]); |
| fclose(fptr); |
| |
| LOGV_IF(EXTRA_VERBOSE, |
| "HAL:accel mounting matrix: " |
| "%+d %+d %+d %+d %+d %+d %+d %+d %+d", |
| om[0], om[1], om[2], om[3], om[4], om[5], om[6], om[7], om[8]); |
| |
| mAccelOrientation[0] = om[0]; |
| mAccelOrientation[1] = om[1]; |
| mAccelOrientation[2] = om[2]; |
| mAccelOrientation[3] = om[3]; |
| mAccelOrientation[4] = om[4]; |
| mAccelOrientation[5] = om[5]; |
| mAccelOrientation[6] = om[6]; |
| mAccelOrientation[7] = om[7]; |
| mAccelOrientation[8] = om[8]; |
| } else { |
| LOGE("HAL:Couldn't read accel mounting matrix"); |
| } |
| } |
| |
| MPLSensor::~MPLSensor() |
| { |
| VFUNC_LOG; |
| |
| mCompassSensor = NULL; |
| |
| /* Close open fds */ |
| if (iio_fd > 0) |
| close(iio_fd); |
| if( accel_fd > 0 ) |
| close(accel_fd ); |
| if (gyro_temperature_fd > 0) |
| close(gyro_temperature_fd); |
| if (sysfs_names_ptr) |
| free(sysfs_names_ptr); |
| |
| if (isDmpDisplayOrientationOn()) { |
| closeDmpOrientFd(); |
| } |
| |
| /* Turn off Gyro master enable */ |
| /* A workaround until driver handles it */ |
| /* TODO: Turn off and close all sensors */ |
| if(write_sysfs_int(mpu.chip_enable, 0) < 0) { |
| LOGE("HAL:could not disable gyro master enable"); |
| } |
| |
| #ifdef INV_PLAYBACK_DBG |
| inv_turn_off_data_logging(); |
| fclose(logfile); |
| #endif |
| } |
| |
| #define GY_ENABLED (((1 << ID_GY) | (1 << ID_RG)) & enabled_sensors) |
| #define A_ENABLED ((1 << ID_A) & enabled_sensors) |
| #define M_ENABLED ((1 << ID_M) & enabled_sensors) |
| #define O_ENABLED ((1 << ID_O) & enabled_sensors) |
| #define LA_ENABLED ((1 << ID_LA) & enabled_sensors) |
| #define GR_ENABLED ((1 << ID_GR) & enabled_sensors) |
| #define RV_ENABLED ((1 << ID_RV) & enabled_sensors) |
| |
| /* TODO: this step is optional, remove? */ |
| int MPLSensor::setGyroInitialState() |
| { |
| VFUNC_LOG; |
| |
| int res = 0; |
| |
| LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)", |
| HW_GYRO_RATE_HZ, mpu.gyro_fifo_rate, getTimestamp()); |
| int fd = open(mpu.gyro_fifo_rate, O_RDWR); |
| res = errno; |
| if(fd < 0) { |
| LOGE("HAL:open of %s failed with '%s' (%d)", |
| mpu.gyro_fifo_rate, strerror(res), res); |
| return res; |
| } |
| res = write_attribute_sensor(fd, HW_GYRO_RATE_HZ); |
| if(res < 0) { |
| LOGE("HAL:write_attribute_sensor : error writing %s with %d", |
| mpu.gyro_fifo_rate, HW_GYRO_RATE_HZ); |
| return res; |
| } |
| |
| // Setting LPF is deprecated |
| |
| return 0; |
| } |
| |
| /* this applies to BMA250 Input Subsystem Driver only */ |
| int MPLSensor::setAccelInitialState() |
| { |
| VFUNC_LOG; |
| |
| struct input_absinfo absinfo_x; |
| struct input_absinfo absinfo_y; |
| struct input_absinfo absinfo_z; |
| float value; |
| if (!ioctl(accel_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo_x) && |
| !ioctl(accel_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo_y) && |
| !ioctl(accel_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo_z)) { |
| value = absinfo_x.value; |
| mPendingEvents[Accelerometer].data[0] = value * CONVERT_A_X; |
| value = absinfo_y.value; |
| mPendingEvents[Accelerometer].data[1] = value * CONVERT_A_Y; |
| value = absinfo_z.value; |
| mPendingEvents[Accelerometer].data[2] = value * CONVERT_A_Z; |
| //mHasPendingEvent = true; |
| } |
| return 0; |
| } |
| |
| int MPLSensor::onPower(int en) |
| { |
| VFUNC_LOG; |
| |
| int res; |
| |
| int count, curr_power_state; |
| |
| LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)", |
| en, mpu.power_state, getTimestamp()); |
| res = read_sysfs_int(mpu.power_state, &curr_power_state); |
| if (res < 0) { |
| LOGE("HAL:Error reading power state"); |
| // will set power_state anyway |
| curr_power_state = -1; |
| } |
| if (en != curr_power_state) { |
| if((res = write_sysfs_int(mpu.power_state, en)) < 0) { |
| LOGE("HAL:Couldn't write power state"); |
| } |
| } else { |
| LOGV_IF(EXTRA_VERBOSE, |
| "HAL:Power state already enable/disable curr=%d new=%d", |
| curr_power_state, en); |
| } |
| return res; |
| } |
| |
| int MPLSensor::onDMP(int en) |
| { |
| VFUNC_LOG; |
| |
| int res = -1; |
| int status; |
| |
| //Sequence to enable DMP |
| //1. Turn On power if not already on |
| //2. Load DMP image if not already loaded |
| //3. Either Gyro or Accel must be enabled/configured before next step |
| //4. Enable DMP |
| |
| LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:cat %s (%lld)", |
| mpu.firmware_loaded, getTimestamp()); |
| res = read_sysfs_int(mpu.firmware_loaded, &status); |
| if (res < 0){ |
| LOGE("HAL:ERR can't get firmware_loaded status"); |
| return res; |
| } |
| LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs: %s status=%d", mpu.firmware_loaded, status); |
| |
| if (status) { |
| //Write only if curr DMP state <> request |
| LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:cat %s (%lld)", |
| mpu.dmp_on, getTimestamp()); |
| if (read_sysfs_int(mpu.dmp_on, &status) < 0) { |
| LOGE("HAL:ERR can't read DMP state"); |
| } else if (status != en) { |
| res = write_sysfs_int(mpu.dmp_on, en); |
| //Enable DMP interrupt |
| if (write_sysfs_int(mpu.dmp_int_on, en) < 0) { |
| LOGE("HAL:ERR can't en/dis DMP interrupt"); |
| } |
| } else { |
| res = 0; //DMP already set as requested |
| } |
| } else { |
| LOGE("HAL:ERR No DMP image"); |
| } |
| return res; |
| } |
| |
| int MPLSensor::checkLPQuaternion(void) |
| { |
| VFUNC_LOG; |
| |
| return ((mFeatureActiveMask & INV_DMP_QUATERNION)? 1:0); |
| } |
| |
| int MPLSensor::enableLPQuaternion(int en) |
| { |
| VFUNC_LOG; |
| |
| if (!en) { |
| enableQuaternionData(0); |
| onDMP(0); |
| mFeatureActiveMask &= ~INV_DMP_QUATERNION; |
| LOGV_IF(PROCESS_VERBOSE, "HAL:LP Quat disabled"); |
| } else { |
| if (enableQuaternionData(1) < 0 || onDMP(1) < 0) { |
| LOGE("HAL:ERR can't enable LP Quaternion"); |
| } else { |
| mFeatureActiveMask |= INV_DMP_QUATERNION; |
| LOGV_IF(PROCESS_VERBOSE, "HAL:LP Quat enabled"); |
| } |
| } |
| return 0; |
| } |
| |
| int MPLSensor::enableQuaternionData(int en) |
| { |
| int res = 0; |
| VFUNC_LOG; |
| |
| // Enable DMP quaternion |
| res = write_sysfs_int(mpu.quaternion_on, en); |
| |
| if (!en) { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:Disabling quat scan elems"); |
| } else { |
| |
| LOGV_IF(PROCESS_VERBOSE, "HAL:Enabling quat scan elems"); |
| } |
| write_sysfs_int(mpu.in_quat_r_en, en); |
| write_sysfs_int(mpu.in_quat_x_en, en); |
| write_sysfs_int(mpu.in_quat_y_en, en); |
| write_sysfs_int(mpu.in_quat_z_en, en); |
| |
| LOGV_IF(EXTRA_VERBOSE, "HAL:DMP quaternion data was turned off"); |
| |
| if (!en) { |
| inv_quaternion_sensor_was_turned_off(); |
| } |
| |
| return res; |
| } |
| |
| int MPLSensor::enableTap(int en) |
| { |
| VFUNC_LOG; |
| |
| return 0; |
| } |
| |
| int MPLSensor::enableFlick(int en) |
| { |
| VFUNC_LOG; |
| |
| return 0; |
| } |
| |
| int MPLSensor::enablePedometer(int en) |
| { |
| VFUNC_LOG; |
| |
| return 0; |
| } |
| |
| int MPLSensor::masterEnable(int en) |
| { |
| VFUNC_LOG; |
| return write_sysfs_int(mpu.chip_enable, en); |
| } |
| |
| int MPLSensor::enableGyro(int en) |
| { |
| VFUNC_LOG; |
| |
| /* TODO: FIX error handling. Handle or ignore it appropriately for hw. */ |
| int res; |
| |
| /* need to also turn on/off the master enable */ |
| res = write_sysfs_int(mpu.gyro_enable, en); |
| |
| if (!en) { |
| LOGV_IF(EXTRA_VERBOSE, "HAL:MPL:inv_gyro_was_turned_off"); |
| inv_gyro_was_turned_off(); |
| } else { |
| write_sysfs_int(mpu.gyro_x_fifo_enable, en); |
| write_sysfs_int(mpu.gyro_y_fifo_enable, en); |
| res = write_sysfs_int(mpu.gyro_z_fifo_enable, en); |
| } |
| |
| return res; |
| } |
| |
| int MPLSensor::enableAccel(int en) |
| { |
| VFUNC_LOG; |
| |
| /* TODO: FIX error handling. Handle or ignore it appropriately for hw. */ |
| int res; |
| |
| /* need to also turn on/off the master enable */ |
| res = write_sysfs_int(mpu.accel_enable, en); |
| |
| if (!en) { |
| LOGV_IF(EXTRA_VERBOSE, "HAL:MPL:inv_accel_was_turned_off"); |
| inv_accel_was_turned_off(); |
| } else { |
| write_sysfs_int(mpu.accel_x_fifo_enable, en); |
| write_sysfs_int(mpu.accel_y_fifo_enable, en); |
| res = write_sysfs_int(mpu.accel_z_fifo_enable, en); |
| } |
| |
| return res; |
| } |
| |
| int MPLSensor::enableCompass(int en) |
| { |
| VFUNC_LOG; |
| |
| int res = mCompassSensor->enable(ID_M, en); |
| if (!en) { |
| LOGV_IF(EXTRA_VERBOSE, "HAL:MPL:inv_compass_was_turned_off"); |
| inv_compass_was_turned_off(); |
| } |
| return res; |
| } |
| |
| void MPLSensor::computeLocalSensorMask(int enabled_sensors) |
| { |
| VFUNC_LOG; |
| |
| do { |
| if (LA_ENABLED || GR_ENABLED || RV_ENABLED || O_ENABLED) { |
| LOGV_IF(ENG_VERBOSE, "FUSION ENABLED"); |
| mLocalSensorMask = ALL_MPL_SENSORS_NP; |
| break; |
| } |
| |
| if(!A_ENABLED && !M_ENABLED && !GY_ENABLED) { |
| /* Invensense compass cal */ |
| LOGV_IF(ENG_VERBOSE, "ALL DISABLED"); |
| mLocalSensorMask = 0; |
| break; |
| } |
| |
| if (GY_ENABLED) { |
| LOGV_IF(ENG_VERBOSE, "G ENABLED"); |
| mLocalSensorMask |= INV_THREE_AXIS_GYRO; |
| } else { |
| LOGV_IF(ENG_VERBOSE, "G DISABLED"); |
| mLocalSensorMask &= ~INV_THREE_AXIS_GYRO; |
| } |
| |
| if (A_ENABLED) { |
| LOGV_IF(ENG_VERBOSE, "A ENABLED"); |
| mLocalSensorMask |= INV_THREE_AXIS_ACCEL; |
| } else { |
| LOGV_IF(ENG_VERBOSE, "A DISABLED"); |
| mLocalSensorMask &= ~INV_THREE_AXIS_ACCEL; |
| } |
| |
| /* Invensense compass calibration */ |
| if (M_ENABLED) { |
| LOGV_IF(ENG_VERBOSE, "M ENABLED"); |
| mLocalSensorMask |= INV_THREE_AXIS_COMPASS; |
| } else { |
| LOGV_IF(ENG_VERBOSE, "M DISABLED"); |
| mLocalSensorMask &= ~INV_THREE_AXIS_COMPASS; |
| } |
| } while (0); |
| } |
| |
| int MPLSensor::enableOneSensor(int en, const char *name, int (MPLSensor::*enabler)(int)) { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:enableSensors - %s %s", en ? "enabled" : "disable", name); |
| return (this->*enabler)(en); |
| } |
| |
| int MPLSensor::enableSensors(unsigned long sensors, int en, uint32_t changed) { |
| VFUNC_LOG; |
| |
| inv_error_t res = -1; |
| bool store_cal = false; |
| bool ext_compass_changed = false; |
| |
| // Sequence to enable or disable a sensor |
| // 1. enable Power state |
| // 2. reset master enable (=0) |
| // 3. enable or disable a sensor |
| // 4. set master enable (=1) |
| |
| pthread_mutex_lock(&GlobalHalMutex); |
| |
| uint32_t all_changeables = (1 << Gyro) | (1 << RawGyro) | (1 << Accelerometer) |
| | (1 << MagneticField); |
| uint32_t all_integrated_changeables = all_changeables; |
| |
| if (!mCompassSensor->isIntegrated()) { |
| ext_compass_changed = changed & (1 << MagneticField); |
| all_integrated_changeables = all_changeables & ~(1 << MagneticField); |
| } |
| |
| if (isLowPowerQuatEnabled() || (changed & all_integrated_changeables)) { |
| /* ensure power state is on */ |
| onPower(1); |
| |
| /* reset master enable */ |
| res = masterEnable(0); |
| if(res < 0) { |
| goto unlock_res; |
| } |
| } |
| |
| LOGV_IF(PROCESS_VERBOSE, "HAL:enableSensors - sensors: 0x%0x", (unsigned int)sensors); |
| |
| if (changed & ((1 << Gyro) | (1 << RawGyro))) { |
| res = enableOneSensor(sensors & INV_THREE_AXIS_GYRO, "gyro", &MPLSensor::enableGyro); |
| if(res < 0) { |
| goto unlock_res; |
| } |
| } |
| |
| if (changed & (1 << Accelerometer)) { |
| res = enableOneSensor(sensors & INV_THREE_AXIS_ACCEL, "accel", &MPLSensor::enableAccel); |
| if(res < 0) { |
| goto unlock_res; |
| } |
| } |
| |
| if (changed & (1 << MagneticField)) { |
| /* Invensense compass calibration */ |
| res = enableOneSensor(sensors & INV_THREE_AXIS_COMPASS, "compass", &MPLSensor::enableCompass); |
| if(res < 0) { |
| goto unlock_res; |
| } |
| } |
| |
| if ( isLowPowerQuatEnabled() ) { |
| // Enable LP Quat |
| if ((mEnabled & ((1 << Orientation) | (1 << RotationVector) | |
| (1 << LinearAccel) | (1 << Gravity)))) { |
| if (!(changed & all_integrated_changeables)) { |
| /* ensure power state is on */ |
| onPower(1); |
| /* reset master enable */ |
| res = masterEnable(0); |
| if(res < 0) { |
| goto unlock_res; |
| } |
| } |
| if (!checkLPQuaternion()) { |
| enableLPQuaternion(1); |
| } else { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:LP Quat already enabled"); |
| } |
| } else if (checkLPQuaternion()) { |
| enableLPQuaternion(0); |
| } |
| } |
| |
| if (changed & all_integrated_changeables) { |
| if (sensors & |
| (INV_THREE_AXIS_GYRO |
| | INV_THREE_AXIS_ACCEL |
| | (INV_THREE_AXIS_COMPASS * mCompassSensor->isIntegrated()))) { |
| if ( isLowPowerQuatEnabled() || |
| (isDmpDisplayOrientationOn() && mDmpOrientationEnabled) ) { |
| // disable DMP event interrupt only (w/ data interrupt) |
| if (write_sysfs_int(mpu.dmp_event_int_on, 0) < 0) { |
| res = -1; |
| LOGE("HAL:ERR can't disable DMP event interrupt"); |
| goto unlock_res; |
| } |
| } |
| |
| if (isDmpDisplayOrientationOn() && mDmpOrientationEnabled) { |
| // enable DMP |
| onDMP(1); |
| |
| res = enableAccel(1); |
| if(res < 0) { |
| goto unlock_res; |
| } |
| |
| if ((sensors & INV_THREE_AXIS_ACCEL) == 0) { |
| res = turnOffAccelFifo(); |
| } |
| if(res < 0) { |
| goto unlock_res; |
| } |
| } |
| |
| res = masterEnable(1); |
| if(res < 0) { |
| goto unlock_res; |
| } |
| } else { // all sensors idle -> reduce power |
| if (isDmpDisplayOrientationOn() && mDmpOrientationEnabled) { |
| // enable DMP |
| onDMP(1); |
| // enable DMP event interrupt only (no data interrupt) |
| if (write_sysfs_int(mpu.dmp_event_int_on, 1) < 0) { |
| res = -1; |
| LOGE("HAL:ERR can't enable DMP event interrupt"); |
| } |
| res = enableAccel(1); |
| if(res < 0) { |
| goto unlock_res; |
| } |
| if ((sensors & INV_THREE_AXIS_ACCEL) == 0) { |
| res = turnOffAccelFifo(); |
| } |
| if(res < 0) { |
| goto unlock_res; |
| } |
| res = masterEnable(1); |
| if(res < 0) { |
| goto unlock_res; |
| } |
| } |
| else { |
| res = onPower(0); |
| if(res < 0) { |
| goto unlock_res; |
| } |
| } |
| store_cal = true; |
| } |
| } else if (ext_compass_changed && |
| !(sensors & (INV_THREE_AXIS_GYRO | INV_THREE_AXIS_ACCEL |
| | (INV_THREE_AXIS_COMPASS * (!mCompassSensor->isIntegrated()))))) { |
| store_cal = true; |
| } |
| |
| if (store_cal || ((changed & all_changeables) != all_changeables)) { |
| storeCalibration(); |
| } |
| |
| unlock_res: |
| pthread_mutex_unlock(&GlobalHalMutex); |
| return res; |
| } |
| |
| /* Store calibration file */ |
| void MPLSensor::storeCalibration() |
| { |
| if(mHaveGoodMpuCal || mAccelAccuracy >= 2 || mCompassAccuracy >= 3) { |
| int res = inv_store_calibration(); |
| if (res) { |
| LOGE("HAL:Cannot store calibration on file"); |
| } else { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:Cal file updated"); |
| } |
| } |
| } |
| |
| void MPLSensor::cbProcData() |
| { |
| mNewData = 1; |
| mSampleCount++; |
| LOGV_IF(EXTRA_VERBOSE, "HAL:new data"); |
| } |
| |
| /* these handlers transform mpl data into one of the Android sensor types */ |
| int MPLSensor::gyroHandler(sensors_event_t* s) |
| { |
| VHANDLER_LOG; |
| int8_t status; |
| int update; |
| update = inv_get_sensor_type_gyroscope(s->gyro.v, &status, &s->timestamp); |
| LOGV_IF(HANDLER_DATA, "HAL:gyro data : %+f %+f %+f -- %lld - %d", |
| s->gyro.v[0], s->gyro.v[1], s->gyro.v[2], s->timestamp, update); |
| return update; |
| } |
| |
| int MPLSensor::rawGyroHandler(sensors_event_t* s) |
| { |
| VHANDLER_LOG; |
| int8_t status; |
| int update; |
| update = inv_get_sensor_type_gyroscope_raw(s->gyro.v, &status, &s->timestamp); |
| LOGV_IF(HANDLER_DATA, "HAL:raw gyro data : %+f %+f %+f -- %lld - %d", |
| s->gyro.v[0], s->gyro.v[1], s->gyro.v[2], s->timestamp, update); |
| return update; |
| } |
| |
| int MPLSensor::accelHandler(sensors_event_t* s) |
| { |
| VHANDLER_LOG; |
| int8_t status; |
| int update; |
| update = inv_get_sensor_type_accelerometer( |
| s->acceleration.v, &status, &s->timestamp); |
| LOGV_IF(HANDLER_DATA, "HAL:accel data : %+f %+f %+f -- %lld - %d", |
| s->acceleration.v[0], s->acceleration.v[1], s->acceleration.v[2], |
| s->timestamp, update); |
| mAccelAccuracy = status; |
| return update; |
| } |
| |
| int MPLSensor::compassHandler(sensors_event_t* s) |
| { |
| VHANDLER_LOG; |
| int update; |
| update = inv_get_sensor_type_magnetic_field( |
| s->magnetic.v, &s->magnetic.status, &s->timestamp); |
| LOGV_IF(HANDLER_DATA, "HAL:compass data: %+f %+f %+f -- %lld - %d", |
| s->magnetic.v[0], s->magnetic.v[1], s->magnetic.v[2], s->timestamp, update); |
| mCompassAccuracy = s->magnetic.status; |
| return update; |
| } |
| |
| int MPLSensor::rvHandler(sensors_event_t* s) |
| { |
| // rotation vector does not have an accuracy or status |
| VHANDLER_LOG; |
| int8_t status; |
| int update; |
| update = inv_get_sensor_type_rotation_vector(s->data, &status, &s->timestamp); |
| LOGV_IF(HANDLER_DATA, "HAL:rv data: %+f %+f %+f %+f - %+lld - %d", |
| s->data[0], s->data[1], s->data[2], s->data[3], s->timestamp, update); |
| return update; |
| } |
| |
| int MPLSensor::laHandler(sensors_event_t* s) |
| { |
| VHANDLER_LOG; |
| int8_t status; |
| int update; |
| update = inv_get_sensor_type_linear_acceleration( |
| s->gyro.v, &status, &s->timestamp); |
| LOGV_IF(HANDLER_DATA, "HAL:la data: %+f %+f %+f - %lld - %d", |
| s->gyro.v[0], s->gyro.v[1], s->gyro.v[2], s->timestamp, update); |
| return update; |
| } |
| |
| int MPLSensor::gravHandler(sensors_event_t* s) |
| { |
| VHANDLER_LOG; |
| int8_t status; |
| int update; |
| update = inv_get_sensor_type_gravity(s->gyro.v, &status, &s->timestamp); |
| LOGV_IF(HANDLER_DATA, "HAL:gr data: %+f %+f %+f - %lld - %d", |
| s->gyro.v[0], s->gyro.v[1], s->gyro.v[2], s->timestamp, update); |
| return update; |
| } |
| |
| int MPLSensor::orienHandler(sensors_event_t* s) |
| { |
| VHANDLER_LOG; |
| int update; |
| update = inv_get_sensor_type_orientation( |
| s->orientation.v, &s->orientation.status, &s->timestamp); |
| LOGV_IF(HANDLER_DATA, "HAL:or data: %f %f %f - %lld - %d", |
| s->orientation.v[0], s->orientation.v[1], s->orientation.v[2], s->timestamp, update); |
| return update; |
| } |
| |
| int MPLSensor::enable(int32_t handle, int en) |
| { |
| VFUNC_LOG; |
| |
| android::String8 sname; |
| int what = -1, err = 0; |
| |
| switch (handle) { |
| case ID_SO: |
| sname = "Screen Orientation"; |
| LOGV_IF(PROCESS_VERBOSE, "HAL:enable - sensor %s (handle %d) %s -> %s", sname.string(), handle, |
| (mDmpOrientationEnabled? "en": "dis"), |
| (en? "en" : "dis")); |
| enableDmpOrientation(en && isDmpDisplayOrientationOn()); |
| /* TODO: stop manually testing/using 0 and 1 instead of |
| * false and true, but just use 0 and non-0. |
| * This allows passing 0 and non-0 ints around instead of |
| * having to convert to 1 and test against 1. |
| */ |
| mDmpOrientationEnabled = en; |
| return 0; |
| case ID_A: |
| what = Accelerometer; |
| sname = "Accelerometer"; |
| break; |
| case ID_M: |
| what = MagneticField; |
| sname = "MagneticField"; |
| break; |
| case ID_O: |
| what = Orientation; |
| sname = "Orientation"; |
| break; |
| case ID_GY: |
| what = Gyro; |
| sname = "Gyro"; |
| break; |
| case ID_RG: |
| what = RawGyro; |
| sname = "RawGyro"; |
| break; |
| case ID_GR: |
| what = Gravity; |
| sname = "Gravity"; |
| break; |
| case ID_RV: |
| what = RotationVector; |
| sname = "RotationVector"; |
| break; |
| case ID_LA: |
| what = LinearAccel; |
| sname = "LinearAccel"; |
| 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(PROCESS_VERBOSE, |
| "HAL:%s sensor state change what=%d", sname.string(), what); |
| |
| // pthread_mutex_lock(&mMplMutex); |
| // pthread_mutex_lock(&mHALMutex); |
| |
| 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(PROCESS_VERBOSE, "HAL:handle = %d", handle); |
| LOGV_IF(PROCESS_VERBOSE, "HAL:flags = %d", flags); |
| computeLocalSensorMask(mEnabled); |
| LOGV_IF(PROCESS_VERBOSE, "HAL:enable : mEnabled = %d", mEnabled); |
| sen_mask = mLocalSensorMask & mMasterSensorMask; |
| mSensorMask = sen_mask; |
| LOGV_IF(PROCESS_VERBOSE, "HAL:sen_mask= 0x%0lx", sen_mask); |
| |
| switch (what) { |
| case Gyro: |
| case RawGyro: |
| case Accelerometer: |
| case MagneticField: |
| if (!(mEnabled & ((1 << Orientation) | (1 << RotationVector) | |
| (1 << LinearAccel) | (1 << Gravity))) && |
| ((lastEnabled & (1 << what)) != (mEnabled & (1 << what)))) { |
| changed |= (1 << what); |
| } |
| break; |
| |
| case Orientation: |
| case RotationVector: |
| case LinearAccel: |
| case Gravity: |
| if ((en && !(lastEnabled & ((1 << Orientation) | (1 << RotationVector) | |
| (1 << LinearAccel) | (1 << Gravity)))) || |
| (!en && !(mEnabled & ((1 << Orientation) | (1 << RotationVector) | |
| (1 << LinearAccel) | (1 << Gravity))))) { |
| for (int i = Gyro; i <= MagneticField; i++) { |
| if (!(mEnabled & (1 << i))) { |
| changed |= (1 << i); |
| } |
| } |
| } |
| break; |
| } |
| LOGV_IF(PROCESS_VERBOSE, "HAL:changed = %d", changed); |
| enableSensors(sen_mask, flags, changed); |
| } |
| |
| // pthread_mutex_unlock(&mMplMutex); |
| // pthread_mutex_unlock(&mHALMutex); |
| |
| #ifdef INV_PLAYBACK_DBG |
| /* apparently the logging needs to be go through this sequence |
| to properly flush the log file */ |
| inv_turn_off_data_logging(); |
| fclose(logfile); |
| logfile = fopen("/data/playback.bin", "ab"); |
| if (logfile) |
| inv_turn_on_data_logging(logfile); |
| #endif |
| |
| return err; |
| } |
| |
| int MPLSensor::setDelay(int32_t handle, int64_t ns) |
| { |
| VFUNC_LOG; |
| |
| android::String8 sname; |
| int what = -1; |
| |
| switch (handle) { |
| case ID_SO: |
| return update_delay(); |
| case ID_A: |
| what = Accelerometer; |
| sname = "Accelerometer"; |
| break; |
| case ID_M: |
| what = MagneticField; |
| sname = "MagneticField"; |
| break; |
| case ID_O: |
| what = Orientation; |
| sname = "Orientation"; |
| break; |
| case ID_GY: |
| what = Gyro; |
| sname = "Gyro"; |
| break; |
| case ID_RG: |
| what = RawGyro; |
| sname = "RawGyro"; |
| break; |
| case ID_GR: |
| what = Gravity; |
| sname = "Gravity"; |
| break; |
| case ID_RV: |
| what = RotationVector; |
| sname = "RotationVector"; |
| break; |
| case ID_LA: |
| what = LinearAccel; |
| sname = "LinearAccel"; |
| break; |
| default: // this takes care of all the gestures |
| what = handle; |
| sname = "Others"; |
| break; |
| } |
| |
| #if 0 |
| // skip the 1st call for enalbing sensors called by ICS/JB sensor service |
| static int counter_delay = 0; |
| if (!(mEnabled & (1 << what))) { |
| counter_delay = 0; |
| } else { |
| if (++counter_delay == 1) { |
| return 0; |
| } |
| else { |
| counter_delay = 0; |
| } |
| } |
| #endif |
| |
| if (uint32_t(what) >= numSensors) |
| return -EINVAL; |
| |
| if (ns < 0) |
| return -EINVAL; |
| |
| LOGV_IF(PROCESS_VERBOSE, "setDelay : %llu ns, (%.2f Hz)", ns, 1000000000.f / ns); |
| |
| // limit all rates to reasonable ones */ |
| /* |
| if (ns < 10000000LL) { |
| ns = 10000000LL; |
| } |
| */ |
| if (ns < 5000000LL) { |
| ns = 5000000LL; |
| } |
| |
| /* store request rate to mDelays arrary for each sensor */ |
| mDelays[what] = ns; |
| |
| switch (what) { |
| case Gyro: |
| case RawGyro: |
| case Accelerometer: |
| for (int i = Gyro; i <= Accelerometer + mCompassSensor->isIntegrated(); |
| i++) { |
| if (i != what && (mEnabled & (1 << i)) && ns > mDelays[i]) { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:ignore delay set due to sensor %d", i); |
| return 0; |
| } |
| } |
| break; |
| |
| case MagneticField: |
| if (mCompassSensor->isIntegrated() && |
| (((mEnabled & (1 << Gyro)) && ns > mDelays[Gyro]) || |
| ((mEnabled & (1 << RawGyro)) && ns > mDelays[RawGyro]) || |
| ((mEnabled & (1 << Accelerometer)) && ns > mDelays[Accelerometer]))) { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:ignore delay set due to gyro/accel"); |
| return 0; |
| } |
| break; |
| |
| case Orientation: |
| case RotationVector: |
| case LinearAccel: |
| case Gravity: |
| if (isLowPowerQuatEnabled()) { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:need to update delay due to LPQ"); |
| break; |
| } |
| |
| for (int i = 0; i < numSensors; i++) { |
| if (i != what && (mEnabled & (1 << i)) && ns > mDelays[i]) { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:ignore delay set due to sensor %d", i); |
| return 0; |
| } |
| } |
| break; |
| } |
| |
| // pthread_mutex_lock(&mHALMutex); |
| int res = update_delay(); |
| // pthread_mutex_unlock(&mHALMutex); |
| return res; |
| } |
| |
| int MPLSensor::update_delay() { |
| VHANDLER_LOG; |
| |
| int res = 0; |
| int64_t got; |
| |
| pthread_mutex_lock(&GlobalHalMutex); |
| if (mEnabled) { |
| int64_t wanted = 1000000000; |
| int64_t wanted_3rd_party_sensor = 1000000000; |
| |
| // Sequence to change sensor's FIFO rate |
| // 1. enable Power state |
| // 2. reset master enable |
| // 3. Update delay |
| // 4. set master enable |
| |
| // ensure power on |
| onPower(1); |
| |
| // reset master enable |
| masterEnable(0); |
| |
| /* search the minimum delay requested across all enabled sensors */ |
| for (int i = 0; i < numSensors; i++) { |
| if (mEnabled & (1 << i)) { |
| int64_t ns = mDelays[i]; |
| wanted = wanted < ns ? wanted : ns; |
| } |
| } |
| |
| // same delay for 3rd party Accel or Compass |
| wanted_3rd_party_sensor = wanted; |
| |
| /* mpl rate in us in future maybe different for |
| gyro vs compass vs accel */ |
| int rateInus = (int)wanted / 1000LL; |
| int mplGyroRate = rateInus; |
| int mplAccelRate = rateInus; |
| int mplCompassRate = rateInus; |
| |
| LOGV_IF(PROCESS_VERBOSE, "HAL:wanted rate for all sensors : " |
| "%llu ns, mpl rate: %d us, (%.2f Hz)", |
| wanted, rateInus, 1000000000.f / wanted); |
| |
| /* set rate in MPL */ |
| /* compass can only do 100Hz max */ |
| inv_set_gyro_sample_rate(mplGyroRate); |
| inv_set_accel_sample_rate(mplAccelRate); |
| inv_set_compass_sample_rate(mplCompassRate); |
| |
| /* TODO: Test 200Hz */ |
| // inv_set_gyro_sample_rate(5000); |
| LOGV_IF(PROCESS_VERBOSE, "HAL:MPL gyro sample rate: %d", mplGyroRate); |
| LOGV_IF(PROCESS_VERBOSE, "HAL:MPL accel sample rate: %d", mplAccelRate); |
| LOGV_IF(PROCESS_VERBOSE, "HAL:MPL compass sample rate: %d", mplCompassRate); |
| |
| int enabled_sensors = mEnabled; |
| int tempFd = -1; |
| if (LA_ENABLED || GR_ENABLED || RV_ENABLED || O_ENABLED) { |
| if (isLowPowerQuatEnabled() || |
| (isDmpDisplayOrientationOn() && mDmpOrientationEnabled)) { |
| bool setDMPrate= 0; |
| // Set LP Quaternion sample rate if enabled |
| if (checkLPQuaternion()) { |
| if (wanted < RATE_200HZ) { |
| enableLPQuaternion(0); |
| } else { |
| inv_set_quat_sample_rate(rateInus); |
| setDMPrate= 1; |
| } |
| } |
| |
| if (checkDMPOrientation() || setDMPrate==1) { |
| getDmpRate(&wanted); |
| } |
| } |
| |
| int64_t tempRate = wanted; |
| LOGV_IF(EXTRA_VERBOSE, "HAL:setDelay - Fusion"); |
| //nsToHz |
| LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)", |
| 1000000000.f / tempRate, mpu.gyro_fifo_rate, |
| getTimestamp()); |
| tempFd = open(mpu.gyro_fifo_rate, O_RDWR); |
| res = write_attribute_sensor(tempFd, 1000000000.f / tempRate); |
| if(res < 0) { |
| LOGE("HAL:GYRO update delay error"); |
| } |
| |
| //nsToHz (BMA250) |
| if(USE_THIRD_PARTY_ACCEL) { |
| LOGV_IF(SYSFS_VERBOSE, "echo %lld > %s (%lld)", |
| wanted_3rd_party_sensor / 1000000L, mpu.accel_fifo_rate, |
| getTimestamp()); |
| tempFd = open(mpu.accel_fifo_rate, O_RDWR); |
| res = write_attribute_sensor(tempFd, wanted_3rd_party_sensor / 1000000L); |
| LOGE_IF(res < 0, "HAL:ACCEL update delay error"); |
| } |
| |
| if (!mCompassSensor->isIntegrated()) { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:Ext compass rate %.2f Hz", 1000000000.f / wanted_3rd_party_sensor); |
| mCompassSensor->setDelay(ID_M, wanted_3rd_party_sensor); |
| got = mCompassSensor->getDelay(ID_M); |
| inv_set_compass_sample_rate(got / 1000); |
| } |
| |
| } else { |
| |
| if (GY_ENABLED) { |
| wanted = (mDelays[Gyro] <= mDelays[RawGyro]? |
| (mEnabled & (1 << Gyro)? mDelays[Gyro]: mDelays[RawGyro]): |
| (mEnabled & (1 << RawGyro)? mDelays[RawGyro]: mDelays[Gyro])); |
| |
| if (isDmpDisplayOrientationOn() && mDmpOrientationEnabled) { |
| getDmpRate(&wanted); |
| } |
| |
| LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)", |
| 1000000000.f / wanted, mpu.gyro_fifo_rate, getTimestamp()); |
| tempFd = open(mpu.gyro_fifo_rate, O_RDWR); |
| res = write_attribute_sensor(tempFd, 1000000000.f / wanted); |
| LOGE_IF(res < 0, "HAL:GYRO update delay error"); |
| } |
| |
| if (A_ENABLED) { /* else if because there is only 1 fifo rate for MPUxxxx */ |
| if (GY_ENABLED && mDelays[Gyro] < mDelays[Accelerometer]) { |
| wanted = mDelays[Gyro]; |
| } |
| else if (GY_ENABLED && mDelays[RawGyro] < mDelays[Accelerometer]) { |
| wanted = mDelays[RawGyro]; |
| |
| } else { |
| wanted = mDelays[Accelerometer]; |
| } |
| |
| if (isDmpDisplayOrientationOn() && mDmpOrientationEnabled) { |
| getDmpRate(&wanted); |
| } |
| |
| /* TODO: use function pointers to calculate delay value specific to vendor */ |
| LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)", |
| 1000000000.f / wanted, mpu.accel_fifo_rate, getTimestamp()); |
| tempFd = open(mpu.accel_fifo_rate, O_RDWR); |
| if(USE_THIRD_PARTY_ACCEL) { |
| //BMA250 in ms |
| res = write_attribute_sensor(tempFd, wanted / 1000000L); |
| } |
| else { |
| //MPUxxxx in hz |
| res = write_attribute_sensor(tempFd, 1000000000.f/wanted); |
| } |
| LOGE_IF(res < 0, "HAL:ACCEL update delay error"); |
| } |
| |
| /* Invensense compass calibration */ |
| if (M_ENABLED) { |
| if (!mCompassSensor->isIntegrated()) { |
| wanted = mDelays[MagneticField]; |
| } else { |
| if (GY_ENABLED && mDelays[Gyro] < mDelays[MagneticField]) { |
| wanted = mDelays[Gyro]; |
| } |
| else if (GY_ENABLED && mDelays[RawGyro] < mDelays[MagneticField]) { |
| wanted = mDelays[RawGyro]; |
| } else if (A_ENABLED && mDelays[Accelerometer] < mDelays[MagneticField]) { |
| wanted = mDelays[Accelerometer]; |
| } else { |
| wanted = mDelays[MagneticField]; |
| } |
| |
| if (isDmpDisplayOrientationOn() && mDmpOrientationEnabled) { |
| getDmpRate(&wanted); |
| } |
| } |
| |
| mCompassSensor->setDelay(ID_M, wanted); |
| got = mCompassSensor->getDelay(ID_M); |
| inv_set_compass_sample_rate(got / 1000); |
| } |
| |
| } |
| |
| unsigned long sensors = mLocalSensorMask & mMasterSensorMask; |
| if (sensors & |
| (INV_THREE_AXIS_GYRO |
| | INV_THREE_AXIS_ACCEL |
| | (INV_THREE_AXIS_COMPASS * mCompassSensor->isIntegrated()))) { |
| res = masterEnable(1); |
| } else { // all sensors idle -> reduce power |
| res = onPower(0); |
| } |
| } |
| pthread_mutex_unlock(&GlobalHalMutex); |
| return res; |
| } |
| |
| /* For Third Party Accel Input Subsystem Drivers only */ |
| /* TODO: FIX! data is not used and count not decremented, results is hardcoded to 0 */ |
| int MPLSensor::readAccelEvents(sensors_event_t* data, int count) |
| { |
| VHANDLER_LOG; |
| |
| if (count < 1) |
| return -EINVAL; |
| |
| ssize_t n = mAccelInputReader.fill(accel_fd); |
| if (n < 0) { |
| LOGE("HAL:missed accel events, exit"); |
| return n; |
| } |
| |
| int numEventReceived = 0; |
| input_event const* event; |
| int nb, done = 0; |
| |
| while (!done && count && mAccelInputReader.readEvent(&event)) { |
| int type = event->type; |
| if (type == EV_ABS) { |
| if (event->code == EVENT_TYPE_ACCEL_X) { |
| mPendingMask |= 1 << Accelerometer; |
| mCachedAccelData[0] = event->value; |
| } else if (event->code == EVENT_TYPE_ACCEL_Y) { |
| mPendingMask |= 1 << Accelerometer; |
| mCachedAccelData[1] = event->value; |
| } else if (event->code == EVENT_TYPE_ACCEL_Z) { |
| mPendingMask |= 1 << Accelerometer; |
| mCachedAccelData[2] =event-> value; |
| } |
| } else if (type == EV_SYN) { |
| done = 1; |
| if (mLocalSensorMask & INV_THREE_AXIS_ACCEL) { |
| inv_build_accel(mCachedAccelData, 0, getTimestamp()); |
| } |
| } else { |
| LOGE("HAL:AccelSensor: unknown event (type=%d, code=%d)", |
| type, event->code); |
| } |
| mAccelInputReader.next(); |
| } |
| |
| return numEventReceived; |
| } |
| |
| /** |
| * Should be called after reading at least one of gyro |
| * compass or accel data. (Also okay for handling all of them). |
| * @returns 0, if successful, error number if not. |
| */ |
| /* TODO: This should probably be called "int readEvents(...)" |
| * and readEvents() called "void cacheData(void)". |
| */ |
| int MPLSensor::executeOnData(sensors_event_t* data, int count) |
| { |
| VFUNC_LOG; |
| |
| inv_execute_on_data(); |
| |
| int numEventReceived = 0; |
| |
| long msg; |
| msg = inv_get_message_level_0(1); |
| if (msg) { |
| if (msg & INV_MSG_MOTION_EVENT) { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:**** Motion ****\n"); |
| } |
| if (msg & INV_MSG_NO_MOTION_EVENT) { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:***** No Motion *****\n"); |
| /* after the first no motion, the gyro should be |
| calibrated well */ |
| mGyroAccuracy = SENSOR_STATUS_ACCURACY_HIGH; |
| /* if gyros are on and we got a no motion, set a flag |
| indicating that the cal file can be written. */ |
| mHaveGoodMpuCal = true; |
| } |
| } |
| |
| // load up virtual sensors |
| for (int i = 0; i < numSensors; i++) { |
| int update; |
| if (mEnabled & (1 << i)) { |
| update = CALL_MEMBER_FN(this, mHandlers[i])(mPendingEvents + i); |
| mPendingMask |= (1 << i); |
| |
| if (update && (count > 0)) { |
| *data++ = mPendingEvents[i]; |
| count--; |
| numEventReceived++; |
| } |
| } |
| } |
| |
| return numEventReceived; |
| } |
| |
| // collect data for MPL (but NOT sensor service currently), from driver layer |
| /* TODO: FIX! data and count are not used, results is hardcoded to 0 */ |
| /* TODO: This should probably be called "void cacheEvents(void)" |
| * And executeOnData() should be int readEvents(data,count) |
| */ |
| int MPLSensor::readEvents(sensors_event_t *data, int count) { |
| |
| |
| int lp_quaternion_on = 0, nbyte; |
| int i, nb, mask = 0, numEventReceived = 0, |
| sensors = ((mLocalSensorMask & INV_THREE_AXIS_GYRO)? 1 : 0) + |
| ((mLocalSensorMask & INV_THREE_AXIS_ACCEL)? 1 : 0) + |
| (((mLocalSensorMask & INV_THREE_AXIS_COMPASS) && mCompassSensor->isIntegrated())? 1 : 0); |
| char *rdata = mIIOBuffer; |
| |
| nbyte= (8 * sensors + 8) * 1; |
| |
| if (isLowPowerQuatEnabled()) { |
| lp_quaternion_on = checkLPQuaternion(); |
| if (lp_quaternion_on) { |
| nbyte += sizeof(mCachedQuaternionData); //currently 16 bytes for Q data |
| } |
| } |
| |
| // pthread_mutex_lock(&mMplMutex); |
| // pthread_mutex_lock(&mHALMutex); |
| |
| ssize_t rsize = read(iio_fd, rdata, nbyte); |
| if (sensors == 0) { |
| // read(iio_fd, rdata, nbyte); |
| rsize = read(iio_fd, rdata, sizeof(mIIOBuffer)); |
| } |
| |
| #ifdef TESTING |
| LOGI("get one sample of IIO data with size: %d", rsize); |
| LOGI("sensors: %d", sensors); |
| |
| LOGI_IF(mLocalSensorMask & INV_THREE_AXIS_GYRO, "gyro x/y/z: %d/%d/%d", |
| *((short *) (rdata + 0)), *((short *) (rdata + 2)), |
| *((short *) (rdata + 4))); |
| LOGI_IF(mLocalSensorMask & INV_THREE_AXIS_ACCEL, "accel x/y/z: %d/%d/%d", |
| *((short *) (rdata + 0 + ((mLocalSensorMask & INV_THREE_AXIS_GYRO)? 6: 0))), |
| *((short *) (rdata + 2 + ((mLocalSensorMask & INV_THREE_AXIS_GYRO)? 6: 0))), |
| *((short *) (rdata + 4) + ((mLocalSensorMask & INV_THREE_AXIS_GYRO)? 6: 0))); |
| |
| LOGI_IF(mLocalSensorMask & INV_THREE_AXIS_COMPASS & |
| mCompassSensor->isIntegrated(), "compass x/y/z: %d/%d/%d", |
| *((short *) (rdata + 0 + ((mLocalSensorMask & INV_THREE_AXIS_GYRO)? 6: 0) + |
| ((mLocalSensorMask & INV_THREE_AXIS_ACCEL)? 6: 0))), |
| *((short *) (rdata + 2 + ((mLocalSensorMask & INV_THREE_AXIS_GYRO)? 6: 0) + |
| ((mLocalSensorMask & INV_THREE_AXIS_ACCEL)? 6: 0))), |
| *((short *) (rdata + 4) + ((mLocalSensorMask & INV_THREE_AXIS_GYRO)? 6: 0) + |
| ((mLocalSensorMask & INV_THREE_AXIS_ACCEL)? 6: 0))); |
| #endif |
| |
| if (rsize < (nbyte - 8)) { |
| LOGE("HAL:ERR Full data packet was not read. rsize=%ld nbyte=%d sensors=%d errno=%d(%s)", |
| rsize, nbyte, sensors, errno, strerror(errno)); |
| return -1; |
| } |
| |
| if (isLowPowerQuatEnabled() && lp_quaternion_on) { |
| |
| for (i=0; i< 4; i++) { |
| mCachedQuaternionData[i]= *(long*)rdata; |
| rdata += sizeof(long); |
| } |
| } |
| |
| for (i = 0; i < 3; i++) { |
| if (mLocalSensorMask & INV_THREE_AXIS_GYRO) { |
| mCachedGyroData[i] = *((short *) (rdata + i * 2)); |
| } |
| if (mLocalSensorMask & INV_THREE_AXIS_ACCEL) { |
| mCachedAccelData[i] = *((short *) (rdata + i * 2 + |
| ((mLocalSensorMask & INV_THREE_AXIS_GYRO)? 6: 0))); |
| } |
| if ((mLocalSensorMask & INV_THREE_AXIS_COMPASS) && mCompassSensor->isIntegrated()) { |
| mCachedCompassData[i] = *((short *) (rdata + i * 2 + 6 * (sensors - 1))); |
| } |
| } |
| |
| mask |= (((mLocalSensorMask & INV_THREE_AXIS_GYRO)? 1 << Gyro: 0) + |
| ((mLocalSensorMask & INV_THREE_AXIS_ACCEL)? 1 << Accelerometer: 0)); |
| if ((mLocalSensorMask & INV_THREE_AXIS_COMPASS) && mCompassSensor->isIntegrated() && |
| (mCachedCompassData[0] != 0 || mCachedCompassData[1] != 0 || mCachedCompassData[0] != 0)) { |
| mask |= 1 << MagneticField; |
| } |
| |
| mSensorTimestamp = *((long long *) (rdata + 8 * sensors)); |
| if (mCompassSensor->isIntegrated()) { |
| mCompassTimestamp = mSensorTimestamp; |
| } |
| |
| if (mask & (1 << Gyro)) { |
| // send down temperature every 0.5 seconds |
| // with timestamp measured in "driver" layer |
| if(mSensorTimestamp - mTempCurrentTime >= 500000000LL) { |
| mTempCurrentTime = mSensorTimestamp; |
| long long temperature[2]; |
| if(inv_read_temperature(temperature) == 0) { |
| LOGV_IF(INPUT_DATA, |
| "HAL:inv_read_temperature = %lld, timestamp= %lld", |
| temperature[0], temperature[1]); |
| inv_build_temp(temperature[0], temperature[1]); |
| } |
| #ifdef TESTING |
| long bias[3], temp, temp_slope[3]; |
| inv_get_gyro_bias(bias, &temp); |
| inv_get_gyro_ts(temp_slope); |
| |
| LOGI("T: %.3f " |
| "GB: %+13f %+13f %+13f " |
| "TS: %+13f %+13f %+13f " |
| "\n", |
| (float)temperature[0] / 65536.f, |
| (float)bias[0] / 65536.f / 16.384f, |
| (float)bias[1] / 65536.f / 16.384f, |
| (float)bias[2] / 65536.f / 16.384f, |
| temp_slope[0] / 65536.f, |
| temp_slope[1] / 65536.f, |
| temp_slope[2] / 65536.f); |
| #endif |
| } |
| |
| mPendingMask |= 1 << Gyro; |
| mPendingMask |= 1 << RawGyro; |
| |
| if (mLocalSensorMask & INV_THREE_AXIS_GYRO) { |
| inv_build_gyro(mCachedGyroData, mSensorTimestamp); |
| LOGV_IF(INPUT_DATA, |
| "HAL:inv_build_gyro: %+8d %+8d %+8d - %lld", |
| mCachedGyroData[0], mCachedGyroData[1], |
| mCachedGyroData[2], mSensorTimestamp); |
| } |
| } |
| |
| if (mask & (1 << Accelerometer)) { |
| mPendingMask |= 1 << Accelerometer; |
| if (mLocalSensorMask & INV_THREE_AXIS_ACCEL) { |
| inv_build_accel(mCachedAccelData, 0, mSensorTimestamp); |
| LOGV_IF(INPUT_DATA, |
| "HAL:inv_build_accel: %+8ld %+8ld %+8ld - %lld", |
| mCachedAccelData[0], mCachedAccelData[1], |
| mCachedAccelData[2], mSensorTimestamp); |
| } |
| } |
| |
| if ((mask & (1 << MagneticField)) && mCompassSensor->isIntegrated()) { |
| int status = 0; |
| if (mCompassSensor->providesCalibration()) { |
| status = mCompassSensor->getAccuracy(); |
| status |= INV_CALIBRATED; |
| } |
| if (mLocalSensorMask & INV_THREE_AXIS_COMPASS) { |
| inv_build_compass(mCachedCompassData, status, |
| mCompassTimestamp); |
| LOGV_IF(INPUT_DATA, "HAL:inv_build_compass: %+8ld %+8ld %+8ld - %lld", |
| mCachedCompassData[0], mCachedCompassData[1], |
| mCachedCompassData[2], mCompassTimestamp); |
| } |
| } |
| |
| if (isLowPowerQuatEnabled() && lp_quaternion_on) { |
| |
| inv_build_quat(mCachedQuaternionData, 32 /*default 32 for now (16/32bits)*/, mSensorTimestamp); |
| LOGV_IF(INPUT_DATA, "HAL:inv_build_quat: %+8ld %+8ld %+8ld %+8ld - %lld", |
| mCachedQuaternionData[0], mCachedQuaternionData[1], |
| mCachedQuaternionData[2], mCachedQuaternionData[3], mSensorTimestamp); |
| } |
| |
| // pthread_mutex_unlock(&mMplMutex); |
| // pthread_mutex_unlock(&mHALMutex); |
| |
| return numEventReceived; |
| } |
| |
| /* use for both MPUxxxx and third party compass */ |
| int MPLSensor::readCompassEvents(sensors_event_t *data, int count) |
| { |
| VHANDLER_LOG; |
| |
| if (count < 1) |
| return -EINVAL; |
| |
| int numEventReceived = 0; |
| int done = 0; |
| int nb; |
| |
| // pthread_mutex_lock(&mMplMutex); |
| // pthread_mutex_lock(&mHALMutex); |
| |
| done = mCompassSensor->readSample(mCachedCompassData, &mCompassTimestamp); |
| #ifdef COMPASS_YAS53x |
| if (mCompassSensor->checkCoilsReset()) { |
| //Reset relevant compass settings |
| resetCompass(); |
| } |
| #endif |
| if (done > 0) { |
| int status = 0; |
| if (mCompassSensor->providesCalibration()) { |
| status = mCompassSensor->getAccuracy(); |
| status |= INV_CALIBRATED; |
| } |
| if (mLocalSensorMask & INV_THREE_AXIS_COMPASS) { |
| inv_build_compass(mCachedCompassData, status, |
| mCompassTimestamp); |
| LOGV_IF(INPUT_DATA, "HAL:inv_build_compass: %+8ld %+8ld %+8ld - %lld", |
| mCachedCompassData[0], mCachedCompassData[1], |
| mCachedCompassData[2], mCompassTimestamp); |
| } |
| } |
| |
| // pthread_mutex_unlock(&mMplMutex); |
| // pthread_mutex_unlock(&mHALMutex); |
| |
| return numEventReceived; |
| } |
| |
| #ifdef COMPASS_YAS53x |
| int MPLSensor::resetCompass() |
| { |
| VFUNC_LOG; |
| |
| //Reset compass cal if enabled |
| if (mFeatureActiveMask & INV_COMPASS_CAL) { |
| LOGV_IF(EXTRA_VERBOSE, "HAL:Reset compass cal"); |
| inv_init_vector_compass_cal(); |
| } |
| |
| //Reset compass fit if enabled |
| if (mFeatureActiveMask & INV_COMPASS_FIT) { |
| LOGV_IF(EXTRA_VERBOSE, "HAL:Reset compass fit"); |
| inv_init_compass_fit(); |
| } |
| |
| return 0; |
| } |
| #endif |
| |
| int MPLSensor::getFd() const |
| { |
| VFUNC_LOG; |
| LOGV_IF(EXTRA_VERBOSE, "MPLSensor::getFd returning %d", iio_fd); |
| return iio_fd; |
| } |
| |
| int MPLSensor::getAccelFd() const |
| { |
| VFUNC_LOG; |
| LOGV_IF(EXTRA_VERBOSE, "MPLSensor::getAccelFd returning %d", accel_fd); |
| return accel_fd; |
| } |
| |
| int MPLSensor::getCompassFd() const |
| { |
| VFUNC_LOG; |
| int fd = mCompassSensor->getFd(); |
| LOGV_IF(EXTRA_VERBOSE, "MPLSensor::getCompassFd returning %d", fd); |
| return fd; |
| } |
| |
| int MPLSensor::turnOffAccelFifo() { |
| int i, res, tempFd; |
| char *accel_fifo_enable[3] = {mpu.accel_x_fifo_enable, |
| mpu.accel_y_fifo_enable, mpu.accel_z_fifo_enable}; |
| |
| for (i = 0; i < 3; i++) { |
| res = write_sysfs_int(accel_fifo_enable[i], 0); |
| if (res < 0) { |
| return res; |
| } |
| } |
| return 0; |
| } |
| |
| int MPLSensor::enableDmpOrientation(int en) |
| { |
| VFUNC_LOG; |
| /* TODO: FIX error handling. Handle or ignore it appropriately for hw. */ |
| int res = 0; |
| int enabled_sensors = mEnabled; |
| |
| if (isMpu3050()) |
| return res; |
| |
| pthread_mutex_lock(&GlobalHalMutex); |
| |
| // on power if not already On |
| res = onPower(1); |
| // reset master enable |
| res = masterEnable(0); |
| |
| if (en) { |
| //Enable DMP orientation |
| if (write_sysfs_int(mpu.display_orientation_on, en) < 0) { |
| LOGE("HAL:ERR can't enable Android orientation"); |
| res = -1; // indicate an err |
| } |
| |
| // open DMP Orient Fd |
| res = openDmpOrientFd(); |
| |
| // enable DMP |
| res = onDMP(1); |
| |
| // default DMP output rate to FIFO |
| if (write_sysfs_int(mpu.dmp_output_rate, 5) < 0) { |
| LOGE("HAL:ERR can't default DMP output rate"); |
| } |
| |
| // set DMP rate to 200Hz |
| if (write_sysfs_int(mpu.accel_fifo_rate, 200) < 0) { |
| res = -1; |
| LOGE("HAL:ERR can't set DMP rate to 200Hz"); |
| } |
| |
| // enable accel engine |
| res = enableAccel(1); |
| |
| // disable accel FIFO |
| if (!A_ENABLED) { |
| res = turnOffAccelFifo(); |
| } |
| |
| mFeatureActiveMask |= INV_DMP_DISPL_ORIENTATION; |
| } else { |
| // disable DMP |
| res = onDMP(0); |
| |
| // disable accel engine |
| if (!A_ENABLED) { |
| res = enableAccel(0); |
| } |
| } |
| |
| res = masterEnable(1); |
| pthread_mutex_unlock(&GlobalHalMutex); |
| return res; |
| } |
| |
| int MPLSensor::openDmpOrientFd() |
| { |
| VFUNC_LOG; |
| |
| if (!isDmpDisplayOrientationOn() || dmp_orient_fd >= 0) { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:DMP display orientation disabled or file desc opened"); |
| return -1; |
| } |
| |
| dmp_orient_fd = open(mpu.event_display_orientation, O_RDONLY| O_NONBLOCK); |
| if (dmp_orient_fd < 0) { |
| LOGE("HAL:ERR couldn't open dmpOrient node"); |
| return -1; |
| } else { |
| LOGV_IF(PROCESS_VERBOSE, "HAL:dmp_orient_fd opened : %d", dmp_orient_fd); |
| return 0; |
| } |
| } |
| |
| int MPLSensor::closeDmpOrientFd() |
| { |
| VFUNC_LOG; |
| if (dmp_orient_fd >= 0) |
| close(dmp_orient_fd); |
| return 0; |
| } |
| |
| int MPLSensor::dmpOrientHandler(int orient) |
| { |
| VFUNC_LOG; |
| |
| LOGV_IF(PROCESS_VERBOSE, "HAL:orient %x", orient); |
| return 0; |
| } |
| |
| int MPLSensor::readDmpOrientEvents(sensors_event_t* data, int count) { |
| VFUNC_LOG; |
| |
| char dummy[4]; |
| int screen_orientation = 0; |
| FILE *fp; |
| |
| fp = fopen(mpu.event_display_orientation, "r"); |
| if (fp == NULL) { |
| LOGE("HAL:cannot open event_display_orientation"); |
| return 0; |
| } |
| fscanf(fp, "%d\n", &screen_orientation); |
| fclose(fp); |
| |
| int numEventReceived = 0; |
| |
| if (mDmpOrientationEnabled && count > 0) { |
| sensors_event_t temp; |
| |
| bzero(&temp, sizeof(temp)); /* Let's hope that SENSOR_TYPE_NONE is 0 */ |
| temp.version = sizeof(sensors_event_t); |
| temp.sensor = ID_SO; |
| #ifdef ENABLE_DMP_SCREEN_AUTO_ROTATION |
| temp.type = SENSOR_TYPE_SCREEN_ORIENTATION; |
| temp.screen_orientation = screen_orientation; |
| #endif |
| struct timespec ts; |
| clock_gettime(CLOCK_MONOTONIC, &ts); |
| temp.timestamp = (int64_t) ts.tv_sec * 1000000000 + ts.tv_nsec; |
| |
| *data++ = temp; |
| count--; |
| numEventReceived++; |
| } |
| |
| // read dummy data per driver's request |
| dmpOrientHandler(screen_orientation); |
| read(dmp_orient_fd, dummy, 4); |
| |
| return numEventReceived; |
| } |
| |
| int MPLSensor::getDmpOrientFd() |
| { |
| VFUNC_LOG; |
| |
| LOGV_IF(EXTRA_VERBOSE, "MPLSensor::getDmpOrientFd returning %d", dmp_orient_fd); |
| return dmp_orient_fd; |
| |
| } |
| |
| int MPLSensor::checkDMPOrientation() |
| { |
| VFUNC_LOG; |
| return ((mFeatureActiveMask & INV_DMP_DISPL_ORIENTATION) ? 1 : 0); |
| } |
| |
| int MPLSensor::getDmpRate(int64_t *wanted) |
| { |
| if (checkDMPOrientation() || checkLPQuaternion()) { |
| // set DMP output rate to FIFO |
| write_sysfs_int(mpu.dmp_output_rate, 1000000000.f / *wanted); |
| LOGV_IF(PROCESS_VERBOSE, "HAL:DMP FIFO rate %.2f Hz", 1000000000.f / *wanted); |
| |
| //DMP running rate must be @ 200Hz |
| *wanted= RATE_200HZ; |
| LOGV_IF(PROCESS_VERBOSE, "HAL:DMP rate= %.2f Hz", 1000000000.f / *wanted); |
| } |
| return 0; |
| } |
| |
| int MPLSensor::getPollTime() |
| { |
| VHANDLER_LOG; |
| return mPollTime; |
| } |
| |
| bool MPLSensor::hasPendingEvents() const |
| { |
| VHANDLER_LOG; |
| // if we are using the polling workaround, force the main |
| // loop to check for data every time |
| return (mPollTime != -1); |
| } |
| |
| /* TODO: support resume suspend when we gain more info about them*/ |
| void MPLSensor::sleepEvent() |
| { |
| VFUNC_LOG; |
| } |
| |
| void MPLSensor::wakeEvent() |
| { |
| VFUNC_LOG; |
| } |
| |
| int MPLSensor::inv_float_to_q16(float *fdata, long *ldata) |
| { |
| VHANDLER_LOG; |
| |
| if (!fdata || !ldata) |
| return -1; |
| ldata[0] = (long)(fdata[0] * 65536.f); |
| ldata[1] = (long)(fdata[1] * 65536.f); |
| ldata[2] = (long)(fdata[2] * 65536.f); |
| return 0; |
| } |
| |
| int MPLSensor::inv_long_to_q16(long *fdata, long *ldata) |
| { |
| VHANDLER_LOG; |
| |
| if (!fdata || !ldata) |
| return -1; |
| ldata[0] = (fdata[1] * 65536.f); |
| ldata[1] = (fdata[2] * 65536.f); |
| ldata[2] = (fdata[3] * 65536.f); |
| return 0; |
| } |
| |
| int MPLSensor::inv_float_to_round(float *fdata, long *ldata) |
| { |
| VHANDLER_LOG; |
| |
| if (!fdata || !ldata) |
| return -1; |
| ldata[0] = (long)fdata[0]; |
| ldata[1] = (long)fdata[1]; |
| ldata[2] = (long)fdata[2]; |
| return 0; |
| } |
| |
| int MPLSensor::inv_float_to_round2(float *fdata, short *ldata) |
| { |
| VHANDLER_LOG; |
| |
| if (!fdata || !ldata) |
| return -1; |
| ldata[0] = (short)fdata[0]; |
| ldata[1] = (short)fdata[1]; |
| ldata[2] = (short)fdata[2]; |
| return 0; |
| } |
| |
| int MPLSensor::inv_read_temperature(long long *data) |
| { |
| VHANDLER_LOG; |
| |
| int count = 0; |
| char raw_buf[40]; |
| long raw = 0; |
| |
| long long timestamp = 0; |
| |
| memset(raw_buf, 0, sizeof(raw_buf)); |
| count = read_attribute_sensor(gyro_temperature_fd, raw_buf, |
| sizeof(raw_buf)); |
| if(count < 1) { |
| LOGE("HAL:error reading gyro temperature"); |
| return -1; |
| } |
| |
| count = sscanf(raw_buf, "%ld%lld", &raw, ×tamp); |
| |
| if(count < 0) { |
| return -1; |
| } |
| |
| LOGV_IF(ENG_VERBOSE, |
| "HAL:temperature raw = %ld, timestamp = %lld, count = %d", |
| raw, timestamp, count); |
| data[0] = raw; |
| data[1] = timestamp; |
| |
| return 0; |
| } |
| |
| int MPLSensor::inv_read_dmp_state(int fd) |
| { |
| VFUNC_LOG; |
| |
| if(fd < 0) |
| return -1; |
| |
| int count = 0; |
| char raw_buf[10]; |
| short raw = 0; |
| |
| memset(raw_buf, 0, sizeof(raw_buf)); |
| count = read_attribute_sensor(fd, raw_buf, sizeof(raw_buf)); |
| if(count < 1) { |
| LOGE("HAL:error reading dmp state"); |
| close(fd); |
| return -1; |
| } |
| count = sscanf(raw_buf, "%hd", &raw); |
| if(count < 0) { |
| LOGE("HAL:dmp state data is invalid"); |
| close(fd); |
| return -1; |
| } |
| LOGV_IF(EXTRA_VERBOSE, "HAL:dmp state = %d, count = %d", raw, count); |
| close(fd); |
| return (int)raw; |
| } |
| |
| int MPLSensor::inv_read_sensor_bias(int fd, long *data) |
| { |
| VFUNC_LOG; |
| |
| if(fd == -1) { |
| return -1; |
| } |
| |
| char buf[50]; |
| char x[15], y[15], z[15]; |
| |
| memset(buf, 0, sizeof(buf)); |
| int count = read_attribute_sensor(fd, buf, sizeof(buf)); |
| if(count < 1) { |
| LOGE("HAL:Error reading gyro bias"); |
| return -1; |
| } |
| count = sscanf(buf, "%[^','],%[^','],%[^',']", x, y, z); |
| if(count) { |
| /* scale appropriately for MPL */ |
| LOGV_IF(ENG_VERBOSE, |
| "HAL:pre-scaled bias: X:Y:Z (%ld, %ld, %ld)", |
| atol(x), atol(y), atol(z)); |
| |
| data[0] = (long)(atol(x) / 10000 * (1L << 16)); |
| data[1] = (long)(atol(y) / 10000 * (1L << 16)); |
| data[2] = (long)(atol(z) / 10000 * (1L << 16)); |
| |
| LOGV_IF(ENG_VERBOSE, |
| "HAL:scaled bias: X:Y:Z (%ld, %ld, %ld)", |
| data[0], data[1], data[2]); |
| } |
| return 0; |
| } |
| |
| /** fill in the sensor list based on which sensors are configured. |
| * return the number of configured sensors. |
| * parameter list must point to a memory region of at least 7*sizeof(sensor_t) |
| * parameter len gives the length of the buffer pointed to by list |
| */ |
| int MPLSensor::populateSensorList(struct sensor_t *list, int len) |
| { |
| VFUNC_LOG; |
| |
| int numsensors; |
| |
| if(len < (int)((sizeof(sSensorList) / sizeof(sensor_t)) * sizeof(sensor_t))) { |
| LOGE("HAL:sensor list too small, not populating."); |
| return -(sizeof(sSensorList) / sizeof(sensor_t)); |
| } |
| |
| /* fill in the base values */ |
| memcpy(list, sSensorList, sizeof (struct sensor_t) * (sizeof(sSensorList) / sizeof(sensor_t))); |
| |
| /* first add gyro, accel and compass to the list */ |
| |
| /* fill in gyro/accel values */ |
| if(chip_ID == NULL) { |
| LOGE("HAL:Can not get gyro/accel id"); |
| } |
| fillGyro(chip_ID, list); |
| fillAccel(chip_ID, list); |
| |
| // TODO: need fixes for unified HAL and 3rd-party solution |
| mCompassSensor->fillList(&list[MagneticField]); |
| |
| if(1) { |
| numsensors = (sizeof(sSensorList) / sizeof(sensor_t)); |
| /* all sensors will be added to the list |
| fill in orientation values */ |
| fillOrientation(list); |
| /* fill in rotation vector values */ |
| fillRV(list); |
| /* fill in gravity values */ |
| fillGravity(list); |
| /* fill in Linear accel values */ |
| fillLinearAccel(list); |
| } else { |
| /* no 9-axis sensors, zero fill that part of the list */ |
| numsensors = 3; |
| memset(list + 3, 0, 4 * sizeof(struct sensor_t)); |
| } |
| |
| return numsensors; |
| } |
| |
| void MPLSensor::fillAccel(const char* accel, struct sensor_t *list) |
| { |
| VFUNC_LOG; |
| |
| if (accel) { |
| if(accel != NULL && strcmp(accel, "BMA250") == 0) { |
| list[Accelerometer].maxRange = ACCEL_BMA250_RANGE; |
| list[Accelerometer].resolution = ACCEL_BMA250_RESOLUTION; |
| list[Accelerometer].power = ACCEL_BMA250_POWER; |
| list[Accelerometer].minDelay = ACCEL_BMA250_MINDELAY; |
| return; |
| } else if (accel != NULL && strcmp(accel, "MPU6050") == 0) { |
| list[Accelerometer].maxRange = ACCEL_MPU6050_RANGE; |
| list[Accelerometer].resolution = ACCEL_MPU6050_RESOLUTION; |
| list[Accelerometer].power = ACCEL_MPU6050_POWER; |
| list[Accelerometer].minDelay = ACCEL_MPU6050_MINDELAY; |
| return; |
| } else if (accel != NULL && strcmp(accel, "MPU6500") == 0) { |
| list[Accelerometer].maxRange = ACCEL_MPU6500_RANGE; |
| list[Accelerometer].resolution = ACCEL_MPU6500_RESOLUTION; |
| list[Accelerometer].power = ACCEL_MPU6500_POWER; |
| list[Accelerometer].minDelay = ACCEL_MPU6500_MINDELAY; |
| |
| return; |
| } else if (accel != NULL && strcmp(accel, "MPU9150") == 0) { |
| list[Accelerometer].maxRange = ACCEL_MPU9150_RANGE; |
| list[Accelerometer].resolution = ACCEL_MPU9150_RESOLUTION; |
| list[Accelerometer].power = ACCEL_MPU9150_POWER; |
| list[Accelerometer].minDelay = ACCEL_MPU9150_MINDELAY; |
| return; |
| } else if (accel != NULL && strcmp(accel, "MPU3050") == 0) { |
| list[Accelerometer].maxRange = ACCEL_BMA250_RANGE; |
| list[Accelerometer].resolution = ACCEL_BMA250_RESOLUTION; |
| list[Accelerometer].power = ACCEL_BMA250_POWER; |
| list[Accelerometer].minDelay = ACCEL_BMA250_MINDELAY; |
| return; |
| } |
| } |
| |
| LOGE("HAL:unknown accel id %s -- " |
| "params default to bma250 and might be wrong.", |
| accel); |
| list[Accelerometer].maxRange = ACCEL_BMA250_RANGE; |
| list[Accelerometer].resolution = ACCEL_BMA250_RESOLUTION; |
| list[Accelerometer].power = ACCEL_BMA250_POWER; |
| list[Accelerometer].minDelay = ACCEL_BMA250_MINDELAY; |
| } |
| |
| void MPLSensor::fillGyro(const char* gyro, struct sensor_t *list) |
| { |
| VFUNC_LOG; |
| |
| if ( gyro != NULL && strcmp(gyro, "MPU3050") == 0) { |
| list[Gyro].maxRange = GYRO_MPU3050_RANGE; |
| list[Gyro].resolution = GYRO_MPU3050_RESOLUTION; |
| list[Gyro].power = GYRO_MPU3050_POWER; |
| list[Gyro].minDelay = GYRO_MPU3050_MINDELAY; |
| } else if( gyro != NULL && strcmp(gyro, "MPU6050") == 0) { |
| list[Gyro].maxRange = GYRO_MPU6050_RANGE; |
| list[Gyro].resolution = GYRO_MPU6050_RESOLUTION; |
| list[Gyro].power = GYRO_MPU6050_POWER; |
| list[Gyro].minDelay = GYRO_MPU6050_MINDELAY; |
| } else if( gyro != NULL && strcmp(gyro, "MPU6500") == 0) { |
| list[Gyro].maxRange = GYRO_MPU6500_RANGE; |
| list[Gyro].resolution = GYRO_MPU6500_RESOLUTION; |
| list[Gyro].power = GYRO_MPU6500_POWER; |
| list[Gyro].minDelay = GYRO_MPU6500_MINDELAY; |
| } else if( gyro != NULL && strcmp(gyro, "MPU9150") == 0) { |
| list[Gyro].maxRange = GYRO_MPU9150_RANGE; |
| list[Gyro].resolution = GYRO_MPU9150_RESOLUTION; |
| list[Gyro].power = GYRO_MPU9150_POWER; |
| list[Gyro].minDelay = GYRO_MPU9150_MINDELAY; |
| } else { |
| LOGE("HAL:unknown gyro id -- gyro params will be wrong."); |
| LOGE("HAL:default to use mpu3050 params"); |
| list[Gyro].maxRange = GYRO_MPU3050_RANGE; |
| list[Gyro].resolution = GYRO_MPU3050_RESOLUTION; |
| list[Gyro].power = GYRO_MPU3050_POWER; |
| list[Gyro].minDelay = GYRO_MPU3050_MINDELAY; |
| } |
| |
| list[RawGyro].maxRange = list[Gyro].maxRange; |
| list[RawGyro].resolution = list[Gyro].resolution; |
| list[RawGyro].power = list[Gyro].power; |
| list[RawGyro].minDelay = list[Gyro].minDelay; |
| |
| return; |
| } |
| |
| /* fillRV depends on values of accel and compass in the list */ |
| void MPLSensor::fillRV(struct sensor_t *list) |
| { |
| VFUNC_LOG; |
| |
| /* compute power on the fly */ |
| list[RotationVector].power = list[Gyro].power + |
| list[Accelerometer].power + |
| list[MagneticField].power; |
| list[RotationVector].resolution = .00001; |
| list[RotationVector].maxRange = 1.0; |
| list[RotationVector].minDelay = 5000; |
| |
| return; |
| } |
| |
| void MPLSensor::fillOrientation(struct sensor_t *list) |
| { |
| VFUNC_LOG; |
| |
| list[Orientation].power = list[Gyro].power + |
| list[Accelerometer].power + |
| list[MagneticField].power; |
| list[Orientation].resolution = .00001; |
| list[Orientation].maxRange = 360.0; |
| list[Orientation].minDelay = 5000; |
| |
| return; |
| } |
| |
| void MPLSensor::fillGravity( struct sensor_t *list) |
| { |
| VFUNC_LOG; |
| |
| list[Gravity].power = list[Gyro].power + |
| list[Accelerometer].power + |
| list[MagneticField].power; |
| list[Gravity].resolution = .00001; |
| list[Gravity].maxRange = 9.81; |
| list[Gravity].minDelay = 5000; |
| |
| return; |
| } |
| |
| void MPLSensor::fillLinearAccel(struct sensor_t *list) |
| { |
| VFUNC_LOG; |
| |
| list[LinearAccel].power = list[Gyro].power + |
| list[Accelerometer].power + |
| list[MagneticField].power; |
| list[LinearAccel].resolution = list[Accelerometer].resolution; |
| list[LinearAccel].maxRange = list[Accelerometer].maxRange; |
| list[LinearAccel].minDelay = 5000; |
| |
| return; |
| } |
| |
| int MPLSensor::inv_init_sysfs_attributes(void) |
| { |
| VFUNC_LOG; |
| |
| unsigned char i; |
| char sysfs_path[MAX_SYSFS_NAME_LEN], iio_trigger_path[MAX_SYSFS_NAME_LEN]; |
| char *sptr; |
| char **dptr; |
| int num; |
| |
| sysfs_names_ptr = |
| (char*)calloc(1, sizeof(char[MAX_SYSFS_ATTRB][MAX_SYSFS_NAME_LEN])); |
| sptr = sysfs_names_ptr; |
| if (sptr == NULL) { |
| LOGE("HAL:couldn't alloc mem for sysfs paths"); |
| return -1; |
| } |
| |
| dptr = (char**)&mpu; |
| i = 0; |
| do { |
| *dptr++ = sptr; |
| sptr += sizeof(char[MAX_SYSFS_NAME_LEN]); |
| } while (++i < MAX_SYSFS_ATTRB); |
| |
| // get proper (in absolute/relative) IIO path & build MPU's sysfs paths |
| // inv_get_sysfs_abs_path(sysfs_path); |
| if(INV_SUCCESS != inv_get_sysfs_path(sysfs_path)) { |
| ALOGE("MPLSensor failed get sysfs path"); |
| return -1; |
| } |
| |
| if(INV_SUCCESS != inv_get_iio_trigger_path(iio_trigger_path)) { |
| ALOGE("MPLSensor failed get iio trigger path"); |
| return -1; |
| } |
| |
| 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.power_state, "%s%s", sysfs_path, "/power_state"); |
| sprintf(mpu.in_timestamp_en, "%s%s", sysfs_path, "/scan_elements/in_timestamp_en"); |
| sprintf(mpu.trigger_name, "%s%s", iio_trigger_path, "/name"); |
| sprintf(mpu.current_trigger, "%s%s", sysfs_path, "/trigger/current_trigger"); |
| |
| 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.dmp_output_rate,"%s%s", sysfs_path, "/dmp_output_rate"); |
| sprintf(mpu.tap_on, "%s%s", sysfs_path, "/tap_on"); |
| |
| // TODO: for self test |
| 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.gyro_fifo_rate, "%s%s", sysfs_path, "/sampling_frequency"); |
| sprintf(mpu.gyro_orient, "%s%s", sysfs_path, "/gyro_matrix"); |
| sprintf(mpu.gyro_x_fifo_enable, "%s%s", sysfs_path, "/scan_elements/in_anglvel_x_en"); |
| sprintf(mpu.gyro_y_fifo_enable, "%s%s", sysfs_path, "/scan_elements/in_anglvel_y_en"); |
| sprintf(mpu.gyro_z_fifo_enable, "%s%s", sysfs_path, "/scan_elements/in_anglvel_z_en"); |
| |
| sprintf(mpu.accel_enable, "%s%s", sysfs_path, "/accl_enable"); |
| sprintf(mpu.accel_fifo_rate, "%s%s", sysfs_path, "/sampling_frequency"); |
| sprintf(mpu.accel_orient, "%s%s", sysfs_path, "/accl_matrix"); |
| |
| |
| #ifndef THIRD_PARTY_ACCEL //MPUxxxx |
| sprintf(mpu.accel_fsr, "%s%s", sysfs_path, "/in_accel_scale"); |
| // TODO: for bias settings |
| sprintf(mpu.accel_bias, "%s%s", sysfs_path, "/accl_bias"); |
| #endif |
| |
| sprintf(mpu.accel_x_fifo_enable, "%s%s", sysfs_path, "/scan_elements/in_accel_x_en"); |
| sprintf(mpu.accel_y_fifo_enable, "%s%s", sysfs_path, "/scan_elements/in_accel_y_en"); |
| sprintf(mpu.accel_z_fifo_enable, "%s%s", sysfs_path, "/scan_elements/in_accel_z_en"); |
| |
| sprintf(mpu.quaternion_on, "%s%s", sysfs_path, "/quaternion_on"); |
| sprintf(mpu.in_quat_r_en, "%s%s", sysfs_path, "/scan_elements/in_quaternion_r_en"); |
| sprintf(mpu.in_quat_x_en, "%s%s", sysfs_path, "/scan_elements/in_quaternion_x_en"); |
| sprintf(mpu.in_quat_y_en, "%s%s", sysfs_path, "/scan_elements/in_quaternion_y_en"); |
| sprintf(mpu.in_quat_z_en, "%s%s", sysfs_path, "/scan_elements/in_quaternion_z_en"); |
| |
| sprintf(mpu.display_orientation_on, "%s%s", sysfs_path, "/display_orientation_on"); |
| sprintf(mpu.event_display_orientation, "%s%s", sysfs_path, "/event_display_orientation"); |
| |
| #if SYSFS_VERBOSE |
| // test print sysfs paths |
| dptr = (char**)&mpu; |
| for (i = 0; i < MAX_SYSFS_ATTRB; i++) { |
| LOGE("HAL:sysfs path: %s", *dptr++); |
| } |
| #endif |
| return 0; |
| } |
| |
| /* TODO: stop manually testing/using 0 and 1 instead of |
| * false and true, but just use 0 and non-0. |
| * This allows passing 0 and non-0 ints around instead of |
| * having to convert to 1 and test against 1. |
| */ |
| bool MPLSensor::isMpu3050() |
| { |
| return !strcmp(chip_ID, "mpu3050") || !strcmp(chip_ID, "MPU3050"); |
| } |
| |
| int MPLSensor::isLowPowerQuatEnabled() |
| { |
| #ifdef ENABLE_LP_QUAT_FEAT |
| return !isMpu3050(); |
| #else |
| return 0; |
| #endif |
| } |
| |
| int MPLSensor::isDmpDisplayOrientationOn() |
| { |
| #ifdef ENABLE_DMP_DISPL_ORIENT_FEAT |
| return !isMpu3050(); |
| #else |
| return 0; |
| #endif |
| } |