1/*
2* Copyright (C) 2014 Invensense, Inc.
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8*      http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17#define LOG_NDEBUG 0
18
19//see also the EXTRA_VERBOSE define in the MPLSensor.h header file
20
21#include <fcntl.h>
22#include <errno.h>
23#include <math.h>
24#include <float.h>
25#include <poll.h>
26#include <unistd.h>
27#include <dirent.h>
28#include <stdlib.h>
29#include <sys/select.h>
30#include <sys/syscall.h>
31#include <dlfcn.h>
32#include <pthread.h>
33#include <cutils/log.h>
34#include <utils/KeyedVector.h>
35#include <utils/Vector.h>
36#include <utils/String8.h>
37#include <string.h>
38#include <linux/input.h>
39#include <utils/Atomic.h>
40
41#include "MPLSensor.h"
42#include "PressureSensor.IIO.secondary.h"
43#include "MPLSupport.h"
44#include "sensor_params.h"
45
46#include "invensense.h"
47#include "invensense_adv.h"
48#include "ml_stored_data.h"
49#include "ml_load_dmp.h"
50#include "ml_sysfs_helper.h"
51
52#define ENABLE_MULTI_RATE
53// #define TESTING
54#define USE_LPQ_AT_FASTEST
55
56#ifdef THIRD_PARTY_ACCEL
57#pragma message("HAL:build third party accel support")
58#define USE_THIRD_PARTY_ACCEL (1)
59#else
60#define USE_THIRD_PARTY_ACCEL (0)
61#endif
62
63#define MAX_SYSFS_ATTRB (sizeof(struct sysfs_attrbs) / sizeof(char*))
64
65/******************************************************************************/
66/*  MPL Interface                                                             */
67/******************************************************************************/
68
69//#define INV_PLAYBACK_DBG
70#ifdef INV_PLAYBACK_DBG
71static FILE *logfile = NULL;
72#endif
73
74/*******************************************************************************
75 * MPLSensor class implementation
76 ******************************************************************************/
77
78static struct timespec mt_pre;
79
80// following extended initializer list would only be available with -std=c++11
81//  or -std=gnu+11
82MPLSensor::MPLSensor(CompassSensor *compass, int (*m_pt2AccelCalLoadFunc)(long *))
83                       : SensorBase(NULL, NULL),
84                         mMasterSensorMask(INV_ALL_SENSORS),
85                         mLocalSensorMask(0),
86                         mPollTime(-1),
87                         mStepCountPollTime(-1),
88                         mHaveGoodMpuCal(0),
89                         mGyroAccuracy(0),
90                         mAccelAccuracy(0),
91                         mCompassAccuracy(0),
92                         dmp_orient_fd(-1),
93                         mDmpOrientationEnabled(0),
94                         dmp_sign_motion_fd(-1),
95                         mDmpSignificantMotionEnabled(0),
96                         dmp_pedometer_fd(-1),
97                         mDmpPedometerEnabled(0),
98                         mDmpStepCountEnabled(0),
99                         mEnabled(0),
100                         mBatchEnabled(0),
101                         mOldBatchEnabledMask(0),
102                         mAccelInputReader(4),
103                         mGyroInputReader(32),
104                         mTempScale(0),
105                         mTempOffset(0),
106                         mTempCurrentTime(0),
107                         mAccelScale(2),
108                         mAccelSelfTestScale(2),
109                         mGyroScale(2000),
110                         mGyroSelfTestScale(2000),
111                         mCompassScale(0),
112                         mFactoryGyroBiasAvailable(false),
113                         mGyroBiasAvailable(false),
114                         mGyroBiasApplied(false),
115                         mFactoryAccelBiasAvailable(false),
116                         mAccelBiasAvailable(false),
117                         mAccelBiasApplied(false),
118                         mPendingMask(0),
119                         mSensorMask(0),
120                         mMplFeatureActiveMask(0),
121                         mFeatureActiveMask(0),
122                         mDmpOn(0),
123                         mPedUpdate(0),
124                         mPressureUpdate(0),
125                         mQuatSensorTimestamp(0),
126                         mStepSensorTimestamp(0),
127                         mLastStepCount(-1),
128                         mLeftOverBufferSize(0),
129                         mInitial6QuatValueAvailable(0),
130                         mFlushBatchSet(0),
131                         mSkipReadEvents(0),
132                         mDataMarkerDetected(0),
133                         mEmptyDataMarkerDetected(0) {
134    VFUNC_LOG;
135
136    inv_error_t rv;
137    int i, fd;
138    char *port = NULL;
139    char *ver_str;
140    unsigned long mSensorMask;
141    int res;
142    FILE *fptr;
143
144    mCompassSensor = compass;
145
146    LOGV_IF(EXTRA_VERBOSE,
147            "HAL:MPLSensor constructor : NumSensors = %d", NumSensors);
148
149    pthread_mutex_init(&mMplMutex, NULL);
150    pthread_mutex_init(&mHALMutex, NULL);
151    memset(mGyroOrientation, 0, sizeof(mGyroOrientation));
152    memset(mAccelOrientation, 0, sizeof(mAccelOrientation));
153    memset(mInitial6QuatValue, 0, sizeof(mInitial6QuatValue));
154    mFlushSensorEnabledVector.setCapacity(NumSensors);
155
156    /* setup sysfs paths */
157    inv_init_sysfs_attributes();
158
159    /* get chip name */
160    if (inv_get_chip_name(chip_ID) != INV_SUCCESS) {
161        LOGE("HAL:ERR- Failed to get chip ID\n");
162    } else {
163        LOGV_IF(PROCESS_VERBOSE, "HAL:Chip ID= %s\n", chip_ID);
164    }
165
166    enable_iio_sysfs();
167
168#ifdef ENABLE_PRESSURE
169    /* instantiate pressure sensor on secondary bus */
170    mPressureSensor = new PressureSensor((const char*)mSysfsPath);
171#endif
172
173    /* reset driver master enable */
174    masterEnable(0);
175
176    /* Load DMP image if capable, ie. MPU6515 */
177    loadDMP();
178
179    /* open temperature fd for temp comp */
180    LOGV_IF(EXTRA_VERBOSE, "HAL:gyro temperature path: %s", mpu.temperature);
181    gyro_temperature_fd = open(mpu.temperature, O_RDONLY);
182    if (gyro_temperature_fd == -1) {
183        LOGE("HAL:could not open temperature node");
184    } else {
185        LOGV_IF(EXTRA_VERBOSE,
186                "HAL:temperature_fd opened: %s", mpu.temperature);
187    }
188
189    /* read gyro FSR to calculate accel scale later */
190    char gyroBuf[5];
191    int count = 0;
192         LOGV_IF(SYSFS_VERBOSE,
193             "HAL:sysfs:cat %s (%lld)", mpu.gyro_fsr, getTimestamp());
194
195    fd = open(mpu.gyro_fsr, O_RDONLY);
196    if(fd < 0) {
197        LOGE("HAL:Error opening gyro FSR");
198    } else {
199        memset(gyroBuf, 0, sizeof(gyroBuf));
200        count = read_attribute_sensor(fd, gyroBuf, sizeof(gyroBuf));
201        if(count < 1) {
202            LOGE("HAL:Error reading gyro FSR");
203        } else {
204            count = sscanf(gyroBuf, "%ld", &mGyroScale);
205            if(count)
206                LOGV_IF(EXTRA_VERBOSE, "HAL:Gyro FSR used %ld", mGyroScale);
207        }
208        close(fd);
209    }
210
211    /* read gyro self test scale used to calculate factory cal bias later */
212    char gyroScale[5];
213         LOGV_IF(SYSFS_VERBOSE,
214             "HAL:sysfs:cat %s (%lld)", mpu.in_gyro_self_test_scale, getTimestamp());
215    fd = open(mpu.in_gyro_self_test_scale, O_RDONLY);
216    if(fd < 0) {
217        LOGE("HAL:Error opening gyro self test scale");
218    } else {
219        memset(gyroBuf, 0, sizeof(gyroBuf));
220        count = read_attribute_sensor(fd, gyroScale, sizeof(gyroScale));
221        if(count < 1) {
222            LOGE("HAL:Error reading gyro self test scale");
223        } else {
224            count = sscanf(gyroScale, "%ld", &mGyroSelfTestScale);
225            if(count)
226                LOGV_IF(EXTRA_VERBOSE, "HAL:Gyro self test scale used %ld", mGyroSelfTestScale);
227        }
228        close(fd);
229    }
230
231    /* open Factory Gyro Bias fd */
232    /* mFactoryGyBias contains bias values that will be used for device offset */
233    memset(mFactoryGyroBias, 0, sizeof(mFactoryGyroBias));
234    LOGV_IF(EXTRA_VERBOSE, "HAL:factory gyro x offset path: %s", mpu.in_gyro_x_offset);
235    LOGV_IF(EXTRA_VERBOSE, "HAL:factory gyro y offset path: %s", mpu.in_gyro_y_offset);
236    LOGV_IF(EXTRA_VERBOSE, "HAL:factory gyro z offset path: %s", mpu.in_gyro_z_offset);
237    gyro_x_offset_fd = open(mpu.in_gyro_x_offset, O_RDWR);
238    gyro_y_offset_fd = open(mpu.in_gyro_y_offset, O_RDWR);
239    gyro_z_offset_fd = open(mpu.in_gyro_z_offset, O_RDWR);
240    if (gyro_x_offset_fd == -1 ||
241             gyro_y_offset_fd == -1 || gyro_z_offset_fd == -1) {
242            LOGE("HAL:could not open factory gyro calibrated bias");
243    } else {
244        LOGV_IF(EXTRA_VERBOSE,
245             "HAL:gyro_offset opened");
246    }
247
248    /* open Gyro Bias fd */
249    /* mGyroBias contains bias values that will be used for framework */
250    /* mGyroChipBias contains bias values that will be used for dmp */
251    memset(mGyroBias, 0, sizeof(mGyroBias));
252    memset(mGyroChipBias, 0, sizeof(mGyroChipBias));
253    LOGV_IF(EXTRA_VERBOSE, "HAL: gyro x dmp bias path: %s", mpu.in_gyro_x_dmp_bias);
254    LOGV_IF(EXTRA_VERBOSE, "HAL: gyro y dmp bias path: %s", mpu.in_gyro_y_dmp_bias);
255    LOGV_IF(EXTRA_VERBOSE, "HAL: gyro z dmp bias path: %s", mpu.in_gyro_z_dmp_bias);
256    gyro_x_dmp_bias_fd = open(mpu.in_gyro_x_dmp_bias, O_RDWR);
257    gyro_y_dmp_bias_fd = open(mpu.in_gyro_y_dmp_bias, O_RDWR);
258    gyro_z_dmp_bias_fd = open(mpu.in_gyro_z_dmp_bias, O_RDWR);
259    if (gyro_x_dmp_bias_fd == -1 ||
260             gyro_y_dmp_bias_fd == -1 || gyro_z_dmp_bias_fd == -1) {
261            LOGE("HAL:could not open gyro DMP calibrated bias");
262    } else {
263        LOGV_IF(EXTRA_VERBOSE,
264             "HAL:gyro_dmp_bias opened");
265    }
266
267    /* read accel FSR to calcuate accel scale later */
268    if (USE_THIRD_PARTY_ACCEL == 0) {
269        char buf[3];
270        int count = 0;
271        LOGV_IF(SYSFS_VERBOSE,
272                "HAL:sysfs:cat %s (%lld)", mpu.accel_fsr, getTimestamp());
273
274        fd = open(mpu.accel_fsr, O_RDONLY);
275        if(fd < 0) {
276            LOGE("HAL:Error opening accel FSR");
277        } else {
278           memset(buf, 0, sizeof(buf));
279           count = read_attribute_sensor(fd, buf, sizeof(buf));
280           if(count < 1) {
281               LOGE("HAL:Error reading accel FSR");
282           } else {
283               count = sscanf(buf, "%d", &mAccelScale);
284               if(count)
285                   LOGV_IF(EXTRA_VERBOSE, "HAL:Accel FSR used %d", mAccelScale);
286           }
287           close(fd);
288        }
289
290        /* read accel self test scale used to calculate factory cal bias later */
291        char accelScale[5];
292             LOGV_IF(SYSFS_VERBOSE,
293                 "HAL:sysfs:cat %s (%lld)", mpu.in_accel_self_test_scale, getTimestamp());
294        fd = open(mpu.in_accel_self_test_scale, O_RDONLY);
295        if(fd < 0) {
296            LOGE("HAL:Error opening gyro self test scale");
297        } else {
298            memset(buf, 0, sizeof(buf));
299            count = read_attribute_sensor(fd, accelScale, sizeof(accelScale));
300            if(count < 1) {
301                LOGE("HAL:Error reading accel self test scale");
302            } else {
303                count = sscanf(accelScale, "%ld", &mAccelSelfTestScale);
304                if(count)
305                    LOGV_IF(EXTRA_VERBOSE, "HAL:Accel self test scale used %ld", mAccelSelfTestScale);
306            }
307            close(fd);
308        }
309
310        /* open Factory Accel Bias fd */
311        /* mFactoryAccelBias contains bias values that will be used for device offset */
312        memset(mFactoryAccelBias, 0, sizeof(mFactoryAccelBias));
313        LOGV_IF(EXTRA_VERBOSE, "HAL:factory accel x offset path: %s", mpu.in_accel_x_offset);
314        LOGV_IF(EXTRA_VERBOSE, "HAL:factory accel y offset path: %s", mpu.in_accel_y_offset);
315        LOGV_IF(EXTRA_VERBOSE, "HAL:factory accel z offset path: %s", mpu.in_accel_z_offset);
316        accel_x_offset_fd = open(mpu.in_accel_x_offset, O_RDWR);
317        accel_y_offset_fd = open(mpu.in_accel_y_offset, O_RDWR);
318        accel_z_offset_fd = open(mpu.in_accel_z_offset, O_RDWR);
319        if (accel_x_offset_fd == -1 ||
320                 accel_y_offset_fd == -1 || accel_z_offset_fd == -1) {
321                LOGE("HAL:could not open factory accel calibrated bias");
322        } else {
323            LOGV_IF(EXTRA_VERBOSE,
324                 "HAL:accel_offset opened");
325        }
326
327        /* open Accel Bias fd */
328        /* mAccelBias contains bias that will be used for dmp */
329        memset(mAccelBias, 0, sizeof(mAccelBias));
330        LOGV_IF(EXTRA_VERBOSE, "HAL:accel x dmp bias path: %s", mpu.in_accel_x_dmp_bias);
331        LOGV_IF(EXTRA_VERBOSE, "HAL:accel y dmp bias path: %s", mpu.in_accel_y_dmp_bias);
332        LOGV_IF(EXTRA_VERBOSE, "HAL:accel z dmp bias path: %s", mpu.in_accel_z_dmp_bias);
333        accel_x_dmp_bias_fd = open(mpu.in_accel_x_dmp_bias, O_RDWR);
334        accel_y_dmp_bias_fd = open(mpu.in_accel_y_dmp_bias, O_RDWR);
335        accel_z_dmp_bias_fd = open(mpu.in_accel_z_dmp_bias, O_RDWR);
336        if (accel_x_dmp_bias_fd == -1 ||
337                 accel_y_dmp_bias_fd == -1 || accel_z_dmp_bias_fd == -1) {
338            LOGE("HAL:could not open accel DMP calibrated bias");
339        } else {
340            LOGV_IF(EXTRA_VERBOSE,
341                 "HAL:accel_dmp_bias opened");
342        }
343    }
344
345    dmp_sign_motion_fd = open(mpu.event_smd, O_RDONLY | O_NONBLOCK);
346    if (dmp_sign_motion_fd < 0) {
347        LOGE("HAL:ERR couldn't open dmp_sign_motion node");
348    } else {
349        LOGV_IF(ENG_VERBOSE,
350                "HAL:dmp_sign_motion_fd opened : %d", dmp_sign_motion_fd);
351    }
352#if 1
353    /* the following threshold can be modified for SMD sensitivity */
354    int motionThreshold = 3000;
355    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
356                motionThreshold, mpu.smd_threshold, getTimestamp());
357        res = write_sysfs_int(mpu.smd_threshold, motionThreshold);
358#endif
359#if 0
360    int StepCounterThreshold = 5;
361    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
362                StepCounterThreshold, mpu.pedometer_step_thresh, getTimestamp());
363        res = write_sysfs_int(mpu.pedometer_step_thresh, StepCounterThreshold);
364#endif
365
366    dmp_pedometer_fd = open(mpu.event_pedometer, O_RDONLY | O_NONBLOCK);
367    if (dmp_pedometer_fd < 0) {
368        LOGE("HAL:ERR couldn't open dmp_pedometer node");
369    } else {
370        LOGV_IF(ENG_VERBOSE,
371                "HAL:dmp_pedometer_fd opened : %d", dmp_pedometer_fd);
372    }
373
374    initBias();
375
376    (void)inv_get_version(&ver_str);
377    LOGI("%s\n", ver_str);
378
379    /* setup MPL */
380    inv_constructor_init();
381
382#ifdef INV_PLAYBACK_DBG
383    LOGV_IF(PROCESS_VERBOSE, "HAL:inv_turn_on_data_logging");
384    logfile = fopen("/data/playback.bin", "w+");
385    if (logfile)
386        inv_turn_on_data_logging(logfile);
387#endif
388
389    /* setup orientation matrix and scale */
390    inv_set_device_properties();
391
392    /* initialize sensor data */
393    memset(mPendingEvents, 0, sizeof(mPendingEvents));
394    memset(mPendingFlushEvents, 0, sizeof(mPendingEvents));
395
396    mPendingEvents[RotationVector].version = sizeof(sensors_event_t);
397    mPendingEvents[RotationVector].sensor = ID_RV;
398    mPendingEvents[RotationVector].type = SENSOR_TYPE_ROTATION_VECTOR;
399    mPendingEvents[RotationVector].acceleration.status
400            = SENSOR_STATUS_ACCURACY_HIGH;
401
402    mPendingEvents[GameRotationVector].version = sizeof(sensors_event_t);
403    mPendingEvents[GameRotationVector].sensor = ID_GRV;
404    mPendingEvents[GameRotationVector].type = SENSOR_TYPE_GAME_ROTATION_VECTOR;
405    mPendingEvents[GameRotationVector].acceleration.status
406            = SENSOR_STATUS_ACCURACY_HIGH;
407
408    mPendingEvents[LinearAccel].version = sizeof(sensors_event_t);
409    mPendingEvents[LinearAccel].sensor = ID_LA;
410    mPendingEvents[LinearAccel].type = SENSOR_TYPE_LINEAR_ACCELERATION;
411    mPendingEvents[LinearAccel].acceleration.status
412            = SENSOR_STATUS_ACCURACY_HIGH;
413
414    mPendingEvents[Gravity].version = sizeof(sensors_event_t);
415    mPendingEvents[Gravity].sensor = ID_GR;
416    mPendingEvents[Gravity].type = SENSOR_TYPE_GRAVITY;
417    mPendingEvents[Gravity].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
418
419    mPendingEvents[Gyro].version = sizeof(sensors_event_t);
420    mPendingEvents[Gyro].sensor = ID_GY;
421    mPendingEvents[Gyro].type = SENSOR_TYPE_GYROSCOPE;
422    mPendingEvents[Gyro].gyro.status = SENSOR_STATUS_ACCURACY_HIGH;
423
424    mPendingEvents[RawGyro].version = sizeof(sensors_event_t);
425    mPendingEvents[RawGyro].sensor = ID_RG;
426    mPendingEvents[RawGyro].type = SENSOR_TYPE_GYROSCOPE_UNCALIBRATED;
427    mPendingEvents[RawGyro].gyro.status = SENSOR_STATUS_ACCURACY_HIGH;
428
429    mPendingEvents[Accelerometer].version = sizeof(sensors_event_t);
430    mPendingEvents[Accelerometer].sensor = ID_A;
431    mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER;
432    mPendingEvents[Accelerometer].acceleration.status
433            = SENSOR_STATUS_ACCURACY_HIGH;
434
435    /* Invensense compass calibration */
436    mPendingEvents[MagneticField].version = sizeof(sensors_event_t);
437    mPendingEvents[MagneticField].sensor = ID_M;
438    mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD;
439    mPendingEvents[MagneticField].magnetic.status =
440        SENSOR_STATUS_ACCURACY_HIGH;
441
442    mPendingEvents[RawMagneticField].version = sizeof(sensors_event_t);
443    mPendingEvents[RawMagneticField].sensor = ID_RM;
444    mPendingEvents[RawMagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED;
445    mPendingEvents[RawMagneticField].magnetic.status =
446        SENSOR_STATUS_ACCURACY_HIGH;
447
448#ifdef ENABLE_PRESSURE
449    mPendingEvents[Pressure].version = sizeof(sensors_event_t);
450    mPendingEvents[Pressure].sensor = ID_PS;
451    mPendingEvents[Pressure].type = SENSOR_TYPE_PRESSURE;
452    mPendingEvents[Pressure].magnetic.status =
453        SENSOR_STATUS_ACCURACY_HIGH;
454#endif
455
456    mPendingEvents[Orientation].version = sizeof(sensors_event_t);
457    mPendingEvents[Orientation].sensor = ID_O;
458    mPendingEvents[Orientation].type = SENSOR_TYPE_ORIENTATION;
459    mPendingEvents[Orientation].orientation.status
460            = SENSOR_STATUS_ACCURACY_HIGH;
461
462    mPendingEvents[GeomagneticRotationVector].version = sizeof(sensors_event_t);
463    mPendingEvents[GeomagneticRotationVector].sensor = ID_GMRV;
464    mPendingEvents[GeomagneticRotationVector].type
465            = SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR;
466    mPendingEvents[GeomagneticRotationVector].acceleration.status
467            = SENSOR_STATUS_ACCURACY_HIGH;
468
469    mSmEvents.version = sizeof(sensors_event_t);
470    mSmEvents.sensor = ID_SM;
471    mSmEvents.type = SENSOR_TYPE_SIGNIFICANT_MOTION;
472    mSmEvents.acceleration.status = SENSOR_STATUS_UNRELIABLE;
473
474    mSdEvents.version = sizeof(sensors_event_t);
475    mSdEvents.sensor = ID_P;
476    mSdEvents.type = SENSOR_TYPE_STEP_DETECTOR;
477    mSdEvents.acceleration.status = SENSOR_STATUS_UNRELIABLE;
478
479    mScEvents.version = sizeof(sensors_event_t);
480    mScEvents.sensor = ID_SC;
481    mScEvents.type = SENSOR_TYPE_STEP_COUNTER;
482    mScEvents.acceleration.status = SENSOR_STATUS_UNRELIABLE;
483
484    /* Event Handlers for HW and Virtual Sensors */
485    mHandlers[RotationVector] = &MPLSensor::rvHandler;
486    mHandlers[GameRotationVector] = &MPLSensor::grvHandler;
487    mHandlers[LinearAccel] = &MPLSensor::laHandler;
488    mHandlers[Gravity] = &MPLSensor::gravHandler;
489    mHandlers[Gyro] = &MPLSensor::gyroHandler;
490    mHandlers[RawGyro] = &MPLSensor::rawGyroHandler;
491    mHandlers[Accelerometer] = &MPLSensor::accelHandler;
492    mHandlers[MagneticField] = &MPLSensor::compassHandler;
493    mHandlers[RawMagneticField] = &MPLSensor::rawCompassHandler;
494    mHandlers[Orientation] = &MPLSensor::orienHandler;
495    mHandlers[GeomagneticRotationVector] = &MPLSensor::gmHandler;
496#ifdef ENABLE_PRESSURE
497    mHandlers[Pressure] = &MPLSensor::psHandler;
498#endif
499
500    /* initialize delays to reasonable values */
501    for (int i = 0; i < NumSensors; i++) {
502        mDelays[i] = 1000000000LL;
503        mBatchDelays[i] = 1000000000LL;
504        mBatchTimeouts[i] = 100000000000LL;
505    }
506
507    /* initialize Compass Bias */
508    memset(mCompassBias, 0, sizeof(mCompassBias));
509
510    /* initialize Factory Accel Bias */
511    memset(mFactoryAccelBias, 0, sizeof(mFactoryAccelBias));
512
513    /* initialize Gyro Bias */
514    memset(mGyroBias, 0, sizeof(mGyroBias));
515    memset(mGyroChipBias, 0, sizeof(mGyroChipBias));
516
517    /* load calibration file from /data/inv_cal_data.bin */
518    rv = inv_load_calibration();
519    if(rv == INV_SUCCESS) {
520        LOGV_IF(PROCESS_VERBOSE, "HAL:Calibration file successfully loaded");
521        /* Get initial values */
522        getCompassBias();
523        getGyroBias();
524        if (mGyroBiasAvailable) {
525            setGyroBias();
526        }
527        getAccelBias();
528        getFactoryGyroBias();
529        if (mFactoryGyroBiasAvailable) {
530            setFactoryGyroBias();
531        }
532        getFactoryAccelBias();
533        if (mFactoryAccelBiasAvailable) {
534            setFactoryAccelBias();
535        }
536    }
537    else
538        LOGE("HAL:Could not open or load MPL calibration file (%d)", rv);
539
540    /* takes external accel calibration load workflow */
541    if( m_pt2AccelCalLoadFunc != NULL) {
542        long accel_offset[3];
543        long tmp_offset[3];
544        int result = m_pt2AccelCalLoadFunc(accel_offset);
545        if(result)
546            LOGW("HAL:Vendor accelerometer calibration file load failed %d\n",
547                 result);
548        else {
549            LOGW("HAL:Vendor accelerometer calibration file successfully "
550                 "loaded");
551            inv_get_mpl_accel_bias(tmp_offset, NULL);
552            LOGV_IF(PROCESS_VERBOSE,
553                    "HAL:Original accel offset, %ld, %ld, %ld\n",
554               tmp_offset[0], tmp_offset[1], tmp_offset[2]);
555            inv_set_accel_bias_mask(accel_offset, mAccelAccuracy,4);
556            inv_get_mpl_accel_bias(tmp_offset, NULL);
557            LOGV_IF(PROCESS_VERBOSE, "HAL:Set accel offset, %ld, %ld, %ld\n",
558               tmp_offset[0], tmp_offset[1], tmp_offset[2]);
559        }
560    }
561    /* end of external accel calibration load workflow */
562
563    /* disable all sensors and features */
564    masterEnable(0);
565    enableGyro(0);
566    enableLowPowerAccel(0);
567    enableAccel(0);
568    enableCompass(0,0);
569#ifdef ENABLE_PRESSURE
570    enablePressure(0);
571#endif
572    enableBatch(0);
573
574    if (isLowPowerQuatEnabled()) {
575        enableLPQuaternion(0);
576    }
577
578    if (isDmpDisplayOrientationOn()) {
579        // open DMP Orient Fd
580        openDmpOrientFd();
581        enableDmpOrientation(!isDmpScreenAutoRotationEnabled());
582    }
583}
584
585void MPLSensor::enable_iio_sysfs(void)
586{
587    VFUNC_LOG;
588
589    char iio_device_node[MAX_CHIP_ID_LEN];
590    FILE *tempFp = NULL;
591
592    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo 1 > %s (%lld)",
593            mpu.in_timestamp_en, getTimestamp());
594    // Either fopen()/open() are okay for sysfs access
595    // developers could choose what they want
596    // with fopen(), the benefit is that fprintf()/fscanf() are available
597    tempFp = fopen(mpu.in_timestamp_en, "w");
598    if (tempFp == NULL) {
599        LOGE("HAL:could not open timestamp enable");
600    } else {
601        if(fprintf(tempFp, "%d", 1) < 0) {
602            LOGE("HAL:could not enable timestamp");
603        }
604        if(fclose(tempFp) < 0) {
605            LOGE("HAL:could not close timestamp");
606        }
607    }
608
609    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
610            IIO_BUFFER_LENGTH, mpu.buffer_length, getTimestamp());
611    tempFp = fopen(mpu.buffer_length, "w");
612    if (tempFp == NULL) {
613        LOGE("HAL:could not open buffer length");
614    } else {
615        if (fprintf(tempFp, "%d", IIO_BUFFER_LENGTH) < 0) {
616            LOGE("HAL:could not write buffer length");
617        }
618        if (fclose(tempFp) < 0) {
619            LOGE("HAL:could not close buffer length");
620        }
621    }
622
623    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
624            1, mpu.chip_enable, getTimestamp());
625    tempFp = fopen(mpu.chip_enable, "w");
626    if (tempFp == NULL) {
627        LOGE("HAL:could not open chip enable");
628    } else {
629        if (fprintf(tempFp, "%d", 1) < 0) {
630            LOGE("HAL:could not write chip enable");
631        }
632        if (fclose(tempFp) < 0) {
633            LOGE("HAL:could not close chip enable");
634        }
635    }
636
637    inv_get_iio_device_node(iio_device_node);
638    iio_fd = open(iio_device_node, O_RDONLY);
639    if (iio_fd < 0) {
640        LOGE("HAL:could not open iio device node");
641    } else {
642        LOGV_IF(ENG_VERBOSE, "HAL:iio iio_fd opened : %d", iio_fd);
643    }
644}
645
646int MPLSensor::inv_constructor_init(void)
647{
648    VFUNC_LOG;
649
650    inv_error_t result = inv_init_mpl();
651    if (result) {
652        LOGE("HAL:inv_init_mpl() failed");
653        return result;
654    }
655    result = inv_constructor_default_enable();
656    result = inv_start_mpl();
657    if (result) {
658        LOGE("HAL:inv_start_mpl() failed");
659        LOG_RESULT_LOCATION(result);
660        return result;
661    }
662
663    return result;
664}
665
666int MPLSensor::inv_constructor_default_enable(void)
667{
668    VFUNC_LOG;
669
670    inv_error_t result;
671
672/*******************************************************************************
673
674********************************************************************************
675
676The InvenSense binary file (libmplmpu.so) is subject to Google's standard terms
677and conditions as accepted in the click-through agreement required to download
678this library.
679The library includes, but is not limited to the following function calls:
680inv_enable_quaternion().
681
682ANY VIOLATION OF SUCH TERMS AND CONDITIONS WILL BE STRICTLY ENFORCED.
683
684********************************************************************************
685
686*******************************************************************************/
687
688    result = inv_enable_quaternion();
689    if (result) {
690        LOGE("HAL:Cannot enable quaternion\n");
691        return result;
692    }
693
694    result = inv_enable_in_use_auto_calibration();
695    if (result) {
696        return result;
697    }
698
699    result = inv_enable_fast_nomot();
700    if (result) {
701        return result;
702    }
703
704    result = inv_enable_gyro_tc();
705    if (result) {
706        return result;
707    }
708
709    result = inv_enable_hal_outputs();
710    if (result) {
711        return result;
712    }
713
714    if (!mCompassSensor->providesCalibration()) {
715        /* Invensense compass calibration */
716        LOGV_IF(ENG_VERBOSE, "HAL:Invensense vector compass cal enabled");
717        result = inv_enable_vector_compass_cal();
718        if (result) {
719            LOG_RESULT_LOCATION(result);
720            return result;
721        } else {
722            mMplFeatureActiveMask |= INV_COMPASS_CAL;
723        }
724        // specify MPL's trust weight, used by compass algorithms
725        inv_vector_compass_cal_sensitivity(3);
726
727        /* disabled by default
728        result = inv_enable_compass_bias_w_gyro();
729        if (result) {
730            LOG_RESULT_LOCATION(result);
731            return result;
732        }
733        */
734
735        result = inv_enable_heading_from_gyro();
736        if (result) {
737            LOG_RESULT_LOCATION(result);
738            return result;
739        }
740
741        result = inv_enable_magnetic_disturbance();
742        if (result) {
743            LOG_RESULT_LOCATION(result);
744            return result;
745        }
746        //inv_enable_magnetic_disturbance_logging();
747    }
748
749    result = inv_enable_9x_sensor_fusion();
750    if (result) {
751        LOG_RESULT_LOCATION(result);
752        return result;
753    } else {
754        // 9x sensor fusion enables Compass fit
755        mMplFeatureActiveMask |= INV_COMPASS_FIT;
756    }
757
758    result = inv_enable_no_gyro_fusion();
759    if (result) {
760        LOG_RESULT_LOCATION(result);
761        return result;
762    }
763
764    return result;
765}
766
767/* TODO: create function pointers to calculate scale */
768void MPLSensor::inv_set_device_properties(void)
769{
770    VFUNC_LOG;
771
772    unsigned short orient;
773
774    inv_get_sensors_orientation();
775
776    inv_set_gyro_sample_rate(DEFAULT_MPL_GYRO_RATE);
777    inv_set_compass_sample_rate(DEFAULT_MPL_COMPASS_RATE);
778
779    /* gyro setup */
780    orient = inv_orientation_matrix_to_scalar(mGyroOrientation);
781    inv_set_gyro_orientation_and_scale(orient, mGyroScale << 15);
782    LOGI_IF(EXTRA_VERBOSE, "HAL: Set MPL Gyro Scale %ld", mGyroScale << 15);
783
784    /* accel setup */
785    orient = inv_orientation_matrix_to_scalar(mAccelOrientation);
786    /* use for third party accel input subsystem driver
787    inv_set_accel_orientation_and_scale(orient, 1LL << 22);
788    */
789    inv_set_accel_orientation_and_scale(orient, (long)mAccelScale << 15);
790    LOGI_IF(EXTRA_VERBOSE,
791            "HAL: Set MPL Accel Scale %ld", (long)mAccelScale << 15);
792
793    /* compass setup */
794    signed char orientMtx[9];
795    mCompassSensor->getOrientationMatrix(orientMtx);
796    orient =
797        inv_orientation_matrix_to_scalar(orientMtx);
798    long sensitivity;
799    sensitivity = mCompassSensor->getSensitivity();
800    inv_set_compass_orientation_and_scale(orient, sensitivity);
801    mCompassScale = sensitivity;
802    LOGI_IF(EXTRA_VERBOSE,
803            "HAL: Set MPL Compass Scale %ld", mCompassScale);
804}
805
806void MPLSensor::loadDMP(void)
807{
808    VFUNC_LOG;
809
810    int res, fd;
811    FILE *fptr;
812
813    if (isMpuNonDmp()) {
814        return;
815    }
816
817    /* load DMP firmware */
818    LOGV_IF(SYSFS_VERBOSE,
819            "HAL:sysfs:cat %s (%lld)", mpu.firmware_loaded, getTimestamp());
820    fd = open(mpu.firmware_loaded, O_RDONLY);
821    if(fd < 0) {
822        LOGE("HAL:could not open dmp state");
823    } else {
824        if(inv_read_dmp_state(fd) == 0) {
825            LOGV_IF(EXTRA_VERBOSE, "HAL:load dmp: %s", mpu.dmp_firmware);
826            fptr = fopen(mpu.dmp_firmware, "w");
827            if(fptr == NULL) {
828                LOGE("HAL:could not open dmp_firmware");
829            } else {
830                if (inv_load_dmp(fptr) < 0) {
831                    LOGE("HAL:load DMP failed");
832                } else {
833                    LOGV_IF(PROCESS_VERBOSE, "HAL:DMP loaded");
834                }
835                if (fclose(fptr) < 0) {
836                    LOGE("HAL:could not close dmp firmware");
837                }
838            }
839        } else {
840            LOGV_IF(ENG_VERBOSE, "HAL:DMP is already loaded");
841        }
842    }
843
844    // onDmp(1);    //Can't enable here. See note onDmp()
845}
846
847void MPLSensor::inv_get_sensors_orientation(void)
848{
849    VFUNC_LOG;
850
851    FILE *fptr;
852
853    // get gyro orientation
854    LOGV_IF(SYSFS_VERBOSE,
855            "HAL:sysfs:cat %s (%lld)", mpu.gyro_orient, getTimestamp());
856    fptr = fopen(mpu.gyro_orient, "r");
857    if (fptr != NULL) {
858        int om[9];
859        if (fscanf(fptr, "%d,%d,%d,%d,%d,%d,%d,%d,%d",
860               &om[0], &om[1], &om[2], &om[3], &om[4], &om[5],
861               &om[6], &om[7], &om[8]) < 0) {
862            LOGE("HAL:Could not read gyro mounting matrix");
863        } else {
864            LOGV_IF(EXTRA_VERBOSE,
865                    "HAL:gyro mounting matrix: "
866                    "%+d %+d %+d %+d %+d %+d %+d %+d %+d",
867                    om[0], om[1], om[2], om[3], om[4], om[5], om[6], om[7], om[8]);
868
869            mGyroOrientation[0] = om[0];
870            mGyroOrientation[1] = om[1];
871            mGyroOrientation[2] = om[2];
872            mGyroOrientation[3] = om[3];
873            mGyroOrientation[4] = om[4];
874            mGyroOrientation[5] = om[5];
875            mGyroOrientation[6] = om[6];
876            mGyroOrientation[7] = om[7];
877            mGyroOrientation[8] = om[8];
878        }
879        if (fclose(fptr) < 0) {
880            LOGE("HAL:Could not close gyro mounting matrix");
881        }
882    }
883
884    // get accel orientation
885    LOGV_IF(SYSFS_VERBOSE,
886            "HAL:sysfs:cat %s (%lld)", mpu.accel_orient, getTimestamp());
887    fptr = fopen(mpu.accel_orient, "r");
888    if (fptr != NULL) {
889        int om[9];
890        if (fscanf(fptr, "%d,%d,%d,%d,%d,%d,%d,%d,%d",
891            &om[0], &om[1], &om[2], &om[3], &om[4], &om[5],
892            &om[6], &om[7], &om[8]) < 0) {
893            LOGE("HAL:could not read accel mounting matrix");
894        } else {
895            LOGV_IF(EXTRA_VERBOSE,
896           "HAL:accel mounting matrix: "
897           "%+d %+d %+d %+d %+d %+d %+d %+d %+d",
898           om[0], om[1], om[2], om[3], om[4], om[5], om[6], om[7], om[8]);
899
900           mAccelOrientation[0] = om[0];
901           mAccelOrientation[1] = om[1];
902           mAccelOrientation[2] = om[2];
903           mAccelOrientation[3] = om[3];
904           mAccelOrientation[4] = om[4];
905           mAccelOrientation[5] = om[5];
906           mAccelOrientation[6] = om[6];
907           mAccelOrientation[7] = om[7];
908           mAccelOrientation[8] = om[8];
909        }
910        if (fclose(fptr) < 0) {
911            LOGE("HAL:could not close accel mounting matrix");
912        }
913    }
914}
915
916MPLSensor::~MPLSensor()
917{
918    VFUNC_LOG;
919
920    /* Close open fds */
921    if (iio_fd > 0)
922        close(iio_fd);
923    if( accel_fd > 0 )
924        close(accel_fd );
925    if (gyro_temperature_fd > 0)
926        close(gyro_temperature_fd);
927    if (sysfs_names_ptr)
928        free(sysfs_names_ptr);
929
930    closeDmpOrientFd();
931
932    if (accel_x_dmp_bias_fd > 0) {
933        close(accel_x_dmp_bias_fd);
934    }
935    if (accel_y_dmp_bias_fd > 0) {
936        close(accel_y_dmp_bias_fd);
937    }
938    if (accel_z_dmp_bias_fd > 0) {
939        close(accel_z_dmp_bias_fd);
940    }
941
942    if (gyro_x_dmp_bias_fd > 0) {
943        close(gyro_x_dmp_bias_fd);
944    }
945    if (gyro_y_dmp_bias_fd > 0) {
946        close(gyro_y_dmp_bias_fd);
947    }
948    if (gyro_z_dmp_bias_fd > 0) {
949        close(gyro_z_dmp_bias_fd);
950    }
951
952    if (gyro_x_offset_fd > 0) {
953        close(gyro_x_dmp_bias_fd);
954    }
955    if (gyro_y_offset_fd > 0) {
956        close(gyro_y_offset_fd);
957    }
958    if (gyro_z_offset_fd > 0) {
959        close(accel_z_offset_fd);
960    }
961
962    /* Turn off Gyro master enable          */
963    /* A workaround until driver handles it */
964    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
965            0, mpu.master_enable, getTimestamp());
966    write_sysfs_int(mpu.master_enable, 0);
967
968#ifdef INV_PLAYBACK_DBG
969    inv_turn_off_data_logging();
970    if (fclose(logfile) < 0) {
971        LOGE("cannot close debug log file");
972    }
973#endif
974}
975
976#define GY_ENABLED  ((1 << ID_GY) & enabled_sensors)
977#define RGY_ENABLED ((1 << ID_RG) & enabled_sensors)
978#define A_ENABLED   ((1 << ID_A)  & enabled_sensors)
979#define M_ENABLED   ((1 << ID_M) & enabled_sensors)
980#define RM_ENABLED  ((1 << ID_RM) & enabled_sensors)
981#define O_ENABLED   ((1 << ID_O)  & enabled_sensors)
982#define LA_ENABLED  ((1 << ID_LA) & enabled_sensors)
983#define GR_ENABLED  ((1 << ID_GR) & enabled_sensors)
984#define RV_ENABLED  ((1 << ID_RV) & enabled_sensors)
985#define GRV_ENABLED ((1 << ID_GRV) & enabled_sensors)
986#define GMRV_ENABLED ((1 << ID_GMRV) & enabled_sensors)
987
988#ifdef ENABLE_PRESSURE
989#define PS_ENABLED  ((1 << ID_PS) & enabled_sensors)
990#endif
991
992/* this applies to BMA250 Input Subsystem Driver only */
993int MPLSensor::setAccelInitialState()
994{
995    VFUNC_LOG;
996
997    struct input_absinfo absinfo_x;
998    struct input_absinfo absinfo_y;
999    struct input_absinfo absinfo_z;
1000    float value;
1001    if (!ioctl(accel_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo_x) &&
1002        !ioctl(accel_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo_y) &&
1003        !ioctl(accel_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo_z)) {
1004        value = absinfo_x.value;
1005        mPendingEvents[Accelerometer].data[0] = value * CONVERT_A_X;
1006        value = absinfo_y.value;
1007        mPendingEvents[Accelerometer].data[1] = value * CONVERT_A_Y;
1008        value = absinfo_z.value;
1009        mPendingEvents[Accelerometer].data[2] = value * CONVERT_A_Z;
1010        //mHasPendingEvent = true;
1011    }
1012    return 0;
1013}
1014
1015int MPLSensor::onDmp(int en)
1016{
1017    VFUNC_LOG;
1018
1019    int res = -1;
1020    int status;
1021    mDmpOn = en;
1022
1023    //Sequence to enable DMP
1024    //1. Load DMP image if not already loaded
1025    //2. Either Gyro or Accel must be enabled/configured before next step
1026    //3. Enable DMP
1027
1028    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:cat %s (%lld)",
1029            mpu.firmware_loaded, getTimestamp());
1030    if(read_sysfs_int(mpu.firmware_loaded, &status) < 0){
1031        LOGE("HAL:ERR can't get firmware_loaded status");
1032    } else if (status == 1) {
1033        //Write only if curr DMP state <> request
1034        LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:cat %s (%lld)",
1035                mpu.dmp_on, getTimestamp());
1036        if (read_sysfs_int(mpu.dmp_on, &status) < 0) {
1037            LOGE("HAL:ERR can't read DMP state");
1038        } else if (status != en) {
1039            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1040                    en, mpu.dmp_on, getTimestamp());
1041            if (write_sysfs_int(mpu.dmp_on, en) < 0) {
1042                LOGE("HAL:ERR can't write dmp_on");
1043            } else {
1044                mDmpOn = en;
1045                res = 0;    //Indicate write successful
1046                if(!en) {
1047                    setAccelBias();
1048                }
1049            }
1050            //Enable DMP interrupt
1051            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1052                    en, mpu.dmp_int_on, getTimestamp());
1053            if (write_sysfs_int(mpu.dmp_int_on, en) < 0) {
1054                LOGE("HAL:ERR can't en/dis DMP interrupt");
1055            }
1056
1057            // disable DMP event interrupt if needed
1058            if (!en) {
1059                LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1060                        en, mpu.dmp_event_int_on, getTimestamp());
1061                if (write_sysfs_int(mpu.dmp_event_int_on, en) < 0) {
1062                    res = -1;
1063                    LOGE("HAL:ERR can't enable DMP event interrupt");
1064                }
1065            }
1066        } else {
1067            mDmpOn = en;
1068            res = 0;    //DMP already set as requested
1069            if(!en) {
1070                setAccelBias();
1071            }
1072        }
1073    } else {
1074        LOGE("HAL:ERR No DMP image");
1075    }
1076    return res;
1077}
1078
1079int MPLSensor::setDmpFeature(int en)
1080{
1081    int res = 0;
1082
1083    // set sensor engine and fifo
1084    if ((mFeatureActiveMask & DMP_FEATURE_MASK) || en) {
1085        if ((mFeatureActiveMask & INV_DMP_6AXIS_QUATERNION) ||
1086                (mFeatureActiveMask & INV_DMP_PED_QUATERNION) ||
1087                (mFeatureActiveMask & INV_DMP_QUATERNION)) {
1088            res = enableGyro(1);
1089            if (res < 0) {
1090                return res;
1091            }
1092            if (!(mLocalSensorMask & mMasterSensorMask & INV_THREE_AXIS_GYRO)) {
1093                res = turnOffGyroFifo();
1094                if (res < 0) {
1095                    return res;
1096                }
1097            }
1098        }
1099        res = enableAccel(1);
1100        if (res < 0) {
1101            return res;
1102        }
1103        if (!(mLocalSensorMask & mMasterSensorMask & INV_THREE_AXIS_ACCEL)) {
1104            res = turnOffAccelFifo();
1105            if (res < 0) {
1106                return res;
1107            }
1108        }
1109    } else {
1110        if (!(mLocalSensorMask & mMasterSensorMask & INV_THREE_AXIS_GYRO)) {
1111            res = enableGyro(0);
1112            if (res < 0) {
1113                return res;
1114            }
1115        }
1116        if (!(mLocalSensorMask & mMasterSensorMask & INV_THREE_AXIS_ACCEL)) {
1117            res = enableAccel(0);
1118            if (res < 0) {
1119                return res;
1120            }
1121        }
1122    }
1123
1124    // set sensor data interrupt
1125    uint32_t dataInterrupt = (mEnabled || (mFeatureActiveMask & INV_DMP_BATCH_MODE));
1126    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1127                !dataInterrupt, mpu.dmp_event_int_on, getTimestamp());
1128    if (write_sysfs_int(mpu.dmp_event_int_on, !dataInterrupt) < 0) {
1129        res = -1;
1130        LOGE("HAL:ERR can't enable DMP event interrupt");
1131    }
1132    return res;
1133}
1134
1135int MPLSensor::computeAndSetDmpState()
1136{
1137    int res = 0;
1138    bool dmpState = 0;
1139
1140    if (mFeatureActiveMask) {
1141        dmpState = 1;
1142        LOGV_IF(PROCESS_VERBOSE, "HAL:computeAndSetDmpState() mFeatureActiveMask = 1");
1143    } else if ((mEnabled & VIRTUAL_SENSOR_9AXES_MASK)
1144                        || (mEnabled & VIRTUAL_SENSOR_GYRO_6AXES_MASK)) {
1145            if (checkLPQuaternion() && checkLPQRateSupported()) {
1146                dmpState = 1;
1147                LOGV_IF(PROCESS_VERBOSE, "HAL:computeAndSetDmpState() Sensor Fusion = 1");
1148            }
1149    } /*else {
1150        unsigned long sensor = mLocalSensorMask & mMasterSensorMask;
1151        if (sensor & (INV_THREE_AXIS_ACCEL & INV_THREE_AXIS_GYRO)) {
1152            dmpState = 1;
1153            LOGV_IF(PROCESS_VERBOSE, "HAL:computeAndSetDmpState() accel and gyro = 1");
1154        }
1155    }*/
1156
1157    // set Dmp state
1158    res = onDmp(dmpState);
1159    if (res < 0)
1160        return res;
1161
1162    if (dmpState) {
1163        // set DMP rate to 200Hz
1164        LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1165                200, mpu.accel_fifo_rate, getTimestamp());
1166        if (write_sysfs_int(mpu.accel_fifo_rate, 200) < 0) {
1167            res = -1;
1168            LOGE("HAL:ERR can't set rate to 200Hz");
1169            return res;
1170        }
1171    }
1172    LOGV_IF(PROCESS_VERBOSE, "HAL:DMP is set %s", (dmpState ? "on" : "off"));
1173    return dmpState;
1174}
1175
1176/* called when batch and hw sensor enabled*/
1177int MPLSensor::enablePedIndicator(int en)
1178{
1179    VFUNC_LOG;
1180
1181    int res = 0;
1182    if (en) {
1183        if (!(mFeatureActiveMask & INV_DMP_PED_QUATERNION)) {
1184            //Disable DMP Pedometer Interrupt
1185            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1186                        0, mpu.pedometer_int_on, getTimestamp());
1187            if (write_sysfs_int(mpu.pedometer_int_on, 0) < 0) {
1188               LOGE("HAL:ERR can't enable Android Pedometer Interrupt");
1189               res = -1;   // indicate an err
1190               return res;
1191            }
1192
1193            LOGV_IF(ENG_VERBOSE, "HAL:Enabling ped standalone");
1194            // enable accel engine
1195            res = enableAccel(1);
1196            if (res < 0)
1197                return res;
1198            LOGV_IF(EXTRA_VERBOSE, "mLocalSensorMask=0x%lx", mLocalSensorMask);
1199            // disable accel FIFO
1200            if (!((mLocalSensorMask & mMasterSensorMask) & INV_THREE_AXIS_ACCEL)) {
1201                res = turnOffAccelFifo();
1202                if (res < 0)
1203                    return res;
1204            }
1205        }
1206    } else {
1207        //Disable Accel if no sensor needs it
1208        if (!(mFeatureActiveMask & DMP_FEATURE_MASK)
1209                               && (!(mLocalSensorMask & mMasterSensorMask
1210                                                   & INV_THREE_AXIS_ACCEL))) {
1211            res = enableAccel(0);
1212                if (res < 0)
1213                    return res;
1214            }
1215    }
1216
1217    LOGV_IF(ENG_VERBOSE, "HAL:Toggling step indicator to %d", en);
1218    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1219                en, mpu.step_indicator_on, getTimestamp());
1220    if (write_sysfs_int(mpu.step_indicator_on, en) < 0) {
1221        res = -1;
1222        LOGE("HAL:ERR can't write to DMP step_indicator_on");
1223    }
1224    return res;
1225}
1226
1227int MPLSensor::checkPedStandaloneBatched(void)
1228{
1229    VFUNC_LOG;
1230    int res = 0;
1231
1232    if ((mFeatureActiveMask & INV_DMP_PEDOMETER) &&
1233            (mBatchEnabled & (1 << StepDetector))) {
1234        res = 1;
1235    } else
1236        res = 0;
1237
1238    LOGV_IF(ENG_VERBOSE, "HAL:checkPedStandaloneBatched=%d", res);
1239    return res;
1240}
1241
1242int MPLSensor::checkPedStandaloneEnabled(void)
1243{
1244    VFUNC_LOG;
1245    return ((mFeatureActiveMask & INV_DMP_PED_STANDALONE)? 1:0);
1246}
1247
1248/* This feature is only used in batch mode */
1249/* Stand-alone Step Detector */
1250int MPLSensor::enablePedStandalone(int en)
1251{
1252    VFUNC_LOG;
1253
1254    if (!en) {
1255        enablePedStandaloneData(0);
1256        mFeatureActiveMask &= ~INV_DMP_PED_STANDALONE;
1257        if (mFeatureActiveMask == 0) {
1258            onDmp(0);
1259        } else if(mFeatureActiveMask & INV_DMP_PEDOMETER) {
1260             //Re-enable DMP Pedometer Interrupt
1261             LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1262                     1, mpu.pedometer_int_on, getTimestamp());
1263             if (write_sysfs_int(mpu.pedometer_int_on, 1) < 0) {
1264                 LOGE("HAL:ERR can't enable Android Pedometer Interrupt");
1265                 return (-1);
1266             }
1267            //Disable data interrupt if no continuous data
1268            if (mEnabled == 0) {
1269                LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1270                       1, mpu.dmp_event_int_on, getTimestamp());
1271                if (write_sysfs_int(mpu.dmp_event_int_on, 1) < 0) {
1272                    LOGE("HAL:ERR can't enable DMP event interrupt");
1273                    return (-1);
1274                }
1275            }
1276        }
1277        LOGV_IF(ENG_VERBOSE, "HAL:Ped Standalone disabled");
1278    } else {
1279        if (enablePedStandaloneData(1) < 0 || onDmp(1) < 0) {
1280            LOGE("HAL:ERR can't enable Ped Standalone");
1281        } else {
1282            mFeatureActiveMask |= INV_DMP_PED_STANDALONE;
1283            //Disable DMP Pedometer Interrupt
1284            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1285                    0, mpu.pedometer_int_on, getTimestamp());
1286            if (write_sysfs_int(mpu.pedometer_int_on, 0) < 0) {
1287                LOGE("HAL:ERR can't disable Android Pedometer Interrupt");
1288                return (-1);
1289            }
1290            //Enable Data Interrupt
1291            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1292                       0, mpu.dmp_event_int_on, getTimestamp());
1293            if (write_sysfs_int(mpu.dmp_event_int_on, 0) < 0) {
1294                LOGE("HAL:ERR can't enable DMP event interrupt");
1295                return (-1);
1296            }
1297            LOGV_IF(ENG_VERBOSE, "HAL:Ped Standalone enabled");
1298        }
1299    }
1300    return 0;
1301}
1302
1303int MPLSensor:: enablePedStandaloneData(int en)
1304{
1305    VFUNC_LOG;
1306
1307    int res = 0;
1308
1309    // Set DMP Ped standalone
1310    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1311            en, mpu.step_detector_on, getTimestamp());
1312    if (write_sysfs_int(mpu.step_detector_on, en) < 0) {
1313        LOGE("HAL:ERR can't write DMP step_detector_on");
1314        res = -1;   //Indicate an err
1315    }
1316
1317    // Set DMP Step indicator
1318    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1319            en, mpu.step_indicator_on, getTimestamp());
1320    if (write_sysfs_int(mpu.step_indicator_on, en) < 0) {
1321        LOGE("HAL:ERR can't write DMP step_indicator_on");
1322        res = -1;   //Indicate an err
1323    }
1324
1325    if (!en) {
1326      LOGV_IF(ENG_VERBOSE, "HAL:Disabling ped standalone");
1327      //Disable Accel if no sensor needs it
1328      if (!(mFeatureActiveMask & DMP_FEATURE_MASK)
1329                               && (!(mLocalSensorMask & mMasterSensorMask
1330                                                   & INV_THREE_AXIS_ACCEL))) {
1331          res = enableAccel(0);
1332          if (res < 0)
1333              return res;
1334      }
1335      if (!(mFeatureActiveMask & DMP_FEATURE_MASK)
1336                               && (!(mLocalSensorMask & mMasterSensorMask
1337                                                   & INV_THREE_AXIS_GYRO))) {
1338          res = enableGyro(0);
1339          if (res < 0)
1340              return res;
1341      }
1342    } else {
1343        LOGV_IF(ENG_VERBOSE, "HAL:Enabling ped standalone");
1344        // enable accel engine
1345        res = enableAccel(1);
1346        if (res < 0)
1347            return res;
1348        LOGV_IF(EXTRA_VERBOSE, "mLocalSensorMask=0x%lx", mLocalSensorMask);
1349        // disable accel FIFO
1350        if (!((mLocalSensorMask & mMasterSensorMask) & INV_THREE_AXIS_ACCEL)) {
1351            res = turnOffAccelFifo();
1352            if (res < 0)
1353                return res;
1354        }
1355    }
1356
1357    return res;
1358}
1359
1360int MPLSensor::checkPedQuatEnabled(void)
1361{
1362    VFUNC_LOG;
1363    return ((mFeatureActiveMask & INV_DMP_PED_QUATERNION)? 1:0);
1364}
1365
1366/* This feature is only used in batch mode */
1367/* Step Detector && Game Rotation Vector */
1368int MPLSensor::enablePedQuaternion(int en)
1369{
1370    VFUNC_LOG;
1371
1372    if (!en) {
1373        enablePedQuaternionData(0);
1374        mFeatureActiveMask &= ~INV_DMP_PED_QUATERNION;
1375        if (mFeatureActiveMask == 0) {
1376            onDmp(0);
1377        } else if(mFeatureActiveMask & INV_DMP_PEDOMETER) {
1378             //Re-enable DMP Pedometer Interrupt
1379             LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1380                     1, mpu.pedometer_int_on, getTimestamp());
1381             if (write_sysfs_int(mpu.pedometer_int_on, 1) < 0) {
1382                 LOGE("HAL:ERR can't enable Android Pedometer Interrupt");
1383                 return (-1);
1384             }
1385            //Disable data interrupt if no continuous data
1386            if (mEnabled == 0) {
1387                LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1388                       1, mpu.dmp_event_int_on, getTimestamp());
1389                if (write_sysfs_int(mpu.dmp_event_int_on, en) < 0) {
1390                    LOGE("HAL:ERR can't enable DMP event interrupt");
1391                    return (-1);
1392                }
1393            }
1394        }
1395        LOGV_IF(ENG_VERBOSE, "HAL:Ped Quat disabled");
1396    } else {
1397        if (enablePedQuaternionData(1) < 0 || onDmp(1) < 0) {
1398            LOGE("HAL:ERR can't enable Ped Quaternion");
1399        } else {
1400            mFeatureActiveMask |= INV_DMP_PED_QUATERNION;
1401            //Disable DMP Pedometer Interrupt
1402            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1403                    0, mpu.pedometer_int_on, getTimestamp());
1404            if (write_sysfs_int(mpu.pedometer_int_on, 0) < 0) {
1405                LOGE("HAL:ERR can't disable Android Pedometer Interrupt");
1406                return (-1);
1407            }
1408            //Enable Data Interrupt
1409            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1410                       0, mpu.dmp_event_int_on, getTimestamp());
1411            if (write_sysfs_int(mpu.dmp_event_int_on, 0) < 0) {
1412                LOGE("HAL:ERR can't enable DMP event interrupt");
1413                return (-1);
1414            }
1415            LOGV_IF(ENG_VERBOSE, "HAL:Ped Quat enabled");
1416        }
1417    }
1418    return 0;
1419}
1420
1421int MPLSensor::enablePedQuaternionData(int en)
1422{
1423    VFUNC_LOG;
1424
1425    int res = 0;
1426
1427    // Enable DMP quaternion
1428    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1429            en, mpu.ped_q_on, getTimestamp());
1430    if (write_sysfs_int(mpu.ped_q_on, en) < 0) {
1431        LOGE("HAL:ERR can't write DMP ped_q_on");
1432        res = -1;   //Indicate an err
1433    }
1434
1435    if (!en) {
1436        LOGV_IF(ENG_VERBOSE, "HAL:Disabling ped quat");
1437        //Disable Accel if no sensor needs it
1438        if (!(mFeatureActiveMask & DMP_FEATURE_MASK)
1439                               && (!(mLocalSensorMask & mMasterSensorMask
1440                                                   & INV_THREE_AXIS_ACCEL))) {
1441          res = enableAccel(0);
1442          if (res < 0)
1443              return res;
1444        }
1445        if (!(mFeatureActiveMask & DMP_FEATURE_MASK)
1446                               && (!(mLocalSensorMask & mMasterSensorMask
1447                                                   & INV_THREE_AXIS_GYRO))) {
1448            res = enableGyro(0);
1449            if (res < 0)
1450                return res;
1451        }
1452        if (mFeatureActiveMask & INV_DMP_QUATERNION) {
1453            res = write_sysfs_int(mpu.gyro_fifo_enable, 1);
1454            res += write_sysfs_int(mpu.accel_fifo_enable, 1);
1455            if (res < 0)
1456                return res;
1457        }
1458        // LOGV_IF(ENG_VERBOSE, "before mLocalSensorMask=0x%lx", mLocalSensorMask);
1459        // reset global mask for buildMpuEvent()
1460        if (mEnabled & (1 << GameRotationVector)) {
1461            mLocalSensorMask |= INV_THREE_AXIS_GYRO;
1462            mLocalSensorMask |= INV_THREE_AXIS_ACCEL;
1463        } else if (mEnabled & (1 << Accelerometer)) {
1464            mLocalSensorMask |= INV_THREE_AXIS_ACCEL;
1465        } else if ((mEnabled & ( 1 << Gyro)) ||
1466            (mEnabled & (1 << RawGyro))) {
1467            mLocalSensorMask |= INV_THREE_AXIS_GYRO;
1468        }
1469        //LOGV_IF(ENG_VERBOSE, "after mLocalSensorMask=0x%lx", mLocalSensorMask);
1470    } else {
1471        LOGV_IF(PROCESS_VERBOSE, "HAL:Enabling ped quat");
1472        // enable accel engine
1473        res = enableAccel(1);
1474        if (res < 0)
1475            return res;
1476
1477        // enable gyro engine
1478        res = enableGyro(1);
1479        if (res < 0)
1480            return res;
1481        LOGV_IF(EXTRA_VERBOSE, "mLocalSensorMask=0x%lx", mLocalSensorMask);
1482        // disable accel FIFO
1483        if ((!((mLocalSensorMask & mMasterSensorMask) & INV_THREE_AXIS_ACCEL)) ||
1484                !(mBatchEnabled & (1 << Accelerometer))) {
1485            res = turnOffAccelFifo();
1486            if (res < 0)
1487                return res;
1488            mLocalSensorMask &= ~INV_THREE_AXIS_ACCEL;
1489        }
1490
1491        // disable gyro FIFO
1492        if ((!((mLocalSensorMask & mMasterSensorMask) & INV_THREE_AXIS_GYRO)) ||
1493                !((mBatchEnabled & (1 << Gyro)) || (mBatchEnabled & (1 << RawGyro)))) {
1494            res = turnOffGyroFifo();
1495            if (res < 0)
1496                return res;
1497            mLocalSensorMask &= ~INV_THREE_AXIS_GYRO;
1498        }
1499    }
1500
1501    return res;
1502}
1503
1504int MPLSensor::setPedQuaternionRate(int64_t wanted)
1505{
1506    VFUNC_LOG;
1507    int res = 0;
1508
1509    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1510                int(1000000000.f / wanted), mpu.ped_q_rate,
1511                getTimestamp());
1512    res = write_sysfs_int(mpu.ped_q_rate, 1000000000.f / wanted);
1513    LOGV_IF(PROCESS_VERBOSE,
1514                "HAL:DMP ped quaternion rate %.2f Hz", 1000000000.f / wanted);
1515
1516    return res;
1517}
1518
1519int MPLSensor::check6AxisQuatEnabled(void)
1520{
1521    VFUNC_LOG;
1522    return ((mFeatureActiveMask & INV_DMP_6AXIS_QUATERNION)? 1:0);
1523}
1524
1525/* This is used for batch mode only */
1526/* GRV is batched but not along with ped */
1527int MPLSensor::enable6AxisQuaternion(int en)
1528{
1529    VFUNC_LOG;
1530
1531    if (!en) {
1532        enable6AxisQuaternionData(0);
1533        mFeatureActiveMask &= ~INV_DMP_6AXIS_QUATERNION;
1534        if (mFeatureActiveMask == 0) {
1535            onDmp(0);
1536        }
1537        LOGV_IF(ENG_VERBOSE, "HAL:6 Axis Quat disabled");
1538    } else {
1539        if (enable6AxisQuaternionData(1) < 0 || onDmp(1) < 0) {
1540            LOGE("HAL:ERR can't enable 6 Axis Quaternion");
1541        } else {
1542            mFeatureActiveMask |= INV_DMP_6AXIS_QUATERNION;
1543            LOGV_IF(PROCESS_VERBOSE, "HAL:6 Axis Quat enabled");
1544        }
1545    }
1546    return 0;
1547}
1548
1549int MPLSensor::enable6AxisQuaternionData(int en)
1550{
1551    VFUNC_LOG;
1552
1553    int res = 0;
1554
1555    // Enable DMP quaternion
1556    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1557            en, mpu.six_axis_q_on, getTimestamp());
1558    if (write_sysfs_int(mpu.six_axis_q_on, en) < 0) {
1559        LOGE("HAL:ERR can't write DMP six_axis_q_on");
1560        res = -1;   //Indicate an err
1561    }
1562
1563    if (!en) {
1564        LOGV_IF(EXTRA_VERBOSE, "HAL:DMP six axis quaternion data was turned off");
1565        inv_quaternion_sensor_was_turned_off();
1566        if (!(mFeatureActiveMask & DMP_FEATURE_MASK)
1567                                 && (!(mLocalSensorMask & mMasterSensorMask
1568                                                     & INV_THREE_AXIS_ACCEL))) {
1569            res = enableAccel(0);
1570            if (res < 0)
1571                return res;
1572        }
1573        if (!(mFeatureActiveMask & DMP_FEATURE_MASK)
1574                                 && (!(mLocalSensorMask & mMasterSensorMask
1575                                                     & INV_THREE_AXIS_GYRO))) {
1576            res = enableGyro(0);
1577            if (res < 0)
1578                return res;
1579        }
1580        if (mFeatureActiveMask & INV_DMP_QUATERNION) {
1581            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1582                    1, mpu.gyro_fifo_enable, getTimestamp());
1583            res = write_sysfs_int(mpu.gyro_fifo_enable, 1);
1584            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1585                    1, mpu.accel_fifo_enable, getTimestamp());
1586            res += write_sysfs_int(mpu.accel_fifo_enable, 1);
1587            if (res < 0)
1588                return res;
1589        }
1590        LOGV_IF(ENG_VERBOSE, "  k=0x%lx", mLocalSensorMask);
1591        // reset global mask for buildMpuEvent()
1592        if (mEnabled & (1 << GameRotationVector)) {
1593            if (!(mFeatureActiveMask & INV_DMP_PED_QUATERNION)) {
1594                mLocalSensorMask |= INV_THREE_AXIS_GYRO;
1595                mLocalSensorMask |= INV_THREE_AXIS_ACCEL;
1596                res = write_sysfs_int(mpu.gyro_fifo_enable, 1);
1597                res += write_sysfs_int(mpu.accel_fifo_enable, 1);
1598                if (res < 0)
1599                    return res;
1600            }
1601        } else if (mEnabled & (1 << Accelerometer)) {
1602            mLocalSensorMask |= INV_THREE_AXIS_ACCEL;
1603        } else if ((mEnabled & ( 1 << Gyro)) ||
1604                (mEnabled & (1 << RawGyro))) {
1605            mLocalSensorMask |= INV_THREE_AXIS_GYRO;
1606        }
1607        LOGV_IF(ENG_VERBOSE, "after mLocalSensorMask=0x%lx", mLocalSensorMask);
1608    } else {
1609        LOGV_IF(PROCESS_VERBOSE, "HAL:Enabling six axis quat");
1610        if (mEnabled & ( 1 << GameRotationVector)) {
1611            // enable accel engine
1612            res = enableAccel(1);
1613            if (res < 0)
1614                return res;
1615
1616            // enable gyro engine
1617            res = enableGyro(1);
1618            if (res < 0)
1619                return res;
1620            LOGV_IF(EXTRA_VERBOSE, "before: mLocalSensorMask=0x%lx", mLocalSensorMask);
1621            if ((!(mLocalSensorMask & mMasterSensorMask & INV_THREE_AXIS_ACCEL)) ||
1622                   (!(mBatchEnabled & (1 << Accelerometer)) ||
1623                       (!(mEnabled & (1 << Accelerometer))))) {
1624                res = turnOffAccelFifo();
1625                if (res < 0)
1626                    return res;
1627                mLocalSensorMask &= ~INV_THREE_AXIS_ACCEL;
1628            }
1629
1630            if ((!(mLocalSensorMask & mMasterSensorMask & INV_THREE_AXIS_GYRO)) ||
1631                    (!(mBatchEnabled & (1 << Gyro)) ||
1632                       (!(mEnabled & (1 << Gyro))))) {
1633                if (!(mBatchEnabled & (1 << RawGyro)) ||
1634                        (!(mEnabled & (1 << RawGyro)))) {
1635                    res = turnOffGyroFifo();
1636                    if (res < 0)
1637                        return res;
1638                     mLocalSensorMask &= ~INV_THREE_AXIS_GYRO;
1639                     }
1640            }
1641            LOGV_IF(ENG_VERBOSE, "after: mLocalSensorMask=0x%lx", mLocalSensorMask);
1642        }
1643    }
1644
1645    return res;
1646}
1647
1648int MPLSensor::set6AxisQuaternionRate(int64_t wanted)
1649{
1650    VFUNC_LOG;
1651    int res = 0;
1652
1653    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1654                int(1000000000.f / wanted), mpu.six_axis_q_rate,
1655                getTimestamp());
1656    res = write_sysfs_int(mpu.six_axis_q_rate, 1000000000.f / wanted);
1657    LOGV_IF(PROCESS_VERBOSE,
1658                "HAL:DMP six axis rate %.2f Hz", 1000000000.f / wanted);
1659
1660    return res;
1661}
1662
1663/* this is for batch  mode only */
1664int MPLSensor::checkLPQRateSupported(void)
1665{
1666    VFUNC_LOG;
1667#ifndef USE_LPQ_AT_FASTEST
1668    return ((mDelays[GameRotationVector] <= RATE_200HZ) ? 0 :1);
1669#else
1670    return 1;
1671#endif
1672}
1673
1674int MPLSensor::checkLPQuaternion(void)
1675{
1676    VFUNC_LOG;
1677    return ((mFeatureActiveMask & INV_DMP_QUATERNION)? 1:0);
1678}
1679
1680int MPLSensor::enableLPQuaternion(int en)
1681{
1682    VFUNC_LOG;
1683
1684    if (!en) {
1685        enableQuaternionData(0);
1686        mFeatureActiveMask &= ~INV_DMP_QUATERNION;
1687        if (mFeatureActiveMask == 0) {
1688            onDmp(0);
1689        }
1690        LOGV_IF(ENG_VERBOSE, "HAL:LP Quat disabled");
1691    } else {
1692        if (enableQuaternionData(1) < 0 || onDmp(1) < 0) {
1693            LOGE("HAL:ERR can't enable LP Quaternion");
1694        } else {
1695            mFeatureActiveMask |= INV_DMP_QUATERNION;
1696            LOGV_IF(ENG_VERBOSE, "HAL:LP Quat enabled");
1697        }
1698    }
1699    return 0;
1700}
1701
1702int MPLSensor::enableQuaternionData(int en)
1703{
1704    VFUNC_LOG;
1705
1706    int res = 0;
1707
1708    // Enable DMP quaternion
1709    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1710            en, mpu.three_axis_q_on, getTimestamp());
1711    if (write_sysfs_int(mpu.three_axis_q_on, en) < 0) {
1712        LOGE("HAL:ERR can't write DMP three_axis_q__on");
1713        res = -1;   //Indicates an err
1714    }
1715
1716    if (!en) {
1717        LOGV_IF(ENG_VERBOSE, "HAL:DMP quaternion data was turned off");
1718        inv_quaternion_sensor_was_turned_off();
1719    } else {
1720        LOGV_IF(ENG_VERBOSE, "HAL:Enabling three axis quat");
1721    }
1722
1723    return res;
1724}
1725
1726int MPLSensor::setQuaternionRate(int64_t wanted)
1727{
1728    VFUNC_LOG;
1729    int res = 0;
1730
1731    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1732            int(1000000000.f / wanted), mpu.three_axis_q_rate,
1733            getTimestamp());
1734    res = write_sysfs_int(mpu.three_axis_q_rate, 1000000000.f / wanted);
1735    LOGV_IF(PROCESS_VERBOSE,
1736            "HAL:DMP three axis rate %.2f Hz", 1000000000.f / wanted);
1737
1738    return res;
1739}
1740
1741int MPLSensor::enableDmpPedometer(int en, int interruptMode)
1742{
1743    VFUNC_LOG;
1744    int res = 0;
1745    int enabled_sensors = mEnabled;
1746
1747    if (isMpuNonDmp())
1748        return res;
1749
1750    // reset master enable
1751    res = masterEnable(0);
1752    if (res < 0) {
1753        return res;
1754    }
1755
1756    if (en == 1) {
1757        //Enable DMP Pedometer Function
1758        LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1759                en, mpu.pedometer_on, getTimestamp());
1760        if (write_sysfs_int(mpu.pedometer_on, en) < 0) {
1761            LOGE("HAL:ERR can't enable Android Pedometer");
1762            res = -1;   // indicate an err
1763            return res;
1764        }
1765
1766        if (interruptMode) {
1767            if(!checkPedStandaloneBatched()) {
1768                //Enable DMP Pedometer Interrupt
1769                LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1770                        en, mpu.pedometer_int_on, getTimestamp());
1771                if (write_sysfs_int(mpu.pedometer_int_on, en) < 0) {
1772                    LOGE("HAL:ERR can't enable Android Pedometer Interrupt");
1773                    res = -1;   // indicate an err
1774                    return res;
1775                }
1776            }
1777        }
1778
1779        if (interruptMode) {
1780            mFeatureActiveMask |= INV_DMP_PEDOMETER;
1781        }
1782        else {
1783            mFeatureActiveMask |= INV_DMP_PEDOMETER_STEP;
1784            mStepCountPollTime = 100000000LL;
1785        }
1786
1787        clock_gettime(CLOCK_MONOTONIC, &mt_pre);
1788    } else {
1789        if (interruptMode) {
1790            mFeatureActiveMask &= ~INV_DMP_PEDOMETER;
1791        }
1792        else {
1793            mFeatureActiveMask &= ~INV_DMP_PEDOMETER_STEP;
1794            mStepCountPollTime = -1;
1795        }
1796
1797        /* if neither step detector or step count is on */
1798        if (!(mFeatureActiveMask & (INV_DMP_PEDOMETER | INV_DMP_PEDOMETER_STEP))) {
1799            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1800                    en, mpu.pedometer_on, getTimestamp());
1801            if (write_sysfs_int(mpu.pedometer_on, en) < 0) {
1802                LOGE("HAL:ERR can't enable Android Pedometer");
1803                res = -1;
1804                return res;
1805            }
1806        }
1807
1808        /* if feature is not step detector */
1809        if (!(mFeatureActiveMask & INV_DMP_PEDOMETER)) {
1810            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1811                    en, mpu.pedometer_int_on, getTimestamp());
1812            if (write_sysfs_int(mpu.pedometer_int_on, en) < 0) {
1813                LOGE("HAL:ERR can't enable Android Pedometer Interrupt");
1814                res = -1;
1815                return res;
1816            }
1817        }
1818    }
1819
1820    if ((res = setDmpFeature(en)) < 0)
1821        return res;
1822
1823    if ((res = computeAndSetDmpState()) < 0)
1824        return res;
1825
1826    if (!mBatchEnabled && (resetDataRates() < 0))
1827        return res;
1828
1829    if(en || enabled_sensors || mFeatureActiveMask) {
1830        res = masterEnable(1);
1831    }
1832    return res;
1833}
1834
1835int MPLSensor::masterEnable(int en)
1836{
1837    VFUNC_LOG;
1838
1839    int res = 0;
1840    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1841            en, mpu.master_enable, getTimestamp());
1842    res = write_sysfs_int(mpu.master_enable, en);
1843    return res;
1844}
1845
1846int MPLSensor::enableGyro(int en)
1847{
1848    VFUNC_LOG;
1849
1850    int res = 0;
1851
1852    /* need to also turn on/off the master enable */
1853    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1854            en, mpu.gyro_enable, getTimestamp());
1855    res = write_sysfs_int(mpu.gyro_enable, en);
1856    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1857            en, mpu.gyro_fifo_enable, getTimestamp());
1858    res += write_sysfs_int(mpu.gyro_fifo_enable, en);
1859
1860    if (!en) {
1861        LOGV_IF(EXTRA_VERBOSE, "HAL:MPL:inv_gyro_was_turned_off");
1862        inv_gyro_was_turned_off();
1863    }
1864
1865    return res;
1866}
1867
1868int MPLSensor::enableLowPowerAccel(int en)
1869{
1870    VFUNC_LOG;
1871
1872    int res;
1873
1874    /* need to also turn on/off the master enable */
1875    res = write_sysfs_int(mpu.motion_lpa_on, en);
1876    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1877                        en, mpu.motion_lpa_on, getTimestamp());
1878    return res;
1879}
1880
1881int MPLSensor::enableAccel(int en)
1882{
1883    VFUNC_LOG;
1884
1885    int res;
1886
1887    /* need to also turn on/off the master enable */
1888    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1889            en, mpu.accel_enable, getTimestamp());
1890    res = write_sysfs_int(mpu.accel_enable, en);
1891    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
1892            en, mpu.accel_fifo_enable, getTimestamp());
1893    res += write_sysfs_int(mpu.accel_fifo_enable, en);
1894
1895    if (!en) {
1896        LOGV_IF(EXTRA_VERBOSE, "HAL:MPL:inv_accel_was_turned_off");
1897        inv_accel_was_turned_off();
1898    }
1899
1900    return res;
1901}
1902
1903int MPLSensor::enableCompass(int en, int rawSensorRequested)
1904{
1905    VFUNC_LOG;
1906
1907    int res = 0;
1908    /* TODO: handle ID_RM if third party compass cal is used */
1909    if (rawSensorRequested && mCompassSensor->providesCalibration()) {
1910        res = mCompassSensor->enable(ID_RM, en);
1911    } else {
1912        res = mCompassSensor->enable(ID_M, en);
1913    }
1914    if (en == 0 || res != 0) {
1915        LOGV_IF(EXTRA_VERBOSE, "HAL:MPL:inv_compass_was_turned_off %d", res);
1916        inv_compass_was_turned_off();
1917    }
1918
1919    return res;
1920}
1921
1922#ifdef ENABLE_PRESSURE
1923int MPLSensor::enablePressure(int en)
1924{
1925    VFUNC_LOG;
1926
1927    int res = 0;
1928
1929    if (mPressureSensor)
1930        res = mPressureSensor->enable(ID_PS, en);
1931
1932    return res;
1933}
1934#endif
1935
1936/* use this function for initialization */
1937int MPLSensor::enableBatch(int64_t timeout)
1938{
1939    VFUNC_LOG;
1940
1941    int res = 0;
1942
1943    res = write_sysfs_int(mpu.batchmode_timeout, timeout);
1944    if (timeout == 0) {
1945        res = write_sysfs_int(mpu.six_axis_q_on, 0);
1946        res = write_sysfs_int(mpu.ped_q_on, 0);
1947        res = write_sysfs_int(mpu.step_detector_on, 0);
1948        res = write_sysfs_int(mpu.step_indicator_on, 0);
1949    }
1950
1951    if (timeout == 0) {
1952        LOGV_IF(EXTRA_VERBOSE, "HAL:MPL:batchmode timeout is zero");
1953    }
1954
1955    return res;
1956}
1957
1958void MPLSensor::computeLocalSensorMask(int enabled_sensors)
1959{
1960    VFUNC_LOG;
1961
1962    do {
1963#ifdef ENABLE_PRESSURE
1964        /* Invensense Pressure on secondary bus */
1965        if (PS_ENABLED) {
1966            LOGV_IF(ENG_VERBOSE, "PS ENABLED");
1967            mLocalSensorMask |= INV_ONE_AXIS_PRESSURE;
1968        } else {
1969            LOGV_IF(ENG_VERBOSE, "PS DISABLED");
1970            mLocalSensorMask &= ~INV_ONE_AXIS_PRESSURE;
1971        }
1972#else
1973        LOGV_IF(ENG_VERBOSE, "PS DISABLED");
1974        mLocalSensorMask &= ~INV_ONE_AXIS_PRESSURE;
1975#endif
1976
1977        if (LA_ENABLED || GR_ENABLED || RV_ENABLED || O_ENABLED
1978                       || (GRV_ENABLED && GMRV_ENABLED)) {
1979            LOGV_IF(ENG_VERBOSE, "FUSION ENABLED");
1980            mLocalSensorMask |= ALL_MPL_SENSORS_NP;
1981            break;
1982        }
1983
1984        if (GRV_ENABLED) {
1985            if (!(mFeatureActiveMask & INV_DMP_BATCH_MODE) ||
1986                !(mBatchEnabled & (1 << GameRotationVector))) {
1987                LOGV_IF(ENG_VERBOSE, "6 Axis Fusion ENABLED");
1988                mLocalSensorMask |= INV_THREE_AXIS_GYRO;
1989                mLocalSensorMask |= INV_THREE_AXIS_ACCEL;
1990            } else {
1991                if (GY_ENABLED || RGY_ENABLED) {
1992                    LOGV_IF(ENG_VERBOSE, "G ENABLED");
1993                    mLocalSensorMask |= INV_THREE_AXIS_GYRO;
1994                } else {
1995                    LOGV_IF(ENG_VERBOSE, "G DISABLED");
1996                    mLocalSensorMask &= ~INV_THREE_AXIS_GYRO;
1997                }
1998                if (A_ENABLED) {
1999                    LOGV_IF(ENG_VERBOSE, "A ENABLED");
2000                    mLocalSensorMask |= INV_THREE_AXIS_ACCEL;
2001                } else {
2002                    LOGV_IF(ENG_VERBOSE, "A DISABLED");
2003                    mLocalSensorMask &= ~INV_THREE_AXIS_ACCEL;
2004                }
2005            }
2006            /* takes care of MAG case */
2007            if (M_ENABLED || RM_ENABLED) {
2008                LOGV_IF(1, "M ENABLED");
2009                mLocalSensorMask |= INV_THREE_AXIS_COMPASS;
2010            } else {
2011                LOGV_IF(1, "M DISABLED");
2012                mLocalSensorMask &= ~INV_THREE_AXIS_COMPASS;
2013            }
2014            break;
2015        }
2016
2017        if (GMRV_ENABLED) {
2018            LOGV_IF(ENG_VERBOSE, "6 Axis Geomagnetic Fusion ENABLED");
2019            mLocalSensorMask |= INV_THREE_AXIS_ACCEL;
2020            mLocalSensorMask |= INV_THREE_AXIS_COMPASS;
2021
2022            /* takes care of Gyro case */
2023            if (GY_ENABLED || RGY_ENABLED) {
2024                LOGV_IF(1, "G ENABLED");
2025                mLocalSensorMask |= INV_THREE_AXIS_GYRO;
2026            } else {
2027                LOGV_IF(1, "G DISABLED");
2028                mLocalSensorMask &= ~INV_THREE_AXIS_GYRO;
2029            }
2030            break;
2031        }
2032
2033#ifdef ENABLE_PRESSURE
2034        if(!A_ENABLED && !M_ENABLED && !RM_ENABLED &&
2035               !GRV_ENABLED && !GMRV_ENABLED && !GY_ENABLED && !RGY_ENABLED &&
2036               !PS_ENABLED) {
2037#else
2038        if(!A_ENABLED && !M_ENABLED && !RM_ENABLED &&
2039               !GRV_ENABLED && !GMRV_ENABLED && !GY_ENABLED && !RGY_ENABLED) {
2040#endif
2041            /* Invensense compass cal */
2042            LOGV_IF(ENG_VERBOSE, "ALL DISABLED");
2043            mLocalSensorMask = 0;
2044            break;
2045        }
2046
2047        if (GY_ENABLED || RGY_ENABLED) {
2048            LOGV_IF(ENG_VERBOSE, "G ENABLED");
2049            mLocalSensorMask |= INV_THREE_AXIS_GYRO;
2050        } else {
2051            LOGV_IF(ENG_VERBOSE, "G DISABLED");
2052            mLocalSensorMask &= ~INV_THREE_AXIS_GYRO;
2053        }
2054
2055        if (A_ENABLED) {
2056            LOGV_IF(ENG_VERBOSE, "A ENABLED");
2057            mLocalSensorMask |= INV_THREE_AXIS_ACCEL;
2058        } else {
2059            LOGV_IF(ENG_VERBOSE, "A DISABLED");
2060            mLocalSensorMask &= ~INV_THREE_AXIS_ACCEL;
2061        }
2062
2063        /* Invensense compass calibration */
2064        if (M_ENABLED || RM_ENABLED) {
2065            LOGV_IF(ENG_VERBOSE, "M ENABLED");
2066            mLocalSensorMask |= INV_THREE_AXIS_COMPASS;
2067        } else {
2068            LOGV_IF(ENG_VERBOSE, "M DISABLED");
2069            mLocalSensorMask &= ~INV_THREE_AXIS_COMPASS;
2070        }
2071    } while (0);
2072}
2073
2074int MPLSensor::enableSensors(unsigned long sensors, int en, uint32_t changed)
2075{
2076    VFUNC_LOG;
2077
2078    inv_error_t res = -1;
2079    int on = 1;
2080    int off = 0;
2081    int cal_stored = 0;
2082
2083    // Sequence to enable or disable a sensor
2084    // 1. reset master enable (=0)
2085    // 2. enable or disable a sensor
2086    // 3. set master enable (=1)
2087
2088    if (isLowPowerQuatEnabled() ||
2089        changed & ((1 << Gyro) | (1 << RawGyro) | (1 << Accelerometer) |
2090        (mCompassSensor->isIntegrated() << MagneticField) |
2091#ifdef ENABLE_PRESSURE
2092        (mPressureSensor->isIntegrated() << Pressure) |
2093#endif
2094        (mCompassSensor->isIntegrated() << RawMagneticField))) {
2095
2096        /* reset master enable */
2097        res = masterEnable(0);
2098        if(res < 0) {
2099            return res;
2100        }
2101    }
2102
2103    LOGV_IF(ENG_VERBOSE, "HAL:enableSensors - sensors: 0x%0x",
2104            (unsigned int)sensors);
2105
2106    if (changed & ((1 << Gyro) | (1 << RawGyro))) {
2107        LOGV_IF(ENG_VERBOSE, "HAL:enableSensors - gyro %s",
2108                (sensors & INV_THREE_AXIS_GYRO? "enable": "disable"));
2109        res = enableGyro(!!(sensors & INV_THREE_AXIS_GYRO));
2110        if(res < 0) {
2111            return res;
2112        }
2113
2114        if (!cal_stored && (!en && (changed & (1 << Gyro)))) {
2115            storeCalibration();
2116            cal_stored = 1;
2117        }
2118    }
2119
2120    if (changed & (1 << Accelerometer)) {
2121        LOGV_IF(ENG_VERBOSE, "HAL:enableSensors - accel %s",
2122                (sensors & INV_THREE_AXIS_ACCEL? "enable": "disable"));
2123        res = enableAccel(!!(sensors & INV_THREE_AXIS_ACCEL));
2124        if(res < 0) {
2125            return res;
2126        }
2127
2128        if (!(sensors & INV_THREE_AXIS_ACCEL) && !cal_stored) {
2129            storeCalibration();
2130            cal_stored = 1;
2131        }
2132    }
2133
2134    if (changed & ((1 << MagneticField) | (1 << RawMagneticField))) {
2135        LOGV_IF(ENG_VERBOSE, "HAL:enableSensors - compass %s",
2136                (sensors & INV_THREE_AXIS_COMPASS? "enable": "disable"));
2137        res = enableCompass(!!(sensors & INV_THREE_AXIS_COMPASS), changed & (1 << RawMagneticField));
2138        if(res < 0) {
2139            return res;
2140        }
2141
2142        if (!cal_stored && (!en && (changed & (1 << MagneticField)))) {
2143            storeCalibration();
2144            cal_stored = 1;
2145        }
2146    }
2147
2148#ifdef ENABLE_PRESSURE
2149     if (changed & (1 << Pressure)) {
2150        LOGV_IF(ENG_VERBOSE, "HAL:enableSensors - pressure %s",
2151                (sensors & INV_ONE_AXIS_PRESSURE? "enable": "disable"));
2152        res = enablePressure(!!(sensors & INV_ONE_AXIS_PRESSURE));
2153        if(res < 0) {
2154            return res;
2155        }
2156    }
2157#endif
2158
2159    if (isLowPowerQuatEnabled()) {
2160        // Enable LP Quat
2161        if ((mEnabled & VIRTUAL_SENSOR_9AXES_MASK)
2162                      || (mEnabled & VIRTUAL_SENSOR_GYRO_6AXES_MASK)) {
2163            LOGV_IF(ENG_VERBOSE, "HAL: 9 axis or game rot enabled");
2164            if (!(changed & ((1 << Gyro)
2165                           | (1 << RawGyro)
2166                           | (1 << Accelerometer)
2167                           | (mCompassSensor->isIntegrated() << MagneticField)
2168                           | (mCompassSensor->isIntegrated() << RawMagneticField)))
2169            ) {
2170                /* reset master enable */
2171                res = masterEnable(0);
2172                if(res < 0) {
2173                    return res;
2174                }
2175            }
2176            if (!checkLPQuaternion()) {
2177                enableLPQuaternion(1);
2178            } else {
2179                LOGV_IF(ENG_VERBOSE, "HAL:LP Quat already enabled");
2180            }
2181        } else if (checkLPQuaternion()) {
2182            enableLPQuaternion(0);
2183        }
2184    }
2185
2186    /* apply accel/gyro bias to DMP bias                        */
2187    /* precondition: masterEnable(0), mGyroBiasAvailable=true   */
2188    /* postcondition: bias is applied upon masterEnable(1)      */
2189    if(!(sensors & INV_THREE_AXIS_GYRO)) {
2190        setGyroBias();
2191    }
2192    if(!(sensors & INV_THREE_AXIS_ACCEL)) {
2193        setAccelBias();
2194    }
2195
2196    /* to batch or not to batch */
2197    int batchMode = computeBatchSensorMask(mEnabled, mBatchEnabled);
2198    /* skip setBatch if there is no need to */
2199    if(((int)mOldBatchEnabledMask != batchMode) || batchMode) {
2200        setBatch(batchMode,0);
2201    }
2202    mOldBatchEnabledMask = batchMode;
2203
2204    /* check for invn hardware sensors change */
2205    if (changed & ((1 << Gyro) | (1 << RawGyro) | (1 << Accelerometer) |
2206            (mCompassSensor->isIntegrated() << MagneticField) |
2207#ifdef ENABLE_PRESSURE
2208            (mPressureSensor->isIntegrated() << Pressure) |
2209#endif
2210            (mCompassSensor->isIntegrated() << RawMagneticField))) {
2211        LOGV_IF(ENG_VERBOSE,
2212                "HAL DEBUG: Gyro, Accel, Compass, Pressure changes");
2213        if ((checkSmdSupport() == 1) || (checkPedometerSupport() == 1) || (sensors &
2214            (INV_THREE_AXIS_GYRO
2215                | INV_THREE_AXIS_ACCEL
2216#ifdef ENABLE_PRESSURE
2217                | (INV_ONE_AXIS_PRESSURE * mPressureSensor->isIntegrated())
2218#endif
2219                | (INV_THREE_AXIS_COMPASS * mCompassSensor->isIntegrated())))) {
2220            LOGV_IF(ENG_VERBOSE, "SMD or Hardware sensors enabled");
2221            LOGV_IF(ENG_VERBOSE,
2222                    "mFeatureActiveMask=0x%llx", mFeatureActiveMask);
2223                LOGV_IF(ENG_VERBOSE, "HAL DEBUG: LPQ, SMD, SO enabled");
2224                // disable DMP event interrupt only (w/ data interrupt)
2225                LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
2226                        0, mpu.dmp_event_int_on, getTimestamp());
2227                if (write_sysfs_int(mpu.dmp_event_int_on, 0) < 0) {
2228                    res = -1;
2229                    LOGE("HAL:ERR can't disable DMP event interrupt");
2230                    return res;
2231                }
2232            LOGV_IF(ENG_VERBOSE, "mFeatureActiveMask=0x%llx", mFeatureActiveMask);
2233            LOGV_IF(ENG_VERBOSE, "DMP_FEATURE_MASK=0x%x", DMP_FEATURE_MASK);
2234        if ((mFeatureActiveMask & (long long)DMP_FEATURE_MASK) &&
2235                    !((mFeatureActiveMask & INV_DMP_6AXIS_QUATERNION) ||
2236                     (mFeatureActiveMask & INV_DMP_PED_STANDALONE) ||
2237                     (mFeatureActiveMask & INV_DMP_PED_QUATERNION) ||
2238                     (mFeatureActiveMask & INV_DMP_BATCH_MODE))) {
2239                // enable DMP
2240                onDmp(1);
2241                res = enableAccel(on);
2242                if(res < 0) {
2243                    return res;
2244                }
2245                LOGV_IF(ENG_VERBOSE, "mLocalSensorMask=0x%lx", mLocalSensorMask);
2246                if (((sensors | mLocalSensorMask) & INV_THREE_AXIS_ACCEL) == 0) {
2247                    res = turnOffAccelFifo();
2248                }
2249                if(res < 0) {
2250                    return res;
2251                }
2252            }
2253        } else { // all sensors idle
2254            LOGV_IF(ENG_VERBOSE, "HAL DEBUG: not SMD or Hardware sensors");
2255            if (isDmpDisplayOrientationOn()
2256                    && (mDmpOrientationEnabled
2257                            || !isDmpScreenAutoRotationEnabled())) {
2258                enableDmpOrientation(1);
2259            }
2260
2261            if (!cal_stored) {
2262                storeCalibration();
2263                cal_stored = 1;
2264            }
2265        }
2266    } else if ((changed &
2267                    ((!mCompassSensor->isIntegrated()) << MagneticField) ||
2268                    ((!mCompassSensor->isIntegrated()) << RawMagneticField))
2269                    &&
2270              !(sensors & (INV_THREE_AXIS_GYRO | INV_THREE_AXIS_ACCEL
2271                | (INV_THREE_AXIS_COMPASS * (!mCompassSensor->isIntegrated()))))
2272    ) {
2273        LOGV_IF(ENG_VERBOSE, "HAL DEBUG: Gyro, Accel, Compass no change");
2274        if (!cal_stored) {
2275            storeCalibration();
2276            cal_stored = 1;
2277        }
2278    } /*else {
2279      LOGV_IF(ENG_VERBOSE, "HAL DEBUG: mEnabled");
2280      if (sensors &
2281            (INV_THREE_AXIS_GYRO
2282                | INV_THREE_AXIS_ACCEL
2283                | (INV_THREE_AXIS_COMPASS * mCompassSensor->isIntegrated()))) {
2284            res = masterEnable(1);
2285            if(res < 0)
2286                return res;
2287        }
2288    }*/
2289
2290    if (!batchMode && (resetDataRates() < 0)) {
2291        LOGE("HAL:ERR can't reset output rate back to original setting");
2292    }
2293
2294    if(mFeatureActiveMask || sensors) {
2295        res = masterEnable(1);
2296        if(res < 0)
2297            return res;
2298    }
2299    return res;
2300}
2301
2302/* check if batch mode should be turned on or not */
2303int MPLSensor::computeBatchSensorMask(int enableSensors, int tempBatchSensor)
2304{
2305    VFUNC_LOG;
2306    int batchMode = 1;
2307    mFeatureActiveMask &= ~INV_DMP_BATCH_MODE;
2308
2309    LOGV_IF(ENG_VERBOSE,
2310            "HAL:computeBatchSensorMask: enableSensors=%d tempBatchSensor=%d",
2311            enableSensors, tempBatchSensor);
2312
2313    // handle initialization case
2314    if (enableSensors == 0 && tempBatchSensor == 0)
2315        return 0;
2316
2317    // check for possible continuous data mode
2318    for(int i = 0; i <= LAST_HW_SENSOR; i++) {
2319        // if any one of the hardware sensor is in continuous data mode
2320        // turn off batch mode.
2321        if ((enableSensors & (1 << i)) && !(tempBatchSensor & (1 << i))) {
2322            LOGV_IF(ENG_VERBOSE, "HAL:computeBatchSensorMask: "
2323                    "hardware sensor on continuous mode:%d", i);
2324            return 0;
2325        }
2326        if ((enableSensors & (1 << i)) && (tempBatchSensor & (1 << i))) {
2327            LOGV_IF(ENG_VERBOSE,
2328                    "HAL:computeBatchSensorMask: hardware sensor is batch:%d",
2329                    i);
2330            // if hardware sensor is batched, check if virtual sensor is also batched
2331            if ((enableSensors & (1 << GameRotationVector))
2332                            && !(tempBatchSensor & (1 << GameRotationVector))) {
2333            LOGV_IF(ENG_VERBOSE,
2334                    "HAL:computeBatchSensorMask: but virtual sensor is not:%d",
2335                    i);
2336                return 0;
2337            }
2338        }
2339    }
2340
2341    // if virtual sensors are on but not batched, turn off batch mode.
2342    for(int i = Orientation; i <= GeomagneticRotationVector; i++) {
2343        if ((enableSensors & (1 << i)) && !(tempBatchSensor & (1 << i))) {
2344             LOGV_IF(ENG_VERBOSE, "HAL:computeBatchSensorMask: "
2345                     "composite sensor on continuous mode:%d", i);
2346            return 0;
2347        }
2348    }
2349
2350    if ((mFeatureActiveMask & INV_DMP_PEDOMETER) && !(tempBatchSensor & (1 << StepDetector))) {
2351        LOGV("HAL:computeBatchSensorMask: step detector on continuous mode.");
2352        return 0;
2353    }
2354
2355    mFeatureActiveMask |= INV_DMP_BATCH_MODE;
2356    LOGV_IF(EXTRA_VERBOSE,
2357            "HAL:computeBatchSensorMask: batchMode=%d, mBatchEnabled=%0x",
2358            batchMode, tempBatchSensor);
2359    return (batchMode && tempBatchSensor);
2360}
2361
2362/* This function is called by enable() */
2363int MPLSensor::setBatch(int en, int toggleEnable)
2364{
2365    VFUNC_LOG;
2366
2367    int res = 0;
2368    int64_t wanted = 1000000000LL;
2369    int64_t timeout = 0;
2370    int timeoutInMs = 0;
2371    int featureMask = computeBatchDataOutput();
2372
2373    // reset master enable
2374    if (toggleEnable == 1) {
2375        res = masterEnable(0);
2376        if (res < 0) {
2377            return res;
2378        }
2379    }
2380
2381    /* step detector is enabled and */
2382    /* batch mode is standalone */
2383    if (en && (mFeatureActiveMask & INV_DMP_PEDOMETER) &&
2384            (featureMask & INV_DMP_PED_STANDALONE)) {
2385        LOGV_IF(ENG_VERBOSE, "setBatch: ID_P only = 0x%x", mBatchEnabled);
2386        enablePedStandalone(1);
2387    } else {
2388        enablePedStandalone(0);
2389    }
2390
2391    /* step detector and GRV are enabled and */
2392    /* batch mode is ped q */
2393    if (en && (mFeatureActiveMask & INV_DMP_PEDOMETER) &&
2394            (mEnabled & (1 << GameRotationVector)) &&
2395            (featureMask & INV_DMP_PED_QUATERNION)) {
2396        LOGV_IF(ENG_VERBOSE, "setBatch: ID_P and GRV or ALL = 0x%x", mBatchEnabled);
2397        LOGV_IF(ENG_VERBOSE, "setBatch: ID_P is enabled for batching, "
2398                "PED quat will be automatically enabled");
2399        enableLPQuaternion(0);
2400        enablePedQuaternion(1);
2401    } else if (!(featureMask & INV_DMP_PED_STANDALONE)){
2402        enablePedQuaternion(0);
2403    } else {
2404        enablePedQuaternion(0);
2405    }
2406
2407    /* step detector and hardware sensors enabled */
2408    if (en && (featureMask & INV_DMP_PED_INDICATOR) &&
2409            ((mEnabled) ||
2410            (mFeatureActiveMask & INV_DMP_PED_STANDALONE))) {
2411        enablePedIndicator(1);
2412    } else {
2413        enablePedIndicator(0);
2414    }
2415
2416    /* GRV is enabled and */
2417    /* batch mode is 6axis q */
2418    if (en && (mEnabled & (1 << GameRotationVector)) &&
2419            (featureMask & INV_DMP_6AXIS_QUATERNION)) {
2420        LOGV_IF(ENG_VERBOSE, "setBatch: GRV = 0x%x", mBatchEnabled);
2421        enableLPQuaternion(0);
2422        enable6AxisQuaternion(1);
2423        setInitial6QuatValue();
2424    } else if (!(featureMask & INV_DMP_PED_QUATERNION)){
2425        LOGV_IF(ENG_VERBOSE, "setBatch: Toggle back to normal 6 axis");
2426        if (mEnabled & (1 << GameRotationVector)) {
2427            enableLPQuaternion(checkLPQRateSupported());
2428        }
2429        enable6AxisQuaternion(0);
2430    } else {
2431        enable6AxisQuaternion(0);
2432    }
2433
2434    writeBatchTimeout(en);
2435
2436    if (en) {
2437        // enable DMP
2438        res = onDmp(1);
2439        if (res < 0) {
2440            return res;
2441        }
2442
2443        // set batch rates
2444        if (setBatchDataRates() < 0) {
2445            LOGE("HAL:ERR can't set batch data rates");
2446        }
2447
2448        // default fifo rate to 200Hz
2449        LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
2450                200, mpu.gyro_fifo_rate, getTimestamp());
2451        if (write_sysfs_int(mpu.gyro_fifo_rate, 200) < 0) {
2452            res = -1;
2453            LOGE("HAL:ERR can't set rate to 200Hz");
2454            return res;
2455        }
2456    } else {
2457        if (mFeatureActiveMask == 0) {
2458            // disable DMP
2459            res = onDmp(0);
2460            if (res < 0) {
2461                return res;
2462            }
2463            /* reset sensor rate */
2464            if (resetDataRates() < 0) {
2465                LOGE("HAL:ERR can't reset output rate back to original setting");
2466            }
2467        }
2468    }
2469
2470    // set sensor data interrupt
2471    uint32_t dataInterrupt = (mEnabled || (mFeatureActiveMask & INV_DMP_BATCH_MODE));
2472    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
2473                !dataInterrupt, mpu.dmp_event_int_on, getTimestamp());
2474    if (write_sysfs_int(mpu.dmp_event_int_on, !dataInterrupt) < 0) {
2475        res = -1;
2476        LOGE("HAL:ERR can't enable DMP event interrupt");
2477    }
2478
2479    if (toggleEnable == 1) {
2480        if (mFeatureActiveMask || mEnabled)
2481            masterEnable(1);
2482    }
2483    return res;
2484}
2485
2486int MPLSensor::writeBatchTimeout(int en)
2487{
2488    VFUNC_LOG;
2489
2490    int64_t timeoutInMs = 0;
2491    if (en) {
2492        /* take the minimum batchmode timeout */
2493        int64_t timeout = 100000000000LL;
2494        int64_t ns = 0;
2495        for (int i = 0; i < NumSensors; i++) {
2496            LOGV_IF(1, "mFeatureActiveMask=0x%016llx, mEnabled=0x%01x, mBatchEnabled=0x%x",
2497                            mFeatureActiveMask, mEnabled, mBatchEnabled);
2498            if (((mEnabled & (1 << i)) && (mBatchEnabled & (1 << i))) ||
2499                    (checkPedStandaloneBatched() && (i == StepDetector))) {
2500                LOGV_IF(ENG_VERBOSE, "sensor=%d, timeout=%lld", i, mBatchTimeouts[i]);
2501                ns = mBatchTimeouts[i];
2502                timeout = (ns < timeout) ? ns : timeout;
2503            }
2504        }
2505        /* Convert ns to millisecond */
2506        timeoutInMs = timeout / 1000000;
2507    } else {
2508        timeoutInMs = 0;
2509    }
2510
2511    LOGV_IF(PROCESS_VERBOSE,
2512                    "HAL: batch timeout set to %lld ms", timeoutInMs);
2513
2514    if(mBatchTimeoutInMs != timeoutInMs) {
2515        /* write required timeout to sysfs */
2516        LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %lld > %s (%lld)",
2517                timeoutInMs, mpu.batchmode_timeout, getTimestamp());
2518        if (write_sysfs_int(mpu.batchmode_timeout, timeoutInMs) < 0) {
2519            LOGE("HAL:ERR can't write batchmode_timeout");
2520        }
2521    }
2522    /* remember last timeout value */
2523    mBatchTimeoutInMs = timeoutInMs;
2524
2525    return 0;
2526}
2527
2528/* Store calibration file */
2529void MPLSensor::storeCalibration(void)
2530{
2531    VFUNC_LOG;
2532
2533    if(mHaveGoodMpuCal == true
2534        || mAccelAccuracy >= 2
2535        || mCompassAccuracy >= 3) {
2536       int res = inv_store_calibration();
2537       if (res) {
2538           LOGE("HAL:Cannot store calibration on file");
2539       } else {
2540           LOGV_IF(PROCESS_VERBOSE, "HAL:Cal file updated");
2541       }
2542    }
2543}
2544
2545/*  these handlers transform mpl data into one of the Android sensor types */
2546int MPLSensor::gyroHandler(sensors_event_t* s)
2547{
2548    VHANDLER_LOG;
2549    int update;
2550    update = inv_get_sensor_type_gyroscope(s->gyro.v, &s->gyro.status,
2551                                           &s->timestamp);
2552    LOGV_IF(HANDLER_DATA, "HAL:gyro data : %+f %+f %+f -- %lld - %d",
2553            s->gyro.v[0], s->gyro.v[1], s->gyro.v[2], s->timestamp, update);
2554    return update;
2555}
2556
2557int MPLSensor::rawGyroHandler(sensors_event_t* s)
2558{
2559    VHANDLER_LOG;
2560    int update;
2561    update = inv_get_sensor_type_gyroscope_raw(s->uncalibrated_gyro.uncalib,
2562                                               &s->gyro.status, &s->timestamp);
2563    if(update) {
2564        memcpy(s->uncalibrated_gyro.bias, mGyroBias, sizeof(mGyroBias));
2565        LOGV_IF(HANDLER_DATA,"HAL:gyro bias data : %+f %+f %+f -- %lld - %d",
2566            s->uncalibrated_gyro.bias[0], s->uncalibrated_gyro.bias[1],
2567            s->uncalibrated_gyro.bias[2], s->timestamp, update);
2568    }
2569    s->gyro.status = SENSOR_STATUS_UNRELIABLE;
2570    LOGV_IF(HANDLER_DATA, "HAL:raw gyro data : %+f %+f %+f -- %lld - %d",
2571            s->uncalibrated_gyro.uncalib[0], s->uncalibrated_gyro.uncalib[1],
2572            s->uncalibrated_gyro.uncalib[2], s->timestamp, update);
2573    return update;
2574}
2575
2576int MPLSensor::accelHandler(sensors_event_t* s)
2577{
2578    VHANDLER_LOG;
2579    int update;
2580    update = inv_get_sensor_type_accelerometer(
2581        s->acceleration.v, &s->acceleration.status, &s->timestamp);
2582    LOGV_IF(HANDLER_DATA, "HAL:accel data : %+f %+f %+f -- %lld - %d",
2583            s->acceleration.v[0], s->acceleration.v[1], s->acceleration.v[2],
2584            s->timestamp, update);
2585    mAccelAccuracy = s->acceleration.status;
2586    return update;
2587}
2588
2589int MPLSensor::compassHandler(sensors_event_t* s)
2590{
2591    VHANDLER_LOG;
2592    int update;
2593    update = inv_get_sensor_type_magnetic_field(
2594        s->magnetic.v, &s->magnetic.status, &s->timestamp);
2595    LOGV_IF(HANDLER_DATA, "HAL:compass data: %+f %+f %+f -- %lld - %d",
2596            s->magnetic.v[0], s->magnetic.v[1], s->magnetic.v[2],
2597            s->timestamp, update);
2598    mCompassAccuracy = s->magnetic.status;
2599    return update | mCompassOverFlow;
2600}
2601
2602int MPLSensor::rawCompassHandler(sensors_event_t* s)
2603{
2604    VHANDLER_LOG;
2605    int update;
2606    //TODO: need to handle uncalib data and bias for 3rd party compass
2607    if(mCompassSensor->providesCalibration()) {
2608        update = mCompassSensor->readRawSample(s->uncalibrated_magnetic.uncalib, &s->timestamp);
2609    }
2610    else {
2611        update = inv_get_sensor_type_magnetic_field_raw(s->uncalibrated_magnetic.uncalib,
2612                     &s->magnetic.status, &s->timestamp);
2613    }
2614    if(update) {
2615        memcpy(s->uncalibrated_magnetic.bias, mCompassBias, sizeof(mCompassBias));
2616        LOGV_IF(HANDLER_DATA, "HAL:compass bias data: %+f %+f %+f -- %lld - %d",
2617                s->uncalibrated_magnetic.bias[0], s->uncalibrated_magnetic.bias[1],
2618                s->uncalibrated_magnetic.bias[2], s->timestamp, update);
2619    }
2620    s->magnetic.status = SENSOR_STATUS_UNRELIABLE;
2621    LOGV_IF(HANDLER_DATA, "HAL:compass raw data: %+f %+f %+f %d -- %lld - %d",
2622        s->uncalibrated_magnetic.uncalib[0], s->uncalibrated_magnetic.uncalib[1],
2623                    s->uncalibrated_magnetic.uncalib[2], s->magnetic.status, s->timestamp, update);
2624    return update | mCompassOverFlow;
2625}
2626
2627/*
2628    Rotation Vector handler.
2629    NOTE: rotation vector does not have an accuracy or status
2630*/
2631int MPLSensor::rvHandler(sensors_event_t* s)
2632{
2633    VHANDLER_LOG;
2634    int8_t status;
2635    int update;
2636    update = inv_get_sensor_type_rotation_vector(s->data, &status,
2637                                                 &s->timestamp);
2638    s->orientation.status = status;
2639    update |= isCompassDisabled();
2640    LOGV_IF(HANDLER_DATA, "HAL:rv data: %+f %+f %+f %+f %+f %d- %+lld - %d",
2641            s->data[0], s->data[1], s->data[2], s->data[3], s->data[4], s->orientation.status, s->timestamp,
2642            update);
2643
2644    return update;
2645}
2646
2647/*
2648    Game Rotation Vector handler.
2649    NOTE: rotation vector does not have an accuracy or status
2650*/
2651int MPLSensor::grvHandler(sensors_event_t* s)
2652{
2653    VHANDLER_LOG;
2654    int8_t status;
2655    int update;
2656    update = inv_get_sensor_type_rotation_vector_6_axis(s->data, &status,
2657                                                     &s->timestamp);
2658    s->orientation.status = status;
2659
2660    LOGV_IF(HANDLER_DATA, "HAL:grv data: %+f %+f %+f %+f %+f %d- %+lld - %d",
2661            s->data[0], s->data[1], s->data[2], s->data[3], s->data[4], s->orientation.status, s->timestamp,
2662            update);
2663    return update;
2664}
2665
2666int MPLSensor::laHandler(sensors_event_t* s)
2667{
2668    VHANDLER_LOG;
2669    int update;
2670    update = inv_get_sensor_type_linear_acceleration(
2671            s->gyro.v, &s->gyro.status, &s->timestamp);
2672    update |= isCompassDisabled();
2673    LOGV_IF(HANDLER_DATA, "HAL:la data: %+f %+f %+f - %lld - %d",
2674            s->gyro.v[0], s->gyro.v[1], s->gyro.v[2], s->timestamp, update);
2675    return update;
2676}
2677
2678int MPLSensor::gravHandler(sensors_event_t* s)
2679{
2680    VHANDLER_LOG;
2681    int update;
2682    update = inv_get_sensor_type_gravity(s->gyro.v, &s->gyro.status,
2683                                         &s->timestamp);
2684    update |= isCompassDisabled();
2685    LOGV_IF(HANDLER_DATA, "HAL:gr data: %+f %+f %+f - %lld - %d",
2686            s->gyro.v[0], s->gyro.v[1], s->gyro.v[2], s->timestamp, update);
2687    return update;
2688}
2689
2690int MPLSensor::orienHandler(sensors_event_t* s)
2691{
2692    VHANDLER_LOG;
2693    int update;
2694    update = inv_get_sensor_type_orientation(
2695            s->orientation.v, &s->orientation.status, &s->timestamp);
2696    update |= isCompassDisabled();
2697    LOGV_IF(HANDLER_DATA, "HAL:or data: %f %f %f - %lld - %d",
2698            s->orientation.v[0], s->orientation.v[1], s->orientation.v[2],
2699            s->timestamp, update);
2700    return update;
2701}
2702
2703int MPLSensor::smHandler(sensors_event_t* s)
2704{
2705    VHANDLER_LOG;
2706    int update = 1;
2707
2708    /* When event is triggered, set data to 1 */
2709    s->data[0] = 1.f;
2710    s->data[1] = 0.f;
2711    s->data[2] = 0.f;
2712
2713    /* Capture timestamp in HAL */
2714    struct timespec ts;
2715    clock_gettime(CLOCK_MONOTONIC, &ts);
2716    s->timestamp = (int64_t) ts.tv_sec * 1000000000 + ts.tv_nsec;
2717
2718    LOGV_IF(HANDLER_DATA, "HAL:sm data: %f - %lld - %d",
2719            s->data[0], s->timestamp, update);
2720    return update;
2721}
2722
2723int MPLSensor::gmHandler(sensors_event_t* s)
2724{
2725    VHANDLER_LOG;
2726    int8_t status;
2727    int update = 0;
2728    update = inv_get_sensor_type_geomagnetic_rotation_vector(s->data, &status,
2729                                                             &s->timestamp);
2730    s->orientation.status = status;
2731    LOGV_IF(HANDLER_DATA, "HAL:gm data: %+f %+f %+f %+f %+f %d- %+lld - %d",
2732            s->data[0], s->data[1], s->data[2], s->data[3], s->data[4], s->orientation.status, s->timestamp, update);
2733    return update < 1 ? 0 :1;
2734
2735}
2736
2737int MPLSensor::psHandler(sensors_event_t* s)
2738{
2739    VHANDLER_LOG;
2740    int8_t status;
2741    int update = 0;
2742
2743    s->pressure = mCachedPressureData / 100.f; //hpa (millibar)
2744    s->data[1] = 0;
2745    s->data[2] = 0;
2746    s->timestamp = mPressureTimestamp;
2747    s->magnetic.status = 0;
2748    update = mPressureUpdate;
2749    mPressureUpdate = 0;
2750
2751    LOGV_IF(HANDLER_DATA, "HAL:ps data: %+f %+f %+f %+f- %+lld - %d",
2752            s->data[0], s->data[1], s->data[2], s->data[3], s->timestamp, update);
2753    return update < 1 ? 0 :1;
2754
2755}
2756
2757int MPLSensor::sdHandler(sensors_event_t* s)
2758{
2759    VHANDLER_LOG;
2760    int update = 1;
2761
2762    /* When event is triggered, set data to 1 */
2763    s->data[0] = 1;
2764    s->data[1] = 0.f;
2765    s->data[2] = 0.f;
2766
2767    /* get current timestamp */
2768    struct timespec ts;
2769    clock_gettime(CLOCK_MONOTONIC, &ts) ;
2770    s->timestamp = (int64_t)ts.tv_sec * 1000000000 + ts.tv_nsec;
2771
2772    LOGV_IF(HANDLER_DATA, "HAL:sd data: %f - %lld - %d",
2773            s->data[0], s->timestamp, update);
2774    return update;
2775}
2776
2777int MPLSensor::scHandler(sensors_event_t* s)
2778{
2779    VHANDLER_LOG;
2780    int update = 1;
2781
2782    /* Set step count */
2783#if defined ANDROID_KITKAT
2784    s->u64.step_counter = mLastStepCount;
2785    LOGV_IF(HANDLER_DATA, "HAL:sc data: %lld - %lld - %d",
2786            s->u64.step_counter, s->timestamp, update);
2787#else
2788    s->step_counter = mLastStepCount;
2789    LOGV_IF(HANDLER_DATA, "HAL:sc data: %lld - %lld - %d",
2790            s->step_counter, s->timestamp, update);
2791#endif
2792    return update;
2793}
2794
2795int MPLSensor::metaHandler(sensors_event_t* s, int flags)
2796{
2797    VHANDLER_LOG;
2798    int update = 1;
2799
2800#if defined ANDROID_KITKAT
2801    /* initalize SENSOR_TYPE_META_DATA */
2802    s->version = 0;
2803    s->sensor = 0;
2804    s->reserved0 = 0;
2805    s->timestamp = 0LL;
2806
2807    switch(flags) {
2808    case META_DATA_FLUSH_COMPLETE:
2809        s->type = SENSOR_TYPE_META_DATA;
2810        s->meta_data.what = flags;
2811        s->meta_data.sensor = mFlushSensorEnabledVector[0];
2812        mFlushSensorEnabledVector.removeAt(0);
2813        mFlushBatchSet = 0;
2814        LOGV_IF(HANDLER_DATA,
2815                "HAL:flush complete data: type=%d what=%d, "
2816                "sensor=%d - %lld - %d",
2817                s->type, s->meta_data.what, s->meta_data.sensor,
2818                s->timestamp, update);
2819        break;
2820
2821    default:
2822        LOGW("HAL: Meta flags not supported");
2823        break;
2824    }
2825#endif
2826    return 1;
2827}
2828
2829int MPLSensor::enable(int32_t handle, int en)
2830{
2831    VFUNC_LOG;
2832
2833    android::String8 sname;
2834    int what = -1, err = 0;
2835    int batchMode = 0;
2836
2837    if (uint32_t(handle) >= NumSensors)
2838        return -EINVAL;
2839
2840    if (!en)
2841        mBatchEnabled &= ~(1 << handle);
2842
2843    LOGV_IF(ENG_VERBOSE, "HAL:handle = %d", handle);
2844
2845    switch (handle) {
2846    case ID_SC:
2847         what = StepCounter;
2848         sname = "Step Counter";
2849         LOGV_IF(PROCESS_VERBOSE, "HAL:enable - sensor %s (handle %d) %s -> %s",
2850                sname.string(), handle,
2851                (mDmpStepCountEnabled? "en": "dis"),
2852                (en? "en" : "dis"));
2853        enableDmpPedometer(en, 0);
2854        mDmpStepCountEnabled = !!en;
2855        return 0;
2856    case ID_P:
2857        sname = "StepDetector";
2858        LOGV_IF(PROCESS_VERBOSE, "HAL:enable - sensor %s (handle %d) %s -> %s",
2859                sname.string(), handle,
2860                (mDmpPedometerEnabled? "en": "dis"),
2861                (en? "en" : "dis"));
2862        enableDmpPedometer(en, 1);
2863        mDmpPedometerEnabled = !!en;
2864        batchMode = computeBatchSensorMask(mEnabled, mBatchEnabled);
2865        /* skip setBatch if there is no need to */
2866        if(((int)mOldBatchEnabledMask != batchMode) || batchMode) {
2867            setBatch(batchMode,1);
2868        }
2869        mOldBatchEnabledMask = batchMode;
2870        return 0;
2871    case ID_SM:
2872        sname = "Significant Motion";
2873        LOGV_IF(PROCESS_VERBOSE, "HAL:enable - sensor %s (handle %d) %s -> %s",
2874                sname.string(), handle,
2875                (mDmpSignificantMotionEnabled? "en": "dis"),
2876                (en? "en" : "dis"));
2877        enableDmpSignificantMotion(en);
2878        mDmpSignificantMotionEnabled = !!en;
2879        return 0;
2880    case ID_SO:
2881        sname = "Screen Orientation";
2882        LOGV_IF(PROCESS_VERBOSE, "HAL:enable - sensor %s (handle %d) %s -> %s",
2883                sname.string(), handle,
2884                (mDmpOrientationEnabled? "en": "dis"),
2885                (en? "en" : "dis"));
2886        enableDmpOrientation(en && isDmpDisplayOrientationOn());
2887        mDmpOrientationEnabled = !!en;
2888        return 0;
2889    case ID_A:
2890        what = Accelerometer;
2891        sname = "Accelerometer";
2892        break;
2893    case ID_M:
2894        what = MagneticField;
2895        sname = "MagneticField";
2896        break;
2897    case ID_RM:
2898        what = RawMagneticField;
2899        sname = "MagneticField Uncalibrated";
2900        break;
2901    case ID_O:
2902        what = Orientation;
2903        sname = "Orientation";
2904        break;
2905    case ID_GY:
2906        what = Gyro;
2907        sname = "Gyro";
2908        break;
2909    case ID_RG:
2910        what = RawGyro;
2911        sname = "Gyro Uncalibrated";
2912        break;
2913    case ID_GR:
2914        what = Gravity;
2915        sname = "Gravity";
2916        break;
2917    case ID_RV:
2918        what = RotationVector;
2919        sname = "RotationVector";
2920        break;
2921    case ID_GRV:
2922        what = GameRotationVector;
2923        sname = "GameRotationVector";
2924        break;
2925    case ID_LA:
2926        what = LinearAccel;
2927        sname = "LinearAccel";
2928        break;
2929    case ID_GMRV:
2930        what = GeomagneticRotationVector;
2931        sname = "GeomagneticRotationVector";
2932        break;
2933#ifdef ENABLE_PRESSURE
2934    case ID_PS:
2935        what = Pressure;
2936        sname = "Pressure";
2937        break;
2938#endif
2939    default:
2940        what = handle;
2941        sname = "Others";
2942        break;
2943    }
2944
2945    int newState = en ? 1 : 0;
2946    unsigned long sen_mask;
2947
2948    LOGV_IF(PROCESS_VERBOSE, "HAL:enable - sensor %s (handle %d) %s -> %s",
2949            sname.string(), handle,
2950            ((mEnabled & (1 << what)) ? "en" : "dis"),
2951            ((uint32_t(newState) << what) ? "en" : "dis"));
2952    LOGV_IF(ENG_VERBOSE,
2953            "HAL:%s sensor state change what=%d", sname.string(), what);
2954
2955    // pthread_mutex_lock(&mMplMutex);
2956    // pthread_mutex_lock(&mHALMutex);
2957
2958    if ((uint32_t(newState) << what) != (mEnabled & (1 << what))) {
2959        uint32_t sensor_type;
2960        short flags = newState;
2961        uint32_t lastEnabled = mEnabled, changed = 0;
2962
2963        mEnabled &= ~(1 << what);
2964        mEnabled |= (uint32_t(flags) << what);
2965
2966        LOGV_IF(ENG_VERBOSE, "HAL:flags = %d", flags);
2967        computeLocalSensorMask(mEnabled);
2968        LOGV_IF(ENG_VERBOSE, "HAL:enable : mEnabled = %d", mEnabled);
2969        LOGV_IF(ENG_VERBOSE, "HAL:last enable : lastEnabled = %d", lastEnabled);
2970        sen_mask = mLocalSensorMask & mMasterSensorMask;
2971        mSensorMask = sen_mask;
2972        LOGV_IF(ENG_VERBOSE, "HAL:sen_mask= 0x%0lx", sen_mask);
2973
2974        switch (what) {
2975            case Gyro:
2976            case RawGyro:
2977            case Accelerometer:
2978                if ((!(mEnabled & VIRTUAL_SENSOR_GYRO_6AXES_MASK) &&
2979                    !(mEnabled & VIRTUAL_SENSOR_9AXES_MASK)) &&
2980                    ((lastEnabled & (1 << what)) != (mEnabled & (1 << what)))) {
2981                    changed |= (1 << what);
2982                }
2983                if (mFeatureActiveMask & INV_DMP_6AXIS_QUATERNION) {
2984                     changed |= (1 << what);
2985                }
2986                break;
2987            case MagneticField:
2988            case RawMagneticField:
2989                if (!(mEnabled & VIRTUAL_SENSOR_9AXES_MASK) &&
2990                    ((lastEnabled & (1 << what)) != (mEnabled & (1 << what)))) {
2991                    changed |= (1 << what);
2992                }
2993                break;
2994#ifdef ENABLE_PRESSURE
2995            case Pressure:
2996                if ((lastEnabled & (1 << what)) != (mEnabled & (1 << what))) {
2997                    changed |= (1 << what);
2998                }
2999                break;
3000#endif
3001            case GameRotationVector:
3002                if (!en)
3003                    storeCalibration();
3004                if ((en && !(lastEnabled & VIRTUAL_SENSOR_ALL_MASK))
3005                         ||
3006                    (en && !(lastEnabled & VIRTUAL_SENSOR_9AXES_MASK))
3007                         ||
3008                    (!en && !(mEnabled & VIRTUAL_SENSOR_ALL_MASK))
3009                         ||
3010                    (!en && (mEnabled & VIRTUAL_SENSOR_MAG_6AXES_MASK))) {
3011                    for (int i = Gyro; i <= RawMagneticField; i++) {
3012                        if (!(mEnabled & (1 << i))) {
3013                            changed |= (1 << i);
3014                        }
3015                    }
3016                }
3017                break;
3018
3019            case Orientation:
3020            case RotationVector:
3021            case LinearAccel:
3022            case Gravity:
3023                if (!en)
3024                    storeCalibration();
3025                if ((en && !(lastEnabled & VIRTUAL_SENSOR_9AXES_MASK))
3026                         ||
3027                    (!en && !(mEnabled & VIRTUAL_SENSOR_9AXES_MASK))) {
3028                    for (int i = Gyro; i <= RawMagneticField; i++) {
3029                        if (!(mEnabled & (1 << i))) {
3030                            changed |= (1 << i);
3031                        }
3032                    }
3033                }
3034                break;
3035            case GeomagneticRotationVector:
3036                if (!en)
3037                    storeCalibration();
3038                if ((en && !(lastEnabled & VIRTUAL_SENSOR_ALL_MASK))
3039                        ||
3040                    (en && !(lastEnabled & VIRTUAL_SENSOR_9AXES_MASK))
3041                         ||
3042                   (!en && !(mEnabled & VIRTUAL_SENSOR_ALL_MASK))
3043                         ||
3044                   (!en && (mEnabled & VIRTUAL_SENSOR_GYRO_6AXES_MASK))) {
3045                   for (int i = Accelerometer; i <= RawMagneticField; i++) {
3046                       if (!(mEnabled & (1<<i))) {
3047                          changed |= (1 << i);
3048                       }
3049                   }
3050                }
3051                break;
3052        }
3053        LOGV_IF(ENG_VERBOSE, "HAL:changed = %d", changed);
3054        enableSensors(sen_mask, flags, changed);
3055    }
3056
3057    // pthread_mutex_unlock(&mMplMutex);
3058    // pthread_mutex_unlock(&mHALMutex);
3059
3060#ifdef INV_PLAYBACK_DBG
3061    /* apparently the logging needs to go through this sequence
3062       to properly flush the log file */
3063    inv_turn_off_data_logging();
3064    if (fclose(logfile) < 0) {
3065         LOGE("cannot close debug log file");
3066    }
3067    logfile = fopen("/data/playback.bin", "ab");
3068    if (logfile)
3069        inv_turn_on_data_logging(logfile);
3070#endif
3071
3072    return err;
3073}
3074
3075void MPLSensor::getHandle(int32_t handle, int &what, android::String8 &sname)
3076{
3077   VFUNC_LOG;
3078
3079   what = -1;
3080
3081   switch (handle) {
3082   case ID_P:
3083        what = StepDetector;
3084        sname = "StepDetector";
3085        break;
3086   case ID_SC:
3087        what = StepCounter;
3088        sname = "StepCounter";
3089        break;
3090   case ID_SM:
3091        what = SignificantMotion;
3092        sname = "SignificantMotion";
3093        break;
3094   case ID_SO:
3095        what = handle;
3096        sname = "ScreenOrienation";
3097        break;
3098   case ID_A:
3099        what = Accelerometer;
3100        sname = "Accelerometer";
3101        break;
3102   case ID_M:
3103        what = MagneticField;
3104        sname = "MagneticField";
3105        break;
3106   case ID_RM:
3107        what = RawMagneticField;
3108        sname = "MagneticField Uncalibrated";
3109        break;
3110   case ID_O:
3111        what = Orientation;
3112        sname = "Orientation";
3113        break;
3114   case ID_GY:
3115        what = Gyro;
3116        sname = "Gyro";
3117        break;
3118   case ID_RG:
3119        what = RawGyro;
3120        sname = "Gyro Uncalibrated";
3121        break;
3122   case ID_GR:
3123        what = Gravity;
3124        sname = "Gravity";
3125        break;
3126   case ID_RV:
3127        what = RotationVector;
3128        sname = "RotationVector";
3129        break;
3130   case ID_GRV:
3131        what = GameRotationVector;
3132        sname = "GameRotationVector";
3133        break;
3134   case ID_LA:
3135        what = LinearAccel;
3136        sname = "LinearAccel";
3137        break;
3138#ifdef ENABLE_PRESSURE
3139   case ID_PS:
3140        what = Pressure;
3141        sname = "Pressure";
3142        break;
3143#endif
3144   default: // this takes care of all the gestures
3145        what = handle;
3146        sname = "Others";
3147        break;
3148    }
3149
3150    LOGI_IF(EXTRA_VERBOSE, "HAL:getHandle - what=%d, sname=%s", what, sname.string());
3151    return;
3152}
3153
3154int MPLSensor::setDelay(int32_t handle, int64_t ns)
3155{
3156    VFUNC_LOG;
3157
3158    android::String8 sname;
3159    int what = -1;
3160
3161#if 0
3162    // skip the 1st call for enalbing sensors called by ICS/JB sensor service
3163    static int counter_delay = 0;
3164    if (!(mEnabled & (1 << what))) {
3165        counter_delay = 0;
3166    } else {
3167        if (++counter_delay == 1) {
3168            return 0;
3169        }
3170        else {
3171            counter_delay = 0;
3172        }
3173    }
3174#endif
3175
3176    getHandle(handle, what, sname);
3177    if (uint32_t(what) >= NumSensors)
3178        return -EINVAL;
3179
3180    if (ns < 0)
3181        return -EINVAL;
3182
3183    LOGV_IF(PROCESS_VERBOSE,
3184            "setDelay : %llu ns, (%.2f Hz)", ns, 1000000000.f / ns);
3185
3186    // limit all rates to reasonable ones */
3187    if (ns < 5000000LL) {
3188        ns = 5000000LL;
3189    }
3190
3191    /* store request rate to mDelays arrary for each sensor */
3192    int64_t previousDelay = mDelays[what];
3193    mDelays[what] = ns;
3194    LOGV_IF(ENG_VERBOSE, "storing mDelays[%d] = %lld, previousDelay = %lld", what, ns, previousDelay);
3195
3196    switch (what) {
3197        case StepCounter:
3198            /* set limits of delivery rate of events */
3199            mStepCountPollTime = ns;
3200            LOGV_IF(ENG_VERBOSE, "step count rate =%lld ns", ns);
3201            break;
3202        case StepDetector:
3203        case SignificantMotion:
3204#ifdef ENABLE_DMP_SCREEN_AUTO_ROTATION
3205        case ID_SO:
3206#endif
3207            LOGV_IF(ENG_VERBOSE, "Step Detect, SMD, SO rate=%lld ns", ns);
3208            break;
3209        case Gyro:
3210        case RawGyro:
3211        case Accelerometer:
3212            // need to update delay since they are different
3213            // resetDataRates was called earlier
3214            // LOGV("what=%d mEnabled=%d mDelays[%d]=%lld previousDelay=%lld",
3215            // what, mEnabled, what, mDelays[what], previousDelay);
3216            if ((mEnabled & (1 << what)) && (previousDelay != mDelays[what])) {
3217                LOGV_IF(ENG_VERBOSE,
3218                    "HAL:need to update delay due to resetDataRates");
3219                break;
3220            }
3221            for (int i = Gyro;
3222                    i <= Accelerometer + mCompassSensor->isIntegrated();
3223                    i++) {
3224                if (i != what && (mEnabled & (1 << i)) && ns > mDelays[i]) {
3225                    LOGV_IF(ENG_VERBOSE,
3226                            "HAL:ignore delay set due to sensor %d", i);
3227                    return 0;
3228                }
3229            }
3230            break;
3231
3232        case MagneticField:
3233        case RawMagneticField:
3234            // need to update delay since they are different
3235            // resetDataRates was called earlier
3236            if ((mEnabled & (1 << what)) && (previousDelay != mDelays[what])) {
3237                LOGV_IF(ENG_VERBOSE,
3238                    "HAL:need to update delay due to resetDataRates");
3239                break;
3240            }
3241            if (mCompassSensor->isIntegrated() &&
3242                    (((mEnabled & (1 << Gyro)) && ns > mDelays[Gyro]) ||
3243                    ((mEnabled & (1 << RawGyro)) && ns > mDelays[RawGyro]) ||
3244                    ((mEnabled & (1 << Accelerometer)) &&
3245                        ns > mDelays[Accelerometer])) &&
3246                        !checkBatchEnabled()) {
3247                 /* if request is slower rate, ignore request */
3248                 LOGV_IF(ENG_VERBOSE,
3249                         "HAL:ignore delay set due to gyro/accel");
3250                 return 0;
3251            }
3252            break;
3253
3254        case Orientation:
3255        case RotationVector:
3256        case GameRotationVector:
3257        case GeomagneticRotationVector:
3258        case LinearAccel:
3259        case Gravity:
3260            if (isLowPowerQuatEnabled()) {
3261                LOGV_IF(ENG_VERBOSE,
3262                        "HAL:need to update delay due to LPQ");
3263                break;
3264            }
3265
3266            for (int i = 0; i < NumSensors; i++) {
3267                if (i != what && (mEnabled & (1 << i)) && ns > mDelays[i]) {
3268                    LOGV_IF(ENG_VERBOSE,
3269                            "HAL:ignore delay set due to sensor %d", i);
3270                    return 0;
3271                }
3272            }
3273            break;
3274    }
3275
3276    // pthread_mutex_lock(&mHALMutex);
3277    int res = update_delay();
3278    // pthread_mutex_unlock(&mHALMutex);
3279    return res;
3280}
3281
3282int MPLSensor::update_delay(void)
3283{
3284    VFUNC_LOG;
3285
3286    int res = 0;
3287    int64_t got;
3288
3289    if (mEnabled) {
3290        int64_t wanted = 1000000000LL;
3291        int64_t wanted_3rd_party_sensor = 1000000000LL;
3292
3293        // Sequence to change sensor's FIFO rate
3294        // 1. reset master enable
3295        // 2. Update delay
3296        // 3. set master enable
3297
3298        // reset master enable
3299        masterEnable(0);
3300
3301        int64_t gyroRate;
3302        int64_t accelRate;
3303        int64_t compassRate;
3304#ifdef ENABLE_PRESSURE
3305        int64_t pressureRate;
3306#endif
3307
3308        int rateInus;
3309        int mplGyroRate;
3310        int mplAccelRate;
3311        int mplCompassRate;
3312        int tempRate = wanted;
3313
3314        /* search the minimum delay requested across all enabled sensors */
3315        for (int i = 0; i < NumSensors; i++) {
3316            if (mEnabled & (1 << i)) {
3317                int64_t ns = mDelays[i];
3318                wanted = wanted < ns ? wanted : ns;
3319            }
3320        }
3321
3322        /* initialize rate for each sensor */
3323        gyroRate = wanted;
3324        accelRate = wanted;
3325        compassRate = wanted;
3326#ifdef ENABLE_PRESSURE
3327        pressureRate = wanted;
3328#endif
3329        // same delay for 3rd party Accel or Compass
3330        wanted_3rd_party_sensor = wanted;
3331
3332        int enabled_sensors = mEnabled;
3333        int tempFd = -1;
3334
3335        if(mFeatureActiveMask & INV_DMP_BATCH_MODE) {
3336            // set batch rates
3337            LOGV_IF(ENG_VERBOSE, "HAL: mFeatureActiveMask=%016llx", mFeatureActiveMask);
3338            LOGV("HAL: batch mode is set, set batch data rates");
3339            if (setBatchDataRates() < 0) {
3340                LOGE("HAL:ERR can't set batch data rates");
3341            }
3342        } else {
3343            /* set master sampling frequency */
3344            int64_t tempWanted = wanted;
3345            getDmpRate(&tempWanted);
3346            /* driver only looks at sampling frequency if DMP is off */
3347            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)",
3348                    1000000000.f / tempWanted, mpu.gyro_fifo_rate, getTimestamp());
3349            tempFd = open(mpu.gyro_fifo_rate, O_RDWR);
3350            res = write_attribute_sensor(tempFd, 1000000000.f / tempWanted);
3351            LOGE_IF(res < 0, "HAL:sampling frequency update delay error");
3352
3353        if (LA_ENABLED || GR_ENABLED || RV_ENABLED
3354                       || GRV_ENABLED || O_ENABLED || GMRV_ENABLED) {
3355            rateInus = (int)wanted / 1000LL;
3356
3357            /* set rate in MPL */
3358            /* compass can only do 100Hz max */
3359            inv_set_gyro_sample_rate(rateInus);
3360            inv_set_accel_sample_rate(rateInus);
3361            inv_set_compass_sample_rate(rateInus);
3362            inv_set_linear_acceleration_sample_rate(rateInus);
3363            inv_set_orientation_sample_rate(rateInus);
3364            inv_set_rotation_vector_sample_rate(rateInus);
3365            inv_set_gravity_sample_rate(rateInus);
3366            inv_set_orientation_geomagnetic_sample_rate(rateInus);
3367            inv_set_rotation_vector_6_axis_sample_rate(rateInus);
3368            inv_set_geomagnetic_rotation_vector_sample_rate(rateInus);
3369
3370            LOGV_IF(ENG_VERBOSE,
3371                    "HAL:MPL virtual sensor sample rate: (mpl)=%d us (mpu)=%.2f Hz",
3372                    rateInus, 1000000000.f / wanted);
3373            LOGV_IF(ENG_VERBOSE,
3374                    "HAL:MPL gyro sample rate: (mpl)=%d us (mpu)=%.2f Hz",
3375                    rateInus, 1000000000.f / gyroRate);
3376            LOGV_IF(ENG_VERBOSE,
3377                    "HAL:MPL accel sample rate: (mpl)=%d us (mpu)=%.2f Hz",
3378                    rateInus, 1000000000.f / accelRate);
3379            LOGV_IF(ENG_VERBOSE,
3380                    "HAL:MPL compass sample rate: (mpl)=%d us (mpu)=%.2f Hz",
3381                    rateInus, 1000000000.f / compassRate);
3382
3383            LOGV_IF(ENG_VERBOSE,
3384                    "mFeatureActiveMask=%016llx", mFeatureActiveMask);
3385            if(mFeatureActiveMask & DMP_FEATURE_MASK) {
3386                bool setDMPrate= 0;
3387                gyroRate = wanted;
3388                accelRate = wanted;
3389                compassRate = wanted;
3390                // same delay for 3rd party Accel or Compass
3391                wanted_3rd_party_sensor = wanted;
3392                rateInus = (int)wanted / 1000LL;
3393                // Set LP Quaternion sample rate if enabled
3394                if (checkLPQuaternion()) {
3395                    if (wanted <= RATE_200HZ) {
3396#ifndef USE_LPQ_AT_FASTEST
3397                        enableLPQuaternion(0);
3398#endif
3399                    } else {
3400                        inv_set_quat_sample_rate(rateInus);
3401                        LOGV_IF(ENG_VERBOSE, "HAL:MPL quat sample rate: "
3402                                "(mpl)=%d us (mpu)=%.2f Hz",
3403                                rateInus, 1000000000.f / wanted);
3404                        setDMPrate= 1;
3405                    }
3406                }
3407            }
3408
3409            LOGV_IF(EXTRA_VERBOSE, "HAL:setDelay - Fusion");
3410            //nsToHz
3411            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)",
3412                    1000000000.f / gyroRate, mpu.gyro_rate,
3413                    getTimestamp());
3414            tempFd = open(mpu.gyro_rate, O_RDWR);
3415            res = write_attribute_sensor(tempFd, 1000000000.f / gyroRate);
3416            if(res < 0) {
3417                LOGE("HAL:GYRO update delay error");
3418            }
3419
3420            if(USE_THIRD_PARTY_ACCEL == 1) {
3421                // 3rd party accelerometer - if applicable
3422                // nsToHz (BMA250)
3423                LOGV_IF(SYSFS_VERBOSE, "echo %lld > %s (%lld)",
3424                        wanted_3rd_party_sensor / 1000000L, mpu.accel_rate,
3425                        getTimestamp());
3426                tempFd = open(mpu.accel_rate, O_RDWR);
3427                res = write_attribute_sensor(tempFd,
3428                        wanted_3rd_party_sensor / 1000000L);
3429                LOGE_IF(res < 0, "HAL:ACCEL update delay error");
3430            } else {
3431                // mpu accel
3432               LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)",
3433                        1000000000.f / accelRate, mpu.accel_rate,
3434                        getTimestamp());
3435                tempFd = open(mpu.accel_rate, O_RDWR);
3436                res = write_attribute_sensor(tempFd, 1000000000.f / accelRate);
3437                LOGE_IF(res < 0, "HAL:ACCEL update delay error");
3438            }
3439
3440            if (!mCompassSensor->isIntegrated()) {
3441                // stand-alone compass - if applicable
3442                LOGV_IF(ENG_VERBOSE,
3443                        "HAL:Ext compass delay %lld", wanted_3rd_party_sensor);
3444                LOGV_IF(ENG_VERBOSE, "HAL:Ext compass rate %.2f Hz",
3445                        1000000000.f / wanted_3rd_party_sensor);
3446                if (wanted_3rd_party_sensor <
3447                        mCompassSensor->getMinDelay() * 1000LL) {
3448                    wanted_3rd_party_sensor =
3449                        mCompassSensor->getMinDelay() * 1000LL;
3450                }
3451                LOGV_IF(ENG_VERBOSE,
3452                        "HAL:Ext compass delay %lld", wanted_3rd_party_sensor);
3453                LOGV_IF(ENG_VERBOSE, "HAL:Ext compass rate %.2f Hz",
3454                        1000000000.f / wanted_3rd_party_sensor);
3455                mCompassSensor->setDelay(ID_M, wanted_3rd_party_sensor);
3456                got = mCompassSensor->getDelay(ID_M);
3457                inv_set_compass_sample_rate(got / 1000);
3458            } else {
3459                // compass on secondary bus
3460                if (compassRate < mCompassSensor->getMinDelay() * 1000LL) {
3461                    compassRate = mCompassSensor->getMinDelay() * 1000LL;
3462                }
3463                mCompassSensor->setDelay(ID_M, compassRate);
3464            }
3465        } else {
3466
3467            if (GY_ENABLED || RGY_ENABLED) {
3468                wanted = (mDelays[Gyro] <= mDelays[RawGyro]?
3469                    (mEnabled & (1 << Gyro)? mDelays[Gyro]: mDelays[RawGyro]):
3470                    (mEnabled & (1 << RawGyro)? mDelays[RawGyro]: mDelays[Gyro]));
3471                LOGV_IF(ENG_VERBOSE, "mFeatureActiveMask=%016llx", mFeatureActiveMask);
3472                inv_set_gyro_sample_rate((int)wanted/1000LL);
3473                LOGV_IF(ENG_VERBOSE,
3474                    "HAL:MPL gyro sample rate: (mpl)=%d us", int(wanted/1000LL));
3475                LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)",
3476                        1000000000.f / wanted, mpu.gyro_rate, getTimestamp());
3477                tempFd = open(mpu.gyro_rate, O_RDWR);
3478                res = write_attribute_sensor(tempFd, 1000000000.f / wanted);
3479                LOGE_IF(res < 0, "HAL:GYRO update delay error");
3480            }
3481
3482            if (A_ENABLED) { /* there is only 1 fifo rate for MPUxxxx */
3483                if (GY_ENABLED && mDelays[Gyro] < mDelays[Accelerometer]) {
3484                    wanted = mDelays[Gyro];
3485                } else if (RGY_ENABLED && mDelays[RawGyro]
3486                            < mDelays[Accelerometer]) {
3487                    wanted = mDelays[RawGyro];
3488                } else {
3489                    wanted = mDelays[Accelerometer];
3490                }
3491                LOGV_IF(ENG_VERBOSE, "mFeatureActiveMask=%016llx", mFeatureActiveMask);
3492                inv_set_accel_sample_rate((int)wanted/1000LL);
3493                LOGV_IF(ENG_VERBOSE, "HAL:MPL accel sample rate: (mpl)=%d us",
3494                        int(wanted/1000LL));
3495                LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)",
3496                        1000000000.f / wanted, mpu.accel_rate,
3497                        getTimestamp());
3498                tempFd = open(mpu.accel_rate, O_RDWR);
3499                if(USE_THIRD_PARTY_ACCEL == 1) {
3500                    //BMA250 in ms
3501                    res = write_attribute_sensor(tempFd, wanted / 1000000L);
3502                }
3503                else {
3504                    //MPUxxxx in hz
3505                    res = write_attribute_sensor(tempFd, 1000000000.f/wanted);
3506                }
3507                LOGE_IF(res < 0, "HAL:ACCEL update delay error");
3508            }
3509
3510            /* Invensense compass calibration */
3511            if (M_ENABLED || RM_ENABLED) {
3512                int64_t compassWanted = (mDelays[MagneticField] <= mDelays[RawMagneticField]?
3513                    (mEnabled & (1 << MagneticField)? mDelays[MagneticField]: mDelays[RawMagneticField]):
3514                    (mEnabled & (1 << RawMagneticField)? mDelays[RawMagneticField]: mDelays[MagneticField]));
3515                if (!mCompassSensor->isIntegrated()) {
3516                    wanted = compassWanted;
3517                } else {
3518                    if (GY_ENABLED
3519                        && (mDelays[Gyro] < compassWanted)) {
3520                        wanted = mDelays[Gyro];
3521                    } else if (RGY_ENABLED
3522                               && mDelays[RawGyro] < compassWanted) {
3523                        wanted = mDelays[RawGyro];
3524                    } else if (A_ENABLED && mDelays[Accelerometer]
3525                                < compassWanted) {
3526                        wanted = mDelays[Accelerometer];
3527                    } else {
3528                        wanted = compassWanted;
3529                    }
3530                    LOGV_IF(ENG_VERBOSE, "mFeatureActiveMask=%016llx", mFeatureActiveMask);
3531                }
3532
3533                mCompassSensor->setDelay(ID_M, wanted);
3534                got = mCompassSensor->getDelay(ID_M);
3535                inv_set_compass_sample_rate(got / 1000);
3536                LOGV_IF(ENG_VERBOSE, "HAL:MPL compass sample rate: (mpl)=%d us",
3537                        int(got/1000LL));
3538            }
3539#ifdef ENABLE_PRESSURE
3540            if (PS_ENABLED) {
3541                int64_t pressureRate = mDelays[Pressure];
3542                LOGV_IF(ENG_VERBOSE, "mFeatureActiveMask=%016llx", mFeatureActiveMask);
3543                mPressureSensor->setDelay(ID_PS, pressureRate);
3544                LOGE_IF(res < 0, "HAL:PRESSURE update delay error");
3545            }
3546#endif
3547        }
3548
3549        } //end of non batch mode
3550
3551        unsigned long sensors = mLocalSensorMask & mMasterSensorMask;
3552        if (sensors &
3553            (INV_THREE_AXIS_GYRO
3554                | INV_THREE_AXIS_ACCEL
3555#ifdef ENABLE_PRESSURE
3556                | (INV_ONE_AXIS_PRESSURE * mPressureSensor->isIntegrated())
3557#endif
3558                | (INV_THREE_AXIS_COMPASS * mCompassSensor->isIntegrated()))) {
3559            LOGV_IF(ENG_VERBOSE, "sensors=%lu", sensors);
3560            res = masterEnable(1);
3561            if(res < 0)
3562                return res;
3563        } else { // all sensors idle -> reduce power, unless DMP is needed
3564            LOGV_IF(ENG_VERBOSE, "mFeatureActiveMask=%016llx", mFeatureActiveMask);
3565            if(mFeatureActiveMask & DMP_FEATURE_MASK) {
3566                res = masterEnable(1);
3567                if(res < 0)
3568                    return res;
3569            }
3570        }
3571    }
3572
3573    return res;
3574}
3575
3576/**
3577 *  Should be called after reading at least one of gyro
3578 *  compass or accel data. (Also okay for handling all of them).
3579 *  @returns 0, if successful, error number if not.
3580 */
3581int MPLSensor::readEvents(sensors_event_t* data, int count)
3582{
3583    VHANDLER_LOG;
3584
3585    inv_execute_on_data();
3586
3587    int numEventReceived = 0;
3588
3589    long msg;
3590    msg = inv_get_message_level_0(1);
3591    if (msg) {
3592        if (msg & INV_MSG_MOTION_EVENT) {
3593            LOGV_IF(PROCESS_VERBOSE, "HAL:**** Motion ****\n");
3594        }
3595        if (msg & INV_MSG_NO_MOTION_EVENT) {
3596            LOGV_IF(PROCESS_VERBOSE, "HAL:***** No Motion *****\n");
3597            /* after the first no motion, the gyro should be
3598               calibrated well */
3599            mGyroAccuracy = SENSOR_STATUS_ACCURACY_HIGH;
3600            /* if gyros are on and we got a no motion, set a flag
3601               indicating that the cal file can be written. */
3602            mHaveGoodMpuCal = true;
3603        }
3604        if(msg & INV_MSG_NEW_AB_EVENT) {
3605            LOGV_IF(EXTRA_VERBOSE, "HAL:***** New Accel Bias *****\n");
3606            getAccelBias();
3607            mAccelAccuracy = inv_get_accel_accuracy();
3608        }
3609        if(msg & INV_MSG_NEW_GB_EVENT) {
3610            LOGV_IF(EXTRA_VERBOSE, "HAL:***** New Gyro Bias *****\n");
3611            getGyroBias();
3612            setGyroBias();
3613        }
3614        if(msg & INV_MSG_NEW_FGB_EVENT) {
3615            LOGV_IF(EXTRA_VERBOSE, "HAL:***** New Factory Gyro Bias *****\n");
3616            getFactoryGyroBias();
3617        }
3618        if(msg & INV_MSG_NEW_FAB_EVENT) {
3619            LOGV_IF(EXTRA_VERBOSE, "HAL:***** New Factory Accel Bias *****\n");
3620            getFactoryAccelBias();
3621        }
3622        if(msg & INV_MSG_NEW_CB_EVENT) {
3623            LOGV_IF(EXTRA_VERBOSE, "HAL:***** New Compass Bias *****\n");
3624            getCompassBias();
3625            mCompassAccuracy = inv_get_mag_accuracy();
3626        }
3627    }
3628
3629    // handle partial packet read and end marker
3630    // skip readEvents from hal_outputs
3631    if (!mFlushSensorEnabledVector.isEmpty()) {
3632        if (!mEmptyDataMarkerDetected) {
3633            // turn off sensors in data_builder
3634            resetMplStates();
3635        }
3636        mEmptyDataMarkerDetected = 0;
3637        mDataMarkerDetected = 0;
3638
3639        // handle flush complete event
3640        for(int k = 0; k < mFlushSensorEnabledVector.size(); k++) {
3641            int sendEvent = metaHandler(&mPendingFlushEvents[k], META_DATA_FLUSH_COMPLETE);
3642            if(sendEvent && count > 0) {
3643                *data++ = mPendingFlushEvents[k];
3644                count--;
3645                numEventReceived++;
3646            }
3647        }
3648        return numEventReceived;
3649    }
3650
3651    if (mSkipReadEvents) {
3652        return numEventReceived;
3653    }
3654
3655    for (int i = 0; i < NumSensors; i++) {
3656        int update = 0;
3657
3658        // handle step detector when ped_q is enabled
3659        if(mPedUpdate) {
3660            if (i == StepDetector) {
3661                update = readDmpPedometerEvents(data, count, ID_P, 1);
3662                mPedUpdate = 0;
3663                if(update == 1 && count > 0) {
3664                    data->timestamp = mStepSensorTimestamp;
3665                    count--;
3666                    numEventReceived++;
3667                    continue;
3668                }
3669            } else {
3670                if (mPedUpdate == DATA_FORMAT_STEP) {
3671                    continue;
3672                }
3673            }
3674        }
3675
3676        // load up virtual sensors
3677        if (mEnabled & (1 << i)) {
3678            update = CALL_MEMBER_FN(this, mHandlers[i])(mPendingEvents + i);
3679            mPendingMask |= (1 << i);
3680
3681            if (update && (count > 0)) {
3682                *data++ = mPendingEvents[i];
3683                count--;
3684                numEventReceived++;
3685            }
3686        }
3687    }
3688    mCompassOverFlow = 0;
3689
3690    return numEventReceived;
3691}
3692
3693// collect data for MPL (but NOT sensor service currently), from driver layer
3694void MPLSensor::buildMpuEvent(void)
3695{
3696    VHANDLER_LOG;
3697
3698    mSkipReadEvents = 0;
3699    int64_t mGyroSensorTimestamp=0, mAccelSensorTimestamp=0, latestTimestamp=0;
3700    int lp_quaternion_on = 0, sixAxis_quaternion_on = 0,
3701        ped_quaternion_on = 0, ped_standalone_on = 0;
3702    size_t nbyte;
3703    unsigned short data_format = 0;
3704    int i, nb, mask = 0,
3705        sensors = ((mLocalSensorMask & INV_THREE_AXIS_GYRO)? 1 : 0) +
3706            ((mLocalSensorMask & INV_THREE_AXIS_ACCEL)? 1 : 0) +
3707            (((mLocalSensorMask & INV_THREE_AXIS_COMPASS)
3708                && mCompassSensor->isIntegrated())? 1 : 0) +
3709            ((mLocalSensorMask & INV_ONE_AXIS_PRESSURE)? 1 : 0);
3710
3711    char *rdata = mIIOBuffer;
3712    ssize_t rsize = 0;
3713    ssize_t readCounter = 0;
3714    char *rdataP = NULL;
3715    bool doneFlag = 0;
3716
3717    lp_quaternion_on = isLowPowerQuatEnabled() && checkLPQuaternion();
3718    sixAxis_quaternion_on = check6AxisQuatEnabled();
3719    ped_quaternion_on = checkPedQuatEnabled();
3720    ped_standalone_on = checkPedStandaloneEnabled();
3721
3722    nbyte = MAX_READ_SIZE - mLeftOverBufferSize;
3723
3724    /* check previous copied buffer */
3725    /* append with just read data */
3726    if (mLeftOverBufferSize > 0) {
3727        LOGV_IF(0, "append old buffer size=%d", mLeftOverBufferSize);
3728        memset(rdata, 0, sizeof(rdata));
3729        memcpy(rdata, mLeftOverBuffer, mLeftOverBufferSize);
3730            LOGV_IF(0,
3731            "HAL:input retrieve old buffer data=:%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, "
3732            "%d, %d,%d, %d, %d, %d\n",
3733            rdata[0], rdata[1], rdata[2], rdata[3],
3734            rdata[4], rdata[5], rdata[6], rdata[7],
3735            rdata[8], rdata[9], rdata[10], rdata[11],
3736            rdata[12], rdata[13], rdata[14], rdata[15]);
3737    }
3738    rdataP = rdata + mLeftOverBufferSize;
3739
3740    /* read expected number of bytes */
3741    rsize = read(iio_fd, rdataP, nbyte);
3742    if(rsize < 0) {
3743        /* IIO buffer might have old data.
3744           Need to flush it if no sensor is on, to avoid infinite
3745           read loop.*/
3746        LOGE("HAL:input data file descriptor not available - (%s)",
3747             strerror(errno));
3748        if (sensors == 0) {
3749            rsize = read(iio_fd, rdata, MAX_SUSPEND_BATCH_PACKET_SIZE);
3750            if(rsize > 0) {
3751                LOGV_IF(ENG_VERBOSE, "HAL:input data flush rsize=%d", (int)rsize);
3752#ifdef TESTING
3753                LOGV_IF(INPUT_DATA,
3754                     "HAL:input rdata:r=%d, n=%d,"
3755                     "%d, %d, %d, %d, %d, %d, %d, %d",
3756                     (int)rsize, nbyte,
3757                     rdataP[0], rdataP[1], rdataP[2], rdataP[3],
3758                     rdataP[4], rdataP[5], rdataP[6], rdataP[7]);
3759#endif
3760                mLeftOverBufferSize = 0;
3761            }
3762        }
3763        return;
3764    }
3765
3766#ifdef TESTING
3767LOGV_IF(INPUT_DATA,
3768         "HAL:input just read rdataP:r=%d, n=%d,"
3769         "%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, %d, %d,"
3770         "%d, %d, %d, %d,%d, %d, %d, %d\n",
3771         (int)rsize, nbyte,
3772         rdataP[0], rdataP[1], rdataP[2], rdataP[3],
3773         rdataP[4], rdataP[5], rdataP[6], rdataP[7],
3774         rdataP[8], rdataP[9], rdataP[10], rdataP[11],
3775         rdataP[12], rdataP[13], rdataP[14], rdataP[15],
3776         rdataP[16], rdataP[17], rdataP[18], rdataP[19],
3777         rdataP[20], rdataP[21], rdataP[22], rdataP[23]);
3778
3779    LOGV_IF(INPUT_DATA,
3780         "HAL:input rdata:r=%d, n=%d,"
3781         "%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, %d, %d,"
3782         "%d, %d, %d, %d,%d, %d, %d, %d\n",
3783         (int)rsize, nbyte,
3784         rdata[0], rdata[1], rdata[2], rdata[3],
3785         rdata[4], rdata[5], rdata[6], rdata[7],
3786         rdata[8], rdata[9], rdata[10], rdata[11],
3787         rdata[12], rdata[13], rdata[14], rdata[15],
3788         rdata[16], rdata[17], rdata[18], rdata[19],
3789         rdata[20], rdata[21], rdata[22], rdata[23]);
3790#endif
3791    /* reset data and count pointer */
3792    rdataP = rdata;
3793    readCounter = rsize + mLeftOverBufferSize;
3794    LOGV_IF(0, "HAL:input readCounter set=%d", (int)readCounter);
3795
3796    if(readCounter < MAX_READ_SIZE) {
3797        // Handle standalone MARKER packet
3798        if (readCounter >= BYTES_PER_SENSOR) {
3799            data_format = *((short *)(rdata));
3800            if (data_format == DATA_FORMAT_MARKER) {
3801                LOGV_IF(ENG_VERBOSE && INPUT_DATA, "MARKER DETECTED:0x%x", data_format);
3802                readCounter -= BYTES_PER_SENSOR;
3803                rdata += BYTES_PER_SENSOR;
3804                if (!mFlushSensorEnabledVector.isEmpty()) {
3805                    mFlushBatchSet = 1;
3806                }
3807                mDataMarkerDetected = 1;
3808            }
3809            else if (data_format == DATA_FORMAT_EMPTY_MARKER) {
3810                LOGV_IF(ENG_VERBOSE && INPUT_DATA, "EMPTY MARKER DETECTED:0x%x", data_format);
3811                readCounter -= BYTES_PER_SENSOR;
3812                rdata += BYTES_PER_SENSOR;
3813                if (!mFlushSensorEnabledVector.isEmpty()) {
3814                    mFlushBatchSet = 1;
3815                }
3816                mEmptyDataMarkerDetected = 1;
3817            }
3818        }
3819
3820        /* store packet then return */
3821        mLeftOverBufferSize = readCounter;
3822        memcpy(mLeftOverBuffer, rdata, mLeftOverBufferSize);
3823
3824#ifdef TESTING
3825        LOGV_IF(1, "HAL:input data has batched partial packet");
3826        LOGV_IF(1, "HAL:input data batched mLeftOverBufferSize=%d", mLeftOverBufferSize);
3827        LOGV_IF(1,
3828            "HAL:input catch up batched retrieve buffer=:%d, %d, %d, %d, %d, %d, %d, %d,"
3829            "%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
3830            mLeftOverBuffer[0], mLeftOverBuffer[1], mLeftOverBuffer[2], mLeftOverBuffer[3],
3831            mLeftOverBuffer[4], mLeftOverBuffer[5], mLeftOverBuffer[6], mLeftOverBuffer[7],
3832            mLeftOverBuffer[8], mLeftOverBuffer[9], mLeftOverBuffer[10], mLeftOverBuffer[11],
3833            mLeftOverBuffer[12], mLeftOverBuffer[13], mLeftOverBuffer[14], mLeftOverBuffer[15]);
3834#endif
3835        mSkipReadEvents = 1;
3836        return;
3837    }
3838
3839    LOGV_IF(INPUT_DATA && ENG_VERBOSE,
3840            "HAL:input b=%d rdata= %d nbyte= %d rsize= %d readCounter= %d",
3841            checkBatchEnabled(), *((short *) rdata), nbyte, (int)rsize, (int)readCounter);
3842    LOGV_IF(INPUT_DATA && ENG_VERBOSE,
3843            "HAL:input sensors= %d, lp_q_on= %d, 6axis_q_on= %d, "
3844            "ped_q_on= %d, ped_standalone_on= %d",
3845            sensors, lp_quaternion_on, sixAxis_quaternion_on, ped_quaternion_on,
3846            ped_standalone_on);
3847
3848    while (readCounter > 0) {
3849        // since copied buffer is already accounted for, reset left over size
3850        mLeftOverBufferSize = 0;
3851        // clear data format mask for parsing the next set of data
3852        mask = 0;
3853        data_format = *((short *)(rdata));
3854        LOGV_IF(INPUT_DATA && ENG_VERBOSE,
3855                "HAL:input data_format=%x", data_format);
3856
3857        if(checkValidHeader(data_format) == 0) {
3858            LOGE("HAL:input invalid data_format 0x%02X", data_format);
3859            return;
3860        }
3861
3862        if (data_format & DATA_FORMAT_STEP) {
3863            if (data_format == DATA_FORMAT_STEP) {
3864                rdata += BYTES_PER_SENSOR;
3865                latestTimestamp = *((long long*) (rdata));
3866                LOGV_IF(ENG_VERBOSE && INPUT_DATA, "STEP DETECTED:0x%x - ts: %lld", data_format, latestTimestamp);
3867                // readCounter is decrement by 24 because DATA_FORMAT_STEP only applies in batch  mode
3868                readCounter -= BYTES_PER_SENSOR_PACKET;
3869            } else {
3870                LOGV_IF(0, "STEP DETECTED:0x%x", data_format);
3871            }
3872            mPedUpdate |= data_format;
3873            mask |= DATA_FORMAT_STEP;
3874            // cancels step bit
3875            data_format &= (~DATA_FORMAT_STEP);
3876        }
3877
3878        if (data_format == DATA_FORMAT_MARKER) {
3879            LOGV_IF(ENG_VERBOSE && INPUT_DATA, "MARKER DETECTED:0x%x", data_format);
3880            readCounter -= BYTES_PER_SENSOR;
3881            if (!mFlushSensorEnabledVector.isEmpty()) {
3882                mFlushBatchSet = 1;
3883            }
3884            mDataMarkerDetected = 1;
3885            mSkipReadEvents = 1;
3886        }
3887        else if (data_format == DATA_FORMAT_EMPTY_MARKER) {
3888            LOGV_IF(ENG_VERBOSE && INPUT_DATA, "EMPTY MARKER DETECTED:0x%x", data_format);
3889            readCounter -= BYTES_PER_SENSOR;
3890            if (!mFlushSensorEnabledVector.isEmpty()) {
3891                mFlushBatchSet = 1;
3892            }
3893            mEmptyDataMarkerDetected = 1;
3894            mSkipReadEvents = 1;
3895        }
3896        else if (data_format == DATA_FORMAT_QUAT) {
3897            LOGV_IF(ENG_VERBOSE && INPUT_DATA, "QUAT DETECTED:0x%x", data_format);
3898            if (readCounter >= BYTES_QUAT_DATA) {
3899                mCachedQuaternionData[0] = *((int *) (rdata + 4));
3900                mCachedQuaternionData[1] = *((int *) (rdata + 8));
3901                mCachedQuaternionData[2] = *((int *) (rdata + 12));
3902                rdata += QUAT_ONLY_LAST_PACKET_OFFSET;
3903                mQuatSensorTimestamp = *((long long*) (rdata));
3904                mask |= DATA_FORMAT_QUAT;
3905                readCounter -= BYTES_QUAT_DATA;
3906            }
3907            else {
3908                doneFlag = 1;
3909            }
3910        }
3911        else if (data_format == DATA_FORMAT_6_AXIS) {
3912            LOGV_IF(ENG_VERBOSE && INPUT_DATA, "6AXIS DETECTED:0x%x", data_format);
3913            if (readCounter >= BYTES_QUAT_DATA) {
3914                mCached6AxisQuaternionData[0] = *((int *) (rdata + 4));
3915                mCached6AxisQuaternionData[1] = *((int *) (rdata + 8));
3916                mCached6AxisQuaternionData[2] = *((int *) (rdata + 12));
3917                rdata += QUAT_ONLY_LAST_PACKET_OFFSET;
3918                mQuatSensorTimestamp = *((long long*) (rdata));
3919                mask |= DATA_FORMAT_6_AXIS;
3920                readCounter -= BYTES_QUAT_DATA;
3921            }
3922            else {
3923                doneFlag = 1;
3924            }
3925        }
3926        else if (data_format == DATA_FORMAT_PED_QUAT) {
3927            LOGV_IF(ENG_VERBOSE && INPUT_DATA, "PED QUAT DETECTED:0x%x", data_format);
3928            if (readCounter >= BYTES_PER_SENSOR_PACKET) {
3929                mCachedPedQuaternionData[0] = *((short *) (rdata + 2));
3930                mCachedPedQuaternionData[1] = *((short *) (rdata + 4));
3931                mCachedPedQuaternionData[2] = *((short *) (rdata + 6));
3932                rdata += BYTES_PER_SENSOR;
3933                mQuatSensorTimestamp = *((long long*) (rdata));
3934                mask |= DATA_FORMAT_PED_QUAT;
3935                readCounter -= BYTES_PER_SENSOR_PACKET;
3936            }
3937            else {
3938                doneFlag = 1;
3939            }
3940        }
3941        else if (data_format == DATA_FORMAT_PED_STANDALONE) {
3942            LOGV_IF(ENG_VERBOSE && INPUT_DATA, "STANDALONE STEP DETECTED:0x%x", data_format);
3943            if (readCounter >= BYTES_PER_SENSOR_PACKET) {
3944                rdata += BYTES_PER_SENSOR;
3945                mStepSensorTimestamp = *((long long*) (rdata));
3946                mask |= DATA_FORMAT_PED_STANDALONE;
3947                readCounter -= BYTES_PER_SENSOR_PACKET;
3948                mPedUpdate |= data_format;
3949            }
3950            else {
3951                doneFlag = 1;
3952            }
3953        }
3954        else if (data_format == DATA_FORMAT_GYRO) {
3955            LOGV_IF(ENG_VERBOSE && INPUT_DATA, "GYRO DETECTED:0x%x", data_format);
3956            if (readCounter >= BYTES_PER_SENSOR_PACKET) {
3957                mCachedGyroData[0] = *((short *) (rdata + 2));
3958                mCachedGyroData[1] = *((short *) (rdata + 4));
3959                mCachedGyroData[2] = *((short *) (rdata + 6));
3960                rdata += BYTES_PER_SENSOR;
3961                mGyroSensorTimestamp = *((long long*) (rdata));
3962                mask |= DATA_FORMAT_GYRO;
3963                readCounter -= BYTES_PER_SENSOR_PACKET;
3964            } else {
3965                doneFlag = 1;
3966            }
3967        }
3968        else if (data_format == DATA_FORMAT_ACCEL) {
3969            LOGV_IF(ENG_VERBOSE && INPUT_DATA, "ACCEL DETECTED:0x%x", data_format);
3970            if (readCounter >= BYTES_PER_SENSOR_PACKET) {
3971                mCachedAccelData[0] = *((short *) (rdata + 2));
3972                mCachedAccelData[1] = *((short *) (rdata + 4));
3973                mCachedAccelData[2] = *((short *) (rdata + 6));
3974                rdata += BYTES_PER_SENSOR;
3975                mAccelSensorTimestamp = *((long long*) (rdata));
3976                mask |= DATA_FORMAT_ACCEL;
3977                readCounter -= BYTES_PER_SENSOR_PACKET;
3978            }
3979            else {
3980                doneFlag = 1;
3981            }
3982        }
3983        else if (data_format == DATA_FORMAT_COMPASS) {
3984            LOGV_IF(ENG_VERBOSE && INPUT_DATA, "COMPASS DETECTED:0x%x", data_format);
3985            if (readCounter >= BYTES_PER_SENSOR_PACKET) {
3986                if (mCompassSensor->isIntegrated()) {
3987                    mCachedCompassData[0] = *((short *) (rdata + 2));
3988                    mCachedCompassData[1] = *((short *) (rdata + 4));
3989                    mCachedCompassData[2] = *((short *) (rdata + 6));
3990                    rdata += BYTES_PER_SENSOR;
3991                    mCompassTimestamp = *((long long*) (rdata));
3992                    mask |= DATA_FORMAT_COMPASS;
3993                    readCounter -= BYTES_PER_SENSOR_PACKET;
3994                }
3995            }
3996            else {
3997                doneFlag = 1;
3998            }
3999        }
4000        else if (data_format == DATA_FORMAT_COMPASS_OF) {
4001            LOGV_IF(ENG_VERBOSE && INPUT_DATA, "COMPASS OF DETECTED:0x%x", data_format);
4002            mask |= DATA_FORMAT_COMPASS_OF;
4003            mCompassOverFlow = 1;
4004#ifdef INV_PLAYBACK_DBG
4005            if (readCounter >= BYTES_PER_SENSOR_PACKET) {
4006                if (mCompassSensor->isIntegrated()) {
4007                    mCachedCompassData[0] = *((short *) (rdata + 2));
4008                    mCachedCompassData[1] = *((short *) (rdata + 4));
4009                    mCachedCompassData[2] = *((short *) (rdata + 6));
4010                    rdata += BYTES_PER_SENSOR;
4011                    mCompassTimestamp = *((long long*) (rdata));
4012                    readCounter -= BYTES_PER_SENSOR_PACKET;
4013                }
4014            }
4015#else
4016            readCounter -= BYTES_PER_SENSOR;
4017#endif
4018        }
4019#ifdef ENABLE_PRESSURE
4020        else if (data_format == DATA_FORMAT_PRESSURE) {
4021            LOGV_IF(ENG_VERBOSE && INPUT_DATA, "PRESSURE DETECTED:0x%x", data_format);
4022            if (readCounter >= BYTES_QUAT_DATA) {
4023                if (mPressureSensor->isIntegrated()) {
4024                    mCachedPressureData =
4025                        ((*((short *)(rdata + 4))) << 16) +
4026                        (*((unsigned short *) (rdata + 6)));
4027                    rdata += BYTES_PER_SENSOR;
4028                    mPressureTimestamp = *((long long*) (rdata));
4029                    if (mCachedPressureData != 0) {
4030                        mask |= DATA_FORMAT_PRESSURE;
4031                    }
4032                    readCounter -= BYTES_PER_SENSOR_PACKET;
4033                }
4034            } else{
4035                doneFlag = 1;
4036            }
4037        }
4038#endif
4039
4040        if(doneFlag == 0) {
4041            rdata += BYTES_PER_SENSOR;
4042            LOGV_IF(ENG_VERBOSE && INPUT_DATA, "HAL: input data doneFlag is zero, readCounter=%d", (int)readCounter);
4043        }
4044        else {
4045            LOGV_IF(ENG_VERBOSE && INPUT_DATA, "HAL: input data doneFlag is set, readCounter=%d", (int)readCounter);
4046        }
4047
4048        /* read ahead and store left over data if any */
4049        if (readCounter != 0) {
4050            int currentBufferCounter = 0;
4051            LOGV_IF(0, "Not enough data readCounter=%d, expected nbyte=%d, rsize=%d", (int)readCounter, nbyte, (int)rsize);
4052            memset(mLeftOverBuffer, 0, sizeof(mLeftOverBuffer));
4053            /* check for end markers, don't save */
4054            data_format = *((short *) (rdata));
4055            if ((data_format == DATA_FORMAT_MARKER) || (data_format == DATA_FORMAT_EMPTY_MARKER)) {
4056				LOGV_IF(ENG_VERBOSE && INPUT_DATA, "s MARKER DETECTED:0x%x", data_format);
4057				rdata += BYTES_PER_SENSOR;
4058				readCounter -= BYTES_PER_SENSOR;
4059				if (!mFlushSensorEnabledVector.isEmpty()) {
4060					mFlushBatchSet = 1;
4061				}
4062				mDataMarkerDetected = 1;
4063				mSkipReadEvents = 1;
4064				if (readCounter == 0) {
4065					mLeftOverBufferSize = 0;
4066					if(doneFlag != 0) {
4067						return;
4068					}
4069				}
4070			}
4071			memcpy(mLeftOverBuffer, rdata, readCounter);
4072			LOGV_IF(0,
4073					"HAL:input store rdata=:%d, %d, %d, %d,%d, %d, %d, %d,%d, "
4074					"%d, %d, %d,%d, %d, %d, %d\n",
4075					mLeftOverBuffer[0], mLeftOverBuffer[1], mLeftOverBuffer[2], mLeftOverBuffer[3],
4076					mLeftOverBuffer[4], mLeftOverBuffer[5], mLeftOverBuffer[6], mLeftOverBuffer[7],
4077					mLeftOverBuffer[8], mLeftOverBuffer[9], mLeftOverBuffer[10], mLeftOverBuffer[11],
4078					mLeftOverBuffer[12],mLeftOverBuffer[13],mLeftOverBuffer[14], mLeftOverBuffer[15]);
4079
4080            mLeftOverBufferSize = readCounter;
4081            readCounter = 0;
4082            LOGV_IF(0, "Stored number of bytes:%d", mLeftOverBufferSize);
4083        } else {
4084            /* reset count since this is the last packet for the data set */
4085            readCounter = 0;
4086            mLeftOverBufferSize = 0;
4087        }
4088
4089        /* take the latest timestamp */
4090        if (mask & DATA_FORMAT_STEP) {
4091        /* work around driver output duplicate step detector bit */
4092            if (latestTimestamp > mStepSensorTimestamp) {
4093                mStepSensorTimestamp = latestTimestamp;
4094                LOGV_IF(INPUT_DATA,
4095                    "HAL:input build step: 1 - %lld", mStepSensorTimestamp);
4096            } else {
4097                mPedUpdate = 0;
4098            }
4099            // cancels step bit
4100            mask &= (~DATA_FORMAT_STEP);
4101        }
4102
4103        /* handle data read */
4104        if (mask == DATA_FORMAT_GYRO) {
4105            /* batch mode does not batch temperature */
4106            /* disable temperature read */
4107            if (!(mFeatureActiveMask & INV_DMP_BATCH_MODE)) {
4108                // send down temperature every 0.5 seconds
4109                // with timestamp measured in "driver" layer
4110                if(mGyroSensorTimestamp - mTempCurrentTime >= 500000000LL) {
4111                    mTempCurrentTime = mGyroSensorTimestamp;
4112                    long long temperature[2];
4113                    if(inv_read_temperature(temperature) == 0) {
4114                        LOGV_IF(INPUT_DATA,
4115                        "HAL:input inv_read_temperature = %lld, timestamp= %lld",
4116                        temperature[0], temperature[1]);
4117                        inv_build_temp(temperature[0], temperature[1]);
4118                     }
4119#ifdef TESTING
4120                    long bias[3], temp, temp_slope[3];
4121                    inv_get_mpl_gyro_bias(bias, &temp);
4122                    inv_get_gyro_ts(temp_slope);
4123                    LOGI("T: %.3f "
4124                     "GB: %+13f %+13f %+13f "
4125                     "TS: %+13f %+13f %+13f "
4126                     "\n",
4127                     (float)temperature[0] / 65536.f,
4128                     (float)bias[0] / 65536.f / 16.384f,
4129                     (float)bias[1] / 65536.f / 16.384f,
4130                     (float)bias[2] / 65536.f / 16.384f,
4131                     temp_slope[0] / 65536.f,
4132                     temp_slope[1] / 65536.f,
4133                     temp_slope[2] / 65536.f);
4134#endif
4135                }
4136            }
4137            mPendingMask |= 1 << Gyro;
4138            mPendingMask |= 1 << RawGyro;
4139
4140            inv_build_gyro(mCachedGyroData, mGyroSensorTimestamp);
4141            LOGV_IF(INPUT_DATA,
4142                   "HAL:input inv_build_gyro: %+8d %+8d %+8d - %lld",
4143                    mCachedGyroData[0], mCachedGyroData[1],
4144                    mCachedGyroData[2], mGyroSensorTimestamp);
4145            latestTimestamp = mGyroSensorTimestamp;
4146        }
4147
4148        if (mask == DATA_FORMAT_ACCEL) {
4149            mPendingMask |= 1 << Accelerometer;
4150            inv_build_accel(mCachedAccelData, 0, mAccelSensorTimestamp);
4151            LOGV_IF(INPUT_DATA,
4152               "HAL:input inv_build_accel: %+8ld %+8ld %+8ld - %lld",
4153                mCachedAccelData[0], mCachedAccelData[1],
4154                mCachedAccelData[2], mAccelSensorTimestamp);
4155                /* remember inital 6 axis quaternion */
4156                inv_time_t tempTimestamp;
4157                inv_get_6axis_quaternion(mInitial6QuatValue, &tempTimestamp);
4158                if (mInitial6QuatValue[0] != 0 && mInitial6QuatValue[1] != 0 &&
4159                        mInitial6QuatValue[2] != 0 && mInitial6QuatValue[3] != 0) {
4160                    mInitial6QuatValueAvailable = 1;
4161                    LOGV_IF(INPUT_DATA && ENG_VERBOSE,
4162                        "HAL:input build 6q init: %+8ld %+8ld %+8ld %+8ld",
4163                        mInitial6QuatValue[0], mInitial6QuatValue[1],
4164                        mInitial6QuatValue[2], mInitial6QuatValue[3]);
4165                }
4166            latestTimestamp = mAccelSensorTimestamp;
4167        }
4168
4169        if (mask  == DATA_FORMAT_COMPASS_OF) {
4170            /* compass overflow detected */
4171            /* reset compass algorithm */
4172            int status = 0;
4173            inv_build_compass(mCachedCompassData, status,
4174                              mCompassTimestamp);
4175            LOGV_IF(INPUT_DATA,
4176                    "HAL:input inv_build_compass_of: %+8ld %+8ld %+8ld - %lld",
4177                    mCachedCompassData[0], mCachedCompassData[1],
4178                    mCachedCompassData[2], mCompassTimestamp);
4179            resetCompass();
4180        }
4181
4182        if ((mask == DATA_FORMAT_COMPASS) && mCompassSensor->isIntegrated()) {
4183            int status = 0;
4184            if (mCompassSensor->providesCalibration()) {
4185                status = mCompassSensor->getAccuracy();
4186                status |= INV_CALIBRATED;
4187            }
4188            inv_build_compass(mCachedCompassData, status,
4189                              mCompassTimestamp);
4190            LOGV_IF(INPUT_DATA,
4191                    "HAL:input inv_build_compass: %+8ld %+8ld %+8ld - %lld",
4192                    mCachedCompassData[0], mCachedCompassData[1],
4193                    mCachedCompassData[2], mCompassTimestamp);
4194            latestTimestamp = mCompassTimestamp;
4195        }
4196
4197        if (mask == DATA_FORMAT_QUAT) {
4198            /* if bias was applied to DMP bias,
4199               set status bits to disable gyro bias cal */
4200            int status = 0;
4201            if (mGyroBiasApplied == true) {
4202                LOGV_IF(INPUT_DATA && ENG_VERBOSE, "HAL:input dmp bias is used");
4203                status |= INV_BIAS_APPLIED;
4204            }
4205            status |= INV_CALIBRATED | INV_QUAT_3AXIS | INV_QUAT_3ELEMENT; /* default 32 (16/32bits) */
4206            inv_build_quat(mCachedQuaternionData,
4207                       status,
4208                       mQuatSensorTimestamp);
4209            LOGV_IF(INPUT_DATA,
4210                    "HAL:input inv_build_quat-3x: %+8ld %+8ld %+8ld - %lld",
4211                    mCachedQuaternionData[0], mCachedQuaternionData[1],
4212                    mCachedQuaternionData[2],
4213                    mQuatSensorTimestamp);
4214            latestTimestamp = mQuatSensorTimestamp;
4215        }
4216
4217        if (mask == DATA_FORMAT_6_AXIS) {
4218            /* if bias was applied to DMP bias,
4219               set status bits to disable gyro bias cal */
4220            int status = 0;
4221            if (mGyroBiasApplied == true) {
4222                LOGV_IF(INPUT_DATA && ENG_VERBOSE, "HAL:input dmp bias is used");
4223                status |= INV_QUAT_6AXIS;
4224            }
4225            status |= INV_CALIBRATED | INV_QUAT_6AXIS | INV_QUAT_3ELEMENT; /* default 32 (16/32bits) */
4226            inv_build_quat(mCached6AxisQuaternionData,
4227                       status,
4228                       mQuatSensorTimestamp);
4229            LOGV_IF(INPUT_DATA,
4230                    "HAL:input inv_build_quat-6x: %+8ld %+8ld %+8ld - %lld",
4231                    mCached6AxisQuaternionData[0], mCached6AxisQuaternionData[1],
4232                    mCached6AxisQuaternionData[2], mQuatSensorTimestamp);
4233            latestTimestamp = mQuatSensorTimestamp;
4234        }
4235
4236        if (mask == DATA_FORMAT_PED_QUAT) {
4237            /* if bias was applied to DMP bias,
4238               set status bits to disable gyro bias cal */
4239            int status = 0;
4240            if (mGyroBiasApplied == true) {
4241                LOGV_IF(INPUT_DATA && ENG_VERBOSE,
4242                        "HAL:input dmp bias is used");
4243                status |= INV_QUAT_6AXIS;
4244            }
4245            status |= INV_CALIBRATED | INV_QUAT_6AXIS | INV_QUAT_3ELEMENT; /* default 32 (16/32bits) */
4246            mCachedPedQuaternionData[0] = mCachedPedQuaternionData[0] << 16;
4247            mCachedPedQuaternionData[1] = mCachedPedQuaternionData[1] << 16;
4248            mCachedPedQuaternionData[2] = mCachedPedQuaternionData[2] << 16;
4249            inv_build_quat(mCachedPedQuaternionData,
4250                       status,
4251                       mQuatSensorTimestamp);
4252
4253            LOGV_IF(INPUT_DATA,
4254                    "HAL:HAL:input inv_build_quat-ped_6x: %+8ld %+8ld %+8ld - %lld",
4255                    mCachedPedQuaternionData[0], mCachedPedQuaternionData[1],
4256                    mCachedPedQuaternionData[2], mQuatSensorTimestamp);
4257            latestTimestamp = mQuatSensorTimestamp;
4258        }
4259
4260#ifdef ENABLE_PRESSURE
4261        if ((mask ==DATA_FORMAT_PRESSURE) && mPressureSensor->isIntegrated()) {
4262            int status = 0;
4263            if (mLocalSensorMask & INV_ONE_AXIS_PRESSURE) {
4264                latestTimestamp = mPressureTimestamp;
4265                mPressureUpdate = 1;
4266                inv_build_pressure(mCachedPressureData,
4267                            status,
4268                            mPressureTimestamp);
4269                LOGV_IF(INPUT_DATA,
4270                    "HAL:input inv_build_pressure: %+8ld - %lld",
4271                    mCachedPressureData, mPressureTimestamp);
4272            }
4273        }
4274#endif
4275   }    //while end
4276}
4277
4278int MPLSensor::checkValidHeader(unsigned short data_format)
4279{
4280    LOGV_IF(ENG_VERBOSE && INPUT_DATA, "check data_format=%x", data_format);
4281
4282    if(data_format == DATA_FORMAT_STEP)
4283        return 1;
4284
4285    if(data_format & DATA_FORMAT_STEP) {
4286        data_format &= (~DATA_FORMAT_STEP);
4287    }
4288
4289    if ((data_format == DATA_FORMAT_PED_STANDALONE) ||
4290        (data_format == DATA_FORMAT_PED_QUAT) ||
4291        (data_format == DATA_FORMAT_6_AXIS) ||
4292        (data_format == DATA_FORMAT_QUAT) ||
4293        (data_format == DATA_FORMAT_COMPASS) ||
4294        (data_format == DATA_FORMAT_GYRO) ||
4295        (data_format == DATA_FORMAT_ACCEL) ||
4296        (data_format == DATA_FORMAT_PRESSURE) ||
4297        (data_format == DATA_FORMAT_EMPTY_MARKER) ||
4298        (data_format == DATA_FORMAT_MARKER) ||
4299        (data_format == DATA_FORMAT_COMPASS_OF))
4300            return 1;
4301     else {
4302        LOGV_IF(ENG_VERBOSE, "bad data_format = %x", data_format);
4303        return 0;
4304    }
4305}
4306
4307/* use for both MPUxxxx and third party compass */
4308void MPLSensor::buildCompassEvent(void)
4309{
4310    VHANDLER_LOG;
4311
4312    int done = 0;
4313
4314    // pthread_mutex_lock(&mMplMutex);
4315    // pthread_mutex_lock(&mHALMutex);
4316
4317    done = mCompassSensor->readSample(mCachedCompassData, &mCompassTimestamp);
4318    if(mCompassSensor->isYasCompass()) {
4319        if (mCompassSensor->checkCoilsReset() == 1) {
4320           //Reset relevant compass settings
4321           resetCompass();
4322        }
4323    }
4324    if (done > 0) {
4325        int status = 0;
4326        if (mCompassSensor->providesCalibration()) {
4327            status = mCompassSensor->getAccuracy();
4328            status |= INV_CALIBRATED;
4329        }
4330        if (mLocalSensorMask & INV_THREE_AXIS_COMPASS) {
4331            inv_build_compass(mCachedCompassData, status,
4332                              mCompassTimestamp);
4333            LOGV_IF(INPUT_DATA,
4334                    "HAL:input inv_build_compass: %+8ld %+8ld %+8ld - %lld",
4335                    mCachedCompassData[0], mCachedCompassData[1],
4336                    mCachedCompassData[2], mCompassTimestamp);
4337            mSkipReadEvents = 0;
4338        }
4339    }
4340
4341    // pthread_mutex_unlock(&mMplMutex);
4342    // pthread_mutex_unlock(&mHALMutex);
4343}
4344
4345int MPLSensor::resetCompass(void)
4346{
4347    VFUNC_LOG;
4348
4349    //Reset compass cal if enabled
4350    if (mMplFeatureActiveMask & INV_COMPASS_CAL) {
4351       LOGV_IF(EXTRA_VERBOSE, "HAL:Reset compass cal");
4352       inv_init_vector_compass_cal();
4353       inv_init_magnetic_disturbance();
4354       inv_vector_compass_cal_sensitivity(3);
4355    }
4356
4357    //Reset compass fit if enabled
4358    if (mMplFeatureActiveMask & INV_COMPASS_FIT) {
4359       LOGV_IF(EXTRA_VERBOSE, "HAL:Reset compass fit");
4360       inv_init_compass_fit();
4361    }
4362
4363    return 0;
4364}
4365
4366int MPLSensor::getFd(void) const
4367{
4368    VFUNC_LOG;
4369    LOGV_IF(EXTRA_VERBOSE, "getFd returning %d", iio_fd);
4370    return iio_fd;
4371}
4372
4373int MPLSensor::getAccelFd(void) const
4374{
4375    VFUNC_LOG;
4376    LOGV_IF(EXTRA_VERBOSE, "getAccelFd returning %d", accel_fd);
4377    return accel_fd;
4378}
4379
4380int MPLSensor::getCompassFd(void) const
4381{
4382    VFUNC_LOG;
4383    int fd = mCompassSensor->getFd();
4384    LOGV_IF(EXTRA_VERBOSE, "getCompassFd returning %d", fd);
4385    return fd;
4386}
4387
4388int MPLSensor::turnOffAccelFifo(void)
4389{
4390    VFUNC_LOG;
4391    int i, res = 0, tempFd;
4392    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
4393                        0, mpu.accel_fifo_enable, getTimestamp());
4394    res += write_sysfs_int(mpu.accel_fifo_enable, 0);
4395    return res;
4396}
4397
4398int MPLSensor::turnOffGyroFifo(void)
4399{
4400    VFUNC_LOG;
4401    int i, res = 0, tempFd;
4402    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
4403                        0, mpu.gyro_fifo_enable, getTimestamp());
4404    res += write_sysfs_int(mpu.gyro_fifo_enable, 0);
4405    return res;
4406}
4407
4408int MPLSensor::enableDmpOrientation(int en)
4409{
4410    VFUNC_LOG;
4411    int res = 0;
4412    int enabled_sensors = mEnabled;
4413
4414    if (isMpuNonDmp())
4415        return res;
4416
4417    // reset master enable
4418    res = masterEnable(0);
4419    if (res < 0)
4420        return res;
4421
4422    if (en == 1) {
4423        // Enable DMP orientation
4424        LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
4425                en, mpu.display_orientation_on, getTimestamp());
4426        if (write_sysfs_int(mpu.display_orientation_on, en) < 0) {
4427            LOGE("HAL:ERR can't enable Android orientation");
4428            res = -1;	// indicate an err
4429            return res;
4430        }
4431
4432        // enable accel engine
4433        res = enableAccel(1);
4434        if (res < 0)
4435            return res;
4436
4437        // disable accel FIFO
4438        if (!(mLocalSensorMask & mMasterSensorMask & INV_THREE_AXIS_ACCEL)) {
4439            res = turnOffAccelFifo();
4440            if (res < 0)
4441                return res;
4442        }
4443
4444        if (!mEnabled){
4445            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
4446                       1, mpu.dmp_event_int_on, getTimestamp());
4447            if (write_sysfs_int(mpu.dmp_event_int_on, en) < 0) {
4448                res = -1;
4449                LOGE("HAL:ERR can't enable DMP event interrupt");
4450            }
4451        }
4452
4453        mFeatureActiveMask |= INV_DMP_DISPL_ORIENTATION;
4454        LOGV_IF(ENG_VERBOSE, "mFeatureActiveMask=%016llx", mFeatureActiveMask);
4455    } else {
4456        mFeatureActiveMask &= ~INV_DMP_DISPL_ORIENTATION;
4457
4458        if (mFeatureActiveMask == 0) {
4459            // disable accel engine
4460            if (!(mLocalSensorMask & mMasterSensorMask
4461                    & INV_THREE_AXIS_ACCEL)) {
4462                res = enableAccel(0);
4463                if (res < 0)
4464                    return res;
4465            }
4466        }
4467
4468        if (mEnabled){
4469            LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
4470                       en, mpu.dmp_event_int_on, getTimestamp());
4471            if (write_sysfs_int(mpu.dmp_event_int_on, en) < 0) {
4472                res = -1;
4473                LOGE("HAL:ERR can't enable DMP event interrupt");
4474            }
4475        }
4476        LOGV_IF(ENG_VERBOSE, "mFeatureActiveMask=%016llx", mFeatureActiveMask);
4477    }
4478
4479    if ((res = computeAndSetDmpState()) < 0)
4480        return res;
4481
4482    if (en || mEnabled || mFeatureActiveMask) {
4483        res = masterEnable(1);
4484    }
4485    return res;
4486}
4487
4488int MPLSensor::openDmpOrientFd(void)
4489{
4490    VFUNC_LOG;
4491
4492    if (!isDmpDisplayOrientationOn() || dmp_orient_fd >= 0) {
4493        LOGV_IF(PROCESS_VERBOSE,
4494                "HAL:DMP display orientation disabled or file desc opened");
4495        return 0;
4496    }
4497
4498    dmp_orient_fd = open(mpu.event_display_orientation, O_RDONLY| O_NONBLOCK);
4499    if (dmp_orient_fd < 0) {
4500        LOGE("HAL:ERR couldn't open dmpOrient node");
4501        return -1;
4502    } else {
4503        LOGV_IF(PROCESS_VERBOSE,
4504                "HAL:dmp_orient_fd opened : %d", dmp_orient_fd);
4505        return 0;
4506    }
4507}
4508
4509int MPLSensor::closeDmpOrientFd(void)
4510{
4511    VFUNC_LOG;
4512    if (dmp_orient_fd >= 0)
4513        close(dmp_orient_fd);
4514    return 0;
4515}
4516
4517int MPLSensor::dmpOrientHandler(int orient)
4518{
4519    VFUNC_LOG;
4520    LOGV_IF(PROCESS_VERBOSE, "HAL:orient %x", orient);
4521    return 0;
4522}
4523
4524int MPLSensor::readDmpOrientEvents(sensors_event_t* data, int count)
4525{
4526    VFUNC_LOG;
4527
4528    char dummy[4];
4529    int screen_orientation = 0;
4530    FILE *fp;
4531
4532    fp = fopen(mpu.event_display_orientation, "r");
4533    if (fp == NULL) {
4534        LOGE("HAL:cannot open event_display_orientation");
4535        return 0;
4536    } else {
4537        if (fscanf(fp, "%d\n", &screen_orientation) < 0 || fclose(fp) < 0)
4538        {
4539            LOGE("HAL:cannot write event_display_orientation");
4540        }
4541    }
4542
4543    int numEventReceived = 0;
4544
4545    if (mDmpOrientationEnabled && count > 0) {
4546        sensors_event_t temp;
4547
4548        temp.acceleration.x = 0;
4549        temp.acceleration.y = 0;
4550        temp.acceleration.z = 0;
4551        temp.version = sizeof(sensors_event_t);
4552        temp.sensor = ID_SO;
4553        temp.acceleration.status
4554            = SENSOR_STATUS_UNRELIABLE;
4555#ifdef ENABLE_DMP_SCREEN_AUTO_ROTATION
4556        temp.type = SENSOR_TYPE_SCREEN_ORIENTATION;
4557        temp.screen_orientation = screen_orientation;
4558#endif
4559        struct timespec ts;
4560        clock_gettime(CLOCK_MONOTONIC, &ts);
4561        temp.timestamp = (int64_t) ts.tv_sec * 1000000000 + ts.tv_nsec;
4562
4563        *data++ = temp;
4564        count--;
4565        numEventReceived++;
4566    }
4567
4568    // read dummy data per driver's request
4569    dmpOrientHandler(screen_orientation);
4570    read(dmp_orient_fd, dummy, 4);
4571
4572    return numEventReceived;
4573}
4574
4575int MPLSensor::getDmpOrientFd(void)
4576{
4577    VFUNC_LOG;
4578
4579    LOGV_IF(EXTRA_VERBOSE, "getDmpOrientFd returning %d", dmp_orient_fd);
4580    return dmp_orient_fd;
4581
4582}
4583
4584int MPLSensor::checkDMPOrientation(void)
4585{
4586    VFUNC_LOG;
4587    return ((mFeatureActiveMask & INV_DMP_DISPL_ORIENTATION) ? 1 : 0);
4588}
4589
4590int MPLSensor::getDmpRate(int64_t *wanted)
4591{
4592    VFUNC_LOG;
4593
4594      // set DMP output rate to FIFO
4595      if(mDmpOn == 1) {
4596        setQuaternionRate(*wanted);
4597        if (mFeatureActiveMask & INV_DMP_BATCH_MODE) {
4598            set6AxisQuaternionRate(*wanted);
4599            setPedQuaternionRate(*wanted);
4600        }
4601        // DMP running rate must be @ 200Hz
4602        *wanted= RATE_200HZ;
4603        LOGV_IF(PROCESS_VERBOSE,
4604                "HAL:DMP rate= %.2f Hz", 1000000000.f / *wanted);
4605    }
4606    return 0;
4607}
4608
4609int MPLSensor::getPollTime(void)
4610{
4611    VFUNC_LOG;
4612    return mPollTime;
4613}
4614
4615int MPLSensor::getStepCountPollTime(void)
4616{
4617    VFUNC_LOG;
4618    /* clamped to 1ms? as spec, still rather large */
4619    return 100;
4620}
4621
4622bool MPLSensor::hasStepCountPendingEvents(void)
4623{
4624    VFUNC_LOG;
4625    if (mDmpStepCountEnabled) {
4626        struct timespec t_now;
4627        int64_t interval = 0;
4628
4629        clock_gettime(CLOCK_MONOTONIC, &t_now);
4630        interval = ((int64_t(t_now.tv_sec) * 1000000000LL + t_now.tv_nsec) -
4631                    (int64_t(mt_pre.tv_sec) * 1000000000LL + mt_pre.tv_nsec));
4632
4633        if (interval < mStepCountPollTime) {
4634            LOGV_IF(0,
4635                    "Step Count interval elapsed: %lld, triggered: %lld",
4636                    interval, mStepCountPollTime);
4637            return false;
4638        } else {
4639            clock_gettime(CLOCK_MONOTONIC, &mt_pre);
4640            LOGV_IF(0, "Step Count previous time: %ld ms",
4641                    mt_pre.tv_nsec / 1000);
4642            return true;
4643        }
4644    }
4645    return false;
4646}
4647
4648bool MPLSensor::hasPendingEvents(void) const
4649{
4650    VFUNC_LOG;
4651    // if we are using the polling workaround, force the main
4652    // loop to check for data every time
4653    return (mPollTime != -1);
4654}
4655
4656int MPLSensor::inv_read_temperature(long long *data)
4657{
4658    VHANDLER_LOG;
4659
4660    int count = 0;
4661    char raw_buf[40];
4662    long raw = 0;
4663
4664    long long timestamp = 0;
4665
4666    memset(raw_buf, 0, sizeof(raw_buf));
4667    count = read_attribute_sensor(gyro_temperature_fd, raw_buf,
4668                                  sizeof(raw_buf));
4669    if(count < 1) {
4670        LOGE("HAL:error reading gyro temperature");
4671        return -1;
4672    }
4673
4674    count = sscanf(raw_buf, "%ld%lld", &raw, &timestamp);
4675
4676    if(count < 0) {
4677        return -1;
4678    }
4679
4680    LOGV_IF(ENG_VERBOSE && INPUT_DATA,
4681            "HAL:temperature raw = %ld, timestamp = %lld, count = %d",
4682            raw, timestamp, count);
4683    data[0] = raw;
4684    data[1] = timestamp;
4685
4686    return 0;
4687}
4688
4689int MPLSensor::inv_read_dmp_state(int fd)
4690{
4691    VFUNC_LOG;
4692
4693    if(fd < 0)
4694        return -1;
4695
4696    int count = 0;
4697    char raw_buf[10];
4698    short raw = 0;
4699
4700    memset(raw_buf, 0, sizeof(raw_buf));
4701    count = read_attribute_sensor(fd, raw_buf, sizeof(raw_buf));
4702    if(count < 1) {
4703        LOGE("HAL:error reading dmp state");
4704        close(fd);
4705        return -1;
4706    }
4707    count = sscanf(raw_buf, "%hd", &raw);
4708    if(count < 0) {
4709        LOGE("HAL:dmp state data is invalid");
4710        close(fd);
4711        return -1;
4712    }
4713    LOGV_IF(EXTRA_VERBOSE, "HAL:dmp state = %d, count = %d", raw, count);
4714    close(fd);
4715    return (int)raw;
4716}
4717
4718int MPLSensor::inv_read_sensor_bias(int fd, long *data)
4719{
4720    VFUNC_LOG;
4721
4722    if(fd == -1) {
4723        return -1;
4724    }
4725
4726    char buf[50];
4727    char x[15], y[15], z[15];
4728
4729    memset(buf, 0, sizeof(buf));
4730    int count = read_attribute_sensor(fd, buf, sizeof(buf));
4731    if(count < 1) {
4732        LOGE("HAL:Error reading gyro bias");
4733        return -1;
4734    }
4735    count = sscanf(buf, "%[^','],%[^','],%[^',']", x, y, z);
4736    if(count) {
4737        /* scale appropriately for MPL */
4738        LOGV_IF(ENG_VERBOSE,
4739                "HAL:pre-scaled bias: X:Y:Z (%ld, %ld, %ld)",
4740                atol(x), atol(y), atol(z));
4741
4742        data[0] = (long)(atol(x) / 10000 * (1L << 16));
4743        data[1] = (long)(atol(y) / 10000 * (1L << 16));
4744        data[2] = (long)(atol(z) / 10000 * (1L << 16));
4745
4746        LOGV_IF(ENG_VERBOSE,
4747                "HAL:scaled bias: X:Y:Z (%ld, %ld, %ld)",
4748                data[0], data[1], data[2]);
4749    }
4750    return 0;
4751}
4752
4753/** fill in the sensor list based on which sensors are configured.
4754 *  return the number of configured sensors.
4755 *  parameter list must point to a memory region of at least 7*sizeof(sensor_t)
4756 *  parameter len gives the length of the buffer pointed to by list
4757 */
4758int MPLSensor::populateSensorList(struct sensor_t *list, int len)
4759{
4760    VFUNC_LOG;
4761
4762    int numsensors;
4763
4764    if(len <
4765        (int)((sizeof(sBaseSensorList) / sizeof(sensor_t)) * sizeof(sensor_t))) {
4766        LOGE("HAL:sensor list too small, not populating.");
4767        return -(sizeof(sBaseSensorList) / sizeof(sensor_t));
4768    }
4769
4770    /* fill in the base values */
4771    memcpy(list, sBaseSensorList,
4772           sizeof (struct sensor_t) * (sizeof(sBaseSensorList) / sizeof(sensor_t)));
4773
4774    /* first add gyro, accel and compass to the list */
4775
4776    /* fill in gyro/accel values */
4777    if(chip_ID == NULL) {
4778        LOGE("HAL:Can not get gyro/accel id");
4779    }
4780    fillGyro(chip_ID, list);
4781    fillAccel(chip_ID, list);
4782
4783    // TODO: need fixes for unified HAL and 3rd-party solution
4784    mCompassSensor->fillList(&list[MagneticField]);
4785    mCompassSensor->fillList(&list[RawMagneticField]);
4786#ifdef ENABLE_PRESSURE
4787    if (mPressureSensor != NULL) {
4788        mPressureSensor->fillList(&list[Pressure]);
4789    }
4790#endif
4791
4792    if(1) {
4793        numsensors = (sizeof(sBaseSensorList) / sizeof(sensor_t));
4794        /* all sensors will be added to the list
4795           fill in orientation values */
4796        fillOrientation(list);
4797        /* fill in rotation vector values */
4798        fillRV(list);
4799        /* fill in game rotation vector values */
4800        fillGRV(list);
4801        /* fill in gravity values */
4802        fillGravity(list);
4803        /* fill in Linear accel values */
4804        fillLinearAccel(list);
4805        /* fill in Significant motion values */
4806        fillSignificantMotion(list);
4807#ifdef ENABLE_DMP_SCREEN_AUTO_ROTATION
4808        /* fill in screen orientation values */
4809        fillScreenOrientation(list);
4810#endif
4811    } else {
4812        /* no 9-axis sensors, zero fill that part of the list */
4813        numsensors = 3;
4814        memset(list + 3, 0, 4 * sizeof(struct sensor_t));
4815    }
4816
4817    return numsensors;
4818}
4819
4820void MPLSensor::fillAccel(const char* accel, struct sensor_t *list)
4821{
4822    VFUNC_LOG;
4823
4824    if (accel) {
4825        if(accel != NULL && strcmp(accel, "BMA250") == 0) {
4826            list[Accelerometer].maxRange = ACCEL_BMA250_RANGE;
4827            list[Accelerometer].resolution = ACCEL_BMA250_RESOLUTION;
4828            list[Accelerometer].power = ACCEL_BMA250_POWER;
4829            list[Accelerometer].minDelay = ACCEL_BMA250_MINDELAY;
4830            return;
4831        } else if (accel != NULL && strcmp(accel, "MPU6050") == 0) {
4832            list[Accelerometer].maxRange = ACCEL_MPU6050_RANGE;
4833            list[Accelerometer].resolution = ACCEL_MPU6050_RESOLUTION;
4834            list[Accelerometer].power = ACCEL_MPU6050_POWER;
4835            list[Accelerometer].minDelay = ACCEL_MPU6050_MINDELAY;
4836            return;
4837        } else if (accel != NULL && strcmp(accel, "MPU6500") == 0) {
4838            list[Accelerometer].maxRange = ACCEL_MPU6500_RANGE;
4839            list[Accelerometer].resolution = ACCEL_MPU6500_RESOLUTION;
4840            list[Accelerometer].power = ACCEL_MPU6500_POWER;
4841            list[Accelerometer].minDelay = ACCEL_MPU6500_MINDELAY;
4842            return;
4843         } else if (accel != NULL && strcmp(accel, "MPU6515") == 0) {
4844            list[Accelerometer].maxRange = ACCEL_MPU6500_RANGE;
4845            list[Accelerometer].resolution = ACCEL_MPU6500_RESOLUTION;
4846            list[Accelerometer].power = ACCEL_MPU6500_POWER;
4847            list[Accelerometer].minDelay = ACCEL_MPU6500_MINDELAY;
4848            return;
4849        } else if (accel != NULL && strcmp(accel, "MPU6500") == 0) {
4850            list[Accelerometer].maxRange = ACCEL_MPU6500_RANGE;
4851            list[Accelerometer].resolution = ACCEL_MPU6500_RESOLUTION;
4852            list[Accelerometer].power = ACCEL_MPU6500_POWER;
4853            list[Accelerometer].minDelay = ACCEL_MPU6500_MINDELAY;
4854            return;
4855        } else if (accel != NULL && strcmp(accel, "MPU6500") == 0) {
4856            list[Accelerometer].maxRange = ACCEL_MPU6500_RANGE;
4857            list[Accelerometer].resolution = ACCEL_MPU6500_RESOLUTION;
4858            list[Accelerometer].power = ACCEL_MPU6500_POWER;
4859            list[Accelerometer].minDelay = ACCEL_MPU6500_MINDELAY;
4860            return;
4861        } else if (accel != NULL && strcmp(accel, "MPU9150") == 0) {
4862            list[Accelerometer].maxRange = ACCEL_MPU9150_RANGE;
4863            list[Accelerometer].resolution = ACCEL_MPU9150_RESOLUTION;
4864            list[Accelerometer].power = ACCEL_MPU9150_POWER;
4865            list[Accelerometer].minDelay = ACCEL_MPU9150_MINDELAY;
4866            return;
4867        } else if (accel != NULL && strcmp(accel, "MPU9250") == 0) {
4868            list[Accelerometer].maxRange = ACCEL_MPU9250_RANGE;
4869            list[Accelerometer].resolution = ACCEL_MPU9250_RESOLUTION;
4870            list[Accelerometer].power = ACCEL_MPU9250_POWER;
4871            list[Accelerometer].minDelay = ACCEL_MPU9250_MINDELAY;
4872            return;
4873        } else if (accel != NULL && strcmp(accel, "MPU9350") == 0) {
4874            list[Accelerometer].maxRange = ACCEL_MPU9350_RANGE;
4875            list[Accelerometer].resolution = ACCEL_MPU9350_RESOLUTION;
4876            list[Accelerometer].power = ACCEL_MPU9350_POWER;
4877            list[Accelerometer].minDelay = ACCEL_MPU9350_MINDELAY;
4878            return;
4879        }  else if (accel != NULL && strcmp(accel, "MPU3050") == 0) {
4880            list[Accelerometer].maxRange = ACCEL_BMA250_RANGE;
4881            list[Accelerometer].resolution = ACCEL_BMA250_RESOLUTION;
4882            list[Accelerometer].power = ACCEL_BMA250_POWER;
4883            list[Accelerometer].minDelay = ACCEL_BMA250_MINDELAY;
4884            return;
4885        }
4886    }
4887
4888    LOGE("HAL:unknown accel id %s -- "
4889         "params default to mpu6515 and might be wrong.",
4890         accel);
4891    list[Accelerometer].maxRange = ACCEL_MPU6500_RANGE;
4892    list[Accelerometer].resolution = ACCEL_MPU6500_RESOLUTION;
4893    list[Accelerometer].power = ACCEL_MPU6500_POWER;
4894    list[Accelerometer].minDelay = ACCEL_MPU6500_MINDELAY;
4895}
4896
4897void MPLSensor::fillGyro(const char* gyro, struct sensor_t *list)
4898{
4899    VFUNC_LOG;
4900
4901    if ( gyro != NULL && strcmp(gyro, "MPU3050") == 0) {
4902        list[Gyro].maxRange = GYRO_MPU3050_RANGE;
4903        list[Gyro].resolution = GYRO_MPU3050_RESOLUTION;
4904        list[Gyro].power = GYRO_MPU3050_POWER;
4905        list[Gyro].minDelay = GYRO_MPU3050_MINDELAY;
4906    } else if( gyro != NULL && strcmp(gyro, "MPU6050") == 0) {
4907        list[Gyro].maxRange = GYRO_MPU6050_RANGE;
4908        list[Gyro].resolution = GYRO_MPU6050_RESOLUTION;
4909        list[Gyro].power = GYRO_MPU6050_POWER;
4910        list[Gyro].minDelay = GYRO_MPU6050_MINDELAY;
4911    } else if( gyro != NULL && strcmp(gyro, "MPU6500") == 0) {
4912        list[Gyro].maxRange = GYRO_MPU6500_RANGE;
4913        list[Gyro].resolution = GYRO_MPU6500_RESOLUTION;
4914        list[Gyro].power = GYRO_MPU6500_POWER;
4915        list[Gyro].minDelay = GYRO_MPU6500_MINDELAY;
4916     } else if( gyro != NULL && strcmp(gyro, "MPU6515") == 0) {
4917        list[Gyro].maxRange = GYRO_MPU6500_RANGE;
4918        list[Gyro].resolution = GYRO_MPU6500_RESOLUTION;
4919        list[Gyro].power = GYRO_MPU6500_POWER;
4920        list[Gyro].minDelay = GYRO_MPU6500_MINDELAY;
4921    } else if( gyro != NULL && strcmp(gyro, "MPU9150") == 0) {
4922        list[Gyro].maxRange = GYRO_MPU9150_RANGE;
4923        list[Gyro].resolution = GYRO_MPU9150_RESOLUTION;
4924        list[Gyro].power = GYRO_MPU9150_POWER;
4925        list[Gyro].minDelay = GYRO_MPU9150_MINDELAY;
4926    } else if( gyro != NULL && strcmp(gyro, "MPU9250") == 0) {
4927        list[Gyro].maxRange = GYRO_MPU9250_RANGE;
4928        list[Gyro].resolution = GYRO_MPU9250_RESOLUTION;
4929        list[Gyro].power = GYRO_MPU9250_POWER;
4930        list[Gyro].minDelay = GYRO_MPU9250_MINDELAY;
4931    } else if( gyro != NULL && strcmp(gyro, "MPU9350") == 0) {
4932        list[Gyro].maxRange = GYRO_MPU9350_RANGE;
4933        list[Gyro].resolution = GYRO_MPU9350_RESOLUTION;
4934        list[Gyro].power = GYRO_MPU9350_POWER;
4935        list[Gyro].minDelay = GYRO_MPU9350_MINDELAY;
4936    } else {
4937        LOGE("HAL:unknown gyro id -- gyro params will be wrong.");
4938        LOGE("HAL:default to use mpu6515 params");
4939        list[Gyro].maxRange = GYRO_MPU6500_RANGE;
4940        list[Gyro].resolution = GYRO_MPU6500_RESOLUTION;
4941        list[Gyro].power = GYRO_MPU6500_POWER;
4942        list[Gyro].minDelay = GYRO_MPU6500_MINDELAY;
4943    }
4944
4945    list[RawGyro].maxRange = list[Gyro].maxRange;
4946    list[RawGyro].resolution = list[Gyro].resolution;
4947    list[RawGyro].power = list[Gyro].power;
4948    list[RawGyro].minDelay = list[Gyro].minDelay;
4949
4950    return;
4951}
4952
4953/* fillRV depends on values of gyro, accel and compass in the list */
4954void MPLSensor::fillRV(struct sensor_t *list)
4955{
4956    VFUNC_LOG;
4957
4958    /* compute power on the fly */
4959    list[RotationVector].power = list[Gyro].power +
4960                                 list[Accelerometer].power +
4961                                 list[MagneticField].power;
4962    list[RotationVector].resolution = .00001;
4963    list[RotationVector].maxRange = 1.0;
4964    list[RotationVector].minDelay = 5000;
4965
4966    return;
4967}
4968
4969/* fillGMRV depends on values of accel and mag in the list */
4970void MPLSensor::fillGMRV(struct sensor_t *list)
4971{
4972    VFUNC_LOG;
4973
4974    /* compute power on the fly */
4975    list[GeomagneticRotationVector].power = list[Accelerometer].power +
4976                                 list[MagneticField].power;
4977    list[GeomagneticRotationVector].resolution = .00001;
4978    list[GeomagneticRotationVector].maxRange = 1.0;
4979    list[GeomagneticRotationVector].minDelay = 5000;
4980
4981    return;
4982}
4983
4984/* fillGRV depends on values of gyro and accel in the list */
4985void MPLSensor::fillGRV(struct sensor_t *list)
4986{
4987    VFUNC_LOG;
4988
4989    /* compute power on the fly */
4990    list[GameRotationVector].power = list[Gyro].power +
4991                                 list[Accelerometer].power;
4992    list[GameRotationVector].resolution = .00001;
4993    list[GameRotationVector].maxRange = 1.0;
4994    list[GameRotationVector].minDelay = 5000;
4995
4996    return;
4997}
4998
4999void MPLSensor::fillOrientation(struct sensor_t *list)
5000{
5001    VFUNC_LOG;
5002
5003    list[Orientation].power = list[Gyro].power +
5004                              list[Accelerometer].power +
5005                              list[MagneticField].power;
5006    list[Orientation].resolution = .00001;
5007    list[Orientation].maxRange = 360.0;
5008    list[Orientation].minDelay = 5000;
5009
5010    return;
5011}
5012
5013void MPLSensor::fillGravity( struct sensor_t *list)
5014{
5015    VFUNC_LOG;
5016
5017    list[Gravity].power = list[Gyro].power +
5018                          list[Accelerometer].power +
5019                          list[MagneticField].power;
5020    list[Gravity].resolution = .00001;
5021    list[Gravity].maxRange = 9.81;
5022    list[Gravity].minDelay = 5000;
5023
5024    return;
5025}
5026
5027void MPLSensor::fillLinearAccel(struct sensor_t *list)
5028{
5029    VFUNC_LOG;
5030
5031    list[LinearAccel].power = list[Gyro].power +
5032                          list[Accelerometer].power +
5033                          list[MagneticField].power;
5034    list[LinearAccel].resolution = list[Accelerometer].resolution;
5035    list[LinearAccel].maxRange = list[Accelerometer].maxRange;
5036    list[LinearAccel].minDelay = 5000;
5037
5038    return;
5039}
5040
5041void MPLSensor::fillSignificantMotion(struct sensor_t *list)
5042{
5043    VFUNC_LOG;
5044
5045    list[SignificantMotion].power = list[Accelerometer].power;
5046    list[SignificantMotion].resolution = 1;
5047    list[SignificantMotion].maxRange = 1;
5048    list[SignificantMotion].minDelay = -1;
5049}
5050
5051#ifdef ENABLE_DMP_SCREEN_AUTO_ROTATION
5052void MPLSensor::fillScreenOrientation(struct sensor_t *list)
5053{
5054    VFUNC_LOG;
5055
5056    list[NumSensors].power = list[Accelerometer].power;
5057    list[NumSensors].resolution = 1;
5058    list[NumSensors].maxRange = 3;
5059    list[NumSensors].minDelay = 0;
5060}
5061#endif
5062
5063int MPLSensor::inv_init_sysfs_attributes(void)
5064{
5065    VFUNC_LOG;
5066
5067    unsigned char i = 0;
5068    char sysfs_path[MAX_SYSFS_NAME_LEN];
5069    char tbuf[2];
5070    char *sptr;
5071    char **dptr;
5072    int num;
5073
5074    memset(sysfs_path, 0, sizeof(sysfs_path));
5075
5076    sysfs_names_ptr =
5077            (char*)malloc(sizeof(char[MAX_SYSFS_ATTRB][MAX_SYSFS_NAME_LEN]));
5078    sptr = sysfs_names_ptr;
5079    if (sptr != NULL) {
5080        dptr = (char**)&mpu;
5081        do {
5082            *dptr++ = sptr;
5083            memset(sptr, 0, sizeof(sptr));
5084            sptr += sizeof(char[MAX_SYSFS_NAME_LEN]);
5085        } while (++i < MAX_SYSFS_ATTRB);
5086    } else {
5087        LOGE("HAL:couldn't alloc mem for sysfs paths");
5088        return -1;
5089    }
5090
5091    // get proper (in absolute) IIO path & build MPU's sysfs paths
5092    inv_get_sysfs_path(sysfs_path);
5093
5094    memcpy(mSysfsPath, sysfs_path, sizeof(sysfs_path));
5095    sprintf(mpu.key, "%s%s", sysfs_path, "/key");
5096    sprintf(mpu.chip_enable, "%s%s", sysfs_path, "/buffer/enable");
5097    sprintf(mpu.buffer_length, "%s%s", sysfs_path, "/buffer/length");
5098    sprintf(mpu.master_enable, "%s%s", sysfs_path, "/master_enable");
5099    sprintf(mpu.power_state, "%s%s", sysfs_path, "/power_state");
5100
5101    sprintf(mpu.in_timestamp_en, "%s%s", sysfs_path,
5102            "/scan_elements/in_timestamp_en");
5103    sprintf(mpu.in_timestamp_index, "%s%s", sysfs_path,
5104            "/scan_elements/in_timestamp_index");
5105    sprintf(mpu.in_timestamp_type, "%s%s", sysfs_path,
5106            "/scan_elements/in_timestamp_type");
5107
5108    sprintf(mpu.dmp_firmware, "%s%s", sysfs_path, "/dmp_firmware");
5109    sprintf(mpu.firmware_loaded, "%s%s", sysfs_path, "/firmware_loaded");
5110    sprintf(mpu.dmp_on, "%s%s", sysfs_path, "/dmp_on");
5111    sprintf(mpu.dmp_int_on, "%s%s", sysfs_path, "/dmp_int_on");
5112    sprintf(mpu.dmp_event_int_on, "%s%s", sysfs_path, "/dmp_event_int_on");
5113    sprintf(mpu.tap_on, "%s%s", sysfs_path, "/tap_on");
5114
5115    sprintf(mpu.self_test, "%s%s", sysfs_path, "/self_test");
5116
5117    sprintf(mpu.temperature, "%s%s", sysfs_path, "/temperature");
5118    sprintf(mpu.gyro_enable, "%s%s", sysfs_path, "/gyro_enable");
5119    sprintf(mpu.gyro_fifo_rate, "%s%s", sysfs_path, "/sampling_frequency");
5120    sprintf(mpu.gyro_orient, "%s%s", sysfs_path, "/gyro_matrix");
5121    sprintf(mpu.gyro_fifo_enable, "%s%s", sysfs_path, "/gyro_fifo_enable");
5122    sprintf(mpu.gyro_fsr, "%s%s", sysfs_path, "/in_anglvel_scale");
5123    sprintf(mpu.gyro_fifo_enable, "%s%s", sysfs_path, "/gyro_fifo_enable");
5124    sprintf(mpu.gyro_rate, "%s%s", sysfs_path, "/gyro_rate");
5125
5126    sprintf(mpu.accel_enable, "%s%s", sysfs_path, "/accel_enable");
5127    sprintf(mpu.accel_fifo_rate, "%s%s", sysfs_path, "/sampling_frequency");
5128    sprintf(mpu.accel_orient, "%s%s", sysfs_path, "/accel_matrix");
5129    sprintf(mpu.accel_fifo_enable, "%s%s", sysfs_path, "/accel_fifo_enable");
5130    sprintf(mpu.accel_rate, "%s%s", sysfs_path, "/accel_rate");
5131
5132#ifndef THIRD_PARTY_ACCEL //MPU3050
5133    sprintf(mpu.accel_fsr, "%s%s", sysfs_path, "/in_accel_scale");
5134
5135    // DMP uses these values
5136    sprintf(mpu.in_accel_x_dmp_bias, "%s%s", sysfs_path, "/in_accel_x_dmp_bias");
5137    sprintf(mpu.in_accel_y_dmp_bias, "%s%s", sysfs_path, "/in_accel_y_dmp_bias");
5138    sprintf(mpu.in_accel_z_dmp_bias, "%s%s", sysfs_path, "/in_accel_z_dmp_bias");
5139
5140    // MPU uses these values
5141    sprintf(mpu.in_accel_x_offset, "%s%s", sysfs_path, "/in_accel_x_offset");
5142    sprintf(mpu.in_accel_y_offset, "%s%s", sysfs_path, "/in_accel_y_offset");
5143    sprintf(mpu.in_accel_z_offset, "%s%s", sysfs_path, "/in_accel_z_offset");
5144    sprintf(mpu.in_accel_self_test_scale, "%s%s", sysfs_path, "/in_accel_self_test_scale");
5145#endif
5146
5147    // DMP uses these bias values
5148    sprintf(mpu.in_gyro_x_dmp_bias, "%s%s", sysfs_path, "/in_anglvel_x_dmp_bias");
5149    sprintf(mpu.in_gyro_y_dmp_bias, "%s%s", sysfs_path, "/in_anglvel_y_dmp_bias");
5150    sprintf(mpu.in_gyro_z_dmp_bias, "%s%s", sysfs_path, "/in_anglvel_z_dmp_bias");
5151
5152    // MPU uses these bias values
5153    sprintf(mpu.in_gyro_x_offset, "%s%s", sysfs_path, "/in_anglvel_x_offset");
5154    sprintf(mpu.in_gyro_y_offset, "%s%s", sysfs_path, "/in_anglvel_y_offset");
5155    sprintf(mpu.in_gyro_z_offset, "%s%s", sysfs_path, "/in_anglvel_z_offset");
5156    sprintf(mpu.in_gyro_self_test_scale, "%s%s", sysfs_path, "/in_anglvel_self_test_scale");
5157
5158    sprintf(mpu.three_axis_q_on, "%s%s", sysfs_path, "/three_axes_q_on"); //formerly quaternion_on
5159    sprintf(mpu.three_axis_q_rate, "%s%s", sysfs_path, "/three_axes_q_rate");
5160
5161    sprintf(mpu.ped_q_on, "%s%s", sysfs_path, "/ped_q_on");
5162    sprintf(mpu.ped_q_rate, "%s%s", sysfs_path, "/ped_q_rate");
5163
5164    sprintf(mpu.six_axis_q_on, "%s%s", sysfs_path, "/six_axes_q_on");
5165    sprintf(mpu.six_axis_q_rate, "%s%s", sysfs_path, "/six_axes_q_rate");
5166
5167    sprintf(mpu.six_axis_q_value, "%s%s", sysfs_path, "/six_axes_q_value");
5168
5169    sprintf(mpu.step_detector_on, "%s%s", sysfs_path, "/step_detector_on");
5170    sprintf(mpu.step_indicator_on, "%s%s", sysfs_path, "/step_indicator_on");
5171
5172    sprintf(mpu.display_orientation_on, "%s%s", sysfs_path,
5173            "/display_orientation_on");
5174    sprintf(mpu.event_display_orientation, "%s%s", sysfs_path,
5175            "/event_display_orientation");
5176
5177    sprintf(mpu.event_smd, "%s%s", sysfs_path,
5178            "/event_smd");
5179    sprintf(mpu.smd_enable, "%s%s", sysfs_path,
5180            "/smd_enable");
5181    sprintf(mpu.smd_delay_threshold, "%s%s", sysfs_path,
5182            "/smd_delay_threshold");
5183    sprintf(mpu.smd_delay_threshold2, "%s%s", sysfs_path,
5184            "/smd_delay_threshold2");
5185    sprintf(mpu.smd_threshold, "%s%s", sysfs_path,
5186            "/smd_threshold");
5187    sprintf(mpu.batchmode_timeout, "%s%s", sysfs_path,
5188            "/batchmode_timeout");
5189    sprintf(mpu.batchmode_wake_fifo_full_on, "%s%s", sysfs_path,
5190            "/batchmode_wake_fifo_full_on");
5191    sprintf(mpu.flush_batch, "%s%s", sysfs_path,
5192            "/flush_batch");
5193    sprintf(mpu.pedometer_on, "%s%s", sysfs_path,
5194            "/pedometer_on");
5195    sprintf(mpu.pedometer_int_on, "%s%s", sysfs_path,
5196            "/pedometer_int_on");
5197    sprintf(mpu.event_pedometer, "%s%s", sysfs_path,
5198            "/event_pedometer");
5199    sprintf(mpu.pedometer_steps, "%s%s", sysfs_path,
5200            "/pedometer_steps");
5201    sprintf(mpu.pedometer_step_thresh, "%s%s", sysfs_path,
5202            "/pedometer_step_thresh");
5203    sprintf(mpu.pedometer_counter, "%s%s", sysfs_path,
5204            "/pedometer_counter");
5205    sprintf(mpu.motion_lpa_on, "%s%s", sysfs_path,
5206            "/motion_lpa_on");
5207    return 0;
5208}
5209
5210//DMP support only for MPU6xxx/9xxx
5211bool MPLSensor::isMpuNonDmp(void)
5212{
5213    VFUNC_LOG;
5214    if (!strcmp(chip_ID, "mpu3050") || !strcmp(chip_ID, "MPU3050"))
5215        return true;
5216    else
5217        return false;
5218}
5219
5220int MPLSensor::isLowPowerQuatEnabled(void)
5221{
5222    VFUNC_LOG;
5223#ifdef ENABLE_LP_QUAT_FEAT
5224    return !isMpuNonDmp();
5225#else
5226    return 0;
5227#endif
5228}
5229
5230int MPLSensor::isDmpDisplayOrientationOn(void)
5231{
5232    VFUNC_LOG;
5233#ifdef ENABLE_DMP_DISPL_ORIENT_FEAT
5234    if (isMpuNonDmp())
5235        return 0;
5236    return 1;
5237#else
5238    return 0;
5239#endif
5240}
5241
5242/* these functions can be consolidated
5243with inv_convert_to_body_with_scale */
5244void MPLSensor::getCompassBias()
5245{
5246    VFUNC_LOG;
5247
5248
5249    long bias[3];
5250    long compassBias[3];
5251    unsigned short orient;
5252    signed char orientMtx[9];
5253    mCompassSensor->getOrientationMatrix(orientMtx);
5254    orient = inv_orientation_matrix_to_scalar(orientMtx);
5255
5256    /* Get Values from MPL */
5257    inv_get_compass_bias(bias);
5258    inv_convert_to_body(orient, bias, compassBias);
5259    LOGV_IF(HANDLER_DATA, "Mpl Compass Bias (HW unit) %ld %ld %ld", bias[0], bias[1], bias[2]);
5260    LOGV_IF(HANDLER_DATA, "Mpl Compass Bias (HW unit) (body) %ld %ld %ld", compassBias[0], compassBias[1], compassBias[2]);
5261    long compassSensitivity = inv_get_compass_sensitivity();
5262    if (compassSensitivity == 0) {
5263        compassSensitivity = mCompassScale;
5264    }
5265    for(int i=0; i<3; i++) {
5266        /* convert to uT */
5267        float temp = (float) compassSensitivity / (1L << 30);
5268        mCompassBias[i] =(float) (compassBias[i] * temp / 65536.f);
5269    }
5270
5271    return;
5272}
5273
5274void MPLSensor::getFactoryGyroBias()
5275{
5276    VFUNC_LOG;
5277
5278    /* Get Values from MPL */
5279    inv_get_gyro_bias(mFactoryGyroBias);
5280    LOGV_IF(ENG_VERBOSE, "Factory Gyro Bias %ld %ld %ld", mFactoryGyroBias[0], mFactoryGyroBias[1], mFactoryGyroBias[2]);
5281    mFactoryGyroBiasAvailable = true;
5282
5283    return;
5284}
5285
5286/* set bias from factory cal file to MPU offset (in chip frame)
5287   x = values store in cal file --> (v/1000 * 2^16 / (2000/250))
5288   offset = x/2^16 * (Gyro scale / self test scale used) * (-1) / offset scale
5289   i.e. self test default scale = 250
5290         gyro scale default to = 2000
5291         offset scale = 4 //as spec by hardware
5292         offset = x/2^16 * (8) * (-1) / (4)
5293*/
5294void MPLSensor::setFactoryGyroBias()
5295{
5296    VFUNC_LOG;
5297    int scaleRatio = mGyroScale / mGyroSelfTestScale;
5298    int offsetScale = 4;
5299    LOGV_IF(ENG_VERBOSE, "HAL: scaleRatio used =%d", scaleRatio);
5300    LOGV_IF(ENG_VERBOSE, "HAL: offsetScale used =%d", offsetScale);
5301
5302    /* Write to Driver */
5303    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
5304            (((int) (((float) mFactoryGyroBias[0]) / 65536.f * scaleRatio)) * -1 / offsetScale),
5305            mpu.in_gyro_x_offset, getTimestamp());
5306    if(write_attribute_sensor_continuous(gyro_x_offset_fd,
5307        (((int) (((float) mFactoryGyroBias[0]) / 65536.f * scaleRatio)) * -1 / offsetScale)) < 0)
5308    {
5309        LOGE("HAL:Error writing to gyro_x_offset");
5310        return;
5311    }
5312    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
5313            (((int) (((float) mFactoryGyroBias[1]) / 65536.f * scaleRatio)) * -1 / offsetScale),
5314            mpu.in_gyro_y_offset, getTimestamp());
5315    if(write_attribute_sensor_continuous(gyro_y_offset_fd,
5316        (((int) (((float) mFactoryGyroBias[1]) / 65536.f * scaleRatio)) * -1 / offsetScale)) < 0)
5317    {
5318        LOGE("HAL:Error writing to gyro_y_offset");
5319        return;
5320    }
5321    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
5322            (((int) (((float) mFactoryGyroBias[2]) / 65536.f * scaleRatio)) * -1 / offsetScale),
5323            mpu.in_gyro_z_offset, getTimestamp());
5324    if(write_attribute_sensor_continuous(gyro_z_offset_fd,
5325        (((int) (((float) mFactoryGyroBias[2]) / 65536.f * scaleRatio)) * -1 / offsetScale)) < 0)
5326    {
5327        LOGE("HAL:Error writing to gyro_z_offset");
5328        return;
5329    }
5330    mFactoryGyroBiasAvailable = false;
5331    LOGV_IF(EXTRA_VERBOSE, "HAL:Factory Gyro Calibrated Bias Applied");
5332
5333    return;
5334}
5335
5336/* these functions can be consolidated
5337with inv_convert_to_body_with_scale */
5338void MPLSensor::getGyroBias()
5339{
5340    VFUNC_LOG;
5341
5342    long *temp = NULL;
5343    long chipBias[3];
5344    long bias[3];
5345    unsigned short orient;
5346
5347    /* Get Values from MPL */
5348    inv_get_mpl_gyro_bias(mGyroChipBias, temp);
5349    orient = inv_orientation_matrix_to_scalar(mGyroOrientation);
5350    inv_convert_to_body(orient, mGyroChipBias, bias);
5351    LOGV_IF(ENG_VERBOSE && INPUT_DATA, "Mpl Gyro Bias (HW unit) %ld %ld %ld", mGyroChipBias[0], mGyroChipBias[1], mGyroChipBias[2]);
5352    LOGV_IF(ENG_VERBOSE && INPUT_DATA, "Mpl Gyro Bias (HW unit) (body) %ld %ld %ld", bias[0], bias[1], bias[2]);
5353    long gyroSensitivity = inv_get_gyro_sensitivity();
5354    if(gyroSensitivity == 0) {
5355        gyroSensitivity = mGyroScale;
5356    }
5357
5358    /* scale and convert to rad */
5359    for(int i=0; i<3; i++) {
5360        float temp = (float) gyroSensitivity / (1L << 30);
5361        mGyroBias[i] = (float) (bias[i] * temp / (1<<16) / 180 * M_PI);
5362        if (mGyroBias[i] != 0)
5363            mGyroBiasAvailable = true;
5364    }
5365
5366    return;
5367}
5368
5369void MPLSensor::setGyroZeroBias()
5370{
5371    VFUNC_LOG;
5372
5373    /* Write to Driver */
5374    LOGV_IF(SYSFS_VERBOSE && INPUT_DATA, "HAL:sysfs:echo %d > %s (%lld)",
5375            0, mpu.in_gyro_x_dmp_bias, getTimestamp());
5376    if(write_attribute_sensor_continuous(gyro_x_dmp_bias_fd, 0) < 0) {
5377        LOGE("HAL:Error writing to gyro_x_dmp_bias");
5378        return;
5379    }
5380    LOGV_IF(SYSFS_VERBOSE && INPUT_DATA, "HAL:sysfs:echo %d > %s (%lld)",
5381            0, mpu.in_gyro_y_dmp_bias, getTimestamp());
5382    if(write_attribute_sensor_continuous(gyro_y_dmp_bias_fd, 0) < 0) {
5383        LOGE("HAL:Error writing to gyro_y_dmp_bias");
5384        return;
5385    }
5386    LOGV_IF(SYSFS_VERBOSE && INPUT_DATA, "HAL:sysfs:echo %d > %s (%lld)",
5387            0, mpu.in_gyro_z_dmp_bias, getTimestamp());
5388    if(write_attribute_sensor_continuous(gyro_z_dmp_bias_fd, 0) < 0) {
5389        LOGE("HAL:Error writing to gyro_z_dmp_bias");
5390        return;
5391    }
5392    LOGV_IF(EXTRA_VERBOSE, "HAL:Zero Gyro DMP Calibrated Bias Applied");
5393
5394    return;
5395}
5396
5397void MPLSensor::setGyroBias()
5398{
5399    VFUNC_LOG;
5400
5401    if(mGyroBiasAvailable == false)
5402        return;
5403
5404    long bias[3];
5405    long gyroSensitivity = inv_get_gyro_sensitivity();
5406
5407    if(gyroSensitivity == 0) {
5408        gyroSensitivity = mGyroScale;
5409    }
5410
5411    inv_get_gyro_bias_dmp_units(bias);
5412
5413    /* Write to Driver */
5414    LOGV_IF(SYSFS_VERBOSE && INPUT_DATA, "HAL:sysfs:echo %ld > %s (%lld)",
5415            bias[0], mpu.in_gyro_x_dmp_bias, getTimestamp());
5416    if(write_attribute_sensor_continuous(gyro_x_dmp_bias_fd, bias[0]) < 0) {
5417        LOGE("HAL:Error writing to gyro_x_dmp_bias");
5418        return;
5419    }
5420    LOGV_IF(SYSFS_VERBOSE && INPUT_DATA, "HAL:sysfs:echo %ld > %s (%lld)",
5421            bias[1], mpu.in_gyro_y_dmp_bias, getTimestamp());
5422    if(write_attribute_sensor_continuous(gyro_y_dmp_bias_fd, bias[1]) < 0) {
5423        LOGE("HAL:Error writing to gyro_y_dmp_bias");
5424        return;
5425    }
5426    LOGV_IF(SYSFS_VERBOSE && INPUT_DATA, "HAL:sysfs:echo %ld > %s (%lld)",
5427            bias[2], mpu.in_gyro_z_dmp_bias, getTimestamp());
5428    if(write_attribute_sensor_continuous(gyro_z_dmp_bias_fd, bias[2]) < 0) {
5429        LOGE("HAL:Error writing to gyro_z_dmp_bias");
5430        return;
5431    }
5432    mGyroBiasApplied = true;
5433    mGyroBiasAvailable = false;
5434    LOGV_IF(EXTRA_VERBOSE, "HAL:Gyro DMP Calibrated Bias Applied");
5435
5436    return;
5437}
5438
5439void MPLSensor::getFactoryAccelBias()
5440{
5441    VFUNC_LOG;
5442
5443    long temp;
5444
5445    /* Get Values from MPL */
5446    inv_get_accel_bias(mFactoryAccelBias);
5447    LOGV_IF(ENG_VERBOSE, "Factory Accel Bias (mg) %ld %ld %ld", mFactoryAccelBias[0], mFactoryAccelBias[1], mFactoryAccelBias[2]);
5448    mFactoryAccelBiasAvailable = true;
5449
5450    return;
5451}
5452
5453void MPLSensor::setFactoryAccelBias()
5454{
5455    VFUNC_LOG;
5456
5457    if(mFactoryAccelBiasAvailable == false)
5458        return;
5459
5460    /* add scaling here - depends on self test parameters */
5461    int scaleRatio = mAccelScale / mAccelSelfTestScale;
5462    int offsetScale = 16;
5463    long tempBias;
5464
5465    LOGV_IF(ENG_VERBOSE, "HAL: scaleRatio used =%d", scaleRatio);
5466    LOGV_IF(ENG_VERBOSE, "HAL: offsetScale used =%d", offsetScale);
5467
5468    /* Write to Driver */
5469    tempBias = -mFactoryAccelBias[0] / 65536.f * scaleRatio / offsetScale;
5470    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %ld > %s (%lld)",
5471            tempBias, mpu.in_accel_x_offset, getTimestamp());
5472    if(write_attribute_sensor_continuous(accel_x_offset_fd, tempBias) < 0) {
5473        LOGE("HAL:Error writing to accel_x_offset");
5474        return;
5475    }
5476    tempBias = -mFactoryAccelBias[1] / 65536.f * scaleRatio / offsetScale;
5477    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %ld > %s (%lld)",
5478            tempBias, mpu.in_accel_y_offset, getTimestamp());
5479    if(write_attribute_sensor_continuous(accel_y_offset_fd, tempBias) < 0) {
5480        LOGE("HAL:Error writing to accel_y_offset");
5481        return;
5482    }
5483    tempBias = -mFactoryAccelBias[2] / 65536.f * scaleRatio / offsetScale;
5484    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %ld > %s (%lld)",
5485            tempBias, mpu.in_accel_z_offset, getTimestamp());
5486    if(write_attribute_sensor_continuous(accel_z_offset_fd, tempBias) < 0) {
5487        LOGE("HAL:Error writing to accel_z_offset");
5488        return;
5489    }
5490    mFactoryAccelBiasAvailable = false;
5491    LOGV_IF(EXTRA_VERBOSE, "HAL:Factory Accel Calibrated Bias Applied");
5492
5493    return;
5494}
5495
5496void MPLSensor::getAccelBias()
5497{
5498    VFUNC_LOG;
5499    long temp;
5500
5501    /* Get Values from MPL */
5502    inv_get_mpl_accel_bias(mAccelBias, &temp);
5503    LOGV_IF(ENG_VERBOSE, "Accel Bias (mg) %ld %ld %ld",
5504            mAccelBias[0], mAccelBias[1], mAccelBias[2]);
5505    mAccelBiasAvailable = true;
5506
5507    return;
5508}
5509
5510/*    set accel bias obtained from MPL
5511      bias is scaled by 65536 from MPL
5512      DMP expects: bias * 536870912 / 2^30 = bias / 2 (in body frame)
5513*/
5514void MPLSensor::setAccelBias()
5515{
5516    VFUNC_LOG;
5517
5518    if(mAccelBiasAvailable == false) {
5519        LOGV_IF(ENG_VERBOSE, "HAL: setAccelBias - accel bias not available");
5520        return;
5521    }
5522
5523    /* write to driver */
5524    LOGV_IF(SYSFS_VERBOSE && INPUT_DATA, "HAL:sysfs:echo %ld > %s (%lld)",
5525            (long) (mAccelBias[0] / 65536.f / 2),
5526            mpu.in_accel_x_dmp_bias, getTimestamp());
5527    if(write_attribute_sensor_continuous(
5528            accel_x_dmp_bias_fd, (long)(mAccelBias[0] / 65536.f / 2)) < 0) {
5529        LOGE("HAL:Error writing to accel_x_dmp_bias");
5530        return;
5531    }
5532    LOGV_IF(SYSFS_VERBOSE && INPUT_DATA, "HAL:sysfs:echo %ld > %s (%lld)",
5533            (long)(mAccelBias[1] / 65536.f / 2),
5534            mpu.in_accel_y_dmp_bias, getTimestamp());
5535    if(write_attribute_sensor_continuous(
5536            accel_y_dmp_bias_fd, (long)(mAccelBias[1] / 65536.f / 2)) < 0) {
5537        LOGE("HAL:Error writing to accel_y_dmp_bias");
5538        return;
5539    }
5540    LOGV_IF(SYSFS_VERBOSE && INPUT_DATA, "HAL:sysfs:echo %ld > %s (%lld)",
5541            (long)(mAccelBias[2] / 65536 / 2),
5542            mpu.in_accel_z_dmp_bias, getTimestamp());
5543    if(write_attribute_sensor_continuous(
5544            accel_z_dmp_bias_fd, (long)(mAccelBias[2] / 65536 / 2)) < 0) {
5545        LOGE("HAL:Error writing to accel_z_dmp_bias");
5546        return;
5547    }
5548
5549    mAccelBiasAvailable = false;
5550    mAccelBiasApplied = true;
5551    LOGV_IF(EXTRA_VERBOSE, "HAL:Accel DMP Calibrated Bias Applied");
5552
5553    return;
5554}
5555
5556int MPLSensor::isCompassDisabled(void)
5557{
5558    VFUNC_LOG;
5559    if(mCompassSensor->getFd() < 0 && !mCompassSensor->isIntegrated()) {
5560    LOGI_IF(EXTRA_VERBOSE, "HAL: Compass is disabled, Six-axis Sensor Fusion is used.");
5561        return 1;
5562    }
5563    return 0;
5564}
5565
5566int MPLSensor::checkBatchEnabled(void)
5567{
5568    VFUNC_LOG;
5569    return ((mFeatureActiveMask & INV_DMP_BATCH_MODE)? 1:0);
5570}
5571
5572/* precondition: framework disallows this case, ie enable continuous sensor, */
5573/* and enable batch sensor */
5574/* if one sensor is in continuous mode, HAL disallows enabling batch for this sensor */
5575/* or any other sensors */
5576int MPLSensor::batch(int handle, int flags, int64_t period_ns, int64_t timeout)
5577{
5578    VFUNC_LOG;
5579
5580    int res = 0;
5581
5582    if (isMpuNonDmp())
5583        return res;
5584
5585    /* Enables batch mode and sets timeout for the given sensor */
5586    /* enum SENSORS_BATCH_DRY_RUN, SENSORS_BATCH_WAKE_UPON_FIFO_FULL */
5587    bool dryRun = false;
5588    android::String8 sname;
5589    int what = -1;
5590    int enabled_sensors = mEnabled;
5591    int batchMode = timeout > 0 ? 1 : 0;
5592
5593    LOGI_IF(DEBUG_BATCHING || ENG_VERBOSE,
5594            "HAL:batch called - handle=%d, flags=%d, period=%lld, timeout=%lld",
5595            handle, flags, period_ns, timeout);
5596
5597    if(flags & SENSORS_BATCH_DRY_RUN) {
5598        dryRun = true;
5599        LOGI_IF(PROCESS_VERBOSE,
5600                "HAL:batch - dry run mode is set (%d)", SENSORS_BATCH_DRY_RUN);
5601    }
5602
5603    /* check if we can support issuing interrupt before FIFO fills-up */
5604    /* in a given timeout.                                          */
5605    if (flags & SENSORS_BATCH_WAKE_UPON_FIFO_FULL) {
5606            LOGE("HAL: batch SENSORS_BATCH_WAKE_UPON_FIFO_FULL is not supported");
5607            return -EINVAL;
5608    }
5609
5610    getHandle(handle, what, sname);
5611    if(uint32_t(what) >= NumSensors) {
5612        LOGE("HAL:batch sensors %d not found", what);
5613        return -EINVAL;
5614    }
5615
5616    LOGV_IF(PROCESS_VERBOSE,
5617            "HAL:batch : %llu ns, (%.2f Hz)", period_ns, 1000000000.f / period_ns);
5618
5619    // limit all rates to reasonable ones */
5620    if (period_ns < 5000000LL) {
5621        period_ns = 5000000LL;
5622    }
5623
5624    switch (what) {
5625    case Gyro:
5626    case RawGyro:
5627    case Accelerometer:
5628#ifdef ENABLE_PRESSURE
5629    case Pressure:
5630#endif
5631    case GameRotationVector:
5632    case StepDetector:
5633        LOGV_IF(PROCESS_VERBOSE, "HAL: batch - select sensor (handle %d)", handle);
5634        break;
5635    case MagneticField:
5636    case RawMagneticField:
5637        if(timeout > 0 && !mCompassSensor->isIntegrated())
5638            return -EINVAL;
5639        else
5640            LOGV_IF(PROCESS_VERBOSE, "HAL: batch - select sensor (handle %d)", handle);
5641        break;
5642    default:
5643        if (timeout > 0) {
5644            LOGE("sensor (handle %d) is not supported in batch mode", handle);
5645            return -EINVAL;
5646        }
5647    }
5648
5649    if(dryRun == true) {
5650        LOGI("HAL: batch Dry Run is complete");
5651        return 0;
5652    }
5653
5654    int tempBatch = 0;
5655    if (timeout > 0) {
5656        tempBatch = mBatchEnabled | (1 << what);
5657    } else {
5658        tempBatch = mBatchEnabled & ~(1 << what);
5659    }
5660
5661    if (!computeBatchSensorMask(mEnabled, tempBatch)) {
5662        batchMode = 0;
5663    } else {
5664        batchMode = 1;
5665    }
5666
5667    /* get maximum possible bytes to batch per sample */
5668    /* get minimum delay for each requested sensor    */
5669    ssize_t nBytes = 0;
5670    int64_t wanted = 1000000000LL, ns = 0;
5671    int64_t timeoutInMs = 0;
5672    for (int i = 0; i < NumSensors; i++) {
5673        if (batchMode == 1) {
5674            ns = mBatchDelays[i];
5675            LOGV_IF(DEBUG_BATCHING && EXTRA_VERBOSE,
5676                    "HAL:batch - requested sensor=0x%01x, batch delay=%lld", mEnabled & (1 << i), ns);
5677            // take the min delay ==> max rate
5678            wanted = (ns < wanted) ? ns : wanted;
5679            if (i <= RawMagneticField) {
5680                nBytes += 8;
5681            }
5682#ifdef ENABLE_PRESSURE
5683            if (i == Pressure) {
5684                nBytes += 6;
5685            }
5686#endif
5687            if ((i == StepDetector) || (i == GameRotationVector)) {
5688                nBytes += 16;
5689            }
5690        }
5691    }
5692
5693    /* starting from code below,  we will modify hardware */
5694    /* first edit global batch mode mask */
5695
5696    if (!timeout) {
5697        mBatchEnabled &= ~(1 << what);
5698        mBatchDelays[what] = 1000000000L;
5699        mDelays[what] = period_ns;
5700        mBatchTimeouts[what] = 100000000000LL;
5701    } else {
5702        mBatchEnabled |= (1 << what);
5703        mBatchDelays[what] = period_ns;
5704        mDelays[what] = period_ns;
5705        mBatchTimeouts[what] = timeout;
5706    }
5707
5708    // reset master enable
5709    res = masterEnable(0);
5710    if (res < 0) {
5711        return res;
5712    }
5713
5714    if(((int)mOldBatchEnabledMask != batchMode) || batchMode) {
5715
5716    /* remember batch mode that is set  */
5717    mOldBatchEnabledMask = batchMode;
5718
5719    /* For these sensors, switch to different data output */
5720    int featureMask = computeBatchDataOutput();
5721
5722    LOGV_IF(ENG_VERBOSE, "batchMode =%d, featureMask=0x%x, mEnabled=%d",
5723                batchMode, featureMask, mEnabled);
5724    if (DEBUG_BATCHING && EXTRA_VERBOSE) {
5725        LOGV("HAL:batch - sensor=0x%01x", mBatchEnabled);
5726        for (int d = 0; d < NumSensors; d++) {
5727            LOGV("HAL:batch - sensor status=0x%01x batch status=0x%01x timeout=%lld delay=%lld",
5728                            mEnabled & (1 << d), (mBatchEnabled & (1 << d)), mBatchTimeouts[d],
5729                            mBatchDelays[d]);
5730        }
5731    }
5732
5733    /* case for Ped standalone */
5734    if ((batchMode == 1) && (featureMask & INV_DMP_PED_STANDALONE) &&
5735           (mFeatureActiveMask & INV_DMP_PEDOMETER)) {
5736        LOGI_IF(ENG_VERBOSE, "batch - ID_P only = 0x%x", mBatchEnabled);
5737        enablePedQuaternion(0);
5738        enablePedStandalone(1);
5739    } else {
5740        enablePedStandalone(0);
5741        if (featureMask & INV_DMP_PED_QUATERNION) {
5742            enableLPQuaternion(0);
5743            enablePedQuaternion(1);
5744        }
5745    }
5746
5747    /* case for Ped Quaternion */
5748    if ((batchMode == 1) && (featureMask & INV_DMP_PED_QUATERNION) &&
5749            (mEnabled & (1 << GameRotationVector)) &&
5750            (mFeatureActiveMask & INV_DMP_PEDOMETER)) {
5751        LOGI_IF(ENG_VERBOSE, "batch - ID_P and GRV or ALL = 0x%x", mBatchEnabled);
5752        LOGI_IF(ENG_VERBOSE, "batch - ID_P is enabled for batching, PED quat will be automatically enabled");
5753        enableLPQuaternion(0);
5754        enablePedQuaternion(1);
5755
5756        /* set pedq rate */
5757        wanted = mBatchDelays[GameRotationVector];
5758        setPedQuaternionRate(wanted);
5759    } else if (!(featureMask & INV_DMP_PED_STANDALONE)){
5760        LOGV_IF(ENG_VERBOSE, "batch - PedQ Toggle back to normal 6 axis");
5761        if (mEnabled & (1 << GameRotationVector)) {
5762            enableLPQuaternion(checkLPQRateSupported());
5763        }
5764        enablePedQuaternion(0);
5765    } else {
5766        enablePedQuaternion(0);
5767    }
5768
5769     /* case for Ped indicator */
5770    if ((batchMode == 1) && ((featureMask & INV_DMP_PED_INDICATOR))) {
5771        enablePedIndicator(1);
5772    } else {
5773        enablePedIndicator(0);
5774    }
5775
5776    /* case for Six Axis Quaternion */
5777    if ((batchMode == 1) && (featureMask & INV_DMP_6AXIS_QUATERNION) &&
5778            (mEnabled & (1 << GameRotationVector))) {
5779        LOGI_IF(ENG_VERBOSE, "batch - GRV = 0x%x", mBatchEnabled);
5780        enableLPQuaternion(0);
5781        enable6AxisQuaternion(1);
5782        if (what == GameRotationVector) {
5783            setInitial6QuatValue();
5784        }
5785
5786        /* set sixaxis rate */
5787        wanted = mBatchDelays[GameRotationVector];
5788        set6AxisQuaternionRate(wanted);
5789    } else if (!(featureMask & INV_DMP_PED_QUATERNION)){
5790        LOGV_IF(ENG_VERBOSE, "batch - 6Axis Toggle back to normal 6 axis");
5791        if (mEnabled & (1 << GameRotationVector)) {
5792            enableLPQuaternion(checkLPQRateSupported());
5793        }
5794        enable6AxisQuaternion(0);
5795    } else {
5796        enable6AxisQuaternion(0);
5797    }
5798
5799    /* TODO: This may make a come back some day */
5800    /* Not to overflow hardware FIFO if flag is set */
5801    /*if (flags & (1 << SENSORS_BATCH_WAKE_UPON_FIFO_FULL)) {
5802        LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
5803                0, mpu.batchmode_wake_fifo_full_on, getTimestamp());
5804        if (write_sysfs_int(mpu.batchmode_wake_fifo_full_on, 0) < 0) {
5805            LOGE("HAL:ERR can't write batchmode_wake_fifo_full_on");
5806        }
5807    }*/
5808
5809    writeBatchTimeout(batchMode);
5810
5811    if (computeAndSetDmpState() < 0) {
5812        LOGE("HAL:ERR can't compute dmp state");
5813    }
5814
5815}//end of batch mode modify
5816
5817    if (batchMode == 1) {
5818        /* set batch rates */
5819        if (setBatchDataRates() < 0) {
5820            LOGE("HAL:ERR can't set batch data rates");
5821        }
5822    } else {
5823        /* reset sensor rate */
5824        if (resetDataRates() < 0) {
5825            LOGE("HAL:ERR can't reset output rate back to original setting");
5826        }
5827    }
5828
5829    // set sensor data interrupt
5830    uint32_t dataInterrupt = (mEnabled || (mFeatureActiveMask & INV_DMP_BATCH_MODE));
5831    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
5832                !dataInterrupt, mpu.dmp_event_int_on, getTimestamp());
5833    if (write_sysfs_int(mpu.dmp_event_int_on, !dataInterrupt) < 0) {
5834        res = -1;
5835        LOGE("HAL:ERR can't enable DMP event interrupt");
5836    }
5837
5838    if (enabled_sensors || mFeatureActiveMask) {
5839        masterEnable(1);
5840    }
5841    return res;
5842}
5843
5844/* Send empty event when:        */
5845/* 1. batch mode is not enabled  */
5846/* 2. no data in HW FIFO         */
5847/* return status zero if (2)     */
5848int MPLSensor::flush(int handle)
5849{
5850    VFUNC_LOG;
5851
5852    int res = 0;
5853    int status = 0;
5854    android::String8 sname;
5855    int what = -1;
5856
5857    getHandle(handle, what, sname);
5858    if (uint32_t(what) >= NumSensors) {
5859        LOGE("HAL:flush - what=%d is invalid", what);
5860        return -EINVAL;
5861    }
5862
5863    LOGV_IF(PROCESS_VERBOSE, "HAL: flush - select sensor %s (handle %d)", sname.string(), handle);
5864
5865    if (((what != StepDetector) && (!(mEnabled & (1 << what)))) ||
5866        ((what == StepDetector) && !(mFeatureActiveMask & INV_DMP_PEDOMETER))) {
5867        LOGV_IF(ENG_VERBOSE, "HAL: flush - sensor %s not enabled", sname.string());
5868         return -EINVAL;
5869    }
5870
5871    if(!(mBatchEnabled & (1 << what))) {
5872         LOGV_IF(PROCESS_VERBOSE, "HAL:flush - batch mode not enabled for sensor %s (handle %d)", sname.string(), handle);
5873    }
5874
5875    mFlushSensorEnabledVector.push_back(handle);
5876
5877    /*write sysfs */
5878    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:cat %s (%lld)",
5879            mpu.flush_batch, getTimestamp());
5880
5881    status = read_sysfs_int(mpu.flush_batch, &res);
5882
5883    if (status < 0)
5884        LOGE("HAL: flush - error invoking flush_batch");
5885
5886    /* driver returns 0 if FIFO is empty */
5887    if (res == 0) {
5888        LOGI("HAL: flush - no data in FIFO");
5889    }
5890
5891    LOGV_IF(ENG_VERBOSE, "HAl:flush - mFlushSensorEnabledVector=%d res=%d status=%d", handle, res, status);
5892
5893    mFlushBatchSet = 0;
5894    return 0;
5895}
5896
5897int MPLSensor::selectAndSetQuaternion(int batchMode, int mEnabled, long long featureMask)
5898{
5899    VFUNC_LOG;
5900    int res = 0;
5901
5902    int64_t wanted;
5903
5904    /* case for Ped Quaternion */
5905    if (batchMode == 1) {
5906        if ((featureMask & INV_DMP_PED_QUATERNION) &&
5907            (mEnabled & (1 << GameRotationVector)) &&
5908            (mFeatureActiveMask & INV_DMP_PEDOMETER)) {
5909                enableLPQuaternion(0);
5910                enable6AxisQuaternion(0);
5911                setInitial6QuatValue();
5912                enablePedQuaternion(1);
5913
5914                /* set pedq rate */
5915                wanted = mBatchDelays[GameRotationVector];
5916                setPedQuaternionRate(wanted);
5917        } else if ((featureMask & INV_DMP_6AXIS_QUATERNION) &&
5918                   (mEnabled & (1 << GameRotationVector))) {
5919                enableLPQuaternion(0);
5920                enablePedQuaternion(0);
5921                setInitial6QuatValue();
5922                enable6AxisQuaternion(1);
5923
5924                /* set sixaxis rate */
5925                wanted = mBatchDelays[GameRotationVector];
5926                set6AxisQuaternionRate(wanted);
5927        } else {
5928            enablePedQuaternion(0);
5929            enable6AxisQuaternion(0);
5930        }
5931    } else {
5932        if(mEnabled & (1 << GameRotationVector)) {
5933            enablePedQuaternion(0);
5934            enable6AxisQuaternion(0);
5935            enableLPQuaternion(checkLPQRateSupported());
5936        }
5937        else {
5938            enablePedQuaternion(0);
5939            enable6AxisQuaternion(0);
5940        }
5941    }
5942
5943    return res;
5944}
5945
5946/*
5947Select Quaternion and Options for Batching
5948
5949    ID_P    ID_GRV     HW Batch     Type
5950a   1       1          1            PedQ, Ped Indicator, HW
5951b   1       1          0            PedQ
5952c   1       0          1            Ped Indicator, HW
5953d   1       0          0            Ped Standalone, Ped Indicator
5954e   0       1          1            6Q, HW
5955f   0       1          0            6Q
5956g   0       0          1            HW
5957h   0       0          0            LPQ <defualt>
5958*/
5959int MPLSensor::computeBatchDataOutput()
5960{
5961    VFUNC_LOG;
5962
5963    int featureMask = 0;
5964    if (mBatchEnabled == 0)
5965        return 0;//h
5966
5967    uint32_t hardwareSensorMask = (1 << Gyro)
5968                                | (1 << RawGyro)
5969                                | (1 << Accelerometer)
5970                                | (1 << MagneticField)
5971#ifdef ENABLE_PRESSURE
5972                                | (1 << Pressure)
5973#endif
5974                                | (1 << RawMagneticField);
5975
5976    LOGV_IF(ENG_VERBOSE, "hardwareSensorMask = 0x%0x, mBatchEnabled = 0x%0x",
5977            hardwareSensorMask, mBatchEnabled);
5978
5979    if (mBatchEnabled & (1 << StepDetector)) {
5980        if (mBatchEnabled & (1 << GameRotationVector)) {
5981            if ((mBatchEnabled & hardwareSensorMask)) {
5982                featureMask |= INV_DMP_6AXIS_QUATERNION;//a
5983                featureMask |= INV_DMP_PED_INDICATOR;
5984//LOGE("batch output: a");
5985            } else {
5986                featureMask |= INV_DMP_PED_QUATERNION;  //b
5987                featureMask |= INV_DMP_PED_INDICATOR;   //always piggy back a bit
5988//LOGE("batch output: b");
5989            }
5990        } else {
5991            if (mBatchEnabled & hardwareSensorMask) {
5992                featureMask |= INV_DMP_PED_INDICATOR;   //c
5993//LOGE("batch output: c");
5994            } else {
5995                featureMask |= INV_DMP_PED_STANDALONE;  //d
5996                featureMask |= INV_DMP_PED_INDICATOR;   //required for standalone
5997//LOGE("batch output: d");
5998            }
5999        }
6000    } else if (mBatchEnabled & (1 << GameRotationVector)) {
6001        featureMask |= INV_DMP_6AXIS_QUATERNION;        //e,f
6002//LOGE("batch output: e,f");
6003    } else {
6004        LOGV_IF(ENG_VERBOSE,
6005                "HAL:computeBatchDataOutput: featuerMask=0x%x", featureMask);
6006//LOGE("batch output: g");
6007        return 0; //g
6008    }
6009
6010    LOGV_IF(ENG_VERBOSE,
6011            "HAL:computeBatchDataOutput: featuerMask=0x%x", featureMask);
6012    return featureMask;
6013}
6014
6015int MPLSensor::getDmpPedometerFd()
6016{
6017    VFUNC_LOG;
6018    LOGV_IF(EXTRA_VERBOSE, "getDmpPedometerFd returning %d", dmp_pedometer_fd);
6019    return dmp_pedometer_fd;
6020}
6021
6022/* @param [in] : outputType = 1 --event is from PED_Q        */
6023/*               outputType = 0 --event is from ID_SC, ID_P  */
6024int MPLSensor::readDmpPedometerEvents(sensors_event_t* data, int count,
6025                                      int32_t id, int outputType)
6026{
6027    VFUNC_LOG;
6028
6029    int res = 0;
6030    char dummy[4];
6031
6032    int numEventReceived = 0;
6033    int update = 0;
6034
6035    LOGI_IF(0, "HAL: Read Pedometer Event ID=%d", id);
6036    switch (id) {
6037    case ID_P:
6038        if (mDmpPedometerEnabled && count > 0) {
6039            /* Handles return event */
6040            LOGI("HAL: Step detected");
6041            update = sdHandler(&mSdEvents);
6042        }
6043
6044        if (update && count > 0) {
6045            *data++ = mSdEvents;
6046            count--;
6047            numEventReceived++;
6048        }
6049        break;
6050    case ID_SC:
6051        FILE *fp;
6052        uint64_t stepCount;
6053        uint64_t stepCountTs;
6054
6055        if (mDmpStepCountEnabled && count > 0) {
6056            fp = fopen(mpu.pedometer_steps, "r");
6057            if (fp == NULL) {
6058                LOGE("HAL:cannot open pedometer_steps");
6059            } else {
6060                if (fscanf(fp, "%lld\n", &stepCount) < 0) {
6061                    LOGW("HAL:cannot read pedometer_steps");
6062                    if (fclose(fp) < 0) {
6063                       LOGW("HAL:cannot close pedometer_steps");
6064                    }
6065                    return 0;
6066                }
6067                if (fclose(fp) < 0) {
6068                       LOGW("HAL:cannot close pedometer_steps");
6069                }
6070            }
6071
6072            /* return event onChange only */
6073            if (stepCount == mLastStepCount) {
6074                return 0;
6075            }
6076
6077            mLastStepCount = stepCount;
6078
6079            /* Read step count timestamp */
6080            fp = fopen(mpu.pedometer_counter, "r");
6081            if (fp == NULL) {
6082                LOGE("HAL:cannot open pedometer_counter");
6083            } else{
6084                if (fscanf(fp, "%lld\n", &stepCountTs) < 0) {
6085                    LOGE("HAL:cannot read pedometer_counter");
6086                    if (fclose(fp) < 0) {
6087                        LOGE("HAL:cannot close pedometer_counter");
6088                    }
6089                    return 0;
6090                }
6091                if (fclose(fp) < 0) {
6092                        LOGE("HAL:cannot close pedometer_counter");
6093                        return 0;
6094                }
6095            }
6096            mScEvents.timestamp = stepCountTs;
6097
6098            /* Handles return event */
6099            update = scHandler(&mScEvents);
6100        }
6101
6102        if (update && count > 0) {
6103            *data++ = mScEvents;
6104            count--;
6105            numEventReceived++;
6106        }
6107        break;
6108    }
6109
6110    if (!outputType) {
6111        // read dummy data per driver's request
6112        // only required if actual irq is issued
6113        read(dmp_pedometer_fd, dummy, 4);
6114    } else {
6115        return 1;
6116    }
6117
6118    return numEventReceived;
6119}
6120
6121int MPLSensor::getDmpSignificantMotionFd()
6122{
6123    VFUNC_LOG;
6124
6125    LOGV_IF(EXTRA_VERBOSE, "getDmpSignificantMotionFd returning %d",
6126            dmp_sign_motion_fd);
6127    return dmp_sign_motion_fd;
6128}
6129
6130int MPLSensor::readDmpSignificantMotionEvents(sensors_event_t* data, int count)
6131{
6132    VFUNC_LOG;
6133
6134    int res = 0;
6135    char dummy[4];
6136    int significantMotion;
6137    FILE *fp;
6138    int sensors = mEnabled;
6139    int numEventReceived = 0;
6140    int update = 0;
6141
6142    /* Technically this step is not necessary for now  */
6143    /* In the future, we may have meaningful values */
6144    fp = fopen(mpu.event_smd, "r");
6145    if (fp == NULL) {
6146        LOGE("HAL:cannot open event_smd");
6147        return 0;
6148    } else {
6149        if (fscanf(fp, "%d\n", &significantMotion) < 0) {
6150            LOGE("HAL:cannot read event_smd");
6151        }
6152        if (fclose(fp) < 0) {
6153            LOGE("HAL:cannot close event_smd");
6154        }
6155    }
6156
6157    if(mDmpSignificantMotionEnabled && count > 0) {
6158       /* By implementation, smd is disabled once an event is triggered */
6159        sensors_event_t temp;
6160
6161        /* Handles return event */
6162        LOGI("HAL: SMD detected");
6163        int update = smHandler(&mSmEvents);
6164        if (update && count > 0) {
6165            *data++ = mSmEvents;
6166            count--;
6167            numEventReceived++;
6168
6169            /* reset smd state */
6170            mDmpSignificantMotionEnabled = 0;
6171            mFeatureActiveMask &= ~INV_DMP_SIGNIFICANT_MOTION;
6172
6173            /* auto disable this sensor */
6174            enableDmpSignificantMotion(0);
6175        }
6176    }
6177
6178    // read dummy data per driver's request
6179    read(dmp_sign_motion_fd, dummy, 4);
6180
6181    return numEventReceived;
6182}
6183
6184int MPLSensor::enableDmpSignificantMotion(int en)
6185{
6186    VFUNC_LOG;
6187
6188    int res = 0;
6189    int enabled_sensors = mEnabled;
6190
6191    if (isMpuNonDmp())
6192        return res;
6193
6194    // reset master enable
6195    res = masterEnable(0);
6196    if (res < 0)
6197        return res;
6198
6199    //Toggle significant montion detection
6200    if(en) {
6201        LOGV_IF(ENG_VERBOSE, "HAL:Enabling Significant Motion");
6202        LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
6203                1, mpu.smd_enable, getTimestamp());
6204        if (write_sysfs_int(mpu.smd_enable, 1) < 0) {
6205            LOGE("HAL:ERR can't write DMP smd_enable");
6206            res = -1;   //Indicate an err
6207        }
6208        mFeatureActiveMask |= INV_DMP_SIGNIFICANT_MOTION;
6209    }
6210    else {
6211        LOGV_IF(ENG_VERBOSE, "HAL:Disabling Significant Motion");
6212        LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
6213                0, mpu.smd_enable, getTimestamp());
6214        if (write_sysfs_int(mpu.smd_enable, 0) < 0) {
6215            LOGE("HAL:ERR write DMP smd_enable");
6216        }
6217        mFeatureActiveMask &= ~INV_DMP_SIGNIFICANT_MOTION;
6218    }
6219
6220    if ((res = setDmpFeature(en)) < 0)
6221        return res;
6222
6223    if ((res = computeAndSetDmpState()) < 0)
6224        return res;
6225
6226    if (!mBatchEnabled && (resetDataRates() < 0))
6227        return res;
6228
6229    if(en || enabled_sensors || mFeatureActiveMask) {
6230        res = masterEnable(1);
6231    }
6232    return res;
6233}
6234
6235void MPLSensor::setInitial6QuatValue()
6236{
6237    VFUNC_LOG;
6238
6239    if (!mInitial6QuatValueAvailable)
6240        return;
6241
6242    /* convert to unsigned char array */
6243    size_t length = 16;
6244    unsigned char quat[16];
6245    convert_long_to_hex_char(mInitial6QuatValue, quat, 4);
6246
6247    /* write to sysfs */
6248    LOGV_IF(EXTRA_VERBOSE, "HAL:sysfs:echo quat value > %s", mpu.six_axis_q_value);
6249    LOGV_IF(EXTRA_VERBOSE && ENG_VERBOSE, "quat=%ld,%ld,%ld,%ld", mInitial6QuatValue[0],
6250					            mInitial6QuatValue[1],
6251                                                    mInitial6QuatValue[2],
6252                                                    mInitial6QuatValue[3]);
6253    FILE* fptr = fopen(mpu.six_axis_q_value, "w");
6254    if(fptr == NULL) {
6255        LOGE("HAL:could not open six_axis_q_value");
6256    } else {
6257        if (fwrite(quat, 1, length, fptr) != length) {
6258           LOGE("HAL:write six axis q value failed");
6259        } else {
6260            mInitial6QuatValueAvailable = 0;
6261        }
6262        if (fclose(fptr) < 0) {
6263            LOGE("HAL:could not close six_axis_q_value");
6264        }
6265    }
6266
6267    return;
6268}
6269int MPLSensor::writeSignificantMotionParams(bool toggleEnable,
6270                                            uint32_t delayThreshold1,
6271                                            uint32_t delayThreshold2,
6272                                            uint32_t motionThreshold)
6273{
6274    VFUNC_LOG;
6275
6276    int res = 0;
6277
6278    // Turn off enable
6279    if (toggleEnable) {
6280        masterEnable(0);
6281    }
6282
6283    // Write supplied values
6284    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
6285            delayThreshold1, mpu.smd_delay_threshold, getTimestamp());
6286    res = write_sysfs_int(mpu.smd_delay_threshold, delayThreshold1);
6287    if (res == 0) {
6288        LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
6289                delayThreshold2, mpu.smd_delay_threshold2, getTimestamp());
6290        res = write_sysfs_int(mpu.smd_delay_threshold2, delayThreshold2);
6291    }
6292    if (res == 0) {
6293        LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
6294                motionThreshold, mpu.smd_threshold, getTimestamp());
6295        res = write_sysfs_int(mpu.smd_threshold, motionThreshold);
6296    }
6297
6298    // Turn on enable
6299    if (toggleEnable) {
6300        masterEnable(1);
6301    }
6302    return res;
6303}
6304
6305/* set batch data rate */
6306/* this function should be optimized */
6307int MPLSensor::setBatchDataRates()
6308{
6309    VFUNC_LOG;
6310
6311    int res = 0;
6312    int tempFd = -1;
6313
6314    int64_t gyroRate;
6315    int64_t accelRate;
6316    int64_t compassRate;
6317#ifdef ENABLE_PRESSURE
6318    int64_t pressureRate;
6319#endif
6320    int64_t quatRate;
6321
6322    int mplGyroRate;
6323    int mplAccelRate;
6324    int mplCompassRate;
6325    int mplQuatRate;
6326
6327#ifdef ENABLE_MULTI_RATE
6328    gyroRate = mBatchDelays[Gyro];
6329    /* take care of case where only one type of gyro sensors or
6330       compass sensors is turned on */
6331    if (mBatchEnabled & (1 << Gyro) || mBatchEnabled & (1 << RawGyro)) {
6332        gyroRate = (mBatchDelays[Gyro] <= mBatchDelays[RawGyro]) ?
6333            (mBatchEnabled & (1 << Gyro) ? mBatchDelays[Gyro] : mBatchDelays[RawGyro]):
6334            (mBatchEnabled & (1 << RawGyro) ? mBatchDelays[RawGyro] : mBatchDelays[Gyro]);
6335    }
6336    compassRate = mBatchDelays[MagneticField];
6337    if (mBatchEnabled & (1 << MagneticField) || mBatchEnabled & (1 << RawMagneticField)) {
6338        compassRate = (mBatchDelays[MagneticField] <= mBatchDelays[RawMagneticField]) ?
6339                (mBatchEnabled & (1 << MagneticField) ? mBatchDelays[MagneticField] :
6340                    mBatchDelays[RawMagneticField]) :
6341                (mBatchEnabled & (1 << RawMagneticField) ? mBatchDelays[RawMagneticField] :
6342                    mBatchDelays[MagneticField]);
6343    }
6344    accelRate = mBatchDelays[Accelerometer];
6345#ifdef ENABLE_PRESSURE
6346    pressureRate = mBatchDelays[Pressure];
6347#endif //ENABLE_PRESSURE
6348
6349    if ((mFeatureActiveMask & INV_DMP_PED_QUATERNION) ||
6350            (mFeatureActiveMask & INV_DMP_6AXIS_QUATERNION)) {
6351        quatRate = mBatchDelays[GameRotationVector];
6352        mplQuatRate = (int) quatRate / 1000LL;
6353        inv_set_quat_sample_rate(mplQuatRate);
6354        inv_set_rotation_vector_6_axis_sample_rate(mplQuatRate);
6355        LOGV_IF(PROCESS_VERBOSE,
6356            "HAL:MPL rv 6 axis sample rate: (mpl)=%d us (mpu)=%.2f Hz", mplQuatRate,
6357                1000000000.f / quatRate );
6358        LOGV_IF(PROCESS_VERBOSE,
6359            "HAL:MPL quat sample rate: (mpl)=%d us (mpu)=%.2f Hz", mplQuatRate,
6360                1000000000.f / quatRate );
6361        getDmpRate(&quatRate);
6362    }
6363
6364    mplGyroRate = (int) gyroRate / 1000LL;
6365    mplAccelRate = (int) accelRate / 1000LL;
6366    mplCompassRate = (int) compassRate / 1000LL;
6367
6368     /* set rate in MPL */
6369     /* compass can only do 100Hz max */
6370    inv_set_gyro_sample_rate(mplGyroRate);
6371    inv_set_accel_sample_rate(mplAccelRate);
6372    inv_set_compass_sample_rate(mplCompassRate);
6373
6374    LOGV_IF(PROCESS_VERBOSE,
6375            "HAL:MPL gyro sample rate: (mpl)=%d us (mpu)=%.2f Hz", mplGyroRate, 1000000000.f / gyroRate);
6376    LOGV_IF(PROCESS_VERBOSE,
6377            "HAL:MPL accel sample rate: (mpl)=%d us (mpu)=%.2f Hz", mplAccelRate, 1000000000.f / accelRate);
6378    LOGV_IF(PROCESS_VERBOSE,
6379            "HAL:MPL compass sample rate: (mpl)=%d us (mpu)=%.2f Hz", mplCompassRate, 1000000000.f / compassRate);
6380
6381#else
6382    /* search the minimum delay requested across all enabled sensors */
6383    int64_t wanted = 1000000000LL;
6384    for (int i = 0; i < NumSensors; i++) {
6385        if (mBatchEnabled & (1 << i)) {
6386            int64_t ns = mBatchDelays[i];
6387            wanted = wanted < ns ? wanted : ns;
6388        }
6389    }
6390    gyroRate = wanted;
6391    accelRate = wanted;
6392    compassRate = wanted;
6393#ifdef ENABLE_PRESSURE
6394    pressureRate = wanted;
6395#endif
6396#endif
6397
6398    /* takes care of gyro rate */
6399    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)",
6400            1000000000.f / gyroRate, mpu.gyro_rate,
6401            getTimestamp());
6402    tempFd = open(mpu.gyro_rate, O_RDWR);
6403    res = write_attribute_sensor(tempFd, 1000000000.f / gyroRate);
6404    if(res < 0) {
6405        LOGE("HAL:GYRO update delay error");
6406    }
6407
6408    /* takes care of accel rate */
6409    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)",
6410            1000000000.f / accelRate, mpu.accel_rate,
6411            getTimestamp());
6412    tempFd = open(mpu.accel_rate, O_RDWR);
6413    res = write_attribute_sensor(tempFd, 1000000000.f / accelRate);
6414    LOGE_IF(res < 0, "HAL:ACCEL update delay error");
6415
6416    /* takes care of compass rate */
6417    if (compassRate < mCompassSensor->getMinDelay() * 1000LL) {
6418        compassRate = mCompassSensor->getMinDelay() * 1000LL;
6419    }
6420    mCompassSensor->setDelay(ID_M, compassRate);
6421
6422#ifdef ENABLE_PRESSURE
6423    /* takes care of pressure rate */
6424    mPressureSensor->setDelay(ID_PS, pressureRate);
6425#endif
6426
6427    return res;
6428}
6429
6430/* Set sensor rate */
6431/* this function should be optimized */
6432int MPLSensor::resetDataRates()
6433{
6434    VFUNC_LOG;
6435
6436    int res = 0;
6437    int tempFd = -1;
6438    int64_t wanted = 1000000000LL;
6439
6440    int64_t resetRate;
6441    int64_t gyroRate;
6442    int64_t accelRate;
6443    int64_t compassRate;
6444#ifdef ENABLE_PRESSURE
6445    int64_t pressureRate;
6446#endif
6447
6448    if (!mEnabled) {
6449        LOGV_IF(ENG_VERBOSE, "skip resetDataRates");
6450        return 0;
6451    }
6452    LOGI("HAL:resetDataRates mEnabled=%d", mEnabled);
6453    /* search the minimum delay requested across all enabled sensors */
6454    /* skip setting rates if it is not changed */
6455    for (int i = 0; i < NumSensors; i++) {
6456        if (mEnabled & (1 << i)) {
6457            int64_t ns = mDelays[i];
6458#ifdef ENABLE_PRESSURE
6459            if ((wanted == ns) && (i != Pressure)) {
6460                LOGV_IF(ENG_VERBOSE, "skip resetDataRates : same delay mDelays[%d]=%lld", i,mDelays[i]);
6461                //return 0;
6462            }
6463#endif
6464            LOGV_IF(ENG_VERBOSE, "resetDataRates - mDelays[%d]=%lld", i, mDelays[i]);
6465            wanted = wanted < ns ? wanted : ns;
6466        }
6467    }
6468
6469    resetRate = wanted;
6470    gyroRate = wanted;
6471    accelRate = wanted;
6472    compassRate = wanted;
6473#ifdef ENABLE_PRESSURE
6474    pressureRate = wanted;
6475#endif
6476
6477    /* set mpl data rate */
6478   inv_set_gyro_sample_rate((int)gyroRate/1000LL);
6479   inv_set_accel_sample_rate((int)accelRate/1000LL);
6480   inv_set_compass_sample_rate((int)compassRate/1000LL);
6481   inv_set_linear_acceleration_sample_rate((int)resetRate/1000LL);
6482   inv_set_orientation_sample_rate((int)resetRate/1000LL);
6483   inv_set_rotation_vector_sample_rate((int)resetRate/1000LL);
6484   inv_set_gravity_sample_rate((int)resetRate/1000LL);
6485   inv_set_orientation_geomagnetic_sample_rate((int)resetRate/1000LL);
6486   inv_set_rotation_vector_6_axis_sample_rate((int)resetRate/1000LL);
6487   inv_set_geomagnetic_rotation_vector_sample_rate((int)resetRate/1000LL);
6488
6489    LOGV_IF(PROCESS_VERBOSE,
6490            "HAL:MPL gyro sample rate: (mpl)=%lld us (mpu)=%.2f Hz",
6491            gyroRate/1000LL, 1000000000.f / gyroRate);
6492    LOGV_IF(PROCESS_VERBOSE,
6493            "HAL:MPL accel sample rate: (mpl)=%lld us (mpu)=%.2f Hz",
6494            accelRate/1000LL, 1000000000.f / accelRate);
6495    LOGV_IF(PROCESS_VERBOSE,
6496            "HAL:MPL compass sample rate: (mpl)=%lld us (mpu)=%.2f Hz",
6497            compassRate/1000LL, 1000000000.f / compassRate);
6498
6499    /* reset dmp rate */
6500    getDmpRate (&wanted);
6501
6502    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)",
6503            1000000000.f / wanted, mpu.gyro_fifo_rate,
6504            getTimestamp());
6505    tempFd = open(mpu.gyro_fifo_rate, O_RDWR);
6506    res = write_attribute_sensor(tempFd, 1000000000.f / wanted);
6507    LOGE_IF(res < 0, "HAL:sampling frequency update delay error");
6508
6509    /* takes care of gyro rate */
6510    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)",
6511            1000000000.f / gyroRate, mpu.gyro_rate,
6512            getTimestamp());
6513    tempFd = open(mpu.gyro_rate, O_RDWR);
6514    res = write_attribute_sensor(tempFd, 1000000000.f / gyroRate);
6515    if(res < 0) {
6516        LOGE("HAL:GYRO update delay error");
6517    }
6518
6519    /* takes care of accel rate */
6520    LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)",
6521            1000000000.f / accelRate, mpu.accel_rate,
6522            getTimestamp());
6523    tempFd = open(mpu.accel_rate, O_RDWR);
6524    res = write_attribute_sensor(tempFd, 1000000000.f / accelRate);
6525    LOGE_IF(res < 0, "HAL:ACCEL update delay error");
6526
6527    /* takes care of compass rate */
6528    if (compassRate < mCompassSensor->getMinDelay() * 1000LL) {
6529        compassRate = mCompassSensor->getMinDelay() * 1000LL;
6530    }
6531    mCompassSensor->setDelay(ID_M, compassRate);
6532
6533#ifdef ENABLE_PRESSURE
6534    /* takes care of pressure rate */
6535    mPressureSensor->setDelay(ID_PS, pressureRate);
6536#endif
6537
6538    /* takes care of lpq case for data rate at 200Hz */
6539    if (checkLPQuaternion()) {
6540        if (resetRate <= RATE_200HZ) {
6541#ifndef USE_LPQ_AT_FASTEST
6542            enableLPQuaternion(0);
6543#endif
6544        }
6545    }
6546
6547    return res;
6548}
6549
6550void MPLSensor::resetMplStates()
6551{
6552    VFUNC_LOG;
6553    LOGV_IF(ENG_VERBOSE, "HAL:resetMplStates()");
6554
6555    inv_gyro_was_turned_off();
6556    inv_accel_was_turned_off();
6557    inv_compass_was_turned_off();
6558    inv_quaternion_sensor_was_turned_off();
6559
6560    return;
6561}
6562
6563void MPLSensor::initBias()
6564{
6565    VFUNC_LOG;
6566
6567    LOGV_IF(ENG_VERBOSE, "HAL:inititalize dmp and device offsets to 0");
6568    if(write_attribute_sensor_continuous(accel_x_dmp_bias_fd, 0) < 0) {
6569        LOGE("HAL:Error writing to accel_x_dmp_bias");
6570    }
6571    if(write_attribute_sensor_continuous(accel_y_dmp_bias_fd, 0) < 0) {
6572        LOGE("HAL:Error writing to accel_y_dmp_bias");
6573    }
6574    if(write_attribute_sensor_continuous(accel_z_dmp_bias_fd, 0) < 0) {
6575        LOGE("HAL:Error writing to accel_z_dmp_bias");
6576    }
6577
6578    if(write_attribute_sensor_continuous(accel_x_offset_fd, 0) < 0) {
6579        LOGE("HAL:Error writing to accel_x_offset");
6580    }
6581    if(write_attribute_sensor_continuous(accel_y_offset_fd, 0) < 0) {
6582        LOGE("HAL:Error writing to accel_y_offset");
6583    }
6584    if(write_attribute_sensor_continuous(accel_z_offset_fd, 0) < 0) {
6585        LOGE("HAL:Error writing to accel_z_offset");
6586    }
6587
6588    if(write_attribute_sensor_continuous(gyro_x_dmp_bias_fd, 0) < 0) {
6589        LOGE("HAL:Error writing to gyro_x_dmp_bias");
6590    }
6591    if(write_attribute_sensor_continuous(gyro_y_dmp_bias_fd, 0) < 0) {
6592        LOGE("HAL:Error writing to gyro_y_dmp_bias");
6593    }
6594    if(write_attribute_sensor_continuous(gyro_z_dmp_bias_fd, 0) < 0) {
6595        LOGE("HAL:Error writing to gyro_z_dmp_bias");
6596    }
6597
6598    if(write_attribute_sensor_continuous(gyro_x_offset_fd, 0) < 0) {
6599        LOGE("HAL:Error writing to gyro_x_offset");
6600    }
6601    if(write_attribute_sensor_continuous(gyro_y_offset_fd, 0) < 0) {
6602        LOGE("HAL:Error writing to gyro_y_offset");
6603    }
6604    if(write_attribute_sensor_continuous(gyro_z_offset_fd, 0) < 0) {
6605        LOGE("HAL:Error writing to gyro_z_offset");
6606    }
6607    return;
6608}
6609
6610/*TODO: reg_dump in a separate file*/
6611void MPLSensor::sys_dump(bool fileMode)
6612{
6613    VFUNC_LOG;
6614
6615    char sysfs_path[MAX_SYSFS_NAME_LEN];
6616    char scan_element_path[MAX_SYSFS_NAME_LEN];
6617
6618    memset(sysfs_path, 0, sizeof(sysfs_path));
6619    memset(scan_element_path, 0, sizeof(scan_element_path));
6620    inv_get_sysfs_path(sysfs_path);
6621    sprintf(scan_element_path, "%s%s", sysfs_path, "/scan_elements");
6622
6623    read_sysfs_dir(fileMode, sysfs_path);
6624    read_sysfs_dir(fileMode, scan_element_path);
6625
6626    dump_dmp_img("/data/local/read_img.h");
6627    return;
6628}
6629