summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>2017-08-23 20:41:07 +0200
committerPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>2017-08-23 20:41:07 +0200
commitf3ab5ba87e6c8594f8ec98435cdfc8ea429a261c (patch)
treec2569044fd8335ebbcc3a5cda0959b20075bc816
Import of Rockchip Android 7.1.1 SDKHEADmaster
-rw-r--r--Android.mk10
-rwxr-xr-xmpu/Android.mk1
-rwxr-xr-xmpu/akm8963/AKCommon.h51
-rwxr-xr-xmpu/akm8963/AKCompass.h164
-rwxr-xr-xmpu/akm8963/AKMD_Driver.c570
-rwxr-xr-xmpu/akm8963/AKMD_Driver.h284
-rwxr-xr-xmpu/akm8963/AKMLog.h160
-rwxr-xr-xmpu/akm8963/Acc_aot.c93
-rwxr-xr-xmpu/akm8963/Acc_aot.h45
-rwxr-xr-xmpu/akm8963/Acc_mma8452.c346
-rwxr-xr-xmpu/akm8963/Acc_mma8452.h75
-rwxr-xr-xmpu/akm8963/Android.mk82
-rwxr-xr-xmpu/akm8963/CustomerSpec.h75
-rwxr-xr-xmpu/akm8963/DispMessage.c127
-rwxr-xr-xmpu/akm8963/DispMessage.h61
-rwxr-xr-xmpu/akm8963/FST.h33
-rwxr-xr-xmpu/akm8963/FST_AK09911.c759
-rwxr-xr-xmpu/akm8963/FST_AK8963.c510
-rwxr-xr-xmpu/akm8963/FST_AK8975.c454
-rwxr-xr-xmpu/akm8963/FileIO.c436
-rwxr-xr-xmpu/akm8963/FileIO.h98
-rwxr-xr-xmpu/akm8963/Measure.c1350
-rwxr-xr-xmpu/akm8963/Measure.h116
-rwxr-xr-xmpu/akm8963/custom_log.h163
-rwxr-xr-xmpu/akm8963/libSmartCompass/AKCertification.h37
-rwxr-xr-xmpu/akm8963/libSmartCompass/AKConfigure.h73
-rwxr-xr-xmpu/akm8963/libSmartCompass/AKDOEPlus.h68
-rwxr-xr-xmpu/akm8963/libSmartCompass/AKDecomp.h61
-rwxr-xr-xmpu/akm8963/libSmartCompass/AKDirection6D.h79
-rwxr-xr-xmpu/akm8963/libSmartCompass/AKHDOE.h102
-rwxr-xr-xmpu/akm8963/libSmartCompass/AKHFlucCheck.h61
-rwxr-xr-xmpu/akm8963/libSmartCompass/AKMDevice.h114
-rwxr-xr-xmpu/akm8963/libSmartCompass/AKMDeviceF.h110
-rwxr-xr-xmpu/akm8963/libSmartCompass/AKManualCal.h43
-rwxr-xr-xmpu/akm8963/libSmartCompass/AKPseudoGyro.h86
-rwxr-xr-xmpu/akm8963/libSmartCompass/AKVersion.h44
-rwxr-xr-xmpu/akm8963/libSmartCompass/libAK09911wPG.abin0 -> 60028 bytes
-rwxr-xr-xmpu/akm8963/libSmartCompass/libAK8963wPGplus.abin0 -> 90828 bytes
-rwxr-xr-xmpu/akm8963/main.c473
-rwxr-xr-xmpu/akm8963/misc.c319
-rwxr-xr-xmpu/akm8963/misc.h66
-rwxr-xr-xmpu/akm8963/mma8452_kernel.h136
-rwxr-xr-xmpu/akm8963/sensors_io.h169
-rwxr-xr-xmpu/libsensors/AkmSensor.cpp301
-rwxr-xr-xmpu/libsensors/AkmSensor.h75
-rwxr-xr-xmpu/libsensors/Android.mk246
-rwxr-xr-xmpu/libsensors/BUILD.sh22
-rwxr-xr-xmpu/libsensors/CompassSensor.AKM.cpp180
-rwxr-xr-xmpu/libsensors/CompassSensor.AKM.h79
-rwxr-xr-xmpu/libsensors/CompassSensor.IIO.9150.cpp435
-rwxr-xr-xmpu/libsensors/CompassSensor.IIO.9150.h94
-rwxr-xr-xmpu/libsensors/CompassSensor.IIO.primary.cpp636
-rwxr-xr-xmpu/libsensors/CompassSensor.IIO.primary.h119
-rwxr-xr-xmpu/libsensors/CompassSensor.YAMAHA.cpp155
-rwxr-xr-xmpu/libsensors/CompassSensor.YAMAHA.h83
-rwxr-xr-xmpu/libsensors/InputEventReader.cpp114
-rwxr-xr-xmpu/libsensors/InputEventReader.h50
-rwxr-xr-xmpu/libsensors/LICENSE-libinvensense_mpl.TXT217
-rwxr-xr-xmpu/libsensors/LightSensor.cpp91
-rwxr-xr-xmpu/libsensors/LightSensor.h56
-rwxr-xr-xmpu/libsensors/MPL integration notes.txt53
-rwxr-xr-xmpu/libsensors/MPLSensor.cpp3576
-rwxr-xr-xmpu/libsensors/MPLSensor.h354
-rwxr-xr-xmpu/libsensors/MPLSensorSysApi.cpp179
-rwxr-xr-xmpu/libsensors/MPLSensorSysApi.h47
-rwxr-xr-xmpu/libsensors/MPLSensorSysPed.cpp451
-rwxr-xr-xmpu/libsensors/MPLSensorSysPed.h70
-rwxr-xr-xmpu/libsensors/MPLSupport.cpp234
-rwxr-xr-xmpu/libsensors/MPLSupport.h33
-rw-r--r--mpu/libsensors/MyTransform.cpp219
-rw-r--r--mpu/libsensors/MyTransform.h82
-rwxr-xr-xmpu/libsensors/SamsungSensorBase.cpp178
-rwxr-xr-xmpu/libsensors/SamsungSensorBase.h59
-rwxr-xr-xmpu/libsensors/SensorBase.cpp142
-rwxr-xr-xmpu/libsensors/SensorBase.h102
-rwxr-xr-xmpu/libsensors/YamahaSensor.cpp369
-rwxr-xr-xmpu/libsensors/YamahaSensor.h54
-rwxr-xr-xmpu/libsensors/akm8975.h28
-rwxr-xr-xmpu/libsensors/inv_32/BUILD.sh46
-rwxr-xr-xmpu/libsensors/inv_32/build/android/common.mk87
-rwxr-xr-xmpu/libsensors/inv_32/build/android/shared.mk75
-rwxr-xr-xmpu/libsensors/inv_32/core/driver/include/linux/mpu.h109
-rwxr-xr-xmpu/libsensors/inv_32/core/driver/include/log.h368
-rwxr-xr-xmpu/libsensors/inv_32/core/driver/include/mlinclude.h38
-rwxr-xr-xmpu/libsensors/inv_32/core/driver/include/mlmath.h95
-rwxr-xr-xmpu/libsensors/inv_32/core/driver/include/mlsl.h283
-rwxr-xr-xmpu/libsensors/inv_32/core/driver/include/mltypes.h235
-rwxr-xr-xmpu/libsensors/inv_32/core/driver/include/stdint_invensense.h41
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/libmllite.sobin0 -> 91592 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/obj/data_builder.c.obin0 -> 51692 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/obj/hal_outputs.c.obin0 -> 16404 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/obj/message_layer.c.obin0 -> 2052 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/obj/ml_load_dmp.c.obin0 -> 5684 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/obj/ml_math_func.c.obin0 -> 35604 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/obj/ml_stored_data.c.obin0 -> 8876 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/obj/ml_sysfs_helper.c.obin0 -> 15980 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/obj/mlos_linux.c.obin0 -> 6732 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/obj/mpl.c.obin0 -> 4100 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/obj/results_holder.c.obin0 -> 25164 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/obj/start_manager.c.obin0 -> 3960 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/obj/storage_manager.c.obin0 -> 5992 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/android/shared.mk87
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/build/filelist.mk42
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/data_builder.c1240
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/data_builder.h283
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/hal_outputs.c490
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/hal_outputs.h45
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/invensense.h28
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/linux/inv_sysfs_utils.c318
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/linux/inv_sysfs_utils.h84
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/linux/ml_load_dmp.c281
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/linux/ml_load_dmp.h33
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/linux/ml_stored_data.c353
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/linux/ml_stored_data.h53
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/linux/ml_sysfs_helper.c431
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/linux/ml_sysfs_helper.h36
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/linux/mlos.h99
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/linux/mlos_linux.c190
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/message_layer.c59
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/message_layer.h35
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/ml_math_func.c725
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/ml_math_func.h122
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/mpl.c72
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/mpl.h24
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/results_holder.c522
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/results_holder.h81
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/start_manager.c105
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/start_manager.h27
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/storage_manager.c202
-rwxr-xr-xmpu/libsensors/inv_32/core/mllite/storage_manager.h30
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/accel_auto_cal.h38
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/authenticate.h21
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/build/android/libmplmpu.sobin0 -> 171084 bytes
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/build/android/shared.mk88
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/build/filelist.mk46
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/compass_bias_w_gyro.h31
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/compass_fit.h28
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/compass_vec_cal.h34
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/fast_no_motion.h46
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/fusion_9axis.h37
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/gyro_tc.h43
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/heading_from_gyro.h33
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/inv_math.h8
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/invensense_adv.h31
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/mag_disturb.h37
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/motion_no_motion.h28
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/no_gyro_fusion.h34
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/quat_accuracy_monitor.h71
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/quaternion_supervisor.h27
-rwxr-xr-xmpu/libsensors/inv_32/core/mpl/shake.h94
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/gesture_test/build/android/inv_gesture_test-sharedbin0 -> 13952 bytes
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/gesture_test/build/android/obj/inv_gesture_test.c.obin0 -> 18108 bytes
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/gesture_test/build/android/shared.mk96
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/gesture_test/build/filelist.mk11
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/gesture_test/inv_gesture_test.c560
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/mpu_iio/build/android/inv_mpu_iio-sharedbin0 -> 31360 bytes
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/mpu_iio/build/android/obj/mpu_iio.c.obin0 -> 46628 bytes
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/mpu_iio/build/android/shared.mk94
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/mpu_iio/build/filelist.mk12
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/mpu_iio/iio_utils.h650
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/mpu_iio/mpu_iio.c932
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/self_test/build/android/inv_self_test-sharedbin0 -> 17716 bytes
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/self_test/build/android/obj/inv_self_test.c.obin0 -> 19556 bytes
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/self_test/build/android/shared.mk98
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/self_test/build/filelist.mk11
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/self_test/inv_self_test.c613
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/stress_iio/README27
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/stress_iio/build/android/inv_stress_iio-sharedbin0 -> 28320 bytes
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/stress_iio/build/android/obj/stress_iio.c.obin0 -> 46940 bytes
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/stress_iio/build/android/shared.mk94
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/stress_iio/build/filelist.mk12
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/stress_iio/iio_utils.h650
-rwxr-xr-xmpu/libsensors/inv_32/simple_apps/stress_iio/stress_iio.c721
-rwxr-xr-xmpu/libsensors/inv_64/BUILD.sh21
-rwxr-xr-xmpu/libsensors/inv_64/build/android/common.mk98
-rwxr-xr-xmpu/libsensors/inv_64/build/android/shared.mk75
-rwxr-xr-xmpu/libsensors/inv_64/core/driver/include/linux/mpu.h109
-rwxr-xr-xmpu/libsensors/inv_64/core/driver/include/log.h380
-rwxr-xr-xmpu/libsensors/inv_64/core/driver/include/mlinclude.h38
-rwxr-xr-xmpu/libsensors/inv_64/core/driver/include/mlmath.h95
-rwxr-xr-xmpu/libsensors/inv_64/core/driver/include/mlsl.h283
-rwxr-xr-xmpu/libsensors/inv_64/core/driver/include/mltypes.h237
-rwxr-xr-xmpu/libsensors/inv_64/core/driver/include/stdint_invensense.h41
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/libmllite.sobin0 -> 91688 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/obj/data_builder.c.obin0 -> 46824 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/obj/hal_outputs.c.obin0 -> 15448 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/obj/message_layer.c.obin0 -> 2168 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/obj/ml_load_dmp.c.obin0 -> 5984 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/obj/ml_math_func.c.obin0 -> 25992 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/obj/ml_stored_data.c.obin0 -> 10016 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/obj/ml_sysfs_helper.c.obin0 -> 17520 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/obj/mlos_linux.c.obin0 -> 5560 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/obj/mpl.c.obin0 -> 4176 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/obj/results_holder.c.obin0 -> 20712 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/obj/start_manager.c.obin0 -> 3880 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/obj/storage_manager.c.obin0 -> 6128 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/android/shared.mk87
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/build/filelist.mk42
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/data_builder.c1240
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/data_builder.h283
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/hal_outputs.c490
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/hal_outputs.h45
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/invensense.h28
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/linux/inv_sysfs_utils.c318
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/linux/inv_sysfs_utils.h84
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/linux/ml_load_dmp.c281
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/linux/ml_load_dmp.h33
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/linux/ml_stored_data.c353
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/linux/ml_stored_data.h53
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/linux/ml_sysfs_helper.c431
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/linux/ml_sysfs_helper.h36
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/linux/mlos.h99
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/linux/mlos_linux.c190
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/message_layer.c59
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/message_layer.h35
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/ml_math_func.c725
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/ml_math_func.h122
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/mpl.c72
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/mpl.h24
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/results_holder.c522
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/results_holder.h81
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/start_manager.c105
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/start_manager.h27
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/storage_manager.c202
-rwxr-xr-xmpu/libsensors/inv_64/core/mllite/storage_manager.h30
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/accel_auto_cal.h38
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/authenticate.h21
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/build/android/libmplmpu.sobin0 -> 163130 bytes
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/build/android/shared.mk88
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/build/filelist.mk46
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/compass_bias_w_gyro.h31
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/compass_fit.h28
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/compass_vec_cal.h34
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/fast_no_motion.h46
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/fusion_9axis.h37
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/gyro_tc.h43
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/heading_from_gyro.h33
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/inv_math.h8
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/invensense_adv.h31
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/mag_disturb.h37
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/motion_no_motion.h28
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/no_gyro_fusion.h34
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/quat_accuracy_monitor.h71
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/quaternion_supervisor.h27
-rwxr-xr-xmpu/libsensors/inv_64/core/mpl/shake.h94
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/gesture_test/build/android/inv_gesture_test-sharedbin0 -> 13952 bytes
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/gesture_test/build/android/shared.mk96
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/gesture_test/build/filelist.mk11
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/gesture_test/inv_gesture_test.c560
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/mpu_iio/build/android/inv_mpu_iio-sharedbin0 -> 31360 bytes
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/mpu_iio/build/android/shared.mk94
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/mpu_iio/build/filelist.mk12
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/mpu_iio/iio_utils.h650
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/mpu_iio/mpu_iio.c932
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/self_test/build/android/gcc.help3003
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/self_test/build/android/inv_self_test-sharedbin0 -> 22592 bytes
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/self_test/build/android/obj/inv_self_test.c.obin0 -> 26400 bytes
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/self_test/build/android/shared.mk100
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/self_test/build/filelist.mk11
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/self_test/inv_self_test.c613
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/stress_iio/README27
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/stress_iio/build/android/inv_stress_iio-sharedbin0 -> 28320 bytes
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/stress_iio/build/android/shared.mk94
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/stress_iio/build/filelist.mk12
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/stress_iio/iio_utils.h650
-rwxr-xr-xmpu/libsensors/inv_64/simple_apps/stress_iio/stress_iio.c721
-rwxr-xr-xmpu/libsensors/libmllite.sobin0 -> 91592 bytes
-rwxr-xr-xmpu/libsensors/libmllite_64.sobin0 -> 91688 bytes
-rwxr-xr-xmpu/libsensors/libmplmpu.sobin0 -> 171084 bytes
-rwxr-xr-xmpu/libsensors/libmplmpu_64.sobin0 -> 163130 bytes
-rwxr-xr-xmpu/libsensors/sensor_params.h197
-rwxr-xr-xmpu/libsensors/sensors.h99
-rwxr-xr-xmpu/libsensors/sensors_mpl.cpp390
-rwxr-xr-xmpu/libsensors/tags4677
-rwxr-xr-xmpu/libsensors/yamaha/drv/3.10/yas_mag_drv-yas532.c823
-rwxr-xr-xmpu/libsensors/yamaha/drv/3.10/yas_mag_drv-yas537.c789
-rwxr-xr-xmpu/libsensors/yamaha/drv/3.10/yas_mag_kernel.c878
-rwxr-xr-xmpu/libsensors/yamaha/drv/3.4/yas_mag_drv-yas532.c823
-rwxr-xr-xmpu/libsensors/yamaha/drv/3.4/yas_mag_drv-yas537.c789
-rwxr-xr-xmpu/libsensors/yamaha/drv/3.4/yas_mag_kernel.c893
-rwxr-xr-xmpu/libsensors/yamaha/hal/CompassSensor.YAMAHA.cpp177
-rwxr-xr-xmpu/libsensors/yamaha/hal/CompassSensor.YAMAHA.h83
-rwxr-xr-xmpu/libsensors/yamaha/hal/YamahaSensor.cpp371
-rwxr-xr-xmpu/libsensors/yamaha/hal/YamahaSensor.h53
-rwxr-xr-xmpu/libsensors/yamaha/inc/yas.h2001
-rwxr-xr-xmpu/libsensors/yamaha/inc/yas_android_lib.h125
-rwxr-xr-xmpu/libsensors/yamaha/inc/yas_cfg.h245
-rwxr-xr-xmpu/libsensors/yamaha/lib/Android.mk51
-rwxr-xr-xmpu/libsensors/yamaha/lib/libyas_mag_algo.abin0 -> 475920 bytes
-rwxr-xr-xmpu/libsensors/yamaha/lib/libyas_mag_algo_32.abin0 -> 735556 bytes
-rwxr-xr-xmpu/libsensors/yamaha/lib/libyas_mag_algo_64.abin0 -> 1436436 bytes
-rwxr-xr-xmpu/libsensors/yamaha/lib/sysfs_util.h25
-rwxr-xr-xmpu/libsensors/yamaha/lib/yas_android_lib.c574
-rwxr-xr-xmpu/libsensors/yamaha/lib/yas_float.h331
-rwxr-xr-xmpu/libsensors/yamaha/lib/yas_mag_file.h30
-rwxr-xr-xmpu/libsensors/yamaha/lib/yas_math.h302
-rwxr-xr-xmpu_vr/Android.mk1
-rwxr-xr-xmpu_vr/akm8963-64/AKCommon.h51
-rwxr-xr-xmpu_vr/akm8963-64/AKCompass.h164
-rwxr-xr-xmpu_vr/akm8963-64/AKMD_Driver.c570
-rwxr-xr-xmpu_vr/akm8963-64/AKMD_Driver.h284
-rwxr-xr-xmpu_vr/akm8963-64/AKMLog.h160
-rwxr-xr-xmpu_vr/akm8963-64/Acc_aot.c93
-rwxr-xr-xmpu_vr/akm8963-64/Acc_aot.h45
-rwxr-xr-xmpu_vr/akm8963-64/Acc_mma8452.c346
-rwxr-xr-xmpu_vr/akm8963-64/Acc_mma8452.h75
-rwxr-xr-xmpu_vr/akm8963-64/Android.mk82
-rwxr-xr-xmpu_vr/akm8963-64/CustomerSpec.h75
-rwxr-xr-xmpu_vr/akm8963-64/DispMessage.c127
-rwxr-xr-xmpu_vr/akm8963-64/DispMessage.h61
-rwxr-xr-xmpu_vr/akm8963-64/FST.h33
-rwxr-xr-xmpu_vr/akm8963-64/FST_AK09911.c759
-rwxr-xr-xmpu_vr/akm8963-64/FST_AK8963.c510
-rwxr-xr-xmpu_vr/akm8963-64/FST_AK8975.c454
-rwxr-xr-xmpu_vr/akm8963-64/FileIO.c436
-rwxr-xr-xmpu_vr/akm8963-64/FileIO.h98
-rwxr-xr-xmpu_vr/akm8963-64/Measure.c1350
-rwxr-xr-xmpu_vr/akm8963-64/Measure.h116
-rwxr-xr-xmpu_vr/akm8963-64/custom_log.h163
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/AKCertification.h37
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/AKConfigure.h73
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/AKDOEPlus.h68
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/AKDecomp.h61
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/AKDirection6D.h79
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/AKHDOE.h102
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/AKHFlucCheck.h61
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/AKMDevice.h114
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/AKMDeviceF.h110
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/AKManualCal.h43
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/AKPseudoGyro.h86
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/AKVersion.h44
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/libAK09911wPG.abin0 -> 60028 bytes
-rwxr-xr-xmpu_vr/akm8963-64/libSmartCompass/libAK8963wPGplus.abin0 -> 90828 bytes
-rwxr-xr-xmpu_vr/akm8963-64/main.c473
-rwxr-xr-xmpu_vr/akm8963-64/misc.c319
-rwxr-xr-xmpu_vr/akm8963-64/misc.h66
-rwxr-xr-xmpu_vr/akm8963-64/mma8452_kernel.h136
-rwxr-xr-xmpu_vr/akm8963-64/sensors_io.h169
-rwxr-xr-xmpu_vr/akm8963/AK8963Driver.c382
-rwxr-xr-xmpu_vr/akm8963/AK8963Driver.h111
-rwxr-xr-xmpu_vr/akm8963/AKCommon.h147
-rwxr-xr-xmpu_vr/akm8963/AKCompass.h133
-rwxr-xr-xmpu_vr/akm8963/Android.mk47
-rwxr-xr-xmpu_vr/akm8963/CustomerSpec.h106
-rwxr-xr-xmpu_vr/akm8963/DispMessage.c184
-rwxr-xr-xmpu_vr/akm8963/DispMessage.h65
-rwxr-xr-xmpu_vr/akm8963/FileIO.c333
-rwxr-xr-xmpu_vr/akm8963/FileIO.h96
-rwxr-xr-xmpu_vr/akm8963/Measure.c1358
-rwxr-xr-xmpu_vr/akm8963/Measure.h117
-rwxr-xr-xmpu_vr/akm8963/TestLimit.h157
-rwxr-xr-xmpu_vr/akm8963/akm8963.h102
-rwxr-xr-xmpu_vr/akm8963/custom_log.h163
-rwxr-xr-xmpu_vr/akm8963/libAK8963/AK8963.h54
-rwxr-xr-xmpu_vr/akm8963/libAK8963/AKCertification.h33
-rwxr-xr-xmpu_vr/akm8963/libAK8963/AKConfigure.h47
-rwxr-xr-xmpu_vr/akm8963/libAK8963/AKDirection6D.h75
-rwxr-xr-xmpu_vr/akm8963/libAK8963/AKHDOE.h98
-rwxr-xr-xmpu_vr/akm8963/libAK8963/AKHFlucCheck.h57
-rwxr-xr-xmpu_vr/akm8963/libAK8963/AKMDevice.h84
-rwxr-xr-xmpu_vr/akm8963/libAK8963/AKManualCal.h39
-rwxr-xr-xmpu_vr/akm8963/libAK8963/AKVersion.h39
-rwxr-xr-xmpu_vr/akm8963/libAK8963/libAK8963.abin0 -> 43338 bytes
-rwxr-xr-xmpu_vr/akm8963/main.c340
-rwxr-xr-xmpu_vr/akm8963/misc.c259
-rwxr-xr-xmpu_vr/akm8963/misc.h61
-rwxr-xr-xmpu_vr/libsensors/AkmSensor.cpp342
-rwxr-xr-xmpu_vr/libsensors/AkmSensor.h68
-rwxr-xr-xmpu_vr/libsensors/Android.mk296
-rwxr-xr-xmpu_vr/libsensors/CompassSensor.AKM.cpp213
-rwxr-xr-xmpu_vr/libsensors/CompassSensor.AKM.h82
-rwxr-xr-xmpu_vr/libsensors/CompassSensor.IIO.9150.cpp648
-rwxr-xr-xmpu_vr/libsensors/CompassSensor.IIO.9150.h107
-rwxr-xr-xmpu_vr/libsensors/CompassSensor.IIO.primary.cpp569
-rwxr-xr-xmpu_vr/libsensors/CompassSensor.IIO.primary.h116
-rwxr-xr-xmpu_vr/libsensors/InputEventReader.cpp114
-rwxr-xr-xmpu_vr/libsensors/InputEventReader.h50
-rw-r--r--mpu_vr/libsensors/LightSensor.cpp91
-rw-r--r--mpu_vr/libsensors/LightSensor.h56
-rwxr-xr-xmpu_vr/libsensors/MPLSensor.cpp4091
-rwxr-xr-xmpu_vr/libsensors/MPLSensor.h402
-rwxr-xr-xmpu_vr/libsensors/MPLSupport.cpp231
-rwxr-xr-xmpu_vr/libsensors/MPLSupport.h33
-rwxr-xr-xmpu_vr/libsensors/ProximitySensor.cpp141
-rwxr-xr-xmpu_vr/libsensors/ProximitySensor.h61
-rwxr-xr-xmpu_vr/libsensors/README_L_arm6416
-rw-r--r--mpu_vr/libsensors/SamsungSensorBase.cpp185
-rw-r--r--mpu_vr/libsensors/SamsungSensorBase.h59
-rwxr-xr-xmpu_vr/libsensors/SensorBase.cpp234
-rwxr-xr-xmpu_vr/libsensors/SensorBase.h108
-rwxr-xr-xmpu_vr/libsensors/akm8975.h28
-rwxr-xr-xmpu_vr/libsensors/libmllite.sobin0 -> 117840 bytes
-rwxr-xr-xmpu_vr/libsensors/libmllite_64.sobin0 -> 116088 bytes
-rwxr-xr-xmpu_vr/libsensors/libmplmpu.sobin0 -> 172208 bytes
-rwxr-xr-xmpu_vr/libsensors/libmplmpu_64.sobin0 -> 169716 bytes
-rwxr-xr-xmpu_vr/libsensors/sensor_params.h199
-rwxr-xr-xmpu_vr/libsensors/sensors.h108
-rwxr-xr-xmpu_vr/libsensors/sensors_mpl.cpp705
-rwxr-xr-xmpu_vr/libsensors/software/build/android/common.mk136
-rwxr-xr-xmpu_vr/libsensors/software/build/android/shared.mk75
-rwxr-xr-xmpu_vr/libsensors/software/core/driver/include/linux/mpu.h108
-rwxr-xr-xmpu_vr/libsensors/software/core/driver/include/log.h393
-rwxr-xr-xmpu_vr/libsensors/software/core/driver/include/mlinclude.h38
-rwxr-xr-xmpu_vr/libsensors/software/core/driver/include/mlmath.h95
-rwxr-xr-xmpu_vr/libsensors/software/core/driver/include/mlsl.h283
-rwxr-xr-xmpu_vr/libsensors/software/core/driver/include/mltypes.h235
-rwxr-xr-xmpu_vr/libsensors/software/core/driver/include/stdint_invensense.h41
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/build/android/shared.mk104
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/build/filelist.mk42
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/data_builder.h291
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/hal_outputs.h57
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/invensense.h28
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/linux/inv_sysfs_utils.h84
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/linux/ml_load_dmp.h33
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/linux/ml_stored_data.h53
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/linux/ml_sysfs_helper.h37
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/linux/mlos.h99
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/message_layer.h41
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/ml_math_func.h128
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/mpl.h24
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/results_holder.h89
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/start_manager.h27
-rwxr-xr-xmpu_vr/libsensors/software/core/mllite/storage_manager.h30
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/accel_auto_cal.h38
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/authenticate.h21
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/build/android/libmplmpu.sobin0 -> 172208 bytes
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/build/android/shared.mk106
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/build/filelist.mk46
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/compass_bias_w_gyro.h31
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/compass_fit.h28
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/compass_vec_cal.h36
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/fast_no_motion.h52
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/fusion_9axis.h37
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/gyro_tc.h43
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/heading_from_gyro.h33
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/inv_math.h8
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/invensense_adv.h31
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/mag_disturb.h63
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/motion_no_motion.h31
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/no_gyro_fusion.h34
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/quat_accuracy_monitor.h71
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/quaternion_supervisor.h27
-rwxr-xr-xmpu_vr/libsensors/software/core/mpl/shake.h94
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/common/console_helper.c54
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/common/console_helper.h33
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/common/mlerrorcode.c96
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/common/mlerrorcode.h86
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/common/testsupport.h57
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/gesture_test/build/android/inv_gesture_test-sharedbin0 -> 16784 bytes
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/gesture_test/build/android/shared.mk118
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/gesture_test/build/filelist.mk11
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/gesture_test/inv_gesture_test.c665
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/mpu_iio/build/android/inv_mpu_iio-sharedbin0 -> 31868 bytes
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/mpu_iio/build/android/shared.mk117
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/mpu_iio/build/filelist.mk12
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/mpu_iio/iio_utils.h650
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/mpu_iio/mpu_iio.c937
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/playback/linux/and_constructor.c379
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/playback/linux/and_constructor.h62
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/playback/linux/build/android/inv_playback-sharedbin0 -> 17512 bytes
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/playback/linux/build/android/shared.mk119
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/playback/linux/build/filelist.mk20
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/playback/linux/datalogger_outputs.c384
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/playback/linux/datalogger_outputs.h61
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/playback/linux/main.c897
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/self_test/build/android/inv_self_test-sharedbin0 -> 16112 bytes
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/self_test/build/android/shared.mk122
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/self_test/build/filelist.mk11
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/self_test/inv_self_test.c530
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/stress_iio/README27
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/stress_iio/build/android/shared.mk117
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/stress_iio/build/filelist.mk12
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/stress_iio/iio_utils.h651
-rwxr-xr-xmpu_vr/libsensors/software/simple_apps/stress_iio/stress_iio.c753
-rwxr-xr-xst/AkmSensor.cpp346
-rwxr-xr-xst/AkmSensor.h69
-rwxr-xr-xst/Android.mk101
-rwxr-xr-xst/GyroSensor.cpp282
-rwxr-xr-xst/GyroSensor.h58
-rwxr-xr-xst/InputEventReader.cpp107
-rwxr-xr-xst/InputEventReader.h50
-rw-r--r--st/LibFusion_ARM_cpp.abin0 -> 96268 bytes
-rwxr-xr-xst/LightSensor.cpp152
-rwxr-xr-xst/LightSensor.h52
-rw-r--r--st/MEMSAlgLib_Fusion.h136
-rwxr-xr-xst/MEMSAlgLib_SI_ARM_cpp.abin0 -> 195054 bytes
-rw-r--r--st/MEMSAlgLib_eCompass.h161
-rwxr-xr-xst/MODULE_LICENSE_APACHE20
-rwxr-xr-xst/MmaSensor.cpp589
-rwxr-xr-xst/MmaSensor.h63
-rwxr-xr-xst/NOTICE190
-rwxr-xr-xst/PressureSensor.cpp155
-rwxr-xr-xst/PressureSensor.h64
-rwxr-xr-xst/ProximitySensor.cpp142
-rwxr-xr-xst/ProximitySensor.h52
-rwxr-xr-xst/SensorBase.cpp197
-rwxr-xr-xst/SensorBase.h69
-rwxr-xr-xst/TemperatureSensor.cpp155
-rwxr-xr-xst/TemperatureSensor.h65
-rwxr-xr-xst/akm09911/AKCommon.h51
-rwxr-xr-xst/akm09911/AKCompass.h137
-rwxr-xr-xst/akm09911/AKMD_Driver.c515
-rwxr-xr-xst/akm09911/AKMD_Driver.h157
-rwxr-xr-xst/akm09911/AKMLog.h156
-rwxr-xr-xst/akm09911/Acc_aot.c93
-rwxr-xr-xst/akm09911/Acc_aot.h45
-rwxr-xr-xst/akm09911/Acc_mma8452.c343
-rwxr-xr-xst/akm09911/Acc_mma8452.h72
-rwxr-xr-xst/akm09911/Android.mk36
-rwxr-xr-xst/akm09911/CustomerSpec.h56
-rwxr-xr-xst/akm09911/DispMessage.c126
-rwxr-xr-xst/akm09911/DispMessage.h61
-rwxr-xr-xst/akm09911/FST.h33
-rwxr-xr-xst/akm09911/FST_AK09911.c361
-rwxr-xr-xst/akm09911/FileIO.c376
-rwxr-xr-xst/akm09911/FileIO.h86
-rwxr-xr-xst/akm09911/Measure.c998
-rwxr-xr-xst/akm09911/Measure.h110
-rwxr-xr-xst/akm09911/akm09911.h102
-rwxr-xr-xst/akm09911/custom_log.h163
-rwxr-xr-xst/akm09911/libSmartCompass/AKCertification.h37
-rwxr-xr-xst/akm09911/libSmartCompass/AKConfigure.h51
-rwxr-xr-xst/akm09911/libSmartCompass/AKDecomp.h61
-rwxr-xr-xst/akm09911/libSmartCompass/AKDirection6D.h79
-rwxr-xr-xst/akm09911/libSmartCompass/AKHDOE.h102
-rwxr-xr-xst/akm09911/libSmartCompass/AKHFlucCheck.h61
-rwxr-xr-xst/akm09911/libSmartCompass/AKMDevice.h88
-rwxr-xr-xst/akm09911/libSmartCompass/AKManualCal.h43
-rwxr-xr-xst/akm09911/libSmartCompass/AKVersion.h44
-rwxr-xr-xst/akm09911/libSmartCompass/libAK09911.abin0 -> 42546 bytes
-rwxr-xr-xst/akm09911/main.c338
-rwxr-xr-xst/akm09911/misc.c263
-rwxr-xr-xst/akm09911/misc.h61
-rwxr-xr-xst/akm09911/mma8452_kernel.h136
-rwxr-xr-xst/akm8963-64/AKCommon.h51
-rwxr-xr-xst/akm8963-64/AKCompass.h164
-rwxr-xr-xst/akm8963-64/AKMD_Driver.c513
-rwxr-xr-xst/akm8963-64/AKMD_Driver.h284
-rwxr-xr-xst/akm8963-64/AKMLog.h160
-rwxr-xr-xst/akm8963-64/Acc_aot.c93
-rwxr-xr-xst/akm8963-64/Acc_aot.h45
-rw-r--r--st/akm8963-64/Acc_mma8452.c346
-rwxr-xr-xst/akm8963-64/Acc_mma8452.h75
-rwxr-xr-xst/akm8963-64/Android.mk83
-rwxr-xr-xst/akm8963-64/CustomerSpec.h75
-rwxr-xr-xst/akm8963-64/DispMessage.c127
-rwxr-xr-xst/akm8963-64/DispMessage.h61
-rwxr-xr-xst/akm8963-64/FST.h33
-rwxr-xr-xst/akm8963-64/FST_AK09911.c759
-rwxr-xr-xst/akm8963-64/FST_AK8963.c510
-rwxr-xr-xst/akm8963-64/FST_AK8975.c454
-rwxr-xr-xst/akm8963-64/FileIO.c436
-rwxr-xr-xst/akm8963-64/FileIO.h98
-rwxr-xr-xst/akm8963-64/Measure.c1350
-rwxr-xr-xst/akm8963-64/Measure.h116
-rwxr-xr-xst/akm8963-64/custom_log.h163
-rwxr-xr-xst/akm8963-64/libSmartCompass/AKCertification.h37
-rwxr-xr-xst/akm8963-64/libSmartCompass/AKConfigure.h73
-rwxr-xr-xst/akm8963-64/libSmartCompass/AKDOEPlus.h68
-rwxr-xr-xst/akm8963-64/libSmartCompass/AKDecomp.h61
-rwxr-xr-xst/akm8963-64/libSmartCompass/AKDirection6D.h79
-rwxr-xr-xst/akm8963-64/libSmartCompass/AKHDOE.h102
-rwxr-xr-xst/akm8963-64/libSmartCompass/AKHFlucCheck.h61
-rwxr-xr-xst/akm8963-64/libSmartCompass/AKMDevice.h114
-rwxr-xr-xst/akm8963-64/libSmartCompass/AKMDeviceF.h110
-rwxr-xr-xst/akm8963-64/libSmartCompass/AKManualCal.h43
-rwxr-xr-xst/akm8963-64/libSmartCompass/AKPseudoGyro.h86
-rwxr-xr-xst/akm8963-64/libSmartCompass/AKVersion.h44
-rwxr-xr-xst/akm8963-64/libSmartCompass/libAK09911wPG.abin0 -> 60028 bytes
-rwxr-xr-xst/akm8963-64/libSmartCompass/libAK8963wPGplus.abin0 -> 90828 bytes
-rw-r--r--st/akm8963-64/main.c477
-rwxr-xr-xst/akm8963-64/misc.c319
-rwxr-xr-xst/akm8963-64/misc.h66
-rwxr-xr-xst/akm8963-64/mma8452_kernel.h136
-rwxr-xr-xst/akm8963-64/sensors_io.h169
-rwxr-xr-xst/akm8963/AK8963Driver.c397
-rwxr-xr-xst/akm8963/AK8963Driver.h111
-rwxr-xr-xst/akm8963/AKCommon.h147
-rwxr-xr-xst/akm8963/AKCompass.h133
-rwxr-xr-xst/akm8963/Acc_aot.c50
-rwxr-xr-xst/akm8963/Acc_aot.h37
-rwxr-xr-xst/akm8963/Acc_mma8452.c314
-rw-r--r--st/akm8963/Acc_mma8452.h72
-rwxr-xr-xst/akm8963/Android.mk30
-rwxr-xr-xst/akm8963/CustomerSpec.h106
-rwxr-xr-xst/akm8963/DispMessage.c184
-rwxr-xr-xst/akm8963/DispMessage.h65
-rwxr-xr-xst/akm8963/FileIO.c333
-rwxr-xr-xst/akm8963/FileIO.h96
-rwxr-xr-xst/akm8963/Measure.c1356
-rwxr-xr-xst/akm8963/Measure.h117
-rwxr-xr-xst/akm8963/TestLimit.h157
-rwxr-xr-xst/akm8963/akm8963.h102
-rwxr-xr-xst/akm8963/custom_log.h163
-rwxr-xr-xst/akm8963/libAK8963/AK8963.h54
-rwxr-xr-xst/akm8963/libAK8963/AKCertification.h33
-rwxr-xr-xst/akm8963/libAK8963/AKConfigure.h47
-rwxr-xr-xst/akm8963/libAK8963/AKDirection6D.h75
-rwxr-xr-xst/akm8963/libAK8963/AKHDOE.h98
-rwxr-xr-xst/akm8963/libAK8963/AKHFlucCheck.h57
-rwxr-xr-xst/akm8963/libAK8963/AKMDevice.h84
-rwxr-xr-xst/akm8963/libAK8963/AKManualCal.h39
-rwxr-xr-xst/akm8963/libAK8963/AKVersion.h39
-rwxr-xr-xst/akm8963/libAK8963/libAK8963.abin0 -> 43338 bytes
-rwxr-xr-xst/akm8963/main.c340
-rwxr-xr-xst/akm8963/misc.c259
-rwxr-xr-xst/akm8963/misc.h61
-rwxr-xr-xst/akm8963/mma8452_kernel.h136
-rwxr-xr-xst/akm8975.h28
-rw-r--r--st/akm8975/AK8975Driver.c334
-rw-r--r--st/akm8975/AK8975Driver.h66
-rw-r--r--st/akm8975/AKCommon.h76
-rw-r--r--st/akm8975/AKCompass.h109
-rw-r--r--st/akm8975/Acc_dummy.c128
-rwxr-xr-xst/akm8975/Acc_mma8452.c314
-rw-r--r--st/akm8975/Acc_mma8452.h72
-rw-r--r--st/akm8975/Android.mk29
-rwxr-xr-xst/akm8975/CustomerSpec.h118
-rw-r--r--st/akm8975/DispMessage.c186
-rw-r--r--st/akm8975/DispMessage.h61
-rw-r--r--st/akm8975/FileIO.c217
-rw-r--r--st/akm8975/FileIO.h58
-rwxr-xr-xst/akm8975/Measure.c980
-rw-r--r--st/akm8975/Measure.h84
-rw-r--r--st/akm8975/TestLimit.h147
-rwxr-xr-xst/akm8975/akm8975_kernel.h88
-rw-r--r--st/akm8975/akmd2_dox1515
-rwxr-xr-xst/akm8975/custom_log.h163
-rw-r--r--st/akm8975/libAK8975/AK8975.h57
-rw-r--r--st/akm8975/libAK8975/AKCertification.h37
-rw-r--r--st/akm8975/libAK8975/AKConfigure.h51
-rw-r--r--st/akm8975/libAK8975/AKDirection6D.h78
-rw-r--r--st/akm8975/libAK8975/AKHDOE.h102
-rw-r--r--st/akm8975/libAK8975/AKHFlucCheck.h53
-rw-r--r--st/akm8975/libAK8975/AKMDevice.h78
-rw-r--r--st/akm8975/libAK8975/AKManualCal.h43
-rw-r--r--st/akm8975/libAK8975/AKVersion.h42
-rw-r--r--st/akm8975/libAK8975/README1
-rw-r--r--st/akm8975/libAK8975/libAK8975.abin0 -> 148524 bytes
-rw-r--r--st/akm8975/main.c269
-rw-r--r--st/akm8975/misc.c180
-rw-r--r--st/akm8975/misc.h61
-rwxr-xr-xst/akm8975/mma8452_kernel.h136
-rw-r--r--st/akm8975/source_layout.txt52
-rwxr-xr-xst/isl29028.h32
-rw-r--r--st/l3g4200d.h30
-rwxr-xr-xst/mma8452.h129
-rwxr-xr-xst/mma8452_kernel.h136
-rwxr-xr-xst/nusensors.cpp389
-rwxr-xr-xst/nusensors.h175
-rwxr-xr-xst/readme.txt14
-rw-r--r--st/sensors.c172
652 files changed, 122313 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..5ca8a6b
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,10 @@
+# Can't have both mpu and st sensor hal.
+ifeq ($(BOARD_SENSOR_MPU_PAD),true)
+include $(call all-named-subdir-makefiles,mpu_vr)
+else ifeq ($(BOARD_SENSOR_MPU_VR),true)
+include $(call all-named-subdir-makefiles,mpu_vr)
+else ifeq ($(BOARD_SENSOR_MPU),true)
+include $(call all-named-subdir-makefiles,mpu)
+else ifeq ($(BOARD_SENSOR_ST),true)
+include $(call all-named-subdir-makefiles,st)
+endif
diff --git a/mpu/Android.mk b/mpu/Android.mk
new file mode 100755
index 0000000..5053e7d
--- /dev/null
+++ b/mpu/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/mpu/akm8963/AKCommon.h b/mpu/akm8963/AKCommon.h
new file mode 100755
index 0000000..e73655d
--- /dev/null
+++ b/mpu/akm8963/AKCommon.h
@@ -0,0 +1,51 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKMD_INC_AKCOMMON_H
+#define AKMD_INC_AKCOMMON_H
+
+#include <errno.h> //errno
+#include <stdarg.h> //va_list
+#include <stdio.h> //frpintf
+#include <stdlib.h> //atoi
+#include <string.h> //memset
+#include <unistd.h>
+
+#include "AKMLog.h"
+
+/*** Constant definition ******************************************************/
+
+/* Definition for operation mode */
+#define OPMODE_CONSOLE (0x01)
+
+/*** Type declaration *********************************************************/
+
+/*** Global variables *********************************************************/
+extern int g_stopRequest; /*!< 0:Not stop, 1:Stop */
+extern int g_opmode; /*!< 0:Daemon mode, 1:Console mode. */
+extern int g_dbgzone; /*!< Debug zone. */
+
+/*** Prototype of function ****************************************************/
+
+#endif //AKMD_INC_AKCOMMON_H
+
diff --git a/mpu/akm8963/AKCompass.h b/mpu/akm8963/AKCompass.h
new file mode 100755
index 0000000..44b38ca
--- /dev/null
+++ b/mpu/akm8963/AKCompass.h
@@ -0,0 +1,164 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKMD_INC_AKCOMPASS_H
+#define AKMD_INC_AKCOMPASS_H
+
+#include "AKCommon.h"
+#include "CustomerSpec.h"
+#include "AKMD_Driver.h" // for using BYTE
+
+//**************************************
+// Include files for SmartCompass library.
+//**************************************
+#include "libSmartCompass/AKCertification.h"
+#include "libSmartCompass/AKConfigure.h"
+#include "libSmartCompass/AKDecomp.h"
+#include "libSmartCompass/AKMDevice.h"
+#include "libSmartCompass/AKMDeviceF.h"
+#include "libSmartCompass/AKDirection6D.h"
+#include "libSmartCompass/AKHDOE.h"
+#include "libSmartCompass/AKHFlucCheck.h"
+#include "libSmartCompass/AKManualCal.h"
+#include "libSmartCompass/AKVersion.h"
+#include "libSmartCompass/AKPseudoGyro.h"
+#include "libSmartCompass/AKDOEPlus.h"
+
+/*** Constant definition ******************************************************/
+#define THETAFILTER_SCALE 4128
+#define HFLUCV_TH 2500
+#define PDC_SIZE 27
+
+/*** Type declaration *********************************************************/
+typedef enum _AKMD_PATNO {
+ PAT_INVALID = 0,
+ PAT1,
+ PAT2,
+ PAT3,
+ PAT4,
+ PAT5,
+ PAT6,
+ PAT7,
+ PAT8
+} AKMD_PATNO;
+
+
+/*! A parameter structure which is needed for HDOE and Direction calculation. */
+typedef struct _AKSCPRMS{
+
+ // Variables for magnetic sensor.
+ int16vec m_ho;
+ int16vec HSUC_HO[CSPEC_NUM_FORMATION];
+ int32vec m_ho32;
+ int16vec m_hs;
+ int16vec HFLUCV_HREF[CSPEC_NUM_FORMATION];
+ AKSC_HFLUCVAR m_hflucv;
+
+ // Variable for uncalibrated magnetic field.
+ int32vec m_uncalib;
+ int32vec m_bias;
+
+ // Variable for magnetic field.
+ int16vec m_calib;
+ // Variables for DecompS3 .
+ int16vec m_hdata[AKSC_HDATA_SIZE];
+ int16 m_hn; // Number of acquired data
+ int16vec m_hvec; // Averaged value
+ int16vec m_asa;
+ uint8 m_pdc[PDC_SIZE];
+ uint8* m_pdcptr;
+
+ // Variables for DOEPlus.
+ int16 akm_device;
+ int16 PG_filter;
+ int16 m_en_doeplus;
+ AKSC_DOEPVAR *m_doep_var;
+ int16 m_doep_lv;
+ AKSC_FLOAT DOEP_PRMS[CSPEC_NUM_FORMATION][AKSC_DOEP_SIZE];
+ int16vec m_hdata_plus[AKSC_HDATA_SIZE];
+
+ // Variables for HDOE.
+ AKSC_HDOEVAR m_hdoev;
+ AKSC_HDST m_hdst;
+ AKSC_HDST HSUC_HDST[CSPEC_NUM_FORMATION];
+
+ // Variables for formation change
+ int16 m_form;
+ int16 m_cntSuspend;
+
+ // Variables for Direction9D.
+ int16 m_d6dRet;
+ int16 m_hnave;
+ int16vec m_dvec;
+ int16 m_theta;
+ int16 m_delta;
+ int16 m_hr;
+ int16 m_hrhoriz;
+ int16 m_ar;
+ int16 m_phi180;
+ int16 m_phi90;
+ int16 m_eta180;
+ int16 m_eta90;
+ I16MATRIX m_mat;
+ I16QUAT m_quat;
+
+ // Variables for acceleration sensor.
+ int16vec m_AO;
+ int16vec m_avec;
+
+ // Layout information
+ AKMD_PATNO m_hlayout;
+ //AKMD_PATNO m_alayout;
+ //AKMD_PATNO m_glayout;
+
+ // Variables for decimation.
+ int16 m_callcnt;
+
+ // PseudoGyro
+ int16 m_pgRet;
+ int16 m_pgdt;
+ AKPG_COND m_pgcond;
+ AKPG_VAR m_pgvar;
+ int32vec m_pgout;
+ I16QUAT m_pgquat;
+ int16vec m_pgGravity;
+ int16vec m_pgLinAcc;
+
+ // Ceritication
+ uint8 m_licenser[AKSC_CI_MAX_CHARSIZE+1]; //end with '\0'
+ uint8 m_licensee[AKSC_CI_MAX_CHARSIZE+1]; //end with '\0'
+ int16 m_key[AKSC_CI_MAX_KEYSIZE];
+
+ // base
+ int32vec m_hbase;
+ int32vec HSUC_HBASE[CSPEC_NUM_FORMATION];
+
+} AKSCPRMS;
+
+
+/*** Global variables *********************************************************/
+
+/*** Prototype of function ****************************************************/
+
+#endif //AKMD_INC_AKCOMPASS_H
+
diff --git a/mpu/akm8963/AKMD_Driver.c b/mpu/akm8963/AKMD_Driver.c
new file mode 100755
index 0000000..98bf4a0
--- /dev/null
+++ b/mpu/akm8963/AKMD_Driver.c
@@ -0,0 +1,570 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#include <fcntl.h>
+#include "AKCommon.h" // DBGPRINT()
+#include "AKMD_Driver.h"
+#include "Acc_mma8452.h"
+
+#define AKM_MEASURE_RETRY_NUM 5
+int s_fdDev = -1;
+
+#define MSENSOR_NAME "/dev/akm8963_dev"
+#define GSENSOR_NAME "/dev/gsensor"
+int g_file_acc = -1;
+
+/* Include proper acceleration file. */
+#ifdef AKMD_ACC_EXTERNAL
+#include "Acc_aot.h"
+static ACCFNC_INITDEVICE Acc_InitDevice = AOT_InitDevice;
+static ACCFNC_DEINITDEVICE Acc_DeinitDevice = AOT_DeinitDevice;
+static ACCFNC_SET_ENABLE Acc_SetEnable = AOT_SetEnable;
+static ACCFNC_SET_DELAY Acc_SetDelay = AOT_SetDelay;
+static ACCFNC_GETACCDATA Acc_GetAccData = AOT_GetAccData;
+static ACCFNC_GETACCOFFSET Acc_GetAccOffset = AOT_GetAccOffset;
+static ACCFNC_GETACCVEC Acc_GetAccVector = AOT_GetAccVector;
+
+#else
+#ifdef AKMD_ACC_ADXL346
+#include "Acc_adxl34x.h"
+static ACCFNC_INITDEVICE Acc_InitDevice = ADXL_InitDevice;
+static ACCFNC_DEINITDEVICE Acc_DeinitDevice = ADXL_DeinitDevice;
+static ACCFNC_SET_ENABLE Acc_SetEnable = ADXL_SetEnable;
+static ACCFNC_SET_DELAY Acc_SetDelay = ADXL_SetDelay;
+static ACCFNC_GETACCDATA Acc_GetAccData = ADXL_GetAccData;
+static ACCFNC_GETACCOFFSET Acc_GetAccOffset = ADXL_GetAccOffset;
+static ACCFNC_GETACCVEC Acc_GetAccVector = ADXL_GetAccVector;
+#endif
+#ifdef AKMD_ACC_KXTF9
+#include "Acc_kxtf9.h"
+static ACCFNC_INITDEVICE Acc_InitDevice = KXTF9_InitDevice;
+static ACCFNC_DEINITDEVICE Acc_DeinitDevice = KXTF9_DeinitDevice;
+static ACCFNC_SET_ENABLE Acc_SetEnable = KXTF9_SetEnable;
+static ACCFNC_SET_DELAY Acc_SetDelay = KXTF9_SetDelay;
+static ACCFNC_GETACCDATA Acc_GetAccData = KXTF9_GetAccData;
+static ACCFNC_GETACCOFFSET Acc_GetAccOffset = KXTF9_GetAccOffset;
+static ACCFNC_GETACCVEC Acc_GetAccVector = KXTF9_GetAccVector;
+#endif
+#ifdef AKMD_ACC_DUMMY
+#include "Acc_dummy.h"
+static ACCFNC_INITDEVICE Acc_InitDevice = ACC_DUMMY_InitDevice;
+static ACCFNC_DEINITDEVICE Acc_DeinitDevice = ACC_DUMMY_DeinitDevice;
+static ACCFNC_SET_ENABLE Acc_SetEnable = ACC_DUMMY_SetEnable;
+static ACCFNC_SET_DELAY Acc_SetDelay = ACC_DUMMY_SetDelay;
+static ACCFNC_GETACCDATA Acc_GetAccData = ACC_DUMMY_GetAccData;
+static ACCFNC_GETACCOFFSET Acc_GetAccOffset = ACC_DUMMY_GetAccOffset;
+static ACCFNC_GETACCVEC Acc_GetAccVector = ACC_DUMMY_GetAccVector;
+#endif
+#endif
+
+/*!
+ Open device driver.
+ This function opens both device drivers of magnetic sensor and acceleration
+ sensor. Additionally, some initial hardware settings are done, such as
+ measurement range, built-in filter function and etc.
+ @return If this function succeeds, the return value is #AKD_SUCCESS.
+ Otherwise the return value is #AKD_FAIL.
+ */
+int16_t AKD_InitDevice(void)
+{
+ if (s_fdDev < 0) {
+ // Open magnetic sensor's device driver.
+ //if ((s_fdDev = open("/dev/" AKM_MISCDEV_NAME, O_RDWR)) < 0) {
+ if ((s_fdDev = open(MSENSOR_NAME, O_RDWR)) < 0) {
+ AKMERROR_STR("open");
+ goto INIT_FAIL;
+ }
+ }
+#if 0
+ if (Acc_InitDevice() != AKD_SUCCESS) {
+ goto INIT_FAIL;
+ }
+#endif
+#if 0
+ if (g_file_acc < 0)
+ {
+ if((g_file_acc = open(GSENSOR_NAME, O_RDWR)) < 0)
+ {
+ AKMERROR_STR("open");
+ goto INIT_FAIL;
+ }
+ }
+#endif
+ return AKD_SUCCESS;
+
+INIT_FAIL:
+ AKD_DeinitDevice();
+ return AKD_FAIL;
+}
+
+/*!
+ Close device driver.
+ This function closes both device drivers of magnetic sensor and acceleration
+ sensor.
+ */
+void AKD_DeinitDevice(void)
+{
+ if (s_fdDev >= 0) {
+ close(s_fdDev);
+ s_fdDev = -1;
+ }
+#if 0
+ //Acc_DeinitDevice();
+ if (g_file_acc >= 0) {
+ close(g_file_acc);
+ g_file_acc = -1;
+ }
+#endif
+}
+
+/*!
+ Writes data to a register of the AKM E-Compass. When more than one byte of
+ data is specified, the data is written in contiguous locations starting at an
+ address specified in \a address.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[in] address Specify the address of a register in which data is to be
+ written.
+ @param[in] data Specify data to write or a pointer to a data array containing
+ the data. When specifying more than one byte of data, specify the starting
+ address of the array.
+ @param[in] numberOfBytesToWrite Specify the number of bytes that make up the
+ data to write. When a pointer to an array is specified in data, this argument
+ equals the number of elements of the array.
+ */
+int16_t AKD_TxData(
+ const BYTE address,
+ const BYTE * data,
+ const uint16_t numberOfBytesToWrite)
+{
+ int i;
+ char buf[AKM_RWBUF_SIZE];
+
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+ if (numberOfBytesToWrite > (AKM_RWBUF_SIZE-2)) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+
+ buf[0] = numberOfBytesToWrite + 1;
+ buf[1] = address;
+
+ for (i = 0; i < numberOfBytesToWrite; i++) {
+ buf[i + 2] = data[i];
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_WRITE, buf) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ } else {
+
+#if ENABLE_AKMDEBUG
+ AKMDEBUG(AKMDBG_MAGDRV, "MAGDRV: addr(HEX)=%02x data(HEX)=", address);
+ for (i = 0; i < numberOfBytesToWrite; i++) {
+ AKMDEBUG(AKMDBG_MAGDRV, " %02x", data[i]);
+ }
+ AKMDEBUG(AKMDBG_MAGDRV, "\n");
+#endif
+ return AKD_SUCCESS;
+ }
+}
+
+/*!
+ Acquires data from a register or the EEPROM of the AKM E-Compass.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[in] address Specify the address of a register from which data is to be
+ read.
+ @param[out] data Specify a pointer to a data array which the read data are
+ stored.
+ @param[in] numberOfBytesToRead Specify the number of bytes that make up the
+ data to read. When a pointer to an array is specified in data, this argument
+ equals the number of elements of the array.
+ */
+int16_t AKD_RxData(
+ const BYTE address,
+ BYTE * data,
+ const uint16_t numberOfBytesToRead)
+{
+ int i;
+ char buf[AKM_RWBUF_SIZE];
+
+ memset(data, 0, numberOfBytesToRead);
+
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+ if (numberOfBytesToRead > (AKM_RWBUF_SIZE-1)) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+
+ buf[0] = numberOfBytesToRead;
+ buf[1] = address;
+
+ if (ioctl(s_fdDev, ECS_IOCTL_READ, buf) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ } else {
+ for (i = 0; i < numberOfBytesToRead; i++) {
+ data[i] = buf[i + 1];
+ }
+#if ENABLE_AKMDEBUG
+ AKMDEBUG(AKMDBG_MAGDRV, "MAGDRV: addr(HEX)=%02x len=%d data(HEX)=",
+ address, numberOfBytesToRead);
+ for (i = 0; i < numberOfBytesToRead; i++) {
+ AKMDEBUG(AKMDBG_MAGDRV, " %02x", data[i]);
+ }
+ AKMDEBUG(AKMDBG_MAGDRV, "\n");
+#endif
+ return AKD_SUCCESS;
+ }
+}
+
+/*!
+ Reset the e-compass.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ */
+int16_t AKD_Reset(void) {
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_RESET, NULL) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+ return AKD_SUCCESS;
+}
+
+/*!
+ Get magnetic sensor information from device. This function returns WIA value.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[out] data An information data array. The size should be larger than
+ #AKM_SENSOR_INFO_SIZE
+ */
+int16_t AKD_GetSensorInfo(BYTE data[AKM_SENSOR_INFO_SIZE])
+{
+ memset(data, 0, AKM_SENSOR_INFO_SIZE);
+
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_GET_INFO, data) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+ return AKD_SUCCESS;
+}
+
+/*!
+ Get magnetic sensor configuration from device. This function returns ASA value.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[out] data An configuration data array. The size should be larger than
+ #AKM_SENSOR_CONF_SIZE
+ */
+int16_t AKD_GetSensorConf(BYTE data[AKM_SENSOR_CONF_SIZE])
+{
+ memset(data, 0, AKM_SENSOR_CONF_SIZE);
+
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_GET_CONF, data) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+ return AKD_SUCCESS;
+}
+
+
+/*!
+ Acquire magnetic data from AKM E-Compass. If measurement is not done, this
+ function waits until measurement completion.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[out] data A magnetic data array. The size should be larger than
+ #AKM_SENSOR_DATA_SIZE.
+ */
+int16_t AKD_GetMagneticData(BYTE data[AKM_SENSOR_DATA_SIZE])
+{
+ int ret;
+ int i;
+
+ memset(data, 0, AKM_SENSOR_DATA_SIZE);
+
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+
+ for (i = 0; i < AKM_MEASURE_RETRY_NUM; i++) {
+ ret = ioctl(s_fdDev, ECS_IOCTL_GETDATA, data);//KY TODO
+
+ if (ret >= 0) {
+ /* Success */
+ break;
+ }
+ if (errno != EAGAIN) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+ AKMDEBUG(AKMDBG_MAGDRV, "MAGDRV: Try Again.");
+ usleep(AKM_MEASURE_TIME_US);
+ }
+
+ if (i >= AKM_MEASURE_RETRY_NUM) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+#ifdef AKMD_AK099XX
+ AKMDEBUG(AKMDBG_MAGDRV,
+ "MAGDRV: bdata(HEX)= %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]);
+#else
+ AKMDEBUG(AKMDBG_MAGDRV,
+ "MAGDRV: bdata(HEX)= %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
+#endif
+
+ return AKD_SUCCESS;
+}
+
+/*!
+ Set calculated data to device driver.
+ @param[in] buf
+ */
+void AKD_SetYPR(const int buf[AKM_YPR_DATA_SIZE])
+{
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return;
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_SET_YPR, buf) < 0) {
+ AKMERROR_STR("ioctl");
+ }
+}
+
+/*!
+ */
+int16_t AKD_GetOpenStatus(int* status)
+{
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_GET_OPEN_STATUS, status) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+ return AKD_SUCCESS;
+}
+
+/*!
+ */
+int16_t AKD_GetCloseStatus(int* status)
+{
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_GET_CLOSE_STATUS, status) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+ return AKD_SUCCESS;
+}
+
+/*!
+ Set AKM E-Compass to the specific mode.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[in] mode This value should be one of the AKM_MODE which is defined in
+ header file.
+ */
+int16_t AKD_SetMode(const BYTE mode)
+{
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_SET_MODE, &mode) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+ AKMDEBUG(AKMDBG_MAGDRV,"MAGDRV: mode=%d\n", mode);
+ return AKD_SUCCESS;
+}
+
+/*!
+ Acquire delay
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[out] delay A delay in microsecond.
+ */
+int16_t AKD_GetDelay(int64_t delay[AKM_NUM_SENSORS])
+{
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_GET_DELAY, delay) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+#if ENABLE_AKMDEBUG
+#if (AKM_NUM_SENSORS == 1)
+ AKMDEBUG(AKMDBG_MAGDRV,"MAGDRV: delay=%lld\n", delay[0]);
+#endif
+#if (AKM_NUM_SENSORS == 2)
+ AKMDEBUG(AKMDBG_MAGDRV,"MAGDRV: delay=%lld,%lld\n", delay[0], delay[1]);
+#endif
+#if (AKM_NUM_SENSORS == 3)
+ AKMDEBUG(AKMDBG_MAGDRV,"MAGDRV: delay=%lld,%lld,%lld\n", delay[0], delay[1], delay[2]);
+#endif
+#endif
+
+ return AKD_SUCCESS;
+}
+
+/*!
+ Get layout information from device driver, i.e. platform data.
+ */
+int16_t AKD_GetLayout(int16_t* layout)
+{
+ char tmp;
+
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_GET_LAYOUT, &tmp) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+
+ *layout = tmp;
+ ALOGE("%s: layout=%d\n", __FUNCTION__, tmp);
+
+ return AKD_SUCCESS;
+}
+
+/*! */
+int16_t AKD_AccSetEnable(int8_t enabled)
+{
+ //return Acc_SetEnable(enabled);
+ return AKD_SUCCESS;
+}
+
+/*! */
+int16_t AKD_AccSetDelay(int64_t delay)
+{
+ //return Acc_SetDelay(delay);
+ return AKD_SUCCESS;
+}
+
+/*!
+ Convert Acceleration sensor coordinate system from Android's one to AK's one.
+ In Android coordinate system, 1G = 9.8f (m/s^2). In AK coordinate system,
+ 1G = 720 (LSB).
+ @param[in] fData A acceleration data array. The coordinate system of this data
+ should follows the definition of Android.
+ @param[out] data A acceleration data array. The coordinate system of the
+ acquired data follows the definition of AK.
+ */
+void Android2AK(int fData[], int16_t data[3])
+{
+/*
+ data[0] = fData[1] / 9.8f * -720;
+ data[1] = fData[0] / 9.8f * 720;
+ data[2] = fData[2] / 9.8f * -720;
+*/
+// data[] is mg unit, so data[] / 9800 * 720 = data[] *72 /980
+ #if 0
+ data[0] = fData[1] * 72 / -980;
+ data[1] = fData[0] * 72 / 980;
+ data[2] = fData[2] * 72 / -980;
+ AKMDEBUG(AKMDBG_MAGDRV, "Get gsensor data %d, %d, %d.\n", data[0], data[1], data[2]);
+ #else //for AK8963C LIB
+ data[0] = fData[0] * 72 / 980;
+ data[1] = fData[1] * 72 / 980;
+ data[2] = fData[2] * 72 / 980;
+ AKMDEBUG(AKMDBG_MAGDRV, "Get gsensor data %d, %d, %d.\n", data[0], data[1], data[2]);
+ #endif
+
+}
+
+/*! */
+int16_t AKD_GetAccelerationData(int16_t data[3])
+{
+// return Acc_GetAccData(data);
+
+#if 0
+ int fData[3];
+ char buf[64];
+ if(ioctl(g_file_acc, GSENSOR_IOCTL_READ_SENSORDATA, (void*)buf) < 0)
+ {
+ AKMDEBUG(AKMDBG_MAGDRV, "Get gsensor data error.\n");
+ return AKD_FAIL;
+ }
+ else
+ {
+ sscanf(buf, "%x %x %x", &fData[0], &fData[1], &fData[2]);
+ Android2AK(fData, data);
+ return AKD_SUCCESS;
+ }
+#else
+ return AKD_SUCCESS;
+#endif
+}
+
+/*! */
+int16_t AKD_GetAccelerationOffset(int16_t offset[3])
+{
+ //return Acc_GetAccOffset(offset);
+ offset[0] = 0;
+ offset[1] = 0;
+ offset[2] = 0;
+ return AKD_SUCCESS;
+}
+
+/*! */
+void AKD_GetAccelerationVector(
+ const int16_t data[3],
+ const int16_t offset[3],
+ int16_t vec[3])
+{
+ //Acc_GetAccVector(data, offset, vec);
+ vec[0] = (int16_t)(data[0] - offset[0]);
+ vec[1] = (int16_t)(data[1] - offset[1]);
+ vec[2] = (int16_t)(data[2] - offset[2]);
+}
+
diff --git a/mpu/akm8963/AKMD_Driver.h b/mpu/akm8963/AKMD_Driver.h
new file mode 100755
index 0000000..71ca215
--- /dev/null
+++ b/mpu/akm8963/AKMD_Driver.h
@@ -0,0 +1,284 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKMD_INC_AKMD_DRIVER_H
+#define AKMD_INC_AKMD_DRIVER_H
+
+/* Device driver */
+#ifdef AKMD_FOR_AK8963
+//#include "akm8963.h"
+
+#elif AKMD_FOR_AK8975
+#include "akm8975.h"
+
+#elif AKMD_FOR_AK09911
+//KY TODO #include "akm09911.h"
+
+#elif AKMD_FOR_AK09912
+#include "akm09912.h"
+
+#else
+#error "No devices are defined."
+#endif
+
+//KY TODO
+#include "sensors_io.h" /* Device driver */
+#include <stdint.h> /* int8_t, int16_t etc. */
+
+#define SENSOR_DATA_SIZE 9 /* Rx buffer size, i.e from ST1 to ST2 */
+#define RWBUF_SIZE 16 /* Read/Write buffer size.*/
+#define CALIBRATION_DATA_SIZE 12
+
+/*! \name AK09911 register address
+\anchor AK09911_REG
+Defines a register address of the AK09911.*/
+/*! @{*/
+/* Device specific constant values */
+#define AK09911_REG_WIA1 0x00
+#define AK09911_REG_WIA2 0x01
+#define AK09911_REG_INFO1 0x02
+#define AK09911_REG_INFO2 0x03
+#define AK09911_REG_ST1 0x10
+#define AK09911_REG_HXL 0x11
+#define AK09911_REG_HXH 0x12
+#define AK09911_REG_HYL 0x13
+#define AK09911_REG_HYH 0x14
+#define AK09911_REG_HZL 0x15
+#define AK09911_REG_HZH 0x16
+#define AK09911_REG_TMPS 0x17
+#define AK09911_REG_ST2 0x18
+#define AK09911_REG_CNTL1 0x30
+#define AK09911_REG_CNTL2 0x31
+#define AK09911_REG_CNTL3 0x32
+
+/*! \name AK09911 fuse-rom address
+\anchor AK09911_FUSE
+Defines a read-only address of the fuse ROM of the AK09911.*/
+#define AK09911_FUSE_ASAX 0x60
+#define AK09911_FUSE_ASAY 0x61
+#define AK09911_FUSE_ASAZ 0x62
+
+/*! \name AK09911 operation mode
+ \anchor AK09911_Mode
+ Defines an operation mode of the AK09911.*/
+#define AK09911_MODE_SNG_MEASURE 0x01
+#define AK09911_MODE_SELF_TEST 0x10
+#define AK09911_MODE_FUSE_ACCESS 0x1F
+#define AK09911_MODE_POWERDOWN 0x00
+#define AK09911_RESET_DATA 0x01
+
+#define AK09911_REGS_SIZE 13
+#define AK09911_WIA1_VALUE 0x48
+#define AK09911_WIA2_VALUE 0x05
+
+/* Device specific constant values for AK8963*/
+#define AK8963_REG_WIA 0x00
+#define AK8963_REG_INFO 0x01
+#define AK8963_REG_ST1 0x02
+#define AK8963_REG_HXL 0x03
+#define AK8963_REG_HXH 0x04
+#define AK8963_REG_HYL 0x05
+#define AK8963_REG_HYH 0x06
+#define AK8963_REG_HZL 0x07
+#define AK8963_REG_HZH 0x08
+#define AK8963_REG_ST2 0x09
+#define AK8963_REG_CNTL1 0x0A
+#define AK8963_REG_CNTL2 0x0B
+#define AK8963_REG_ASTC 0x0C
+#define AK8963_REG_TS1 0x0D
+#define AK8963_REG_TS2 0x0E
+#define AK8963_REG_I2CDIS 0x0F
+
+#define AK8963_FUSE_ASAX 0x10
+#define AK8963_FUSE_ASAY 0x11
+#define AK8963_FUSE_ASAZ 0x12
+
+#define AK8963_MODE_SNG_MEASURE 0x01
+#define AK8963_MODE_SELF_TEST 0x08
+#define AK8963_MODE_FUSE_ACCESS 0x0F
+#define AK8963_MODE_POWERDOWN 0x00
+#define AK8963_RESET_DATA 0x01
+
+#define AK8963_REGS_SIZE 13
+#define AK8963_WIA_VALUE 0x48
+
+
+/* To avoid device dependency, convert to general name */
+#define AKM_I2C_NAME "akm8963"
+#define AKM_MISCDEV_NAME "akm8963_dev"
+#define AKM_SYSCLS_NAME "compass"
+#define AKM_SYSDEV_NAME "akm8963"
+#define AKM_REG_MODE AK8963_REG_CNTL1
+#define AKM_REG_RESET AK8963_REG_CNTL2
+#define AKM_REG_STATUS AK8963_REG_ST1
+#define AKM_MEASURE_TIME_US 10000
+#define AKM_DRDY_IS_HIGH(x) ((x) & 0x01)
+#define AKM_SENSOR_INFO_SIZE 2
+#define AKM_SENSOR_CONF_SIZE 3
+#define AKM_SENSOR_DATA_SIZE 9
+
+#define AKM_YPR_DATA_SIZE 26
+#define AKM_RWBUF_SIZE 16
+#define AKM_REGS_SIZE AK8963_REGS_SIZE
+#define AKM_REGS_1ST_ADDR AK8963_REG_WIA
+#define AKM_FUSE_1ST_ADDR AK8963_FUSE_ASAX
+
+#define AKM_MODE_SNG_MEASURE AK8963_MODE_SNG_MEASURE
+#define AKM_MODE_SELF_TEST AK8963_MODE_SELF_TEST
+#define AKM_MODE_FUSE_ACCESS AK8963_MODE_FUSE_ACCESS
+#define AKM_MODE_POWERDOWN AK8963_MODE_POWERDOWN
+#define AKM_RESET_DATA AK8963_RESET_DATA
+
+#define ACC_DATA_FLAG 0
+#define MAG_DATA_FLAG 1
+#define FUSION_DATA_FLAG 2
+#define AKM_NUM_SENSORS 3
+
+#define ACC_DATA_READY (1<<(ACC_DATA_FLAG))
+#define MAG_DATA_READY (1<<(MAG_DATA_FLAG))
+#define FUSION_DATA_READY (1<<(FUSION_DATA_FLAG))
+
+/*** Constant definition ******************************************************/
+#define AKD_TRUE 1 /*!< Represents true */
+#define AKD_FALSE 0 /*!< Represents false */
+#define AKD_SUCCESS 1 /*!< Represents success.*/
+#define AKD_FAIL 0 /*!< Represents fail. */
+#define AKD_ERROR -1 /*!< Represents error. */
+
+#define AKD_ENABLE 1
+#define AKD_DISABLE 0
+
+/*! 0:Don't Output data, 1:Output data */
+#define AKD_DBG_DATA 0
+/*! Typical interval in ns */
+#define AKM_MEASUREMENT_TIME_NS ((AKM_MEASURE_TIME_US) * 1000)
+
+
+/*** Type declaration *********************************************************/
+typedef unsigned char BYTE;
+
+/*!
+ Open device driver.
+ This function opens device driver of other sensor.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ */
+typedef int16_t(*ACCFNC_INITDEVICE)(void);
+
+/*!
+ Close device driver.
+ This function closes device drivers of acceleration sensor.
+ */
+typedef void(*ACCFNC_DEINITDEVICE)(void);
+
+/*!
+ Enable or disable sensor
+*/
+typedef int16_t(*ACCFNC_SET_ENABLE)(const int8_t enabled);
+
+/*!
+ Set delay value
+*/
+typedef int16_t(*ACCFNC_SET_DELAY)(const int64_t ns);
+
+/*!
+ Acquire data from other sensor.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[out] data A data array. The coordinate system and the unit
+ follows the sensor local definition.
+ */
+typedef int16_t(*ACCFNC_GETACCDATA)(int16_t data[3]);
+
+/*!
+ Acquire offset from other sensor.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[out] offset A offset data array. The coordinate system and the unit
+ follows the sensor local definition.
+ */
+typedef int16_t(*ACCFNC_GETACCOFFSET)(int16_t offset[3]);
+
+/*!
+ Convert from sensor native format to AKSC format
+ @param[out] vec A data array. The coordinate system of the
+ acquired data follows the definition of Android. Unit is SmartCompass.
+*/
+typedef void(*ACCFNC_GETACCVEC)(
+ const int16_t data[3],
+ const int16_t offset[3],
+ int16_t vec[3]);
+
+/*** Global variables *********************************************************/
+
+/*** Prototype of Function ***************************************************/
+
+int16_t AKD_InitDevice(void);
+
+void AKD_DeinitDevice(void);
+
+int16_t AKD_TxData(
+ const BYTE address,
+ const BYTE* data,
+ const uint16_t numberOfBytesToWrite);
+
+int16_t AKD_RxData(
+ const BYTE address,
+ BYTE* data,
+ const uint16_t numberOfBytesToRead);
+
+int16_t AKD_Reset(void);
+
+int16_t AKD_GetSensorInfo(BYTE data[AKM_SENSOR_INFO_SIZE]);
+
+int16_t AKD_GetSensorConf(BYTE data[AKM_SENSOR_CONF_SIZE]);
+
+int16_t AKD_GetMagneticData(BYTE data[AKM_SENSOR_DATA_SIZE]);
+
+void AKD_SetYPR(const int buf[AKM_YPR_DATA_SIZE]);
+
+int16_t AKD_GetOpenStatus(int* status);
+
+int16_t AKD_GetCloseStatus(int* status);
+
+int16_t AKD_SetMode(const BYTE mode);
+
+int16_t AKD_GetDelay(int64_t delay[AKM_NUM_SENSORS]);
+
+int16_t AKD_GetLayout(int16_t* layout);
+
+int16_t AKD_AccSetEnable(int8_t enabled);
+
+int16_t AKD_AccSetDelay(int64_t delay);
+
+int16_t AKD_GetAccelerationData(int16_t data[3]);
+
+int16_t AKD_GetAccelerationOffset(int16_t offset[3]);
+
+void AKD_GetAccelerationVector(
+ const int16_t data[3],
+ const int16_t offset[3],
+ int16_t vec[3]);
+
+#endif //AKMD_INC_AKMD_DRIVER_H
+
diff --git a/mpu/akm8963/AKMLog.h b/mpu/akm8963/AKMLog.h
new file mode 100755
index 0000000..de74129
--- /dev/null
+++ b/mpu/akm8963/AKMLog.h
@@ -0,0 +1,160 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKMD_INC_AKMLOG_H
+#define AKMD_INC_AKMLOG_H
+
+#include <cutils/log.h>
+
+/*** Constant definition ******************************************************/
+#undef LOG_TAG
+#define LOG_TAG "AKMD2"
+
+#ifndef ALOGE
+#ifdef LOGE
+#define ALOGE LOGE
+#endif
+#endif
+#ifndef ALOGE_IF
+#ifdef LOGE_IF
+#define ALOGE_IF LOGE_IF
+#endif
+#endif
+
+#ifndef ALOGW
+#ifdef LOGW
+#define ALOGW LOGW
+#endif
+#endif
+#ifndef ALOGW_IF
+#ifdef LOGW_IF
+#define ALOGW_IF LOGW_IF
+#endif
+#endif
+
+#ifndef ALOGI
+#ifdef LOGI
+#define ALOGI LOGI
+#endif
+#endif
+#ifndef ALOGI_IF
+#ifdef LOGI_IF
+#define ALOGI_IF LOGI_IF
+#endif
+#endif
+
+#ifndef ALOGD
+#ifdef LOGD
+#define ALOGD LOGD
+#endif
+#endif
+#ifndef ALOGD_IF
+#ifdef LOGD_IF
+#define ALOGD_IF LOGD_IF
+#endif
+#endif
+
+#ifndef ALOGV
+#ifdef LOGV
+#define ALOGV LOGV
+#endif
+#endif
+#ifndef ALOGV_IF
+#ifdef LOGV_IF
+#define ALOGV_IF LOGV_IF
+#endif
+#endif
+
+
+#define DATA_AREA01 0x0001
+#define DATA_AREA02 0x0002
+#define DATA_AREA03 0x0004
+#define DATA_AREA04 0x0008
+#define DATA_AREA05 0x0010
+#define DATA_AREA06 0x0020
+#define DATA_AREA07 0x0040
+#define DATA_AREA08 0x0080
+#define DATA_AREA09 0x0100
+#define DATA_AREA10 0x0200
+#define DATA_AREA11 0x0400
+#define DATA_AREA12 0x0800
+#define DATA_AREA13 0x1000
+#define DATA_AREA14 0x2000
+#define DATA_AREA15 0x4000
+#define DATA_AREA16 0x8000
+
+
+/* Debug area definition */
+#define AKMDBG_DEBUG (DATA_AREA01) /*<! Debug output */
+#define AKMDBG_DUMP (DATA_AREA02) /*<! Error Dump */
+#define AKMDBG_EXECTIME (DATA_AREA03) /*<! Execution flags */
+#define AKMDBG_GETINTERVAL (DATA_AREA04) /*<! Interval */
+#define AKMDBG_VECTOR (DATA_AREA05) /*<! Sensor Vector */
+#define AKMDBG_D6D (DATA_AREA06) /*<! Direction6D */
+#define AKMDBG_PGYR (DATA_AREA07) /*<! Pseudo Gyroscope */
+#define AKMDBG_MAGDRV (DATA_AREA08) /*<! AKM driver's data */
+#define AKMDBG_ACCDRV (DATA_AREA09) /*<! Acceleration driver's data */
+#define AKMDBG_DISP1 (DATA_AREA10) /*<! DispMessage level1 */
+#define AKMDBG_DISP2 (DATA_AREA11) /*<! DispMessage level2 */
+#define AKMDBG_DOEPLUS (DATA_AREA12) /*<! DOEPlus */
+
+#ifndef ENABLE_AKMDEBUG
+#define ENABLE_AKMDEBUG (1) /* Eanble debug output when it is 1. */
+#endif
+
+/***** Debug output ******************************************/
+#if ENABLE_AKMDEBUG
+#define AKMDEBUG(flag, format, ...) \
+ ((((int)flag) & g_dbgzone) \
+ ? (fprintf(stdout, (format), ##__VA_ARGS__)) \
+ : ((void)0))
+#else
+#define AKMDEBUG(flag, format, ...)
+#endif
+
+/***** Log output ********************************************/
+#ifdef AKM_LOG_ENABLE
+#define AKM_LOG(format, ...) ALOGD((format), ##__VA_ARGS__)
+#else
+#define AKM_LOG(format, ...)
+#endif
+
+int g_akmlog_enable;
+
+
+/***** Error output *******************************************/
+#define AKMERROR \
+ (ALOGE("%s:%d Error.", __FUNCTION__, __LINE__))
+
+#define AKMERROR_STR(api) \
+ (ALOGE("%s:%d %s Error (%s).", \
+ __FUNCTION__, __LINE__, (api), strerror(errno)))
+
+/*** Type declaration *********************************************************/
+
+/*** Global variables *********************************************************/
+
+/*** Prototype of function ****************************************************/
+
+#endif //AKMD_INC_AKMLOG_H
+
diff --git a/mpu/akm8963/Acc_aot.c b/mpu/akm8963/Acc_aot.c
new file mode 100755
index 0000000..a98f577
--- /dev/null
+++ b/mpu/akm8963/Acc_aot.c
@@ -0,0 +1,93 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#include <fcntl.h>
+#include "Acc_aot.h"
+#include "AKCommon.h" /* For AKMERROR */
+
+extern int s_fdDev;
+
+/* Initialize communication device. See "AKMD_Driver.h" */
+int16_t AOT_InitDevice(void)
+{
+ /* When this function is called, the device file is already opened. */
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+
+ return AKD_SUCCESS;
+}
+
+/* Release communication device and resources. See "AKMD_Driver.h" */
+void AOT_DeinitDevice(void)
+{
+ /* When this function is called, the device file is already closed. */
+}
+
+int16_t AOT_SetEnable(const int8_t enabled)
+{
+ /* AOT cannot control device */
+ return AKD_SUCCESS;
+}
+
+int16_t AOT_SetDelay(const int64_t ns)
+{
+ /* AOT cannot control device */
+ return AKD_SUCCESS;
+}
+
+int16_t AOT_GetAccData(int16_t data[3])
+{
+ if (s_fdDev < 0) {
+ AKMERROR;
+ return AKD_FAIL;
+ }
+
+ /* Get acceleration data from "/dev/Acc_aot" */
+ if (ioctl(s_fdDev, ECS_IOCTL_GET_ACCEL, data) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+
+ AKMDEBUG(AKMDBG_ACCDRV, "%s: acc=%d, %d, %d\n",
+ __FUNCTION__, data[0], data[1], data[2]);
+
+ return AKD_SUCCESS;
+}
+
+int16_t AOT_GetAccOffset(int16_t offset[3])
+{
+ offset[0] = 0;
+ offset[1] = 0;
+ offset[2] = 0;
+ return AKD_SUCCESS;
+}
+
+void AOT_GetAccVector(const int16_t data[3], const int16_t offset[3], int16_t vec[3])
+{
+ vec[0] = (int16_t)(data[0] - offset[0]);
+ vec[1] = (int16_t)(data[1] - offset[1]);
+ vec[2] = (int16_t)(data[2] - offset[2]);
+}
+
diff --git a/mpu/akm8963/Acc_aot.h b/mpu/akm8963/Acc_aot.h
new file mode 100755
index 0000000..b58eea2
--- /dev/null
+++ b/mpu/akm8963/Acc_aot.h
@@ -0,0 +1,45 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKMD_INC_ACCAOT_H
+#define AKMD_INC_ACCAOT_H
+
+#include "AKMD_Driver.h"
+
+/*** Constant definition ******************************************************/
+
+/*** Type declaration *********************************************************/
+
+/*** Global variables *********************************************************/
+
+/*** Prototype of function ****************************************************/
+int16_t AOT_InitDevice(void);
+void AOT_DeinitDevice(void);
+int16_t AOT_SetEnable(const int8_t enabled);
+int16_t AOT_SetDelay(const int64_t ns);
+int16_t AOT_GetAccData(int16_t data[3]);
+int16_t AOT_GetAccOffset(int16_t offset[3]);
+void AOT_GetAccVector(const int16_t data[3], const int16_t offset[3], int16_t vec[3]);
+
+#endif //AKMD_INC_ACCAOT_H
+
diff --git a/mpu/akm8963/Acc_mma8452.c b/mpu/akm8963/Acc_mma8452.c
new file mode 100755
index 0000000..b8d8888
--- /dev/null
+++ b/mpu/akm8963/Acc_mma8452.c
@@ -0,0 +1,346 @@
+/* --------------------------------------------------------------------------------------------------------
+ * Copyright(C), 2010-2011, Fuzhou Rockchip Co. ,Ltd. All Rights Reserved.
+ *
+ * File: Acc_mma8452.c
+ *
+ * Desc: 实现 akmd8975 要求的 accelerometer sensor 的功能接口 : 开启, 关闭, 获取数据等.
+ *
+ * -----------------------------------------------------------------------------------
+ * < 习语 和 缩略语 > :
+ *
+ * acc : accelerometer sensor, "g sensor" 的 别名.
+ *
+ * -----------------------------------------------------------------------------------
+ * < 内部模块 or 对象的层次结构 > :
+ *
+ * -----------------------------------------------------------------------------------
+ * < 功能实现的基本流程 > :
+ *
+ * -----------------------------------------------------------------------------------
+ * < 关键标识符 > :
+ *
+ * -----------------------------------------------------------------------------------
+ * < 本模块实现依赖的外部模块 > :
+ * ...
+ * -----------------------------------------------------------------------------------
+ * Note:
+ *
+ * Author: ChenZhen
+ *
+ * --------------------------------------------------------------------------------------------------------
+ * Version:
+ * v1.0 : init version
+ * --------------------------------------------------------------------------------------------------------
+ * Log:
+ ----Wed Jan 19 18:55:55 2011 v1.0
+ *
+ * --------------------------------------------------------------------------------------------------------
+ */
+
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Include Files
+ * ---------------------------------------------------------------------------------------------------------
+ */
+#include <stdio.h>
+#include <time.h>
+#include <signal.h>
+#include <pthread.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "mma8452_kernel.h"
+
+#include "AKCommon.h"
+#include "AKMD_Driver.h"
+#include "Acc_mma8452.h"
+
+//#define ENABLE_DEBUG_LOG
+#include "custom_log.h"
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Local Macros
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+/** path to accelerometer control device. */
+#define ASENSOR_PATH "/dev/mma8452_daemon"
+
+/** 表征相同的 加速度物理量的时, "Android 上层使用的 数值" 和 "sensor 数据设备送出的 数值" 之间的比值. */
+#define ACCELERATION_RATIO_ANDROID_TO_HW (9.80665f / 1000000)
+
+/** "sDisableAccTimer" 在本 app 模块 scope 中的标识 ID. */
+#define APP_TIME_ID__DISABLE_ACC (1)
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Local Typedefs
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+typedef char bool;
+
+#undef TRUE
+#define TRUE 1
+
+#undef FALSE
+#define FALSE 0
+
+/* ---------------------------------------------------------------------------------------------------------
+ * External Function Prototypes (referenced in other file)
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Local Function Prototypes
+ * ---------------------------------------------------------------------------------------------------------
+ */
+void onTimeOut(sigval_t v);
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Local Variables
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+/** acc(g sensor) 控制设备(ASENSOR_PATH) 的 FD. */
+static int sAccFd = -1;
+
+/** timer, 用于定时超时之后 disable acc. 这里是 "系统 timer ID", 动态创建. */
+static timer_t sDisableAccTimer = -1;
+/** 若在 ENABLE_TIME_OUT 秒内, akmd8975 没有再次读取 acc 数据, 则 disable acc 设备. */
+static const int ENABLE_TIME_OUT = 5;
+
+/** 标识当前模块是否 使能了 acc 设备(要求其采集 g sensor 数据). */
+static bool sHasEnabledAcc = FALSE;
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Global Variables
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Global Functions Implementation
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+/**
+ * Open device driver.
+ * This function opens device driver of acceleration sensor.
+ * Additionally, measurement range is set to +/- 2G mode, bandwidth is set to 25Hz.
+ * @return
+ * If this function succeeds, the return value is #AKD_SUCCESS.
+ * Otherwise the return value is #AKD_FAIL.
+ */
+int16_t Acc_InitDevice(void)
+{
+ D("Entered.");
+ int16_t result = AKD_SUCCESS;
+ struct sigevent se; /* 将用来定义对 timer 超时事件的定制处理方式. */
+ struct itimerspec ts; /* 将用于定义超时时间. */
+
+ /* 尝试打开 acc 控制设备文件. */
+ if ( 0 > (sAccFd = open(ASENSOR_PATH, O_RDONLY ) ) )
+ {
+ E("failed to open acc file '%s', error is '%s'", ASENSOR_PATH, strerror(errno));
+ result = AKD_FAIL;
+ goto EXIT;
+ }
+
+ /* < 创建 sDisableAccTimer. > */
+ memset(&se, 0, sizeof(se) );
+ se.sigev_notify = SIGEV_THREAD; /* "A notification function will be called to perform notification". */
+ se.sigev_notify_function = onTimeOut; /* 通知回调函数. */
+ se.sigev_value.sival_int = APP_TIME_ID__DISABLE_ACC; /* sigev_value : sigev_notify_function 的回调实参. */
+ if ( timer_create (CLOCK_REALTIME, &se, &sDisableAccTimer) < 0 )
+ {
+ E("failed create 'sDisableAccTimer'; error is '%s'.", strerror(errno));
+ result = AKD_FAIL;
+ goto EXIT;
+ }
+ // sDisableAccTimer 将在 Acc_GetAccelerationData() 中启动.
+
+ sHasEnabledAcc = FALSE; // 显式初始化.
+
+EXIT:
+ if ( AKD_SUCCESS != result )
+ {
+ if ( -1 != sDisableAccTimer )
+ {
+ timer_delete(sDisableAccTimer);
+ sDisableAccTimer = -1;
+ }
+ if ( -1 != sAccFd )
+ {
+ close(sAccFd);
+ sAccFd = -1;
+ }
+ }
+
+ return result;
+}
+
+/**
+ * Close device driver.
+ * This function closes device drivers of acceleration sensor.
+ */
+void Acc_DeinitDevice(void)
+{
+ ALOGI("Entered.");
+
+ timer_delete(sDisableAccTimer);
+ sDisableAccTimer = -1;
+
+ /* 若 acc 设备已经被启动, 则... */
+ if ( sHasEnabledAcc )
+ {
+ D("to call 'GSENSOR_IOCTL_CLOSE'.");
+ if ( ioctl(sAccFd, GSENSOR_IOCTL_CLOSE) < 0 )
+ {
+ E("failed to disable acc device.");
+ }
+ sHasEnabledAcc = FALSE;
+ }
+
+ close(sAccFd);
+ sAccFd = -1;
+}
+
+/**
+ * Acquire acceleration data from acceleration sensor and convert it to Android coordinate system.
+ * .! : 目前设计为 尽量不阻塞的形式.
+ * @param[out] fData
+ * A acceleration data array.
+ * The coordinate system of the acquired data follows the definition of Android.
+ * @return
+ * If this function succeeds, the return value is #AKD_SUCCESS.
+ * Otherwise the return value is #AKD_FAIL.
+ *
+ */
+int16_t Acc_GetAccData(int16_t fData[3])
+{
+ int16_t result = AKD_SUCCESS;
+ struct itimerspec ts; /* 将用于定义超时时间. */
+
+ struct sensor_axis accData = {0, 0, 0};
+
+ /* 若尚未使能 acc, 则... */
+ if ( !sHasEnabledAcc )
+ {
+ /* 使能 acc. */
+ if ( 0 > ioctl(sAccFd, GSENSOR_IOCTL_START) )
+ {
+ E("failed to START acc device; error is '%s'.", strerror(errno));
+ result = AKD_FAIL;
+ goto EXIT;
+ }
+ /* 设置采样率. */
+ int sample_rate = MMA8452_RATE_12P5; // .! : 暂时先使用 12.5 Hz.
+ if ( 0 > ioctl(sAccFd, GSENSOR_IOCTL_APP_SET_RATE, &sample_rate) )
+ {
+ E("failed to set sample rete of acc device; error is '%s'.", strerror(errno));
+ result = AKD_FAIL;
+ goto EXIT;
+ }
+ /* 置位标识. */
+ sHasEnabledAcc = TRUE;
+ }
+
+ /* 获取 acc sensor 数据. */ // .! : 尽量不阻塞.
+ if ( 0 > ioctl(sAccFd, GSENSOR_IOCTL_GETDATA, &accData) )
+ {
+ E("failed to GET acc data, error is '%s.'", strerror(errno));
+ result = AKD_FAIL;
+ goto EXIT;
+ }
+
+ /* 重置 sDisableAccTimer. */
+ // D("to reset 'sDisableAccTimer'.");
+ memset(&ts, 0, sizeof(ts) );
+ ts.it_value.tv_sec = ENABLE_TIME_OUT;
+ if ( timer_settime(sDisableAccTimer, 0, &ts, NULL) < 0 )
+ {
+ E("failed start 'sDisableAccTimer'; error is '%s'.", strerror(errno));
+ result = AKD_FAIL;
+ goto EXIT;
+ }
+
+ /* 转化为 Android 定义的格式, 待返回. */ // .! : 和 HAL 的 MmaSensor.cpp 中一致, 使用 默认横屏坐标定义 g sensor 数据.
+ fData[0] = ( (accData.x) * ACCELERATION_RATIO_ANDROID_TO_HW);
+ fData[1] = ( (accData.y) * ACCELERATION_RATIO_ANDROID_TO_HW);
+ fData[2] = ( (accData.z) * ACCELERATION_RATIO_ANDROID_TO_HW);
+ fData[0] = fData[0]/9.8f * 720;
+ fData[1] = fData[1]/9.8f * 720;
+ fData[2] = fData[2]/9.8f * 720;
+ D_WHEN_REPEAT(100, "got acc sensor data : x = %f, y = %f, z = %f.", fData[0], fData[1], fData[2] );
+
+EXIT:
+ return result;
+}
+
+int16_t Acc_SetEnable(const int8_t enabled)
+{
+ /* AOT cannot control device */
+ return AKD_SUCCESS;
+}
+
+int16_t Acc_SetDelay(const int64_t ns)
+{
+ /* AOT cannot control device */
+ return AKD_SUCCESS;
+}
+
+
+int16_t Acc_GetAccOffset(int16_t offset[3])
+{
+ offset[0] = 0;
+ offset[1] = 0;
+ offset[2] = 0;
+ return AKD_SUCCESS;
+}
+
+void Acc_GetAccVector(const int16_t data[3], const int16_t offset[3], int16_t vec[3])
+{
+ vec[0] = (int16_t)(data[0] - offset[0]);
+ vec[1] = (int16_t)(data[1] - offset[1]);
+ vec[2] = (int16_t)(data[2] - offset[2]);
+}
+
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Local Functions Implementation
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+/**
+ * sDisableAccTimer 超时的通知回调.
+ */
+void onTimeOut(sigval_t v)
+{
+ int appTimerId = v.sival_int;
+ I("'sDisableAccTimer' timers out, appTimerId = %d.", appTimerId);
+ switch ( appTimerId )
+ {
+ case APP_TIME_ID__DISABLE_ACC:
+ D("to disable acc device.");
+ if ( sHasEnabledAcc )
+ {
+ D("to call 'GSENSOR_IOCTL_CLOSE'.");
+ if ( ioctl(sAccFd, GSENSOR_IOCTL_CLOSE) < 0 )
+ {
+ E("failed to disable acc device.");
+ }
+ sHasEnabledAcc = FALSE;
+ }
+ break;
+
+ default:
+ E("unknow app timer ID.");
+ return;
+ }
+}
+
diff --git a/mpu/akm8963/Acc_mma8452.h b/mpu/akm8963/Acc_mma8452.h
new file mode 100755
index 0000000..150ee08
--- /dev/null
+++ b/mpu/akm8963/Acc_mma8452.h
@@ -0,0 +1,75 @@
+/* --------------------------------------------------------------------------------------------------------
+ * Copyright(C), 2010-2011, Fuzhou Rockchip Co., Ltd. All Rights Reserved.
+ *
+ * File: Acc_mma8452.h
+ *
+ * Desc:
+ *
+ * -----------------------------------------------------------------------------------
+ * < 习语 和 缩略语 > :
+ *
+ * -----------------------------------------------------------------------------------
+ * Usage:
+ *
+ * Note:
+ *
+ * Author: ChenZhen
+ *
+ * --------------------------------------------------------------------------------------------------------
+ * Version:
+ * v1.0
+ * --------------------------------------------------------------------------------------------------------
+ * Log:
+ *
+ * --------------------------------------------------------------------------------------------------------
+ */
+
+
+#ifndef __ACC_MMA8452_H__
+#define __ACC_MMA8452_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Include Files
+ * ---------------------------------------------------------------------------------------------------------
+ */
+#include "AKCommon.h"
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Macros Definition
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Types and Structures Definition
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Global Functions' Prototype
+ * ---------------------------------------------------------------------------------------------------------
+ */
+int16_t Acc_InitDevice(void);
+void Acc_DeinitDevice(void);
+int16_t Acc_GetAccData(int16_t fData[3]);
+int16_t Acc_SetEnable(const int8_t enabled);
+int16_t Acc_SetDelay(const int64_t ns);
+int16_t Acc_GetAccOffset(int16_t offset[3]);
+void Acc_GetAccVector(const int16_t data[3], const int16_t offset[3], int16_t vec[3]);
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Inline Functions Implementation
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ACC_MMA8452_H__ */
+
diff --git a/mpu/akm8963/Android.mk b/mpu/akm8963/Android.mk
new file mode 100755
index 0000000..94540f2
--- /dev/null
+++ b/mpu/akm8963/Android.mk
@@ -0,0 +1,82 @@
+ifeq (${TARGET_ARCH},arm64)
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_PATH:= $(call my-dir)
+
+SMARTCOMPASS_LIB=libSmartCompass
+
+AKMD_DEVICE_TYPE := 8963
+AKMD_ACC_AOT := yes
+
+include $(CLEAR_VARS)
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/$(SMARTCOMPASS_LIB)
+
+LOCAL_SRC_FILES:= \
+ AKMD_Driver.c \
+ DispMessage.c \
+ FileIO.c \
+ Measure.c \
+ main.c \
+ misc.c
+
+LOCAL_MODULE := akmd
+
+ifeq ($(AKMD_DEVICE_TYPE), 8963)
+LOCAL_SRC_FILES += FST_AK8963.c
+LOCAL_CFLAGS += -DAKMD_FOR_AK8963
+LOCAL_LDFLAGS += -L$(LOCAL_PATH)/$(SMARTCOMPASS_LIB) -lAK8963wPGplus
+
+else ifeq ($(AKMD_DEVICE_TYPE), 8975)
+LOCAL_SRC_FILES += FST_AK8975.c
+LOCAL_CFLAGS += -DAKMD_FOR_AK8975
+LOCAL_LDFLAGS += -L$(LOCAL_PATH)/$(SMARTCOMPASS_LIB) -lAK8975wPGplus
+
+else ifeq ($(AKMD_DEVICE_TYPE), 9911)
+LOCAL_SRC_FILES += FST_AK09911.c
+LOCAL_CFLAGS += -DAKMD_FOR_AK09911
+LOCAL_CFLAGS += -DAKMD_AK099XX
+LOCAL_LDFLAGS += -L$(LOCAL_PATH)/$(SMARTCOMPASS_LIB) -lAK09911wPGplus
+
+else
+$(error AKMD_DEVICE_TYPE is not defined)
+endif
+
+
+### Acceleration Sensors
+ifeq ($(AKMD_ACC_AOT),yes)
+#LOCAL_CFLAGS += -DAKMD_ACC_EXTERNAL
+#LOCAL_SRC_FILES += Acc_aot.c
+else
+
+ifeq ($(AKMD_SENSOR_ACC),adxl346)
+LOCAL_CFLAGS += -DAKMD_ACC_ADXL346
+LOCAL_SRC_FILES += Acc_adxl34x.c
+
+else ifeq ($(AKMD_SENSOR_ACC),kxtf9)
+LOCAL_CFLAGS += -DAKMD_ACC_KXTF9
+LOCAL_SRC_FILES += Acc_kxtf9.c
+
+else ifeq ($(AKMD_SENSOR_ACC),dummy)
+LOCAL_CFLAGS += -DAKMD_ACC_DUMMY
+LOCAL_SRC_FILES += Acc_dummy.c
+
+else
+$(error AKMD_SENSOR_ACC is not defined)
+endif
+
+endif
+
+LOCAL_CFLAGS += -Wall -Wextra
+#LOCAL_CFLAGS += -DENABLE_AKMDEBUG=1
+#LOCAL_CFLAGS += -DAKM_LOG_ENABLE
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_FORCE_STATIC_EXECUTABLE := false
+LOCAL_STATIC_LIBRARIES :=
+LOCAL_SHARED_LIBRARIES := libc libm libutils libcutils
+include $(BUILD_EXECUTABLE)
+
+
+endif # TARGET_SIMULATOR != true
+endif # TARGET_ARCH := arm64
diff --git a/mpu/akm8963/CustomerSpec.h b/mpu/akm8963/CustomerSpec.h
new file mode 100755
index 0000000..ac10b4e
--- /dev/null
+++ b/mpu/akm8963/CustomerSpec.h
@@ -0,0 +1,75 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKMD_INC_CUSTOMERSPEC_H
+#define AKMD_INC_CUSTOMERSPEC_H
+
+/*******************************************************************************
+ User defines parameters.
+ ******************************************************************************/
+
+// Certification information
+#define CSPEC_CI_LICENSER "ASAHIKASEI"
+#define CSPEC_CI_LICENSEE "RC_63_V7_AR_64"
+
+// Parameters for Average
+// The number of magnetic data to be averaged.
+// CSPEC_HNAVE must be 1, 2, 4, 8, 16 or 32.
+#define CSPEC_HNAVE 32
+
+// Parameters for Direction Calculation
+#define CSPEC_DVEC_X 0
+#define CSPEC_DVEC_Y 0
+#define CSPEC_DVEC_Z 0
+
+// The number of formation
+#define CSPEC_NUM_FORMATION 2
+
+// the counter of Suspend
+#define CSPEC_CNTSUSPEND_SNG 8
+
+// Parameters for FST
+// 1 : USE SPI
+// 0 : NOT USE SPI(I2C)
+#define CSPEC_SPI_USE 0
+
+//Parameters for Temperature sensor
+// 0x00 : disable
+// 0x80 : enable
+#define CSPEC_TEMPERATURE 0x80
+
+//Parameters for Noise Suppression Filter
+// 0x00 : disable
+// 0x20 : Low
+// 0x40 : Middle
+// 0x60 : High
+#define CSPEC_NSF 0x40
+
+// Setting file
+#define CSPEC_SETTING_FILE "/data/misc/akmd_set.txt"
+#define CSPEC_PDC_FILE "/data/misc/pdc.txt"
+
+// DOEPlus(software softiron distortion compensation) Enable(1)/Disable(0)
+#define CSPEC_ENABLE_DOEPLUS 1
+#endif //AKMD_INC_CUSTOMERSPEC_H
+
diff --git a/mpu/akm8963/DispMessage.c b/mpu/akm8963/DispMessage.c
new file mode 100755
index 0000000..c731ef9
--- /dev/null
+++ b/mpu/akm8963/DispMessage.c
@@ -0,0 +1,127 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#include "DispMessage.h"
+#include "AKCommon.h"
+
+/*!
+ Print startup message to Android Log daemon.
+ */
+void Disp_StartMessage(void)
+{
+ ALOGI("AKMD PG and DOEPlus v20140729 (Library for AK%d: v%d.%d.%d.%d.%d) started.",
+ AKSC_GetVersion_Device(),
+ AKSC_GetVersion_Major(),
+ AKSC_GetVersion_Minor(),
+ AKSC_GetVersion_Revision(),
+ AKSC_GetVersion_DateCode(),
+ AKSC_GetVersion_Variation());
+ ALOGI("Debug: %s", ((ENABLE_AKMDEBUG)?("ON"):("OFF")));
+}
+
+/*!
+ Print ending message to Android Log daemon.
+ */
+void Disp_EndMessage(int ret)
+{
+ ALOGI("AKMD end (%d).", ret);
+}
+
+/*!
+ Print calculated result.
+ @param[in] prms A pointer to a #AKSCPRMS structure. The value of member
+ variables of this structure will be printed.
+ */
+void Disp_MeasurementResult(AKSCPRMS* prms)
+{
+ AKMDEBUG(AKMDBG_DISP2, "FORMATION = %d\n", prms->m_form);
+
+ if (prms->m_d6dRet & 0x1) {
+ AKMDEBUG(AKMDBG_DISP1, "THETA[deg]=%6.1f, ", DISP_CONV_Q6F(prms->m_theta));
+ } else {
+ AKMDEBUG(AKMDBG_DISP1, "THETA[deg]= - , ");
+ }
+ if (prms->m_d6dRet & 0x2) {
+ AKMDEBUG(AKMDBG_DISP1, "PITCH[deg]=%6.1f(%6.1f), ROLL[deg]=%6.1f(%6.1f)\n",
+ DISP_CONV_Q6F(prms->m_phi180),
+ DISP_CONV_Q6F(prms->m_phi90),
+ DISP_CONV_Q6F(prms->m_eta180),
+ DISP_CONV_Q6F(prms->m_eta90)
+ );
+ } else {
+ AKMDEBUG(AKMDBG_DISP1, "PITCH[deg]= - ( - ), ROLL[deg]= - ( - )\n");
+ }
+
+ // hr is in AKSC format, i.e. 1LSB = 0.06uT
+ AKMDEBUG(AKMDBG_DISP1, "HR[uT]=%5.1f\n", DISP_CONV_AKSCF(prms->m_hr));
+ AKMDEBUG(AKMDBG_DISP2, "HR HORIZ[uT]=%5.1f\n", DISP_CONV_AKSCF(prms->m_hrhoriz));
+ AKMDEBUG(AKMDBG_DISP2, "INCLINATION[deg]=%6.1f\n", DISP_CONV_Q6F(prms->m_delta));
+
+ AKMDEBUG(AKMDBG_DISP2, "HDOE Parameter Set:%s\n",
+ ((prms->m_hdoev.hthIdx == AKSC_HDFI_SMA)?"Small":"Normal"));
+ AKMDEBUG(AKMDBG_DISP1, "LEVEL=%2d\n", prms->m_hdst);
+ AKMDEBUG(AKMDBG_DISP2, "HOFFSET[uT]: x=%8.1f, y=%8.1f, z=%8.1f\n",
+ DISP_CONV_AKSCF((int32)prms->m_ho.u.x + prms->m_hbase.u.x),
+ DISP_CONV_AKSCF((int32)prms->m_ho.u.y + prms->m_hbase.u.y),
+ DISP_CONV_AKSCF((int32)prms->m_ho.u.z + prms->m_hbase.u.z));
+ AKMDEBUG(AKMDBG_DISP2, "DOE HR[uT]=%5.1f\n",
+ DISP_CONV_AKSCF(prms->m_hdoev.hrdoeHR));
+
+ AKMDEBUG(AKMDBG_DISP1, "\n");
+}
+
+/*!
+ Output main menu to stdout and wait for user input from stdin.
+ @return Selected mode.
+ */
+MODE Menu_Main(void)
+{
+ char msg[20];
+ memset(msg, 0, sizeof(msg));
+
+ AKMDEBUG(AKMDBG_DISP1, " ------------------ AKMD main menu ------------------ \n");
+ AKMDEBUG(AKMDBG_DISP1, " T. Start Factory Shipment Test. \n");
+ AKMDEBUG(AKMDBG_DISP1, " 1. Start Single Measurement. \n");
+ AKMDEBUG(AKMDBG_DISP1, " 2. Start simple offset calibration. \n");
+ AKMDEBUG(AKMDBG_DISP1, " Q. Quit application. \n");
+ AKMDEBUG(AKMDBG_DISP1, " ----------------------------------------------------- \n\n");
+ AKMDEBUG(AKMDBG_DISP1, " Please select a number.\n");
+ AKMDEBUG(AKMDBG_DISP1, " ---> ");
+ fgets(msg, 10, stdin);
+ AKMDEBUG(AKMDBG_DISP1, "\n");
+
+ // BUG : If 2-digits number is input,
+ // only the first character is compared.
+ if (strncmp(msg, "T", 1) == 0 || strncmp(msg, "t", 1) == 0) {
+ return MODE_FST;
+ } else if (!strncmp(msg, "1", 1)) {
+ return MODE_MeasureSNG;
+ } else if (!strncmp(msg, "2", 1)) {
+ return MODE_OffsetCalibration;
+ } else if (strncmp(msg, "Q", 1) == 0 || strncmp(msg, "q", 1) == 0) {
+ return MODE_Quit;
+ } else {
+ return MODE_ERROR;
+ }
+}
+
diff --git a/mpu/akm8963/DispMessage.h b/mpu/akm8963/DispMessage.h
new file mode 100755
index 0000000..af67970
--- /dev/null
+++ b/mpu/akm8963/DispMessage.h
@@ -0,0 +1,61 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKMD_INC_DISPMESG_H
+#define AKMD_INC_DISPMESG_H
+
+// Include file for SmartCompass Library.
+#include "AKCompass.h"
+
+/*** Constant definition ******************************************************/
+#define DISP_CONV_AKSCF(val) ((val)*0.06f)
+#define DISP_CONV_Q6F(val) ((val)*0.015625f)
+
+/*** Type declaration *********************************************************/
+
+/*! These defined types represents the current mode. */
+typedef enum _MODE {
+ MODE_ERROR, /*!< Error */
+ MODE_FST, /*!< On board function test */
+ MODE_MeasureSNG, /*!< Measurement */
+ MODE_OffsetCalibration, /*!< Offset calibration */
+ MODE_Quit /*!< Quit */
+} MODE;
+
+/*** Prototype of function ****************************************************/
+// Disp_ : Display messages.
+// Menu_ : Display menu (two or more selection) and wait for user input.
+
+void Disp_StartMessage(void);
+
+void Disp_EndMessage(int ret);
+
+void Disp_MeasurementResult(AKSCPRMS* prms);
+
+// Defined in main.c
+void Disp_MeasurementResultHook(AKSCPRMS* prms, const uint16 flag);
+
+MODE Menu_Main(void);
+
+#endif
+
diff --git a/mpu/akm8963/FST.h b/mpu/akm8963/FST.h
new file mode 100755
index 0000000..9cd15c9
--- /dev/null
+++ b/mpu/akm8963/FST.h
@@ -0,0 +1,33 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKMD_INC_FST_H
+#define AKMD_INC_FST_H
+
+#include "AKCommon.h"
+#include "AKCompass.h"
+
+int16 FST_Body(AKSCPRMS* prms);
+
+#endif
+
diff --git a/mpu/akm8963/FST_AK09911.c b/mpu/akm8963/FST_AK09911.c
new file mode 100755
index 0000000..360c1ff
--- /dev/null
+++ b/mpu/akm8963/FST_AK09911.c
@@ -0,0 +1,759 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#include "AKCommon.h"
+#include "AKMD_Driver.h"
+#include "FST.h"
+#include "misc.h"
+
+#ifndef AKMD_FOR_AK09911
+#error "AKMD parameter is not set"
+#endif
+
+#define TLIMIT_TN_REVISION_09911 ""
+#define TLIMIT_NO_RST_WIA1_09911 "1-3"
+#define TLIMIT_TN_RST_WIA1_09911 "RST_WIA1"
+#define TLIMIT_LO_RST_WIA1_09911 0x48
+#define TLIMIT_HI_RST_WIA1_09911 0x48
+#define TLIMIT_NO_RST_WIA2_09911 "1-4"
+#define TLIMIT_TN_RST_WIA2_09911 "RST_WIA2"
+#define TLIMIT_LO_RST_WIA2_09911 0x05
+#define TLIMIT_HI_RST_WIA2_09911 0x05
+
+#define TLIMIT_NO_ASAX_09911 "1-7"
+#define TLIMIT_TN_ASAX_09911 "ASAX"
+#define TLIMIT_LO_ASAX_09911 1
+#define TLIMIT_HI_ASAX_09911 254
+#define TLIMIT_NO_ASAY_09911 "1-8"
+#define TLIMIT_TN_ASAY_09911 "ASAY"
+#define TLIMIT_LO_ASAY_09911 1
+#define TLIMIT_HI_ASAY_09911 254
+#define TLIMIT_NO_ASAZ_09911 "1-9"
+#define TLIMIT_TN_ASAZ_09911 "ASAZ"
+#define TLIMIT_LO_ASAZ_09911 1
+#define TLIMIT_HI_ASAZ_09911 254
+
+#define TLIMIT_NO_SNG_ST1_09911 "2-3"
+#define TLIMIT_TN_SNG_ST1_09911 "SNG_ST1"
+#define TLIMIT_LO_SNG_ST1_09911 1
+#define TLIMIT_HI_SNG_ST1_09911 1
+
+#define TLIMIT_NO_SNG_HX_09911 "2-4"
+#define TLIMIT_TN_SNG_HX_09911 "SNG_HX"
+#define TLIMIT_LO_SNG_HX_09911 -8189
+#define TLIMIT_HI_SNG_HX_09911 8189
+
+#define TLIMIT_NO_SNG_HY_09911 "2-6"
+#define TLIMIT_TN_SNG_HY_09911 "SNG_HY"
+#define TLIMIT_LO_SNG_HY_09911 -8189
+#define TLIMIT_HI_SNG_HY_09911 8189
+
+#define TLIMIT_NO_SNG_HZ_09911 "2-8"
+#define TLIMIT_TN_SNG_HZ_09911 "SNG_HZ"
+#define TLIMIT_LO_SNG_HZ_09911 -8189
+#define TLIMIT_HI_SNG_HZ_09911 8189
+
+#define TLIMIT_NO_SNG_ST2_09911 "2-10"
+#define TLIMIT_TN_SNG_ST2_09911 "SNG_ST2"
+#define TLIMIT_LO_SNG_ST2_09911 0
+#define TLIMIT_HI_SNG_ST2_09911 0
+
+#define TLIMIT_NO_SLF_ST1_09911 "2-13"
+#define TLIMIT_TN_SLF_ST1_09911 "SLF_ST1"
+#define TLIMIT_LO_SLF_ST1_09911 1
+#define TLIMIT_HI_SLF_ST1_09911 1
+
+#define TLIMIT_NO_SLF_RVHX_09911 "2-14"
+#define TLIMIT_TN_SLF_RVHX_09911 "SLF_REVSHX"
+#define TLIMIT_LO_SLF_RVHX_09911 -30
+#define TLIMIT_HI_SLF_RVHX_09911 30
+
+#define TLIMIT_NO_SLF_RVHY_09911 "2-16"
+#define TLIMIT_TN_SLF_RVHY_09911 "SLF_REVSHY"
+#define TLIMIT_LO_SLF_RVHY_09911 -30
+#define TLIMIT_HI_SLF_RVHY_09911 30
+
+#define TLIMIT_NO_SLF_RVHZ_09911 "2-18"
+#define TLIMIT_TN_SLF_RVHZ_09911 "SLF_REVSHZ"
+#define TLIMIT_LO_SLF_RVHZ_09911 -400
+#define TLIMIT_HI_SLF_RVHZ_09911 -50
+
+#define TLIMIT_NO_SLF_ST2_09911 "2-20"
+#define TLIMIT_TN_SLF_ST2_09911 "SLF_ST2"
+#define TLIMIT_LO_SLF_ST2_09911 0
+#define TLIMIT_HI_SLF_ST2_09911 0
+
+
+////below is for AK8963C
+#define TLIMIT_TN_REVISION ""
+#define TLIMIT_NO_RST_WIA "1-3"
+#define TLIMIT_TN_RST_WIA "RST_WIA"
+#define TLIMIT_LO_RST_WIA 0x48
+#define TLIMIT_HI_RST_WIA 0x48
+#define TLIMIT_NO_RST_INFO "1-4"
+#define TLIMIT_TN_RST_INFO "RST_INFO"
+#define TLIMIT_LO_RST_INFO 0
+#define TLIMIT_HI_RST_INFO 255
+#define TLIMIT_NO_RST_ST1 "1-5"
+#define TLIMIT_TN_RST_ST1 "RST_ST1"
+#define TLIMIT_LO_RST_ST1 0
+#define TLIMIT_HI_RST_ST1 0
+#define TLIMIT_NO_RST_HXL "1-6"
+#define TLIMIT_TN_RST_HXL "RST_HXL"
+#define TLIMIT_LO_RST_HXL 0
+#define TLIMIT_HI_RST_HXL 0
+#define TLIMIT_NO_RST_HXH "1-7"
+#define TLIMIT_TN_RST_HXH "RST_HXH"
+#define TLIMIT_LO_RST_HXH 0
+#define TLIMIT_HI_RST_HXH 0
+#define TLIMIT_NO_RST_HYL "1-8"
+#define TLIMIT_TN_RST_HYL "RST_HYL"
+#define TLIMIT_LO_RST_HYL 0
+#define TLIMIT_HI_RST_HYL 0
+#define TLIMIT_NO_RST_HYH "1-9"
+#define TLIMIT_TN_RST_HYH "RST_HYH"
+#define TLIMIT_LO_RST_HYH 0
+#define TLIMIT_HI_RST_HYH 0
+#define TLIMIT_NO_RST_HZL "1-10"
+#define TLIMIT_TN_RST_HZL "RST_HZL"
+#define TLIMIT_LO_RST_HZL 0
+#define TLIMIT_HI_RST_HZL 0
+#define TLIMIT_NO_RST_HZH "1-11"
+#define TLIMIT_TN_RST_HZH "RST_HZH"
+#define TLIMIT_LO_RST_HZH 0
+#define TLIMIT_HI_RST_HZH 0
+#define TLIMIT_NO_RST_ST2 "1-12"
+#define TLIMIT_TN_RST_ST2 "RST_ST2"
+#define TLIMIT_LO_RST_ST2 0
+#define TLIMIT_HI_RST_ST2 0
+#define TLIMIT_NO_RST_CNTL1 "1-13"
+#define TLIMIT_TN_RST_CNTL1 "RST_CNTL1"
+#define TLIMIT_LO_RST_CNTL1 0
+#define TLIMIT_HI_RST_CNTL1 0
+#define TLIMIT_NO_RST_CNTL2 "1-14"
+#define TLIMIT_TN_RST_CNTL2 "RST_CNTL2"
+#define TLIMIT_LO_RST_CNTL2 0
+#define TLIMIT_HI_RST_CNTL2 0
+
+#define TLIMIT_NO_RST_ASTC "1-15"
+#define TLIMIT_TN_RST_ASTC "RST_ASTC"
+#define TLIMIT_LO_RST_ASTC 0
+#define TLIMIT_HI_RST_ASTC 0
+#define TLIMIT_NO_RST_I2CDIS "1-16"
+#define TLIMIT_TN_RST_I2CDIS "RST_I2CDIS"
+#define TLIMIT_LO_RST_I2CDIS_USEI2C 0
+#define TLIMIT_HI_RST_I2CDIS_USEI2C 0
+#define TLIMIT_LO_RST_I2CDIS_USESPI 1
+#define TLIMIT_HI_RST_I2CDIS_USESPI 1
+#define TLIMIT_NO_ASAX "1-18"
+#define TLIMIT_TN_ASAX "ASAX"
+#define TLIMIT_LO_ASAX 1
+#define TLIMIT_HI_ASAX 254
+#define TLIMIT_NO_ASAY "1-19"
+#define TLIMIT_TN_ASAY "ASAY"
+#define TLIMIT_LO_ASAY 1
+#define TLIMIT_HI_ASAY 254
+#define TLIMIT_NO_ASAZ "1-20"
+#define TLIMIT_TN_ASAZ "ASAZ"
+#define TLIMIT_LO_ASAZ 1
+#define TLIMIT_HI_ASAZ 254
+#define TLIMIT_NO_WR_CNTL1 "1-21"
+#define TLIMIT_TN_WR_CNTL1 "WR_CNTL1"
+#define TLIMIT_LO_WR_CNTL1 0x0F
+#define TLIMIT_HI_WR_CNTL1 0x0F
+
+#define TLIMIT_NO_SNG_ST1 "2-3"
+#define TLIMIT_TN_SNG_ST1 "SNG_ST1"
+#define TLIMIT_LO_SNG_ST1 1
+#define TLIMIT_HI_SNG_ST1 1
+
+#define TLIMIT_NO_SNG_HX "2-4"
+#define TLIMIT_TN_SNG_HX "SNG_HX"
+#define TLIMIT_LO_SNG_HX -32759
+#define TLIMIT_HI_SNG_HX 32759
+
+#define TLIMIT_NO_SNG_HY "2-6"
+#define TLIMIT_TN_SNG_HY "SNG_HY"
+#define TLIMIT_LO_SNG_HY -32759
+#define TLIMIT_HI_SNG_HY 32759
+
+#define TLIMIT_NO_SNG_HZ "2-8"
+#define TLIMIT_TN_SNG_HZ "SNG_HZ"
+#define TLIMIT_LO_SNG_HZ -32759
+#define TLIMIT_HI_SNG_HZ 32759
+
+#define TLIMIT_NO_SNG_ST2 "2-10"
+#define TLIMIT_TN_SNG_ST2 "SNG_ST2"
+#define TLIMIT_LO_SNG_ST2_14BIT 0
+#define TLIMIT_HI_SNG_ST2_14BIT 0
+#define TLIMIT_LO_SNG_ST2_16BIT 16
+#define TLIMIT_HI_SNG_ST2_16BIT 16
+
+#define TLIMIT_NO_SLF_ST1 "2-14"
+#define TLIMIT_TN_SLF_ST1 "SLF_ST1"
+#define TLIMIT_LO_SLF_ST1 1
+#define TLIMIT_HI_SLF_ST1 1
+
+#define TLIMIT_NO_SLF_RVHX "2-15"
+#define TLIMIT_TN_SLF_RVHX "SLF_REVSHX"
+#define TLIMIT_LO_SLF_RVHX -200
+#define TLIMIT_HI_SLF_RVHX 200
+
+#define TLIMIT_NO_SLF_RVHY "2-17"
+#define TLIMIT_TN_SLF_RVHY "SLF_REVSHY"
+#define TLIMIT_LO_SLF_RVHY -200
+#define TLIMIT_HI_SLF_RVHY 200
+
+#define TLIMIT_NO_SLF_RVHZ "2-19"
+#define TLIMIT_TN_SLF_RVHZ "SLF_REVSHZ"
+#define TLIMIT_LO_SLF_RVHZ -3200
+#define TLIMIT_HI_SLF_RVHZ -800
+
+#define TLIMIT_NO_SLF_ST2 "2-21"
+#define TLIMIT_TN_SLF_ST2 "SLF_ST2"
+#define TLIMIT_LO_SLF_ST2_14BIT 0
+#define TLIMIT_HI_SLF_ST2_14BIT 0
+#define TLIMIT_LO_SLF_ST2_16BIT 16
+#define TLIMIT_HI_SLF_ST2_16BIT 16
+
+
+/*!
+ @return If @a testdata is in the range of between @a lolimit and @a hilimit,
+ the return value is 1, otherwise -1.
+ @param[in] testno A pointer to a text string.
+ @param[in] testname A pointer to a text string.
+ @param[in] testdata A data to be tested.
+ @param[in] lolimit The maximum allowable value of @a testdata.
+ @param[in] hilimit The minimum allowable value of @a testdata.
+ @param[in,out] pf_total
+ */
+int16
+TEST_DATA(const char testno[],
+ const char testname[],
+ const int16 testdata,
+ const int16 lolimit,
+ const int16 hilimit,
+ int16 * pf_total)
+{
+ int16 pf; //Pass;1, Fail;-1
+
+ if ((testno == NULL) && (strncmp(testname, "START", 5) == 0)) {
+ // Display header
+ AKMDEBUG(AKMDBG_DISP1, "--------------------------------------------------------------------\n");
+ AKMDEBUG(AKMDBG_DISP1, " Test No. Test Name Fail Test Data [ Low High]\n");
+ AKMDEBUG(AKMDBG_DISP1, "--------------------------------------------------------------------\n");
+
+ pf = 1;
+ } else if ((testno == NULL) && (strncmp(testname, "END", 3) == 0)) {
+ // Display result
+ AKMDEBUG(AKMDBG_DISP1, "--------------------------------------------------------------------\n");
+ if (*pf_total == 1) {
+ AKMDEBUG(AKMDBG_DISP1, "Factory shipment test was passed.\n\n");
+ } else {
+ AKMDEBUG(AKMDBG_DISP1, "Factory shipment test was failed.\n\n");
+ }
+
+ pf = 1;
+ } else {
+ if ((lolimit <= testdata) && (testdata <= hilimit)) {
+ //Pass
+ pf = 1;
+ } else {
+ //Fail
+ pf = -1;
+ }
+
+ //display result
+ AKMDEBUG(AKMDBG_DISP1, " %7s %-10s %c %9d [%9d %9d]\n",
+ testno, testname, ((pf == 1) ? ('.') : ('F')), testdata,
+ lolimit, hilimit);
+ }
+
+ //Pass/Fail check
+ if (*pf_total != 0) {
+ if ((*pf_total == 1) && (pf == 1)) {
+ *pf_total = 1; //Pass
+ } else {
+ *pf_total = -1; //Fail
+ }
+ }
+ return pf;
+}
+/*!
+ Execute "Onboard Function Test" (NOT includes "START" and "END" command).
+ @retval 1 The test is passed successfully.
+ @retval -1 The test is failed.
+ @retval 0 The test is aborted by kind of system error.
+ */
+int16 FST_AK8963(void)
+{
+ int16 pf_total; //p/f flag for this subtest
+ BYTE i2cData[16];
+ int16 hdata[3];
+ int16 asax;
+ int16 asay;
+ int16 asaz;
+
+ //***********************************************
+ // Reset Test Result
+ //***********************************************
+ pf_total = 1;
+
+ //***********************************************
+ // Step1
+ //***********************************************
+
+ // Reset device.
+ if (AKD_Reset() != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // When the serial interface is SPI,
+ // write "00011011" to I2CDIS register(to disable I2C,).
+ if (CSPEC_SPI_USE == 1) {
+ i2cData[0] = 0x1B;
+ if (AKD_TxData(AK8963_REG_I2CDIS, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+ }
+
+ // Read values from WIA to HZL.
+ if (AKD_RxData(AK8963_REG_WIA, i2cData, 8) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Read values from HZH to ASTC.
+ if (AKD_RxData(AK8963_REG_HZH, &i2cData[8], 5) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_RST_WIA, TLIMIT_TN_RST_WIA, (int16)i2cData[0], TLIMIT_LO_RST_WIA, TLIMIT_HI_RST_WIA, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_INFO, TLIMIT_TN_RST_INFO, (int16)i2cData[1], TLIMIT_LO_RST_INFO, TLIMIT_HI_RST_INFO, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_ST1, TLIMIT_TN_RST_ST1, (int16)i2cData[2], TLIMIT_LO_RST_ST1, TLIMIT_HI_RST_ST1, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HXL, TLIMIT_TN_RST_HXL, (int16)i2cData[3], TLIMIT_LO_RST_HXL, TLIMIT_HI_RST_HXL, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HXH, TLIMIT_TN_RST_HXH, (int16)i2cData[4], TLIMIT_LO_RST_HXH, TLIMIT_HI_RST_HXH, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HYL, TLIMIT_TN_RST_HYL, (int16)i2cData[5], TLIMIT_LO_RST_HYL, TLIMIT_HI_RST_HYL, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HYH, TLIMIT_TN_RST_HYH, (int16)i2cData[6], TLIMIT_LO_RST_HYH, TLIMIT_HI_RST_HYH, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HZL, TLIMIT_TN_RST_HZL, (int16)i2cData[7], TLIMIT_LO_RST_HZL, TLIMIT_HI_RST_HZL, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HZH, TLIMIT_TN_RST_HZH, (int16)i2cData[8], TLIMIT_LO_RST_HZH, TLIMIT_HI_RST_HZH, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_ST2, TLIMIT_TN_RST_ST2, (int16)i2cData[9], TLIMIT_LO_RST_ST2, TLIMIT_HI_RST_ST2, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_CNTL1, TLIMIT_TN_RST_CNTL1, (int16)i2cData[10], TLIMIT_LO_RST_CNTL1, TLIMIT_HI_RST_CNTL1, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_CNTL2, TLIMIT_TN_RST_CNTL2, (int16)i2cData[11], TLIMIT_LO_RST_CNTL2, TLIMIT_HI_RST_CNTL2, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_ASTC, TLIMIT_TN_RST_ASTC, (int16)i2cData[12], TLIMIT_LO_RST_ASTC, TLIMIT_HI_RST_ASTC, &pf_total);
+
+ // Read values from I2CDIS.
+ if (AKD_RxData(AK8963_REG_I2CDIS, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+ if (CSPEC_SPI_USE == 1) {
+ TEST_DATA(TLIMIT_NO_RST_I2CDIS, TLIMIT_TN_RST_I2CDIS, (int16)i2cData[0], TLIMIT_LO_RST_I2CDIS_USESPI, TLIMIT_HI_RST_I2CDIS_USESPI, &pf_total);
+ }else{
+ TEST_DATA(TLIMIT_NO_RST_I2CDIS, TLIMIT_TN_RST_I2CDIS, (int16)i2cData[0], TLIMIT_LO_RST_I2CDIS_USEI2C, TLIMIT_HI_RST_I2CDIS_USEI2C, &pf_total);
+ }
+
+ // Set to FUSE ROM access mode
+ if (AKD_SetMode(AK8963_MODE_FUSE_ACCESS) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Read values from ASAX to ASAZ
+ if (AKD_RxData(AK8963_FUSE_ASAX, i2cData, 3) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+ asax = (int16)i2cData[0];
+ asay = (int16)i2cData[1];
+ asaz = (int16)i2cData[2];
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_ASAX, TLIMIT_TN_ASAX, asax, TLIMIT_LO_ASAX, TLIMIT_HI_ASAX, &pf_total);
+ TEST_DATA(TLIMIT_NO_ASAY, TLIMIT_TN_ASAY, asay, TLIMIT_LO_ASAY, TLIMIT_HI_ASAY, &pf_total);
+ TEST_DATA(TLIMIT_NO_ASAZ, TLIMIT_TN_ASAZ, asaz, TLIMIT_LO_ASAZ, TLIMIT_HI_ASAZ, &pf_total);
+
+ // Read values. CNTL
+ if (AKD_RxData(AK8963_REG_CNTL1, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Set to PowerDown mode
+ if (AKD_SetMode(AK8963_MODE_POWERDOWN) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_WR_CNTL1, TLIMIT_TN_WR_CNTL1, (int16)i2cData[0], TLIMIT_LO_WR_CNTL1, TLIMIT_HI_WR_CNTL1, &pf_total);
+
+ //***********************************************
+ // Step2
+ //***********************************************
+
+ // Set to SNG measurement pattern (Set CNTL register)
+ if (AKD_SetMode(AK8963_MODE_SNG_MEASURE) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Wait for DRDY pin changes to HIGH.
+ //usleep(AKM_MEASURE_TIME_US);
+ // Get measurement data from AK8963
+ // ST1 + (HXL + HXH) + (HYL + HYH) + (HZL + HZH) + ST2
+ // = 1 + (1 + 1) + (1 + 1) + (1 + 1) + 1 = 8 bytes
+ if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ hdata[0] = (int16)((((uint16)(i2cData[2]))<<8)+(uint16)(i2cData[1]));
+ hdata[1] = (int16)((((uint16)(i2cData[4]))<<8)+(uint16)(i2cData[3]));
+ hdata[2] = (int16)((((uint16)(i2cData[6]))<<8)+(uint16)(i2cData[5]));
+
+ if((i2cData[8] & 0x10) == 0){ // 14bit mode //format changed at kernel part as AK09911
+ hdata[0] <<= 2;
+ hdata[1] <<= 2;
+ hdata[2] <<= 2;
+ }
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_SNG_ST1, TLIMIT_TN_SNG_ST1, (int16)i2cData[0], TLIMIT_LO_SNG_ST1, TLIMIT_HI_SNG_ST1, &pf_total);
+ TEST_DATA(TLIMIT_NO_SNG_HX, TLIMIT_TN_SNG_HX, hdata[0], TLIMIT_LO_SNG_HX, TLIMIT_HI_SNG_HX, &pf_total);
+ TEST_DATA(TLIMIT_NO_SNG_HY, TLIMIT_TN_SNG_HY, hdata[1], TLIMIT_LO_SNG_HY, TLIMIT_HI_SNG_HY, &pf_total);
+ TEST_DATA(TLIMIT_NO_SNG_HZ, TLIMIT_TN_SNG_HZ, hdata[2], TLIMIT_LO_SNG_HZ, TLIMIT_HI_SNG_HZ, &pf_total);
+ if((i2cData[8] & 0x10) == 0){ // 14bit mode
+ TEST_DATA(
+ TLIMIT_NO_SNG_ST2,
+ TLIMIT_TN_SNG_ST2,
+ (int16)i2cData[7],
+ TLIMIT_LO_SNG_ST2_14BIT,
+ TLIMIT_HI_SNG_ST2_14BIT,
+ &pf_total
+ );
+ } else { // 16bit mode
+ TEST_DATA(
+ TLIMIT_NO_SNG_ST2,
+ TLIMIT_TN_SNG_ST2,
+ (int16)i2cData[7],
+ TLIMIT_LO_SNG_ST2_16BIT,
+ TLIMIT_HI_SNG_ST2_16BIT,
+ &pf_total
+ );
+ }
+
+ // Generate magnetic field for self-test (Set ASTC register)
+ i2cData[0] = 0x40;
+ if (AKD_TxData(AK8963_REG_ASTC, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Set to Self-test mode (Set CNTL register)
+ if (AKD_SetMode(AK8963_MODE_SELF_TEST) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Wait for DRDY pin changes to HIGH.
+ //usleep(AKM_MEASURE_TIME_US);
+ // Get measurement data from AK8963
+ // ST1 + (HXL + HXH) + (HYL + HYH) + (HZL + HZH) + ST2
+ // = 1 + (1 + 1) + (1 + 1) + (1 + 1) + 1 = 8Byte
+ if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_SLF_ST1, TLIMIT_TN_SLF_ST1, (int16)i2cData[0], TLIMIT_LO_SLF_ST1, TLIMIT_HI_SLF_ST1, &pf_total);
+
+ hdata[0] = (int16)((((uint16)(i2cData[2]))<<8)+(uint16)(i2cData[1]));
+ hdata[1] = (int16)((((uint16)(i2cData[4]))<<8)+(uint16)(i2cData[3]));
+ hdata[2] = (int16)((((uint16)(i2cData[6]))<<8)+(uint16)(i2cData[5]));
+
+ if((i2cData[8] & 0x10) == 0){ // 14bit mode
+ hdata[0] <<= 2;
+ hdata[1] <<= 2;
+ hdata[2] <<= 2;
+ }
+
+ // TEST
+ TEST_DATA(
+ TLIMIT_NO_SLF_RVHX,
+ TLIMIT_TN_SLF_RVHX,
+ (hdata[0])*((asax - 128)*0.5f/128.0f + 1),
+ TLIMIT_LO_SLF_RVHX,
+ TLIMIT_HI_SLF_RVHX,
+ &pf_total
+ );
+
+ TEST_DATA(
+ TLIMIT_NO_SLF_RVHY,
+ TLIMIT_TN_SLF_RVHY,
+ (hdata[1])*((asay - 128)*0.5f/128.0f + 1),
+ TLIMIT_LO_SLF_RVHY,
+ TLIMIT_HI_SLF_RVHY,
+ &pf_total
+ );
+
+ TEST_DATA(
+ TLIMIT_NO_SLF_RVHZ,
+ TLIMIT_TN_SLF_RVHZ,
+ (hdata[2])*((asaz - 128)*0.5f/128.0f + 1),
+ TLIMIT_LO_SLF_RVHZ,
+ TLIMIT_HI_SLF_RVHZ,
+ &pf_total
+ );
+
+ // TEST
+ if((i2cData[8] & 0x10) == 0){ // 14bit mode
+ TEST_DATA(
+ TLIMIT_NO_SLF_ST2,
+ TLIMIT_TN_SLF_ST2,
+ (int16)i2cData[7],
+ TLIMIT_LO_SLF_ST2_14BIT,
+ TLIMIT_HI_SLF_ST2_14BIT,
+ &pf_total
+ );
+ }else{ // 16bit mode
+ TEST_DATA(
+ TLIMIT_NO_SLF_ST2,
+ TLIMIT_TN_SLF_ST2,
+ (int16)i2cData[7],
+ TLIMIT_LO_SLF_ST2_16BIT,
+ TLIMIT_HI_SLF_ST2_16BIT,
+ &pf_total
+ );
+ }
+
+ // Set to Normal mode for self-test.
+ i2cData[0] = 0x00;
+ if (AKD_TxData(AK8963_REG_ASTC, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ return pf_total;
+}
+
+/*!
+ Execute "Onboard Function Test" (NOT includes "START" and "END" command).
+ @retval 1 The test is passed successfully.
+ @retval -1 The test is failed.
+ @retval 0 The test is aborted by kind of system error.
+ */
+int16 FST_AK09911(void)
+{
+ int16 pf_total; //p/f flag for this subtest
+ BYTE i2cData[16];
+ int16 hdata[3];
+ int16 asax;
+ int16 asay;
+ int16 asaz;
+
+ //***********************************************
+ // Reset Test Result
+ //***********************************************
+ pf_total = 1;
+
+ //***********************************************
+ // Step1
+ //***********************************************
+
+ // Reset device.
+ if (AKD_Reset() != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Read values from WIA.
+ if (AKD_RxData(AK09911_REG_WIA1, i2cData, 2) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_RST_WIA1_09911, TLIMIT_TN_RST_WIA1_09911, (int16)i2cData[0], TLIMIT_LO_RST_WIA1_09911, TLIMIT_HI_RST_WIA1_09911, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_WIA2_09911, TLIMIT_TN_RST_WIA2_09911, (int16)i2cData[1], TLIMIT_LO_RST_WIA2_09911, TLIMIT_HI_RST_WIA2_09911, &pf_total);
+
+ // Set to FUSE ROM access mode
+ if (AKD_SetMode(AK09911_MODE_FUSE_ACCESS) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Read values from ASAX to ASAZ
+ if (AKD_RxData(AK09911_FUSE_ASAX, i2cData, 3) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+ asax = (int16)i2cData[0];
+ asay = (int16)i2cData[1];
+ asaz = (int16)i2cData[2];
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_ASAX_09911, TLIMIT_TN_ASAX_09911, asax, TLIMIT_LO_ASAX_09911, TLIMIT_HI_ASAX_09911, &pf_total);
+ TEST_DATA(TLIMIT_NO_ASAY_09911, TLIMIT_TN_ASAY_09911, asay, TLIMIT_LO_ASAY_09911, TLIMIT_HI_ASAY_09911, &pf_total);
+ TEST_DATA(TLIMIT_NO_ASAZ_09911, TLIMIT_TN_ASAZ_09911, asaz, TLIMIT_LO_ASAZ_09911, TLIMIT_HI_ASAZ_09911, &pf_total);
+
+ // Set to PowerDown mode
+ if (AKD_SetMode(AK09911_MODE_POWERDOWN) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ //***********************************************
+ // Step2
+ //***********************************************
+
+ // Set to SNG measurement pattern (Set CNTL register)
+ if (AKD_SetMode(AK09911_MODE_SNG_MEASURE) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Wait for DRDY pin changes to HIGH.
+ //usleep(AKM_MEASURE_TIME_US);
+ // Get measurement data from AK09911
+ // ST1 + (HXL + HXH) + (HYL + HYH) + (HZL + HZH) + TEMP + ST2
+ // = 1 + (1 + 1) + (1 + 1) + (1 + 1) + 1 + 1 = 9yte
+ if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ hdata[0] = (int16)((((uint16)(i2cData[2]))<<8)+(uint16)(i2cData[1]));
+ hdata[1] = (int16)((((uint16)(i2cData[4]))<<8)+(uint16)(i2cData[3]));
+ hdata[2] = (int16)((((uint16)(i2cData[6]))<<8)+(uint16)(i2cData[5]));
+
+ // TEST
+ i2cData[0] &= 0x7F;
+ TEST_DATA(TLIMIT_NO_SNG_ST1_09911, TLIMIT_TN_SNG_ST1_09911, (int16)i2cData[0], TLIMIT_LO_SNG_ST1_09911, TLIMIT_HI_SNG_ST1_09911, &pf_total);
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_SNG_HX_09911, TLIMIT_TN_SNG_HX_09911, hdata[0], TLIMIT_LO_SNG_HX_09911, TLIMIT_HI_SNG_HX_09911, &pf_total);
+ TEST_DATA(TLIMIT_NO_SNG_HY_09911, TLIMIT_TN_SNG_HY_09911, hdata[1], TLIMIT_LO_SNG_HY_09911, TLIMIT_HI_SNG_HY_09911, &pf_total);
+ TEST_DATA(TLIMIT_NO_SNG_HZ_09911, TLIMIT_TN_SNG_HZ_09911, hdata[2], TLIMIT_LO_SNG_HZ_09911, TLIMIT_HI_SNG_HZ_09911, &pf_total);
+ TEST_DATA(TLIMIT_NO_SNG_ST2_09911, TLIMIT_TN_SNG_ST2_09911, (int16)i2cData[8], TLIMIT_LO_SNG_ST2_09911, TLIMIT_HI_SNG_ST2_09911, &pf_total);
+
+ // Set to Self-test mode (Set CNTL register)
+ if (AKD_SetMode(AK09911_MODE_SELF_TEST) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Wait for DRDY pin changes to HIGH.
+ //usleep(AKM_MEASURE_TIME_US);
+ // Get measurement data from AK09911
+ // ST1 + (HXL + HXH) + (HYL + HYH) + (HZL + HZH) + TEMP + ST2
+ // = 1 + (1 + 1) + (1 + 1) + (1 + 1) + 1 + 1 = 9byte
+ if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // TEST
+ i2cData[0] &= 0x7F;
+ TEST_DATA(TLIMIT_NO_SLF_ST1_09911, TLIMIT_TN_SLF_ST1_09911, (int16)i2cData[0], TLIMIT_LO_SLF_ST1_09911, TLIMIT_HI_SLF_ST1_09911, &pf_total);
+
+ hdata[0] = (int16)((((uint16)(i2cData[2]))<<8)+(uint16)(i2cData[1]));
+ hdata[1] = (int16)((((uint16)(i2cData[4]))<<8)+(uint16)(i2cData[3]));
+ hdata[2] = (int16)((((uint16)(i2cData[6]))<<8)+(uint16)(i2cData[5]));
+
+ // TEST
+ TEST_DATA(
+ TLIMIT_NO_SLF_RVHX_09911,
+ TLIMIT_TN_SLF_RVHX_09911,
+ (hdata[0])*(asax/128.0f + 1),
+ TLIMIT_LO_SLF_RVHX_09911,
+ TLIMIT_HI_SLF_RVHX_09911,
+ &pf_total
+ );
+
+ TEST_DATA(
+ TLIMIT_NO_SLF_RVHY_09911,
+ TLIMIT_TN_SLF_RVHY_09911,
+ (hdata[1])*(asay/128.0f + 1),
+ TLIMIT_LO_SLF_RVHY_09911,
+ TLIMIT_HI_SLF_RVHY_09911,
+ &pf_total
+ );
+
+ TEST_DATA(
+ TLIMIT_NO_SLF_RVHZ_09911,
+ TLIMIT_TN_SLF_RVHZ_09911,
+ (hdata[2])*(asaz/128.0f + 1),
+ TLIMIT_LO_SLF_RVHZ_09911,
+ TLIMIT_HI_SLF_RVHZ_09911,
+ &pf_total
+ );
+
+ TEST_DATA(
+ TLIMIT_NO_SLF_ST2_09911,
+ TLIMIT_TN_SLF_ST2_09911,
+ (int16)i2cData[8],
+ TLIMIT_LO_SLF_ST2_09911,
+ TLIMIT_HI_SLF_ST2_09911,
+ &pf_total
+ );
+
+ return pf_total;
+}
+
+/*!
+ Execute "Onboard Function Test" (includes "START" and "END" command).
+ @retval 1 The test is passed successfully.
+ @retval -1 The test is failed.
+ @retval 0 The test is aborted by kind of system error.
+ */
+int16 FST_Body(AKSCPRMS* prms)
+{
+ int16 pf_total = 1;
+
+ //***********************************************
+ // Reset Test Result
+ //***********************************************
+ TEST_DATA(NULL, "START", 0, 0, 0, &pf_total);
+
+ //***********************************************
+ // Step 1 to 2
+ //***********************************************
+ if(prms->akm_device==0)
+ pf_total = FST_AK8963();
+ else
+ pf_total = FST_AK09911();
+
+ //***********************************************
+ // Judge Test Result
+ //***********************************************
+ TEST_DATA(NULL, "END", 0, 0, 0, &pf_total);
+
+ return pf_total;
+}
+
diff --git a/mpu/akm8963/FST_AK8963.c b/mpu/akm8963/FST_AK8963.c
new file mode 100755
index 0000000..9dcaee1
--- /dev/null
+++ b/mpu/akm8963/FST_AK8963.c
@@ -0,0 +1,510 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#include "AKCommon.h"
+#include "AKMD_Driver.h"
+#include "FST.h"
+#include "misc.h"
+
+#ifndef AKMD_FOR_AK8963
+#error "AKMD parameter is not set"
+#endif
+
+#define TLIMIT_TN_REVISION ""
+#define TLIMIT_NO_RST_WIA "1-3"
+#define TLIMIT_TN_RST_WIA "RST_WIA"
+#define TLIMIT_LO_RST_WIA 0x48
+#define TLIMIT_HI_RST_WIA 0x48
+#define TLIMIT_NO_RST_INFO "1-4"
+#define TLIMIT_TN_RST_INFO "RST_INFO"
+#define TLIMIT_LO_RST_INFO 0
+#define TLIMIT_HI_RST_INFO 255
+#define TLIMIT_NO_RST_ST1 "1-5"
+#define TLIMIT_TN_RST_ST1 "RST_ST1"
+#define TLIMIT_LO_RST_ST1 0
+#define TLIMIT_HI_RST_ST1 0
+#define TLIMIT_NO_RST_HXL "1-6"
+#define TLIMIT_TN_RST_HXL "RST_HXL"
+#define TLIMIT_LO_RST_HXL 0
+#define TLIMIT_HI_RST_HXL 0
+#define TLIMIT_NO_RST_HXH "1-7"
+#define TLIMIT_TN_RST_HXH "RST_HXH"
+#define TLIMIT_LO_RST_HXH 0
+#define TLIMIT_HI_RST_HXH 0
+#define TLIMIT_NO_RST_HYL "1-8"
+#define TLIMIT_TN_RST_HYL "RST_HYL"
+#define TLIMIT_LO_RST_HYL 0
+#define TLIMIT_HI_RST_HYL 0
+#define TLIMIT_NO_RST_HYH "1-9"
+#define TLIMIT_TN_RST_HYH "RST_HYH"
+#define TLIMIT_LO_RST_HYH 0
+#define TLIMIT_HI_RST_HYH 0
+#define TLIMIT_NO_RST_HZL "1-10"
+#define TLIMIT_TN_RST_HZL "RST_HZL"
+#define TLIMIT_LO_RST_HZL 0
+#define TLIMIT_HI_RST_HZL 0
+#define TLIMIT_NO_RST_HZH "1-11"
+#define TLIMIT_TN_RST_HZH "RST_HZH"
+#define TLIMIT_LO_RST_HZH 0
+#define TLIMIT_HI_RST_HZH 0
+#define TLIMIT_NO_RST_ST2 "1-12"
+#define TLIMIT_TN_RST_ST2 "RST_ST2"
+#define TLIMIT_LO_RST_ST2 0
+#define TLIMIT_HI_RST_ST2 0
+#define TLIMIT_NO_RST_CNTL1 "1-13"
+#define TLIMIT_TN_RST_CNTL1 "RST_CNTL1"
+#define TLIMIT_LO_RST_CNTL1 0
+#define TLIMIT_HI_RST_CNTL1 0
+#define TLIMIT_NO_RST_CNTL2 "1-14"
+#define TLIMIT_TN_RST_CNTL2 "RST_CNTL2"
+#define TLIMIT_LO_RST_CNTL2 0
+#define TLIMIT_HI_RST_CNTL2 0
+
+#define TLIMIT_NO_RST_ASTC "1-15"
+#define TLIMIT_TN_RST_ASTC "RST_ASTC"
+#define TLIMIT_LO_RST_ASTC 0
+#define TLIMIT_HI_RST_ASTC 0
+#define TLIMIT_NO_RST_I2CDIS "1-16"
+#define TLIMIT_TN_RST_I2CDIS "RST_I2CDIS"
+#define TLIMIT_LO_RST_I2CDIS_USEI2C 0
+#define TLIMIT_HI_RST_I2CDIS_USEI2C 0
+#define TLIMIT_LO_RST_I2CDIS_USESPI 1
+#define TLIMIT_HI_RST_I2CDIS_USESPI 1
+#define TLIMIT_NO_ASAX "1-18"
+#define TLIMIT_TN_ASAX "ASAX"
+#define TLIMIT_LO_ASAX 1
+#define TLIMIT_HI_ASAX 254
+#define TLIMIT_NO_ASAY "1-19"
+#define TLIMIT_TN_ASAY "ASAY"
+#define TLIMIT_LO_ASAY 1
+#define TLIMIT_HI_ASAY 254
+#define TLIMIT_NO_ASAZ "1-20"
+#define TLIMIT_TN_ASAZ "ASAZ"
+#define TLIMIT_LO_ASAZ 1
+#define TLIMIT_HI_ASAZ 254
+#define TLIMIT_NO_WR_CNTL1 "1-21"
+#define TLIMIT_TN_WR_CNTL1 "WR_CNTL1"
+#define TLIMIT_LO_WR_CNTL1 0x0F
+#define TLIMIT_HI_WR_CNTL1 0x0F
+
+#define TLIMIT_NO_SNG_ST1 "2-3"
+#define TLIMIT_TN_SNG_ST1 "SNG_ST1"
+#define TLIMIT_LO_SNG_ST1 1
+#define TLIMIT_HI_SNG_ST1 1
+
+#define TLIMIT_NO_SNG_HX "2-4"
+#define TLIMIT_TN_SNG_HX "SNG_HX"
+#define TLIMIT_LO_SNG_HX -32759
+#define TLIMIT_HI_SNG_HX 32759
+
+#define TLIMIT_NO_SNG_HY "2-6"
+#define TLIMIT_TN_SNG_HY "SNG_HY"
+#define TLIMIT_LO_SNG_HY -32759
+#define TLIMIT_HI_SNG_HY 32759
+
+#define TLIMIT_NO_SNG_HZ "2-8"
+#define TLIMIT_TN_SNG_HZ "SNG_HZ"
+#define TLIMIT_LO_SNG_HZ -32759
+#define TLIMIT_HI_SNG_HZ 32759
+
+#define TLIMIT_NO_SNG_ST2 "2-10"
+#define TLIMIT_TN_SNG_ST2 "SNG_ST2"
+#define TLIMIT_LO_SNG_ST2_14BIT 0
+#define TLIMIT_HI_SNG_ST2_14BIT 0
+#define TLIMIT_LO_SNG_ST2_16BIT 16
+#define TLIMIT_HI_SNG_ST2_16BIT 16
+
+#define TLIMIT_NO_SLF_ST1 "2-14"
+#define TLIMIT_TN_SLF_ST1 "SLF_ST1"
+#define TLIMIT_LO_SLF_ST1 1
+#define TLIMIT_HI_SLF_ST1 1
+
+#define TLIMIT_NO_SLF_RVHX "2-15"
+#define TLIMIT_TN_SLF_RVHX "SLF_REVSHX"
+#define TLIMIT_LO_SLF_RVHX -200
+#define TLIMIT_HI_SLF_RVHX 200
+
+#define TLIMIT_NO_SLF_RVHY "2-17"
+#define TLIMIT_TN_SLF_RVHY "SLF_REVSHY"
+#define TLIMIT_LO_SLF_RVHY -200
+#define TLIMIT_HI_SLF_RVHY 200
+
+#define TLIMIT_NO_SLF_RVHZ "2-19"
+#define TLIMIT_TN_SLF_RVHZ "SLF_REVSHZ"
+#define TLIMIT_LO_SLF_RVHZ -3200
+#define TLIMIT_HI_SLF_RVHZ -800
+
+#define TLIMIT_NO_SLF_ST2 "2-21"
+#define TLIMIT_TN_SLF_ST2 "SLF_ST2"
+#define TLIMIT_LO_SLF_ST2_14BIT 0
+#define TLIMIT_HI_SLF_ST2_14BIT 0
+#define TLIMIT_LO_SLF_ST2_16BIT 16
+#define TLIMIT_HI_SLF_ST2_16BIT 16
+
+/*!
+ @return If @a testdata is in the range of between @a lolimit and @a hilimit,
+ the return value is 1, otherwise -1.
+ @param[in] testno A pointer to a text string.
+ @param[in] testname A pointer to a text string.
+ @param[in] testdata A data to be tested.
+ @param[in] lolimit The maximum allowable value of @a testdata.
+ @param[in] hilimit The minimum allowable value of @a testdata.
+ @param[in,out] pf_total
+ */
+int16
+TEST_DATA(const char testno[],
+ const char testname[],
+ const int16 testdata,
+ const int16 lolimit,
+ const int16 hilimit,
+ int16 * pf_total)
+{
+ int16 pf; //Pass;1, Fail;-1
+
+ if ((testno == NULL) && (strncmp(testname, "START", 5) == 0)) {
+ // Display header
+ AKMDEBUG(AKMDBG_DISP1, "--------------------------------------------------------------------\n");
+ AKMDEBUG(AKMDBG_DISP1, " Test No. Test Name Fail Test Data [ Low High]\n");
+ AKMDEBUG(AKMDBG_DISP1, "--------------------------------------------------------------------\n");
+
+ pf = 1;
+ } else if ((testno == NULL) && (strncmp(testname, "END", 3) == 0)) {
+ // Display result
+ AKMDEBUG(AKMDBG_DISP1, "--------------------------------------------------------------------\n");
+ if (*pf_total == 1) {
+ AKMDEBUG(AKMDBG_DISP1, "Factory shipment test was passed.\n\n");
+ } else {
+ AKMDEBUG(AKMDBG_DISP1, "Factory shipment test was failed.\n\n");
+ }
+
+ pf = 1;
+ } else {
+ if ((lolimit <= testdata) && (testdata <= hilimit)) {
+ //Pass
+ pf = 1;
+ } else {
+ //Fail
+ pf = -1;
+ }
+
+ //display result
+ AKMDEBUG(AKMDBG_DISP1, " %7s %-10s %c %9d [%9d %9d]\n",
+ testno, testname, ((pf == 1) ? ('.') : ('F')), testdata,
+ lolimit, hilimit);
+ }
+
+ //Pass/Fail check
+ if (*pf_total != 0) {
+ if ((*pf_total == 1) && (pf == 1)) {
+ *pf_total = 1; //Pass
+ } else {
+ *pf_total = -1; //Fail
+ }
+ }
+ return pf;
+}
+
+/*!
+ Execute "Onboard Function Test" (NOT includes "START" and "END" command).
+ @retval 1 The test is passed successfully.
+ @retval -1 The test is failed.
+ @retval 0 The test is aborted by kind of system error.
+ */
+int16 FST_AK8963(void)
+{
+ int16 pf_total; //p/f flag for this subtest
+ BYTE i2cData[16];
+ int16 hdata[3];
+ int16 asax;
+ int16 asay;
+ int16 asaz;
+
+ //***********************************************
+ // Reset Test Result
+ //***********************************************
+ pf_total = 1;
+
+ //***********************************************
+ // Step1
+ //***********************************************
+
+ // Reset device.
+ if (AKD_Reset() != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // When the serial interface is SPI,
+ // write "00011011" to I2CDIS register(to disable I2C,).
+ if (CSPEC_SPI_USE == 1) {
+ i2cData[0] = 0x1B;
+ if (AKD_TxData(AK8963_REG_I2CDIS, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+ }
+
+ // Read values from WIA to ASTC.
+ if (AKD_RxData(AK8963_REG_WIA, i2cData, 13) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_RST_WIA, TLIMIT_TN_RST_WIA, (int16)i2cData[0], TLIMIT_LO_RST_WIA, TLIMIT_HI_RST_WIA, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_INFO, TLIMIT_TN_RST_INFO, (int16)i2cData[1], TLIMIT_LO_RST_INFO, TLIMIT_HI_RST_INFO, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_ST1, TLIMIT_TN_RST_ST1, (int16)i2cData[2], TLIMIT_LO_RST_ST1, TLIMIT_HI_RST_ST1, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HXL, TLIMIT_TN_RST_HXL, (int16)i2cData[3], TLIMIT_LO_RST_HXL, TLIMIT_HI_RST_HXL, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HXH, TLIMIT_TN_RST_HXH, (int16)i2cData[4], TLIMIT_LO_RST_HXH, TLIMIT_HI_RST_HXH, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HYL, TLIMIT_TN_RST_HYL, (int16)i2cData[5], TLIMIT_LO_RST_HYL, TLIMIT_HI_RST_HYL, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HYH, TLIMIT_TN_RST_HYH, (int16)i2cData[6], TLIMIT_LO_RST_HYH, TLIMIT_HI_RST_HYH, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HZL, TLIMIT_TN_RST_HZL, (int16)i2cData[7], TLIMIT_LO_RST_HZL, TLIMIT_HI_RST_HZL, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HZH, TLIMIT_TN_RST_HZH, (int16)i2cData[8], TLIMIT_LO_RST_HZH, TLIMIT_HI_RST_HZH, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_ST2, TLIMIT_TN_RST_ST2, (int16)i2cData[9], TLIMIT_LO_RST_ST2, TLIMIT_HI_RST_ST2, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_CNTL1, TLIMIT_TN_RST_CNTL1, (int16)i2cData[10], TLIMIT_LO_RST_CNTL1, TLIMIT_HI_RST_CNTL1, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_CNTL2, TLIMIT_TN_RST_CNTL2, (int16)i2cData[11], TLIMIT_LO_RST_CNTL2, TLIMIT_HI_RST_CNTL2, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_ASTC, TLIMIT_TN_RST_ASTC, (int16)i2cData[12], TLIMIT_LO_RST_ASTC, TLIMIT_HI_RST_ASTC, &pf_total);
+
+ // Read values from I2CDIS.
+ if (AKD_RxData(AK8963_REG_I2CDIS, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+ if (CSPEC_SPI_USE == 1) {
+ TEST_DATA(TLIMIT_NO_RST_I2CDIS, TLIMIT_TN_RST_I2CDIS, (int16)i2cData[0], TLIMIT_LO_RST_I2CDIS_USESPI, TLIMIT_HI_RST_I2CDIS_USESPI, &pf_total);
+ }else{
+ TEST_DATA(TLIMIT_NO_RST_I2CDIS, TLIMIT_TN_RST_I2CDIS, (int16)i2cData[0], TLIMIT_LO_RST_I2CDIS_USEI2C, TLIMIT_HI_RST_I2CDIS_USEI2C, &pf_total);
+ }
+
+ // Set to FUSE ROM access mode
+ if (AKD_SetMode(AK8963_MODE_FUSE_ACCESS) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Read values from ASAX to ASAZ
+ if (AKD_RxData(AK8963_FUSE_ASAX, i2cData, 3) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+ asax = (int16)i2cData[0];
+ asay = (int16)i2cData[1];
+ asaz = (int16)i2cData[2];
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_ASAX, TLIMIT_TN_ASAX, asax, TLIMIT_LO_ASAX, TLIMIT_HI_ASAX, &pf_total);
+ TEST_DATA(TLIMIT_NO_ASAY, TLIMIT_TN_ASAY, asay, TLIMIT_LO_ASAY, TLIMIT_HI_ASAY, &pf_total);
+ TEST_DATA(TLIMIT_NO_ASAZ, TLIMIT_TN_ASAZ, asaz, TLIMIT_LO_ASAZ, TLIMIT_HI_ASAZ, &pf_total);
+
+ // Read values. CNTL
+ if (AKD_RxData(AK8963_REG_CNTL1, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Set to PowerDown mode
+ if (AKD_SetMode(AK8963_MODE_POWERDOWN) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_WR_CNTL1, TLIMIT_TN_WR_CNTL1, (int16)i2cData[0], TLIMIT_LO_WR_CNTL1, TLIMIT_HI_WR_CNTL1, &pf_total);
+
+ //***********************************************
+ // Step2
+ //***********************************************
+
+ // Set to SNG measurement pattern (Set CNTL register)
+ if (AKD_SetMode(AK8963_MODE_SNG_MEASURE) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Wait for DRDY pin changes to HIGH.
+ //usleep(AKM_MEASURE_TIME_US);
+ // Get measurement data from AK8963
+ // ST1 + (HXL + HXH) + (HYL + HYH) + (HZL + HZH) + ST2
+ // = 1 + (1 + 1) + (1 + 1) + (1 + 1) + 1 = 8 bytes
+ if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ hdata[0] = (int16)((((uint16)(i2cData[2]))<<8)+(uint16)(i2cData[1]));
+ hdata[1] = (int16)((((uint16)(i2cData[4]))<<8)+(uint16)(i2cData[3]));
+ hdata[2] = (int16)((((uint16)(i2cData[6]))<<8)+(uint16)(i2cData[5]));
+
+ if((i2cData[7] & 0x10) == 0){ // 14bit mode
+ hdata[0] <<= 2;
+ hdata[1] <<= 2;
+ hdata[2] <<= 2;
+ }
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_SNG_ST1, TLIMIT_TN_SNG_ST1, (int16)i2cData[0], TLIMIT_LO_SNG_ST1, TLIMIT_HI_SNG_ST1, &pf_total);
+ TEST_DATA(TLIMIT_NO_SNG_HX, TLIMIT_TN_SNG_HX, hdata[0], TLIMIT_LO_SNG_HX, TLIMIT_HI_SNG_HX, &pf_total);
+ TEST_DATA(TLIMIT_NO_SNG_HY, TLIMIT_TN_SNG_HY, hdata[1], TLIMIT_LO_SNG_HY, TLIMIT_HI_SNG_HY, &pf_total);
+ TEST_DATA(TLIMIT_NO_SNG_HZ, TLIMIT_TN_SNG_HZ, hdata[2], TLIMIT_LO_SNG_HZ, TLIMIT_HI_SNG_HZ, &pf_total);
+ if((i2cData[7] & 0x10) == 0){ // 14bit mode
+ TEST_DATA(
+ TLIMIT_NO_SNG_ST2,
+ TLIMIT_TN_SNG_ST2,
+ (int16)i2cData[7],
+ TLIMIT_LO_SNG_ST2_14BIT,
+ TLIMIT_HI_SNG_ST2_14BIT,
+ &pf_total
+ );
+ } else { // 16bit mode
+ TEST_DATA(
+ TLIMIT_NO_SNG_ST2,
+ TLIMIT_TN_SNG_ST2,
+ (int16)i2cData[7],
+ TLIMIT_LO_SNG_ST2_16BIT,
+ TLIMIT_HI_SNG_ST2_16BIT,
+ &pf_total
+ );
+ }
+
+ // Generate magnetic field for self-test (Set ASTC register)
+ i2cData[0] = 0x40;
+ if (AKD_TxData(AK8963_REG_ASTC, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Set to Self-test mode (Set CNTL register)
+ if (AKD_SetMode(AK8963_MODE_SELF_TEST) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Wait for DRDY pin changes to HIGH.
+ //usleep(AKM_MEASURE_TIME_US);
+ // Get measurement data from AK8963
+ // ST1 + (HXL + HXH) + (HYL + HYH) + (HZL + HZH) + ST2
+ // = 1 + (1 + 1) + (1 + 1) + (1 + 1) + 1 = 8Byte
+ if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_SLF_ST1, TLIMIT_TN_SLF_ST1, (int16)i2cData[0], TLIMIT_LO_SLF_ST1, TLIMIT_HI_SLF_ST1, &pf_total);
+
+ hdata[0] = (int16)((((uint16)(i2cData[2]))<<8)+(uint16)(i2cData[1]));
+ hdata[1] = (int16)((((uint16)(i2cData[4]))<<8)+(uint16)(i2cData[3]));
+ hdata[2] = (int16)((((uint16)(i2cData[6]))<<8)+(uint16)(i2cData[5]));
+
+ if((i2cData[7] & 0x10) == 0){ // 14bit mode
+ hdata[0] <<= 2;
+ hdata[1] <<= 2;
+ hdata[2] <<= 2;
+ }
+
+ // TEST
+ TEST_DATA(
+ TLIMIT_NO_SLF_RVHX,
+ TLIMIT_TN_SLF_RVHX,
+ (hdata[0])*((asax - 128)*0.5f/128.0f + 1),
+ TLIMIT_LO_SLF_RVHX,
+ TLIMIT_HI_SLF_RVHX,
+ &pf_total
+ );
+
+ TEST_DATA(
+ TLIMIT_NO_SLF_RVHY,
+ TLIMIT_TN_SLF_RVHY,
+ (hdata[1])*((asay - 128)*0.5f/128.0f + 1),
+ TLIMIT_LO_SLF_RVHY,
+ TLIMIT_HI_SLF_RVHY,
+ &pf_total
+ );
+
+ TEST_DATA(
+ TLIMIT_NO_SLF_RVHZ,
+ TLIMIT_TN_SLF_RVHZ,
+ (hdata[2])*((asaz - 128)*0.5f/128.0f + 1),
+ TLIMIT_LO_SLF_RVHZ,
+ TLIMIT_HI_SLF_RVHZ,
+ &pf_total
+ );
+
+ // TEST
+ if((i2cData[7] & 0x10) == 0){ // 14bit mode
+ TEST_DATA(
+ TLIMIT_NO_SLF_ST2,
+ TLIMIT_TN_SLF_ST2,
+ (int16)i2cData[7],
+ TLIMIT_LO_SLF_ST2_14BIT,
+ TLIMIT_HI_SLF_ST2_14BIT,
+ &pf_total
+ );
+ }else{ // 16bit mode
+ TEST_DATA(
+ TLIMIT_NO_SLF_ST2,
+ TLIMIT_TN_SLF_ST2,
+ (int16)i2cData[7],
+ TLIMIT_LO_SLF_ST2_16BIT,
+ TLIMIT_HI_SLF_ST2_16BIT,
+ &pf_total
+ );
+ }
+
+ // Set to Normal mode for self-test.
+ i2cData[0] = 0x00;
+ if (AKD_TxData(AK8963_REG_ASTC, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ return pf_total;
+}
+
+/*!
+ Execute "Onboard Function Test" (includes "START" and "END" command).
+ @retval 1 The test is passed successfully.
+ @retval -1 The test is failed.
+ @retval 0 The test is aborted by kind of system error.
+ */
+int16 FST_Body(AKSCPRMS* prms)
+{
+ int16 pf_total = 1;
+
+ //***********************************************
+ // Reset Test Result
+ //***********************************************
+ TEST_DATA(NULL, "START", 0, 0, 0, &pf_total);
+
+ //***********************************************
+ // Step 1 to 2
+ //***********************************************
+ pf_total = FST_AK8963();
+ //***********************************************
+ // Judge Test Result
+ //***********************************************
+ TEST_DATA(NULL, "END", 0, 0, 0, &pf_total);
+
+ return pf_total;
+}
+
diff --git a/mpu/akm8963/FST_AK8975.c b/mpu/akm8963/FST_AK8975.c
new file mode 100755
index 0000000..ed9f0aa
--- /dev/null
+++ b/mpu/akm8963/FST_AK8975.c
@@ -0,0 +1,454 @@
+/******************************************************************************
+ *
+ * $Id: FST_AK8975.c 878 2012-11-30 07:57:24Z yamada.rj $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#include "AKCommon.h"
+#include "AKMD_Driver.h"
+#include "FST.h"
+#include "misc.h"
+
+#ifndef AKMD_FOR_AK8975
+#error "AKMD parameter is not set"
+#endif
+
+#define TLIMIT_TN_REVISION ""
+#define TLIMIT_NO_RST_WIA "1-3"
+#define TLIMIT_TN_RST_WIA "RST_WIA"
+#define TLIMIT_LO_RST_WIA 0x48
+#define TLIMIT_HI_RST_WIA 0x48
+#define TLIMIT_NO_RST_INFO "1-4"
+#define TLIMIT_TN_RST_INFO "RST_INFO"
+#define TLIMIT_LO_RST_INFO 0
+#define TLIMIT_HI_RST_INFO 255
+#define TLIMIT_NO_RST_ST1 "1-5"
+#define TLIMIT_TN_RST_ST1 "RST_ST1"
+#define TLIMIT_LO_RST_ST1 0
+#define TLIMIT_HI_RST_ST1 0
+#define TLIMIT_NO_RST_HXL "1-6"
+#define TLIMIT_TN_RST_HXL "RST_HXL"
+#define TLIMIT_LO_RST_HXL 0
+#define TLIMIT_HI_RST_HXL 0
+#define TLIMIT_NO_RST_HXH "1-7"
+#define TLIMIT_TN_RST_HXH "RST_HXH"
+#define TLIMIT_LO_RST_HXH 0
+#define TLIMIT_HI_RST_HXH 0
+#define TLIMIT_NO_RST_HYL "1-8"
+#define TLIMIT_TN_RST_HYL "RST_HYL"
+#define TLIMIT_LO_RST_HYL 0
+#define TLIMIT_HI_RST_HYL 0
+#define TLIMIT_NO_RST_HYH "1-9"
+#define TLIMIT_TN_RST_HYH "RST_HYH"
+#define TLIMIT_LO_RST_HYH 0
+#define TLIMIT_HI_RST_HYH 0
+#define TLIMIT_NO_RST_HZL "1-10"
+#define TLIMIT_TN_RST_HZL "RST_HZL"
+#define TLIMIT_LO_RST_HZL 0
+#define TLIMIT_HI_RST_HZL 0
+#define TLIMIT_NO_RST_HZH "1-11"
+#define TLIMIT_TN_RST_HZH "RST_HZH"
+#define TLIMIT_LO_RST_HZH 0
+#define TLIMIT_HI_RST_HZH 0
+#define TLIMIT_NO_RST_ST2 "1-12"
+#define TLIMIT_TN_RST_ST2 "RST_ST2"
+#define TLIMIT_LO_RST_ST2 0
+#define TLIMIT_HI_RST_ST2 0
+#define TLIMIT_NO_RST_CNTL "1-13"
+#define TLIMIT_TN_RST_CNTL "RST_CNTL"
+#define TLIMIT_LO_RST_CNTL 0
+#define TLIMIT_HI_RST_CNTL 0
+#define TLIMIT_NO_RST_ASTC "1-14"
+#define TLIMIT_TN_RST_ASTC "RST_ASTC"
+#define TLIMIT_LO_RST_ASTC 0
+#define TLIMIT_HI_RST_ASTC 0
+#define TLIMIT_NO_RST_I2CDIS "1-15"
+#define TLIMIT_TN_RST_I2CDIS "RST_I2CDIS"
+#define TLIMIT_LO_RST_I2CDIS_USEI2C 0
+#define TLIMIT_HI_RST_I2CDIS_USEI2C 0
+#define TLIMIT_LO_RST_I2CDIS_USESPI 1
+#define TLIMIT_HI_RST_I2CDIS_USESPI 1
+#define TLIMIT_NO_ASAX "1-17"
+#define TLIMIT_TN_ASAX "ASAX"
+#define TLIMIT_LO_ASAX 1
+#define TLIMIT_HI_ASAX 254
+#define TLIMIT_NO_ASAY "1-18"
+#define TLIMIT_TN_ASAY "ASAY"
+#define TLIMIT_LO_ASAY 1
+#define TLIMIT_HI_ASAY 254
+#define TLIMIT_NO_ASAZ "1-19"
+#define TLIMIT_TN_ASAZ "ASAZ"
+#define TLIMIT_LO_ASAZ 1
+#define TLIMIT_HI_ASAZ 254
+#define TLIMIT_NO_WR_CNTL "1-20"
+#define TLIMIT_TN_WR_CNTL "WR_CNTL"
+#define TLIMIT_LO_WR_CNTL 0x0F
+#define TLIMIT_HI_WR_CNTL 0x0F
+
+#define TLIMIT_NO_SNG_ST1 "2-3"
+#define TLIMIT_TN_SNG_ST1 "SNG_ST1"
+#define TLIMIT_LO_SNG_ST1 1
+#define TLIMIT_HI_SNG_ST1 1
+
+#define TLIMIT_NO_SNG_HX "2-4"
+#define TLIMIT_TN_SNG_HX "SNG_HX"
+#define TLIMIT_LO_SNG_HX -4095
+#define TLIMIT_HI_SNG_HX 4094
+
+#define TLIMIT_NO_SNG_HY "2-6"
+#define TLIMIT_TN_SNG_HY "SNG_HY"
+#define TLIMIT_LO_SNG_HY -4095
+#define TLIMIT_HI_SNG_HY 4094
+
+#define TLIMIT_NO_SNG_HZ "2-8"
+#define TLIMIT_TN_SNG_HZ "SNG_HZ"
+#define TLIMIT_LO_SNG_HZ -4095
+#define TLIMIT_HI_SNG_HZ 4094
+
+#define TLIMIT_NO_SNG_ST2 "2-10"
+#define TLIMIT_TN_SNG_ST2 "SNG_ST2"
+#define TLIMIT_LO_SNG_ST2 0
+#define TLIMIT_HI_SNG_ST2 0
+
+#define TLIMIT_NO_SLF_ST1 "2-14"
+#define TLIMIT_TN_SLF_ST1 "SLF_ST1"
+#define TLIMIT_LO_SLF_ST1 1
+#define TLIMIT_HI_SLF_ST1 1
+
+#define TLIMIT_NO_SLF_RVHX "2-15"
+#define TLIMIT_TN_SLF_RVHX "SLF_REVSHX"
+#define TLIMIT_LO_SLF_RVHX -100
+#define TLIMIT_HI_SLF_RVHX 100
+
+#define TLIMIT_NO_SLF_RVHY "2-17"
+#define TLIMIT_TN_SLF_RVHY "SLF_REVSHY"
+#define TLIMIT_LO_SLF_RVHY -100
+#define TLIMIT_HI_SLF_RVHY 100
+
+#define TLIMIT_NO_SLF_RVHZ "2-19"
+#define TLIMIT_TN_SLF_RVHZ "SLF_REVSHZ"
+#define TLIMIT_LO_SLF_RVHZ -1000
+#define TLIMIT_HI_SLF_RVHZ -300
+
+#define TLIMIT_NO_SLF_ST2 "2-21"
+#define TLIMIT_TN_SLF_ST2 "SLF_ST2"
+#define TLIMIT_LO_SLF_ST2 0
+#define TLIMIT_HI_SLF_ST2 0
+
+/*!
+ @return If @a testdata is in the range of between @a lolimit and @a hilimit,
+ the return value is 1, otherwise -1.
+ @param[in] testno A pointer to a text string.
+ @param[in] testname A pointer to a text string.
+ @param[in] testdata A data to be tested.
+ @param[in] lolimit The maximum allowable value of @a testdata.
+ @param[in] hilimit The minimum allowable value of @a testdata.
+ @param[in,out] pf_total
+ */
+int16
+TEST_DATA(const char testno[],
+ const char testname[],
+ const int16 testdata,
+ const int16 lolimit,
+ const int16 hilimit,
+ int16 * pf_total)
+{
+ int16 pf; //Pass;1, Fail;-1
+
+ if ((testno == NULL) && (strncmp(testname, "START", 5) == 0)) {
+ // Display header
+ AKMDEBUG(AKMDBG_DISP1, "--------------------------------------------------------------------\n");
+ AKMDEBUG(AKMDBG_DISP1, " Test No. Test Name Fail Test Data [ Low High]\n");
+ AKMDEBUG(AKMDBG_DISP1, "--------------------------------------------------------------------\n");
+
+ pf = 1;
+ } else if ((testno == NULL) && (strncmp(testname, "END", 3) == 0)) {
+ // Display result
+ AKMDEBUG(AKMDBG_DISP1, "--------------------------------------------------------------------\n");
+ if (*pf_total == 1) {
+ AKMDEBUG(AKMDBG_DISP1, "Factory shipment test was passed.\n\n");
+ } else {
+ AKMDEBUG(AKMDBG_DISP1, "Factory shipment test was failed.\n\n");
+ }
+
+ pf = 1;
+ } else {
+ if ((lolimit <= testdata) && (testdata <= hilimit)) {
+ //Pass
+ pf = 1;
+ } else {
+ //Fail
+ pf = -1;
+ }
+
+ //display result
+ AKMDEBUG(AKMDBG_DISP1, " %7s %-10s %c %9d [%9d %9d]\n",
+ testno, testname, ((pf == 1) ? ('.') : ('F')), testdata,
+ lolimit, hilimit);
+ }
+
+ //Pass/Fail check
+ if (*pf_total != 0) {
+ if ((*pf_total == 1) && (pf == 1)) {
+ *pf_total = 1; //Pass
+ } else {
+ *pf_total = -1; //Fail
+ }
+ }
+ return pf;
+}
+
+/*!
+ Execute "Onboard Function Test" (NOT includes "START" and "END" command).
+ @retval 1 The test is passed successfully.
+ @retval -1 The test is failed.
+ @retval 0 The test is aborted by kind of system error.
+ */
+int16 FST_AK8975(void)
+{
+ int16 pf_total; //p/f flag for this subtest
+ BYTE i2cData[16];
+ int16 hdata[3];
+ int16 asax;
+ int16 asay;
+ int16 asaz;
+
+ //***********************************************
+ // Reset Test Result
+ //***********************************************
+ pf_total = 1;
+
+ //***********************************************
+ // Step1
+ //***********************************************
+
+ // Set to PowerDown mode
+ if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // When the serial interface is SPI,
+ // write "00011011" to I2CDIS register(to disable I2C,).
+ if (CSPEC_SPI_USE == 1) {
+ i2cData[0] = 0x1B;
+ if (AKD_TxData(AK8975_REG_I2CDIS, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+ }
+
+ // Read values from WIA to ASTC.
+ if (AKD_RxData(AK8975_REG_WIA, i2cData, 13) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_RST_WIA, TLIMIT_TN_RST_WIA, (int16)i2cData[0], TLIMIT_LO_RST_WIA, TLIMIT_HI_RST_WIA, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_INFO, TLIMIT_TN_RST_INFO, (int16)i2cData[1], TLIMIT_LO_RST_INFO, TLIMIT_HI_RST_INFO, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_ST1, TLIMIT_TN_RST_ST1, (int16)i2cData[2], TLIMIT_LO_RST_ST1, TLIMIT_HI_RST_ST1, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HXL, TLIMIT_TN_RST_HXL, (int16)i2cData[3], TLIMIT_LO_RST_HXL, TLIMIT_HI_RST_HXL, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HXH, TLIMIT_TN_RST_HXH, (int16)i2cData[4], TLIMIT_LO_RST_HXH, TLIMIT_HI_RST_HXH, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HYL, TLIMIT_TN_RST_HYL, (int16)i2cData[5], TLIMIT_LO_RST_HYL, TLIMIT_HI_RST_HYL, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HYH, TLIMIT_TN_RST_HYH, (int16)i2cData[6], TLIMIT_LO_RST_HYH, TLIMIT_HI_RST_HYH, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HZL, TLIMIT_TN_RST_HZL, (int16)i2cData[7], TLIMIT_LO_RST_HZL, TLIMIT_HI_RST_HZL, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_HZH, TLIMIT_TN_RST_HZH, (int16)i2cData[8], TLIMIT_LO_RST_HZH, TLIMIT_HI_RST_HZH, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_ST2, TLIMIT_TN_RST_ST2, (int16)i2cData[9], TLIMIT_LO_RST_ST2, TLIMIT_HI_RST_ST2, &pf_total);
+ TEST_DATA(TLIMIT_NO_RST_CNTL, TLIMIT_TN_RST_CNTL, (int16)i2cData[10], TLIMIT_LO_RST_CNTL, TLIMIT_HI_RST_CNTL, &pf_total);
+ // i2cData[11] is BLANK.
+ TEST_DATA(TLIMIT_NO_RST_ASTC, TLIMIT_TN_RST_ASTC, (int16)i2cData[12], TLIMIT_LO_RST_ASTC, TLIMIT_HI_RST_ASTC, &pf_total);
+
+ // Read values from I2CDIS.
+ if (AKD_RxData(AK8975_REG_I2CDIS, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+ if (CSPEC_SPI_USE == 1) {
+ TEST_DATA(TLIMIT_NO_RST_I2CDIS, TLIMIT_TN_RST_I2CDIS, (int16)i2cData[0], TLIMIT_LO_RST_I2CDIS_USESPI, TLIMIT_HI_RST_I2CDIS_USESPI, &pf_total);
+ }else{
+ TEST_DATA(TLIMIT_NO_RST_I2CDIS, TLIMIT_TN_RST_I2CDIS, (int16)i2cData[0], TLIMIT_LO_RST_I2CDIS_USEI2C, TLIMIT_HI_RST_I2CDIS_USEI2C, &pf_total);
+ }
+
+ // Set to FUSE ROM access mode
+ if (AKD_SetMode(AK8975_MODE_FUSE_ACCESS) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Read values from ASAX to ASAZ
+ if (AKD_RxData(AK8975_FUSE_ASAX, i2cData, 3) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+ asax = (int16)i2cData[0];
+ asay = (int16)i2cData[1];
+ asaz = (int16)i2cData[2];
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_ASAX, TLIMIT_TN_ASAX, asax, TLIMIT_LO_ASAX, TLIMIT_HI_ASAX, &pf_total);
+ TEST_DATA(TLIMIT_NO_ASAY, TLIMIT_TN_ASAY, asay, TLIMIT_LO_ASAY, TLIMIT_HI_ASAY, &pf_total);
+ TEST_DATA(TLIMIT_NO_ASAZ, TLIMIT_TN_ASAZ, asaz, TLIMIT_LO_ASAZ, TLIMIT_HI_ASAZ, &pf_total);
+
+ // Read values. CNTL
+ if (AKD_RxData(AK8975_REG_CNTL, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Set to PowerDown mode
+ if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_WR_CNTL, TLIMIT_TN_WR_CNTL, (int16)i2cData[0], TLIMIT_LO_WR_CNTL, TLIMIT_HI_WR_CNTL, &pf_total);
+
+ //***********************************************
+ // Step2
+ //***********************************************
+
+ // Set to SNG measurement pattern (Set CNTL register)
+ if (AKD_SetMode(AK8975_MODE_SNG_MEASURE) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Wait for DRDY pin changes to HIGH.
+ //usleep(AKM_MEASURE_TIME_US);
+ // Get measurement data from AK8975
+ // ST1 + (HXL + HXH) + (HYL + HYH) + (HZL + HZH) + ST2
+ // = 1 + (1 + 1) + (1 + 1) + (1 + 1) + 1 = 8 bytes
+ if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ hdata[0] = (int16)((((uint16)(i2cData[2]))<<8)+(uint16)(i2cData[1]));
+ hdata[1] = (int16)((((uint16)(i2cData[4]))<<8)+(uint16)(i2cData[3]));
+ hdata[2] = (int16)((((uint16)(i2cData[6]))<<8)+(uint16)(i2cData[5]));
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_SNG_ST1, TLIMIT_TN_SNG_ST1, (int16)i2cData[0], TLIMIT_LO_SNG_ST1, TLIMIT_HI_SNG_ST1, &pf_total);
+ TEST_DATA(TLIMIT_NO_SNG_HX, TLIMIT_TN_SNG_HX, hdata[0], TLIMIT_LO_SNG_HX, TLIMIT_HI_SNG_HX, &pf_total);
+ TEST_DATA(TLIMIT_NO_SNG_HY, TLIMIT_TN_SNG_HY, hdata[1], TLIMIT_LO_SNG_HY, TLIMIT_HI_SNG_HY, &pf_total);
+ TEST_DATA(TLIMIT_NO_SNG_HZ, TLIMIT_TN_SNG_HZ, hdata[2], TLIMIT_LO_SNG_HZ, TLIMIT_HI_SNG_HZ, &pf_total);
+ TEST_DATA(TLIMIT_NO_SNG_ST2, TLIMIT_TN_SNG_ST2, (int16)i2cData[7], TLIMIT_LO_SNG_ST2, TLIMIT_HI_SNG_ST2, &pf_total);
+
+ // Generate magnetic field for self-test (Set ASTC register)
+ i2cData[0] = 0x40;
+ if (AKD_TxData(AK8975_REG_ASTC, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Set to Self-test mode (Set CNTL register)
+ if (AKD_SetMode(AK8975_MODE_SELF_TEST) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // Wait for DRDY pin changes to HIGH.
+ //usleep(AKM_MEASURE_TIME_US);
+ // Get measurement data from AK8975
+ // ST1 + (HXL + HXH) + (HYL + HYH) + (HZL + HZH) + ST2
+ // = 1 + (1 + 1) + (1 + 1) + (1 + 1) + 1 = 8Byte
+ if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_SLF_ST1, TLIMIT_TN_SLF_ST1, (int16)i2cData[0], TLIMIT_LO_SLF_ST1, TLIMIT_HI_SLF_ST1, &pf_total);
+
+ hdata[0] = (int16)((((uint16)(i2cData[2]))<<8)+(uint16)(i2cData[1]));
+ hdata[1] = (int16)((((uint16)(i2cData[4]))<<8)+(uint16)(i2cData[3]));
+ hdata[2] = (int16)((((uint16)(i2cData[6]))<<8)+(uint16)(i2cData[5]));
+
+ // TEST
+ TEST_DATA(
+ TLIMIT_NO_SLF_RVHX,
+ TLIMIT_TN_SLF_RVHX,
+ (hdata[0])*((asax - 128)*0.5f/128.0f + 1),
+ TLIMIT_LO_SLF_RVHX,
+ TLIMIT_HI_SLF_RVHX,
+ &pf_total
+ );
+
+ TEST_DATA(
+ TLIMIT_NO_SLF_RVHY,
+ TLIMIT_TN_SLF_RVHY,
+ (hdata[1])*((asay - 128)*0.5f/128.0f + 1),
+ TLIMIT_LO_SLF_RVHY,
+ TLIMIT_HI_SLF_RVHY,
+ &pf_total
+ );
+
+ TEST_DATA(
+ TLIMIT_NO_SLF_RVHZ,
+ TLIMIT_TN_SLF_RVHZ,
+ (hdata[2])*((asaz - 128)*0.5f/128.0f + 1),
+ TLIMIT_LO_SLF_RVHZ,
+ TLIMIT_HI_SLF_RVHZ,
+ &pf_total
+ );
+
+ // TEST
+ TEST_DATA(TLIMIT_NO_SLF_ST2, TLIMIT_TN_SLF_ST2, (int16)i2cData[7], TLIMIT_LO_SLF_ST2, TLIMIT_HI_SLF_ST2, &pf_total);
+
+ // Set to Normal mode for self-test.
+ i2cData[0] = 0x00;
+ if (AKD_TxData(AK8975_REG_ASTC, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+
+ return pf_total;
+}
+
+/*!
+ Execute "Onboard Function Test" (includes "START" and "END" command).
+ @retval 1 The test is passed successfully.
+ @retval -1 The test is failed.
+ @retval 0 The test is aborted by kind of system error.
+ */
+int16 FST_Body(void)
+{
+ int16 pf_total = 1;
+
+ //***********************************************
+ // Reset Test Result
+ //***********************************************
+ TEST_DATA(NULL, "START", 0, 0, 0, &pf_total);
+
+ //***********************************************
+ // Step 1 to 2
+ //***********************************************
+ pf_total = FST_AK8975();
+
+ //***********************************************
+ // Judge Test Result
+ //***********************************************
+ TEST_DATA(NULL, "END", 0, 0, 0, &pf_total);
+
+ return pf_total;
+}
+
diff --git a/mpu/akm8963/FileIO.c b/mpu/akm8963/FileIO.c
new file mode 100755
index 0000000..9a16ef7
--- /dev/null
+++ b/mpu/akm8963/FileIO.c
@@ -0,0 +1,436 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#include "FileIO.h"
+#include <sys/stat.h>
+
+#define AKM_PERM (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
+
+/*!
+ Load parameters from file which is specified with #CSPEC_SETTING_FILE.
+ This function reads data from a beginning of the file line by line, and
+ check parameter name sequentially. In otherword, this function depends on
+ the order of eache parameter described in the file.
+ @return If function fails, the return value is 0. When function fails, the
+ output is undefined. Therefore, parameters which are possibly overwritten
+ by this function should be initialized again. If function succeeds, the
+ return value is 1.
+ @param[out] prms A pointer to #AKSCPRMS structure. Loaded parameter is
+ stored to the member of this structure.
+ */
+int16 LoadParameters(AKSCPRMS * prms)
+{
+ int16 i, j, ret;
+ int tmp;
+ double dtmp;
+ FILE *fp = NULL;
+ char keyName[KEYNAME_SIZE];
+
+ //Open setting file for read.
+ if ((fp = fopen(CSPEC_SETTING_FILE, "r")) == NULL) {
+ AKMERROR_STR("fopen");
+ return 0;
+ }
+
+ ret = 1;
+
+ // Load data to HDST, HO, HREF, THRE
+ for (i = 0; i < CSPEC_NUM_FORMATION; i++) {
+ snprintf(keyName, sizeof(keyName), "HSUC_HDST_FORM%d", i);
+ tmp = 0;
+ ret = ret && LoadInt(fp, keyName, &tmp);
+ prms->HSUC_HDST[i] = (AKSC_HDST)tmp;
+
+ snprintf(keyName, sizeof(keyName), "HSUC_HO_FORM%d", i);
+ ret = ret && LoadInt16vec(fp, keyName, &prms->HSUC_HO[i]);
+
+ snprintf(keyName, sizeof(keyName), "HFLUCV_HREF_FORM%d", i);
+ ret = ret && LoadInt16vec(fp, keyName, &prms->HFLUCV_HREF[i]);
+
+ snprintf(keyName, sizeof(keyName), "HSUC_HBASE_FORM%d", i);
+ ret = ret && LoadInt32vec(fp, keyName, &prms->HSUC_HBASE[i]);
+
+ for (j = 0; j < AKSC_DOEP_SIZE; j++) {
+ snprintf(keyName, sizeof(keyName), "DOEP_PRMS_FORM%d[%d]", i, j);
+ ret = ret && LoadDouble(fp, keyName, &dtmp);
+ prms->DOEP_PRMS[i][j] = (AKSC_FLOAT)dtmp;
+ }
+ }
+
+ // Offset of other sensors.
+ ret = ret && LoadInt16vec(fp, "AO", &prms->m_AO);
+
+ if (fclose(fp) != 0) {
+ AKMERROR_STR("fclose");
+ ret = 0;
+ }
+
+ if (ret == 0) {
+ AKMERROR;
+ }
+ return ret;
+}
+
+/*! Load PDC from file named with #SETTING_PDC_FILE_NAME.
+ This function reads parameters from a beginning of the file line by line,
+ and check parameter name sequentially.
+
+ @return When function fails, the return value is 0. In that case, all
+ related parameters, i.e. m_pdc and m_pdcptr, are initialized with 0.
+*/
+int16 LoadPDC(AKSCPRMS* prms)
+{
+ int16 ret, i;
+ FILE* fp;
+ char keyName[KEYNAME_SIZE];
+ char header[HEADER_SIZE];
+ int tmp;
+
+ ret = 1;
+
+ //Open setting file for read.
+ if((fp = fopen(CSPEC_PDC_FILE, "r")) == NULL){
+ //AKMERROR_STR("fopen");
+ goto PDCREAD_FAILED;
+ }
+
+ //Read file header
+ if(fgets(header, sizeof(header), fp) == NULL){
+ //AKMERROR_STR("fgets");
+ fclose(fp);
+ goto PDCREAD_FAILED;
+ }
+
+ //Set loaded data to pdc.
+ for (i = 0; i<PDC_SIZE; i++) {
+ snprintf(keyName, sizeof(keyName), "HPRMS%d", i);
+ tmp = 0;
+ ret = ret && LoadInt(fp, keyName, &tmp);
+ prms->m_pdc[i] = (uint8)tmp;
+ }
+
+ if (fclose(fp) != 0) {
+ AKMERROR_STR("fclose");
+ goto PDCREAD_FAILED;
+ }
+
+ if(ret != 1){
+ AKMERROR;
+ goto PDCREAD_FAILED;
+ }
+
+ // Set parameter's pointer.
+ prms->m_pdcptr = prms->m_pdc;
+
+
+ ALOGE("AK09911 pdc.txt Parameter loaded: %s\n", header);
+
+ return 1;
+
+PDCREAD_FAILED:
+ memset(prms->m_pdc, 0, sizeof(prms->m_pdc));
+ prms->m_pdcptr = 0;
+
+ return 0;
+}
+
+/*!
+ Load \c int type value from file. The name of parameter is specified with
+ \a lpKeyName. If the name matches the beginning of read line, the string
+ after #DELIMITER will converted to \c int type value.
+ @return If function fails, the return value is 0. When function fails, the
+ value @ val is not overwritten. If function succeeds, the return value is 1.
+ @param[in] fp Pointer to \c FILE structure.
+ @param[in] lpKeyName The name of parameter.
+ @param[out] val Pointer to \c int type value. Upon successful completion
+ of this function, read value is copied to this variable.
+ */
+int16 LoadInt(FILE * fp, const char *lpKeyName, int *val)
+{
+ char buf[KEYNAME_SIZE] = { '\0' };
+
+ // ATTENTION! %ns should be modified according to the size of buf.
+ if (fscanf(fp, "%63s" DELIMITER "%11d", buf, val) != 2) {
+ AKMERROR;
+ return 0;
+ }
+ // Compare the read parameter name with given name.
+ if (strncmp(buf, lpKeyName, sizeof(buf)) != 0) {
+ ALOGE("%s: strncmp (%s) error.", __FUNCTION__, lpKeyName);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*!
+ Load \c int type value from file. The name of parameter is specified with
+ \a lpKeyName. If the name matches the beginning of read line, the string
+ after #DELIMITER will converted to \c int type value.
+ @return If function fails, the return value is 0. When function fails, the
+ value @ val is not overwritten. If function succeeds, the return value is 1.
+ @param[in] fp Pointer to \c FILE structure.
+ @param[in] lpKeyName The name of parameter.
+ @param[out] val Pointer to \c double type value. Upon successful completion
+ of this function, read value is copied to this variable.
+ */
+int16 LoadDouble(FILE * fp, const char *lpKeyName, double *val)
+{
+ char buf[KEYNAME_SIZE] = { '\0' };
+
+ // ATTENTION! %ns should be modified according to the size of buf.
+ if (fscanf(fp, "%63s" DELIMITER "%20lf", buf, val) != 2) {
+ AKMERROR;
+ return 0;
+ }
+ // Compare the read parameter name with given name.
+ if (strncmp(buf, lpKeyName, sizeof(buf)) != 0) {
+ ALOGE("%s: strncmp (%s) error.", __FUNCTION__, lpKeyName);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*!
+ Load \c int16vec type value from file and convert it to int16vec type
+ structure. This function adds ".x", ".y" and ".z" to the last of parameter
+ name and try to read value with combined name.
+ @return If function fails, the return value is 0. When function fails, the
+ output is undefined. If function succeeds, the return value is 1.
+ @param[in] fp A opened \c FILE pointer.
+ @param[in] lpKeyName The parameter name.
+ @param[out] vec A pointer to int16vec structure. Upon successful completion
+ of this function, read values are copied to this variable.
+ */
+int16 LoadInt16vec(FILE * fp, const char *lpKeyName, int16vec * vec)
+{
+ char keyName[KEYNAME_SIZE];
+ int16 ret = 1;
+ int tmp;
+
+ snprintf(keyName, sizeof(keyName), "%s.x", lpKeyName);
+ ret = ret && LoadInt(fp, keyName, &tmp);
+ vec->u.x = (int16)tmp;
+
+ snprintf(keyName, sizeof(keyName), "%s.y", lpKeyName);
+ ret = ret && LoadInt(fp, keyName, &tmp);
+ vec->u.y = (int16)tmp;
+
+ snprintf(keyName, sizeof(keyName), "%s.z", lpKeyName);
+ ret = ret && LoadInt(fp, keyName, &tmp);
+ vec->u.z = (int16)tmp;
+
+ return ret;
+}
+
+/*!
+ Load \c int32vec type value from file and convert it to int32vec type
+ structure. This function adds ".x", ".y" and ".z" to the last of parameter
+ name and try to read value with combined name.
+ @return If function fails, the return value is 0. When function fails, the
+ output is undefined. If function succeeds, the return value is 1.
+ @param[in] fp A opened \c FILE pointer.
+ @param[in] lpKeyName The parameter name.
+ @param[out] vec A pointer to int32vec structure. Upon successful completion
+ of this function, read values are copied to this variable.
+ */
+int16 LoadInt32vec(FILE * fp, const char *lpKeyName, int32vec * vec)
+{
+ char keyName[KEYNAME_SIZE];
+ int16 ret = 1;
+ int tmp;
+
+ snprintf(keyName, sizeof(keyName), "%s.x", lpKeyName);
+ ret = ret && LoadInt(fp, keyName, &tmp);
+ vec->u.x = (int32)tmp;
+
+ snprintf(keyName, sizeof(keyName), "%s.y", lpKeyName);
+ ret = ret && LoadInt(fp, keyName, &tmp);
+ vec->u.y = (int32)tmp;
+
+ snprintf(keyName, sizeof(keyName), "%s.z", lpKeyName);
+ ret = ret && LoadInt(fp, keyName, &tmp);
+ vec->u.z = (int32)tmp;
+
+ return ret;
+}
+
+
+/*!
+ Save parameters to file which is specified with #CSPEC_SETTING_FILE. This
+ function saves variables when the offsets of magnetic sensor estimated
+ successfully.
+ @return If function fails, the return value is 0. When function fails, the
+ parameter file may collapsed. Therefore, the parameters file should be
+ discarded. If function succeeds, the return value is 1.
+ @param[out] prms A pointer to #AKSCPRMS structure. Member variables are
+ saved to the parameter file.
+ */
+int16 SaveParameters(AKSCPRMS * prms)
+{
+ int16 ret = 1;
+ int16 i, j;
+ FILE *fp;
+ char keyName[KEYNAME_SIZE];
+
+ //Open setting file for write.
+ if ((fp = fopen(CSPEC_SETTING_FILE, "w")) == NULL) {
+ AKMERROR_STR("fopen");
+ return 0;
+ }
+
+ for (i = 0; i < CSPEC_NUM_FORMATION; i++) {
+ snprintf(keyName, sizeof(keyName), "HSUC_HDST_FORM%d", i);
+ ret = ret && SaveInt(fp, keyName, (int)prms->HSUC_HDST[i]);
+
+ snprintf(keyName, sizeof(keyName), "HSUC_HO_FORM%d", i);
+ ret = ret && SaveInt16vec(fp, keyName, &prms->HSUC_HO[i]);
+
+ snprintf(keyName, sizeof(keyName), "HFLUCV_HREF_FORM%d", i);
+ ret = ret && SaveInt16vec(fp, keyName, &prms->HFLUCV_HREF[i]);
+
+ snprintf(keyName, sizeof(keyName), "HSUC_HBASE_FORM%d", i);
+ ret = ret && SaveInt32vec(fp, keyName, &prms->HSUC_HBASE[i]);
+
+ for (j = 0; j < AKSC_DOEP_SIZE; j++) {
+ snprintf(keyName, sizeof(keyName), "DOEP_PRMS_FORM%d[%d]", i, j);
+ ret = ret && SaveDouble(fp, keyName, (double)prms->DOEP_PRMS[i][j]);
+ }
+ }
+
+ // Offset of other sensors.
+ ret = ret && SaveInt16vec(fp, "AO", &prms->m_AO);
+
+ if (fclose(fp) != 0) {
+ AKMERROR_STR("fclose");
+ ret = 0;
+ }
+ if (chmod(CSPEC_SETTING_FILE, AKM_PERM) != 0) {
+ AKMERROR_STR("chmod");
+ ret = 0;
+ }
+
+ if (ret == 0) {
+ AKMERROR;
+ }
+
+ return ret;
+}
+
+/*!
+ Save parameters of int16 type structure to file. This function adds
+ @return If function fails, the return value is 0. When function fails,
+ parameter is not saved to file. If function succeeds, the return value is 1.
+ @param[in] fp Pointer to \c FILE structure.
+ @param[in] lpKeyName The name of paraemter.
+ @param[in] val Pointer to \c int16 type value.
+ */
+int16 SaveInt(FILE * fp, const char *lpKeyName, const int val)
+{
+ if (fprintf(fp, "%s" DELIMITER "%d\n", lpKeyName, val) < 0) {
+ ALOGE("%s: printf (%s) error.", __FUNCTION__, lpKeyName);
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+/*!
+ Save parameters of AKSC_FLOAT type structure to file. This function adds
+ @return If function fails, the return value is 0. When function fails,
+ parameter is not saved to file. If function succeeds, the return value is 1.
+ @param[in] fp Pointer to \c FILE structure.
+ @param[in] lpKeyName The name of paraemter.
+ @param[in] val Pointer to \c AKSC_FLOAT type value.
+ */
+int16 SaveDouble(FILE * fp, const char *lpKeyName, const double val)
+{
+ if (fprintf(fp, "%s" DELIMITER "%20.12lf\n", lpKeyName, val) < 0) {
+ ALOGE("%s: printf (%s) error.", __FUNCTION__, lpKeyName);
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+/*!
+ Save parameters of int16vec type structure to file. This function adds
+ ".x", ".y" and ".z" to the last of parameter name and save value with
+ the combined name.
+ @return If function fails, the return value is 0. When function fails, not
+ all parameters are saved to file, i.e. parameters file may collapsed.
+ If function succeeds, the return value is 1.
+ @param[in] fp Pointer to \c FILE structure.
+ @param[in] lpKeyName The name of paraemter.
+ @param[in] vec Pointer to \c int16vec type structure.
+ */
+int16 SaveInt16vec(FILE * fp, const char *lpKeyName,
+ const int16vec * vec)
+{
+ int16 ret = 0;
+ char keyName[KEYNAME_SIZE];
+
+ ret = 1;
+ snprintf(keyName, sizeof(keyName), "%s.x", lpKeyName);
+ ret = ret && SaveInt(fp, keyName, vec->u.x);
+
+ snprintf(keyName, sizeof(keyName), "%s.y", lpKeyName);
+ ret = ret && SaveInt(fp, keyName, vec->u.y);
+
+ snprintf(keyName, sizeof(keyName), "%s.z", lpKeyName);
+ ret = ret && SaveInt(fp, keyName, vec->u.z);
+
+ return ret;
+}
+
+/*!
+ Save parameters of int32vec type structure to file. This function adds
+ ".x", ".y" and ".z" to the last of parameter name and save value with
+ the combined name.
+ @return If function fails, the return value is 0. When function fails, not
+ all parameters are saved to file, i.e. parameters file may collapsed.
+ If function succeeds, the return value is 1.
+ @param[in] fp Pointer to \c FILE structure.
+ @param[in] lpKeyName The name of paraemter.
+ @param[in] vec Pointer to \c int32vec type structure.
+ */
+int16 SaveInt32vec(FILE * fp, const char *lpKeyName,
+ const int32vec * vec)
+{
+ int16 ret = 0;
+ char keyName[KEYNAME_SIZE];
+
+ ret = 1;
+ snprintf(keyName, sizeof(keyName), "%s.x", lpKeyName);
+ ret = ret && SaveInt(fp, keyName, vec->u.x);
+
+ snprintf(keyName, sizeof(keyName), "%s.y", lpKeyName);
+ ret = ret && SaveInt(fp, keyName, vec->u.y);
+
+ snprintf(keyName, sizeof(keyName), "%s.z", lpKeyName);
+ ret = ret && SaveInt(fp, keyName, vec->u.z);
+
+ return ret;
+}
+
diff --git a/mpu/akm8963/FileIO.h b/mpu/akm8963/FileIO.h
new file mode 100755
index 0000000..4a983b9
--- /dev/null
+++ b/mpu/akm8963/FileIO.h
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKMD_INC_FILEIO_H
+#define AKMD_INC_FILEIO_H
+
+// Common include files.
+#include "AKCommon.h"
+
+// Include file for SmartCompass library.
+#include "AKCompass.h"
+
+/*** Constant definition ******************************************************/
+#define KEYNAME_SIZE 64
+#define HEADER_SIZE 256
+#define DELIMITER " = "
+
+/*** Type declaration *********************************************************/
+
+/*** Global variables *********************************************************/
+
+/*** Prototype of function ****************************************************/
+int16 LoadParameters(AKSCPRMS* prms);
+
+int16 LoadPDC(AKSCPRMS* prms);
+
+int16 LoadInt(
+ FILE* lpFile,
+ const char* lpKeyName,
+ int* val
+);
+
+int16 LoadDouble(
+ FILE* lpFile,
+ const char* lpKeyName,
+ double* val
+);
+
+int16 LoadInt16vec(
+ FILE* lpFile,
+ const char* lpKeyName,
+ int16vec* vec
+);
+
+int16 LoadInt32vec(
+ FILE* lpFile,
+ const char* lpKeyName,
+ int32vec* vec
+);
+
+int16 SaveParameters(AKSCPRMS* prms);
+
+int16 SaveInt(
+ FILE* lpFile,
+ const char* lpKeyName,
+ const int val
+);
+
+int16 SaveDouble(
+ FILE* lpFile,
+ const char* lpKeyName,
+ const double val
+);
+
+int16 SaveInt16vec(
+ FILE* lpFile,
+ const char* lpKeyName,
+ const int16vec* vec
+);
+
+int16 SaveInt32vec(
+ FILE* lpFile,
+ const char* lpKeyName,
+ const int32vec* vec
+);
+
+#endif
+
diff --git a/mpu/akm8963/Measure.c b/mpu/akm8963/Measure.c
new file mode 100755
index 0000000..fd467dd
--- /dev/null
+++ b/mpu/akm8963/Measure.c
@@ -0,0 +1,1350 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#include "AKCommon.h"
+#include "AKMD_Driver.h"
+#include "DispMessage.h"
+#include "FileIO.h"
+#include "Measure.h"
+#include "misc.h"
+
+
+#define ACC_ACQ_FLAG_POS ACC_DATA_FLAG
+#define MAG_ACQ_FLAG_POS MAG_DATA_FLAG
+#define FUSION_ACQ_FLAG_POS FUSION_DATA_FLAG
+#define ACC_MES_FLAG_POS 8
+#define ACC_INT_FLAG_POS 9
+#define MAG_MES_FLAG_POS 10
+#define MAG_INT_FLAG_POS 11
+#define SETTING_FLAG_POS 12
+
+#define AKMD_MAG_MIN_INTERVAL 10000000 /*!< magnetometer interval */
+#define AKMD_ACC_MIN_INTERVAL 10000000 /*!< acceleration interval */
+#define AKMD_FUSION_MIN_INTERVAL 10000000 /*!< fusion interval */
+#define AKMD_MAG_INTERVAL 50000000 /*!< magnetometer interval */
+#define AKMD_ACC_INTERVAL 50000000 /*!< acceleration interval */
+#define AKMD_FUSION_INTERVAL 10000000 /*!< fusion interval */
+#define AKMD_LOOP_MARGIN 3000000 /*!< Minimum sleep time */
+#define AKMD_SETTING_INTERVAL 500000000 /*!< Setting event interval */
+
+#define DEG2RAD(x) ((AKSC_FLOAT)(((x) * AKSC_PI) / 180.0))
+#define AKSC2SI(x) ((AKSC_FLOAT)(((x) * 9.80665f) / 720.0))
+
+#ifdef AKMD_AK099XX
+#define AKMD_ST2_POS 8
+#else
+#define AKMD_ST2_POS 7
+#endif
+
+static FORM_CLASS* g_form = NULL;
+
+/*!
+ This function open formation status device.
+ @return Return 0 on success. Negative value on fail.
+ */
+static int16 openForm(void)
+{
+ if (g_form != NULL) {
+ if (g_form->open != NULL) {
+ return g_form->open();
+ }
+ }
+ // If function is not set, return success.
+ return 0;
+}
+
+/*!
+ This function close formation status device.
+ @return None.
+ */
+static void closeForm(void)
+{
+ if (g_form != NULL) {
+ if (g_form->close != NULL) {
+ g_form->close();
+ }
+ }
+}
+
+/*!
+ This function check formation status
+ @return The index of formation.
+ */
+static int16 checkForm(void)
+{
+ if (g_form != NULL) {
+ if (g_form->check != NULL) {
+ return g_form->check();
+ }
+ }
+ // If function is not set, return default value.
+ return 0;
+}
+
+/*!
+ This function registers the callback function.
+ @param[in]
+ */
+void RegisterFormClass(FORM_CLASS* pt)
+{
+ g_form = pt;
+}
+
+/*!
+ Initialize #AKSCPRMS structure. At first, 0 is set to all parameters.
+ After that, some parameters, which should not be 0, are set to specific
+ value. Some of initial values can be customized by editing the file
+ \c "CustomerSpec.h".
+ @param[out] prms A pointer to #AKSCPRMS structure.
+ */
+void InitAKSCPRMS(AKSCPRMS* prms)
+{
+ // Set 0 to the AKSCPRMS structure.
+ memset(prms, 0, sizeof(AKSCPRMS));
+
+ // Sensitivity
+ prms->m_hs.u.x = AKSC_HSENSE_TARGET;
+ prms->m_hs.u.y = AKSC_HSENSE_TARGET;
+ prms->m_hs.u.z = AKSC_HSENSE_TARGET;
+
+ // HDOE
+ prms->m_hdst = AKSC_HDST_UNSOLVED;
+
+ // (m_hdata is initialized with AKSC_InitDecomp)
+ prms->m_hnave = CSPEC_HNAVE;
+ prms->m_dvec.u.x = CSPEC_DVEC_X;
+ prms->m_dvec.u.y = CSPEC_DVEC_Y;
+ prms->m_dvec.u.z = CSPEC_DVEC_Z;
+}
+
+/*!
+ Fill #AKSCPRMS structure with default value.
+ @param[out] prms A pointer to #AKSCPRMS structure.
+ */
+void SetDefaultPRMS(AKSCPRMS* prms)
+{
+ int16 i, j;
+ // Set parameter to HDST, HO, HREF
+ for (i = 0; i < CSPEC_NUM_FORMATION; i++) {
+ prms->HSUC_HDST[i] = AKSC_HDST_UNSOLVED;
+ prms->HSUC_HO[i].u.x = 0;
+ prms->HSUC_HO[i].u.y = 0;
+ prms->HSUC_HO[i].u.z = 0;
+ prms->HFLUCV_HREF[i].u.x = 0;
+ prms->HFLUCV_HREF[i].u.y = 0;
+ prms->HFLUCV_HREF[i].u.z = 0;
+ prms->HSUC_HBASE[i].u.x = 0;
+ prms->HSUC_HBASE[i].u.y = 0;
+ prms->HSUC_HBASE[i].u.z = 0;
+ for (j = 0; j < AKSC_DOEP_SIZE; j++) {
+ prms->DOEP_PRMS[i][j] = (AKSC_FLOAT)(0.);
+ }
+ }
+}
+
+/*!
+ Get interval from device driver. This function will not resolve dependencies.
+ Dependencies will be resolved in Sensor HAL.
+ @param[out] acc_mes Accelerometer measurement timing.
+ @param[out] mag_mes Magnetometer measurement timing.
+ @param[out] acc_acq Accelerometer acquisition timing.
+ @param[out] mag_acq Magnetometer acquisition timing.
+ @param[out] fusion_acq Orientation sensor acquisition timing.
+ @param[out] hdoe_interval HDOE decimator.
+ */
+int16 GetInterval(
+ AKMD_LOOP_TIME* acc_mes,
+ AKMD_LOOP_TIME* mag_mes,
+ AKMD_LOOP_TIME* acc_acq,
+ AKMD_LOOP_TIME* mag_acq,
+ AKMD_LOOP_TIME* fusion_acq,
+ int16* hdoe_dec)
+{
+ /* Accelerometer, Magnetometer, Orientation */
+ /* Delay is in nano second unit. */
+ /* Negative value means the sensor is disabled.*/
+ int64_t delay[AKM_NUM_SENSORS];
+ int64_t acc_last_interval = 0;
+
+ if (AKD_GetDelay(delay) != AKD_SUCCESS) {
+ return AKRET_PROC_FAIL;
+ }
+
+#ifdef AKMD_ACC_EXTERNAL
+ /* Always disabled */
+ delay[0] = -1;
+#else
+ /* Accelerometer's interval limit */
+ if ((0 <= delay[0]) && (delay[0] <= AKMD_ACC_MIN_INTERVAL)) {
+ delay[0] = AKMD_ACC_MIN_INTERVAL;
+ }
+#endif
+ /* Magnetmeter's frequency should be discrete value */
+ if ((0 <= delay[1]) && (delay[1] <= AKMD_MAG_MIN_INTERVAL)) {
+ delay[1] = AKMD_MAG_MIN_INTERVAL;
+ }
+ /* Fusion sensor's interval limit */
+ if ((0 <= delay[2]) && (delay[2] <= AKMD_FUSION_MIN_INTERVAL)) {
+ delay[2] = AKMD_FUSION_MIN_INTERVAL;
+ }
+
+ if ((delay[0] != acc_acq->interval) ||
+ (delay[1] != mag_acq->interval) ||
+ (delay[2] != fusion_acq->interval)) {
+
+ /* reserve previous value */
+ acc_last_interval = acc_mes->interval;
+
+ /* Copy new value */
+ acc_acq->duration = acc_acq->interval = delay[0];
+ mag_acq->duration = mag_acq->interval = delay[1];
+ fusion_acq->duration = fusion_acq->interval = delay[2];
+
+ if (fusion_acq->interval < 0) {
+ /* NO relation between fusion sensor and physical sensor */
+ acc_mes->interval = acc_acq->interval;
+ mag_mes->interval = mag_acq->interval;
+ } else {
+ /* Solve dependency */
+ if ((acc_acq->interval >= 0) &&
+ (acc_acq->interval < fusion_acq->interval)) {
+ acc_mes->interval = acc_acq->interval;
+ } else {
+ acc_mes->interval = fusion_acq->interval;
+ }
+ if ((mag_acq->interval >= 0) &&
+ (mag_acq->interval < fusion_acq->interval)) {
+ mag_mes->interval = mag_acq->interval;
+ } else {
+ mag_mes->interval = fusion_acq->interval;
+ }
+ }
+ acc_mes->duration = 0;
+ mag_mes->duration = 0;
+
+ if (mag_mes->interval >= 0) {
+ /* Magnetometer measurement interval should be discrete value */
+ GetHDOEDecimator(&(mag_mes->interval), hdoe_dec);
+ }
+
+ if (acc_last_interval != acc_mes->interval) {
+ if (acc_mes->interval >= 0) {
+ /* Acc is enabled */
+ if (AKD_AccSetEnable(AKD_ENABLE) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKRET_PROC_FAIL;
+ }
+ /* Then set interval */
+ if (AKD_AccSetDelay(acc_acq->interval) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKRET_PROC_FAIL;
+ }
+ } else {
+ /* Acc is disabled */
+ if (AKD_AccSetEnable(AKD_DISABLE) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKRET_PROC_FAIL;
+ }
+ }
+ }
+
+ AKMDEBUG(AKMDBG_GETINTERVAL,
+ "%s:\n"
+ " AcqInterval(M,A,Fusion)=%8.2f,%8.2f,%8.2f\n"
+ " MesInterval(M,A)=%8.2f,%8.2f\n",
+ __FUNCTION__,
+ mag_acq->interval/1000000.0f,
+ acc_acq->interval/1000000.0f,
+ fusion_acq->interval/1000000.0f,
+ mag_mes->interval/1000000.0f,
+ acc_mes->interval/1000000.0f);
+ }
+
+ return AKRET_PROC_SUCCEED;
+}
+
+/*!
+ Calculate loop duration
+ @return If it is time to fire the event, the return value is 1, otherwise 0.
+ @param[in,out] tm An event.
+ @param[in] execTime The time to execute main loop for one time.
+ @param[in,out] minDuration The minimum sleep time in all events.
+ */
+int SetLoopTime(
+ AKMD_LOOP_TIME* tm,
+ int64_t execTime,
+ int64_t* minDuration)
+{
+ int ret = 0;
+ if (tm->interval >= 0) {
+ tm->duration -= execTime;
+ if (tm->duration <= AKMD_LOOP_MARGIN) {
+ tm->duration = tm->interval;
+ ret = 1;
+ } else if (tm->duration < *minDuration) {
+ *minDuration = tm->duration;
+ }
+ }
+ return ret;
+}
+
+/*!
+ Read hard coded value (Fuse ROM) from AKM E-Compass. Then set the read value
+ to calculation parameter.
+ @return If parameters are read successfully, the return value is
+ #AKRET_PROC_SUCCEED. Otherwise the return value is #AKRET_PROC_FAIL. No
+ error code is reserved to show which operation has failed.
+ @param[out] prms A pointer to #AKSCPRMS structure.
+ */
+int16 ReadFUSEROM(AKSCPRMS* prms)
+{
+ BYTE info[AKM_SENSOR_INFO_SIZE];
+ BYTE conf[AKM_SENSOR_CONF_SIZE];
+
+ prms->akm_device=0;
+#if 1
+ // Get information
+ if (AKD_GetSensorInfo(info) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKRET_PROC_FAIL;
+ }
+
+ if((info[1]==0x05)&&(info[0]==0x48))
+ prms->akm_device=1;
+ else
+ {
+ info[1]=0x05;
+ info[0]=0x48;
+ }
+
+ // Get configuration
+ if (AKD_GetSensorConf(conf) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKRET_PROC_FAIL;
+ }
+#endif
+ if(prms->akm_device==0)
+ {
+ conf[0]=(conf[0]-128)/2;
+ conf[1]=(conf[1]-128)/2;
+ conf[2]=(conf[2]-128)/2;
+ }
+
+ prms->m_asa.u.x = (int16)conf[0];
+ prms->m_asa.u.y = (int16)conf[1];
+ prms->m_asa.u.z = (int16)conf[2];
+
+ AKMDEBUG(AKMDBG_DEBUG, "%s: asa(dec)=%d,%d,%d\n", __FUNCTION__,
+ prms->m_asa.u.x, prms->m_asa.u.y, prms->m_asa.u.z);
+
+ // Set keywords for SmartCompassLibrary certification
+ prms->m_key[0] = AKSC_GetVersion_Device();
+
+#ifdef AKMD_AK099XX
+ /* This definition is used by AK099XX. */
+ prms->m_key[1] = (int16)(((uint16)info[1] << 8) | info[0]);
+#else
+ /* This definition is used by AK89XX. */
+ prms->m_key[1] = (int16)info[0];
+#endif
+ prms->m_key[2] = (int16)conf[0];
+ prms->m_key[3] = (int16)conf[1];
+ prms->m_key[4] = (int16)conf[2];
+ strncpy((char *)prms->m_licenser, CSPEC_CI_LICENSER, AKSC_CI_MAX_CHARSIZE);
+ strncpy((char *)prms->m_licensee, CSPEC_CI_LICENSEE, AKSC_CI_MAX_CHARSIZE);
+
+ AKMDEBUG(AKMDBG_DEBUG, "%s: key=%d, licenser=%s, licensee=%s\n",
+ __FUNCTION__, prms->m_key[1], prms->m_licenser, prms->m_licensee);
+
+ if(prms->akm_device==0)
+ prms->m_en_doeplus = 0 ;
+
+ AKMDEBUG(AKMDBG_DEBUG, "%s: device=%d, DOEPlus=%d\n",
+ __FUNCTION__, prms->akm_device, prms->m_en_doeplus);
+
+ return AKRET_PROC_SUCCEED;
+}
+
+
+/*!
+ Set initial values for SmartCompass library.
+ @return If parameters are read successfully, the return value is
+ #AKRET_PROC_SUCCEED. Otherwise the return value is #AKRET_PROC_FAIL. No
+ error code is reserved to show which operation has failed.
+ @param[in,out] prms A pointer to a #AKSCPRMS structure.
+ */
+int16 Init_Measure(AKSCPRMS* prms)
+{
+#ifdef AKMD_FOR_AK09912
+ BYTE i2cData[AKM_SENSOR_DATA_SIZE];
+#endif
+
+ // Reset device.
+ if (AKD_Reset() != AKD_SUCCESS) {
+ AKMERROR;
+ return AKRET_PROC_FAIL;
+ }
+
+#ifdef AKMD_FOR_AK09912
+ // Set to Temperature mode and Noise Suppression Filter mode.
+ i2cData[0] = CSPEC_TEMPERATURE | CSPEC_NSF;
+ if (AKD_TxData(AK09912_REG_CNTL1, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return 0;
+ }
+#endif
+ prms->m_form = checkForm();
+
+ // Restore the value when succeeding in estimating of HOffset.
+ prms->m_ho = prms->HSUC_HO[prms->m_form];
+ prms->m_ho32.u.x = (int32)prms->HSUC_HO[prms->m_form].u.x;
+ prms->m_ho32.u.y = (int32)prms->HSUC_HO[prms->m_form].u.y;
+ prms->m_ho32.u.z = (int32)prms->HSUC_HO[prms->m_form].u.z;
+
+ prms->m_hdst = prms->HSUC_HDST[prms->m_form];
+ prms->m_hbase = prms->HSUC_HBASE[prms->m_form];
+
+ // Initialize the decompose parameters
+ AKSC_InitDecomp(prms->m_hdata);
+ // Initialize DOEPlus parameters
+ if (prms->m_en_doeplus == 1) {
+ AKSC_InitDOEPlus(prms->m_doep_var);
+ prms->m_doep_lv = AKSC_LoadDOEPlus(
+ prms->DOEP_PRMS[prms->m_form],
+ prms->m_doep_var);
+ AKSC_InitDecomp(prms->m_hdata_plus);
+ }
+
+ // Initialize HDOE parameters
+ AKSC_InitHDOEProcPrmsS3(
+ &prms->m_hdoev,
+ 1,
+ &prms->m_ho,
+ prms->m_hdst
+ );
+
+ AKSC_InitHFlucCheck(
+ &(prms->m_hflucv),
+ &(prms->HFLUCV_HREF[prms->m_form]),
+ HFLUCV_TH
+ );
+
+ AKSC_InitPseudoGyro(
+ &prms->m_pgcond,
+ &prms->m_pgvar
+ );
+
+ prms->m_pgcond.fmode=1;
+ prms->m_pgcond.th_rdif=666;
+ prms->m_pgcond.th_rmax=1667;
+ prms->m_pgcond.th_rmin=333;
+ prms->m_pgcond.ihave=24;
+ prms->m_pgcond.iaave=24;
+ prms->m_pgcond.ocoef=90;//103;
+
+ switch(prms->PG_filter){
+
+ case 0:
+ prms->m_pgcond.ihave=24;
+ prms->m_pgcond.iaave=24;
+ prms->m_pgcond.ocoef=103;
+ break;
+ case 1:
+ prms->m_pgcond.ihave=24;
+ prms->m_pgcond.iaave=24;
+ prms->m_pgcond.ocoef=205;
+ break;
+
+ case 2:
+ prms->m_pgcond.ihave=24;
+ prms->m_pgcond.iaave=24;
+ prms->m_pgcond.ocoef=307;
+ break;
+
+ case 3:
+ prms->m_pgcond.ihave=32;
+ prms->m_pgcond.iaave=32;
+ prms->m_pgcond.ocoef=205;
+ break;
+
+ case 4:
+ prms->m_pgcond.ihave=32;
+ prms->m_pgcond.iaave=32;
+ prms->m_pgcond.ocoef=307;
+ break;
+
+ case 5:
+ prms->m_pgcond.ihave=12;
+ prms->m_pgcond.iaave=12;
+ prms->m_pgcond.ocoef=307;
+ break;
+
+ case 6:
+ prms->m_pgcond.ihave=12;
+ prms->m_pgcond.iaave=12;
+ prms->m_pgcond.ocoef=205;
+ break;
+
+ case 7:
+ prms->m_pgcond.ihave=12;
+ prms->m_pgcond.iaave=12;
+ prms->m_pgcond.ocoef=103;
+ break;
+
+ }
+
+ // Reset counter
+ prms->m_cntSuspend = 0;
+ prms->m_callcnt = 0;
+
+ return AKRET_PROC_SUCCEED;
+}
+
+
+/*!
+ This is the main routine of measurement.
+ @param[in,out] prms A pointer to a #AKSCPRMS structure.
+ */
+void MeasureSNGLoop(AKSCPRMS* prms)
+{
+ BYTE i2cData[AKM_SENSOR_DATA_SIZE];
+ int16 bData[AKM_SENSOR_DATA_SIZE]; // Measuring block data
+ int16 adata[3];
+ int16 ret;
+ int16 i;
+ int16 hdoe_interval = 1;
+
+ /* Acceleration interval */
+ AKMD_LOOP_TIME acc_acq = { -1, 0 };
+ /* Magnetic field interval */
+ AKMD_LOOP_TIME mag_acq = { -1, 0 };
+ /* Orientation interval */
+ AKMD_LOOP_TIME fusion_acq = { -1, 0 };
+ /* Magnetic acquisition interval */
+ AKMD_LOOP_TIME mag_mes = { -1, 0 };
+ /* Acceleration acquisition interval */
+ AKMD_LOOP_TIME acc_mes = { -1, 0 };
+ /* Magnetic measurement interval */
+ AKMD_LOOP_TIME mag_int = { AKM_MEASUREMENT_TIME_NS, 0 };
+ /* Setting interval */
+ AKMD_LOOP_TIME setting = { AKMD_SETTING_INTERVAL, 0 };
+
+ /* 0x0001: Acceleration execute flag (data output) */
+ /* 0x0002: Magnetic execute flag (data output) */
+ /* 0x0004: Fusion execute flag (data output) */
+ /* 0x0100: Magnetic measurement flag */
+ /* 0x0200: Magnetic interrupt flag */
+ /* 0x0400: Acceleration measurement flag */
+ /* 0x0800: Acceleration interrupt flag */
+ /* 0x0400: Setting execute flag */
+ uint16 exec_flags;
+
+ struct timespec currTime = { 0, 0 }; /* Current time */
+ struct timespec lastTime = { 0, 0 }; /* Previous time */
+ struct timespec prevGtm = { 0, 0 };
+
+ int64_t execTime; /* Time between two points */
+ int64_t minVal; /* The minimum duration to the next event */
+ int measuring = 0; /* The value is 1, if while measuring. */
+
+ if (openForm() < 0) {
+ AKMERROR;
+ return;
+ }
+
+ /* Initialize */
+ if (Init_Measure(prms) != AKRET_PROC_SUCCEED) {
+ goto MEASURE_SNG_END;
+ }
+
+ /* Get initial interval */
+ if (GetInterval(
+ &acc_mes, &mag_mes,
+ &acc_acq, &mag_acq, &fusion_acq,
+ &hdoe_interval) != AKRET_PROC_SUCCEED) {
+ AKMERROR;
+ goto MEASURE_SNG_END;
+ }
+
+ /* Beginning time */
+ if (clock_gettime(CLOCK_MONOTONIC, &currTime) < 0) {
+ AKMERROR;
+ goto MEASURE_SNG_END;
+ }
+ /* Set initial value */
+ prevGtm = currTime;
+
+ //TODO: Define stop flag
+ while (g_stopRequest != 1) {
+ exec_flags = 0;
+ minVal = 1000000000; /*1sec*/
+
+ /* Copy the last time */
+ lastTime = currTime;
+
+ /* Get current time */
+ if (clock_gettime(CLOCK_MONOTONIC, &currTime) < 0) {
+ AKMERROR;
+ break;
+ }
+
+ /* Calculate the difference */
+ execTime = CalcDuration(&currTime, &lastTime);
+
+ AKMDEBUG(AKMDBG_EXECTIME,
+ "Executing(%6.2f)\n", (double)execTime / 1000000.0);
+
+ /* Subtract the differential time from each event.
+ If subtracted value is negative turn event flag on. */
+ exec_flags |= (SetLoopTime(&setting, execTime, &minVal)
+ << (SETTING_FLAG_POS));
+
+ exec_flags |= (SetLoopTime(&acc_acq, execTime, &minVal)
+ << (ACC_ACQ_FLAG_POS));
+
+ exec_flags |= (SetLoopTime(&mag_acq, execTime, &minVal)
+ << (MAG_ACQ_FLAG_POS));
+
+ exec_flags |= (SetLoopTime(&fusion_acq, execTime, &minVal)
+ << (FUSION_ACQ_FLAG_POS));
+
+ exec_flags |= (SetLoopTime(&acc_mes, execTime, &minVal)
+ << (ACC_MES_FLAG_POS));
+
+ /* Magnetometer needs special care. While the device is
+ under measuring, measurement start flag should not be turned on.*/
+ if (mag_mes.interval >= 0) {
+ mag_mes.duration -= execTime;
+ if (!measuring) {
+ /* Not measuring */
+ if (mag_mes.duration <= AKMD_LOOP_MARGIN) {
+ exec_flags |= (1 << (MAG_MES_FLAG_POS));
+ } else if (mag_mes.duration < minVal) {
+ minVal = mag_mes.duration;
+ }
+ } else {
+ /* While measuring */
+ mag_int.duration -= execTime;
+ /* NO_MARGIN! */
+ if (mag_int.duration <= 0) {
+ exec_flags |= (1 << (MAG_INT_FLAG_POS));
+ } else if (mag_int.duration < minVal) {
+ minVal = mag_int.duration;
+ }
+ }
+ }
+
+ /* If all flag is off, go sleep */
+ if (exec_flags == 0) {
+ AKMDEBUG(AKMDBG_EXECTIME, "Sleeping(%6.2f)...\n",
+ (double)minVal / 1000000.0);
+ if (minVal > 0) {
+ struct timespec doze = { 0, 0 };
+ doze = int64_to_timespec(minVal);
+ nanosleep(&doze, NULL);
+ }
+ } else {
+ AKMDEBUG(AKMDBG_EXECTIME, "ExecFlags=0x%04X\n", exec_flags);
+
+ if (exec_flags & (1 << (MAG_MES_FLAG_POS))) {
+ /* Set to SNG measurement pattern (Set CNTL register) */
+ if (AKD_SetMode(AKM_MODE_SNG_MEASURE) != AKD_SUCCESS) {
+ AKMERROR;
+ } else {
+ mag_mes.duration = mag_mes.interval;
+ mag_int.duration = mag_int.interval;
+ measuring = 1;
+ }
+ }
+
+ if (exec_flags & (1 << (MAG_INT_FLAG_POS))) {
+ /* Get magnetometer measurement data */
+ if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) {
+ AKMERROR;
+ // Reset driver
+ AKD_Reset();
+ // Unset flag
+ exec_flags &= ~(1 << (MAG_INT_FLAG_POS));
+ } else {
+ // Copy to local variable
+ for (i=0; i<AKM_SENSOR_DATA_SIZE; i++) {
+ bData[i] = i2cData[i];
+ }
+
+ ret = GetMagneticVector(
+ bData,
+ prms,
+ checkForm(),
+ hdoe_interval);
+
+ // Check the return value
+ if ((ret != AKRET_PROC_SUCCEED) && (ret != AKRET_FORMATION_CHANGED)) {
+ ALOGE("GetMagneticVector has failed (0x%04X).\n", ret);
+ }
+
+ AKMDEBUG(AKMDBG_VECTOR, "mag(dec)=%6d,%6d,%6d\n",
+ prms->m_hvec.u.x, prms->m_hvec.u.y, prms->m_hvec.u.z);
+ }
+ measuring = 0;
+ }
+
+ if (exec_flags & (1 << (ACC_MES_FLAG_POS))) {
+ /* Get accelerometer data */
+ if (AKD_GetAccelerationData(adata) != AKD_SUCCESS) {
+ AKMERROR;
+ break;
+ }
+ AKD_GetAccelerationVector(adata, prms->m_AO.v, prms->m_avec.v);
+
+ AKMDEBUG(AKMDBG_VECTOR, "acc(dec)=%6d,%6d,%6d\n",
+ prms->m_avec.u.x, prms->m_avec.u.y, prms->m_avec.u.z);
+ }
+
+ if (exec_flags & (1 << (FUSION_ACQ_FLAG_POS))) {
+ int64_t tmpDuration;
+ tmpDuration = CalcDuration(&currTime, &prevGtm);
+ /* Limit to 16-bit value */
+ if (tmpDuration > 2047000000) {
+ tmpDuration = 2047000000;
+ }
+ prms->m_pgdt = (tmpDuration * 16) / 1000000;
+ prevGtm = currTime;
+ if (CalcDirection(prms) != AKRET_PROC_SUCCEED) {
+ exec_flags &= ~(1 << (FUSION_ACQ_FLAG_POS));
+ AKMERROR;
+ }
+ /* Calculate angular rate */
+#if 0
+ if (CalcAngularRate(prms) != AKRET_PROC_SUCCEED) {
+ exec_flags &= ~(1 << (FUSION_ACQ_FLAG_POS));
+ AKMERROR;
+ }
+#endif
+ }
+
+ /* Calculate direction angle */
+ if (exec_flags & 0x0F) {
+ /* If any ACQ flag is on, report the data to device driver */
+ Disp_MeasurementResultHook(prms, (uint16)(exec_flags & 0x0F));
+ }
+
+ if (exec_flags & (1 << (SETTING_FLAG_POS))) {
+ /* Get measurement interval from device driver */
+ GetInterval(
+ &acc_mes, &mag_mes,
+ &acc_acq, &mag_acq, &fusion_acq,
+ &hdoe_interval);
+ }
+ }
+ }
+
+MEASURE_SNG_END:
+ // Disable all sensors
+ if (AKD_SetMode(AKM_MODE_POWERDOWN) != AKD_SUCCESS) {AKMERROR;}
+ if (AKD_AccSetEnable(AKD_DISABLE) != AKD_SUCCESS) {AKMERROR;}
+
+ closeForm();
+}
+
+
+
+/*!
+ SmartCompass main calculation routine. This function will be processed
+ when INT pin event is occurred.
+ @retval AKRET_
+ @param[in] bData An array of register values which holds,
+ ST1, HXL, HXH, HYL, HYH, HZL, HZH and ST2 value respectively.
+ @param[in,out] prms A pointer to a #AKSCPRMS structure.
+ @param[in] curForm The index of hardware position which represents the
+ index when this function is called.
+ @param[in] hDecimator HDOE will execute once while this function is called
+ this number of times.
+ */
+int16 GetMagneticVector(
+ const int16 bData[],
+ AKSCPRMS* prms,
+ const int16 curForm,
+ const int16 hDecimator)
+{
+ const int16vec hrefZero = {{0, 0, 0}};
+ int16vec have, hvec;
+ int16 i;
+ int16 temperature, dor, derr, hofl, cb, dc;
+ int32vec preHbase;
+ int16 overflow;
+ int16 hfluc;
+ int16 hdSucc;
+ int16 aksc_ret;
+ int16 ret;
+ int16 doep_ret;
+
+ have.u.x = 0;
+ have.u.y = 0;
+ have.u.z = 0;
+ temperature = 0;
+ dor = 0;
+ derr = 0;
+ hofl = 0;
+ cb = 0;
+ dc = 0;
+
+ preHbase = prms->m_hbase;
+ overflow = 0;
+ ret = AKRET_PROC_SUCCEED;
+
+ // Subtract the formation suspend counter
+ if (prms->m_cntSuspend > 0) {
+ prms->m_cntSuspend--;
+
+ // Check the suspend counter
+ if (prms->m_cntSuspend == 0) {
+ // Restore the value when succeeding in estimating of HOffset.
+ prms->m_ho = prms->HSUC_HO[prms->m_form];
+ prms->m_ho32.u.x = (int32)prms->HSUC_HO[prms->m_form].u.x;
+ prms->m_ho32.u.y = (int32)prms->HSUC_HO[prms->m_form].u.y;
+ prms->m_ho32.u.z = (int32)prms->HSUC_HO[prms->m_form].u.z;
+
+ prms->m_hdst = prms->HSUC_HDST[prms->m_form];
+ prms->m_hbase = prms->HSUC_HBASE[prms->m_form];
+
+ // Initialize the decompose parameters
+ AKSC_InitDecomp(prms->m_hdata);
+
+ // Initialize DOEPlus parameters
+ if (prms->m_en_doeplus == 1) {
+ AKSC_InitDOEPlus(prms->m_doep_var);
+ prms->m_doep_lv = AKSC_LoadDOEPlus(
+ prms->DOEP_PRMS[prms->m_form],
+ prms->m_doep_var);
+ AKSC_InitDecomp(prms->m_hdata_plus);
+ }
+
+ // Initialize HDOE parameters
+ AKSC_InitHDOEProcPrmsS3(
+ &prms->m_hdoev,
+ 1,
+ &prms->m_ho,
+ prms->m_hdst
+ );
+
+ // Initialize HFlucCheck parameters
+ AKSC_InitHFlucCheck(
+ &(prms->m_hflucv),
+ &(prms->HFLUCV_HREF[prms->m_form]),
+ HFLUCV_TH
+ );
+ }
+ }
+ // Decompose one block data into each Magnetic sensor's data
+ aksc_ret = AKSC_DecompS3(
+ AKSC_GetVersion_Device(),
+ bData,
+ prms->m_hnave,
+ &prms->m_asa,
+ prms->m_pdcptr,
+ prms->m_hdata,
+ &prms->m_hbase,
+ &prms->m_hn,
+ &have,
+ &temperature,
+ &dor,
+ &derr,
+ &hofl,
+ &cb,
+ &dc
+ );
+ if(g_akmlog_enable)
+ {
+ ALOGE("%s: ST1, HXH&HXL, HYH&HYL, HZH&HZL, ST2,"
+ " hdata[0].u.x, hdata[0].u.y, hdata[0].u.z,"
+ " asax, asay, asaz ="
+ " %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+ __FUNCTION__,
+ bData[0],
+ (int16)(((uint16)bData[2])<<8|bData[1]),
+ (int16)(((uint16)bData[4])<<8|bData[3]),
+ (int16)(((uint16)bData[6])<<8|bData[5]), bData[AKMD_ST2_POS],
+ prms->m_hdata[0].u.x, prms->m_hdata[0].u.y, prms->m_hdata[0].u.z,
+ prms->m_asa.u.x, prms->m_asa.u.y, prms->m_asa.u.z);
+ }
+
+ if (aksc_ret == 0) {
+ AKMERROR;
+ AKMDEBUG(AKMDBG_DUMP,
+ "AKSC_DecompS3 failed.\n"
+ " ST1=0x%02X, ST2=0x%02X\n"
+ " XYZ(HEX)=%02X,%02X,%02X,%02X,%02X,%02X\n"
+ " asa(dec)=%d,%d,%d\n"
+ " pdc(addr)=0x%p\n"
+ " hbase(dec)=%ld,%ld,%ld\n",
+ bData[0], bData[AKMD_ST2_POS],
+ bData[1], bData[2], bData[3], bData[4], bData[5], bData[6],
+ prms->m_asa.u.x, prms->m_asa.u.y, prms->m_asa.u.z,
+ prms->m_pdcptr,
+ prms->m_hbase.u.x, prms->m_hbase.u.y, prms->m_hbase.u.z);
+ return AKRET_PROC_FAIL;
+ }
+ // Check the formation change
+ if (prms->m_form != curForm) {
+ prms->m_form = curForm;
+ prms->m_cntSuspend = CSPEC_CNTSUSPEND_SNG;
+ prms->m_callcnt = 0;
+ ret |= AKRET_FORMATION_CHANGED;
+ return ret;
+ }
+
+ // Check derr
+ if (derr == 1) {
+ ret |= AKRET_DATA_READERROR;
+ return ret;
+ }
+
+ // Check hofl
+ if (hofl == 1) {
+ if (prms->m_cntSuspend <= 0) {
+ // Set a HDOE level as "HDST_UNSOLVED"
+ AKSC_SetHDOELevel(
+ &prms->m_hdoev,
+ &prms->m_ho,
+ AKSC_HDST_UNSOLVED,
+ 1
+ );
+ prms->m_hdst = AKSC_HDST_UNSOLVED;
+ }
+ ret |= AKRET_DATA_OVERFLOW;
+ return ret;
+ }
+
+ // Check hbase
+ if (cb == 1) {
+ // Translate HOffset
+ AKSC_TransByHbase(
+ &(preHbase),
+ &(prms->m_hbase),
+ &(prms->m_ho),
+ &(prms->m_ho32),
+ &overflow
+ );
+ if (overflow == 1) {
+ ret |= AKRET_OFFSET_OVERFLOW;
+ }
+
+ // Set hflucv.href to 0
+ AKSC_InitHFlucCheck(
+ &(prms->m_hflucv),
+ &(hrefZero),
+ HFLUCV_TH
+ );
+
+ if (prms->m_cntSuspend <= 0) {
+ AKSC_SetHDOELevel(
+ &prms->m_hdoev,
+ &prms->m_ho,
+ AKSC_HDST_UNSOLVED,
+ 1
+ );
+ prms->m_hdst = AKSC_HDST_UNSOLVED;
+ }
+
+ ret |= AKRET_HBASE_CHANGED;
+ return ret;
+ }
+
+ if (prms->m_cntSuspend <= 0) {
+ // Detect a fluctuation of magnetic field.
+ hfluc = AKSC_HFlucCheck(&(prms->m_hflucv), &(prms->m_hdata[0]));
+
+ if (hfluc == 1) {
+ // Set a HDOE level as "HDST_UNSOLVED"
+ AKSC_SetHDOELevel(
+ &prms->m_hdoev,
+ &prms->m_ho,
+ AKSC_HDST_UNSOLVED,
+ 1
+ );
+ prms->m_hdst = AKSC_HDST_UNSOLVED;
+ ret |= AKRET_HFLUC_OCCURRED;
+ return ret;
+ }
+ else {
+ prms->m_callcnt--;
+ if (prms->m_callcnt <= 0) {
+ if (prms->m_en_doeplus == 1) {
+ // Compensate Magnetic Distortion by DOEPlus
+ doep_ret = AKSC_DOEPlus(&prms->m_hdata[0], prms->m_doep_var, &prms->m_doep_lv);
+
+ // Save DOEPlus parameters
+ if ((doep_ret == 1) && (prms->m_doep_lv == 3)) {
+ AKSC_SaveDOEPlus(prms->m_doep_var, prms->DOEP_PRMS[prms->m_form]);
+ }
+
+ // Calculate compensated vector for DOE
+ for(i = 0; i < prms->m_hn; i++) {
+ AKSC_DOEPlus_DistCompen(&prms->m_hdata[i], prms->m_doep_var, &prms->m_hdata_plus[i]);
+ }
+
+ AKMDEBUG(AKMDBG_DOEPLUS,"DOEP: %7d, %7d, %7d ",
+ prms->m_hdata[0].u.x,
+ prms->m_hdata[0].u.y,
+ prms->m_hdata[0].u.z);
+ AKMDEBUG(AKMDBG_DOEPLUS,"|%7d, %7d, %7d \n",
+ prms->m_hdata_plus[0].u.x,
+ prms->m_hdata_plus[0].u.y,
+ prms->m_hdata_plus[0].u.z);
+ }else{
+ // Copy magnetic vector for DOE
+ for(i = 0; i < prms->m_hn; i++) {
+ prms->m_hdata_plus[i] = prms->m_hdata[i];
+ }
+ }
+ //Calculate Magnetic sensor's offset by DOE
+ if (prms->m_en_doeplus == 1) {
+ hdSucc = AKSC_HDOEProcessS3(
+ prms->m_licenser,
+ prms->m_licensee,
+ prms->m_key,
+ &prms->m_hdoev,
+ prms->m_hdata_plus,
+ prms->m_hn,
+ &prms->m_ho,
+ &prms->m_hdst
+ );
+ } else {
+ hdSucc = AKSC_HDOEProcessS3(
+ prms->m_licenser,
+ prms->m_licensee,
+ prms->m_key,
+ &prms->m_hdoev,
+ prms->m_hdata,
+ prms->m_hn,
+ &prms->m_ho,
+ &prms->m_hdst
+ );
+ }
+
+ if (hdSucc == AKSC_CERTIFICATION_DENIED) {
+ AKMERROR;
+ return AKRET_PROC_FAIL;
+ }
+ if (hdSucc > 0) {
+ prms->HSUC_HO[prms->m_form] = prms->m_ho;
+ prms->m_ho32.u.x = (int32)prms->m_ho.u.x;
+ prms->m_ho32.u.y = (int32)prms->m_ho.u.y;
+ prms->m_ho32.u.z = (int32)prms->m_ho.u.z;
+
+ prms->HSUC_HDST[prms->m_form] = prms->m_hdst;
+ prms->HFLUCV_HREF[prms->m_form] = prms->m_hflucv.href;
+ prms->HSUC_HBASE[prms->m_form] = prms->m_hbase;
+ }
+
+ //Set decimator counter
+ prms->m_callcnt = hDecimator;
+ }
+ }
+ }
+
+ if (prms->m_en_doeplus == 1) {
+ // Calculate compensated vector
+ AKSC_DOEPlus_DistCompen(&have, prms->m_doep_var, &have);
+ }
+
+ // Subtract offset and normalize magnetic field vector.
+ aksc_ret = AKSC_VNorm(
+ &have,
+ &prms->m_ho,
+ &prms->m_hs,
+ AKSC_HSENSE_TARGET,
+ &hvec
+ );
+ if (aksc_ret == 0) {
+ AKMERROR;
+ AKMDEBUG(AKMDBG_DUMP,
+ "AKSC_VNorm failed.\n"
+ " have=%6d,%6d,%6d ho=%6d,%6d,%6d hs=%6d,%6d,%6d\n",
+ have.u.x, have.u.y, have.u.z,
+ prms->m_ho.u.x, prms->m_ho.u.y, prms->m_ho.u.z,
+ prms->m_hs.u.x, prms->m_hs.u.y, prms->m_hs.u.z);
+ ret |= AKRET_VNORM_ERROR;
+ return ret;
+ }
+
+ // hvec is updated only when VNorm function is succeeded.
+ prms->m_hvec = hvec;
+
+ // Bias of Uncalibrated Magnetic Field
+ prms->m_bias.u.x = (int32)(prms->m_ho.u.x) + prms->m_hbase.u.x;
+ prms->m_bias.u.y = (int32)(prms->m_ho.u.y) + prms->m_hbase.u.y;
+ prms->m_bias.u.z = (int32)(prms->m_ho.u.z) + prms->m_hbase.u.z;
+
+ //Convert layout from sensor to Android by using PAT number.
+ // Magnetometer
+ ConvertCoordinate(prms->m_hlayout, &prms->m_hvec);
+ // Bias of Uncalibrated Magnetic Field
+ ConvertCoordinate32(prms->m_hlayout, &prms->m_bias);
+ // Magnetic Field
+ prms->m_calib.u.x = prms->m_hvec.u.x;
+ prms->m_calib.u.y = prms->m_hvec.u.y;
+ prms->m_calib.u.z = prms->m_hvec.u.z;
+
+ // Uncalibrated Magnetic Field
+ prms->m_uncalib.u.x = (int32)(prms->m_calib.u.x) + prms->m_bias.u.x;
+ prms->m_uncalib.u.y = (int32)(prms->m_calib.u.y) + prms->m_bias.u.y;
+ prms->m_uncalib.u.z = (int32)(prms->m_calib.u.z) + prms->m_bias.u.z;
+
+ AKMDEBUG(AKMDBG_VECTOR,
+ "mag(dec)=%6d,%6d,%6d\n"
+ "maguc(dec),bias(dec)=%7ld,%7ld,%7ld,%7ld,%7ld,%7ld\n",
+ prms->m_calib.u.x, prms->m_calib.u.y, prms->m_calib.u.z,
+ prms->m_uncalib.u.x, prms->m_uncalib.u.y, prms->m_uncalib.u.z,
+ prms->m_bias.u.x, prms->m_bias.u.y, prms->m_bias.u.z);
+
+ //prms->m_uncalib.u.x = DISP_CONV_AKSCF(prms->m_uncalib.u.x);
+ //prms->m_uncalib.u.y = DISP_CONV_AKSCF(prms->m_uncalib.u.y);
+ //prms->m_uncalib.u.z = DISP_CONV_AKSCF(prms->m_uncalib.u.z);
+ //ALOGE("maguc(dec) = %d, %d, %d\n",
+ // prms->m_uncalib.u.x, prms->m_uncalib.u.y, prms->m_uncalib.u.z);
+
+ return AKRET_PROC_SUCCEED;
+}
+
+/*!
+ Calculate Yaw, Pitch, Roll angle.
+ m_hvec, m_avec and m_gvec should be Android coordination.
+ @return Always return #AKRET_PROC_SUCCEED.
+ @param[in,out] prms A pointer to a #AKSCPRMS structure.
+ */
+int16 CalcDirection(AKSCPRMS* prms)
+{
+ /* Conversion matrix from Android to SmartCompass coordination */
+ int16 preThe, swp;
+ const I16MATRIX hlayout = {{
+ 0, 1, 0,
+ -1, 0, 0,
+ 0, 0, 1}};
+ const I16MATRIX alayout = {{
+ 0,-1, 0,
+ 1, 0, 0,
+ 0, 0,-1}};
+
+ preThe = prms->m_theta;
+
+ prms->m_d6dRet = AKSC_DirectionS3(
+ prms->m_licenser,
+ prms->m_licensee,
+ prms->m_key,
+ &prms->m_hvec,
+ &prms->m_avec,
+ &prms->m_dvec,
+ &hlayout,
+ &alayout,
+ &prms->m_theta,
+ &prms->m_delta,
+ &prms->m_hr,
+ &prms->m_hrhoriz,
+ &prms->m_ar,
+ &prms->m_phi180,
+ &prms->m_phi90,
+ &prms->m_eta180,
+ &prms->m_eta90,
+ &prms->m_mat,
+ &prms->m_quat);
+
+ prms->m_theta = AKSC_ThetaFilter(
+ prms->m_theta,
+ preThe,
+ THETAFILTER_SCALE);
+
+ if (prms->m_d6dRet == AKSC_CERTIFICATION_DENIED) {
+ AKMERROR;
+ return AKRET_PROC_FAIL;
+ }
+
+ if (prms->m_d6dRet != 3) {
+ AKMDEBUG(AKMDBG_DUMP,
+ "AKSC_Direction6D failed (0x%02x).\n"
+ " hvec=%d,%d,%d avec=%d,%d,%d dvec=%d,%d,%d\n",
+ prms->m_d6dRet,
+ prms->m_hvec.u.x, prms->m_hvec.u.y, prms->m_hvec.u.z,
+ prms->m_avec.u.x, prms->m_avec.u.y, prms->m_avec.u.z,
+ prms->m_dvec.u.x, prms->m_dvec.u.y, prms->m_dvec.u.z);
+ }
+
+ /* Convert Yaw, Pitch, Roll angle to Android coordinate system */
+ if (prms->m_d6dRet & 0x02) {
+ /*
+ from: AKM coordinate, AKSC units
+ to : Android coordinate, AKSC units. */
+ prms->m_eta180 = -prms->m_eta180;
+ prms->m_eta90 = -prms->m_eta90;
+ /*
+ from: AKM coordinate, AKSC units
+ to : Android coordinate, AKSC units. */
+ swp = prms->m_quat.u.x;
+ prms->m_quat.u.x = prms->m_quat.u.y;
+ prms->m_quat.u.y = -(swp);
+ prms->m_quat.u.z = -(prms->m_quat.u.z);
+
+ AKMDEBUG(AKMDBG_D6D, "AKSC_Direction6D (0x%02x):\n"
+ " Yaw, Pitch, Roll=%6.1f,%6.1f,%6.1f\n",
+ prms->m_d6dRet,
+ DISP_CONV_Q6F(prms->m_theta),
+ DISP_CONV_Q6F(prms->m_phi180),
+ DISP_CONV_Q6F(prms->m_eta90));
+ }
+
+ return AKRET_PROC_SUCCEED;
+}
+
+int16 SimpleCalibration(AKSCPRMS* prms)
+{
+ /* Boot up device */
+ if (AKD_AccSetEnable(AKD_ENABLE) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKRET_PROC_FAIL;
+ }
+ if (AKD_AccSetDelay(AKMD_ACC_INTERVAL) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKRET_PROC_FAIL;
+ }
+
+ /* Wait for a while until device boot up */
+ msleep(100);
+
+ AKD_GetAccelerationOffset(prms->m_AO.v);
+
+ if (AKD_AccSetEnable(AKD_DISABLE) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKRET_PROC_FAIL;
+ }
+
+ return AKRET_PROC_SUCCEED;
+}
+
+
+
+/*!
+ Calculate angular speed.
+ m_hvec and m_avec should be Android coordination.
+ @return
+ @param[in,out] prms A pointer to a #AKSCPRMS structure.
+ */
+int16 CalcAngularRate(AKSCPRMS* prms)
+{
+ /* Conversion matrix from Android to SmartCompass coordination */
+ const I16MATRIX hlayout = {{
+ 0, 1, 0,
+ -1, 0, 0,
+ 0, 0, 1}};
+ const I16MATRIX alayout = {{
+ 0,-1, 0,
+ 1, 0, 0,
+ 0, 0,-1}};
+
+
+ int16vec tmp_hvec;
+ int16 aksc_ret;
+ int32 swp;
+
+ // Subtract offset from non-averaged value.
+ aksc_ret = AKSC_VNorm(
+ &prms->m_hdata[0],
+ &prms->m_ho,
+ &prms->m_hs,
+ AKSC_HSENSE_TARGET,
+ &tmp_hvec
+ );
+ if (aksc_ret == 0) {
+ AKMERROR;
+ AKMDEBUG(AKMDBG_DUMP,"AKSC_VNorm failed.\n"
+ " have=%6d,%6d,%6d ho=%6d,%6d,%6d hs=%6d,%6d,%6d\n",
+ prms->m_hdata[0].u.x, prms->m_hdata[0].u.y, prms->m_hdata[0].u.z,
+ prms->m_ho.u.x, prms->m_ho.u.y, prms->m_ho.u.z,
+ prms->m_hs.u.x, prms->m_hs.u.y, prms->m_hs.u.z);
+ return AKRET_PROC_FAIL;
+ }
+
+ // Convert to Android coordination
+ ConvertCoordinate(prms->m_hlayout, &tmp_hvec);
+
+ prms->m_pgRet = AKSC_PseudoGyro(
+ &prms->m_pgcond,
+ prms->m_pgdt,
+ &tmp_hvec,
+ &prms->m_avec,
+ &hlayout,
+ &alayout,
+ &prms->m_pgvar,
+ &prms->m_pgout,
+ &prms->m_pgquat,
+ &prms->m_pgGravity,
+ &prms->m_pgLinAcc
+ );
+
+ if(prms->m_pgRet != 1) {
+ AKMERROR;
+ AKMDEBUG(AKMDBG_DUMP,"AKSC_PseudoGyro failed: dt=%6.2f\n"
+ " hvec=%8.2f,%8.2f,%8.2f avec=%8.5f,%8.5f,%8.5f\n",
+ prms->m_pgdt/16.0f,
+ tmp_hvec.u.x/16.0f, tmp_hvec.u.y/16.0f, tmp_hvec.u.z/16.0f,
+ prms->m_avec.u.x/720.0f, prms->m_avec.u.y/720.0f, prms->m_avec.u.z/720.0f);
+ return AKRET_PROC_FAIL;
+ } else {
+ /* Convertion:
+ from: AKM coordinate
+ to : Android coordinate
+ Unit conversion will be done in HAL. */
+ swp = prms->m_pgout.u.x;
+ prms->m_pgout.u.x = -(prms->m_pgout.u.y);
+ prms->m_pgout.u.y = swp;
+ prms->m_pgout.u.z = prms->m_pgout.u.z;
+
+ swp = prms->m_pgquat.u.x;
+ prms->m_pgquat.u.x = prms->m_pgquat.u.y;
+ prms->m_pgquat.u.y = -(swp);
+ prms->m_pgquat.u.z = -(prms->m_pgquat.u.z);
+
+ swp = prms->m_pgGravity.u.x;
+ prms->m_pgGravity.u.x = prms->m_pgGravity.u.y;
+ prms->m_pgGravity.u.y = -(swp);
+ prms->m_pgGravity.u.z = -(prms->m_pgGravity.u.z);
+
+ swp = prms->m_pgLinAcc.u.x;
+ prms->m_pgLinAcc.u.x = prms->m_pgLinAcc.u.y;
+ prms->m_pgLinAcc.u.y = -(swp);
+ prms->m_pgLinAcc.u.z = -(prms->m_pgLinAcc.u.z);
+
+ AKMDEBUG(AKMDBG_PGYR, "AKSC_PseudoGyro:\n"
+ " dt=%6.2f rate=%8.2f,%8.2f,%8.2f quat=%8.5f,%8.5f,%8.5f,%8.5f\n",
+ prms->m_pgdt/16.0f,
+ prms->m_pgout.u.x/64.0f,
+ prms->m_pgout.u.y/64.0f,
+ prms->m_pgout.u.z/64.0f,
+ prms->m_pgquat.u.x/16384.0f,
+ prms->m_pgquat.u.y/16384.0f,
+ prms->m_pgquat.u.z/16384.0f,
+ prms->m_pgquat.u.w/16384.0f);
+ }
+
+ return AKRET_PROC_SUCCEED;
+}
+
diff --git a/mpu/akm8963/Measure.h b/mpu/akm8963/Measure.h
new file mode 100755
index 0000000..83494ea
--- /dev/null
+++ b/mpu/akm8963/Measure.h
@@ -0,0 +1,116 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKMD_INC_MEASURE_H
+#define AKMD_INC_MEASURE_H
+
+// Include files for SmartCompass Library.
+#include "AKCompass.h"
+#include "misc.h"
+
+/*** Constant definition ******************************************************/
+#define AKRET_PROC_SUCCEED 0x00 /*!< The process has been successfully done. */
+#define AKRET_FORMATION_CHANGED 0x01 /*!< The formation is changed */
+#define AKRET_DATA_READERROR 0x02 /*!< Data read error occurred. */
+#define AKRET_DATA_OVERFLOW 0x04 /*!< Data overflow occurred. */
+#define AKRET_OFFSET_OVERFLOW 0x08 /*!< Offset values overflow. */
+#define AKRET_HBASE_CHANGED 0x10 /*!< hbase was changed. */
+#define AKRET_HFLUC_OCCURRED 0x20 /*!< A magnetic field fluctuation occurred. */
+#define AKRET_VNORM_ERROR 0x40 /*!< AKSC_VNorm error. */
+#define AKRET_PROC_FAIL 0x80 /*!< The process failes. */
+
+
+/*** Type declaration *********************************************************/
+typedef int16(*OPEN_FORM)(void);
+typedef void(*CLOSE_FORM)(void);
+typedef int16(*CHECK_FORM)(void);
+
+typedef struct _FORM_CLASS {
+ OPEN_FORM open;
+ CLOSE_FORM close;
+ CHECK_FORM check;
+} FORM_CLASS;
+
+/*** Global variables *********************************************************/
+
+/*** Prototype of function ****************************************************/
+void RegisterFormClass(
+ FORM_CLASS* pt
+);
+
+void InitAKSCPRMS(
+ AKSCPRMS* prms
+);
+
+void SetDefaultPRMS(
+ AKSCPRMS* prms
+);
+
+int16 GetInterval(
+ AKMD_LOOP_TIME* acc_mes,
+ AKMD_LOOP_TIME* mag_mes,
+ AKMD_LOOP_TIME* acc_acq,
+ AKMD_LOOP_TIME* mag_acq,
+ AKMD_LOOP_TIME* fusion_acq,
+ int16* hdoe_dec
+);
+
+int SetLoopTime(
+ AKMD_LOOP_TIME* tm,
+ int64_t execTime,
+ int64_t* minDuration
+);
+
+int16 ReadFUSEROM(
+ AKSCPRMS* prms
+);
+
+int16 Init_Measure(
+ AKSCPRMS* prms
+);
+
+void MeasureSNGLoop(
+ AKSCPRMS* prms
+);
+
+int16 GetMagneticVector(
+ const int16 bData[],
+ AKSCPRMS* prms,
+ const int16 curForm,
+ const int16 hDecimator
+);
+
+int16 CalcDirection(
+ AKSCPRMS* prms
+);
+
+int16 SimpleCalibration(
+ AKSCPRMS* prms
+);
+
+int16 CalcAngularRate(
+ AKSCPRMS* prms
+);
+
+#endif
+
diff --git a/mpu/akm8963/custom_log.h b/mpu/akm8963/custom_log.h
new file mode 100755
index 0000000..ca4b270
--- /dev/null
+++ b/mpu/akm8963/custom_log.h
@@ -0,0 +1,163 @@
+/* --------------------------------------------------------------------------------------------------------
+ * Copyright(C), 2009-2010, Fuzhou Rockchip Co., Ltd. All Rights Reserved.
+ *
+ * File: custom_log.h
+ *
+ * Desc: ChenZhen 偏好的, 对 Android log 机构的定制配置.
+ *
+ * -----------------------------------------------------------------------------------
+ * < 习语 和 缩略语 > :
+ *
+ * -----------------------------------------------------------------------------------
+ *
+ * Usage: 调用本 log 机构的 .c or .h 文件, 若要使能这里的 log 机制,
+ * 则必须在 inclue 本文件之前, "#define ENABLE_DEBUG_LOG" 先.
+ *
+ * 同 log.h 一样, client 文件在 inclue 本文件之前, "最好" #define LOG_TAG <module_tag>
+ *
+ * Note:
+ *
+ * Author: ChenZhen
+ *
+ * --------------------------------------------------------------------------------------------------------
+ * Version:
+ * v1.0
+ * --------------------------------------------------------------------------------------------------------
+ * Log:
+ ----Tue Mar 02 21:30:33 2010 v.10
+ *
+ * --------------------------------------------------------------------------------------------------------
+ */
+
+
+#ifndef __CUSTOM_LOG_H__
+#define __CUSTOM_LOG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Include Files
+ * ---------------------------------------------------------------------------------------------------------
+ */
+#include <cutils/log.h>
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Macros Definition
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+/** 若下列 macro 有被定义, 才 使能 log 输出 : 参见 "Usage". */
+// #define ENABLE_DEBUG_LOG
+
+/** 是否 log 源文件 路径信息. */
+#define LOG_FILE_PATH
+
+/*-----------------------------------*/
+
+#if PLATFORM_SDK_VERSION >= 16
+#define LOGV(fmt,args...) ALOGV(fmt,##args)
+#define LOGD(fmt,args...) ALOGD(fmt,##args)
+#define LOGI(fmt,args...) ALOGI(fmt,##args)
+#define LOGW(fmt,args...) ALOGW(fmt,##args)
+#define LOGE(fmt,args...) ALOGE(fmt,##args)
+#define LOGE_IF(cond,fmt,args...) ALOGE_IF(cond,fmt,##args)
+#endif
+
+#ifdef ENABLE_DEBUG_LOG
+
+#ifdef LOG_FILE_PATH
+#define D(fmt, args...) \
+ { LOGD("[File] : %s; [Line] : %d; [Func] : %s() ; " fmt, __FILE__, __LINE__, __FUNCTION__, ## args); }
+#else
+#define D(fmt, args...) \
+ { LOGD("[Line] : %d; [Func] : %s() ; " fmt, __LINE__, __FUNCTION__, ## args); }
+#endif
+
+#else
+#define D(...) ((void)0)
+#endif
+
+
+/*-----------------------------------*/
+
+#ifdef ENABLE_DEBUG_LOG
+
+#ifdef LOG_FILE_PATH
+#define I(fmt, args...) \
+ { LOGI("[File] : %s; [Line] : %d; [Func] : %s() ; ! Info : " fmt, __FILE__, __LINE__, __FUNCTION__, ## args); }
+#else
+#define I(fmt, args...) \
+ { LOGI("[Line] : %d; [Func] : %s() ; ! Info : " fmt, __LINE__, __FUNCTION__, ## args); }
+#endif
+#else
+#define I(...) ((void)0)
+#endif
+
+/*-----------------------------------*/
+#ifdef ENABLE_DEBUG_LOG
+#ifdef LOG_FILE_PATH
+#define W(fmt, args...) \
+ { LOGW("[File] : %s; [Line] : %d; [Func] : %s() ; !! Warning : " fmt, __FILE__, __LINE__, __FUNCTION__, ## args); }
+#else
+#define W(fmt, args...) \
+ { LOGW("[Line] : %d; [Func] : %s() ; !! Warning : " fmt, __LINE__, __FUNCTION__, ## args); }
+#endif
+#else
+#define W(...) ((void)0)
+#endif
+
+/*-----------------------------------*/
+#ifdef ENABLE_DEBUG_LOG
+#ifdef LOG_FILE_PATH
+#define E(fmt, args...) \
+ { LOGE("[File] : %s; [Line] : %d; [Func] : %s() ; !!! Error : " fmt, __FILE__, __LINE__, __FUNCTION__, ## args); }
+#else
+#define E(fmt, args...) \
+ { LOGE("[Line] : %d; [Func] : %s() ; !!! Error : " fmt, __LINE__, __FUNCTION__, ## args); }
+#endif
+#else
+#define E(...) ((void)0)
+#endif
+
+/*-----------------------------------*/
+/**
+ * 若程序重复运行到当前位置的次数等于 threshold 或者第一次到达, 则打印指定的 log 信息.
+ */
+#ifdef ENABLE_DEBUG_LOG
+#define D_WHEN_REPEAT(threshold, fmt, args...) \
+ do { \
+ static int count = 0; \
+ if ( 0 == count || (count++) == threshold ) { \
+ D(fmt, ##args); \
+ count = 1; \
+ } \
+ } while (0)
+#else
+#define D_WHEN_REPEAT(...) ((void)0)
+#endif
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Types and Structures Definition
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Global Functions' Prototype
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+
+/* ---------------------------------------------------------------------------------------------------------
+ * Inline Functions Implementation
+ * ---------------------------------------------------------------------------------------------------------
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUSTOM_LOG_H__ */
+
diff --git a/mpu/akm8963/libSmartCompass/AKCertification.h b/mpu/akm8963/libSmartCompass/AKCertification.h
new file mode 100755
index 0000000..8fb9d1e
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/AKCertification.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * $Id: AKCertification.h 98 2012-12-04 04:30:13Z yamada.rj $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKSC_INC_AKCERTIFICATION_H
+#define AKSC_INC_AKCERTIFICATION_H
+
+//========================= Type declaration ===========================//
+#define AKSC_CI_MAX_CHARSIZE 16
+#define AKSC_CI_MAX_KEYSIZE 16
+#define AKSC_CERTIFICATION_CERTIFICATED ((int16)0x0001)
+#define AKSC_CERTIFICATION_DENIED ((int16)0x8000)
+
+//========================= Constant definition =========================//
+
+//========================= Prototype of Function =======================//
+
+#endif
diff --git a/mpu/akm8963/libSmartCompass/AKConfigure.h b/mpu/akm8963/libSmartCompass/AKConfigure.h
new file mode 100755
index 0000000..0395ccd
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/AKConfigure.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+ *
+ * $Id: AKConfigure.h 116 2012-12-21 01:50:11Z suzuki.thj $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKSC_INC_AKCONFIG_H
+#define AKSC_INC_AKCONFIG_H
+
+//========================= Language configuration ===================//
+#if defined(__cplusplus)
+#define AKLIB_C_API_START extern "C" {
+#define AKLIB_C_API_END }
+#else
+#define AKLIB_C_API_START
+#define AKLIB_C_API_END
+#endif
+
+//========================= Debug configuration ======================//
+#if defined(_DEBUG) || defined(DEBUG)
+#define AKSC_TEST_MODE
+#endif
+#if defined(AKSC_TEST_MODE)
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+//========================= Arithmetic Cast ==========================//
+#define AKSC_ARITHMETIC_CAST
+
+//======================== Arithmetic configuration ==================//
+// If this definition is uncommented, double type is used for
+// mathematical functions and AK's floating point type "AKSC_FLOAT".
+// Otherwise float type is used for theirs.
+// This configuration does not changes floating point calculation used
+// in AK's functions. This is intended to cut down memory.
+//#define AKSC_MATH_DOUBLE
+
+//======================== Constant value configuration ==============//
+// If this definition is uncommented, use FLT_EPSILON, which is
+// defined in <float.h>. Otherwise AK's defined value or 0 is used.
+#define AKSC_USE_STD_FLOAT
+
+//======================== Use AKM's type definition =================//
+// If this definition is uncommented, use type definition, which is
+// defined in <stdint.h>. Otherwise AK's definition is used
+//#define AKSC_USE_STD_TYPES
+
+// When AK's definition is used (i.e. AKSC_USE_STD_TYPES is commented
+// out), int32 type depends on the system architecture. If the system
+// is 64bit architecture, please uncomment below.
+#define AKSC_ARCH_64BIT
+
+#endif
+
diff --git a/mpu/akm8963/libSmartCompass/AKDOEPlus.h b/mpu/akm8963/libSmartCompass/AKDOEPlus.h
new file mode 100755
index 0000000..7d38354
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/AKDOEPlus.h
@@ -0,0 +1,68 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKSC_AKDOEPLUS_H
+#define AKSC_AKDOEPLUS_H
+
+#include "AKMDevice.h"
+#include "AKMDeviceF.h"
+
+//========================= Constant definition ==============================//
+#define AKSC_DOEP_SIZE 16 // array size of save data
+
+//========================= type definition ==================================//
+typedef struct _AKSC_DOEPVAR AKSC_DOEPVAR; // DOEPlus parameters struct
+
+//========================= Prototype of Function ============================//
+AKLIB_C_API_START
+int16 AKSC_GetSizeDOEPVar(void); //(o) : size of DOEPlus parameters
+
+void AKSC_InitDOEPlus(
+ AKSC_DOEPVAR *var //(o) : pointer of DOEPlus parameters struct
+);
+
+void AKSC_SaveDOEPlus(
+ const AKSC_DOEPVAR *var, //(i) : pointer of DOEPlus parameters struct
+ AKSC_FLOAT data[] //(o) : saved data
+);
+
+int16 AKSC_LoadDOEPlus( //(o) : lv of save data
+ const AKSC_FLOAT data[], //(i) : saved data
+ AKSC_DOEPVAR *var //(i/o) : pointer of DOEPlus parameters struct
+);
+
+int16 AKSC_DOEPlus( //(o) : compensation parameter is updated(1) or not(0)
+ const int16vec *i16v, //(i) : new magnetic vector
+ AKSC_DOEPVAR *var, //(i/o) : pointer of DOEPlus parameters struct
+ int16 *lv //(o) : DOEPlus lv
+);
+
+void AKSC_DOEPlus_DistCompen(
+ const int16vec *ivec, //(i) : distorted vector
+ const AKSC_DOEPVAR *var, //(i) : pointer of DOEPlus parameters struct
+ int16vec *ovec //(o) : compensated vector
+);
+
+AKLIB_C_API_END
+
+#endif
diff --git a/mpu/akm8963/libSmartCompass/AKDecomp.h b/mpu/akm8963/libSmartCompass/AKDecomp.h
new file mode 100755
index 0000000..1e811d0
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/AKDecomp.h
@@ -0,0 +1,61 @@
+/******************************************************************************
+ *
+ * $Id: AKDecomp.h 98 2012-12-04 04:30:13Z yamada.rj $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKSC_INC_AKDECOMP_H
+#define AKSC_INC_AKDECOMP_H
+
+#include "AKMDevice.h"
+
+//========================= Type declaration ===========================//
+
+//========================= Constant definition =========================//
+#define AKSC_HSENSE_TARGET 833 // Target sensitivity for magnetic sensor
+
+//========================= Prototype of Function =======================//
+AKLIB_C_API_START
+
+void AKSC_InitDecomp(
+ int16vec hdata[] //(i/o) : Magnetic data. index 0 is earlier data. The size of hdata must be HDATA_SIZE.
+);
+
+int16 AKSC_DecompS3( //(o) : (0)abend, (1)normally calculated
+ const int16 device, //(i) : Device part number (4 digits)
+ const int16 bdata[],//(i) : Block data
+ const int16 hNave, //(i) : The number of magnetic data to be averaged. hNave must be 0,1,2,4,8,16,32
+ const int16vec* asa, //(i) : Sensitivity adjustment value(the value read from Fuse ROM)
+ const uint8* pdc, //(i) : Reserved for debug operation.
+ int16vec hdata[],//(i/o) : Magnetic data. index 0 is earlier data.
+ int32vec* hbase, //(i/o) : Magnetic data base.
+ int16* hn, //(o) : The number of magnetic data, output 1.
+ int16vec* have, //(o) : Average of magnetic data
+ int16* temperature,//(o): Temperature in celcius degree.
+ int16* dor, //(o) : 0;normal data, 1;data overrun is occurred.
+ int16* derr, //(o) : 0;normal data, 1;data read error occurred.
+ int16* hofl, //(o) : 0;normal data, 1;data overflow occurred.
+ int16* cb, //(o) : 0;hbase is not changed, 1;hbase is changed.
+ int16* dc //(o) : Reserved for debug operation.
+);
+
+AKLIB_C_API_END
+
+#endif
diff --git a/mpu/akm8963/libSmartCompass/AKDirection6D.h b/mpu/akm8963/libSmartCompass/AKDirection6D.h
new file mode 100755
index 0000000..97fe68b
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/AKDirection6D.h
@@ -0,0 +1,79 @@
+/******************************************************************************
+ *
+ * $Id: AKDirection6D.h 116 2012-12-21 01:50:11Z suzuki.thj $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKSC_INC_AKDIRECTION6D_H
+#define AKSC_INC_AKDIRECTION6D_H
+
+#include "AKMDevice.h"
+
+
+//========================= Constant definition =========================//
+
+//========================= Type declaration ===========================//
+
+//========================= Prototype of Function =======================//
+AKLIB_C_API_START
+int16 AKSC_VNorm(
+ const int16vec* v, //(i) : Vector
+ const int16vec* o, //(i) : Offset
+ const int16vec* s, //(i) : Amplitude
+ const int16 tgt, //(i) : Target sensitivity value
+ int16vec* nv //(o) : Resulted normalized vector
+);
+
+void AKSC_SetLayout( // :
+ int16vec* v, //(i/o) : Magnetic/Gravity vector data
+ const I16MATRIX* layout //(i) : Layout matrix
+);
+
+int16 AKSC_DirectionS3(
+ const uint8 licenser[], //(i) : Licenser
+ const uint8 licensee[], //(i) : Licensee
+ const int16 key[], //(i) : Key
+ const int16vec* h, //(i) : Geomagnetic vector (offset and sensitivity are compensated)
+ const int16vec* a, //(i) : Acceleration vector (offset and sensitivity are compensated)
+ const int16vec* dvec, //(i) : A vector to define reference axis of the azimuth on the terminal coordinate system
+ const I16MATRIX* hlayout, //(i) : Layout matrix for geomagnetic vector
+ const I16MATRIX* alayout, //(i) : Layout matrix for acceleration vector
+ int16* theta, //(o) : Azimuth direction (degree)
+ int16* delta, //(o) : The inclination (degree)
+ int16* hr, //(o) : Geomagnetic vector size
+ int16* hrhoriz, //(o) : Horizontal element of geomagnetic vector
+ int16* ar, //(o) : Acceleration vector size
+ int16* phi180, //(o) : Pitch angle (-180 to +180 degree)
+ int16* phi90, //(o) : Pitch angle (-90 to +90 degree)
+ int16* eta180, //(o) : Roll angle (-180 to +180 degree)
+ int16* eta90, //(o) : Roll angle (-90 to +90 degree)
+ I16MATRIX* mat, //(o) : Rotation matrix
+ I16QUAT* quat //(o) : Rotation Quaternion
+);
+
+int16 AKSC_ThetaFilter( //(o) : theta filterd
+ const int16 the, //(i) : current theta(Q6)
+ const int16 pre_the, //(i) : previous theta(Q6)
+ const int16 scale //(i) : Q12.
+);
+AKLIB_C_API_END
+
+#endif
+
diff --git a/mpu/akm8963/libSmartCompass/AKHDOE.h b/mpu/akm8963/libSmartCompass/AKHDOE.h
new file mode 100755
index 0000000..77d1793
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/AKHDOE.h
@@ -0,0 +1,102 @@
+/******************************************************************************
+ *
+ * $Id: AKHDOE.h 98 2012-12-04 04:30:13Z yamada.rj $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKSC_INC_AKHDOE_H
+#define AKSC_INC_AKHDOE_H
+
+#include "AKMDevice.h"
+
+//========================= Constant definition =========================//
+#define AKSC_NUM_HCOND 2 // The number of HCOND. e.g. HCOND[0];for small magnetism size, HCOND[1];for normal magnetism size
+#define AKSC_MAX_HDOE_LEVEL 3 // The maximum DOE level
+#define AKSC_HBUF_SIZE 32 // Buffer size for DOE
+#define AKSC_HOBUF_SIZE 16 // Offset buffer size for DOE
+
+//========================= Macro definition =========================//
+#define AKSC_InitHDOEProcPrmsS3(hdoev, idxhcond, ho, hdst) zzAKSC_InitHDOEProcPrmsS3((hdoev), 0, 0, (idxhcond), (ho), (hdst))
+#define AKSC_HDOEProcessS3(licenser, licensee, key, hdoev, hdata, hn, ho, hdst) zzAKSC_HDOEProcessS3((licenser), (licensee), (key), (hdoev), (hdata), (hn), 0, 1, (ho), (hdst))
+
+//========================= Type declaration ===========================//
+typedef enum _AKSC_HDFI{
+ AKSC_HDFI_SMA = 0, // Low magnetic intensity
+ AKSC_HDFI_NOR = 1 // Normal magnetic intensity
+} AKSC_HDFI;
+
+typedef enum _AKSC_HDST{
+ AKSC_HDST_UNSOLVED = 0, // Offset is not determined.
+ AKSC_HDST_L0 = 1, // Offset has been determined once or more with Level0 parameter
+ AKSC_HDST_L1 = 2, // Offset has been determined once or more with Level1 parameter
+ AKSC_HDST_L2 = 3 // Offset has been determined once or more with Level2 parameter
+} AKSC_HDST;
+
+typedef struct _AKSC_HDOEVAR{ // Variables necessary for DOE calculation
+ void** HTH; // [AKSC_NUM_HCOND][AKSC_MAX_HDOE_LEVEL]
+ int16vec hbuf[AKSC_HBUF_SIZE]; // Buffer for measurement values
+ int16vec hobuf[AKSC_HOBUF_SIZE]; // Buffer for offsets
+ int16vec hvobuf[AKSC_HOBUF_SIZE]; // Buffer for successful offsets
+ int16 hdoeCnt; // DOE counter
+ int16 hdoeLv; // HDOE level
+ int16 hrdoe; // Geomagnetic vector size
+ int16 hthIdx; // Index of HTH. This value can be from 0 to AKSC_NUM_HCOND-1
+
+ void** HTHHR; // [AKSC_NUM_HCOND or 1][AKSC_MAX_HDOE_LEVEL or 1]
+ int16vec hobufHR[AKSC_HOBUF_SIZE]; // Buffer for offsets to check the size of geomagnetism
+ int16 hrdoeHR;
+
+ int16 reserved; // Reserve
+} AKSC_HDOEVAR;
+
+//========================= Prototype of Function =======================//
+AKLIB_C_API_START
+void zzAKSC_InitHDOEProcPrmsS3(
+ AKSC_HDOEVAR* hdoev, //(i/o) : A set of variables
+ void** HTH, //(i) : Only 0 is acceptable
+ void** HTHHR, //(i) : Only 0 is acceptable
+ const int16 idxhcond, //(i) : Initial index of criteria
+ const int16vec* ho, //(i) : Initial offset
+ const AKSC_HDST hdst //(i) : Initial DOE level
+);
+
+int16 zzAKSC_HDOEProcessS3( //(o) : Estimation success(1 ~ hn), failure(0)
+ const uint8 licenser[], //(i) : Licenser
+ const uint8 licensee[], //(i) : Licensee
+ const int16 key[], //(i) : Key
+ AKSC_HDOEVAR* hdoev, //(i/o) : A set of variables
+ const int16vec hdata[], //(i) : Vectors of data
+ const int16 hn, //(i) : The number of data (the value must be less than the size of hdata array)
+ const int16 linkHthHRIdxToHth,//(i) : (1)link hthHR[idx][] index to hth[idx][]. (0) use only hthHR[0][].
+ const int16 linkHthHRLvlToHth,//(i) : (1)link hthHR[][lvl] level to hth[][lvl]. (0) use only hthHR[][0].
+ int16vec* ho, //(i/o) : Offset
+ AKSC_HDST* hdst //(o) : HDOE status
+);
+
+void AKSC_SetHDOELevel(
+ AKSC_HDOEVAR* hdoev, //(i/o) : A set of variables
+ const int16vec* ho, //(i) : Initial offset
+ const AKSC_HDST hdst, //(i) : DOE level
+ const int16 initBuffer //(i) : If this flag is 0, don't clear buffer
+);
+AKLIB_C_API_END
+
+#endif
+
diff --git a/mpu/akm8963/libSmartCompass/AKHFlucCheck.h b/mpu/akm8963/libSmartCompass/AKHFlucCheck.h
new file mode 100755
index 0000000..bbb8382
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/AKHFlucCheck.h
@@ -0,0 +1,61 @@
+/******************************************************************************
+ *
+ * $Id: AKHFlucCheck.h 98 2012-12-04 04:30:13Z yamada.rj $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKSC_INC_AKHFLUCCHECK_H
+#define AKSC_INC_AKHFLUCCHECK_H
+
+#include "AKMDevice.h"
+
+//========================= Constant definition =========================//
+
+//========================= Type declaration ===========================//
+typedef struct _AKSC_HFLUCVAR {
+ int16vec href; // Basis of magnetic field
+ int16 th; // The range of fluctuation
+}AKSC_HFLUCVAR;
+
+//========================= Prototype of Function =======================//
+AKLIB_C_API_START
+
+int16 AKSC_InitHFlucCheck(
+ AKSC_HFLUCVAR* hflucv, //(o) : A set of criteria to be initialized
+ const int16vec* href, //(i) : Initial value of basis
+ const int16 th //(i) : The range of fluctuation
+);
+
+int16 AKSC_HFlucCheck(
+ AKSC_HFLUCVAR* hflucv, //(i/o) : A set of criteria
+ const int16vec* hdata //(i) : Current magnetic vector
+);
+
+void AKSC_TransByHbase(
+ const int32vec* prevHbase, //(i) : Previous hbase
+ const int32vec* hbase, //(i) : Current hbase
+ int16vec* ho, //(i/o) : Offset value based on current hbase(16bit)
+ int32vec* ho32, //(i/o) : Offset value based on current hbase(32bit)
+ int16* overflow //(o) : 0;success, 1;ho overflow.
+);
+
+AKLIB_C_API_END
+
+#endif
diff --git a/mpu/akm8963/libSmartCompass/AKMDevice.h b/mpu/akm8963/libSmartCompass/AKMDevice.h
new file mode 100755
index 0000000..ce4b62e
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/AKMDevice.h
@@ -0,0 +1,114 @@
+/******************************************************************************
+ *
+ * $Id: AKMDevice.h 116 2012-12-21 01:50:11Z suzuki.thj $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKSC_INC_AKMDEVICE_H
+#define AKSC_INC_AKMDEVICE_H
+
+#include "AKConfigure.h"
+
+//========================= Compiler configuration ======================//
+#ifdef AKSC_ARITHMETIC_CAST
+#define I32MUL(x,y) ((int32)(x)*(int32)(y))
+#define UI32MUL(x,y) ((uint32)(x)*(uint32)(y))
+#else
+#define I32MUL(x,y) ((x)*(y))
+#define UI32MUL(x,y) ((x)*(y))
+#endif
+
+//========================= Constant definition =========================//
+#define AKSC_HDATA_SIZE 32
+
+//========================= Type declaration ===========================//
+#ifdef AKSC_USE_STD_TYPES
+#include <stdint.h>
+typedef uint8_t uint8;
+typedef int16_t int16;
+typedef uint16_t uint16;
+typedef int32_t int32;
+typedef uint32_t uint32;
+
+#else //AKSC_USE_STD_TYPES
+typedef unsigned char uint8;
+typedef short int16;
+typedef unsigned short uint16;
+#ifdef AKSC_ARCH_64BIT
+typedef int int32;
+typedef unsigned int uint32;
+#else //AKSC_ARCH_64BIT
+typedef long int32;
+typedef unsigned long uint32;
+#endif //AKSC_ARCH_64BIT
+#endif //AKSC_USE_STD_TYPES
+
+//========================= Vectors =====================================//
+typedef union _int16vec{ // Three-dimensional vector constructed of signed 16 bits fixed point numbers
+ struct {
+ int16 x;
+ int16 y;
+ int16 z;
+ }u;
+ int16 v[3];
+} int16vec;
+
+typedef union _int32vec{ // Three-dimensional vector constructed of signed 32 bits fixed point numbers
+ struct{
+ int32 x;
+ int32 y;
+ int32 z;
+ } u;
+ int32 v[3];
+} int32vec;
+
+//========================= Matrix ======================================//
+typedef union _I16MATRIX{
+ struct {
+ int16 _11, _12, _13;
+ int16 _21, _22, _23;
+ int16 _31, _32, _33;
+ }u;
+ int16 m[3][3];
+} I16MATRIX;
+
+typedef union _I32MATRIX {
+ struct {
+ int32 _11, _12, _13;
+ int32 _21, _22, _23;
+ int32 _31, _32, _33;
+ } u;
+ int32 m[3][3];
+} I32MATRIX;
+
+//========================= Quaternion ===================================//
+// Quaternion constructed of signed 16 bits fixed point numbers
+typedef union _I16QUAT{
+ struct {
+ int16 w;
+ int16 x;
+ int16 y;
+ int16 z;
+ }u;
+ int16 q[4];
+} I16QUAT;
+
+#endif
+
diff --git a/mpu/akm8963/libSmartCompass/AKMDeviceF.h b/mpu/akm8963/libSmartCompass/AKMDeviceF.h
new file mode 100755
index 0000000..b18645d
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/AKMDeviceF.h
@@ -0,0 +1,110 @@
+/******************************************************************************
+ *
+ * $Id: AKMDeviceF.h 98 2012-12-04 04:30:13Z yamada.rj $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKSC_INC_AKMDEVICEF_H
+#define AKSC_INC_AKMDEVICEF_H
+
+#include "AKConfigure.h"
+
+#ifdef AKSC_MATH_DOUBLE
+ typedef double AKSC_FLOAT;
+#else
+ typedef float AKSC_FLOAT;
+#endif
+
+#ifdef AKSC_USE_STD_FLOAT
+ #include <float.h>
+ #ifdef AKSC_MATH_DOUBLE
+ #define AKSC_EPSILON DBL_EPSILON
+ #define AKSC_FLTMAX DBL_MAX
+ #else
+ #define AKSC_EPSILON FLT_EPSILON
+ #define AKSC_FLTMAX FLT_MAX
+ #endif
+#else
+ #ifdef AKSC_MATH_DOUBLE
+ #define AKSC_EPSILON ((AKSC_FLOAT)2.2204460492503131e-016)
+ #define AKSC_FLTMAX ((AKSC_FLOAT)1.7976931348623158e+308)
+ #else
+ #define AKSC_EPSILON ((AKSC_FLOAT)1.192092896e-07F)
+ #define AKSC_FLTMAX ((AKSC_FLOAT)3.402823466e+38F)
+ #endif
+#endif
+
+#define AKSC_PI ((AKSC_FLOAT)3.14159265358979323846264338)
+
+//========================= macro definition =================================//
+#ifdef AKSC_MATH_DOUBLE
+ // inplementation double
+ #define AKSC_COSF(ang) cos((ang))
+ #define AKSC_SINF(ang) sin((ang))
+ #define AKSC_ATAN2F(y,x) atan2((y),(x))
+ #define AKSC_FABSF(val) fabs((val))
+ #define AKSC_SQRTF(val) sqrt((val))
+ #define AKSC_POWF(x,y) pow((x),(y))
+#else
+ // inplementation float
+ #define AKSC_COSF(ang) cosf((ang))
+ #define AKSC_SINF(ang) sinf((ang))
+ #define AKSC_ATAN2F(y,x) atan2f((y),(x))
+ #define AKSC_FABSF(val) fabsf((val))
+ #define AKSC_SQRTF(val) sqrtf((val))
+ #define AKSC_POWF(x,y) powf((x),(y))
+#endif
+
+//========================= Vectors =====================================//
+// AKSC_FLOAT-precision floating-point 3 dimensional vector
+typedef union _AKSC_FVEC{
+ struct {
+ AKSC_FLOAT x;
+ AKSC_FLOAT y;
+ AKSC_FLOAT z;
+ }u;
+ AKSC_FLOAT v[3];
+} AKSC_FVEC;
+
+//========================= Matrix ======================================//
+// AKSC_FLOAT-precision floating-point 3x3 matrix
+typedef union _AKSC_FMAT{
+ struct {
+ AKSC_FLOAT _11, _12, _13;
+ AKSC_FLOAT _21, _22, _23;
+ AKSC_FLOAT _31, _32, _33;
+ }u;
+ AKSC_FLOAT m[3][3];
+} AKSC_FMAT;
+
+//========================= Quaternion ===================================//
+// AKSC_FLOAT-precision floating-point Quaternion
+typedef union _AKSC_FQUAT{
+ struct {
+ AKSC_FLOAT w;
+ AKSC_FLOAT x;
+ AKSC_FLOAT y;
+ AKSC_FLOAT z;
+ }u;
+ AKSC_FLOAT q[4];
+} AKSC_FQUAT;
+
+#endif
+
diff --git a/mpu/akm8963/libSmartCompass/AKManualCal.h b/mpu/akm8963/libSmartCompass/AKManualCal.h
new file mode 100755
index 0000000..bbe65f1
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/AKManualCal.h
@@ -0,0 +1,43 @@
+/******************************************************************************
+ *
+ * $Id: AKManualCal.h 98 2012-12-04 04:30:13Z yamada.rj $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKSC_INC_AKMANUALCAL_H
+#define AKSC_INC_AKMANUALCAL_H
+
+#include "AKMDevice.h"
+
+//========================= Type declaration ===========================//
+
+//========================= Constant definition =========================//
+
+//========================= Prototype of Function =======================//
+AKLIB_C_API_START
+int16 AKSC_HOffsetCal( //(o) : Calibration success(1), failure(0)
+ const int16vec hdata[], //(i) : Geomagnetic vectors(the size must be 3)
+ int16vec* ho //(o) : Offset(5Q11)
+);
+
+AKLIB_C_API_END
+
+#endif
+
diff --git a/mpu/akm8963/libSmartCompass/AKPseudoGyro.h b/mpu/akm8963/libSmartCompass/AKPseudoGyro.h
new file mode 100755
index 0000000..ee9a530
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/AKPseudoGyro.h
@@ -0,0 +1,86 @@
+/******************************************************************************
+ *
+ * $Id: AKPseudoGyro.h 134 2013-04-04 06:45:53Z kitaura.mc $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKSC_INC_AKPSEUDOGYRO_H
+#define AKSC_INC_AKPSEUDOGYRO_H
+
+#include "AKMDevice.h"
+
+//========================= Constant definition ==============================//
+#define AKPG_FBUF_SIZE 32 ///< buffer size definition for PseudoGyro algorithm
+ ///< Please do not change this value.
+#define AKPG_MBUF_SIZE 2 ///< buffer size definition for PseudoGyro algorithm
+ ///< Please do not change this value.
+#define AKPG_NBUF_SIZE 8 ///< buffer size definition for PseudoGyro algorithm
+ ///< Please do not change this value.
+#define AKPG_DBUF_SIZE 3 ///< buffer size definition for PseudoGyro algorithm
+ ///< Please do not change this value.
+
+//========================= Type declaration ================================//
+/// variables for AKSC_PseudoGyro()
+typedef struct _AKPG_VAR {
+ int16vec hfbuf[AKPG_FBUF_SIZE];
+ int16vec afbuf[AKPG_FBUF_SIZE];
+ I16MATRIX mbuf[AKPG_MBUF_SIZE];
+ int16vec hnbuf[AKPG_NBUF_SIZE];
+ int16vec anbuf[AKPG_NBUF_SIZE];
+ int16vec hdbuf[AKPG_DBUF_SIZE];
+ int16vec adbuf[AKPG_DBUF_SIZE];
+ int16 dtbuf[AKPG_FBUF_SIZE];
+} AKPG_VAR;
+
+typedef struct _AKPG_COND {
+ int16 fmode; // 0:filter mode 0, 1:filter mode 1
+ int16 dtave; // average number of dt
+ int16 ihave; // average number of input magnetic vector
+ int16 iaave; // average number of input acceleration vector
+ uint16 th_rmax; // |H| upper threshold [16.67code/uT]
+ uint16 th_rmin; // |H| lower threshold [16.67code/uT]
+ uint16 th_rdif; // |H| change threshold [16.67code/uT]
+ int16 ocoef; // damping fuctor [0(static), 1024(through)]
+} AKPG_COND;
+
+//========================= Prototype of Function ============================//
+AKLIB_C_API_START
+void AKSC_InitPseudoGyro(
+ AKPG_COND *cond, //(o) PG condition parameters
+ AKPG_VAR *var //(o) variable
+);
+
+int16 AKSC_PseudoGyro(
+ const AKPG_COND *cond, //(i) PG condition parameters
+ const int16 dt, //(i) measurement frequency [1/16ms]
+ const int16vec *hvec, //(i) input hdata [16.67code/uT]
+ const int16vec *avec, //(i) input adata [720code/G]
+ const I16MATRIX *hlayout, //(i) hlayout
+ const I16MATRIX *alayout, //(i) alayout
+ AKPG_VAR *pgvar, //(i/o) PG variable
+ int32vec *pgangrate, //(o) PG angular rate vector [1/64 deg/sec]
+ I16QUAT *pgquat, //(o) PG orientation quaternion
+ int16vec *pgGravity, //(o) PG Gravity [720code/G]
+ int16vec *pgLinAcc //(o) PG linear acc. vector [720code/G]
+);
+
+AKLIB_C_API_END
+
+#endif
diff --git a/mpu/akm8963/libSmartCompass/AKVersion.h b/mpu/akm8963/libSmartCompass/AKVersion.h
new file mode 100755
index 0000000..d1805b1
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/AKVersion.h
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *
+ * $Id: AKVersion.h 98 2012-12-04 04:30:13Z yamada.rj $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKSC_INC_AKVERSION_H
+#define AKSC_INC_AKVERSION_H
+
+#include "AKMDevice.h"
+
+//========================= Type declaration ===========================//
+
+//========================= Constant definition =========================//
+
+//========================= Prototype of Function =======================//
+AKLIB_C_API_START
+int16 AKSC_GetVersion_Major(void);
+int16 AKSC_GetVersion_Minor(void);
+int16 AKSC_GetVersion_Revision(void);
+int16 AKSC_GetVersion_DateCode(void);
+int16 AKSC_GetVersion_Variation(void);
+int16 AKSC_GetVersion_Device(void);
+AKLIB_C_API_END
+
+#endif
+
diff --git a/mpu/akm8963/libSmartCompass/libAK09911wPG.a b/mpu/akm8963/libSmartCompass/libAK09911wPG.a
new file mode 100755
index 0000000..72ce0a5
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/libAK09911wPG.a
Binary files differ
diff --git a/mpu/akm8963/libSmartCompass/libAK8963wPGplus.a b/mpu/akm8963/libSmartCompass/libAK8963wPGplus.a
new file mode 100755
index 0000000..0deb498
--- /dev/null
+++ b/mpu/akm8963/libSmartCompass/libAK8963wPGplus.a
Binary files differ
diff --git a/mpu/akm8963/main.c b/mpu/akm8963/main.c
new file mode 100755
index 0000000..afd367e
--- /dev/null
+++ b/mpu/akm8963/main.c
@@ -0,0 +1,473 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#include <sched.h>
+#include <pthread.h>
+#include <linux/input.h>
+
+#include "AKCommon.h"
+#include "AKMD_Driver.h"
+#include "DispMessage.h"
+#include "FileIO.h"
+#include "FST.h"
+#include "Measure.h"
+#include "misc.h"
+
+#define ERROR_OPTPARSE (-1)
+#define ERROR_INITDEVICE (-2)
+#define ERROR_HLAYOUT (-3)
+#define ERROR_FUSEROM (-4)
+#define ERROR_GET_SIZE_DOEP (-5)
+#define ERROR_MALLOC_DOEP (-6)
+#define ERROR_GETOPEN_STAT (-7)
+#define ERROR_STARTCLONE (-8)
+#define ERROR_GETCLOSE_STAT (-9)
+
+#define CONVERT_Q14_TO_Q16(x) ((int32_t)((x) * 4))
+#define CONVERT_FLOAT_Q16(x) ((int32_t)((x) * 65536))
+#define CONVERT_AKSC_Q16(x) ((int32_t)((x) * 65535 * 9.80665f / 720.0))
+#define CONVERT_Q6_DEG_Q16_RAD(x) ((int32_t)((x) * 1024 * 3.141592f / 180.0f))
+
+/* Global variable. See AKCommon.h file. */
+int g_stopRequest = 0;
+int g_opmode = 0;
+int g_dbgzone = 0;
+int g_mainQuit = AKD_FALSE;
+
+/* Static variable. */
+static pthread_t s_thread; /*!< Thread handle */
+static FORM_CLASS s_formClass = {
+ .open = misc_openForm,
+ .close = misc_closeForm,
+ .check = misc_checkForm,
+};
+
+/*!
+ A thread function which is raised when measurement is started.
+ @param[in] args A pointer to #AKSCPRMS structure.
+ */
+static void* thread_main(void* args)
+{
+ MeasureSNGLoop((AKSCPRMS *)args);
+ return ((void*)0);
+}
+
+static void signal_handler(int sig)
+{
+ if (sig == SIGINT) {
+ AKMERROR;
+ g_stopRequest = 1;
+ g_mainQuit = AKD_TRUE;
+ }
+}
+
+/*!
+ Starts new thread.
+ @return If this function succeeds, the return value is 1. Otherwise,
+ the return value is 0.
+ @param[in] prms A pointer to #AKSCPRMS structure. This pointer is passed
+ to the new thread argument.
+ */
+static int startClone(AKSCPRMS* prms)
+{
+ pthread_attr_t attr;
+
+ pthread_attr_init(&attr);
+ g_stopRequest = 0;
+ if (pthread_create(&s_thread, &attr, thread_main, prms) == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ Output measurement result. If this application is run as ConsoleMode,
+ the measurement result is output to console. If this application is run as
+ DaemonMode, the measurement result is written to device driver.
+ @param[in] prms pointer to #AKSCPRMS structure.
+ @param[in] flag This flag shows which data contains the valid data.
+ The device driver will report only the valid data to HAL layer.
+ */
+ #if 0
+void Disp_MeasurementResultHook(AKSCPRMS* prms, const uint16 flag)
+ {
+ int32_t rbuf[AKM_YPR_DATA_SIZE] = { 0 };
+ int16_t totalHDST = 0;
+ int16_t i = 0;
+
+ /* Adjust magnetic reliability based on the level of each algorithm */
+ if (prms->m_en_doeplus == 1) {
+ if ((prms->m_hdst == 3) && (prms->m_doep_lv <= 2)){
+ totalHDST = 2;
+ } else if ((prms->m_hdst == 2) && (prms->m_doep_lv <= 1)){
+ totalHDST = 1;
+ } else {
+ totalHDST = prms->m_hdst;
+ }
+ AKMDEBUG(AKMDBG_DOEPLUS, "DOE level: %2d, %2d, %2d\n",
+ prms->m_hdst, prms->m_doep_lv, totalHDST);
+ } else {
+ totalHDST = prms->m_hdst;
+ }
+
+ /* Coordinate system is already converted to Android */
+ rbuf[0] = flag; /* Data flag */
+ rbuf[1] = prms->m_avec.u.x; /* Ax */
+ rbuf[2] = prms->m_avec.u.y; /* Ay */
+ rbuf[3] = prms->m_avec.u.z; /* Az */
+ rbuf[4] = 3;
+ /* Acc status */
+ rbuf[5] = prms->m_hvec.u.x; /* Mx */
+ rbuf[6] = prms->m_hvec.u.y; /* My */
+ rbuf[7] = prms->m_hvec.u.z; /* Mz */
+ rbuf[8] = totalHDST; /* Mag status */
+ /* Gyr: Q16 Format (rad/sec) */
+ rbuf[9] = CONVERT_Q6_DEG_Q16_RAD(prms->m_pgout.u.x); /* Gy_x */
+ rbuf[10] = CONVERT_Q6_DEG_Q16_RAD(prms->m_pgout.u.y); /* Gy_y */
+ rbuf[11] = CONVERT_Q6_DEG_Q16_RAD(prms->m_pgout.u.z); /* Gy_z */
+ /* if(rbuf[9] == 0)
+ {
+ i++;
+ rbuf[9] = i + 1;
+ ALOGE("AKMD2 gyro.x = %d,i = %d\n",rbuf[9],i);
+ }
+ else
+ {
+ i = 0;
+ }*/
+ rbuf[12] = totalHDST; /* Gyro status */
+ /* Orientation Q6 format (degree)*/
+ rbuf[13] = prms->m_theta; /* yaw */
+ rbuf[14] = prms->m_phi180; /* pitch */
+ rbuf[15] = prms->m_eta90; /* roll */
+ ALOGI("--------------rbuf[]1 2 3, 5 6 7, 13 14 15 =%d %d %d,%d %d %d, %d %d %d\n",rbuf[1],rbuf[2],rbuf[3],rbuf[5],rbuf[6],rbuf[7],rbuf[13]/64,rbuf[14]/64,rbuf[15]/64);
+ /* Gravity (from AKSC format to Q16 format) */
+ rbuf[16] = CONVERT_AKSC_Q16(prms->m_pgGravity.u.x);
+ rbuf[17] = CONVERT_AKSC_Q16(prms->m_pgGravity.u.y);
+ rbuf[18] = CONVERT_AKSC_Q16(prms->m_pgGravity.u.z);
+ /* LinAcc (from Float to Q16 format) */
+ rbuf[19] = CONVERT_AKSC_Q16(prms->m_pgLinAcc.u.x);
+ rbuf[20] = CONVERT_AKSC_Q16(prms->m_pgLinAcc.u.y);
+ rbuf[21] = CONVERT_AKSC_Q16(prms->m_pgLinAcc.u.z);
+ /* RotVec Q14 format */
+ rbuf[22] = CONVERT_Q14_TO_Q16(prms->m_pgquat.u.x);
+ rbuf[23] = CONVERT_Q14_TO_Q16(prms->m_pgquat.u.y);
+ rbuf[24] = CONVERT_Q14_TO_Q16(prms->m_pgquat.u.z);
+ rbuf[25] = CONVERT_Q14_TO_Q16(prms->m_pgquat.u.w);
+ AKD_SetYPR(rbuf);
+
+ if (g_opmode & OPMODE_CONSOLE) {
+ Disp_MeasurementResult(prms);
+ }
+ }
+#endif
+
+void Disp_MeasurementResultHook(AKSCPRMS* prms, const uint16 flag)
+{
+ if (!g_opmode) {
+ int rbuf[AKM_YPR_DATA_SIZE] = { 0 };
+ int16_t totalHDST = 0;
+ /* Adjust magnetic reliability based on the level of each algorithm */
+ if (prms->m_en_doeplus == 1) {
+ if ((prms->m_hdst == 3) && (prms->m_doep_lv <= 2)){
+ totalHDST = 2;
+ } else if ((prms->m_hdst == 2) && (prms->m_doep_lv <= 1)){
+ totalHDST = 1;
+ } else {
+ totalHDST = prms->m_hdst;
+ }
+ AKMDEBUG(AKMDBG_DOEPLUS, "DOE level: %2d, %2d, %2d\n",
+ prms->m_hdst, prms->m_doep_lv, totalHDST);
+ } else {
+ totalHDST = prms->m_hdst;
+ }
+
+ //ALOGE("%s: totalHDST=%d, prms->m_hdst=%d\n", __FUNCTION__,
+ // totalHDST, prms->m_hdst);
+
+ rbuf[0] = flag; /* Data flag */
+ rbuf[1] = prms->m_avec.u.x; /* Ax */
+ rbuf[2] = prms->m_avec.u.y; /* Ay */
+ rbuf[3] = prms->m_avec.u.z; /* Az */
+ rbuf[4] = 3; /* Acc status */
+ rbuf[5] = prms->m_hvec.u.x; /* Mx */
+ rbuf[6] = prms->m_hvec.u.y; /* My */
+ rbuf[7] = prms->m_hvec.u.z; /* Mz */
+ rbuf[8] = totalHDST; /* Mag status */
+ rbuf[9] = prms->m_theta; /* yaw (deprecate) x*/
+ rbuf[10] = prms->m_phi180; /* pitch (deprecate) y*/
+ rbuf[11] = prms->m_eta90; /* roll (deprecate) z*/
+ AKD_SetYPR(rbuf);
+ } else {
+ Disp_MeasurementResult(prms);
+ }
+}
+
+/*!
+ This function parse the option.
+ @retval 1 Parse succeeds.
+ @retval 0 Parse failed.
+ @param[in] argc Argument count
+ @param[in] argv Argument vector
+ @param[out] layout_patno
+ */
+int OptParse(
+ int argc,
+ char* argv[],
+ AKMD_PATNO* hlayout_patno,
+ int16* en_doeplus,
+ int16* pg_filter)
+{
+ int opt;
+ char optVal;
+
+ /* Initial value */
+ *hlayout_patno = PAT_INVALID;
+ *en_doeplus = CSPEC_ENABLE_DOEPLUS;
+ *pg_filter = 0; //default
+
+ while ((opt = getopt(argc, argv, "dsm:z:p:f:")) != -1) {
+ switch(opt){
+ case 'm':
+ optVal = (char)(optarg[0] - '0');
+ if ((PAT1 <= optVal) && (optVal <= PAT8)) {
+ *hlayout_patno = (AKMD_PATNO)optVal;
+ }
+ break;
+ case 'z':
+ /* If error detected, hopefully 0 is returned. */
+ g_dbgzone = (int)strtol(optarg, (char**)NULL, 0);
+ break;
+ case 's':
+ g_opmode |= OPMODE_CONSOLE;
+ break;
+
+ case 'p':
+ /* DOEPlus enable/disable */
+ optVal = (char)(optarg[0] - '0');
+ if ((0 == optVal) || (1 == optVal)) {
+ *en_doeplus = optVal;
+ }
+ break;
+ case 'f':
+ /* DOEPlus enable/disable */
+ optVal = (char)(optarg[0] - '0');
+ if ((0 <= optVal) && (optVal<8) ){
+ *pg_filter = optVal;
+ }
+ break;
+ case 'd': //Enable AKM RAW data LOG
+ g_akmlog_enable = 1;
+ break;
+
+ default:
+ ALOGE("%s: Invalid argument", argv[0]);
+ return 0;
+ }
+ }
+
+ AKMDEBUG(AKMDBG_DEBUG, "%s: Mode=0x%04X\n", __FUNCTION__, g_opmode);
+ AKMDEBUG(AKMDBG_DEBUG, "%s: Layout=%d\n", __FUNCTION__, *hlayout_patno);
+ AKMDEBUG(AKMDBG_DEBUG, "%s: Dbg Zone=0x%04X\n", __FUNCTION__, g_dbgzone);
+
+ return 1;
+}
+
+/*!
+ This is main function.
+ */
+int main(int argc, char **argv)
+{
+ AKSCPRMS prms;
+ int retValue = 0;
+ int16_t size;
+
+ ALOGI("start in akmd\n");
+ /* Show the version info of this software. */
+ Disp_StartMessage();
+
+ g_akmlog_enable=0;
+
+#if ENABLE_AKMDEBUG
+ /* Register signal handler */
+ signal(SIGINT, signal_handler);
+#endif
+
+#if ENABLE_FORMATION
+ RegisterFormClass(&s_formClass);
+#endif
+
+ /* Initialize parameters structure. */
+ InitAKSCPRMS(&prms);
+
+ /* Parse command-line options */
+ if (OptParse(argc, argv, &prms.m_hlayout, &prms.m_en_doeplus,&prms.PG_filter) == 0) {
+ retValue = ERROR_OPTPARSE;
+ goto THE_END_OF_MAIN_FUNCTION;
+ }
+
+ /* Open device driver. */
+ if (AKD_InitDevice() != AKD_SUCCESS) {
+ retValue = ERROR_INITDEVICE;
+ goto THE_END_OF_MAIN_FUNCTION;
+ }
+
+ /* If layout is not specified with argument, get parameter from driver */
+ if (prms.m_hlayout == PAT_INVALID) {
+ int16_t n;
+ if (AKD_GetLayout(&n) == AKD_SUCCESS) {
+ if ((PAT1 <= n) && (n <= PAT8)) {
+ prms.m_hlayout = (AKMD_PATNO)n;
+ }
+ }
+ /* Error */
+ if (prms.m_hlayout == PAT_INVALID) {
+ ALOGE("Magnetic sensor's layout is not specified.");
+ retValue = ERROR_HLAYOUT;
+ goto THE_END_OF_MAIN_FUNCTION;
+ }
+ }
+
+ /* Read Fuse ROM */
+ if (ReadFUSEROM(&prms) != AKRET_PROC_SUCCEED) {
+ retValue = ERROR_FUSEROM;
+ goto THE_END_OF_MAIN_FUNCTION;
+ }
+
+ /* PDC */
+ LoadPDC(&prms);
+
+ /* malloc DOEPlus prms*/
+ size = AKSC_GetSizeDOEPVar();
+ if(size <= 0){
+ retValue = ERROR_GET_SIZE_DOEP;
+ goto THE_END_OF_MAIN_FUNCTION;
+ }
+ prms.m_doep_var = (AKSC_DOEPVAR *)malloc(size*sizeof(int32));
+ if(prms.m_doep_var == NULL){
+ retValue = ERROR_MALLOC_DOEP;
+ goto THE_END_OF_MAIN_FUNCTION;
+ }
+
+ /* Here is the Main Loop */
+ if (g_opmode & OPMODE_CONSOLE) {
+ /*** Console Mode *********************************************/
+ while (AKD_TRUE) {
+ /* Select operation */
+ switch (Menu_Main()) {
+ case MODE_FST:
+ FST_Body(&prms);
+ break;
+
+ case MODE_MeasureSNG:
+ /* Read Parameters from file. */
+ if (LoadParameters(&prms) == 0) {
+ SetDefaultPRMS(&prms);
+ }
+ /* Reset flag */
+ g_stopRequest = 0;
+ /* Measurement routine */
+ MeasureSNGLoop(&prms);
+
+ /* Write Parameters to file. */
+ SaveParameters(&prms);
+ break;
+
+ case MODE_OffsetCalibration:
+ /* Read Parameters from file. */
+ if (LoadParameters(&prms) == 0) {
+ SetDefaultPRMS(&prms);
+ }
+ /* measure offset (NOT sensitivity) */
+ if (SimpleCalibration(&prms) == AKRET_PROC_SUCCEED) {
+ SaveParameters(&prms);
+ }
+ break;
+
+ case MODE_Quit:
+ goto THE_END_OF_MAIN_FUNCTION;
+ break;
+
+ default:
+ AKMDEBUG(AKMDBG_DEBUG, "Unknown operation mode.\n");
+ break;
+ }
+ }
+ } else {
+ /*** Daemon Mode *********************************************/
+ while (g_mainQuit == AKD_FALSE) {
+ int st = 0;
+ /* Wait until device driver is opened. */
+ if (AKD_GetOpenStatus(&st) != AKD_SUCCESS) {
+ retValue = ERROR_GETOPEN_STAT;
+ goto THE_END_OF_MAIN_FUNCTION;
+ }
+ if (st == 0) {
+ AKMDEBUG(AKMDBG_DEBUG, "Suspended.");
+ } else {
+ AKMDEBUG(AKMDBG_DEBUG, "Compass Opened.");
+ /* Read Parameters from file. */
+ if (LoadParameters(&prms) == 0) {
+ SetDefaultPRMS(&prms);
+ }
+ /* Reset flag */
+ g_stopRequest = 0;
+ /* Start measurement thread. */
+ if (startClone(&prms) == 0) {
+ retValue = ERROR_STARTCLONE;
+ goto THE_END_OF_MAIN_FUNCTION;
+ }
+
+ /* Wait until device driver is closed. */
+ if (AKD_GetCloseStatus(&st) != AKD_SUCCESS) {
+ retValue = ERROR_GETCLOSE_STAT;
+ g_mainQuit = AKD_TRUE;
+ }
+ /* Wait thread completion. */
+ g_stopRequest = 1;
+ pthread_join(s_thread, NULL);
+ AKMDEBUG(AKMDBG_DEBUG, "Compass Closed.");
+
+ /* Write Parameters to file. */
+ SaveParameters(&prms);
+ }
+ }
+ }
+
+ /* free */
+ free(prms.m_doep_var);
+ prms.m_doep_var = NULL;
+
+THE_END_OF_MAIN_FUNCTION:
+
+ /* Close device driver. */
+ AKD_DeinitDevice();
+
+ /* Show the last message. */
+ Disp_EndMessage(retValue);
+
+ return retValue;
+}
+
+
diff --git a/mpu/akm8963/misc.c b/mpu/akm8963/misc.c
new file mode 100755
index 0000000..d75ac5e
--- /dev/null
+++ b/mpu/akm8963/misc.c
@@ -0,0 +1,319 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#include "misc.h"
+#include "AKCommon.h"
+#include <fcntl.h>
+#include <linux/input.h>
+#include <time.h> /* ns_to_timespec() */
+
+static int s_fdForm = -1; /*!< FD to formation detect device */
+
+struct AKMD_INTERVAL {
+ long interval; /*!< Measurement interval, 32-bit is enough for HDOE */
+ int16 decimator; /*!< HDOE decimator */
+};
+
+static struct AKMD_INTERVAL s_interval[] = {
+ { 10000000, 10 }, /* 100Hz SENSOR_DELAY_FASTEST */
+ { 16667000, 6 }, /* 60Hz */
+ { 20000000, 5 }, /* 50Hz SENSOR_DELAY_GAME */
+ { 25000000, 4 }, /* 40Hz */
+ { 31250000, 3 }, /* 32Hz */
+ { 66667000, 1 }, /* 15Hz SENSOR_DELAY_UI */
+ { 125000000, 1 } /* 8Hz SENSOR_DELAY_NORMAL */
+};
+
+/*!
+ Sleep function in millisecond.
+ @param[in] msec Suspend time in millisecond.
+ */
+inline void msleep(signed int msec)
+{
+ usleep(1000 * msec);
+}
+
+/*!
+ Open device driver which detects current formation. This is just a stab of
+ interface. Therefore, this function do nothing.
+ @return If function succeeds, the return value is 1. Otherwise, the return
+ value is 0.
+ */
+int16 misc_openForm(void)
+{
+ if (s_fdForm < 0) {
+ s_fdForm = 0;
+ }
+ return 1;
+}
+
+/*!
+ Close device driver
+ */
+void misc_closeForm(void)
+{
+ if (s_fdForm != -1) {
+ s_fdForm = -1;
+ }
+}
+
+/*!
+ Get current formation This is just a stab of interface. Therefore, this
+ function do nothing.
+ @return The number represents current form.
+ */
+int16 misc_checkForm(void)
+{
+ return 0;
+}
+
+/*!
+ Convert from int64_t value to timespec structure
+ @return timespec value
+ @param[in] val int64_t value
+ */
+struct timespec int64_to_timespec(int64_t val)
+{
+ struct timespec ret;
+ ret.tv_sec = (long) (val / 1000000000);
+ ret.tv_nsec = val - ret.tv_sec;
+
+ return ret;
+}
+
+/*!
+ Convert from timespec structure to int64_t value
+ @return int64_t value
+ @param[in] val timespec value
+ */
+int64_t timespec_to_int64(struct timespec* val)
+{
+ return ((int64_t)(val->tv_sec * 1000000000) + (int64_t)val->tv_nsec);
+}
+
+/*!
+ Calculate the difference between two timespec structure.
+ \a begin should be later than \a end.
+ @return the difference in int64_t type value.
+ @param[in] begin
+ @param[in] end
+ */
+int64_t CalcDuration(struct timespec* begin, struct timespec* end)
+{
+ struct timespec diff;
+
+ diff.tv_sec = begin->tv_sec - end->tv_sec;
+
+ if ((diff.tv_nsec = begin->tv_nsec - end->tv_nsec) < 0) {
+ diff.tv_nsec += 1000000000;
+ diff.tv_sec -= 1;
+ }
+
+ if (diff.tv_sec < 0) {
+ return 0; /* Minimum nanosec */
+ }
+
+ return timespec_to_int64(&diff);
+}
+
+/*!
+ Search and open an input event file by name. This function search the
+ directory "/dev/input/".
+ @return When this function succeeds, the return value is a file descriptor
+ to the found event file. If fails, the return value is -1.
+ @param[in] name The name of input device to be searched.
+ */
+int openInputDevice(const char* name)
+{
+ const int NUM_EVENT = 16;
+ const int BUFSIZE = 32;
+ const int NAMESIZE = 128;
+ char buf[BUFSIZE];
+ char evName[NAMESIZE];
+ int i;
+ int fd;
+ for (i = 0; i < NUM_EVENT; i++) {
+ if (snprintf(buf, sizeof(buf), "/dev/input/event%d", i) < 0) {
+ break;
+ }
+ fd = open(buf, O_RDONLY | O_NONBLOCK);
+ if (fd >= 0) {
+ if (ioctl(fd, EVIOCGNAME(NAMESIZE - 1), &evName) >= 1) {
+ AKMDEBUG(AKMDBG_DEBUG, "event%d(%d): %s\n", i, fd, evName);
+ if (!strncmp(name, evName, strnlen(name, NAMESIZE))) {
+ break;
+ }
+ }
+ close(fd);
+ }
+ fd = -1;
+ }
+
+ AKMDEBUG(AKMDBG_DEBUG, "openInput(%s): fd=%d\n", name, fd);
+ return fd;
+}
+
+/*!
+ Get valid measurement interval and HDOE decimator.
+ @return If this function succeeds, the return value is 1. Otherwise 0.
+ @param[in,out] time Input a requirement of sensor measurement interval.
+ The closest interval will be returned as output.
+ @param[out] hdoe_interval When the output interval value is set to looper,
+ this decimation value should be used to decimate the HDOE.
+ */
+int16 GetHDOEDecimator(int64_t* time, int16* hdoe_interval)
+{
+ const int n = (sizeof(s_interval) / sizeof(s_interval[0]));
+ int i;
+ int64_t org;
+
+ org = *time;
+
+ for (i = 0; i < n; i++) {
+ *time = s_interval[i].interval;
+ *hdoe_interval = s_interval[i].decimator;
+ if (org <= *time) {
+ break;
+ }
+ }
+
+ AKMDEBUG(AKMDBG_DEBUG, "HDOEDecimator:%lld,%lld\n", org, *time);
+ return 1;
+}
+
+/*!
+ This function convert coordinate system.
+ @retval 1 Conversion succeeds.
+ @retval 0 Conversion failed.
+ @param[in] pat Conversion pattern number.
+ @param[in,out] Original vector as input, converted data as output.
+*/
+int16 ConvertCoordinate(
+ const AKMD_PATNO pat,
+ int16vec* vec)
+{
+ int16 tmp;
+ switch(pat){
+ // Obverse
+ case PAT1:
+ // This is Android default
+ break;
+ case PAT2:
+ tmp = vec->u.x;
+ vec->u.x = vec->u.y;
+ vec->u.y = -tmp;
+ break;
+ case PAT3:
+ vec->u.x = -(vec->u.x);
+ vec->u.y = -(vec->u.y);
+ break;
+ case PAT4:
+ tmp = vec->u.x;
+ vec->u.x = -(vec->u.y);
+ vec->u.y = tmp;
+ break;
+ // Reverse
+ case PAT5:
+ vec->u.x = -(vec->u.x);
+ vec->u.z = -(vec->u.z);
+ break;
+ case PAT6:
+ tmp = vec->u.x;
+ vec->u.x = vec->u.y;
+ vec->u.y = tmp;
+ vec->u.z = -(vec->u.z);
+ break;
+ case PAT7:
+ vec->u.y = -(vec->u.y);
+ vec->u.z = -(vec->u.z);
+ break;
+ case PAT8:
+ tmp = vec->u.x;
+ vec->u.x = -(vec->u.y);
+ vec->u.y = -tmp;
+ vec->u.z = -(vec->u.z);
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+/*!
+ This function convert coordinate system.
+ @retval 1 Conversion succeeds.
+ @retval 0 Conversion failed.
+ @param[in] pat Conversion pattern number.
+ @param[in,out] Original vector as input, converted data as output.
+*/
+int16 ConvertCoordinate32(
+ const AKMD_PATNO pat,
+ int32vec* vec)
+{
+ int32 tmp;
+ switch(pat){
+ // Obverse
+ case PAT1:
+ // This is Android default
+ break;
+ case PAT2:
+ tmp = vec->u.x;
+ vec->u.x = vec->u.y;
+ vec->u.y = -tmp;
+ break;
+ case PAT3:
+ vec->u.x = -(vec->u.x);
+ vec->u.y = -(vec->u.y);
+ break;
+ case PAT4:
+ tmp = vec->u.x;
+ vec->u.x = -(vec->u.y);
+ vec->u.y = tmp;
+ break;
+ // Reverse
+ case PAT5:
+ vec->u.x = -(vec->u.x);
+ vec->u.z = -(vec->u.z);
+ break;
+ case PAT6:
+ tmp = vec->u.x;
+ vec->u.x = vec->u.y;
+ vec->u.y = tmp;
+ vec->u.z = -(vec->u.z);
+ break;
+ case PAT7:
+ vec->u.y = -(vec->u.y);
+ vec->u.z = -(vec->u.z);
+ break;
+ case PAT8:
+ tmp = vec->u.x;
+ vec->u.x = -(vec->u.y);
+ vec->u.y = -tmp;
+ vec->u.z = -(vec->u.z);
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
diff --git a/mpu/akm8963/misc.h b/mpu/akm8963/misc.h
new file mode 100755
index 0000000..34f1c6b
--- /dev/null
+++ b/mpu/akm8963/misc.h
@@ -0,0 +1,66 @@
+/******************************************************************************
+ *
+ * $Id: $
+ *
+ * -- Copyright Notice --
+ *
+ * Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
+ * All Rights Reserved.
+ *
+ * This software program is the proprietary program of Asahi Kasei Microdevices
+ * Corporation("AKM") licensed to authorized Licensee under the respective
+ * agreement between the Licensee and AKM only for use with AKM's electronic
+ * compass IC.
+ *
+ * THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
+ * THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
+ * WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
+ *
+ * -- End Asahi Kasei Microdevices Copyright Notice --
+ *
+ ******************************************************************************/
+#ifndef AKMD_INC_MISC_H
+#define AKMD_INC_MISC_H
+
+#include "AKCompass.h"
+
+/*** Constant definition ******************************************************/
+#define AKMD_FORM0 0
+#define AKMD_FORM1 1
+
+/*** Type declaration *********************************************************/
+typedef struct _AKMD_LOOP_TIME {
+ int64_t interval; /*!< Interval of each event */
+ int64_t duration; /*!< duration to the next event */
+} AKMD_LOOP_TIME;
+
+/*** Global variables *********************************************************/
+
+/*** Prototype of Function ***************************************************/
+void msleep(signed int msec);
+
+int16 misc_openForm(void);
+void misc_closeForm(void);
+int16 misc_checkForm(void);
+
+struct timespec int64_to_timespec(int64_t val);
+int64_t timespec_to_int64(struct timespec* val);
+int64_t CalcDuration(struct timespec* begin, struct timespec* end);
+
+int openInputDevice(const char* name);
+int16 GetHDOEDecimator(int64_t* time, int16* hdoe_interval);
+
+int16 ConvertCoordinate(
+ const AKMD_PATNO pat,/*!< [in] Convert Pattern Number */
+ int16vec* vec /*!< [out] Coordinate system after converted */
+);
+
+int16 ConvertCoordinate32(
+ const AKMD_PATNO pat,/*!< [in] Convert Pattern Number */
+ int32vec* vec /*!< [out] Coordinate system after converted */
+);
+
+#endif /*AKMD_INC_MISC_H*/
+
diff --git a/mpu/akm8963/mma8452_kernel.h b/mpu/akm8963/mma8452_kernel.h
new file mode 100755
index 0000000..65f09b9
--- /dev/null
+++ b/mpu/akm8963/mma8452_kernel.h
@@ -0,0 +1,136 @@
+/*
+ * Definitions for mma8452 compass chip.
+ */
+#ifndef MMA8452_H
+#define MMA8452_H
+
+#include <linux/ioctl.h>
+
+/* Default register settings */
+#define RBUFF_SIZE 12 /* Rx buffer size */
+
+#define MMA8452_REG_STATUS 0x0 //RO
+#define MMA8452_REG_X_OUT_MSB 0x1 //RO
+#define MMA8452_REG_X_OUT_LSB 0x2 //RO
+#define MMA8452_REG_Y_OUT_MSB 0x3 //RO
+#define MMA8452_REG_Y_OUT_LSB 0x4 //RO
+#define MMA8452_REG_Z_OUT_MSB 0x5 //RO
+#define MMA8452_REG_Z_OUT_LSB 0x6 //RO
+#define MMA8452_REG_F_SETUP 0x9 //RW
+
+#define MMA8452_REG_SYSMOD 0xB //RO
+#define MMA8452_REG_INTSRC 0xC //RO
+#define MMA8452_REG_WHO_AM_I 0xD //RO
+#define MMA8452_REG_XYZ_DATA_CFG 0xE //RW
+#define MMA8452_REG_HP_FILTER_CUTOFF 0xF //RW
+#define MMA8452_REG_PL_STATUS 0x10 //RO
+#define MMA8452_REG_PL_CFG 0x11 //RW
+#define MMA8452_REG_PL_COUNT 0x12 //RW
+#define MMA8452_REG_PL_BF_ZCOMP 0x13 //RW
+#define MMA8452_REG_P_L_THS_REG 0x14 //RW
+#define MMA8452_REG_FF_MT_CFG 0x15 //RW
+#define MMA8452_REG_FF_MT_SRC 0x16 //RO
+#define MMA8452_REG_FF_MT_THS 0x17 //RW
+#define MMA8452_REG_FF_MT_COUNT 0x18 //RW
+#define MMA8452_REG_TRANSIENT_CFG 0x1D //RW
+#define MMA8452_REG_TRANSIENT_SRC 0x1E //RO
+#define MMA8452_REG_TRANSIENT_THS 0x1F //RW
+#define MMA8452_REG_TRANSIENT_COUNT 0x20 //RW
+#define MMA8452_REG_PULSE_CFG 0x21 //RW
+#define MMA8452_REG_PULSE_SRC 0x22 //RO
+#define MMA8452_REG_PULSE_THSX 0x23 //RW
+#define MMA8452_REG_PULSE_THSY 0x24 //RW
+#define MMA8452_REG_PULSE_THSZ 0x25 //RW
+#define MMA8452_REG_PULSE_TMLT 0x26 //RW
+#define MMA8452_REG_PULSE_LTCY 0x27 //RW
+#define MMA8452_REG_PULSE_WIND 0x28 //RW
+#define MMA8452_REG_ASLP_COUNT 0x29 //RW
+#define MMA8452_REG_CTRL_REG1 0x2A //RW
+#define MMA8452_REG_CTRL_REG2 0x2B //RW
+#define MMA8452_REG_CTRL_REG3 0x2C //RW
+#define MMA8452_REG_CTRL_REG4 0x2D //RW
+#define MMA8452_REG_CTRL_REG5 0x2E //RW
+#define MMA8452_REG_OFF_X 0x2F //RW
+#define MMA8452_REG_OFF_Y 0x30 //RW
+#define MMA8452_REG_OFF_Z 0x31 //RW
+
+#define GSENSOR_IOCTL_MAGIC 'a'
+
+/* IOCTLs for MMA8452 library */
+#define GSENSOR_IOCTL_INIT _IO(GSENSOR_IOCTL_MAGIC, 0x01)
+#define GSENSOR_IOCTL_RESET _IO(GSENSOR_IOCTL_MAGIC, 0x04)
+#define GSENSOR_IOCTL_CLOSE _IO(GSENSOR_IOCTL_MAGIC, 0x02)
+#define GSENSOR_IOCTL_START _IO(GSENSOR_IOCTL_MAGIC, 0x03)
+#define GSENSOR_IOCTL_GETDATA _IOR(GSENSOR_IOCTL_MAGIC, 0x08, char[RBUFF_SIZE+1])
+
+/* IOCTLs for APPs */
+#define GSENSOR_IOCTL_APP_SET_RATE _IOW(GSENSOR_IOCTL_MAGIC, 0x10, char)
+
+
+/* IOCTLs for MMA8452 library */
+#define MMA_IOCTL_INIT _IO(GSENSOR_IOCTL_MAGIC, 0x01)
+#define MMA_IOCTL_RESET _IO(GSENSOR_IOCTL_MAGIC, 0x04)
+#define MMA_IOCTL_CLOSE _IO(GSENSOR_IOCTL_MAGIC, 0x02)
+#define MMA_IOCTL_START _IO(GSENSOR_IOCTL_MAGIC, 0x03)
+#define MMA_IOCTL_GETDATA _IOR(GSENSOR_IOCTL_MAGIC, 0x08, char[RBUFF_SIZE+1])
+
+/* IOCTLs for APPs */
+#define MMA_IOCTL_APP_SET_RATE _IOW(GSENSOR_IOCTL_MAGIC, 0x10, char)
+
+/*rate*/
+#define MMA8452_RATE_800 0
+#define MMA8452_RATE_400 1
+#define MMA8452_RATE_200 2
+#define MMA8452_RATE_100 3
+#define MMA8452_RATE_50 4
+#define MMA8452_RATE_12P5 5
+#define MMA8452_RATE_6P25 6
+#define MMA8452_RATE_1P56 7
+#define MMA8452_RATE_SHIFT 3
+
+
+#define MMA8452_ASLP_RATE_50 0
+#define MMA8452_ASLP_RATE_12P5 1
+#define MMA8452_ASLP_RATE_6P25 2
+#define MMA8452_ASLP_RATE_1P56 3
+#define MMA8452_ASLP_RATE_SHIFT 6
+
+#define ACTIVE_MASK 1
+#define FREAD_MASK 2
+
+
+
+
+/*status*/
+#define MMA8452_OPEN 1
+#define MMA8452_CLOSE 0
+
+//#define MMA8452_IIC_ADDR 0x98
+#define MMA8452_REG_LEN 11
+#define MMA8452_GRAVITY_STEP 156 //2g full scale range
+#define MMA8452_PRECISION 8 //8bit data
+#define MMA8452_BOUNDARY (0x1 << (MMA8452_PRECISION - 1))
+#define MMA8452_TOTAL_TIME 10
+
+
+/*
+struct mma8452_platform_data {
+ int reset;
+ int clk_on;
+ int intr;
+};
+
+*/
+
+struct sensor_axis {
+ int x;
+ int y;
+ int z;
+};
+
+
+#define GSENSOR_DEV_PATH "/dev/mma8452_daemon"
+
+
+#endif
+
diff --git a/mpu/akm8963/sensors_io.h b/mpu/akm8963/sensors_io.h
new file mode 100755
index 0000000..206a672
--- /dev/null
+++ b/mpu/akm8963/sensors_io.h
@@ -0,0 +1,169 @@
+/*
+*
+* (C) Copyright 2008
+* MediaTek <www.mediatek.com>
+*
+* Sensors IO command file for MT6516
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#ifndef SENSORS_IO_H
+#define SENSORS_IO_H
+
+#include <linux/ioctl.h>
+
+typedef struct {
+ unsigned short x; /**< X axis */
+ unsigned short y; /**< Y axis */
+ unsigned short z; /**< Z axis */
+} GSENSOR_VECTOR3D;
+
+typedef struct{
+ int x;
+ int y;
+ int z;
+}SENSOR_DATA;
+
+
+#define GSENSOR 0x85
+#define GSENSOR_IOCTL_INIT _IO(GSENSOR, 0x01)
+#define GSENSOR_IOCTL_READ_CHIPINFO _IOR(GSENSOR, 0x02, int)
+#define GSENSOR_IOCTL_READ_SENSORDATA _IOR(GSENSOR, 0x03, int)
+#define GSENSOR_IOCTL_READ_OFFSET _IOR(GSENSOR, 0x04, GSENSOR_VECTOR3D)
+#define GSENSOR_IOCTL_READ_GAIN _IOR(GSENSOR, 0x05, GSENSOR_VECTOR3D)
+#define GSENSOR_IOCTL_READ_RAW_DATA _IOR(GSENSOR, 0x06, int)
+#define GSENSOR_IOCTL_SET_CALI _IOW(GSENSOR, 0x06, SENSOR_DATA)
+#define GSENSOR_IOCTL_GET_CALI _IOW(GSENSOR, 0x07, SENSOR_DATA)
+#define GSENSOR_IOCTL_CLR_CALI _IO(GSENSOR, 0x08)
+
+
+
+
+/* IOCTLs for Msensor misc. device library 0x83*/
+#define MSENSOR 'c'
+#define MSENSOR_IOCTL_INIT _IO(MSENSOR, 0x01)
+#define MSENSOR_IOCTL_READ_CHIPINFO _IOR(MSENSOR, 0x02, int)
+#define MSENSOR_IOCTL_READ_SENSORDATA _IOR(MSENSOR, 0x03, int)
+#define MSENSOR_IOCTL_READ_POSTUREDATA _IOR(MSENSOR, 0x04, int)
+#define MSENSOR_IOCTL_READ_CALIDATA _IOR(MSENSOR, 0x05, int)
+#define MSENSOR_IOCTL_READ_CONTROL _IOR(MSENSOR, 0x06, int)
+#define MSENSOR_IOCTL_SET_CONTROL _IOW(MSENSOR, 0x07, int)
+#define MSENSOR_IOCTL_SET_MODE _IOW(MSENSOR, 0x08, int)
+#define MSENSOR_IOCTL_SET_POSTURE _IOW(MSENSOR, 0x09, int)
+#define MSENSOR_IOCTL_SET_CALIDATA _IOW(MSENSOR, 0x0a, int)
+#define MSENSOR_IOCTL_SENSOR_ENABLE _IOW(MSENSOR, 0x51, int)
+#define MSENSOR_IOCTL_READ_FACTORY_SENSORDATA _IOW(MSENSOR, 0x52, int)
+
+#define ECS_IOCTL_GET_INFO _IOR(MSENSOR, 0x27, unsigned char[AKM_SENSOR_INFO_SIZE])
+#define ECS_IOCTL_GET_CONF _IOR(MSENSOR, 0x28, unsigned char[AKM_SENSOR_CONF_SIZE])
+#define ECS_IOCTL_SET_YPR_09911 _IOW(MSENSOR, 0x29, int[26])
+#define ECS_IOCTL_GET_DELAY_09911 _IOR(MSENSOR, 0x30, int64_t[3])
+#define ECS_IOCTL_GET_LAYOUT_09911 _IOR(MSENSOR, 0x31, char)
+
+
+/* IOCTLs for AKM library */
+#define ECS_IOCTL_WRITE _IOW(MSENSOR, 0x0b, char*)
+#define ECS_IOCTL_READ _IOWR(MSENSOR, 0x0c, char*)
+#define ECS_IOCTL_RESET _IO(MSENSOR, 0x0d) /* NOT used in AK8975 */
+#define ECS_IOCTL_SET_MODE _IOW(MSENSOR, 0x0e, short)
+#define ECS_IOCTL_GETDATA _IOR(MSENSOR, 0x0f, char[SENSOR_DATA_SIZE])
+#define ECS_IOCTL_SET_YPR _IOW(MSENSOR, 0x10, short[12])
+#define ECS_IOCTL_GET_OPEN_STATUS _IOR(MSENSOR, 0x11, int)
+#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(MSENSOR, 0x12, int)
+#define ECS_IOCTL_GET_OSENSOR_STATUS _IOR(MSENSOR, 0x13, int)
+#define ECS_IOCTL_GET_DELAY _IOR(MSENSOR, 0x14, short)
+#define ECS_IOCTL_GET_PROJECT_NAME _IOR(MSENSOR, 0x15, char[64])
+#define ECS_IOCTL_GET_MATRIX _IOR(MSENSOR, 0x16, short [4][3][3])
+#define ECS_IOCTL_GET_LAYOUT _IOR(MSENSOR, 0x17, int[3])
+
+#define ECS_IOCTL_GET_OUTBIT _IOR(MSENSOR, 0x23, char)
+#define ECS_IOCTL_GET_ACCEL _IOR(MSENSOR, 0x24, short[3])
+#define MMC31XX_IOC_RM _IO(MSENSOR, 0x25)
+#define MMC31XX_IOC_RRM _IO(MSENSOR, 0x26)
+
+/* tzb add */
+#define COMPASS_IOCTL_MAGIC 'c'
+#define ECS_IOCTL_WRITE _IOW(COMPASS_IOCTL_MAGIC, 0x01, char*)
+#define ECS_IOCTL_READ _IOWR(COMPASS_IOCTL_MAGIC, 0x02, char*)
+#define ECS_IOCTL_RESET _IO(COMPASS_IOCTL_MAGIC, 0x03) /* NOT used in AK8975 */
+#define ECS_IOCTL_SET_MODE _IOW(COMPASS_IOCTL_MAGIC, 0x04, short)
+#define ECS_IOCTL_GETDATA _IOR(COMPASS_IOCTL_MAGIC, 0x05, char[8])
+#define ECS_IOCTL_SET_YPR _IOW(COMPASS_IOCTL_MAGIC, 0x06, short[12])
+#define ECS_IOCTL_GET_OPEN_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x07, int)
+#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(COMPASS_IOCTL_MAGIC, 0x08, int)
+#define ECS_IOCTL_GET_LAYOUT _IOR(COMPASS_IOCTL_MAGIC, 0x09, char)
+#define ECS_IOCTL_GET_ACCEL _IOR(COMPASS_IOCTL_MAGIC, 0x0A, short[3])
+#define ECS_IOCTL_GET_OUTBIT _IOR(COMPASS_IOCTL_MAGIC, 0x0B, char)
+#define ECS_IOCTL_GET_DELAY _IOR(COMPASS_IOCTL_MAGIC, 0x30, short)
+#define ECS_IOCTL_GET_PROJECT_NAME _IOR(COMPASS_IOCTL_MAGIC, 0x0D, char[64])
+#define ECS_IOCTL_GET_MATRIX _IOR(COMPASS_IOCTL_MAGIC, 0x0E, short [4][3][3])
+#define ECS_IOCTL_GET_PLATFORM_DATA _IOR(COMPASS_IOCTL_MAGIC, 0x0E, struct akm_platform_data)
+#define ECS_IOCTL_GET_INFO _IOR(COMPASS_IOCTL_MAGIC, 0x27, unsigned char[AKM_SENSOR_INFO_SIZE])
+#define ECS_IOCTL_GET_CONF _IOR(COMPASS_IOCTL_MAGIC, 0x28, unsigned char[AKM_SENSOR_CONF_SIZE])
+
+
+/* IOCTLs for MMC31XX device */
+#define MMC31XX_IOC_TM _IO(MSENSOR, 0x18)
+#define MMC31XX_IOC_SET _IO(MSENSOR, 0x19)
+#define MMC31XX_IOC_RESET _IO(MSENSOR, 0x1a)
+#define MMC31XX_IOC_READ _IOR(MSENSOR, 0x1b, int[3])
+#define MMC31XX_IOC_READXYZ _IOR(MSENSOR, 0x1c, int[3])
+
+#define ECOMPASS_IOC_GET_DELAY _IOR(MSENSOR, 0x1d, int)
+#define ECOMPASS_IOC_GET_MFLAG _IOR(MSENSOR, 0x1e, short)
+#define ECOMPASS_IOC_GET_OFLAG _IOR(MSENSOR, 0x1f, short)
+#define ECOMPASS_IOC_GET_OPEN_STATUS _IOR(MSENSOR, 0x20, int)
+#define ECOMPASS_IOC_SET_YPR _IOW(MSENSOR, 0x21, int[12])
+#define ECOMPASS_IOC_GET_LAYOUT _IOR(MSENSOR, 0X22, int)
+
+
+
+
+#define ALSPS 0X84
+#define ALSPS_SET_PS_MODE _IOW(ALSPS, 0x01, int)
+#define ALSPS_GET_PS_MODE _IOR(ALSPS, 0x02, int)
+#define ALSPS_GET_PS_DATA _IOR(ALSPS, 0x03, int)
+#define ALSPS_GET_PS_RAW_DATA _IOR(ALSPS, 0x04, int)
+#define ALSPS_SET_ALS_MODE _IOW(ALSPS, 0x05, int)
+#define ALSPS_GET_ALS_MODE _IOR(ALSPS, 0x06, int)
+#define ALSPS_GET_ALS_DATA _IOR(ALSPS, 0x07, int)
+#define ALSPS_GET_ALS_RAW_DATA _IOR(ALSPS, 0x08, int)
+/*-------------------yucong add-------------------------------------------*/
+#define ALSPS_GET_PS_TEST_RESULT _IOR(ALSPS, 0x09, int)
+#define ALSPS_GET_ALS_TEST_RESULT _IOR(ALSPS, 0x0A, int)
+#define ALSPS_GET_PS_THRESHOLD_HIGH _IOR(ALSPS, 0x0B, int)
+#define ALSPS_GET_PS_THRESHOLD_LOW _IOR(ALSPS, 0x0C, int)
+#define ALSPS_GET_ALS_THRESHOLD_HIGH _IOR(ALSPS, 0x0D, int)
+#define ALSPS_GET_ALS_THRESHOLD_LOW _IOR(ALSPS, 0x0E, int)
+
+
+#define GYROSCOPE 0X86
+#define GYROSCOPE_IOCTL_INIT _IO(GYROSCOPE, 0x01)
+#define GYROSCOPE_IOCTL_SMT_DATA _IOR(GYROSCOPE, 0x02, int)
+#define GYROSCOPE_IOCTL_READ_SENSORDATA _IOR(GYROSCOPE, 0x03, int)
+#define GYROSCOPE_IOCTL_SET_CALI _IOW(GYROSCOPE, 0x04, SENSOR_DATA)
+#define GYROSCOPE_IOCTL_GET_CALI _IOW(GYROSCOPE, 0x05, SENSOR_DATA)
+#define GYROSCOPE_IOCTL_CLR_CALI _IO(GYROSCOPE, 0x06)
+
+#define BROMETER 0X87
+#define BAROMETER_IOCTL_INIT _IO(BROMETER, 0x01)
+#define BAROMETER_GET_PRESS_DATA _IOR(BROMETER, 0x02, int)
+#define BAROMETER_GET_TEMP_DATA _IOR(BROMETER, 0x03, int)
+#define BAROMETER_IOCTL_READ_CHIPINFO _IOR(BROMETER, 0x04, int)
+
+
+
+
+#endif
diff --git a/mpu/libsensors/AkmSensor.cpp b/mpu/libsensors/AkmSensor.cpp
new file mode 100755
index 0000000..25f8a34
--- /dev/null
+++ b/mpu/libsensors/AkmSensor.cpp
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <poll.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/select.h>
+#include <dlfcn.h>
+
+#include <cutils/log.h>
+
+#include "AkmSensor.h"
+#include "akm8975.h"
+#define AKMD_DEFAULT_INTERVAL 200000000
+
+/*****************************************************************************/
+
+AkmSensor::AkmSensor()
+: SensorBase(AKM_DEVICE_NAME, "compass"),
+ //mPendingMask(0),
+ mInputReader(32)
+{
+ mEnabled = 0;
+ mDelay = -1;
+
+ //mPendingEvents.version = sizeof(sensors_event_t);
+ //mPendingEvents.sensor = ID_M;
+ //mPendingEvents.type = SENSOR_TYPE_MAGNETIC_FIELD;
+ //mPendingEvents.magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
+ //memset(mPendingEvents.data, 0, sizeof(mPendingEvents.data));
+
+ setEnable(ID_M, 0);
+}
+
+AkmSensor::~AkmSensor()
+{
+ setEnable(ID_M, 0);
+}
+
+int AkmSensor::write_sys_attribute(const char *path, const char *value, int bytes)
+{
+ int fd, amt;
+
+ fd = open(path, O_WRONLY);
+ if (fd < 0) {
+ LOGE("AkmSensor: write_attr failed to open %s (%s)",
+ path, strerror(errno));
+ return -1;
+ }
+
+ amt = write(fd, value, bytes);
+ amt = ((amt == -1) ? -errno : 0);
+ LOGE_IF(amt < 0, "AkmSensor: write_int failed to write %s (%s)",
+ path, strerror(errno));
+ close(fd);
+ return amt;
+}
+
+int AkmSensor::setEnable(int32_t handle, int enabled)
+{
+ int id = (int)handle;
+ int err = 0;
+ int cmd;
+ int newState;
+ short flags;
+
+ switch (id) {
+ case ID_M:
+ cmd = ECS_IOCTL_APP_SET_MFLAG;
+ break;
+ default:
+ LOGE("AkmSensor: unknown handle (%d)", handle);
+ return -EINVAL;
+ }
+
+ if (mEnabled <= 0) {
+ if (enabled) {
+ open_device();
+ flags = 1;
+ err = ioctl(dev_fd, cmd, &flags);
+ if (err < 0) {
+ LOGE("ECS_IOCTL_APP_SET_XXX failed (%s)", strerror(-err));
+ return err;
+ }
+ LOGD("AkmSensor: enable");
+ setDelay(handle, AKMD_DEFAULT_INTERVAL);
+ }
+ } else if (mEnabled == 1) {
+ if (!enabled) {
+ flags = 0;
+ err = ioctl(dev_fd, cmd, &flags);
+ if (err < 0) {
+ LOGE("ECS_IOCTL_APP_SET_XXX failed (%s)", strerror(-err));
+ return err;
+ }
+ LOGD("AkmSensor: disable");
+ setDelay(handle, -1);
+ close_device();
+ }
+ }
+
+ if (enabled) {
+ (mEnabled)++;
+ if (mEnabled > 32767) mEnabled = 32767;
+ } else {
+ (mEnabled)--;
+ if (mEnabled < 0) mEnabled = 0;
+ }
+ LOGD("AkmSensor: mEnabled = %d", mEnabled);
+
+ return err;
+}
+
+int AkmSensor::setDelay(int32_t handle, int64_t ns)
+{
+ int id = (int)handle;
+ int err = 0;
+ char buffer[32];
+ int cmd;
+
+ if (ns < -1 || 2147483647 < ns) {
+ LOGE("AkmSensor: invalid delay (%lld)", ns);
+ return -EINVAL;
+ }
+
+ switch (id) {
+ case ID_M:
+ cmd = ECS_IOCTL_APP_SET_DELAY;
+ break;
+ default:
+ LOGE("AkmSensor: unknown handle (%d)", handle);
+ return -EINVAL;
+ }
+
+ if (ns != mDelay) {
+ short delay = ns / 1000000;
+ err = ioctl(dev_fd, ECS_IOCTL_APP_SET_DELAY, &delay);
+ if (err == 0) {
+ mDelay = ns;
+ LOGD("AkmSensor: set delay to %f ms.", ns/1000000.0f);
+ }
+ }
+
+ return err;
+}
+
+int64_t AkmSensor::getDelay()
+{
+ return mDelay;
+}
+
+int AkmSensor::getEnable()
+{
+ return mEnabled;
+}
+
+int AkmSensor::readEvents(sensors_event_t* data, int count)
+{
+ return 0;
+}
+#if 0
+int AkmSensor::readEvents(sensors_event_t* data, int count)
+{
+ if (count < 1)
+ return -EINVAL;
+
+ ssize_t n = mInputReader.fill(data_fd);
+ if (n < 0)
+ return n;
+
+ int numEventReceived = 0;
+ input_event const* event;
+
+ while (count && mInputReader.readEvent(&event)) {
+ int type = event->type;
+ if (type == EV_ABS) {
+ switch (event->code) {
+ case EVENT_TYPE_MAGV_X:
+ mPendingMask |= 1;
+ mPendingEvents.magnetic.x = event->value * CONVERT_M;
+ break;
+ case EVENT_TYPE_MAGV_Y:
+ mPendingMask |= 1;
+ mPendingEvents.magnetic.y = event->value * CONVERT_M;
+ break;
+ case EVENT_TYPE_MAGV_Z:
+ mPendingMask |= 1;
+ mPendingEvents.magnetic.z = event->value * CONVERT_M;
+ break;
+ case EVENT_TYPE_MAGV_STATUS:
+ mPendingMask |= 1;
+ mPendingEvents.magnetic.status = event->value;
+ break;
+ }
+ mInputReader.next();
+ } else if (type == EV_SYN) {
+ int64_t time = timevalToNano(event->time);
+ if (count && mPendingMask) {
+ if (mPendingMask & 1) {
+ mPendingMask &= ~(1);
+ mPendingEvents.timestamp = time;
+ //LOGD("data=%8.5f,%8.5f,%8.5f",
+ //mPendingEvents.data[0],
+ //mPendingEvents.data[1],
+ //mPendingEvents.data[2]);
+ if (mEnabled) {
+ *data++ = mPendingEvents;
+ count--;
+ numEventReceived++;
+ }
+ }
+ }
+ if (!mPendingMask) {
+ mInputReader.next();
+ }
+ } else {
+ LOGE("AkmSensor: unknown event (type=%d, code=%d)",
+ type, event->code);
+ mInputReader.next();
+ }
+ }
+ return numEventReceived;
+}
+#endif
+
+#define COMPASS_EVENT_DEBUG (0)
+void AkmSensor::processCompassEvent(int code, int value)
+{
+ switch (code) {
+ case EVENT_TYPE_MAGV_X:
+ LOGV_IF(COMPASS_EVENT_DEBUG, "EVENT_TYPE_MAGV_X\n");
+ mCachedCompassData[0] = value * CONVERT_M * 65536;
+ break;
+ case EVENT_TYPE_MAGV_Y:
+ LOGV_IF(COMPASS_EVENT_DEBUG, "EVENT_TYPE_MAGV_Y\n");
+ mCachedCompassData[1] = value * CONVERT_M * 65536;
+ break;
+ case EVENT_TYPE_MAGV_Z:
+ LOGV_IF(COMPASS_EVENT_DEBUG, "EVENT_TYPE_MAGV_Z\n");
+ mCachedCompassData[2] = value * CONVERT_M * 65536;
+ break;
+ case EVENT_TYPE_MAGV_STATUS:
+ LOGV_IF(COMPASS_EVENT_DEBUG, "EVENT_TYPE_MAGV_STATUS\n");
+ mCachedCompassAccuracy = value;
+ break;
+ }
+}
+
+int AkmSensor::readSample(long *data, int64_t *timestamp)
+{
+ int numEventReceived = 0, done = 0;
+
+ ssize_t n = mInputReader.fill(data_fd);
+ if (n < 0) {
+ return n;
+ }
+
+ input_event const* event;
+
+ while (done == 0 && mInputReader.readEvent(&event)) {
+ int type = event->type;
+ if (type == EV_ABS) {
+ // TODO: if getting compass data
+ processCompassEvent(event->code, event->value);
+ } else if (type == EV_SYN) {
+ // TODO: if getting timestamp from 3rd-party's driver
+ *timestamp = timevalToNano(event->time);
+ memcpy(data, mCachedCompassData, sizeof(mCachedCompassData));
+ done = 1;
+ } else {
+ LOGE("HAL:Compass Sensor: unknown event (type=%d, code=%d)", type, event->code);
+ LOGE("AkmSensor: unknown event (type=%d, code=%d)", type, event->code);
+ }
+ mInputReader.next();
+ }
+ return done;
+}
+
+int AkmSensor::getAccuracy()
+{
+ if(mCachedCompassAccuracy>=2)
+ return 3;
+ else
+ return mCachedCompassAccuracy;
+}
diff --git a/mpu/libsensors/AkmSensor.h b/mpu/libsensors/AkmSensor.h
new file mode 100755
index 0000000..4c06dc4
--- /dev/null
+++ b/mpu/libsensors/AkmSensor.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AKM_SENSOR_H
+#define ANDROID_AKM_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "sensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+#if 1//??
+#define LOGD ALOGD
+#define LOGE ALOGE
+#define LOGI ALOGI
+#define LOGV ALOGV
+#define LOGW ALOGW
+#define LOGV_IF ALOGV_IF
+#define LOGE_IF ALOGE_IF
+#endif
+
+/*****************************************************************************/
+
+struct input_event;
+
+class AkmSensor : public SensorBase {
+public:
+ AkmSensor();
+ virtual ~AkmSensor();
+
+ virtual int readEvents(sensors_event_t* data, int count);
+ virtual int write_sys_attribute(char const *path, char const *value, int bytes);
+ virtual int setDelay(int32_t handle, int64_t ns);
+ virtual int setEnable(int32_t handle, int enabled);
+ virtual int64_t getDelay();
+ virtual int getEnable();
+ virtual int getAccuracy();
+ virtual int readSample(long *data, int64_t *timestamp);
+
+private:
+ int mEnabled;
+ int64_t mDelay;
+ //uint32_t mPendingMask;
+ InputEventCircularReader mInputReader;
+ //sensors_event_t mPendingEvents;
+ char input_sysfs_path[PATH_MAX];
+ int input_sysfs_path_len;
+ long mCachedCompassData[3];
+ int64_t mCompassTimestamp;
+ int mCachedCompassAccuracy;
+
+ void processCompassEvent(int code, int value);
+
+};
+
+/*****************************************************************************/
+
+#endif // ANDROID_AKM_SENSOR_H
diff --git a/mpu/libsensors/Android.mk b/mpu/libsensors/Android.mk
new file mode 100755
index 0000000..0a6f33e
--- /dev/null
+++ b/mpu/libsensors/Android.mk
@@ -0,0 +1,246 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# Modified 2011 by InvenSense, Inc
+
+LOCAL_PATH := $(call my-dir)
+#COMPILE_COMPASS_YAS537 := 1
+COMPILE_INVENSENSE_COMPASS_CAL := 0
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+ifeq (${TARGET_ARCH},arm64)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MODULE := libmplmpu
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_SRC_FILES_arm := libmplmpu.so
+LOCAL_32_BIT_ONLY := true
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MODULE := libmplmpu
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_SRC_FILES_arm64 := libmplmpu_64.so
+include $(BUILD_PREBUILT)
+
+else
+
+include $(CLEAR_VARS)
+LOCAL_PREBUILT_LIBS := libmplmpu.so
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_MULTI_PREBUILT)
+
+endif
+
+
+ifeq (${TARGET_ARCH},arm64)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MODULE := libmllite
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_SRC_FILES_arm := libmllite.so
+LOCAL_32_BIT_ONLY := true
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MODULE := libmllite
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_SRC_FILES_arm64 := libmllite_64.so
+include $(BUILD_PREBUILT)
+
+else
+
+include $(CLEAR_VARS)
+LOCAL_PREBUILT_LIBS := libmllite.so
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_MULTI_PREBUILT)
+
+endif
+
+
+
+# InvenSense fragment of the HAL
+include $(CLEAR_VARS)
+
+ifeq (${TARGET_ARCH},arm64)
+BIN_PATH := inv_64
+else
+BIN_PATH := inv_32
+endif
+
+LOCAL_MODULE := libinvensense_hal
+
+$(info LOCAL_MODULE=$(LOCAL_MODULE))
+$(info TARGET_ARCH=$(TARGET_ARCH))
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_OWNER := invensense
+
+LOCAL_CFLAGS := -DLOG_TAG=\"Sensors\"
+
+# ANDROID version check
+MAJOR_VERSION :=$(shell echo $(PLATFORM_VERSION) | cut -f1 -d.)
+MINOR_VERSION :=$(shell echo $(PLATFORM_VERSION) | cut -f2 -d.)
+VERSION_JB :=$(shell test $(MAJOR_VERSION) -gt 4 -o $(MAJOR_VERSION) -eq 4 -a $(MINOR_VERSION) -gt 0 && echo true)
+$(info MAJOR_VERSION=$(MAJOR_VERSION))
+$(info MINOR_VERSION=$(MINOR_VERSION))
+$(info VERSION_JB=$(VERSION_JB))
+#ANDROID version check END
+
+ifeq ($(VERSION_JB),true)
+LOCAL_CFLAGS += -DANDROID_JELLYBEAN
+endif
+
+ifneq (,$(filter $(TARGET_BUILD_VARIANT),eng userdebug))
+ifneq ($(COMPILE_INVENSENSE_COMPASS_CAL),0)
+LOCAL_CFLAGS += -DINVENSENSE_COMPASS_CAL
+endif
+ifeq ($(COMPILE_THIRD_PARTY_ACCEL),1)
+LOCAL_CFLAGS += -DTHIRD_PARTY_ACCEL
+endif
+ifeq ($(COMPILE_COMPASS_YAS537),1)
+LOCAL_CFLAGS += -DCOMPASS_YAS537
+endif
+ifeq ($(COMPILE_COMPASS_AK8975),1)
+LOCAL_CFLAGS += -DCOMPASS_AK8975
+endif
+ifeq ($(COMPILE_COMPASS_AMI306),1)
+LOCAL_CFLAGS += -DCOMPASS_AMI306
+endif
+else # release builds, default
+LOCAL_CFLAGS += -DINVENSENSE_COMPASS_CAL
+endif
+
+LOCAL_SRC_FILES += SensorBase.cpp
+LOCAL_SRC_FILES += MPLSensor.cpp
+LOCAL_SRC_FILES += MPLSupport.cpp
+LOCAL_SRC_FILES += InputEventReader.cpp
+
+ifneq (,$(filter $(TARGET_BUILD_VARIANT),eng userdebug))
+ifeq ($(COMPILE_INVENSENSE_COMPASS_CAL),0)
+LOCAL_SRC_FILES += AkmSensor.cpp
+LOCAL_SRC_FILES += CompassSensor.AKM.cpp
+else ifeq ($(COMPILE_COMPASS_AMI306),1)
+LOCAL_SRC_FILES += CompassSensor.IIO.primary.cpp
+else ifeq ($(COMPILE_COMPASS_YAS537),1)
+LOCAL_SRC_FILES += CompassSensor.YAMAHA.cpp
+LOCAL_SRC_FILES += YamahaSensor.cpp
+else
+LOCAL_SRC_FILES += CompassSensor.IIO.9150.cpp
+endif
+else # release builds, default
+LOCAL_SRC_FILES += AkmSensor.cpp
+LOCAL_SRC_FILES += CompassSensor.AKM.cpp
+endif #userdebug
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(BIN_PATH)/core/mllite
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(BIN_PATH)/core/mllite/linux
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(BIN_PATH)/core/driver/include
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(BIN_PATH)/core/driver/include/linux
+#LOCAL_C_INCLUDES += $(LOCAL_PATH)/yamaha/inc
+#LOCAL_C_INCLUDES += $(LOCAL_PATH)/yamaha/lib
+
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SHARED_LIBRARIES += libcutils
+LOCAL_SHARED_LIBRARIES += libutils
+LOCAL_SHARED_LIBRARIES += libdl
+LOCAL_SHARED_LIBRARIES += libmllite
+#LOCAL_SHARED_LIBRARIES += libyasalgo
+
+# Additions for SysPed
+LOCAL_SHARED_LIBRARIES += libmplmpu
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(BIN_PATH)/core/mpl
+LOCAL_CPPFLAGS += -DLINUX=1
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # !TARGET_SIMULATOR
+
+# Build a temporary HAL that links the InvenSense .so
+include $(CLEAR_VARS)
+
+ifeq (${TARGET_ARCH},arm64)
+BIN_PATH := inv_64
+else
+BIN_PATH := inv_32
+endif
+
+ifneq ($(filter manta grouper tilapia, $(TARGET_DEVICE)),)
+LOCAL_MODULE := sensors.invensense
+else
+LOCAL_MODULE := sensors.${TARGET_PRODUCT}
+endif
+LOCAL_MODULE := sensors.rk30board
+
+ifdef TARGET_2ND_ARCH
+LOCAL_MODULE_RELATIVE_PATH := hw
+else
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+endif
+
+LOCAL_SHARED_LIBRARIES += libmplmpu
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(BIN_PATH)/core/mllite
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(BIN_PATH)/core/mllite/linux
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(BIN_PATH)/core/mpl
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(BIN_PATH)/core/driver/include
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(BIN_PATH)/core/driver/include/linux
+
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -DLOG_TAG=\"Sensors\"
+
+ifeq ($(VERSION_JB),true)
+LOCAL_CFLAGS += -DANDROID_JELLYBEAN
+endif
+
+ifneq (,$(filter $(TARGET_BUILD_VARIANT),eng userdebug))
+ifneq ($(COMPILE_INVENSENSE_COMPASS_CAL),0)
+LOCAL_CFLAGS += -DINVENSENSE_COMPASS_CAL
+endif
+ifeq ($(COMPILE_THIRD_PARTY_ACCEL),1)
+LOCAL_CFLAGS += -DTHIRD_PARTY_ACCEL
+endif
+ifeq ($(COMPILE_COMPASS_YAS537),1)
+LOCAL_CFLAGS += -DCOMPASS_YAS537
+endif
+ifeq ($(COMPILE_COMPASS_AK8975),1)
+LOCAL_CFLAGS += -DCOMPASS_AK8975
+endif
+ifeq ($(COMPILE_COMPASS_AMI306),1)
+LOCAL_CFLAGS += -DCOMPASS_AMI306
+endif
+else # release builds, default
+LOCAL_CFLAGS += -DINVENSENSE_COMPASS_CAL
+endif # userdebug
+
+ifneq ($(filter manta grouper tilapia, $(TARGET_DEVICE)),)
+LOCAL_SRC_FILES := sensors_mpl.cpp
+else
+LOCAL_SRC_FILES := sensors_mpl.cpp
+endif
+
+LOCAL_SHARED_LIBRARIES := libinvensense_hal
+LOCAL_SHARED_LIBRARIES += libcutils
+LOCAL_SHARED_LIBRARIES += libutils
+LOCAL_SHARED_LIBRARIES += libdl
+LOCAL_SHARED_LIBRARIES += liblog
+LOCAL_SHARED_LIBRARIES += libmllite
+include $(BUILD_SHARED_LIBRARY)
+
+
+
diff --git a/mpu/libsensors/BUILD.sh b/mpu/libsensors/BUILD.sh
new file mode 100755
index 0000000..ca7dab7
--- /dev/null
+++ b/mpu/libsensors/BUILD.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+# This is a sample of the command line make used to build
+# the libraries and binaries for the Pandaboard.
+# Please customize this path to match the location of your
+# Android source tree. Other variables may also need to
+# be customized such as:
+# $CROSS, $PRODUCT, $KERNEL_ROOT
+
+export ANDROID_BASE=/home2/tzb/develop/marshmallow/
+
+make -C software/build/android \
+ VERBOSE=0 \
+ TARGET=android \
+ ANDROID_ROOT=${ANDROID_BASE}/rk3399_6.0_64 \
+ KERNEL_ROOT=${ANDROID_BASE}/rk3399_6.0_64/kernel \
+ CROSS=${ANDROID_BASE}/rk3399_6.0_64/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- \
+ PRODUCT=generic_arm64 \
+ MPL_LIB_NAME=mplmpu \
+ echo_in_colors=echo \
+ -f shared.mk
+
diff --git a/mpu/libsensors/CompassSensor.AKM.cpp b/mpu/libsensors/CompassSensor.AKM.cpp
new file mode 100755
index 0000000..f161e7b
--- /dev/null
+++ b/mpu/libsensors/CompassSensor.AKM.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <poll.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/select.h>
+#include <cutils/log.h>
+#include <linux/input.h>
+
+#include "sensor_params.h"
+#include "MPLSupport.h"
+
+// TODO: include corresponding unified header file for compass sensor
+#include "CompassSensor.AKM.h"
+
+// TODO: specify this for "fillList()" API
+#define COMPASS_NAME "AKM8963"
+
+/*****************************************************************************/
+
+CompassSensor::CompassSensor()
+ : SensorBase(NULL, NULL)
+{
+ VFUNC_LOG;
+
+ // TODO: initiate 3rd-party's class, and disable its funtionalities
+ // proper commands
+ mCompassSensor = new AkmSensor();
+ mCompassSensor->setEnable(ID_M, 0);
+}
+
+CompassSensor::~CompassSensor()
+{
+ VFUNC_LOG;
+
+ // TODO: disable 3rd-party's funtionalities and delete the object
+ mCompassSensor->setEnable(ID_M, 0);
+ delete mCompassSensor;
+}
+
+int CompassSensor::getFd(void) const
+{
+ VFUNC_LOG;
+
+ // TODO: return 3rd-party's file descriptor
+ return mCompassSensor->getFd();
+}
+
+/**
+ @brief This function will enable/disable sensor.
+ @param[in] handle which sensor to enable/disable.
+ @param[in] en en=1 enable; en=0 disable
+ @return if the operation is successful.
+**/
+int CompassSensor::enable(int32_t handle, int en)
+{
+ VFUNC_LOG;
+
+ // TODO: called 3rd-party's "set enable/disable" function
+ return mCompassSensor->setEnable(handle, en);
+}
+
+int CompassSensor::setDelay(int32_t handle, int64_t ns)
+{
+ VFUNC_LOG;
+
+ // TODO: called 3rd-party's "set delay" function
+ return mCompassSensor->setDelay(handle, ns);
+}
+
+/**
+ @brief This function will return the state of the sensor.
+ @return 1=enabled; 0=disabled
+**/
+int CompassSensor::getEnable(int32_t handle)
+{
+ VFUNC_LOG;
+
+ // TODO: return if 3rd-party compass is enabled
+ return mCompassSensor->getEnable();
+}
+
+/**
+ @brief This function will return the current delay for this sensor.
+ @return delay in nanoseconds.
+**/
+int64_t CompassSensor::getDelay(int32_t handle)
+{
+ VFUNC_LOG;
+
+ // TODO: return 3rd-party's delay time (should be in ns)
+ return mCompassSensor->getDelay();
+}
+
+/**
+ @brief Integrators need to implement this function per 3rd-party solution
+ @param[out] data sensor data is stored in this variable. Scaled such that
+ 1 uT = 2^16
+ @para[in] timestamp data's timestamp
+ @return 1, if 1 sample read, 0, if not, negative if error
+**/
+int CompassSensor::readSample(long *data, int64_t *timestamp)
+{
+ VFUNC_LOG;
+
+ // TODO: need to implement "readSample()" for MPL in 3rd-party's .cpp file
+ return mCompassSensor->readSample(data, timestamp);
+}
+
+void CompassSensor::fillList(struct sensor_t *list)
+{
+ VFUNC_LOG;
+
+ const char *compass = COMPASS_NAME;
+
+ if (compass) {
+ if (!strcmp(compass, "AKM8963")) {
+ list->maxRange = COMPASS_AKM8963_RANGE;
+ list->resolution = COMPASS_AKM8963_RESOLUTION;
+ list->power = COMPASS_AKM8963_POWER;
+ list->minDelay = COMPASS_AKM8963_MINDELAY;
+ return;
+ }
+ if (!strcmp(compass, "AKM8975")) {
+ list->maxRange = COMPASS_AKM8975_RANGE;
+ list->resolution = COMPASS_AKM8975_RESOLUTION;
+ list->power = COMPASS_AKM8975_POWER;
+ list->minDelay = COMPASS_AKM8975_MINDELAY;
+ LOGW("HAL:support for AKM8975 is incomplete");
+ }
+ }
+
+ LOGE("HAL:unsupported compass id %s -- "
+ "this implementation only supports AKM compasses", compass);
+ list->maxRange = COMPASS_AKM8975_RANGE;
+ list->resolution = COMPASS_AKM8975_RESOLUTION;
+ list->power = COMPASS_AKM8975_POWER;
+ list->minDelay = COMPASS_AKM8975_MINDELAY;
+}
+
+// TODO: specify compass sensor's mounting matrix for MPL
+void CompassSensor::getOrientationMatrix(signed char *orient)
+{
+ VFUNC_LOG;
+
+ orient[0] = 1;
+ orient[1] = 0;
+ orient[2] = 0;
+ orient[3] = 0;
+ orient[4] = 1;
+ orient[5] = 0;
+ orient[6] = 0;
+ orient[7] = 0;
+ orient[8] = 1;
+}
+
+int CompassSensor::getAccuracy(void)
+{
+ VFUNC_LOG;
+
+ // TODO: need to implement "getAccuracy()" for MPL in 3rd-party's .cpp file
+ return mCompassSensor->getAccuracy();
+}
diff --git a/mpu/libsensors/CompassSensor.AKM.h b/mpu/libsensors/CompassSensor.AKM.h
new file mode 100755
index 0000000..9e6057b
--- /dev/null
+++ b/mpu/libsensors/CompassSensor.AKM.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COMPASS_SENSOR_H
+#define COMPASS_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "SensorBase.h"
+
+// TODO: include 3rd-party compass vendor's header file
+// p.s.: before using unified HAL, make sure 3rd-party compass
+// solution's driver/HAL work well by themselves
+#include "AkmSensor.h"
+
+/*****************************************************************************/
+
+class CompassSensor : public SensorBase {
+
+protected:
+
+public:
+ CompassSensor();
+ virtual ~CompassSensor();
+
+ // TODO: make sure either 3rd-party compass solution has following virtual
+ // functions, or SensorBase.cpp could provide equal functionalities
+ virtual int getFd() const;
+ virtual int enable(int32_t handle, int enabled);
+ virtual int setDelay(int32_t handle, int64_t ns);
+ virtual int getEnable(int32_t handle);
+ virtual int64_t getDelay(int32_t handle);
+ virtual int64_t getMinDelay() { return -1; } // stub
+
+ // TODO: unnecessary for MPL solution (override 3rd-party solution)
+ virtual int readEvents(sensors_event_t *data, int count) { return 0; }
+
+ // TODO: following four APIs need further implementation for MPL's
+ // reference (look into .cpp for detailed information, also refer to
+ // 3rd-party's readEvents() for relevant APIs)
+ int readSample(long *data, int64_t *timestamp);
+ void fillList(struct sensor_t *list);
+ void getOrientationMatrix(signed char *orient);
+ int getAccuracy();
+
+ // TODO: if 3rd-party provides calibrated compass data, just return 1
+ int providesCalibration() { return 1; }
+
+ // TODO: hard-coded for 3rd-party's sensitivity transformation
+ //??long getSensitivity() { return (1L << 30); }
+ long getSensitivity() { return (4915 * (1L << 15)); } //??
+
+ /* all 3rd pary solution have compasses on the primary bus, hence they
+ have no dependency on the MPU */
+ int isIntegrated() { return 0; }
+
+private:
+ AkmSensor *mCompassSensor;
+};
+
+/*****************************************************************************/
+
+#endif // COMPASS_SENSOR_H
diff --git a/mpu/libsensors/CompassSensor.IIO.9150.cpp b/mpu/libsensors/CompassSensor.IIO.9150.cpp
new file mode 100755
index 0000000..03898fb
--- /dev/null
+++ b/mpu/libsensors/CompassSensor.IIO.9150.cpp
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/select.h>
+#include <cutils/log.h>
+#include <linux/input.h>
+#include <string.h>
+
+#include "CompassSensor.IIO.9150.h"
+#include "sensors.h"
+#include "MPLSupport.h"
+#include "sensor_params.h"
+#include "ml_sysfs_helper.h"
+
+#define COMPASS_MAX_SYSFS_ATTRB sizeof(compassSysFs) / sizeof(char*)
+
+#if defined COMPASS_YAS53x
+# warning "Invensense compass cal with YAS53x IIO on secondary bus"
+# define USE_MPL_COMPASS_HAL (1)
+# define COMPASS_NAME "INV_YAS530"
+#elif defined COMPASS_AK8975
+# warning "Invensense compass cal with AK8975 on primary bus"
+# define USE_MPL_COMPASS_HAL (1)
+# define COMPASS_NAME "INV_AK8975"
+#elif defined INVENSENSE_COMPASS_CAL
+# warning "Invensense compass cal with compass IIO on secondary bus"
+# define USE_MPL_COMPASS_HAL (1)
+# define COMPASS_NAME "INV_COMPASS"
+#else
+# warning "third party compass cal HAL"
+# define USE_MPL_COMPASS_HAL (0)
+// TODO: change to vendor's name
+# define COMPASS_NAME "AKM8975"
+#endif
+
+
+/*****************************************************************************/
+
+CompassSensor::CompassSensor()
+ : SensorBase(NULL, NULL),
+ compass_fd(-1),
+ mCompassTimestamp(0),
+ mCompassInputReader(8)
+{
+ VFUNC_LOG;
+
+ if(inv_init_sysfs_attributes()) {
+ LOGE("Error Instantiating Compass\n");
+ return;
+ }
+
+ if (!strcmp(COMPASS_NAME, "INV_COMPASS")) {
+ mI2CBus = COMPASS_BUS_SECONDARY;
+ } else {
+ mI2CBus = COMPASS_BUS_PRIMARY;
+ }
+
+ memset(mCachedCompassData, 0, sizeof(mCachedCompassData));
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:cat %s (%lld)",
+ compassSysFs.compass_orient, getTimestamp());
+ FILE *fptr;
+ fptr = fopen(compassSysFs.compass_orient, "r");
+ if (fptr != NULL) {
+ int om[9];
+ fscanf(fptr, "%d,%d,%d,%d,%d,%d,%d,%d,%d",
+ &om[0], &om[1], &om[2], &om[3], &om[4], &om[5],
+ &om[6], &om[7], &om[8]);
+ fclose(fptr);
+
+ LOGV_IF(EXTRA_VERBOSE,
+ "HAL:compass mounting matrix: "
+ "%+d %+d %+d %+d %+d %+d %+d %+d %+d",
+ om[0], om[1], om[2], om[3], om[4], om[5], om[6], om[7], om[8]);
+
+ mCompassOrientation[0] = om[0];
+ mCompassOrientation[1] = om[1];
+ mCompassOrientation[2] = om[2];
+ mCompassOrientation[3] = om[3];
+ mCompassOrientation[4] = om[4];
+ mCompassOrientation[5] = om[5];
+ mCompassOrientation[6] = om[6];
+ mCompassOrientation[7] = om[7];
+ mCompassOrientation[8] = om[8];
+ } else {
+ LOGE("HAL:Couldn't read compass mounting matrix");
+ }
+
+ if (!isIntegrated()) {
+ enable(ID_M, 0);
+ }
+}
+
+CompassSensor::~CompassSensor()
+{
+ VFUNC_LOG;
+
+ free(pathP);
+ if( compass_fd > 0)
+ close(compass_fd);
+}
+
+int CompassSensor::getFd() const
+{
+ VHANDLER_LOG;
+ LOGI_IF(EXTRA_VERBOSE,"HAL:compass_fd=%d", compass_fd);
+ return compass_fd;
+}
+
+/**
+ * @brief This function will enable/disable sensor.
+ * @param[in] handle
+ * which sensor to enable/disable.
+ * @param[in] en
+ * en=1, enable;
+ * en=0, disable
+ * @return if the operation is successful.
+ */
+int CompassSensor::enable(int32_t handle, int en)
+{
+ VFUNC_LOG;
+
+ mEnable = en;
+ int tempFd;
+ int res = 0;
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, compassSysFs.compass_enable, getTimestamp());
+ tempFd = open(compassSysFs.compass_enable, O_RDWR);
+ res = errno;
+ if(tempFd < 0) {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ compassSysFs.compass_enable, strerror(res), res);
+ return res;
+ }
+ res = enable_sysfs_sensor(tempFd, en);
+ LOGE_IF(res < 0, "HAL:enable compass failed");
+ close(tempFd);
+
+ if (en) {
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, compassSysFs.compass_x_fifo_enable, getTimestamp());
+ tempFd = open(compassSysFs.compass_x_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ close(tempFd);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ compassSysFs.compass_x_fifo_enable, strerror(res), res);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, compassSysFs.compass_y_fifo_enable, getTimestamp());
+ tempFd = open(compassSysFs.compass_y_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ close(tempFd);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ compassSysFs.compass_y_fifo_enable, strerror(res), res);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, compassSysFs.compass_z_fifo_enable, getTimestamp());
+ tempFd = open(compassSysFs.compass_z_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ close(tempFd);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ compassSysFs.compass_z_fifo_enable, strerror(res), res);
+ }
+ }
+
+ return res;
+}
+
+int CompassSensor::setDelay(int32_t handle, int64_t ns)
+{
+ VFUNC_LOG;
+ int tempFd;
+ int res;
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)",
+ 1000000000.f / ns, compassSysFs.compass_rate, getTimestamp());
+ mDelay = ns;
+ if (ns == 0)
+ return -1;
+ tempFd = open(compassSysFs.compass_rate, O_RDWR);
+ res = write_attribute_sensor(tempFd, 1000000000.f / ns);
+ if(res < 0) {
+ LOGE("HAL:Compass update delay error");
+ }
+ return res;
+}
+
+
+/**
+ @brief This function will return the state of the sensor.
+ @return 1=enabled; 0=disabled
+**/
+int CompassSensor::getEnable(int32_t handle)
+{
+ VFUNC_LOG;
+ return mEnable;
+}
+
+/* use for Invensense compass calibration */
+#define COMPASS_EVENT_DEBUG (0)
+void CompassSensor::processCompassEvent(const input_event *event)
+{
+ VHANDLER_LOG;
+
+ switch (event->code) {
+ case EVENT_TYPE_ICOMPASS_X:
+ LOGV_IF(COMPASS_EVENT_DEBUG, "EVENT_TYPE_ICOMPASS_X\n");
+ mCachedCompassData[0] = event->value;
+ break;
+ case EVENT_TYPE_ICOMPASS_Y:
+ LOGV_IF(COMPASS_EVENT_DEBUG, "EVENT_TYPE_ICOMPASS_Y\n");
+ mCachedCompassData[1] = event->value;
+ break;
+ case EVENT_TYPE_ICOMPASS_Z:
+ LOGV_IF(COMPASS_EVENT_DEBUG, "EVENT_TYPE_ICOMPASS_Z\n");
+ mCachedCompassData[2] = event->value;
+ break;
+ }
+
+ mCompassTimestamp =
+ (int64_t)event->time.tv_sec * 1000000000L + event->time.tv_usec * 1000L;
+}
+
+void CompassSensor::getOrientationMatrix(signed char *orient)
+{
+ VFUNC_LOG;
+ memcpy(orient, mCompassOrientation, sizeof(mCompassOrientation));
+}
+
+long CompassSensor::getSensitivity()
+{
+ VFUNC_LOG;
+
+ long sensitivity;
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:cat %s (%lld)",
+ compassSysFs.compass_scale, getTimestamp());
+ inv_read_data(compassSysFs.compass_scale, &sensitivity);
+ return sensitivity;
+}
+
+/**
+ @brief This function is called by sensors_mpl.cpp
+ to read sensor data from the driver.
+ @param[out] data sensor data is stored in this variable. Scaled such that
+ 1 uT = 2^16
+ @para[in] timestamp data's timestamp
+ @return 1, if 1 sample read, 0, if not, negative if error
+ */
+int CompassSensor::readSample(long *data, int64_t *timestamp)
+{
+ VHANDLER_LOG;
+
+ int numEventReceived = 0, done = 0;
+
+ ssize_t n = mCompassInputReader.fill(compass_fd);
+ if (n < 0) {
+ LOGE("HAL:no compass events read");
+ return n;
+ }
+
+ input_event const* event;
+
+ while (done == 0 && mCompassInputReader.readEvent(&event)) {
+ int type = event->type;
+ if (type == EV_REL) {
+ processCompassEvent(event);
+ } else if (type == EV_SYN) {
+ *timestamp = mCompassTimestamp;
+ memcpy(data, mCachedCompassData, sizeof(mCachedCompassData));
+ done = 1;
+ } else {
+ LOGE("HAL:Compass Sensor: unknown event (type=%d, code=%d)",
+ type, event->code);
+ }
+ mCompassInputReader.next();
+ }
+
+ return done;
+}
+
+/**
+ * @brief This function will return the current delay for this sensor.
+ * @return delay in nanoseconds.
+ */
+int64_t CompassSensor::getDelay(int32_t handle)
+{
+ VFUNC_LOG;
+ return mDelay;
+}
+
+void CompassSensor::fillList(struct sensor_t *list)
+{
+ VFUNC_LOG;
+
+ const char *compass = COMPASS_NAME;
+
+ if (compass) {
+ if(!strcmp(compass, "INV_COMPASS")) {
+ list->maxRange = COMPASS_MPU9150_RANGE;
+ list->resolution = COMPASS_MPU9150_RESOLUTION;
+ list->power = COMPASS_MPU9150_POWER;
+ list->minDelay = COMPASS_MPU9150_MINDELAY;
+ return;
+ }
+ if(!strcmp(compass, "compass")
+ || !strcmp(compass, "INV_AK8975") ) {
+ list->maxRange = COMPASS_AKM8975_RANGE;
+ list->resolution = COMPASS_AKM8975_RESOLUTION;
+ list->power = COMPASS_AKM8975_POWER;
+ list->minDelay = COMPASS_AKM8975_MINDELAY;
+ return;
+ }
+ if(!strcmp(compass, "INV_YAS530")) {
+ list->maxRange = COMPASS_YAS53x_RANGE;
+ list->resolution = COMPASS_YAS53x_RESOLUTION;
+ list->power = COMPASS_YAS53x_POWER;
+ list->minDelay = COMPASS_YAS53x_MINDELAY;
+ return;
+ }
+ if(!strcmp(compass, "INV_AMI306")) {
+ list->maxRange = COMPASS_AMI306_RANGE;
+ list->resolution = COMPASS_AMI306_RESOLUTION;
+ list->power = COMPASS_AMI306_POWER;
+ list->minDelay = COMPASS_AMI306_MINDELAY;
+ return;
+ }
+ }
+
+ LOGE("HAL:unknown compass id %s -- "
+ "params default to ak8975 and might be wrong.",
+ compass);
+ list->maxRange = COMPASS_AKM8975_RANGE;
+ list->resolution = COMPASS_AKM8975_RESOLUTION;
+ list->power = COMPASS_AKM8975_POWER;
+ list->minDelay = COMPASS_AKM8975_MINDELAY;
+}
+
+int CompassSensor::inv_init_sysfs_attributes(void)
+{
+ VFUNC_LOG;
+
+ unsigned char i = 0;
+ char sysfs_path[MAX_SYSFS_NAME_LEN], iio_trigger_path[MAX_SYSFS_NAME_LEN], tbuf[2];
+ char *sptr;
+ char **dptr;
+ int num;
+
+ pathP = (char*)malloc(
+ sizeof(char[COMPASS_MAX_SYSFS_ATTRB][MAX_SYSFS_NAME_LEN]));
+ sptr = pathP;
+ dptr = (char**)&compassSysFs;
+ if (sptr == NULL)
+ return -1;
+
+ memset(sysfs_path, 0, sizeof(sysfs_path));
+ memset(iio_trigger_path, 0, sizeof(iio_trigger_path));
+
+ do {
+ *dptr++ = sptr;
+ memset(sptr, 0, sizeof(sptr));
+ sptr += sizeof(char[MAX_SYSFS_NAME_LEN]);
+ } while (++i < COMPASS_MAX_SYSFS_ATTRB);
+
+ // get proper (in absolute/relative) IIO path & build MPU's sysfs paths
+ // inv_get_sysfs_abs_path(sysfs_path);
+ inv_get_sysfs_path(sysfs_path);
+ inv_get_iio_trigger_path(iio_trigger_path);
+
+ if (strcmp(sysfs_path, "") == 0 || strcmp(iio_trigger_path, "") == 0)
+ return 0;
+
+#if defined COMPASS_AK8975
+ inv_get_input_number(COMPASS_NAME, &num);
+ tbuf[0] = num + 0x30;
+ tbuf[1] = 0;
+ sprintf(sysfs_path, "%s%s", "sys/class/input/input", tbuf);
+ strcat(sysfs_path, "/ak8975");
+
+ sprintf(compassSysFs.compass_enable, "%s%s", sysfs_path, "/enable");
+ sprintf(compassSysFs.compass_rate, "%s%s", sysfs_path, "/rate");
+ sprintf(compassSysFs.compass_scale, "%s%s", sysfs_path, "/scale");
+ sprintf(compassSysFs.compass_orient, "%s%s", sysfs_path, "/compass_matrix");
+#else
+ sprintf(compassSysFs.compass_enable, "%s%s", sysfs_path, "/compass_enable");
+ sprintf(compassSysFs.compass_x_fifo_enable, "%s%s", sysfs_path, "/scan_elements/in_magn_x_en");
+ sprintf(compassSysFs.compass_y_fifo_enable, "%s%s", sysfs_path, "/scan_elements/in_magn_y_en");
+ sprintf(compassSysFs.compass_z_fifo_enable, "%s%s", sysfs_path, "/scan_elements/in_magn_z_en");
+ sprintf(compassSysFs.compass_rate, "%s%s", sysfs_path, "/sampling_frequency");
+ sprintf(compassSysFs.compass_scale, "%s%s", sysfs_path, "/in_magn_scale");
+ sprintf(compassSysFs.compass_orient, "%s%s", sysfs_path, "/compass_matrix");
+#endif
+
+#if 0
+ // test print sysfs paths
+ dptr = (char**)&compassSysFs;
+ for (i = 0; i < COMPASS_MAX_SYSFS_ATTRB; i++) {
+ LOGE("HAL:sysfs path: %s", *dptr++);
+ }
+#endif
+ return 0;
+}
+
+
diff --git a/mpu/libsensors/CompassSensor.IIO.9150.h b/mpu/libsensors/CompassSensor.IIO.9150.h
new file mode 100755
index 0000000..4cb8d40
--- /dev/null
+++ b/mpu/libsensors/CompassSensor.IIO.9150.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COMPASS_SENSOR_H
+#define COMPASS_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+// TODO fixme, need input_event
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <poll.h>
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+
+#include "sensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+class CompassSensor : public SensorBase {
+
+public:
+ CompassSensor();
+ virtual ~CompassSensor();
+
+ virtual int getFd() const;
+ virtual int enable(int32_t handle, int enabled);
+ virtual int setDelay(int32_t handle, int64_t ns);
+ virtual int getEnable(int32_t handle);
+ virtual int64_t getDelay(int32_t handle);
+ virtual int64_t getMinDelay() { return -1; } // stub
+
+ // unnecessary for MPL
+ virtual int readEvents(sensors_event_t *data, int count) { return 0; }
+
+ int readSample(long *data, int64_t *timestamp);
+ int providesCalibration() { return 0; }
+ void getOrientationMatrix(signed char *orient);
+ long getSensitivity();
+ int getAccuracy() { return 0; }
+ void fillList(struct sensor_t *list);
+ int isIntegrated() { return (mI2CBus == COMPASS_BUS_SECONDARY); }
+
+private:
+ enum CompassBus {
+ COMPASS_BUS_PRIMARY = 0,
+ COMPASS_BUS_SECONDARY = 1
+ } mI2CBus;
+
+ struct sysfs_attrbs {
+ char *compass_enable;
+ char *compass_x_fifo_enable;
+ char *compass_y_fifo_enable;
+ char *compass_z_fifo_enable;
+ char *compass_rate;
+ char *compass_scale;
+ char *compass_orient;
+ } compassSysFs;
+
+ // implementation specific
+ signed char mCompassOrientation[9];
+ long mCachedCompassData[3];
+ int compass_fd;
+ int64_t mCompassTimestamp;
+ InputEventCircularReader mCompassInputReader;
+ int64_t mDelay;
+ int mEnable;
+ char *pathP;
+
+ void processCompassEvent(const input_event *event);
+ int inv_init_sysfs_attributes(void);
+};
+
+/*****************************************************************************/
+
+#endif // COMPASS_SENSOR_H
diff --git a/mpu/libsensors/CompassSensor.IIO.primary.cpp b/mpu/libsensors/CompassSensor.IIO.primary.cpp
new file mode 100755
index 0000000..54529fa
--- /dev/null
+++ b/mpu/libsensors/CompassSensor.IIO.primary.cpp
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/select.h>
+#include <cutils/log.h>
+#include <linux/input.h>
+#include <string.h>
+
+#include "CompassSensor.IIO.primary.h"
+#include "sensors.h"
+#include "MPLSupport.h"
+#include "sensor_params.h"
+#include "ml_sysfs_helper.h"
+//#include "log.h"
+
+#define COMPASS_MAX_SYSFS_ATTRB sizeof(compassSysFs) / sizeof(char*)
+
+#if defined COMPASS_AK8975
+# warning "Invensense compass cal with AK8975 on primary bus"
+# define USE_MPL_COMPASS_HAL (1)
+# define COMPASS_NAME "INV_AK8975"
+#elif defined INVENSENSE_COMPASS_CAL
+
+#if defined COMPASS_YAS53x
+# warning "Invensense compass cal with YAS53x IIO on primary bus"
+# define USE_MPL_COMPASS_HAL (1)
+# define COMPASS_NAME "yas53" // prefix for YAS53[023]
+#elif defined COMPASS_AMI306
+# warning "Invensense compass cal with AMI306 IIO on primary bus"
+# define USE_MPL_COMPASS_HAL (1)
+# define COMPASS_NAME "ami306"
+#else
+# warning "Invensense compass cal with compass on secondary bus"
+# define USE_MPL_COMPASS_HAL (1)
+# define COMPASS_NAME "INV_COMPASS"
+#endif
+
+#else
+# warning "third party compass cal HAL"
+# define USE_MPL_COMPASS_HAL (0)
+// TODO: change to vendor's name
+# define COMPASS_NAME "AKM8975"
+#endif
+
+/******************************************************************************/
+
+CompassSensor::CompassSensor()
+ : SensorBase(COMPASS_NAME, NULL),
+ mCompassTimestamp(0),
+ mCompassInputReader(8)
+#ifdef COMPASS_YAS53x
+ , mCoilsResetFd(0)
+#endif
+{
+ FILE *fptr;
+
+ VFUNC_LOG;
+
+ /*
+ char temp_sysfs_path[30];
+ inv_get_sysfs_path(temp_sysfs_path);
+ LOGI("sysfs: %s", temp_sysfs_path);
+ */
+
+#ifdef COMPASS_YAS53x
+ /* for YAS53x compasses, dev_name is just a prefix,
+ we need to find the actual name */
+ if (fill_dev_full_name_by_prefix(dev_name,
+ dev_full_name, sizeof(dev_full_name) / sizeof(dev_full_name[0]))) {
+ LOGE("Cannot find Yamaha device with prefix name '%s' - "
+ "magnetometer will likely not work.", dev_name);
+ }
+#else
+ strncpy(dev_full_name, dev_name,
+ sizeof(dev_full_name) / sizeof(dev_full_name[0]));
+#endif
+
+ if (inv_init_sysfs_attributes()) {
+ LOGE("Error Instantiating Compass\n");
+ return;
+ }
+
+ if (!strcmp(dev_full_name, "INV_COMPASS")) {
+ mI2CBus = COMPASS_BUS_SECONDARY;
+ } else {
+ mI2CBus = COMPASS_BUS_PRIMARY;
+ }
+
+ memset(mCachedCompassData, 0, sizeof(mCachedCompassData));
+
+ if (!isIntegrated()) {
+ enable(ID_M, 0);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:compass name: %s", dev_full_name);
+ enable_iio_sysfs();
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:cat %s (%lld)",
+ compassSysFs.compass_orient, getTimestamp());
+ fptr = fopen(compassSysFs.compass_orient, "r");
+ if (fptr != NULL) {
+ int om[9];
+ fscanf(fptr, "%d,%d,%d,%d,%d,%d,%d,%d,%d",
+ &om[0], &om[1], &om[2], &om[3], &om[4], &om[5],
+ &om[6], &om[7], &om[8]);
+ fclose(fptr);
+
+ LOGV_IF(EXTRA_VERBOSE,
+ "HAL:compass mounting matrix: "
+ "%+d %+d %+d %+d %+d %+d %+d %+d %+d",
+ om[0], om[1], om[2], om[3], om[4], om[5], om[6], om[7], om[8]);
+
+ mCompassOrientation[0] = om[0];
+ mCompassOrientation[1] = om[1];
+ mCompassOrientation[2] = om[2];
+ mCompassOrientation[3] = om[3];
+ mCompassOrientation[4] = om[4];
+ mCompassOrientation[5] = om[5];
+ mCompassOrientation[6] = om[6];
+ mCompassOrientation[7] = om[7];
+ mCompassOrientation[8] = om[8];
+ } else {
+ LOGE("HAL:Couldn't read compass mounting matrix");
+ }
+
+#ifdef COMPASS_YAS53x
+ mCoilsResetFd = fopen(compassSysFs.compass_attr_1, "r+");
+ if (fptr == NULL) {
+ LOGE("HAL:Couldn't read compass overunderflow");
+ }
+#endif
+}
+
+void CompassSensor::enable_iio_sysfs()
+{
+ VFUNC_LOG;
+
+ int tempFd = 0;
+ char iio_trigger_name[MAX_CHIP_ID_LEN], iio_device_node[MAX_CHIP_ID_LEN];
+ FILE *tempFp = NULL;
+ const char* compass = dev_full_name;
+
+ LOGV_IF(SYSFS_VERBOSE,
+ "HAL:sysfs:echo 1 > %s (%lld)",
+ compassSysFs.in_timestamp_en, getTimestamp());
+ tempFd = open(compassSysFs.in_timestamp_en, O_RDWR);
+ if(tempFd < 0) {
+ LOGE("HAL:could not open %s timestamp enable", compass);
+ } else if(enable_sysfs_sensor(tempFd, 1) < 0) {
+ LOGE("HAL:could not enable timestamp");
+ }
+
+ LOGV_IF(SYSFS_VERBOSE,
+ "HAL:sysfs:cat %s (%lld)",
+ compassSysFs.trigger_name, getTimestamp());
+ tempFp = fopen(compassSysFs.trigger_name, "r");
+ if (tempFp == NULL) {
+ LOGE("HAL:could not open %s trigger name", compass);
+ } else {
+ if (fscanf(tempFp, "%s", iio_trigger_name) < 0) {
+ LOGE("HAL:could not read trigger name");
+ }
+ fclose(tempFp);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE,
+ "HAL:sysfs:echo %s > %s (%lld)",
+ iio_trigger_name, compassSysFs.current_trigger, getTimestamp());
+ tempFp = fopen(compassSysFs.current_trigger, "w");
+ if (tempFp == NULL) {
+ LOGE("HAL:could not open current trigger");
+ } else {
+ if (fprintf(tempFp, "%s", iio_trigger_name) < 0) {
+ LOGE("HAL:could not write current trigger");
+ }
+ fclose(tempFp);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE,
+ "HAL:sysfs:echo %d > %s (%lld)",
+ IIO_BUFFER_LENGTH, compassSysFs.buffer_length, getTimestamp());
+ tempFp = fopen(compassSysFs.buffer_length, "w");
+ if (tempFp == NULL) {
+ LOGE("HAL:could not open buffer length");
+ } else {
+ if (fprintf(tempFp, "%d", IIO_BUFFER_LENGTH) < 0) {
+ LOGE("HAL:could not write buffer length");
+ }
+ fclose(tempFp);
+ }
+
+ sprintf(iio_device_node, "%s%d", "/dev/iio:device",
+ find_type_by_name(compass, "iio:device"));
+ compass_fd = open(iio_device_node, O_RDONLY);
+ int res = errno;
+ if (compass_fd < 0) {
+ LOGE("HAL:could not open '%s' iio device node in path '%s' - "
+ "error '%s' (%d)",
+ compass, iio_device_node, strerror(res), res);
+ } else {
+ LOGV_IF(EXTRA_VERBOSE,
+ "HAL:iio %s, compass_fd opened : %d", compass, compass_fd);
+ }
+
+ /* TODO: need further tests for optimization to reduce context-switch
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo 1 > %s (%lld)",
+ compassSysFs.compass_x_fifo_enable, getTimestamp());
+ tempFd = open(compassSysFs.compass_x_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, 1);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ compassSysFs.compass_x_fifo_enable, strerror(res), res);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo 1 > %s (%lld)",
+ compassSysFs.compass_y_fifo_enable, getTimestamp());
+ tempFd = open(compassSysFs.compass_y_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, 1);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ compassSysFs.compass_y_fifo_enable, strerror(res), res);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo 1 > %s (%lld)",
+ compassSysFs.compass_z_fifo_enable, getTimestamp());
+ tempFd = open(compassSysFs.compass_z_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, 1);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ compassSysFs.compass_z_fifo_enable, strerror(res), res);
+ }
+ */
+}
+
+CompassSensor::~CompassSensor()
+{
+ VFUNC_LOG;
+
+ free(pathP);
+ if( compass_fd > 0)
+ close(compass_fd);
+#ifdef COMPASS_YAS53x
+ if( mCoilsResetFd != NULL )
+ fclose(mCoilsResetFd);
+#endif
+}
+
+int CompassSensor::getFd(void) const
+{
+ VHANDLER_LOG;
+ LOGI_IF(EXTRA_VERBOSE, "HAL:compass_fd=%d", compass_fd);
+ return compass_fd;
+}
+
+/**
+ * @brief This function will enable/disable sensor.
+ * @param[in] handle
+ * which sensor to enable/disable.
+ * @param[in] en
+ * en=1, enable;
+ * en=0, disable
+ * @return if the operation is successful.
+ */
+int CompassSensor::enable(int32_t handle, int en)
+{
+ VFUNC_LOG;
+
+ mEnable = en;
+ int tempFd;
+ int res = 0;
+
+ /* reset master enable */
+ res = masterEnable(0);
+ if (res < 0) {
+ return res;
+ }
+
+ if (en) {
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, compassSysFs.compass_x_fifo_enable, getTimestamp());
+ tempFd = open(compassSysFs.compass_x_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ compassSysFs.compass_x_fifo_enable, strerror(res), res);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, compassSysFs.compass_y_fifo_enable, getTimestamp());
+ tempFd = open(compassSysFs.compass_y_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ compassSysFs.compass_y_fifo_enable, strerror(res), res);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, compassSysFs.compass_z_fifo_enable, getTimestamp());
+ tempFd = open(compassSysFs.compass_z_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ compassSysFs.compass_z_fifo_enable, strerror(res), res);
+ }
+
+ res = masterEnable(en);
+ if (res < en) {
+ return res;
+ }
+ }
+
+ return res;
+}
+
+int CompassSensor::masterEnable(int en) {
+ VFUNC_LOG;
+
+ int res = 0;
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, compassSysFs.chip_enable, getTimestamp());
+ int tempFd = open(compassSysFs.chip_enable, O_RDWR);
+ res = errno;
+ if(tempFd < 0){
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ compassSysFs.chip_enable, strerror(res), res);
+ return res;
+ }
+ res = enable_sysfs_sensor(tempFd, en);
+ return res;
+}
+
+int CompassSensor::setDelay(int32_t handle, int64_t ns)
+{
+ VFUNC_LOG;
+ int tempFd;
+ int res;
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %.0f > %s (%lld)",
+ 1000000000.f / ns, compassSysFs.compass_rate, getTimestamp());
+ mDelay = ns;
+ if (ns == 0)
+ return -1;
+ tempFd = open(compassSysFs.compass_rate, O_RDWR);
+ res = write_attribute_sensor(tempFd, 1000000000.f / ns);
+ if(res < 0) {
+ LOGE("HAL:Compass update delay error");
+ }
+ return res;
+}
+
+/**
+ @brief This function will return the state of the sensor.
+ @return 1=enabled; 0=disabled
+**/
+int CompassSensor::getEnable(int32_t handle)
+{
+ VFUNC_LOG;
+ return mEnable;
+}
+
+/* use for Invensense compass calibration */
+#define COMPASS_EVENT_DEBUG (0)
+void CompassSensor::processCompassEvent(const input_event *event)
+{
+ VHANDLER_LOG;
+
+ switch (event->code) {
+ case EVENT_TYPE_ICOMPASS_X:
+ LOGV_IF(COMPASS_EVENT_DEBUG, "EVENT_TYPE_ICOMPASS_X\n");
+ mCachedCompassData[0] = event->value;
+ break;
+ case EVENT_TYPE_ICOMPASS_Y:
+ LOGV_IF(COMPASS_EVENT_DEBUG, "EVENT_TYPE_ICOMPASS_Y\n");
+ mCachedCompassData[1] = event->value;
+ break;
+ case EVENT_TYPE_ICOMPASS_Z:
+ LOGV_IF(COMPASS_EVENT_DEBUG, "EVENT_TYPE_ICOMPASS_Z\n");
+ mCachedCompassData[2] = event->value;
+ break;
+ }
+
+ mCompassTimestamp =
+ (int64_t)event->time.tv_sec * 1000000000L + event->time.tv_usec * 1000L;
+}
+
+void CompassSensor::getOrientationMatrix(signed char *orient)
+{
+ VFUNC_LOG;
+ memcpy(orient, mCompassOrientation, sizeof(mCompassOrientation));
+}
+
+long CompassSensor::getSensitivity()
+{
+ VFUNC_LOG;
+
+ long sensitivity;
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:cat %s (%lld)",
+ compassSysFs.compass_scale, getTimestamp());
+ inv_read_data(compassSysFs.compass_scale, &sensitivity);
+ return sensitivity;
+}
+
+/**
+ @brief This function is called by sensors_mpl.cpp
+ to read sensor data from the driver.
+ @param[out] data sensor data is stored in this variable. Scaled such that
+ 1 uT = 2^16
+ @para[in] timestamp data's timestamp
+ @return 1, if 1 sample read, 0, if not, negative if error
+ */
+int CompassSensor::readSample(long *data, int64_t *timestamp) {
+ VFUNC_LOG;
+
+ int i;
+ char *rdata = mIIOBuffer;
+
+ size_t rsize = read(compass_fd, rdata, (8 * mEnable + 8) * 1);
+
+ if (!mEnable) {
+ rsize = read(compass_fd, rdata, (8 + 8) * IIO_BUFFER_LENGTH);
+ // LOGI("clear buffer with size: %d", rsize);
+ }
+/*
+ LOGI("get one sample of AMI IIO data with size: %d", rsize);
+ LOGI_IF(mEnable, "compass x/y/z: %d/%d/%d", *((short *) (rdata + 0)),
+ *((short *) (rdata + 2)), *((short *) (rdata + 4)));
+*/
+ if (mEnable) {
+ for (i = 0; i < 3; i++) {
+ data[i] = *((short *) (rdata + i * 2));
+ }
+ *timestamp = *((long long *) (rdata + 8 * mEnable));
+ }
+
+ return mEnable;
+}
+
+/**
+ * @brief This function will return the current delay for this sensor.
+ * @return delay in nanoseconds.
+ */
+int64_t CompassSensor::getDelay(int32_t handle)
+{
+ VFUNC_LOG;
+ return mDelay;
+}
+
+void CompassSensor::fillList(struct sensor_t *list)
+{
+ VFUNC_LOG;
+
+ const char *compass = dev_full_name;
+
+ if (compass) {
+ if(!strcmp(compass, "INV_COMPASS")) {
+ list->maxRange = COMPASS_MPU9150_RANGE;
+ list->resolution = COMPASS_MPU9150_RESOLUTION;
+ list->power = COMPASS_MPU9150_POWER;
+ list->minDelay = COMPASS_MPU9150_MINDELAY;
+ mMinDelay = list->minDelay;
+ return;
+ }
+ if(!strcmp(compass, "compass")
+ || !strcmp(compass, "INV_AK8975")) {
+ list->maxRange = COMPASS_AKM8975_RANGE;
+ list->resolution = COMPASS_AKM8975_RESOLUTION;
+ list->power = COMPASS_AKM8975_POWER;
+ list->minDelay = COMPASS_AKM8975_MINDELAY;
+ mMinDelay = list->minDelay;
+ return;
+ }
+ if(!strcmp(compass, "ami306")) {
+ list->maxRange = COMPASS_AMI306_RANGE;
+ list->resolution = COMPASS_AMI306_RESOLUTION;
+ list->power = COMPASS_AMI306_POWER;
+ list->minDelay = COMPASS_AMI306_MINDELAY;
+ mMinDelay = list->minDelay;
+ return;
+ }
+ if(!strcmp(compass, "yas530")
+ || !strcmp(compass, "yas532")
+ || !strcmp(compass, "yas533")) {
+ list->maxRange = COMPASS_YAS53x_RANGE;
+ list->resolution = COMPASS_YAS53x_RESOLUTION;
+ list->power = COMPASS_YAS53x_POWER;
+ list->minDelay = COMPASS_YAS53x_MINDELAY;
+ mMinDelay = list->minDelay;
+ return;
+ }
+ }
+
+ LOGE("HAL:unknown compass id %s -- "
+ "params default to ak8975 and might be wrong.",
+ compass);
+ list->maxRange = COMPASS_AKM8975_RANGE;
+ list->resolution = COMPASS_AKM8975_RESOLUTION;
+ list->power = COMPASS_AKM8975_POWER;
+ list->minDelay = COMPASS_AKM8975_MINDELAY;
+ mMinDelay = list->minDelay;
+}
+
+#ifdef COMPASS_YAS53x
+/* Read sysfs entry to determine whether overflow had happend
+ then write to sysfs to reset to zero */
+int CompassSensor::checkCoilsReset()
+{
+ int result =- 1;
+ VFUNC_LOG;
+
+ if(mCoilsResetFd != NULL) {
+ int attr;
+ rewind(mCoilsResetFd);
+ fscanf(mCoilsResetFd, "%d", &attr);
+ if(attr == 0)
+ return 0;
+ else {
+ LOGV_IF(SYSFS_VERBOSE, "HAL:overflow detected");
+ rewind(mCoilsResetFd);
+ if( fprintf(mCoilsResetFd, "%d", 0) < 0) {
+ LOGE("HAL:could not write overunderflow");
+ }
+ else
+ return 1;
+ }
+ }
+ else {
+ LOGE("HAL:could not read overunderflow");
+ }
+ return result;
+}
+#endif
+
+int CompassSensor::inv_init_sysfs_attributes(void)
+{
+ VFUNC_LOG;
+
+ unsigned char i = 0;
+ char sysfs_path[MAX_SYSFS_NAME_LEN],
+ iio_trigger_path[MAX_SYSFS_NAME_LEN], tbuf[2];
+ char *sptr;
+ char **dptr;
+ int num;
+ const char* compass = dev_full_name;
+
+ pathP = (char*)malloc(
+ sizeof(char[COMPASS_MAX_SYSFS_ATTRB][MAX_SYSFS_NAME_LEN]));
+ sptr = pathP;
+ dptr = (char**)&compassSysFs;
+ if (sptr == NULL)
+ return -1;
+
+ do {
+ *dptr++ = sptr;
+ sptr += sizeof(char[MAX_SYSFS_NAME_LEN]);
+ } while (++i < COMPASS_MAX_SYSFS_ATTRB);
+
+ // get proper (in absolute/relative) IIO path & build sysfs paths
+ sprintf(sysfs_path, "%s%d", "/sys/bus/iio/devices/iio:device",
+ find_type_by_name(compass, "iio:device"));
+ sprintf(iio_trigger_path, "%s%d", "/sys/bus/iio/devices/trigger",
+ find_type_by_name(compass, "iio:device"));
+
+#if defined COMPASS_AK8975
+ inv_get_input_number(compass, &num);
+ tbuf[0] = num + 0x30;
+ tbuf[1] = 0;
+ sprintf(sysfs_path, "%s%s", "sys/class/input/input", tbuf);
+ strcat(sysfs_path, "/ak8975");
+
+ sprintf(compassSysFs.compass_enable, "%s%s", sysfs_path, "/enable");
+ sprintf(compassSysFs.compass_rate, "%s%s", sysfs_path, "/rate");
+ sprintf(compassSysFs.compass_scale, "%s%s", sysfs_path, "/scale");
+ sprintf(compassSysFs.compass_orient, "%s%s", sysfs_path, "/compass_matrix");
+#else /* IIO */
+ sprintf(compassSysFs.chip_enable, "%s%s", sysfs_path, "/buffer/enable");
+ sprintf(compassSysFs.in_timestamp_en, "%s%s", sysfs_path, "/scan_elements/in_timestamp_en");
+ sprintf(compassSysFs.trigger_name, "%s%s", iio_trigger_path, "/name");
+ sprintf(compassSysFs.current_trigger, "%s%s", sysfs_path, "/trigger/current_trigger");
+ sprintf(compassSysFs.buffer_length, "%s%s", sysfs_path, "/buffer/length");
+
+ sprintf(compassSysFs.compass_x_fifo_enable, "%s%s", sysfs_path, "/scan_elements/in_magn_x_en");
+ sprintf(compassSysFs.compass_y_fifo_enable, "%s%s", sysfs_path, "/scan_elements/in_magn_y_en");
+ sprintf(compassSysFs.compass_z_fifo_enable, "%s%s", sysfs_path, "/scan_elements/in_magn_z_en");
+ sprintf(compassSysFs.compass_rate, "%s%s", sysfs_path, "/sampling_frequency");
+ sprintf(compassSysFs.compass_scale, "%s%s", sysfs_path, "/in_magn_scale");
+ sprintf(compassSysFs.compass_orient, "%s%s", sysfs_path, "/compass_matrix");
+
+#if defined COMPASS_YAS53x
+ sprintf(compassSysFs.compass_attr_1, "%s%s", sysfs_path, "/overunderflow");
+#endif
+#endif
+
+#if 0
+ // test print sysfs paths
+ dptr = (char**)&compassSysFs;
+ LOGI("sysfs path base: %s", sysfs_path);
+ LOGI("trigger sysfs path base: %s", iio_trigger_path);
+ for (i = 0; i < COMPASS_MAX_SYSFS_ATTRB; i++) {
+ LOGE("HAL:sysfs path: %s", *dptr++);
+ }
+#endif
+ return 0;
+}
diff --git a/mpu/libsensors/CompassSensor.IIO.primary.h b/mpu/libsensors/CompassSensor.IIO.primary.h
new file mode 100755
index 0000000..027921c
--- /dev/null
+++ b/mpu/libsensors/CompassSensor.IIO.primary.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COMPASS_SENSOR_H
+#define COMPASS_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+// TODO fixme, need input_event
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <poll.h>
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+
+#include "sensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+#define MAX_CHIP_ID_LEN (20)
+
+class CompassSensor : public SensorBase {
+
+public:
+ CompassSensor();
+ virtual ~CompassSensor();
+
+ virtual int getFd() const;
+ virtual int enable(int32_t handle, int enabled);
+ virtual int setDelay(int32_t handle, int64_t ns);
+ virtual int getEnable(int32_t handle);
+ virtual int64_t getDelay(int32_t handle);
+ virtual int64_t getMinDelay() { return mMinDelay; }
+
+ // unnecessary for MPL
+ virtual int readEvents(sensors_event_t *data, int count) { return 0; }
+
+ int readSample(long *data, int64_t *timestamp);
+ int providesCalibration() { return 0; }
+ void getOrientationMatrix(signed char *orient);
+ long getSensitivity();
+ int getAccuracy() { return 0; }
+ void fillList(struct sensor_t *list);
+ int isIntegrated() { return (mI2CBus == COMPASS_BUS_SECONDARY); }
+#ifdef COMPASS_YAS53x
+ int checkCoilsReset(void);
+#endif
+
+private:
+ enum CompassBus {
+ COMPASS_BUS_PRIMARY = 0,
+ COMPASS_BUS_SECONDARY = 1
+ } mI2CBus;
+
+ struct sysfs_attrbs {
+ char *chip_enable;
+ char *in_timestamp_en;
+ char *trigger_name;
+ char *current_trigger;
+ char *buffer_length;
+
+ char *compass_enable;
+ char *compass_x_fifo_enable;
+ char *compass_y_fifo_enable;
+ char *compass_z_fifo_enable;
+ char *compass_rate;
+ char *compass_scale;
+ char *compass_orient;
+#ifdef COMPASS_YAS53x
+ char *compass_attr_1;
+#endif
+ } compassSysFs;
+
+ char dev_full_name[20];
+
+ // implementation specific
+ signed char mCompassOrientation[9];
+ long mCachedCompassData[3];
+ int64_t mCompassTimestamp;
+ InputEventCircularReader mCompassInputReader;
+ int compass_fd;
+ int64_t mDelay;
+ int64_t mMinDelay;
+ int mEnable;
+ char *pathP;
+
+ char mIIOBuffer[(8 + 8) * IIO_BUFFER_LENGTH];
+
+ int masterEnable(int en);
+ void enable_iio_sysfs(void);
+ void processCompassEvent(const input_event *event);
+ int inv_init_sysfs_attributes(void);
+
+#ifdef COMPASS_YAS53x
+ FILE *mCoilsResetFd;
+#endif
+};
+
+/*****************************************************************************/
+
+#endif // COMPASS_SENSOR_H
diff --git a/mpu/libsensors/CompassSensor.YAMAHA.cpp b/mpu/libsensors/CompassSensor.YAMAHA.cpp
new file mode 100755
index 0000000..733a19b
--- /dev/null
+++ b/mpu/libsensors/CompassSensor.YAMAHA.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <poll.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/select.h>
+#include <cutils/log.h>
+#include <linux/input.h>
+
+#include "sensor_params.h"
+#include "CompassSensor.YAMAHA.h"
+#include "yas.h"
+#include "sensors.h"
+#if (YAS_MAG_DRIVER == YAS_MAG_DRIVER_YAS532 \
+ || YAS_MAG_DRIVER == YAS_MAG_DRIVER_YAS533)
+#define COMPASS_NAME "YAS532"
+#elif YAS_MAG_DRIVER == YAS_MAG_DRIVER_YAS537
+#define COMPASS_NAME "YAS537"
+#endif
+
+/*****************************************************************************/
+
+CompassSensor::CompassSensor()
+ : SensorBase(NULL, NULL)
+{
+ mCompassSensor = new YamahaSensor();
+ mCompassSensor->enable(ID_M, 0);
+}
+
+CompassSensor::~CompassSensor()
+{
+ mCompassSensor->enable(ID_M, 0);
+ delete mCompassSensor;
+}
+
+int CompassSensor::getFd(void) const
+{
+ return mCompassSensor->getFd();
+}
+
+/**
+ @brief This function will enable/disable sensor.
+ @param[in] handle which sensor to enable/disable.
+ @param[in] en en=1 enable; en=0 disable
+ @return if the operation is successful.
+**/
+int CompassSensor::enable(int32_t handle, int en)
+{
+ return mCompassSensor->enable(handle, en);
+}
+
+int CompassSensor::setDelay(int32_t handle, int64_t ns)
+{
+ return mCompassSensor->setDelay(handle, ns);
+}
+
+/**
+ @brief This function will return the state of the sensor.
+ @return 1=enabled; 0=disabled
+**/
+int CompassSensor::getEnable(int32_t handle)
+{
+ return mCompassSensor->getEnable(handle);
+}
+
+/**
+ @brief This function will return the current delay for this sensor.
+ @return delay in nanoseconds.
+**/
+int64_t CompassSensor::getDelay(int32_t handle)
+{
+ return mCompassSensor->getDelay(handle);
+}
+
+/**
+ @brief Integrators need to implement this function per 3rd-party solution
+ @param[out] data sensor data is stored in this variable. Scaled such that
+ 1 uT = 2^16
+ @para[in] timestamp data's timestamp
+ @return 1, if 1 sample read, 0, if not, negative if error
+**/
+int CompassSensor::readSample(long *data, int64_t *timestamp)
+{
+ return mCompassSensor->readSample(data, timestamp);
+}
+
+void CompassSensor::fillList(struct sensor_t *list)
+{
+ const char *compass = COMPASS_NAME;
+
+ if (compass) {
+ if (!strcmp(compass, "YAS532")) {
+ list->maxRange = COMPASS_YAS532_RANGE;
+ list->resolution = COMPASS_YAS532_RESOLUTION;
+ list->power = COMPASS_YAS532_POWER;
+ list->minDelay = COMPASS_YAS532_MINDELAY;
+ return;
+ }
+ if (!strcmp(compass, "YAS537")) {
+ list->maxRange = COMPASS_YAS537_RANGE;
+ list->resolution = COMPASS_YAS537_RESOLUTION;
+ list->power = COMPASS_YAS537_POWER;
+ list->minDelay = COMPASS_YAS537_MINDELAY;
+ }
+ }
+
+ ALOGE("HAL:unsupported compass id %s -- "
+ "this implementation only supports YAMAHA compasses", compass);
+ list->maxRange = COMPASS_YAS537_RANGE;
+ list->resolution = COMPASS_YAS537_RESOLUTION;
+ list->power = COMPASS_YAS537_POWER;
+ list->minDelay = COMPASS_YAS537_MINDELAY;
+}
+
+void CompassSensor::getOrientationMatrix(signed char *orient)
+{
+ orient[0] = 1;
+ orient[1] = 0;
+ orient[2] = 0;
+ orient[3] = 0;
+ orient[4] = 1;
+ orient[5] = 0;
+ orient[6] = 0;
+ orient[7] = 0;
+ orient[8] = 1;
+}
+
+int CompassSensor::getAccuracy(void)
+{
+ return mCompassSensor->getAccuracy();
+}
+
+long CompassSensor::getSensitivity() {
+ /*
+ * TODO: hard-coded for 3rd-party's sensitivity transformation
+ * ??long getSensitivity() { return (1L << 30); }
+ */
+ return (4915 * (1L << 15));
+}
diff --git a/mpu/libsensors/CompassSensor.YAMAHA.h b/mpu/libsensors/CompassSensor.YAMAHA.h
new file mode 100755
index 0000000..70adffb
--- /dev/null
+++ b/mpu/libsensors/CompassSensor.YAMAHA.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COMPASS_SENSOR_H
+#define COMPASS_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "SensorBase.h"
+
+#include "YamahaSensor.h"
+
+#define COMPASS_YAS532_RANGE (1200.0f)
+#define COMPASS_YAS532_RESOLUTION (0.15f)
+#define COMPASS_YAS532_POWER (0.16f)
+#define COMPASS_YAS532_MINDELAY (10000)
+#define COMPASS_YAS537_RANGE (2000.0f)
+#define COMPASS_YAS537_RESOLUTION (0.3f)
+#define COMPASS_YAS537_POWER (0.16f)
+#define COMPASS_YAS537_MINDELAY (10000)
+
+class CompassSensor : public SensorBase {
+
+ protected:
+
+ public:
+ CompassSensor();
+ virtual ~CompassSensor();
+
+ int providesCalibration() { return 1; }
+ /* all 3rd pary solution have compasses on the primary bus, hence they
+ have no dependency on the MPU */
+ int isIntegrated() { return 0; }
+ /* unnecessary for MPL solution (override 3rd-party solution) */
+ virtual int readEvents(sensors_event_t *data, int count) {
+ (void) data;
+ (void) count;
+ return 0;
+ }
+
+ /*
+ * make sure either 3rd-party compass solution has following virtual
+ * functions, or SensorBase.cpp could provide equal functionalities
+ */
+ virtual int getFd() const;
+ virtual int enable(int32_t handle, int enabled);
+ virtual int setDelay(int32_t handle, int64_t ns);
+ virtual int getEnable(int32_t handle);
+ virtual int64_t getDelay(int32_t handle);
+ virtual int64_t getMinDelay() { return -1; } // stub
+
+ /*
+ * following four APIs need further implementation for MPL's reference
+ * (look into .cpp for detailed information, also refer to 3rd-party's
+ * readEvents() for relevant APIs)
+ */
+ int readSample(long *data, int64_t *timestamp);
+ void fillList(struct sensor_t *list);
+ void getOrientationMatrix(signed char *orient);
+ int getAccuracy();
+ long getSensitivity();
+
+ private:
+ YamahaSensor *mCompassSensor;
+};
+
+#endif /* COMPASS_SENSOR_H */
diff --git a/mpu/libsensors/InputEventReader.cpp b/mpu/libsensors/InputEventReader.cpp
new file mode 100755
index 0000000..62afbf0
--- /dev/null
+++ b/mpu/libsensors/InputEventReader.cpp
@@ -0,0 +1,114 @@
+/*
+* Copyright (C) 2012 Invensense, Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#define LOG_NDEBUG 0
+
+#include <stdint.h>
+#include <errno.h>
+#include <unistd.h>
+#include <poll.h>
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <linux/input.h>
+
+#include <cutils/log.h>
+
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+
+struct input_event;
+
+InputEventCircularReader::InputEventCircularReader(size_t numEvents)
+ : mBuffer(new input_event[numEvents * 2]),
+ mBufferEnd(mBuffer + numEvents),
+ mHead(mBuffer),
+ mCurr(mBuffer),
+ mFreeSpace(numEvents)
+{
+ mLastFd = -1;
+}
+
+InputEventCircularReader::~InputEventCircularReader()
+{
+ delete [] mBuffer;
+}
+
+#define INPUT_EVENT_DEBUG (0)
+ssize_t InputEventCircularReader::fill(int fd)
+{
+ size_t numEventsRead = 0;
+ mLastFd = fd;
+
+ LOGV_IF(INPUT_EVENT_DEBUG,
+ "DEBUG:%s enter, fd=%d\n", __PRETTY_FUNCTION__, fd);
+ if (mFreeSpace) {
+ const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event));
+ if (nread < 0 || nread % sizeof(input_event)) {
+ //LOGE("Partial event received nread=%d, required=%d",
+ // nread, sizeof(input_event));
+ //LOGE("FD trying to read is: %d");
+ // we got a partial event!!
+ if (INPUT_EVENT_DEBUG) {
+ LOGV_IF(nread < 0, "DEBUG:%s exit nread < 0\n",
+ __PRETTY_FUNCTION__);
+ LOGV_IF(nread % sizeof(input_event),
+ "DEBUG:%s exit nread %% sizeof(input_event)\n",
+ __PRETTY_FUNCTION__);
+ }
+ return (nread < 0 ? -errno : -EINVAL);
+ }
+
+ numEventsRead = nread / sizeof(input_event);
+ if (numEventsRead) {
+ mHead += numEventsRead;
+ mFreeSpace -= numEventsRead;
+ if (mHead > mBufferEnd) {
+ size_t s = mHead - mBufferEnd;
+ memcpy(mBuffer, mBufferEnd, s * sizeof(input_event));
+ mHead = mBuffer + s;
+ }
+ }
+ }
+
+ LOGV_IF(INPUT_EVENT_DEBUG, "DEBUG:%s exit, numEventsRead:%d\n",
+ __PRETTY_FUNCTION__, numEventsRead);
+ return numEventsRead;
+}
+
+ssize_t InputEventCircularReader::readEvent(input_event const** events)
+{
+ *events = mCurr;
+ ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace;
+ LOGV_IF(INPUT_EVENT_DEBUG, "DEBUG:%s fd:%d, available:%d\n",
+ __PRETTY_FUNCTION__, mLastFd, (int)available);
+ return (available ? 1 : 0);
+}
+
+void InputEventCircularReader::next()
+{
+ mCurr++;
+ mFreeSpace++;
+ if (mCurr >= mBufferEnd) {
+ mCurr = mBuffer;
+ }
+ ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace;
+ LOGV_IF(INPUT_EVENT_DEBUG, "DEBUG:%s fd:%d, still available:%d\n",
+ __PRETTY_FUNCTION__, mLastFd, (int)available);
+}
+
diff --git a/mpu/libsensors/InputEventReader.h b/mpu/libsensors/InputEventReader.h
new file mode 100755
index 0000000..9e8db31
--- /dev/null
+++ b/mpu/libsensors/InputEventReader.h
@@ -0,0 +1,50 @@
+/*
+* Copyright (C) 2012 Invensense, Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef ANDROID_INPUT_EVENT_READER_H
+#define ANDROID_INPUT_EVENT_READER_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "SensorBase.h"
+
+/*****************************************************************************/
+
+struct input_event;
+
+class InputEventCircularReader
+{
+ struct input_event* const mBuffer;
+ struct input_event* const mBufferEnd;
+ struct input_event* mHead;
+ struct input_event* mCurr;
+ ssize_t mFreeSpace;
+ int mLastFd;
+
+public:
+ InputEventCircularReader(size_t numEvents);
+ ~InputEventCircularReader();
+ ssize_t fill(int fd);
+ ssize_t readEvent(input_event const** events);
+ void next();
+};
+
+/*****************************************************************************/
+
+#endif // ANDROID_INPUT_EVENT_READER_H
diff --git a/mpu/libsensors/LICENSE-libinvensense_mpl.TXT b/mpu/libsensors/LICENSE-libinvensense_mpl.TXT
new file mode 100755
index 0000000..930f931
--- /dev/null
+++ b/mpu/libsensors/LICENSE-libinvensense_mpl.TXT
@@ -0,0 +1,217 @@
+SOFTWARE LICENSE AGREEMENT
+
+Unless you and InvenSense Corporation ("InvenSense") execute a separate written
+software license agreement governing use of the accompanying software, this
+software is licensed to you under the terms of this Software License
+Agreement ("Agreement").
+
+ANY USE, REPRODUCTION OR DISTRIBUTION OF THE SOFTWARE CONSTITUTES YOUR
+ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS.
+
+1.1. "InvenSense Product" means any of the proprietary integrated circuit
+product(s) sold by InvenSense with which the Software was designed to be used,
+or their successors.
+
+1.2. "Licensee" means you or if you are accepting on behalf of an entity
+then the entity and its affiliates exercising rights under, and complying
+with all of the terms of this Agreement.
+
+1.3. "Software" shall mean that software made available by InvenSense to
+Licensee in binary code form with this Agreement.
+
+2. LICENSE GRANT; OWNERSHIP
+
+2.1. License Grants. Subject to the terms and conditions of this Agreement,
+InvenSense hereby grants to Licensee a non-exclusive, non-transferable,
+royalty-free license (i) to use and integrate the Software in conjunction
+with any other software; and (ii) to reproduce and distribute the Software
+complete, unmodified and only for use with a InvenSense Product.
+
+2.2. Restriction on Modification. If and to the extent that the Software is
+designed to be compliant with any published communications standard
+(including, without limitation, DOCSIS, HomePNA, IEEE, and ITU standards),
+Licensee may not make any modifications to the Software that would cause the
+Software or the accompanying InvenSense Products to be incompatible with such
+standard.
+
+2.3. Restriction on Distribution. Licensee shall only distribute the
+Software (a) under the terms of this Agreement and a copy of this Agreement
+accompanies such distribution, and (b) agrees to defend and indemnify
+InvenSense and its licensors from and against any damages, costs, liabilities,
+settlement amounts and/or expenses (including attorneys' fees) incurred in
+connection with any claim, lawsuit or action by any third party that arises
+or results from the use or distribution of any and all Software by the
+Licensee except as contemplated herein.
+
+2.4. Proprietary Notices. Licensee shall not remove, efface or obscure any
+copyright or trademark notices from the Software. Licensee shall include
+reproductions of the InvenSense copyright notice with each copy of the
+Software, except where such Software is embedded in a manner not readily
+accessible to the end user. Licensee acknowledges that any symbols,
+trademarks, tradenames, and service marks adopted by InvenSense to identify the
+Software belong to InvenSense and that Licensee shall have no rights therein.
+
+2.5. Ownership. InvenSense shall retain all right, title and interest,
+including all intellectual property rights, in and to the Software. Licensee
+hereby covenants that it will not assert any claim that the Software created
+by or for InvenSense infringe any intellectual property right owned or
+controlled by Licensee.
+
+2.6. No Other Rights Granted; Restrictions. Apart from the license rights
+expressly set forth in this Agreement, InvenSense does not grant and Licensee
+does not receive any ownership right, title or interest nor any security
+interest or other interest in any intellectual property rights relating to
+the Software, nor in any copy of any part of the foregoing. No license is
+granted to Licensee in any human readable code of the Software (source code).
+Licensee shall not (i) use, license, sell or otherwise distribute the
+Software except as provided in this Agreement, (ii) attempt to reverse
+engineer, decompile or disassemble any portion of the Software; or (iii) use
+the Software or other material in violation of any applicable law or
+regulation, including but not limited to any regulatory agency, such as FCC,
+rules.
+
+3. NO WARRANTY OR SUPPORT
+
+3.1. No Warranty. THE SOFTWARE IS OFFERED "AS IS," AND INVENSENSE GRANTS AND
+LICENSEE RECEIVES NO WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, BY STATUTE,
+COMMUNICATION OR CONDUCT WITH LICENSEE, OR OTHERWISE. INVENSENSE SPECIFICALLY
+DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A SPECIFIC
+PURPOSE OR NONINFRINGEMENT CONCERNING THE SOFTWARE OR ANY UPGRADES TO OR
+DOCUMENTATION FOR THE SOFTWARE. WITHOUT LIMITATION OF THE ABOVE, INVENSENSE
+GRANTS NO WARRANTY THAT THE SOFTWARE IS ERROR-FREE OR WILL OPERATE WITHOUT
+INTERRUPTION, AND GRANTS NO WARRANTY REGARDING ITS USE OR THE RESULTS
+THEREFROM INCLUDING, WITHOUT LIMITATION, ITS CORRECTNESS, ACCURACY OR
+RELIABILITY.
+
+3.2. No Support. Nothing in this agreement shall obligate InvenSense to
+provide any support for the Software. InvenSense may, but shall be under no
+obligation to, correct any defects in the Software and/or provide updates to
+licensees of the Software. Licensee shall make reasonable efforts to
+promptly report to InvenSense any defects it finds in the Software, as an aid
+to creating improved revisions of the Software.
+
+3.3. Dangerous Applications. The Software is not designed, intended, or
+certified for use in components of systems intended for the operation of
+weapons, weapons systems, nuclear installations, means of mass
+transportation, aviation, life-support computers or equipment (including
+resuscitation equipment and surgical implants), pollution control, hazardous
+substances management, or for any other dangerous application in which the
+failure of the Software could create a situation where personal injury or
+death may occur. Licensee understands that use of the Software in such
+applications is fully at the risk of Licensee.
+
+4. TERM AND TERMINATION
+
+4.1. Termination. This Agreement will automatically terminate if Licensee
+fails to comply with any of the terms and conditions hereof. In such event,
+Licensee must destroy all copies of the Software and all of its component
+parts.
+
+4.2. Effect Of Termination. Upon any termination of this Agreement, the
+rights and licenses granted to Licensee under this Agreement shall
+immediately terminate.
+
+4.3. Survival. The rights and obligations under this Agreement which by
+their nature should survive termination will remain in effect after
+expiration or termination of this Agreement.
+
+5. CONFIDENTIALITY
+
+5.1. Obligations. Licensee acknowledges and agrees that any documentation
+relating to the Software, and any other information (if such other
+information is identified as confidential or should be recognized as
+confidential under the circumstances) provided to Licensee by InvenSense
+hereunder (collectively, "Confidential Information") constitute the
+confidential and proprietary information of InvenSense, and that Licensee's
+protection thereof is an essential condition to Licensee's use and possession
+of the Software. Licensee shall retain all Confidential Information in
+strict confidence and not disclose it to any third party or use it in any way
+except under a written agreement with terms and conditions at least as
+protective as the terms of this Section. Licensee will exercise at least the
+same amount of diligence in preserving the secrecy of the Confidential
+Information as it uses in preserving the secrecy of its own most valuable
+confidential information, but in no event less than reasonable diligence.
+Information shall not be considered Confidential Information if and to the
+extent that it: (i) was in the public domain at the time it was disclosed or
+has entered the public domain through no fault of Licensee; (ii) was known to
+Licensee, without restriction, at the time of disclosure as proven by the
+files of Licensee in existence at the time of disclosure; or (iii) becomes
+known to Licensee, without restriction, from a source other than InvenSense
+without breach of this Agreement by Licensee and otherwise not in violation
+of InvenSense's rights.
+
+5.2. Return of Confidential Information. Notwithstanding the foregoing, all
+documents and other tangible objects containing or representing InvenSense
+Confidential Information and all copies thereof which are in the possession
+of Licensee shall be and remain the property of InvenSense, and shall be
+promptly returned to InvenSense upon written request by InvenSense or upon
+termination of this Agreement.
+
+6. LIMITATION OF LIABILITY
+TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL INVENSENSE OR ANY OF
+INVENSENSE'S LICENSORS HAVE ANY LIABILITY FOR ANY INDIRECT, INCIDENTAL,
+SPECIAL, OR CONSEQUENTIAL DAMAGES, HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER FOR BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE) OR
+OTHERWISE, ARISING OUT OF THIS AGREEMENT, INCLUDING BUT NOT LIMITED TO LOSS
+OF PROFITS, EVEN IF SUCH PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES. IN NO EVENT WILL INVENSENSE'S LIABILITY WHETHER IN CONTRACT, TORT
+(INCLUDING NEGLIGENCE), OR OTHERWISE, EXCEED THE AMOUNT PAID BY LICENSEE FOR
+SOFTWARE UNDER THIS AGREEMENT. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING
+ANY FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY.
+
+7. MISCELLANEOUS
+
+7.1. Export Regulations. YOU UNDERSTAND AND AGREE THAT THE SOFTWARE IS
+SUBJECT TO UNITED STATES AND OTHER APPLICABLE EXPORT-RELATED LAWS AND
+REGULATIONS AND THAT YOU MAY NOT EXPORT, RE-EXPORT OR TRANSFER THE SOFTWARE
+OR ANY DIRECT PRODUCT OF THE SOFTWARE EXCEPT AS PERMITTED UNDER THOSE LAWS.
+WITHOUT LIMITING THE FOREGOING, EXPORT, RE-EXPORT OR TRANSFER OF THE SOFTWARE
+TO CUBA, IRAN, NORTH KOREA, SUDAN AND SYRIA IS PROHIBITED.
+
+7.2 Assignment. This Agreement shall be binding upon and inure to the
+benefit of the parties and their respective successors and assigns, provided,
+however that Licensee may not assign this Agreement or any rights or
+obligation hereunder, directly or indirectly, by operation of law or
+otherwise, without the prior written consent of InvenSense, and any such
+attempted assignment shall be void. Notwithstanding the foregoing, Licensee
+may assign this Agreement to a successor to all or substantially all of its
+business or assets to which this Agreement relates that is not a competitor
+of InvenSense.
+
+7.3. Governing Law; Venue. This Agreement shall be governed by the laws of
+California without regard to any conflict-of-laws rules, and the United
+Nations Convention on Contracts for the International Sale of Goods is hereby
+excluded. The sole jurisdiction and venue for actions related to the subject
+matter hereof shall be the state and federal courts located in the County of
+Orange, California, and both parties hereby consent to such jurisdiction and
+venue.
+
+7.4. Severability. All terms and provisions of this Agreement shall, if
+possible, be construed in a manner which makes them valid, but in the event
+any term or provision of this Agreement is found by a court of competent
+jurisdiction to be illegal or unenforceable, the validity or enforceability
+of the remainder of this Agreement shall not be affected if the illegal or
+unenforceable provision does not materially affect the intent of this
+Agreement. If the illegal or unenforceable provision materially affects the
+intent of the parties to this Agreement, this Agreement shall become
+terminated.
+
+7.5. Equitable Relief. Licensee hereby acknowledges that its breach of this
+Agreement would cause irreparable harm and significant injury to InvenSense
+that may be difficult to ascertain and that a remedy at law would be
+inadequate. Accordingly, Licensee agrees that InvenSense shall have the right
+to seek and obtain immediate injunctive relief to enforce obligations under
+the Agreement in addition to any other rights and remedies it may have.
+
+7.6. Waiver. The waiver of, or failure to enforce, any breach or default
+hereunder shall not constitute the waiver of any other or subsequent breach
+or default.
+
+7.7. Entire Agreement. This Agreement sets forth the entire Agreement
+between the parties and supersedes any and all prior proposals, agreements
+and representations between them, whether written or oral concerning the
+Software. This Agreement may be changed only by mutual agreement of the
+parties in writing.
+
diff --git a/mpu/libsensors/LightSensor.cpp b/mpu/libsensors/LightSensor.cpp
new file mode 100755
index 0000000..04a637f
--- /dev/null
+++ b/mpu/libsensors/LightSensor.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 Samsung
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <poll.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/select.h>
+#include <cutils/log.h>
+#include <pthread.h>
+
+#include "LightSensor.h"
+
+LightSensor::LightSensor()
+ : SamsungSensorBase("/dev/lightsensor", "lightsensor-level", ABS_MISC)
+{
+ mPendingEvent.sensor = ID_L;
+ mPendingEvent.type = SENSOR_TYPE_LIGHT;
+ mPreviousLight = -1;
+}
+
+int LightSensor::handleEnable(int en) {
+ mPreviousLight = -1;
+//cvte_zxl add
+ int flags = en ? 1 : 0;
+ int err = 0;
+ if (flags != mEnabled) {
+ if (!mEnabled) {
+ open_device();
+ }
+ err = ioctl(dev_fd, LIGHTSENSOR_IOCTL_ENABLE, &flags);
+ err = err<0 ? -errno : 0;
+ ALOGE_IF(err, "LIGHTSENSOR_IOCTL_ENABLE failed (%s)", strerror(-err));
+ if (!err) {
+ mEnabled = en ? 1 : 0;
+ }
+ if (!mEnabled) {
+ close_device();
+ }
+ }
+ return err;
+//end of cvte_zxl add
+}
+
+bool LightSensor::handleEvent(input_event const *event) {
+ if (event->value == -1) {
+ return false;
+ }
+ mPendingEvent.light = indexToValue(event->value);
+ // mPendingEvent.light = event->value;
+ if (mPendingEvent.light != mPreviousLight) {
+ mPreviousLight = mPendingEvent.light;
+ return true;
+ }
+ return true;
+}
+
+//cvt_zxl modify
+float LightSensor::indexToValue(size_t index) const {
+ /* Driver gives a rolling average adc value. We convert it lux levels. */
+ static const float lux_value[] = {
+ 33.0,
+ 66.0,
+ 108.0,
+ 192.0,
+ 365.0,
+ 720.0,
+ 1080.0,
+ 1440.0,
+ };
+ if (index < 0 || index > ARRAY_SIZE(lux_value) - 1) {
+ index = 7;
+ }
+ return lux_value[index];
+}
+//end of cvt_zxl modify
diff --git a/mpu/libsensors/LightSensor.h b/mpu/libsensors/LightSensor.h
new file mode 100755
index 0000000..38357d8
--- /dev/null
+++ b/mpu/libsensors/LightSensor.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 Samsung
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_LIGHT_SENSOR_H
+#define ANDROID_LIGHT_SENSOR_H
+
+//cvt_zxl add
+#include <linux/types.h>
+#include <linux/ioctl.h>
+//end of cvt_zxl add
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "sensors.h"
+#include "SamsungSensorBase.h"
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+//cvte_zxl add
+#define LIGHTSENSOR_IOCTL_MAGIC 'l'
+#define LIGHTSENSOR_IOCTL_GET_ENABLED _IOR(LIGHTSENSOR_IOCTL_MAGIC, 1, int *)
+#define LIGHTSENSOR_IOCTL_ENABLE _IOW(LIGHTSENSOR_IOCTL_MAGIC, 2, int *)
+#define LIGHTSENSOR_IOCTL_DISABLE _IOW(LIGHTSENSOR_IOCTL_MAGIC, 3, int *)
+//end of cvte_zxl add
+
+struct input_event;
+
+class LightSensor:public SamsungSensorBase {
+
+ float mPreviousLight;
+ virtual int handleEnable(int en);
+ virtual bool handleEvent(input_event const * event);
+ float indexToValue(size_t index) const;
+public:
+ LightSensor();
+};
+
+/*****************************************************************************/
+
+#endif /* ANDROID_LIGHT_SENSOR_H */
diff --git a/mpu/libsensors/MPL integration notes.txt b/mpu/libsensors/MPL integration notes.txt
new file mode 100755
index 0000000..1caa703
--- /dev/null
+++ b/mpu/libsensors/MPL integration notes.txt
@@ -0,0 +1,53 @@
+Notes on integrating Invensense MPL with Gingerbread
+----------------------------------------------------
+VERSION : 3.5.0
+
+First things: Make sure the platform is properly set up
+ -- modify the kernel to include the MPU3050 driver
+ -- be aware that the MPU3050 driver introduces kernel defines that may conflict with existing drivers
+ -- ak8975 in particular
+ -- double check the bus attachment for the compass and the mpu
+ -- double check the mounting matrices
+ -- check that the modified kernel boots and that /dev/mpu and /dev/mpuirq and /dev/accelirq exist and have usable permissions
+ -- run the driver selftest to confirm that the driver is working and i2c traffic to the mpu works
+
+ -- mpl libraries are processor specific! this was a problem for us, as we tried to run a nexus1 lib on the ventana platform and the two processors do not have the same fpu.
+
+
+The HAL implementation Invensense provides for Gingerbread is derived from the implementation
+provided by Google for NexusS (crespo). A comparison of the Invensense code and the original google
+code will be very instructive, especially as regards using additional sensors (like light and pressure).
+
+Any existing HAL implementations need to be disabled. Check in vendor/ directories as well as the device/ subtree.
+
+To install the invensense implementation:
+ 1) copy the provided vendor/invensense directory to your android tree
+ 2) modify Android.mk in vendor/invensense/libsensors to generate a sensors.[platform].so appropriate for your platform
+ 3) copy (or link) the appropriate mpl shared libraries into vendor/invensense/libsensors
+ 4) copy or link the mpl headers under vendor/invensense/libsensors
+ -or-
+ modify the Android.mk in vendor/invensense/libsensors to point to the installed mpl headers on your system
+
+ 5) mmm -B vendor/invensense
+ 6) make (to regenerate the .img files)
+ 7) update the flash or system disk for your platform using the new img files
+
+
+The FroYo version of the MPL integration included additional APIs (not specified by google) which allowed java apps
+to call MPL management functions. These apis are available on Gingerbread via the SysApi class. Java code for this class
+is included with the RollDice app. The java code needs to be added to any project which requires access to the SysApi functions.
+
+As of version 3.3, a gestures extension is also included with the gingerbread sensor manager package. This extension is not an offical
+Android api, but does attempt to mimic the sensors API. The implementation of the gesture extension places limitations on integrating
+other sensors (such as light and pressure). The MPL and it's sensors claim IDs 0-16. No other sensors are allowed to use these ids.
+
+Additionally, the MPL may make use of several file handles including /dev/mpu, /dev/mpuirq, /dev/accelirq, /dev/compassirq, and /dev/timerirq.
+These filehandles must have appropriate permissions after boot. Also note that there is some special handling in sensors_mpl for the multiple
+file handles.
+
+
+
+
+
+
+
diff --git a/mpu/libsensors/MPLSensor.cpp b/mpu/libsensors/MPLSensor.cpp
new file mode 100755
index 0000000..3b5ba1d
--- /dev/null
+++ b/mpu/libsensors/MPLSensor.cpp
@@ -0,0 +1,3576 @@
+/*
+* Copyright (C) 2012 Invensense, Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#define LOG_NDEBUG 0
+//see also the EXTRA_VERBOSE define in the MPLSensor.h header file
+
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <float.h>
+#include <poll.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <sys/select.h>
+#include <sys/syscall.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include <cutils/log.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include <string.h>
+#include <linux/input.h>
+#include <utils/Atomic.h>
+
+#include "MPLSensor.h"
+#include "MPLSupport.h"
+#include "sensor_params.h"
+
+#include "invensense.h"
+#include "invensense_adv.h"
+#include "ml_stored_data.h"
+#include "ml_load_dmp.h"
+#include "ml_sysfs_helper.h"
+
+//#define TESTING
+
+//#define NO_COMPASS
+#ifdef NO_COMPASS
+//#define NO_ORI
+//#define NO_RV
+//#define NO_LA
+//#define NO_GR
+#endif
+
+#ifdef THIRD_PARTY_ACCEL
+# warning "Third party accel"
+# define USE_THIRD_PARTY_ACCEL (1)
+#else
+# define USE_THIRD_PARTY_ACCEL (0)
+#endif
+
+#define MAX_SYSFS_ATTRB (sizeof(struct sysfs_attrbs) / sizeof(char*))
+
+/******************************************************************************/
+/* MPL interface misc. */
+/******************************************************************************/
+static int hertz_request = 200;
+
+#define DEFAULT_MPL_GYRO_RATE (20000L) //us
+#define DEFAULT_MPL_COMPASS_RATE (20000L) //us
+
+#define DEFAULT_HW_GYRO_RATE (100) //Hz
+#define DEFAULT_HW_ACCEL_RATE (20) //ms
+#define DEFAULT_HW_COMPASS_RATE (20000000L) //ns
+#define DEFAULT_HW_AKMD_COMPASS_RATE (200000000L) //ns
+
+/* convert ns to hardware units */
+#define HW_GYRO_RATE_NS (1000000000LL / rate_request) // to Hz
+#define HW_ACCEL_RATE_NS (rate_request / (1000000L)) // to ms
+#define HW_COMPASS_RATE_NS (rate_request) // to ns
+
+/* convert Hz to hardware units */
+#define HW_GYRO_RATE_HZ (hertz_request)
+#define HW_ACCEL_RATE_HZ (1000 / hertz_request)
+#define HW_COMPASS_RATE_HZ (1000000000LL / hertz_request)
+
+#define MAX_RATE 1000000LL
+#define RATE_200HZ 5000000LL
+#define RATE_15HZ 66667000LL
+#define RATE_5HZ 200000000LL
+
+#ifndef NO_COMPASS
+static struct sensor_t sSensorList[] =
+{
+ {"MPL Gyroscope", "Invensense", 1,
+ SENSORS_GYROSCOPE_HANDLE,
+ SENSOR_TYPE_GYROSCOPE, 2000.0f, 1.0f, 0.5f, 10000, 0, 0, 0, 0, 0, 0, {}},
+ {"MPL Raw Gyroscope", "Invensense", 1,
+ SENSORS_RAW_GYROSCOPE_HANDLE,
+ SENSOR_TYPE_GYROSCOPE_UNCALIBRATED, 2000.0f, 1.0f, 0.5f, 10000, 0, 0, 0, 0, 0, 0, {}},
+ {"MPL Accelerometer", "Invensense", 1,
+ SENSORS_ACCELERATION_HANDLE,
+ SENSOR_TYPE_ACCELEROMETER, 10240.0f, 1.0f, 0.5f, 10000, 0, 0, 0, 0, 0, 0, {}},
+ {"MPL Magnetic Field", "Invensense", 1,
+ SENSORS_MAGNETIC_FIELD_HANDLE,
+ SENSOR_TYPE_MAGNETIC_FIELD, 10240.0f, 1.0f, 0.5f, 10000, 0, 0, 0, 0, 0, 0, {}},
+ {"MPL Orientation", "Invensense", 1,
+ SENSORS_ORIENTATION_HANDLE,
+ SENSOR_TYPE_ORIENTATION, 360.0f, 1.0f, 9.7f, 10000, 0, 0, 0, 0, 0, 0, {}},
+ {"MPL Rotation Vector", "Invensense", 1,
+ SENSORS_ROTATION_VECTOR_HANDLE,
+ SENSOR_TYPE_ROTATION_VECTOR, 10240.0f, 1.0f, 0.5f, 10000,0, 0, 0, 0, 0, 0, {}},
+ {"MPL Linear Acceleration", "Invensense", 1,
+ SENSORS_LINEAR_ACCEL_HANDLE,
+ SENSOR_TYPE_LINEAR_ACCELERATION, 10240.0f, 1.0f, 0.5f, 10000, 0, 0, 0, 0, 0, 0, {}},
+ {"MPL Gravity", "Invensense", 1,
+ SENSORS_GRAVITY_HANDLE,
+ SENSOR_TYPE_GRAVITY, 10240.0f, 1.0f, 0.5f, 10000, 0, 0, 0, 0, 0, 0, {}},
+#ifdef ENABLE_DMP_SCREEN_AUTO_ROTATION
+ {"MPL Screen Orientation", "Invensense ", 1,
+ SENSORS_SCREEN_ORIENTATION_HANDLE,
+ SENSOR_TYPE_SCREEN_ORIENTATION, 100.0f, 1.0f, 1.1f, 0, 0, 0, 0, 0, 0, 0, {}},
+#endif
+};
+#endif//#ifndef NO_COMPASS
+
+/* calibration data transfer function from 92 bytes to 96 bytes*/
+#include "data_builder.h"
+struct data_header_t {
+ long size;
+ uint32_t checksum;
+ unsigned int key;
+};
+#define DEFAULT_KEY 29681
+#define INV_DB_SAVE_KEY_92 53395
+
+struct inv_db_save_92_t {
+ /** Compass Bias in Chip Frame in Hardware units scaled by 2^16 */
+ long compass_bias[3];
+ /** Gyro Bias in Chip Frame in Hardware units scaled by 2^16 */
+ long gyro_bias[3];
+ /** Temperature when *gyro_bias was stored. */
+ long gyro_temp;
+ /** Accel Bias in Chip Frame in Hardware units scaled by 2^16 */
+ long accel_bias[3];
+ /** Temperature when accel bias was stored. */
+ long accel_temp;
+ long gyro_temp_slope[3];
+ /** Sensor Accuracy */
+ int gyro_accuracy;
+ int accel_accuracy;
+ int compass_accuracy;
+};
+
+#define CAL_BIN_SIZE_503 92
+#define CAL_BIN_SIZE_514 96
+
+extern "C" {
+inv_error_t inv_calbin_92to96(void)
+{
+ unsigned char *calData= NULL, *cur, *calData2, *cur2;
+ inv_error_t result = 0;
+ size_t bytesRead = 0;
+ struct inv_db_save_92_t *db_save92;
+ struct inv_db_save_t *db_save;
+ struct data_header_t *hd;
+
+ LOGV("%\n", __func__);
+
+ result = inv_read_cal(&calData, &bytesRead);
+ if(result != INV_SUCCESS) {
+ LOGE("Could not load cal file - "
+ "aborting\n");
+ goto free_mem_n_exit;
+ }
+
+ if (bytesRead != CAL_BIN_SIZE_503) {
+ LOGV("file size != %d(size=%d), not MA503 selftest cal bin\n", CAL_BIN_SIZE_503, bytesRead);
+ goto free_mem_n_exit;
+ }
+
+ cur = calData;
+ cur += sizeof(struct data_header_t);
+ hd = (struct data_header_t *)cur;
+ if (hd->key != INV_DB_SAVE_KEY_92) {
+ LOGV("not MA503 selftest cal bin\n");
+ goto free_mem_n_exit;
+ }
+
+ cur += sizeof(struct data_header_t);
+ db_save92 = (struct inv_db_save_92_t *)cur;
+
+ calData2 = (unsigned char *)malloc(CAL_BIN_SIZE_514);
+ if (calData2==NULL) {
+ LOGE("Could not allocate buffer of %d bytes - aborting\n", CAL_BIN_SIZE_514);
+ goto free_mem_n_exit;
+ }
+ cur2 = calData2;
+ cur2 += 2*sizeof(struct data_header_t);
+ db_save = (struct inv_db_save_t *)cur2;
+
+ db_save->compass_bias[0] = db_save92->compass_bias[0];
+ db_save->compass_bias[1] = db_save92->compass_bias[1];
+ db_save->compass_bias[2] = db_save92->compass_bias[2];
+ db_save->gyro_bias[0] = db_save92->gyro_bias[0];
+ db_save->gyro_bias[1] = db_save92->gyro_bias[1];
+ db_save->gyro_bias[2] = db_save92->gyro_bias[2];
+ db_save->gyro_temp = db_save92->gyro_temp;
+ db_save->gyro_bias_tc_set = 0;
+ db_save->accel_bias[0] = db_save92->accel_bias[0];
+ db_save->accel_bias[1] = db_save92->accel_bias[1];
+ db_save->accel_bias[2] = db_save92->accel_bias[2];
+ db_save->accel_temp = db_save92->accel_temp;
+ db_save->gyro_temp_slope[0] = db_save92->gyro_temp_slope[0];
+ db_save->gyro_temp_slope[1] = db_save92->gyro_temp_slope[1];
+ db_save->gyro_temp_slope[2] = db_save92->gyro_temp_slope[2];
+ db_save->gyro_accuracy = db_save92->gyro_accuracy;
+ db_save->accel_accuracy = db_save92->accel_accuracy;
+ db_save->compass_accuracy = db_save92->compass_accuracy;
+
+ cur2 = calData2;
+ cur2 += sizeof(struct data_header_t);
+ hd = (struct data_header_t *)cur2;
+ hd->size = sizeof(struct inv_db_save_t);
+ hd->key = INV_DB_SAVE_KEY;
+ cur2 += sizeof(struct data_header_t);
+ hd->checksum = inv_checksum(cur2, hd->size);
+
+ cur2 = calData2;
+ hd = (struct data_header_t *)cur2;
+ hd->size = CAL_BIN_SIZE_514;
+ hd->key = DEFAULT_KEY;
+ cur2 += sizeof(struct data_header_t);
+ hd->checksum = inv_checksum(cur2, hd->size-sizeof(struct data_header_t));
+
+ result = inv_write_cal(calData2, CAL_BIN_SIZE_514);
+ if (result != INV_SUCCESS) {
+ LOGE("Could not store calibrated data on file - "
+ "error %d - aborting\n", result);
+ }
+
+ free(calData2);
+free_mem_n_exit:
+ free(calData);
+ return result;
+}
+}
+/* end of calibration data transfer function*/
+MPLSensor *MPLSensor::gMPLSensor = NULL;
+
+extern "C" {
+void procData_cb_wrapper()
+{
+ if(MPLSensor::gMPLSensor) {
+ MPLSensor::gMPLSensor->cbProcData();
+ }
+}
+
+void setCallbackObject(MPLSensor* gbpt)
+{
+ MPLSensor::gMPLSensor = gbpt;
+}
+
+MPLSensor* getCallbackObject() {
+ return MPLSensor::gMPLSensor;
+}
+
+} // end of extern C
+
+#ifdef INV_PLAYBACK_DBG
+static FILE *logfile = NULL;
+#endif
+
+#if CAL_DATA_AUTO_LOAD == 1
+#define cal_data_auto_load_path "/cal_data_auto_load"
+
+static int self_test_auto_load_state_read(void)
+{
+ int count = 0;
+ char raw_buf[10];
+ short raw = 0;
+ char sysfs_path[100];
+ int res = 0;
+ int fd;
+
+ inv_get_sysfs_path(sysfs_path);
+ strcat(sysfs_path, cal_data_auto_load_path);
+
+ fd = open(sysfs_path, O_RDONLY);
+ res = errno;
+ if(fd < 0){
+ LOGE("HAL: %s: Open of %s failed with '%s' (%d)",
+ __func__, sysfs_path, strerror(res), res);
+ return -1;
+ }
+
+ memset(raw_buf, 0, sizeof(raw_buf));
+ count = read_attribute_sensor(fd, raw_buf, sizeof(raw_buf));
+ if(count < 1) {
+ LOGE("HAL:error reading auto load state");
+ close(fd);
+ return -1;
+ }
+ count = sscanf(raw_buf, "%hd", &raw);
+ if(count < 0) {
+ LOGE("HAL:auto load state data is invalid");
+ close(fd);
+ return -1;
+ }
+ LOGV_IF(EXTRA_VERBOSE, "HAL:auto load state read = %d, count = %d", raw, count);
+ close(fd);
+ return (int)raw;
+}
+
+static void self_test_auto_load_state_write(int en)
+{
+ char sysfs_path[MAX_SYSFS_NAME_LEN];
+ int res = 0;
+ int fd;
+
+ inv_get_sysfs_path(sysfs_path);
+ strcat(sysfs_path, cal_data_auto_load_path);
+
+ fd = open(sysfs_path, O_WRONLY);
+ res = errno;
+ if(fd < 0){
+ LOGE("HAL: %s: Open of %s failed with '%s' (%d)",
+ __func__, sysfs_path, strerror(res), res);
+ return;
+ }
+
+ if((res=enable_sysfs_sensor(fd, en)) < 0) {
+ LOGE("HAL:Couldn't write auto load state");
+ } else {
+ LOGV_IF(EXTRA_VERBOSE, "HAL:auto load state write = %d", en);
+ }
+}
+#endif
+
+/*******************************************************************************
+ * MPLSensor class implementation
+ ******************************************************************************/
+
+// following extended initializer list would only be available with -std=c++11
+// or -std=gnu+11
+MPLSensor::MPLSensor(CompassSensor *compass, int (*m_pt2AccelCalLoadFunc)(long *))
+ : SensorBase(NULL, NULL),
+ mNewData(0),
+ mMasterSensorMask(INV_ALL_SENSORS),
+ mLocalSensorMask(0),
+ mPollTime(-1),
+ mHaveGoodMpuCal(0),
+ mGyroAccuracy(0),
+ mAccelAccuracy(0),
+ mCompassAccuracy(0),
+ mSampleCount(0),
+ dmp_orient_fd(-1),
+ mDmpOrientationEnabled(0),
+ mEnabled(0),
+ mOldEnabledMask(0),
+ mAccelInputReader(4),
+ mGyroInputReader(32),
+ mTempScale(0),
+ mTempOffset(0),
+ mTempCurrentTime(0),
+#if CAL_DATA_AUTO_LOAD == 1
+ mCalDataCurrentTime(0),
+#endif
+ mAccelScale(2),
+ mGyroScale(2000),
+ mPendingMask(0),
+ mSensorMask(0),
+ mFeatureActiveMask(0) {
+ VFUNC_LOG;
+
+ inv_error_t rv;
+ int i, fd;
+ char *port = NULL;
+ char *ver_str;
+ unsigned long mSensorMask;
+ int res;
+ FILE *fptr;
+
+ mCompassSensor = compass;
+
+ LOGV_IF(EXTRA_VERBOSE,
+ "HAL:MPLSensor constructor : NumSensors = %d", NumSensors);
+
+ pthread_mutex_init(&mMplMutex, NULL);
+ pthread_mutex_init(&mHALMutex, NULL);
+ memset(mGyroOrientation, 0, sizeof(mGyroOrientation));
+ memset(mAccelOrientation, 0, sizeof(mAccelOrientation));
+
+#ifdef INV_PLAYBACK_DBG
+ LOGV_IF(PROCESS_VERBOSE, "HAL:inv_turn_on_data_logging");
+ logfile = fopen("/data/playback.bin", "w+");
+ if (logfile)
+ inv_turn_on_data_logging(logfile);
+#endif
+
+ /* setup sysfs paths */
+ inv_init_sysfs_attributes();
+
+ /* get chip name */
+ if (inv_get_chip_name(chip_ID) != INV_SUCCESS) {
+ LOGE("HAL:ERR- Failed to get chip ID\n");
+ } else {
+ LOGV_IF(PROCESS_VERBOSE, "HAL:Chip ID= %s\n", chip_ID);
+ }
+
+ enable_iio_sysfs();
+
+ /* turn on power state */
+ onPower(1);
+
+ /* reset driver master enable */
+ masterEnable(0);
+
+ if (isLowPowerQuatEnabled() || isDmpDisplayOrientationOn()) {
+ /* Load DMP image if capable, ie. MPU6xxx/9xxx */
+ loadDMP();
+ }
+
+ /* open temperature fd for temp comp */
+ LOGV_IF(EXTRA_VERBOSE, "HAL:gyro temperature path: %s", mpu.temperature);
+ gyro_temperature_fd = open(mpu.temperature, O_RDONLY);
+ if (gyro_temperature_fd == -1) {
+ LOGE("HAL:could not open temperature node");
+ } else {
+ LOGV_IF(EXTRA_VERBOSE,
+ "HAL:temperature_fd opened: %s", mpu.temperature);
+ }
+
+ /* read gyro FSR to calculate accel scale later */
+ char gyroBuf[5];
+ int count = 0;
+ LOGV_IF(SYSFS_VERBOSE,
+ "HAL:sysfs:cat %s (%lld)", mpu.gyro_fsr, getTimestamp());
+
+ fd = open(mpu.gyro_fsr, O_RDONLY);
+ if(fd < 0) {
+ LOGE("HAL:Error opening gyro FSR");
+ } else {
+ memset(gyroBuf, 0, sizeof(gyroBuf));
+ count = read_attribute_sensor(fd, gyroBuf, sizeof(gyroBuf));
+ if(count < 1) {
+ LOGE("HAL:Error reading gyro FSR");
+ } else {
+ count = sscanf(gyroBuf, "%ld", &mGyroScale);
+ if(count)
+ LOGV_IF(EXTRA_VERBOSE, "HAL:Gyro FSR used %ld", mGyroScale);
+ }
+ close(fd);
+ }
+
+ /* read accel FSR to calcuate accel scale later */
+ if (USE_THIRD_PARTY_ACCEL == 0) {
+ char buf[3];
+ int count = 0;
+ LOGV_IF(SYSFS_VERBOSE,
+ "HAL:sysfs:cat %s (%lld)", mpu.accel_fsr, getTimestamp());
+
+ fd = open(mpu.accel_fsr, O_RDONLY);
+ if(fd < 0) {
+ LOGE("HAL:Error opening accel FSR");
+ } else {
+ memset(buf, 0, sizeof(buf));
+ count = read_attribute_sensor(fd, buf, sizeof(buf));
+ if(count < 1) {
+ LOGE("HAL:Error reading accel FSR");
+ } else {
+ count = sscanf(buf, "%d", &mAccelScale);
+ if(count)
+ LOGV_IF(EXTRA_VERBOSE, "HAL:Accel FSR used %d", mAccelScale);
+ }
+ close(fd);
+ }
+ }
+
+ /* initialize sensor data */
+ memset(mPendingEvents, 0, sizeof(mPendingEvents));
+
+ mPendingEvents[RotationVector].version = sizeof(sensors_event_t);
+ mPendingEvents[RotationVector].sensor = ID_RV;
+ mPendingEvents[RotationVector].type = SENSOR_TYPE_ROTATION_VECTOR;
+ mPendingEvents[RotationVector].acceleration.status
+ = SENSOR_STATUS_ACCURACY_HIGH;
+
+ mPendingEvents[LinearAccel].version = sizeof(sensors_event_t);
+ mPendingEvents[LinearAccel].sensor = ID_LA;
+ mPendingEvents[LinearAccel].type = SENSOR_TYPE_LINEAR_ACCELERATION;
+ mPendingEvents[LinearAccel].acceleration.status
+ = SENSOR_STATUS_ACCURACY_HIGH;
+
+ mPendingEvents[Gravity].version = sizeof(sensors_event_t);
+ mPendingEvents[Gravity].sensor = ID_GR;
+ mPendingEvents[Gravity].type = SENSOR_TYPE_GRAVITY;
+ mPendingEvents[Gravity].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
+
+ mPendingEvents[Gyro].version = sizeof(sensors_event_t);
+ mPendingEvents[Gyro].sensor = ID_GY;
+ mPendingEvents[Gyro].type = SENSOR_TYPE_GYROSCOPE;
+ mPendingEvents[Gyro].gyro.status = SENSOR_STATUS_ACCURACY_HIGH;
+
+ mPendingEvents[RawGyro].version = sizeof(sensors_event_t);
+ mPendingEvents[RawGyro].sensor = ID_RG;
+ mPendingEvents[RawGyro].type = SENSOR_TYPE_GYROSCOPE_UNCALIBRATED;
+ mPendingEvents[RawGyro].gyro.status = SENSOR_STATUS_ACCURACY_HIGH;
+
+ mPendingEvents[Accelerometer].version = sizeof(sensors_event_t);
+ mPendingEvents[Accelerometer].sensor = ID_A;
+ mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER;
+ mPendingEvents[Accelerometer].acceleration.status
+ = SENSOR_STATUS_ACCURACY_HIGH;
+
+ /* Invensense compass calibration */
+ mPendingEvents[MagneticField].version = sizeof(sensors_event_t);
+ mPendingEvents[MagneticField].sensor = ID_M;
+ mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD;
+ mPendingEvents[MagneticField].magnetic.status =
+ SENSOR_STATUS_ACCURACY_HIGH;
+
+ mPendingEvents[Orientation].version = sizeof(sensors_event_t);
+ mPendingEvents[Orientation].sensor = ID_O;
+ mPendingEvents[Orientation].type = SENSOR_TYPE_ORIENTATION;
+ mPendingEvents[Orientation].orientation.status
+ = SENSOR_STATUS_ACCURACY_HIGH;
+
+ mHandlers[RotationVector] = &MPLSensor::rvHandler;
+ mHandlers[LinearAccel] = &MPLSensor::laHandler;
+ mHandlers[Gravity] = &MPLSensor::gravHandler;
+ mHandlers[Gyro] = &MPLSensor::gyroHandler;
+ mHandlers[RawGyro] = &MPLSensor::rawGyroHandler;
+ mHandlers[Accelerometer] = &MPLSensor::accelHandler;
+ mHandlers[MagneticField] = &MPLSensor::compassHandler;
+ mHandlers[Orientation] = &MPLSensor::orienHandler;
+
+ for (int i = 0; i < NumSensors; i++) {
+ mDelays[i] = 1000000000LL;
+ }
+
+ (void)inv_get_version(&ver_str);
+ LOGV_IF(PROCESS_VERBOSE, "%s\n", ver_str);
+
+ /* setup MPL */
+ inv_constructor_init();
+
+ inv_calbin_92to96();
+
+ /* load calibration file from /data/inv_cal_data.bin */
+ rv = inv_load_calibration();
+ if(rv == INV_SUCCESS)
+ LOGV_IF(PROCESS_VERBOSE, "HAL:Calibration file successfully loaded");
+ else
+ LOGE("HAL:Could not open or load MPL calibration file (%d)", rv);
+
+#if CAL_DATA_AUTO_LOAD == 1
+ //set to "0" after loading calibration
+ self_test_auto_load_state_write(0);
+#endif
+
+ /* takes external accel calibration load workflow */
+ if( m_pt2AccelCalLoadFunc != NULL)
+ {
+ long accel_offset[3];
+ long tmp_offset[3];
+ int result = m_pt2AccelCalLoadFunc(accel_offset);
+ if(result)
+ LOGW("HAL:Vendor accelerometer calibration file load failed %d\n",
+ result);
+ else {
+ LOGW("HAL:Vendor accelerometer calibration file successfully "
+ "loaded");
+ inv_get_accel_bias(tmp_offset, NULL);
+ LOGV_IF(PROCESS_VERBOSE,
+ "HAL:Original accel offset, %ld, %ld, %ld\n",
+ tmp_offset[0], tmp_offset[1], tmp_offset[2]);
+ inv_set_accel_bias(accel_offset, mAccelAccuracy);
+ inv_get_accel_bias(tmp_offset, NULL);
+ LOGV_IF(PROCESS_VERBOSE, "HAL:Set accel offset, %ld, %ld, %ld\n",
+ tmp_offset[0], tmp_offset[1], tmp_offset[2]);
+ }
+ }
+ /* end of external accel calibration load workflow */
+
+ inv_set_device_properties();
+
+ /* disable driver master enable the first sensor goes on */
+ masterEnable(0);
+ enableGyro(0);
+ enableAccel(0);
+ enableCompass(0);
+
+ if ( isLowPowerQuatEnabled() ) {
+ enableLPQuaternion(0);
+ }
+
+ if (isDmpDisplayOrientationOn()) {
+ // open DMP Orient Fd
+ openDmpOrientFd();
+
+ enableDmpOrientation(!isDmpScreenAutoRotationEnabled());
+ }
+
+ onPower(0);
+}
+
+void MPLSensor::enable_iio_sysfs()
+{
+ VFUNC_LOG;
+
+ char iio_trigger_name[MAX_CHIP_ID_LEN], iio_device_node[MAX_CHIP_ID_LEN];
+ FILE *tempFp = NULL;
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo 1 > %s (%lld)",
+ mpu.in_timestamp_en, getTimestamp());
+ // fopen()/open() would both be okay for sysfs access
+ // developers could choose what they want
+ // with fopen(), benefits from fprintf()/fscanf() would be available
+ tempFp = fopen(mpu.in_timestamp_en, "w");
+ if (tempFp == NULL) {
+ LOGE("HAL:could not open timestamp enable");
+ } else {
+ if(fprintf(tempFp, "%d", 1) < 0) {
+ LOGE("HAL:could not enable timestamp");
+ }
+ fclose(tempFp);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE,
+ "HAL:sysfs:cat %s (%lld)",
+ mpu.trigger_name, getTimestamp());
+ tempFp = fopen(mpu.trigger_name, "r");
+ if (tempFp == NULL) {
+ LOGE("HAL:could not open trigger name");
+ } else {
+ if (fscanf(tempFp, "%s", iio_trigger_name) < 0) {
+ LOGE("HAL:could not read trigger name");
+ }
+ fclose(tempFp);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %s > %s (%lld)",
+ iio_trigger_name, mpu.current_trigger, getTimestamp());
+ tempFp = fopen(mpu.current_trigger, "w");
+ if (tempFp == NULL) {
+ LOGE("HAL:could not open current trigger");
+ } else {
+ if (fprintf(tempFp, "%s", iio_trigger_name) < 0) {
+ LOGE("HAL:could not write current trigger");
+ }
+ fclose(tempFp);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ IIO_BUFFER_LENGTH, mpu.buffer_length, getTimestamp());
+ tempFp = fopen(mpu.buffer_length, "w");
+ if (tempFp == NULL) {
+ LOGE("HAL:could not open buffer length");
+ } else {
+ if (fprintf(tempFp, "%d", IIO_BUFFER_LENGTH) < 0) {
+ LOGE("HAL:could not write buffer length");
+ }
+ fclose(tempFp);
+ }
+
+ inv_get_iio_device_node(iio_device_node);
+ iio_fd = open(iio_device_node, O_RDONLY);
+ if (iio_fd < 0) {
+ LOGE("HAL:could not open iio device node");
+ } else {
+ LOGV_IF(PROCESS_VERBOSE, "HAL:iio iio_fd opened : %d", iio_fd);
+ }
+}
+
+int MPLSensor::inv_constructor_init()
+{
+ VFUNC_LOG;
+
+ inv_error_t result = inv_init_mpl();
+ if (result) {
+ LOGE("HAL:inv_init_mpl() failed");
+ return result;
+ }
+ result = inv_constructor_default_enable();
+ result = inv_start_mpl();
+ if (result) {
+ LOGE("HAL:inv_start_mpl() failed");
+ LOG_RESULT_LOCATION(result);
+ return result;
+ }
+
+ return result;
+}
+
+int MPLSensor::inv_constructor_default_enable()
+{
+ VFUNC_LOG;
+
+ inv_error_t result;
+
+/*******************************************************************************
+
+********************************************************************************
+
+The InvenSense binary file (libmplmpu.so) is subject to Google's standard terms
+and conditions as accepted in the click-through agreement required to download
+this library.
+The library includes, but is not limited to the following function calls:
+inv_enable_quaternion().
+
+ANY VIOLATION OF SUCH TERMS AND CONDITIONS WILL BE STRICTLY ENFORCED.
+
+********************************************************************************
+
+*******************************************************************************/
+
+ result = inv_enable_quaternion();
+ if (result) {
+ LOGE("HAL:Cannot enable quaternion\n");
+ return result;
+ }
+
+#if 0
+ result = inv_enable_in_use_auto_calibration();
+ if (result) {
+ return result;
+ }
+ LOGV("HAL:in_use_auto_calibration, enable");
+#else
+ mAccelAccuracy = 3;
+ inv_set_accel_bias(NULL, 3);
+ LOGV("HAL:in_use_auto_calibration, disable");
+#endif
+
+ // result = inv_enable_motion_no_motion();
+ result = inv_enable_fast_nomot();
+ if (result) {
+ return result;
+ }
+
+ result = inv_enable_gyro_tc();
+ if (result) {
+ return result;
+ }
+
+ result = inv_enable_hal_outputs();
+ if (result) {
+ return result;
+ }
+
+ if (!mCompassSensor->providesCalibration()) {
+ /* Invensense compass calibration */
+ LOGV_IF(PROCESS_VERBOSE, "HAL:Invensense vector compass cal enabled");
+ result = inv_enable_vector_compass_cal();
+ if (result) {
+ LOG_RESULT_LOCATION(result);
+ return result;
+ } else {
+ mFeatureActiveMask |= INV_COMPASS_CAL;
+ }
+
+ // specify MPL's trust weight, used by compass algorithms
+ inv_vector_compass_cal_sensitivity(3);
+
+ result = inv_enable_compass_bias_w_gyro();
+ if (result) {
+ LOG_RESULT_LOCATION(result);
+ return result;
+ }
+
+ result = inv_enable_heading_from_gyro();
+ if (result) {
+ LOG_RESULT_LOCATION(result);
+ return result;
+ }
+
+ result = inv_enable_magnetic_disturbance();
+ if (result) {
+ LOG_RESULT_LOCATION(result);
+ return result;
+ }
+ }
+
+ result = inv_enable_9x_sensor_fusion();
+ if (result) {
+ LOG_RESULT_LOCATION(result);
+ return result;
+ } else {
+ // 9x sensor fusion enables Compass fit
+ mFeatureActiveMask |= INV_COMPASS_FIT;
+ }
+
+ result = inv_enable_no_gyro_fusion();
+ if (result) {
+ LOG_RESULT_LOCATION(result);
+ return result;
+ }
+
+ result = inv_enable_quat_accuracy_monitor();
+ if (result) {
+ LOG_RESULT_LOCATION(result);
+ return result;
+ }
+
+ return result;
+}
+
+/* TODO: create function pointers to calculate scale */
+void MPLSensor::inv_set_device_properties()
+{
+ VFUNC_LOG;
+
+ unsigned short orient;
+
+ inv_get_sensors_orientation();
+
+ inv_set_gyro_sample_rate(DEFAULT_MPL_GYRO_RATE);
+ inv_set_compass_sample_rate(DEFAULT_MPL_COMPASS_RATE);
+
+ /* gyro setup */
+ orient = inv_orientation_matrix_to_scalar(mGyroOrientation);
+ inv_set_gyro_orientation_and_scale(orient, mGyroScale << 15);
+ LOGI_IF(EXTRA_VERBOSE, "HAL: Set MPL Gyro Scale %ld", mGyroScale << 15);
+
+ /* accel setup */
+ orient = inv_orientation_matrix_to_scalar(mAccelOrientation);
+ /* use for third party accel input subsystem driver
+ inv_set_accel_orientation_and_scale(orient, 1LL << 22);
+ */
+ inv_set_accel_orientation_and_scale(orient, mAccelScale << 15);
+ LOGI_IF(EXTRA_VERBOSE, "HAL: Set MPL Accel Scale %ld", mAccelScale << 15);
+
+ /* compass setup */
+ signed char orientMtx[9];
+ mCompassSensor->getOrientationMatrix(orientMtx);
+ orient =
+ inv_orientation_matrix_to_scalar(orientMtx);
+ long sensitivity;
+ sensitivity = mCompassSensor->getSensitivity();
+ inv_set_compass_orientation_and_scale(orient, sensitivity);
+}
+
+void MPLSensor::loadDMP()
+{
+ int res, fd;
+ FILE *fptr;
+
+ if (isMpu3050()) {
+ //DMP support only for MPU6xxx/9xxx currently
+ return;
+ }
+
+ /* load DMP firmware */
+ LOGV_IF(SYSFS_VERBOSE,
+ "HAL:sysfs:cat %s (%lld)", mpu.firmware_loaded, getTimestamp());
+ fd = open(mpu.firmware_loaded, O_RDONLY);
+ if(fd < 0) {
+ LOGE("HAL:could not open dmp state");
+ } else {
+ if(inv_read_dmp_state(fd) == 0) {
+ LOGV_IF(EXTRA_VERBOSE, "HAL:load dmp: %s", mpu.dmp_firmware);
+ fptr = fopen(mpu.dmp_firmware, "w");
+ if(!fptr) {
+ LOGE("HAL:could not write to dmp");
+ } else {
+ int res = inv_load_dmp(fptr);
+ if(res < 0) {
+ LOGE("HAL:load DMP failed");
+ } else {
+ LOGV_IF(PROCESS_VERBOSE, "HAL:DMP loaded");
+ }
+ fclose(fptr);
+ }
+ } else {
+ LOGV_IF(PROCESS_VERBOSE, "HAL:DMP is already loaded");
+ }
+ }
+
+ // onDmp(1); //Can't enable here. See note onDmp()
+}
+
+void MPLSensor::inv_get_sensors_orientation()
+{
+ FILE *fptr;
+
+ // get gyro orientation
+ LOGV_IF(SYSFS_VERBOSE,
+ "HAL:sysfs:cat %s (%lld)", mpu.gyro_orient, getTimestamp());
+ fptr = fopen(mpu.gyro_orient, "r");
+ if (fptr != NULL) {
+ int om[9];
+ fscanf(fptr, "%d,%d,%d,%d,%d,%d,%d,%d,%d",
+ &om[0], &om[1], &om[2], &om[3], &om[4], &om[5],
+ &om[6], &om[7], &om[8]);
+ fclose(fptr);
+
+ LOGV_IF(EXTRA_VERBOSE,
+ "HAL:gyro mounting matrix: "
+ "%+d %+d %+d %+d %+d %+d %+d %+d %+d",
+ om[0], om[1], om[2], om[3], om[4], om[5], om[6], om[7], om[8]);
+
+ mGyroOrientation[0] = om[0];
+ mGyroOrientation[1] = om[1];
+ mGyroOrientation[2] = om[2];
+ mGyroOrientation[3] = om[3];
+ mGyroOrientation[4] = om[4];
+ mGyroOrientation[5] = om[5];
+ mGyroOrientation[6] = om[6];
+ mGyroOrientation[7] = om[7];
+ mGyroOrientation[8] = om[8];
+ } else {
+ LOGE("HAL:Couldn't read gyro mounting matrix");
+ }
+
+ // get accel orientation
+ LOGV_IF(SYSFS_VERBOSE,
+ "HAL:sysfs:cat %s (%lld)", mpu.accel_orient, getTimestamp());
+ fptr = fopen(mpu.accel_orient, "r");
+ if (fptr != NULL) {
+ int om[9];
+ fscanf(fptr, "%d,%d,%d,%d,%d,%d,%d,%d,%d",
+ &om[0], &om[1], &om[2], &om[3], &om[4], &om[5],
+ &om[6], &om[7], &om[8]);
+ fclose(fptr);
+
+ LOGV_IF(EXTRA_VERBOSE,
+ "HAL:accel mounting matrix: "
+ "%+d %+d %+d %+d %+d %+d %+d %+d %+d",
+ om[0], om[1], om[2], om[3], om[4], om[5], om[6], om[7], om[8]);
+
+ mAccelOrientation[0] = om[0];
+ mAccelOrientation[1] = om[1];
+ mAccelOrientation[2] = om[2];
+ mAccelOrientation[3] = om[3];
+ mAccelOrientation[4] = om[4];
+ mAccelOrientation[5] = om[5];
+ mAccelOrientation[6] = om[6];
+ mAccelOrientation[7] = om[7];
+ mAccelOrientation[8] = om[8];
+ } else {
+ LOGE("HAL:Couldn't read accel mounting matrix");
+ }
+}
+
+MPLSensor::~MPLSensor()
+{
+ VFUNC_LOG;
+
+ /* Close open fds */
+ if (iio_fd > 0)
+ close(iio_fd);
+ if( accel_fd > 0 )
+ close(accel_fd );
+ if (gyro_temperature_fd > 0)
+ close(gyro_temperature_fd);
+ if (sysfs_names_ptr)
+ free(sysfs_names_ptr);
+
+ if (isDmpDisplayOrientationOn()) {
+ closeDmpOrientFd();
+ }
+
+ /* Turn off Gyro master enable */
+ /* A workaround until driver handles it */
+ /* TODO: Turn off and close all sensors */
+ LOGV_IF(SYSFS_VERBOSE,
+ "HAL:sysfs:echo 0 > %s (%lld)", mpu.chip_enable, getTimestamp());
+ int fd = open(mpu.chip_enable, O_RDWR);
+ if(fd < 0) {
+ LOGE("HAL:could not open gyro chip enable");
+ } else {
+ if(enable_sysfs_sensor(fd, 0) < 0) {
+ LOGE("HAL:could not disable gyro master enable");
+ }
+ }
+
+#ifdef INV_PLAYBACK_DBG
+ inv_turn_off_data_logging();
+ fclose(logfile);
+#endif
+}
+
+#define GY_ENABLED (((1 << ID_GY) | (1 << ID_RG)) & enabled_sensors)
+#define A_ENABLED ((1 << ID_A) & enabled_sensors)
+#define M_ENABLED ((1 << ID_M) & enabled_sensors)
+#define O_ENABLED ((1 << ID_O) & enabled_sensors)
+#define LA_ENABLED ((1 << ID_LA) & enabled_sensors)
+#define GR_ENABLED ((1 << ID_GR) & enabled_sensors)
+#define RV_ENABLED ((1 << ID_RV) & enabled_sensors)
+
+/* TODO: this step is optional, remove? */
+int MPLSensor::setGyroInitialState()
+{
+ VFUNC_LOG;
+
+ int res = 0;
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ HW_GYRO_RATE_HZ, mpu.gyro_fifo_rate, getTimestamp());
+ int fd = open(mpu.gyro_fifo_rate, O_RDWR);
+ res = errno;
+ if(fd < 0) {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ mpu.gyro_fifo_rate, strerror(res), res);
+ return res;
+ }
+ res = write_attribute_sensor(fd, HW_GYRO_RATE_HZ);
+ if(res < 0) {
+ LOGE("HAL:write_attribute_sensor : error writing %s with %d",
+ mpu.gyro_fifo_rate, HW_GYRO_RATE_HZ);
+ return res;
+ }
+
+ // Setting LPF is deprecated
+
+ return 0;
+}
+
+/* this applies to BMA250 Input Subsystem Driver only */
+int MPLSensor::setAccelInitialState()
+{
+ VFUNC_LOG;
+
+ struct input_absinfo absinfo_x;
+ struct input_absinfo absinfo_y;
+ struct input_absinfo absinfo_z;
+ float value;
+ if (!ioctl(accel_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo_x) &&
+ !ioctl(accel_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo_y) &&
+ !ioctl(accel_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo_z)) {
+ value = absinfo_x.value;
+ mPendingEvents[Accelerometer].data[0] = value * CONVERT_A_X;
+ value = absinfo_y.value;
+ mPendingEvents[Accelerometer].data[1] = value * CONVERT_A_Y;
+ value = absinfo_z.value;
+ mPendingEvents[Accelerometer].data[2] = value * CONVERT_A_Z;
+ //mHasPendingEvent = true;
+ }
+ return 0;
+}
+
+int MPLSensor::onPower(int en)
+{
+ VFUNC_LOG;
+
+ int res = 0;
+ char buf[sizeof(int)+1];
+ int count, curr_power_state;
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, mpu.power_state, getTimestamp());
+ int tempFd = open(mpu.power_state, O_RDWR);
+ res = errno;
+ if(tempFd < 0){
+ LOGE("HAL:Open of %s failed with '%s' (%d)",
+ mpu.power_state, strerror(res), res);
+ } else {
+ // check and set new power state
+ count = read_attribute_sensor(tempFd, buf, sizeof(buf));
+ if(count < 1) {
+ LOGE("HAL:Error reading power state");
+ // will set power_state anyway
+ curr_power_state= -1;
+ } else {
+ sscanf(buf, "%d", &curr_power_state);
+ }
+
+ if (en!=curr_power_state) {
+ if((res=enable_sysfs_sensor(tempFd, en)) < 0) {
+ LOGE("HAL:Couldn't write power state");
+ }
+ } else {
+ LOGV_IF(EXTRA_VERBOSE,
+ "HAL:Power state already enable/disable curr=%d new=%d",
+ curr_power_state, en);
+ close(tempFd);
+ }
+ }
+ return res;
+}
+
+int MPLSensor::onDmp(int en)
+{
+ VFUNC_LOG;
+
+ int res = -1;
+ int status;
+
+ //Sequence to enable DMP
+ //1. Turn On power if not already on
+ //2. Load DMP image if not already loaded
+ //3. Either Gyro or Accel must be enabled/configured before next step
+ //4. Enable DMP
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:cat %s (%lld)",
+ mpu.firmware_loaded, getTimestamp());
+ if(read_sysfs_int(mpu.firmware_loaded, &status) < 0){
+ LOGE("HAL:ERR can't get firmware_loaded status");
+ } else if (status == 1) {
+ //Write only if curr DMP state <> request
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:cat %s (%lld)",
+ mpu.dmp_on, getTimestamp());
+ if (read_sysfs_int(mpu.dmp_on, &status) < 0) {
+ LOGE("HAL:ERR can't read DMP state");
+ } else if (status != en) {
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, mpu.dmp_on, getTimestamp());
+ if (write_sysfs_int(mpu.dmp_on, en) < 0) {
+ LOGE("HAL:ERR can't write dmp_on");
+ } else {
+ res = 0; //Indicate write successful
+ }
+ //Enable DMP interrupt
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, mpu.dmp_int_on, getTimestamp());
+ if (write_sysfs_int(mpu.dmp_int_on, en) < 0) {
+ LOGE("HAL:ERR can't en/dis DMP interrupt");
+ }
+ } else {
+ res = 0; //DMP already set as requested
+ }
+ } else {
+ LOGE("HAL:ERR No DMP image");
+ }
+ return res;
+}
+
+int MPLSensor::checkLPQuaternion(void)
+{
+ VFUNC_LOG;
+
+ return ((mFeatureActiveMask & INV_DMP_QUATERNION)? 1:0);
+}
+
+int MPLSensor::enableLPQuaternion(int en)
+{
+ VFUNC_LOG;
+
+ if (!en) {
+ enableQuaternionData(0);
+ onDmp(0);
+ mFeatureActiveMask &= ~INV_DMP_QUATERNION;
+ LOGV_IF(PROCESS_VERBOSE, "HAL:LP Quat disabled");
+ } else {
+ if (enableQuaternionData(1) < 0 || onDmp(1) < 0) {
+ LOGE("HAL:ERR can't enable LP Quaternion");
+ } else {
+ mFeatureActiveMask |= INV_DMP_QUATERNION;
+ LOGV_IF(PROCESS_VERBOSE, "HAL:LP Quat enabled");
+ }
+ }
+ return 0;
+}
+
+int MPLSensor::enableQuaternionData(int en)
+{
+ int res = 0;
+ VFUNC_LOG;
+
+ // Enable DMP quaternion
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, mpu.quaternion_on, getTimestamp());
+ if (write_sysfs_int(mpu.quaternion_on, en) < 0) {
+ LOGE("HAL:ERR can't write DMP quaternion_on");
+ res = -1; //Indicate an err
+ }
+
+ if (!en) {
+ LOGV_IF(PROCESS_VERBOSE, "HAL:Disabling quat scan elems");
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ 0, mpu.in_quat_r_en, getTimestamp());
+ if (write_sysfs_int(mpu.in_quat_r_en, 0) < 0) {
+ LOGE("HAL:ERR write in_quat_r_en");
+ }
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ 0, mpu.in_quat_x_en, getTimestamp());
+ if (write_sysfs_int(mpu.in_quat_x_en, 0) < 0) {
+ LOGE("HAL:ERR write in_quat_x_en");
+ }
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ 0, mpu.in_quat_y_en, getTimestamp());
+ if (write_sysfs_int(mpu.in_quat_y_en, 0) < 0) {
+ LOGE("HAL:ERR write in_quat_y_en");
+ }
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ 0, mpu.in_quat_z_en, getTimestamp());
+
+ if (write_sysfs_int(mpu.in_quat_z_en, 0) < 0) {
+ LOGE("HAL:ERR write in_quat_z_en");
+ }
+
+ LOGV_IF(EXTRA_VERBOSE, "HAL:DMP quaternion data was turned off");
+ inv_quaternion_sensor_was_turned_off();
+ } else {
+ LOGV_IF(PROCESS_VERBOSE, "HAL:Enabling quat scan elems");
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ 1, mpu.in_quat_r_en, getTimestamp());
+ if (write_sysfs_int(mpu.in_quat_r_en, 1) < 0) {
+ LOGE("HAL:ERR write in_quat_r_en");
+ }
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ 1, mpu.in_quat_x_en, getTimestamp());
+ if (write_sysfs_int(mpu.in_quat_x_en, 1) < 0) {
+ LOGE("HAL:ERR write in_quat_x_en");
+ }
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ 1, mpu.in_quat_y_en, getTimestamp());
+ if (write_sysfs_int(mpu.in_quat_y_en, 1) < 0) {
+ LOGE("HAL:ERR write in_quat_y_en");
+ }
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ 1, mpu.in_quat_z_en, getTimestamp());
+ if (write_sysfs_int(mpu.in_quat_z_en, 1) < 0) {
+ LOGE("HAL:ERR write in_quat_z_en");
+ }
+ }
+
+ return res;
+}
+
+int MPLSensor::enableTap(int en)
+{
+ VFUNC_LOG;
+
+ return 0;
+}
+
+int MPLSensor::enableFlick(int en)
+{
+ VFUNC_LOG;
+
+ return 0;
+}
+
+int MPLSensor::enablePedometer(int en)
+{
+ VFUNC_LOG;
+
+ return 0;
+}
+
+int MPLSensor::masterEnable(int en)
+{
+ VFUNC_LOG;
+
+ int res = 0;
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, mpu.chip_enable, getTimestamp());
+ int tempFd = open(mpu.chip_enable, O_RDWR);
+ res = errno;
+ if(tempFd < 0){
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ mpu.chip_enable, strerror(res), res);
+ return res;
+ }
+ res = enable_sysfs_sensor(tempFd, en);
+ return res;
+}
+
+int MPLSensor::enableGyro(int en)
+{
+ VFUNC_LOG;
+
+ int res = 0;
+
+ /* need to also turn on/off the master enable */
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, mpu.gyro_enable, getTimestamp());
+ int tempFd = open(mpu.gyro_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ mpu.gyro_enable, strerror(res), res);
+ }
+
+ if (!en) {
+ LOGV_IF(EXTRA_VERBOSE, "HAL:MPL:inv_gyro_was_turned_off");
+ inv_gyro_was_turned_off();
+ } else {
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, mpu.gyro_x_fifo_enable, getTimestamp());
+ tempFd = open(mpu.gyro_x_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ mpu.gyro_x_fifo_enable, strerror(res), res);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, mpu.gyro_y_fifo_enable, getTimestamp());
+ tempFd = open(mpu.gyro_y_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ mpu.gyro_y_fifo_enable, strerror(res), res);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, mpu.gyro_z_fifo_enable, getTimestamp());
+ tempFd = open(mpu.gyro_z_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ mpu.gyro_z_fifo_enable, strerror(res), res);
+ }
+ }
+
+ return res;
+}
+
+int MPLSensor::enableAccel(int en)
+{
+ VFUNC_LOG;
+
+ int res;
+
+ /* need to also turn on/off the master enable */
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, mpu.accel_enable, getTimestamp());
+ int tempFd = open(mpu.accel_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ mpu.accel_enable, strerror(res), res);
+ }
+
+ if (!en) {
+ LOGV_IF(EXTRA_VERBOSE, "HAL:MPL:inv_accel_was_turned_off");
+ inv_accel_was_turned_off();
+ } else {
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, mpu.accel_x_fifo_enable, getTimestamp());
+ tempFd = open(mpu.accel_x_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ mpu.accel_x_fifo_enable, strerror(res), res);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, mpu.accel_y_fifo_enable, getTimestamp());
+ tempFd = open(mpu.accel_y_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ mpu.accel_y_fifo_enable, strerror(res), res);
+ }
+
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ en, mpu.accel_z_fifo_enable, getTimestamp());
+ tempFd = open(mpu.accel_z_fifo_enable, O_RDWR);
+ res = errno;
+ if (tempFd > 0) {
+ res = enable_sysfs_sensor(tempFd, en);
+ } else {
+ LOGE("HAL:open of %s failed with '%s' (%d)",
+ mpu.accel_z_fifo_enable, strerror(res), res);
+ }
+ }
+
+ return res;
+}
+
+int MPLSensor::enableCompass(int en)
+{
+ VFUNC_LOG;
+
+ int res = mCompassSensor->enable(ID_M, en);
+ if (en == 0 || res != 0) {
+ LOGV_IF(EXTRA_VERBOSE, "HAL:MPL:inv_compass_was_turned_off");
+ inv_compass_was_turned_off();
+ }
+ return res;
+}
+
+void MPLSensor::computeLocalSensorMask(int enabled_sensors)
+{
+ VFUNC_LOG;
+
+ do {
+ if (LA_ENABLED || GR_ENABLED || RV_ENABLED || O_ENABLED) {
+ LOGV_IF(ENG_VERBOSE, "FUSION ENABLED");
+#ifndef NO_COMPASS
+ mLocalSensorMask = ALL_MPL_SENSORS_NP;
+#else
+ mLocalSensorMask = (INV_THREE_AXIS_ACCEL | INV_THREE_AXIS_GYRO);
+#endif
+ break;
+ }
+
+ if(!A_ENABLED && !M_ENABLED && !GY_ENABLED) {
+ /* Invensense compass cal */
+ LOGV_IF(ENG_VERBOSE, "ALL DISABLED");
+ mLocalSensorMask = 0;
+ break;
+ }
+
+ if (GY_ENABLED) {
+ LOGV_IF(ENG_VERBOSE, "G ENABLED");
+ mLocalSensorMask |= INV_THREE_AXIS_GYRO;
+ } else {
+ LOGV_IF(ENG_VERBOSE, "G DISABLED");
+ mLocalSensorMask &= ~INV_THREE_AXIS_GYRO;
+ }
+
+ if (A_ENABLED) {
+ LOGV_IF(ENG_VERBOSE, "A ENABLED");
+ mLocalSensorMask |= INV_THREE_AXIS_ACCEL;
+ } else {
+ LOGV_IF(ENG_VERBOSE, "A DISABLED");
+ mLocalSensorMask &= ~INV_THREE_AXIS_ACCEL;
+ }
+
+#ifndef NO_COMPASS
+ /* Invensense compass calibration */
+ if (M_ENABLED) {
+ LOGV_IF(ENG_VERBOSE, "M ENABLED");
+ mLocalSensorMask |= INV_THREE_AXIS_COMPASS;
+ } else {
+ LOGV_IF(ENG_VERBOSE, "M DISABLED");
+ mLocalSensorMask &= ~INV_THREE_AXIS_COMPASS;
+ }
+#endif
+ } while (0);
+}
+
+int MPLSensor::enableSensors(unsigned long sensors, int en, uint32_t changed) {
+ VFUNC_LOG;
+
+ inv_error_t res = -1;
+ int on = 1;
+ int off = 0;
+ int cal_stored = 0;
+
+ // Sequence to enable or disable a sensor
+ // 1. enable Power state
+ // 2. reset master enable (=0)
+ // 3. enable or disable a sensor
+ // 4. set master enable (=1)
+
+ if (isLowPowerQuatEnabled() ||
+ changed & ((1 << Gyro) | (1 << RawGyro) | (1 << Accelerometer) |
+ (mCompassSensor->isIntegrated() << MagneticField))) {
+ /* ensure power state is on */
+ onPower(1);
+
+ /* reset master enable */
+ res = masterEnable(0);
+ if(res < 0) {
+ return res;
+ }
+ }
+
+ LOGV_IF(PROCESS_VERBOSE, "HAL:enableSensors - sensors: 0x%0x",
+ (unsigned int)sensors);
+
+ if (changed & ((1 << Gyro) | (1 << RawGyro))) {
+ LOGV_IF(PROCESS_VERBOSE, "HAL:enableSensors - gyro %s",
+ (sensors & INV_THREE_AXIS_GYRO? "enable": "disable"));
+ res = enableGyro(!!(sensors & INV_THREE_AXIS_GYRO));
+ if(res < 0) {
+ return res;
+ }
+
+ if (!(sensors & INV_THREE_AXIS_GYRO) && !cal_stored) {
+ storeCalibration();
+ cal_stored = 1;
+ }
+ }
+
+ if (changed & (1 << Accelerometer)) {
+ LOGV_IF(PROCESS_VERBOSE, "HAL:enableSensors - accel %s",
+ (sensors & INV_THREE_AXIS_ACCEL? "enable": "disable"));
+ res = enableAccel(!!(sensors & INV_THREE_AXIS_ACCEL));
+ if(res < 0) {
+ return res;
+ }
+
+ if (!(sensors & INV_THREE_AXIS_ACCEL) && !cal_stored) {
+ storeCalibration();
+ cal_stored = 1;
+ }
+ }
+
+ if (changed & (1 << MagneticField)) {
+ LOGV_IF(PROCESS_VERBOSE, "HAL:enableSensors - compass %s",
+ (sensors & INV_THREE_AXIS_COMPASS? "enable": "disable"));
+ res = enableCompass(!!(sensors & INV_THREE_AXIS_COMPASS));
+ if(res < 0) {
+ return res;
+ }
+
+ if (!(sensors & INV_THREE_AXIS_COMPASS) && !cal_stored) {
+ storeCalibration();
+ cal_stored = 1;
+ }
+ }
+
+ if (isLowPowerQuatEnabled()) {
+ // Enable LP Quat
+ if ((mEnabled & ((1 << Orientation) | (1 << RotationVector)
+ | (1 << LinearAccel) | (1 << Gravity)))) {
+ if (!(changed & ((1 << Gyro)
+ | (1 << RawGyro)
+ | (1 << Accelerometer)
+ | (mCompassSensor->isIntegrated() << MagneticField)))
+ ) {
+ /* ensure power state is on */
+ onPower(1);
+ /* reset master enable */
+ res = masterEnable(0);
+ if(res < 0) {
+ return res;
+ }
+ }
+ if (!checkLPQuaternion()) {
+ enableLPQuaternion(1);
+ } else {
+ LOGV_IF(PROCESS_VERBOSE, "HAL:LP Quat already enabled");
+ }
+ } else if (checkLPQuaternion()) {
+ enableLPQuaternion(0);
+ }
+ }
+
+ if (changed & ((1 << Gyro) | (1 << RawGyro) | (1 << Accelerometer) |
+ (mCompassSensor->isIntegrated() << MagneticField))) {
+ if (sensors &
+ (INV_THREE_AXIS_GYRO
+ | INV_THREE_AXIS_ACCEL
+ | (INV_THREE_AXIS_COMPASS * mCompassSensor->isIntegrated()))) {
+ if (isLowPowerQuatEnabled() ||
+ (isDmpDisplayOrientationOn()
+ && (mDmpOrientationEnabled
+ || !isDmpScreenAutoRotationEnabled()))) {
+ // disable DMP event interrupt only (w/ data interrupt)
+ LOGV_IF(SYSFS_VERBOSE, "HAL:sysfs:echo %d > %s (%lld)",
+ 0, mpu.dmp_event_int_on, getTimestamp());
+ if (write_sysfs_int(mpu.dmp_event_int_on, 0) < 0) {
+ res = -1;
+ LOGE("HAL:ERR can't disable DMP event interrupt");
+ return res;
+ }
+ }
+
+ if (isDmpDisplayOrientationOn()
+ && (mDmpOrientationEnabled
+ || !isDmpScreenAutoRotationEnabled())) {
+ // enable DMP
+ onDmp(1);
+ res = enableAccel(on);
+ if(res < 0) {
+ return res;
+ }
+ if ((sensors & INV_THREE_AXIS_ACCEL) == 0) {
+ res = turnOffAccelFifo();
+ }
+ if(res < 0) {
+ return res;
+ }
+ }
+ res = masterEnable(1);
+ if(res < 0) {
+ return res;
+ }
+ } else { // all sensors idle -> reduce power
+ if (isDmpDisplayOrientationOn()
+ && (mDmpOrientationEnabled
+ || !isDmpScreenAutoRotationEnabled())) {
+ enableDmpOrientation(1);
+ }
+ else {
+ res = onPower(0);
+ if(res < 0) {
+ return res;
+ }
+ }
+
+ if (!cal_stored) {
+ storeCalibration();
+ cal_stored = 1;
+ }
+ }
+ } else if ((changed & ((!mCompassSensor->isIntegrated()) << MagneticField))
+ &&
+ !(sensors & (INV_THREE_AXIS_GYRO | INV_THREE_AXIS_ACCEL
+ | (INV_THREE_AXIS_COMPASS * (!mCompassSensor->isIntegrated()))))
+ ) {
+ if (!cal_stored) {
+ storeCalibration();
+ cal_stored = 1;
+ }
+ }
+
+ return res;
+}
+
+/* Store calibration file */
+void MPLSensor::storeCalibration()
+{
+ if(mHaveGoodMpuCal == true
+ || mAccelAccuracy >= 2
+ || mCompassAccuracy >= 3) {
+ int res = inv_store_calibration();
+ if (res) {
+ LOGE("HAL:Cannot store calibration on file");
+ } else {
+ LOGV_IF(PROCESS_VERBOSE, "HAL:Cal file updated");
+ }
+ }
+}
+
+void MPLSensor::cbProcData()
+{
+ mNewData = 1;
+ mSampleCount++;
+ LOGV_IF(EXTRA_VERBOSE, "HAL:new data");
+}
+
+/* these handlers transform mpl data into one of the Android sensor types */
+int MPLSensor::gyroHandler(sensors_event_t* s)
+{
+ VHANDLER_LOG;
+ int update;
+ update = inv_get_sensor_type_gyroscope(s->gyro.v, &s->gyro.status,
+ &s->timestamp);
+ LOGV_IF(HANDLER_DATA, "HAL:gyro data : %+f %+f %+f -- %lld - %d",
+ s->gyro.v[0], s->gyro.v[1], s->gyro.v[2], s->timestamp, update);
+ return update;
+}
+
+int MPLSensor::rawGyroHandler(sensors_event_t* s)
+{
+ VHANDLER_LOG;
+ int update;
+ update = inv_get_sensor_type_gyroscope_raw(s->gyro.v, &s->gyro.status,
+ &s->timestamp);
+ LOGV_IF(HANDLER_DATA, "HAL:raw gyro data : %+f %+f %+f -- %lld - %d",
+ s->gyro.v[0], s->gyro.v[1], s->gyro.v[2], s->timestamp, update);
+ return update;
+}
+
+int MPLSensor::accelHandler(sensors_event_t* s)
+{
+ VHANDLER_LOG;
+ int update;
+ update = inv_get_sensor_type_accelerometer(
+ s->acceleration.v, &s->acceleration.status, &s->timestamp);
+ LOGV_IF(HANDLER_DATA, "HAL:accel data : %+f %+f %+f -- %lld - %d",
+ s->acceleration.v[0], s->acceleration.v[1], s->acceleration.v[2],
+ s->timestamp, update);
+ mAccelAccuracy = s->acceleration.status;
+ return update;
+}
+
+int MPLSensor::compassHandler(sensors_event_t* s)
+{
+ VHANDLER_LOG;
+ int update;
+ update = inv_get_sensor_type_magnetic_field(
+ s->magnetic.v, &s->magnetic.status, &s->timestamp);
+ LOGV_IF(HANDLER_DATA, "HAL:compass data: %+f %+f %+f -- %lld - %d",
+ s->magnetic.v[0], s->magnetic.v[1], s->magnetic.v[2],
+ s->timestamp, update);
+ mCompassAccuracy = s->magnetic.status;
+ return update;
+}
+
+int MPLSensor::rvHandler(sensors_event_t* s)
+{
+ // rotation vector does not have an accuracy or status
+ VHANDLER_LOG;
+ int8_t status;
+ int update;
+ update = inv_get_sensor_type_rotation_vector(s->data, &status,
+ &s->timestamp);
+#ifdef NO_COMPASS
+ update = 1;
+#endif
+ update |= isCompassDisabled();
+ LOGV_IF(HANDLER_DATA, "HAL:rv data: %+f %+f %+f %+f - %+lld - %d",
+ s->data[0], s->data[1], s->data[2], s->data[3], s->timestamp,
+ update);
+ return update;
+}
+
+int MPLSensor::laHandler(sensors_event_t* s)
+{
+ VHANDLER_LOG;
+ int update;
+ update = inv_get_sensor_type_linear_acceleration(
+ s->gyro.v, &s->gyro.status, &s->timestamp);
+#ifdef NO_COMPASS
+ update = 1;
+#endif
+ update |= isCompassDisabled();
+ LOGV_IF(HANDLER_DATA, "HAL:la data: %+f %+f %+f - %lld - %d",
+ s->gyro.v[0], s->gyro.v[1], s->gyro.v[2], s->timestamp, update);
+ return update;
+}
+
+int MPLSensor::gravHandler(sensors_event_t* s)
+{
+ VHANDLER_LOG;
+ int update;
+ update = inv_get_sensor_type_gravity(s->gyro.v, &s->gyro.status,
+ &s->timestamp);
+ update |= isCompassDisabled();
+ LOGV_IF(HANDLER_DATA, "HAL:gr data: %+f %+f %+f - %lld - %d",
+ s->gyro.v[0], s->gyro.v[1], s->gyro.v[2], s->timestamp, update);
+ return update;
+}
+
+int MPLSensor::orienHandler(sensors_event_t* s)
+{
+ VHANDLER_LOG;
+ int update;
+ update = inv_get_sensor_type_orientation(
+ s->orientation.v, &s->orientation.status, &s->timestamp);
+#ifdef NO_COMPASS
+ update = 1;
+#endif
+ update |= isCompassDisabled();
+ LOGV_IF(HANDLER_DATA, "HAL:or data: %f %f %f - %lld - %d",
+ s->orientation.v[0], s->orientation.v[1], s->orientation.v[2],
+ s->timestamp, update);
+ return update;
+}
+
+int MPLSensor::enable(int32_t handle, int en)
+{
+ VFUNC_LOG;
+
+ android::String8 sname;
+ int what = -1, err = 0;
+
+ switch (handle) {
+ case ID_SO:
+ sname = "Screen Orientation";
+ LOGV_IF(PROCESS_VERBOSE, "HAL:enable - sensor %s (handle %d) %s -> %s",
+ sname.string(), handle,
+ (mDmpOrientationEnabled? "en": "dis"),
+ (en? "en" : "dis"));
+ enableDmpOrientation(en && isDmpDisplayOrientationOn());
+ mDmpOrientationEnabled = !!en;
+ return 0;
+ case ID_A:
+ what = Accelerometer;
+ sname = "Accelerometer";
+ break;
+#ifndef NO_COMPASS
+ case ID_M:
+ what = MagneticField;
+ sname = "MagneticField";
+ break;
+#endif
+#ifndef NO_ORI
+ case ID_O:
+ what = Orientation;
+ sname = "Orientation";
+ break;
+#endif
+ case ID_GY:
+ what = Gyro;
+ sname = "Gyro";
+ break;
+ case ID_RG:
+ what = RawGyro;
+ sname = "RawGyro";
+ break;
+#ifndef NO_GR
+ case ID_GR:
+ what = Gravity;
+ sname = "Gravity";
+ break;
+#endif
+#ifndef NO_RV
+ case ID_RV:
+ what = RotationVector;
+ sname = "RotationVector";
+ break;
+#endif
+#ifndef NO_LA
+ case ID_LA:
+ what = LinearAccel;
+ sname = "LinearAccel";
+ break;
+#endif
+ default: //this takes care of all the gestures
+ what = handle;
+ sname = "Others";
+ break;
+ }
+
+ if (uint32_t(what) >= NumSensors)
+ return -EINVAL;
+
+ int newState = en ? 1 : 0;
+
+ LOGV_IF(PROCESS_VERBOSE, "HAL:enable - sensor %s (handle %d) %s -> %s",
+ sname.string(), handle,
+ ((mEnabled & (1 << what)) ? "en" : "dis"),
+ ((uint32_t(newState) << what) ? "en" : "dis"));
+ LOGV_IF(PROCESS_VERBOSE,
+ "HAL:%s sensor state change what=%d", sname.string(), what);
+
+ // pthread_mutex_lock(&mMplMutex);
+ // pthread_mutex_lock(&mHALMutex);
+
+ if ((uint32_t(newState) << what) != (mEnabled & (1 << what))) {
+ uint32_t sensor_type;
+ short flags = newState;
+ uint32_t lastEnabled = mEnabled, changed = 0;
+ unsigned long sen_mask;
+ unsigned long sen_mask_old;
+
+#if CAL_DATA_AUTO_LOAD == 1
+ if (newState == 1)
+ {
+ if (self_test_auto_load_state_read()==1) {
+ inv_load_calibration();
+ //set to "0" after loading calibration
+ self_test_auto_load_state_write(0);
+ LOGV("HAL:Calibration file successfully loaded, %s", __func__);
+ }
+ }
+#endif
+
+ mEnabled &= ~(1 << what);
+ mEnabled |= (uint32_t(flags) << what);
+
+ LOGV_IF(PROCESS_VERBOSE, "HAL:handle = %d", handle);
+ LOGV_IF(PROCESS_VERBOSE, "HAL:flags = %d", flags);
+ sen_mask_old = mLocalSensorMask & mMasterSensorMask;
+ computeLocalSensorMask(mEnabled);
+ LOGV_IF(PROCESS_VERBOSE, "HAL:enable : mEnabled = %d", mEnabled);
+ sen_mask = mLocalSensorMask & mMasterSensorMask;
+ mSensorMask = sen_mask;
+ LOGV_IF(PROCESS_VERBOSE, "HAL:sen_mask= 0x%0lx", sen_mask);
+
+#if 1
+ if ((sen_mask_old & INV_THREE_AXIS_ACCEL) != (sen_mask & INV_THREE_AXIS_ACCEL)) {
+ changed |= (1 << Accelerometer);
+ }
+ if ((sen_mask_old & INV_THREE_AXIS_GYRO) != (sen_mask & INV_THREE_AXIS_GYRO)) {
+ changed |= (1 << Gyro);
+ }
+ if ((sen_mask_old & INV_THREE_AXIS_COMPASS) != (sen_mask & INV_THREE_AXIS_COMPASS)) {
+ changed |= (1 << MagneticField);
+ }
+#else
+ switch (what) {
+ case Gyro:
+ case RawGyro:
+ case Accelerometer:
+ case MagneticField:
+ if (!(mEnabled & ((1 << Orientation)
+ | (1 << RotationVector)
+ | (1 << LinearAccel)
+ | (1 << Gravity))) &&
+ ((lastEnabled & (1 << what)) != (mEnabled & (1 << what)))) {
+ changed |= (1 << what);
+ }
+ break;
+
+ case Orientation:
+ case RotationVector:
+ case LinearAccel:
+ case Gravity:
+ if ((en && !(lastEnabled
+ & ((1 << Orientation)
+ | (1 << RotationVector)
+ | (1 << LinearAccel)
+ | (1 << Gravity))))
+ ||
+ (!en && !(mEnabled
+ & ((1 << Orientation)
+ | (1 << RotationVector)
+ | (1 << LinearAccel)
+ | (1 << Gravity))))) {
+ for (int i = Gyro; i <= MagneticField; i++) {
+ if (!(mEnabled & (1 << i))) {
+ changed |= (1 << i);
+ }
+ }
+ }
+ break;
+ }
+#endif
+ LOGV_IF(PROCESS_VERBOSE, "HAL:changed = %d", changed);
+ enableSensors(sen_mask, flags, changed);
+ }
+
+ // pthread_mutex_unlock(&mMplMutex);
+ // pthread_mutex_unlock(&mHALMutex);
+
+#ifdef INV_PLAYBACK_DBG
+ /* apparently the logging needs to go through this sequence
+ to properly flush the log file */
+ inv_turn_off_data_logging();
+ fclose(logfile);
+ logfile = fopen("/data/playback.bin", "ab");
+ if (logfile)
+ inv_turn_on_data_logging(logfile);
+#endif
+
+ return err;
+}
+
+int MPLSensor::setDelay(int32_t handle, int64_t ns)
+{
+ VFUNC_LOG;
+
+ android::String8 sname;
+ int what = -1;
+
+ switch (handle) {
+ case ID_SO:
+ return update_delay();
+ case ID_A:
+ what = Accelerometer;
+ sname = "Accelerometer";
+ break;
+#ifndef NO_COMPASS
+ case ID_M:
+ what = MagneticField;
+ sname = "MagneticField";
+ break;
+#endif
+#ifndef NO_ORI
+ case ID_O:
+ what = Orientation;
+ sname = "Orientation";
+ break;
+#endif
+ case ID_GY:
+ what = Gyro;
+ sname = "Gyro";
+ break;
+ case ID_RG:
+ what = RawGyro;
+ sname = "RawGyro";
+ break;
+#ifndef NO_GR
+ case ID_GR:
+ what = Gravity;
+ sname = "Gravity";
+ break;
+#endif
+#ifndef NO_RV
+ case ID_RV:
+ what = RotationVector;
+ sname = "RotationVector";
+ break;
+#endif
+#ifndef NO_LA
+ case ID_LA:
+ what = LinearAccel;
+ sname = "LinearAccel";
+ break;
+#endif
+ default: // this takes care of all the gestures
+ what = handle;
+ sname = "Others";
+ break;
+ }
+
+#if 0
+ // skip the 1st call for enalbing sensors called by ICS/JB sensor service
+ static int counter_delay = 0;
+ if (!(mEnabled & (1 << what))) {
+ counter_delay = 0;
+ } else {
+ if (++counter_delay == 1) {
+ return 0;
+ }
+ else {
+ counter_delay = 0;
+ }
+ }
+#endif
+
+ if (uint32_t(what) >= NumSensors)
+ return -EINVAL;
+
+ if (ns < 0)
+ return -EINVAL;
+
+ LOGV_IF(PROCESS_VERBOSE,
+ "setDelay : %llu ns, (%.2f Hz)", ns, 1000000000.f / ns);
+
+ // limit all rates to reasonable ones */
+ if (ns < MAX_RATE) {
+ ns = MAX_RATE;
+ }
+
+ /* store request rate to mDelays arrary for each sensor */
+ mDelays[what] = ns;
+
+ switch (what) {
+ case Gyro:
+ case RawGyro:
+ case Accelerometer:
+ for (int i = Gyro;
+ i <= Accelerometer + mCompassSensor->isIntegrated();
+ i++) {
+ if (i != what && (mEnabled & (1 << i)) && ns > mDelays[i]) {
+ LOGV_IF(PROCESS_VERBOSE,
+ "HAL:ignore delay set due to sensor %d", i);
+ return 0;
+ }
+ }
+ break;
+
+ case MagneticField:
+ if (mCompassSensor->isIntegrated() &&
+ (((mEnabled & (1 << Gyro)) && ns > mDelays[Gyro]) ||
+ ((mEnabled & (1 << RawGyro)) && ns > mDelays[RawGyro]) ||
+ ((mEnabled & (1 << Accelerometer)) &&
+ ns > mDelays[Accelerometer]))) {
+ LOGV_IF(PROCESS_VERBOSE,
+ "HAL:ignore delay set due to gyro/accel");
+ return 0;
+ }
+ break;
+
+ case Orientation:
+ case RotationVector:
+ case LinearAccel:
+ case Gravity:
+ if (isLowPowerQuatEnabled()) {
+ LOGV_IF(PROCESS_VERBOSE,
+ "HAL:need to update delay due to LPQ");
+ break;
+ }
+
+ for (int i = 0; i < NumSensors; i++) {
+ if (i != what && (mEnabled & (1 << i)) && ns > mDelays[i]) {
+ LOGV_IF(PROCESS_VERBOSE,
+ "HAL:ignore delay set due to sensor %d", i);
+ return 0;
+ }
+ }
+ break;
+ }
+
+ // pthread_mutex_lock(&mHALMutex);
+ int res = update_delay();
+ // pthread_mutex_unlock(&mHALMutex);
+ return res;
+}
+
+int MPLSensor::update_delay(void)
+{
+ VHANDLER_LOG;
+
+ int res = 0;
+ int64_t got;
+
+ if (mEnabled) {
+ int64_t wanted = 1000000000LL;
+ int64_t wanted_3rd_party_sensor = 1000000000LL;
+
+ // Sequence to change sensor's FIFO rate
+ // 1. enable Power state
+ // 2. reset master enable
+ // 3. Update delay
+ // 4. set master enable
+
+ // ensure power on
+ onPower(1);
+
+ // reset master enable
+ masterEnable(0);
+
+ /* search the minimum delay requested across all enabled sensors */
+ for (int i = 0; i < NumSensors; i++) {
+ if (mEnabled & (1 << i)) {
+ int64_t ns = mDelays[i];
+ wanted = wanted < ns ? wanted : ns;
+ }
+ }
+
+ // same delay for 3rd party Accel or Compass
+ wanted_3rd_party_sensor = wanted;
+
+ /* mpl rate in us in future maybe different for
+ gyro vs compass vs accel */
+ int rateInus = (int)wanted / 1000LL;
+ int mplGyroRate = rateInus;
+ int mplAccelRate = rateInus;
+ int mplCompassRate = rateInus;
+
+ LOGV_IF(PROCESS_VERBOSE, "HAL:wanted rate for all sensors : "
+ "%llu ns, mpl rate: %d us, (%.2f Hz)",
+ wanted, rateInus, 1000000000.f / wanted);
+
+ /* set rate in MPL */
+ /* compass can only do 100Hz max */
+ inv_set_gyro_sample_rate(mplGyroRate);
+ inv_set_accel_sample_rate(mplAccelRate);
+ inv_set_compass_sample_rate(mplCompassRate);
+
+ /* TODO: Test 200Hz */
+ // inv_set_gyro_sample_rate(5000);
+ LOGV_IF(PROCESS_VERBOSE,