sensor-hal-emul: initial commit for emulator sensor HAL 43/69043/3
authorkibak.yoon <kibak.yoon@samsung.com>
Wed, 11 May 2016 08:21:00 +0000 (17:21 +0900)
committerkibak.yoon <kibak.yoon@samsung.com>
Wed, 11 May 2016 10:35:57 +0000 (19:35 +0900)
Change-Id: I0786cff7c9c8427ef0c974906b0685b439cd03d1
Signed-off-by: kibak.yoon <kibak.yoon@samsung.com>
37 files changed:
CMakeLists.txt [new file with mode: 0644]
LICENSE.APLv2 [new file with mode: 0644]
packaging/sensor-hal-emul.manifest [new file with mode: 0644]
packaging/sensor-hal-emul.spec [new file with mode: 0644]
sensor.xml.in [new file with mode: 0644]
src/accel/accel_device.cpp [new file with mode: 0644]
src/accel/accel_device.h [new file with mode: 0644]
src/create.cpp [new file with mode: 0644]
src/geomag/geomag_device.cpp [new file with mode: 0644]
src/geomag/geomag_device.h [new file with mode: 0644]
src/gyro/gyro_device.cpp [new file with mode: 0644]
src/gyro/gyro_device.h [new file with mode: 0644]
src/gyro_uncal/gyro_uncal_device.cpp [new file with mode: 0644]
src/gyro_uncal/gyro_uncal_device.h [new file with mode: 0644]
src/hrm/hrm_device.cpp [new file with mode: 0644]
src/hrm/hrm_device.h [new file with mode: 0644]
src/hrm_raw/hrm_raw_data_reader.cpp [new file with mode: 0644]
src/hrm_raw/hrm_raw_data_reader.h [new file with mode: 0644]
src/hrm_raw/hrm_raw_data_reader_standard.cpp [new file with mode: 0644]
src/hrm_raw/hrm_raw_data_reader_standard.h [new file with mode: 0644]
src/hrm_raw/hrm_raw_device.cpp [new file with mode: 0644]
src/hrm_raw/hrm_raw_device.h [new file with mode: 0644]
src/light/light_device.cpp [new file with mode: 0644]
src/light/light_device.h [new file with mode: 0644]
src/macro.h [new file with mode: 0644]
src/pressure/pressure_device.cpp [new file with mode: 0644]
src/pressure/pressure_device.h [new file with mode: 0644]
src/proxi/proxi_device.cpp [new file with mode: 0644]
src/proxi/proxi_device.h [new file with mode: 0644]
src/sensor_common.h [new file with mode: 0644]
src/sensor_config.cpp [new file with mode: 0644]
src/sensor_config.h [new file with mode: 0644]
src/sensor_log.h [new file with mode: 0644]
src/ultraviolet/uv_device.cpp [new file with mode: 0644]
src/ultraviolet/uv_device.h [new file with mode: 0644]
src/util.cpp [new file with mode: 0644]
src/util.h [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5d31095
--- /dev/null
@@ -0,0 +1,161 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(sensor-hal-emul CXX)
+INCLUDE(GNUInstallDirs)
+
+SET(ACCEL "ON")
+SET(GYRO "ON")
+SET(GYRO_UNCAL "OFF")
+SET(PROXIMITY "ON")
+SET(LIGHT "ON")
+SET(GEOMAG "ON")
+SET(GEOMAG_UNCAL "OFF")
+SET(HRM_RAW "OFF")
+SET(HRM "ON")
+SET(RV "OFF")
+SET(PRESSURE "ON")
+SET(PIR "OFF")
+SET(PIR_LONG "OFF")
+SET(TEMPERATURE "OFF")
+SET(HUMIDITY "OFF")
+SET(TEMP_HUMIDITY "OFF")
+SET(ULTRAVIOLET "ON")
+SET(DUST "OFF")
+SET(GSR "OFF")
+SET(SENSORHUB "OFF")
+
+# Common Options
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O2 -omit-frame-pointer -std=gnu++0x")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections")
+SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-section -Wl,--print-gc-section")
+MESSAGE("FLAGS: ${CMAKE_CXX_FLAGS}")
+MESSAGE("FLAGS: ${CMAKE_EXE_LINKER_FLAGS}")
+
+# Internal Debugging Options
+#ADD_DEFINITIONS(-Wall -g -D_DEBUG)
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(HAL_PKGS REQUIRED dlog glib-2.0 gio-2.0 gobject-2.0 vconf libxml-2.0)
+
+FOREACH(flag ${HAL_PKGS_CFLAGS})
+       SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src)
+FILE(GLOB SRCS src/*.cpp)
+
+IF("${ACCEL}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/accel/*.cpp)
+ADD_DEFINITIONS(-DENABLE_ACCEL)
+ENDIF()
+
+IF("${GYRO}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/gyro/*.cpp)
+ADD_DEFINITIONS(-DENABLE_GYRO)
+ENDIF()
+
+IF("${GYRO_UNCAL}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/gyro_uncal/*.cpp)
+ADD_DEFINITIONS(-DENABLE_GYRO_UNCAL)
+ENDIF()
+
+IF("${PROXIMITY}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/proxi/*.cpp)
+ADD_DEFINITIONS(-DENABLE_PROXIMITY)
+ENDIF()
+
+IF("${LIGHT}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/light/*.cpp)
+ADD_DEFINITIONS(-DENABLE_LIGHT)
+ENDIF()
+
+IF("${GEOMAG}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/geomag/*.cpp)
+ADD_DEFINITIONS(-DENABLE_GEOMAG)
+ENDIF()
+
+IF("${GEOMAG_UNCAL}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/geo_uncal/*.cpp)
+ADD_DEFINITIONS(-DENABLE_GEOMAG_UNCAL)
+ENDIF()
+
+IF("${HRM_RAW}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/hrm_raw/*.cpp)
+ADD_DEFINITIONS(-DENABLE_HRM_RAW)
+ENDIF()
+
+IF("${HRM}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/hrm/*.cpp)
+ADD_DEFINITIONS(-DENABLE_HRM)
+ENDIF()
+
+IF("${RV}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/rv/*.cpp)
+ADD_DEFINITIONS(-DENABLE_RV)
+ENDIF()
+
+IF("${PRESSURE}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/pressure/*.cpp)
+ADD_DEFINITIONS(-DENABLE_PRESSURE)
+ENDIF()
+
+IF("${ULTRAVIOLET}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/ultraviolet/*.cpp)
+ADD_DEFINITIONS(-DENABLE_UV)
+ENDIF()
+
+IF("${PIR}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/pir/*.cpp)
+ADD_DEFINITIONS(-DENABLE_PIR)
+ENDIF()
+
+IF("${PIR_LONG}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/pir_long/*.cpp)
+ADD_DEFINITIONS(-DENABLE_PIR_LONG)
+ENDIF()
+
+IF("${TEMPERATURE}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/temperature/*.cpp)
+ADD_DEFINITIONS(-DENABLE_TEMPERATURE)
+ENDIF()
+
+IF("${HUMIDITY}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/humidity/*.cpp)
+ADD_DEFINITIONS(-DENABLE_HUMIDITY)
+ENDIF()
+
+IF("${TEMP_HUMIDITY}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/temp_humidity/*.cpp)
+ADD_DEFINITIONS(-DENABLE_TEMP_HUMIDITY)
+ENDIF()
+
+IF("${ULTRAVIOLET}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/ultraviolet/*.cpp)
+ADD_DEFINITIONS(-DENABLE_ULTRAVIOLET)
+ENDIF()
+
+IF("${DUST}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/dust/*.cpp)
+ADD_DEFINITIONS(-DENABLE_DUST)
+ENDIF()
+
+IF("${GSR}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/gsr/*.cpp)
+ADD_DEFINITIONS(-DENABLE_GSR)
+ENDIF()
+
+IF("${SENSORHUB}" STREQUAL "ON")
+FILE(GLOB_RECURSE SRCS ${SRCS} src/sensorhub/*.cpp)
+ADD_DEFINITIONS(-DENABLE_SENSORHUB)
+ENDIF()
+
+MESSAGE("Sources: ${SRCS}")
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${HAL_PKGS_LDFLAGS})
+
+CONFIGURE_FILE(sensor.xml.in sensor.xml @ONLY)
+
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.APLv2 DESTINATION share/license RENAME ${PROJECT_NAME})
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}/sensor)
+INSTALL(FILES sensor.xml DESTINATION etc)
diff --git a/LICENSE.APLv2 b/LICENSE.APLv2
new file mode 100644 (file)
index 0000000..6b17abb
--- /dev/null
@@ -0,0 +1,203 @@
+Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/packaging/sensor-hal-emul.manifest b/packaging/sensor-hal-emul.manifest
new file mode 100644 (file)
index 0000000..75b0fa5
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+    <request>
+        <domain name="_"/>
+    </request>
+</manifest>
diff --git a/packaging/sensor-hal-emul.spec b/packaging/sensor-hal-emul.spec
new file mode 100644 (file)
index 0000000..93552a7
--- /dev/null
@@ -0,0 +1,47 @@
+Name:       sensor-hal-emul
+Summary:    Emulator Sensor HAL
+Version:    1.0.0
+Release:    0
+Group:      Service/Sensor
+License:    Apache-2.0
+Source0:    %{name}-%{version}.tar.gz
+
+ExcludeArch: %{arm} aarch64
+
+BuildRequires:  cmake
+BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(gio-2.0)
+BuildRequires:  pkgconfig(libxml-2.0)
+BuildRequires:  pkgconfig(vconf)
+BuildRequires:  sensor-hal-devel
+
+%description
+Emulator Sensor HAL
+
+%prep
+%setup -q
+
+%build
+export CXXFLAGS+=" -Wextra -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wswitch-default"
+export CXXFLAGS+=" -Wnon-virtual-dtor -Wno-c++0x-compat -Wno-unused-parameter -Wno-empty-body"
+export CXXFLAGS+=" -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-strict-aliasing"
+export CXXFLAGS+=" -fno-unroll-loops -fsigned-char -fstrict-overflow"
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+%post
+/sbin/ldconfig
+
+%postun
+/sbin/ldconfig
+
+%files
+%attr(0644,root,root)/usr/etc/sensor.xml
+%manifest packaging/%{name}.manifest
+%{_libdir}/sensor/*.so
+%{_datadir}/license/sensor-hal-emul
diff --git a/sensor.xml.in b/sensor.xml.in
new file mode 100644 (file)
index 0000000..47230d7
--- /dev/null
@@ -0,0 +1,615 @@
+<?xml version="1.0" encoding="utf-8"?>
+<SENSOR>
+       <ACCEL>
+               <MODEL id="lsm330dlc-accel">
+                       <NAME value="LSM330DLC"/>
+                       <VENDOR value="ST Microelectronics"/>
+                       <RAW_DATA_UNIT value="1" />
+                       <RESOLUTION value="12" />
+               </MODEL>
+
+               <MODEL id="LSM330">
+                       <NAME value="LSM330"/>
+                       <VENDOR value="ST Microelectronics"/>
+                       <RAW_DATA_UNIT value="1" />
+                       <RESOLUTION value="12" />
+               </MODEL>
+
+               <MODEL id="K2HH">
+                       <NAME value="K2HH" />
+                       <VENDOR value="ST Microelectronics"/>
+                       <RAW_DATA_UNIT value="0.061"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+
+               <MODEL id="MPU6500">
+                       <NAME value="MPU6500"/>
+                       <VENDOR value="Invensense"/>
+                       <RAW_DATA_UNIT SM-Z910F="0.061" SM-Z9005="0.061" value="0.244"/>
+                       <RESOLUTION value="16" />
+               </MODEL>
+
+               <MODEL id="MPU6515">
+                       <NAME value="MPU6515" />
+                       <VENDOR value="Invensense"/>
+                       <RAW_DATA_UNIT value="0.061"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+
+               <MODEL id="MPU6050">
+                       <NAME value="MPU6050"/>
+                       <VENDOR value="Invensense"/>
+                       <RAW_DATA_UNIT value="0.061"/>
+                       <RESOLUTION value="16" />
+               </MODEL>
+
+               <MODEL id="MPU6051">
+                       <NAME value="MPU6051" />
+                       <VENDOR value="Invensense"/>
+                       <RAW_DATA_UNIT value="0.061"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+
+               <MODEL id="MPU9250">
+                       <NAME value="MPU9250"/>
+                       <VENDOR value="Invensense"/>
+                       <RAW_DATA_UNIT value="0.244" />
+                       <RESOLUTION value="16" />
+               </MODEL>
+
+               <MODEL id="ICM20628">
+                       <NAME value="ICM20628"/>
+                       <VENDOR value="Invensense"/>
+                       <RAW_DATA_UNIT value="0.244" />
+                       <RESOLUTION value="16" />
+               </MODEL>
+
+               <MODEL id="bma222e">
+                       <NAME value="BMA222E" />
+                       <VENDOR value="BOSCH"/>
+                       <RAW_DATA_UNIT value="15.63"/>
+                       <RESOLUTION value="8"/>
+               </MODEL>
+
+               <MODEL id="BMI160">
+                       <NAME value="BMI160" />
+                       <VENDOR value="Bosch"/>
+                       <RAW_DATA_UNIT value="0.244"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+
+               <MODEL id="BMC150">
+                       <NAME value="BMC150" />
+                       <VENDOR value="Bosch"/>
+                       <RAW_DATA_UNIT value="0.244"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+
+               <MODEL id="BMI168">
+                       <NAME value="BMI168" />
+                       <VENDOR value="Bosch"/>
+                       <RAW_DATA_UNIT value="0.244"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+
+               <MODEL id="K6DS3TR">
+                       <NAME value="K6DS3TR" />
+                       <VENDOR value="ST Microelectronics"/>
+                       <RAW_DATA_UNIT value="0.244"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+
+               <MODEL id="maru_sensor_accel_1">
+                       <NAME value="maru_sensor_accel_1" />
+                       <VENDOR value="Tizen_SDK"/>
+                       <RAW_DATA_UNIT value="0.061"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+       </ACCEL>
+
+
+       <GYRO>
+               <MODEL id="lsm330dlc_gyro">
+                       <NAME value="LSM330DLC"/>
+                       <VENDOR value="ST Microelectronics"/>
+                       <RAW_DATA_UNIT value="17.50" />
+                       <RESOLUTION value="12" />
+               </MODEL>
+
+               <MODEL id="LSM330">
+                       <NAME value="LSM330"/>
+                       <VENDOR value="ST Microelectronics"/>
+                       <RAW_DATA_UNIT value="17.50" />
+                       <RESOLUTION value="16" />
+               </MODEL>
+
+               <MODEL id="MPU6500">
+                       <NAME value="MPU6500"/>
+                       <VENDOR value="Invensense"/>
+                       <RAW_DATA_UNIT value="15.26" />
+                       <RESOLUTION value="16" />
+               </MODEL>
+
+               <MODEL id="MPU6515">
+                       <NAME value="MPU6515"/>
+                       <VENDOR value="Invensense"/>
+                       <RAW_DATA_UNIT value="15.26" />
+                       <RESOLUTION value="16" />
+               </MODEL>
+
+               <MODEL id="MPU6050">
+                       <NAME value="MPU6050"/>
+                       <VENDOR value="Invensense"/>
+                       <RAW_DATA_UNIT value="15.26"/>
+                       <RESOLUTION value="16" />
+               </MODEL>
+
+               <MODEL id="MPU6051">
+                       <NAME value="MPU6051" />
+                       <VENDOR value="Invensense"/>
+                       <RAW_DATA_UNIT value="15.26"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+
+               <MODEL id="MPU9250">
+                       <NAME value="MPU9250" />
+                       <VENDOR value="Invensense"/>
+                       <RAW_DATA_UNIT value="15.26"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+
+               <MODEL id="ICM20628">
+                       <NAME value="ICM20628" />
+                       <VENDOR value="Invensense"/>
+                       <RAW_DATA_UNIT value="61.04"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+
+               <MODEL id="BMI160">
+                       <NAME value="BMI160" />
+                       <VENDOR value="Bosch"/>
+                       <RAW_DATA_UNIT value="61.04"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+
+               <MODEL id="BMI168">
+                       <NAME value="BMI168" />
+                       <VENDOR value="Bosch"/>
+                       <RAW_DATA_UNIT value="61.04"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+
+               <MODEL id="K6DS3TR">
+                       <NAME value="K6DS3TR" />
+                       <VENDOR value="ST Microelectronics"/>
+                       <RAW_DATA_UNIT value="70.00"/>
+                       <RESOLUTION value="16"/>
+               </MODEL>
+
+               <MODEL id="maru_sensor_gyro_1">
+                       <NAME value="maru_sensor_gyro_1" />
+                       <VENDOR value="Tizen_SDK"/>
+                       <RAW_DATA_UNIT value="1000"/>
+                       <RESOLUTION value="16"/>
+                       <MIN_RANGE value="-573"/>
+                       <MAX_RANGE value="573"/>
+               </MODEL>
+       </GYRO>
+
+       <PROXI>
+               <MODEL id="taos">
+                       <NAME value="TMD27723" />
+                       <VENDOR value="TAOS"/>
+               </MODEL>
+
+               <MODEL id="TMD3782">
+                       <NAME value="TMD3782" />
+                       <VENDOR value="TAOS"/>
+               </MODEL>
+
+               <MODEL id="gp2a">
+                       <NAME value="GP2AP020" />
+                       <VENDOR value="Sharp"/>
+               </MODEL>
+
+               <MODEL id="gp2ap002s">
+                       <NAME value="GP2AP002S" />
+                       <VENDOR value="Sharp"/>
+               </MODEL>
+
+               <MODEL id="CM36651">
+                       <NAME value="CM36651" />
+                       <VENDOR value="Capella"/>
+               </MODEL>
+
+               <MODEL id="CM36686">
+                       <NAME value="CM36686" />
+                       <VENDOR value="Capella"/>
+               </MODEL>
+
+               <MODEL id="MAX88922">
+                       <NAME value="MAX88922" />
+                       <VENDOR value="MAXIM"/>
+               </MODEL>
+
+               <MODEL id="IMS1911">
+                       <NAME value="IMS1911" />
+                       <VENDOR value="ITM"/>
+               </MODEL>
+
+               <MODEL id="TMG399X">
+                       <NAME value="TMG399X" />
+                       <VENDOR value="AMS"/>
+               </MODEL>
+
+               <MODEL id="maru_sensor_proxi_1">
+                       <NAME value="maru_sensor_proxi_1" />
+                       <VENDOR value="Tizen_SDK"/>
+               </MODEL>
+       </PROXI>
+
+       <LIGHT>
+               <MODEL id="taos">
+                       <NAME value="TMD27723" />
+                       <VENDOR value="TAOS"/>
+               </MODEL>
+
+               <MODEL id="TMD3782">
+                       <NAME value="TMD3782" />
+                       <VENDOR value="TAOS"/>
+               </MODEL>
+
+               <MODEL id="gp2a">
+                       <NAME value="GP2AP020" />
+                       <VENDOR value="Sharp"/>
+               </MODEL>
+
+               <MODEL id="CM36651">
+                       <NAME value="CM36651" />
+                       <VENDOR value="Capella"/>
+               </MODEL>
+
+               <MODEL id="CM36686">
+                       <NAME value="CM36686" />
+                       <VENDOR value="Capella"/>
+               </MODEL>
+
+               <MODEL id="MAX88922">
+                       <NAME value="MAX88922" />
+                       <VENDOR value="MAXIM"/>
+               </MODEL>
+
+               <MODEL id="AL3320">
+                       <NAME value="AL3320" />
+                       <VENDOR value="LITEON"/>
+               </MODEL>
+
+               <MODEL id="BH1733">
+                       <NAME value="BH1733" />
+                       <VENDOR value="ROHM"/>
+               </MODEL>
+
+               <MODEL id="TSL2584">
+                       <NAME value="TSL2584" />
+                       <VENDOR value="AMS"/>
+               </MODEL>
+
+               <MODEL id=" TMG399X">
+                       <NAME value=" TMG399X" />
+                       <VENDOR value="AMS"/>
+               </MODEL>
+
+               <MODEL id="maru_sensor_light_1">
+                       <NAME value="maru_sensor_light_1" />
+                       <VENDOR value="Tizen_SDK"/>
+               </MODEL>
+       </LIGHT>
+
+       <MAGNETIC>
+               <MODEL id="AK8975C">
+                       <NAME value="AK8975C" />
+                       <VENDOR value="AKM"/>
+                       <RAW_DATA_UNIT value="0.06"/>
+                       <MIN_INTERVAL value="20"/>
+                       <MIN_RANGE value="-1200"/>
+                       <MAX_RANGE value="1200"/>
+               </MODEL>
+
+               <MODEL id="AK09911C">
+                       <NAME value="AK09911C" />
+                       <VENDOR value="AKM"/>
+                       <RAW_DATA_UNIT value="0.06"/>
+                       <MIN_RANGE value="-4900"/>
+                       <MAX_RANGE value="4900"/>
+               </MODEL>
+
+               <MODEL id="MPU9250">
+                       <NAME value="MPU9250" />
+                       <VENDOR value="Invensense"/>
+                       <RAW_DATA_UNIT value="1.0"/>
+                       <MIN_RANGE value="-4800"/>
+                       <MAX_RANGE value="4800"/>
+               </MODEL>
+
+               <MODEL id="YAS537">
+                       <NAME value="YAS537" />
+                       <VENDOR value="Yamaha"/>
+                       <RAW_DATA_UNIT value="0.1"/>
+                       <MIN_RANGE value="-4800"/>
+                       <MAX_RANGE value="4800"/>
+               </MODEL>
+
+               <MODEL id="maru_sensor_geo_1">
+                       <NAME value="maru_sensor_geo_1" />
+                       <VENDOR value="Tizen_SDK"/>
+                       <RAW_DATA_UNIT value="0.6"/>
+                       <RESOLUTION value="14"/>
+                       <MIN_INTERVAL value="1"/>
+                       <MIN_RANGE value="-2000"/>
+                       <MAX_RANGE value="2000"/>
+               </MODEL>
+       </MAGNETIC>
+
+       <PEDO>
+               <MODEL id="MPU6051">
+                       <NAME value="MPU6051" />
+                       <VENDOR value="Invensense"/>
+               </MODEL>
+
+               <MODEL id="MPU6500">
+                       <NAME value="MPU6500" />
+                       <VENDOR value="Invensense"/>
+               </MODEL>
+
+               <MODEL id="MPU6515">
+                       <NAME value="MPU6515" />
+                       <VENDOR value="Invensense"/>
+               </MODEL>
+       </PEDO>
+
+       <FLAT>
+               <MODEL id="MPU6051">
+                       <NAME value="MPU6051" />
+                       <VENDOR value="Invensense"/>
+               </MODEL>
+
+               <MODEL id="MPU6500">
+                       <NAME value="MPU6500" />
+                       <VENDOR value="Invensense"/>
+               </MODEL>
+
+               <MODEL id="MPU6515">
+                       <NAME value="MPU6515" />
+                       <VENDOR value="Invensense"/>
+               </MODEL>
+       </FLAT>
+
+       <HRM_RAW>
+               <MODEL id="ADPD142">
+                       <NAME value="ADPD142" />
+                       <VENDOR value="ANALOG DEVICES"/>
+                       <READER SM-Z910F="adi" value="standard"/>
+               </MODEL>
+
+               <MODEL id="ADPD142RI">
+                       <NAME value="ADPD142RI" />
+                       <VENDOR value="ANALOG DEVICES"/>
+                       <READER SM-Z910F="adi" value="standard"/>
+               </MODEL>
+
+               <MODEL id="AD45251">
+                       <NAME value="AD45251" />
+                       <VENDOR value="ANALOG DEVICES"/>
+                       <READER SM-Z910F="adi" value="standard"/>
+               </MODEL>
+
+               <MODEL id="AD45265">
+                       <NAME value="AD45265" />
+                       <VENDOR value="ANALOG DEVICES"/>
+                       <READER SM-Z910F="adi" value="standard"/>
+               </MODEL>
+
+               <MODEL id="PPS960">
+                       <NAME value="PPS960" />
+                       <VENDOR value="TI"/>
+                       <READER SM-Z910F="adi" value="standard"/>
+               </MODEL>
+       </HRM_RAW>
+
+       <HRM>
+               <MODEL id="ADPD142">
+                       <NAME value="ADPD142" />
+                       <VENDOR value="ANALOG DEVICES"/>
+               </MODEL>
+
+               <MODEL id="ADPD142RI">
+                       <NAME value="ADPD142RI" />
+                       <VENDOR value="ANALOG DEVICES"/>
+               </MODEL>
+
+               <MODEL id="AD45251">
+                       <NAME value="AD45251" />
+                       <VENDOR value="ANALOG DEVICES"/>
+               </MODEL>
+
+               <MODEL id="AD45265">
+                       <NAME value="AD45265" />
+                       <VENDOR value="ANALOG DEVICES"/>
+               </MODEL>
+
+               <MODEL id="PPS960">
+                       <NAME value="PPS960" />
+                       <VENDOR value="TI"/>
+               </MODEL>
+
+               <MODEL id="maru_sensor_hrm_1">
+                       <NAME value="maru_sensor_hrm_1" />
+                       <VENDOR value="Tizen_SDK"/>
+                       <RAW_DATA_UNIT value="0.1"/>
+               </MODEL>
+       </HRM>
+
+       <PRESSURE>
+               <MODEL id="LPS25H">
+                       <NAME value="LPS25H" />
+                       <VENDOR value="ST Microelectronics"/>
+                       <RAW_DATA_UNIT value="0.000244"/>
+                       <MIN_RANGE value="260"/>
+                       <MAX_RANGE value="1260"/>
+                       <RESOLUTION value="1"/>
+                       <TEMPERATURE_RESOLUTION value="0.002083"/>
+                       <TEMPERATURE_OFFSET value="42.5"/>
+               </MODEL>
+
+               <MODEL id="LPS22H">
+                       <NAME value="LPS22H" />
+                       <VENDOR value="ST Microelectronics"/>
+                       <RAW_DATA_UNIT value="0.000244"/>
+                       <MIN_RANGE value="260"/>
+                       <MAX_RANGE value="1260"/>
+                       <RESOLUTION value="1"/>
+                       <TEMPERATURE_RESOLUTION value="0.001"/>
+                       <TEMPERATURE_OFFSET value="0.0"/>
+               </MODEL>
+
+               <MODEL id="LPS331">
+                       <NAME value="LPS331" />
+                       <VENDOR value="ST Microelectronics"/>
+                       <RAW_DATA_UNIT value="0.000244"/>
+                       <MIN_RANGE value="260"/>
+                       <MAX_RANGE value="1260"/>
+                       <RESOLUTION value="1"/>
+                       <TEMPERATURE_RESOLUTION value="0.002083"/>
+                       <TEMPERATURE_OFFSET value="42.5"/>
+               </MODEL>
+
+               <MODEL id="maru_sensor_pressure_1">
+                       <NAME value="maru_sensor_pressure_1" />
+                       <VENDOR value="Tizen_SDK"/>
+                       <RAW_DATA_UNIT value="0.0193"/>
+                       <MIN_RANGE value="260"/>
+                       <MAX_RANGE value="1260"/>
+                       <RESOLUTION value="1"/>
+                       <TEMPERATURE_RESOLUTION value="0.05"/>
+                       <TEMPERATURE_OFFSET value="0"/>
+               </MODEL>
+       </PRESSURE>
+
+       <ROTATION_VECTOR>
+               <MODEL id="MPU6500">
+                       <NAME value="MPU6500" />
+                       <VENDOR value="Invensense"/>
+               </MODEL>
+
+               <MODEL id="MPU9250">
+                       <NAME value="MPU9250" />
+                       <VENDOR value="Invensense"/>
+               </MODEL>
+
+               <MODEL id="AK09911C">
+                       <NAME value="AK09911C" />
+                       <VENDOR value="AKM"/>
+               </MODEL>
+
+               <MODEL id="YAS537">
+                       <NAME value="YAS537" />
+                       <VENDOR value="Yamaha"/>
+               </MODEL>
+
+               <MODEL id="maru_sensor_rotation_vector_1">
+                       <NAME value="maru_sensor_rotation_vector_1" />
+                       <VENDOR value="Tizen_SDK"/>
+               </MODEL>
+       </ROTATION_VECTOR>
+
+       <PIR>
+               <MODEL id="EKMC1601111">
+                       <NAME value="EKMC1601111" />
+                       <VENDOR value="PANASONIC"/>
+               </MODEL>
+               <MODEL id="PYD1798">
+                       <NAME value="PYD1798" />
+                       <VENDOR value="PYRO-ELECTRIC"/>
+               </MODEL>
+       </PIR>
+
+       <PIR_LONG>
+               <MODEL id="EKMC1603111">
+                       <NAME value="EKMC1603111" />
+                       <VENDOR value="PANASONIC"/>
+               </MODEL>
+               <MODEL id="PYD1798">
+                       <NAME value="PYD1798" />
+                       <VENDOR value="PYRO-ELECTRIC"/>
+               </MODEL>
+       </PIR_LONG>
+
+       <TEMPERATURE>
+               <MODEL id="SHTC1">
+                       <NAME value="SHTC1" />
+                       <VENDOR value="SENSIRION"/>
+                       <RAW_DATA_UNIT value="0.01"/>
+                       <RESOLUTION value="1"/>
+               </MODEL>
+       </TEMPERATURE>
+
+       <HUMIDITY>
+               <MODEL id="SHTC1">
+                       <NAME value="SHTC1" />
+                       <VENDOR value="SENSIRION"/>
+                       <RAW_DATA_UNIT value="0.01"/>
+                       <MIN_RANGE value="-10"/>
+                       <MAX_RANGE value="110"/>
+                       <RESOLUTION value="1"/>
+               </MODEL>
+       </HUMIDITY>
+
+       <TEMP_HUMIDITY>
+               <MODEL id="SHTC1">
+                       <NAME value="SHTC1" />
+                       <VENDOR value="SENSIRION"/>
+                       <TEMPERATURE_RESOLUTION value="0.01"/>
+                       <TEMPERATURE_MIN_RANGE value="-165.0" />
+                       <TEMPERATURE_MAX_RANGE value="165.0" />
+                       <HUMIDITY_RESOLUTION value="0.04"/>
+                       <HUMIDITY_MIN_RANGE value="0.0" />
+                       <HUMIDITY_MAX_RANGE value="100.0" />
+               </MODEL>
+       </TEMP_HUMIDITY>
+
+       <ULTRAVIOLET>
+               <MODEL id="UVIS25">
+                       <NAME value="UVIS25" />
+                       <VENDOR value="STM"/>
+                       <RAW_DATA_UNIT value="0.0625"/>
+                       <MIN_RANGE value="0"/>
+                       <MAX_RANGE value="15"/>
+               </MODEL>
+               <MODEL id="maru_sensor_uv_1">
+                       <NAME value="maru_sensor_uv_1" />
+                       <VENDOR value="Tizen_SDK"/>
+                       <RAW_DATA_UNIT value="0.1"/>
+                       <MIN_RANGE value="0"/>
+                       <MAX_RANGE value="15"/>
+               </MODEL>
+       </ULTRAVIOLET>
+
+       <DUST>
+               <MODEL id="GP2Y1023AU0F">
+                       <NAME value="GP2Y1023AU0F" />
+                       <VENDOR value="SHARP"/>
+                       <RAW_DATA_UNIT value="1"/>
+               </MODEL>
+       </DUST>
+
+       <GSR>
+               <MODEL id="HM121">
+                       <NAME value="HM121" />
+                       <VENDOR value="STM"/>
+                       <RAW_DATA_UNIT value="0.001"/>
+                       <MIN_RANGE value="0"/>
+                       <MAX_RANGE value="524287"/>
+                       <RESOLUTION value="1"/>
+               </MODEL>
+       </GSR>
+</SENSOR>
diff --git a/src/accel/accel_device.cpp b/src/accel/accel_device.cpp
new file mode 100644 (file)
index 0000000..e1229af
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/input.h>
+#include <sys/ioctl.h>
+#include <poll.h>
+
+#include <util.h>
+#include <sensor_common.h>
+#include <sensor_log.h>
+#include <sensor_config.h>
+#include "accel_device.h"
+
+#define GRAVITY 9.80665
+#define G_TO_MG 1000
+#define RAW_DATA_TO_G_UNIT(X) (((float)(X))/((float)G_TO_MG))
+#define RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(X) (GRAVITY * (RAW_DATA_TO_G_UNIT(X)))
+
+#define MIN_RANGE(RES) (-((1 << (RES))/2))
+#define MAX_RANGE(RES) (((1 << (RES))/2)-1)
+
+#define MODEL_NAME "UNKNOWN"
+#define VENDOR "UNKNOWN"
+#define RESOLUTION 0
+#define RAW_DATA_UNIT 0
+#define MIN_INTERVAL 0
+#define MAX_BATCH_COUNT 0
+
+#define SENSOR_NAME "SENSOR_ACCELEROMETER"
+#define SENSOR_TYPE_ACCEL              "ACCEL"
+
+#define INPUT_NAME     "accelerometer_sensor"
+#define ACCEL_SENSORHUB_POLL_NODE_NAME "accel_poll_delay"
+
+static sensor_info_t sensor_info = {
+       id: 0x1,
+       name: SENSOR_NAME,
+       type: SENSOR_DEVICE_ACCELEROMETER,
+       event_type: (SENSOR_DEVICE_ACCELEROMETER << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
+       model_name: MODEL_NAME,
+       vendor: VENDOR,
+       min_range: MIN_RANGE(RESOLUTION) * RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(RAW_DATA_UNIT),
+       max_range: MAX_RANGE(RESOLUTION) * RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(RAW_DATA_UNIT),
+       resolution: RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(RAW_DATA_UNIT),
+       min_interval: MIN_INTERVAL,
+       max_batch_count: MAX_BATCH_COUNT,
+       wakeup_supported: false
+};
+
+accel_device::accel_device()
+: m_node_handle(-1)
+, m_x(-1)
+, m_y(-1)
+, m_z(-1)
+, m_polling_interval(1000)
+, m_fired_time(0)
+, m_sensorhub_controlled(false)
+{
+       const std::string sensorhub_interval_node_name = ACCEL_SENSORHUB_POLL_NODE_NAME;
+       config::sensor_config &config = config::sensor_config::get_instance();
+
+       node_info_query query;
+       node_info info;
+
+       if (!util::find_model_id(SENSOR_TYPE_ACCEL, m_model_id)) {
+               _E("Failed to find model id");
+               throw ENXIO;
+       }
+
+       query.sensorhub_controlled = m_sensorhub_controlled = util::is_sensorhub_controlled(sensorhub_interval_node_name);
+       query.sensor_type = SENSOR_TYPE_ACCEL;
+       query.key = INPUT_NAME;
+       query.iio_enable_node_name = "accel_enable";
+       query.sensorhub_interval_node_name = sensorhub_interval_node_name;
+
+       if (!util::get_node_info(query, info)) {
+               _E("Failed to get node info");
+               throw ENXIO;
+       }
+
+       util::show_node_info(info);
+
+       m_method = info.method;
+       m_data_node = info.data_node_path;
+       m_enable_node = info.enable_node_path;
+       m_interval_node = info.interval_node_path;
+
+       if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_VENDOR, m_vendor)) {
+               _E("[VENDOR] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_vendor = %s", m_vendor.c_str());
+
+       if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_NAME, m_chip_name)) {
+               _E("[NAME] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_chip_name = %s",m_chip_name.c_str());
+
+       long resolution;
+
+       if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_RESOLUTION, resolution)) {
+               _E("[RESOLUTION] is empty");
+               throw ENXIO;
+       }
+
+       m_resolution = (int)resolution;
+
+       _I("m_resolution = %d",m_resolution);
+
+       double raw_data_unit;
+
+       if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) {
+               _E("[RAW_DATA_UNIT] is empty");
+               throw ENXIO;
+       }
+
+       m_raw_data_unit = (float)(raw_data_unit);
+       _I("m_raw_data_unit = %f", m_raw_data_unit);
+
+       m_node_handle = open(m_data_node.c_str(), O_RDONLY);
+
+       if (m_node_handle < 0) {
+               _ERRNO(errno, _E, "accel handle open fail for accel processor");
+               throw ENXIO;
+       }
+
+       if (m_method == INPUT_EVENT_METHOD) {
+               if (!util::set_monotonic_clock(m_node_handle))
+                       throw ENXIO;
+
+               update_value = [=]() {
+                       return this->update_value_input_event();
+               };
+       } else {
+               if (!info.buffer_length_node_path.empty())
+                       util::set_node_value(info.buffer_length_node_path, 480);
+
+               if (!info.buffer_enable_node_path.empty())
+                       util::set_node_value(info.buffer_enable_node_path, 1);
+
+               update_value = [=]() {
+                       return this->update_value_iio();
+               };
+       }
+
+       _I("accel_sensor is created!");
+}
+
+accel_device::~accel_device()
+{
+       close(m_node_handle);
+       m_node_handle = -1;
+
+       _I("accel_sensor is destroyed!");
+}
+
+int accel_device::get_poll_fd()
+{
+       return m_node_handle;
+}
+
+int accel_device::get_sensors(const sensor_info_t **sensors)
+{
+       sensor_info.model_name = m_chip_name.c_str();
+       sensor_info.vendor = m_vendor.c_str();
+       sensor_info.min_range = MIN_RANGE(m_resolution) * RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(m_raw_data_unit);
+       sensor_info.max_range = MAX_RANGE(m_resolution) * RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(m_raw_data_unit);
+       sensor_info.resolution = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(m_raw_data_unit);
+       sensor_info.min_interval = 1;
+       sensor_info.max_batch_count = 0;
+       *sensors = &sensor_info;
+
+       return 1;
+}
+
+bool accel_device::enable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_ACCELEROMETER_ENABLE_BIT);
+       set_interval(id, m_polling_interval);
+
+       m_fired_time = 0;
+       _I("Enable accelerometer sensor");
+       return true;
+}
+
+bool accel_device::disable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_ACCELEROMETER_ENABLE_BIT);
+
+       _I("Disable accelerometer sensor");
+       return true;
+}
+
+bool accel_device::set_interval(uint32_t id, unsigned long val)
+{
+       unsigned long long polling_interval_ns;
+
+       polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
+
+       if (!util::set_node_value(m_interval_node, polling_interval_ns)) {
+               _E("Failed to set polling resource: %s", m_interval_node.c_str());
+               return false;
+       }
+
+       _I("Interval is changed from %dms to %dms", m_polling_interval, val);
+       m_polling_interval = val;
+       return true;
+}
+
+bool accel_device::update_value_input_event(void)
+{
+       int accel_raw[3] = {0,};
+       bool x,y,z;
+       int read_input_cnt = 0;
+       const int INPUT_MAX_BEFORE_SYN = 10;
+       unsigned long long fired_time = 0;
+       bool syn = false;
+
+       x = y = z = false;
+
+       struct input_event accel_input;
+       _D("accel event detection!");
+
+       while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
+               int len = read(m_node_handle, &accel_input, sizeof(accel_input));
+               if (len != sizeof(accel_input)) {
+                       _E("accel_file read fail, read_len = %d",len);
+                       return false;
+               }
+
+               ++read_input_cnt;
+
+               if (accel_input.type == EV_REL) {
+                       switch (accel_input.code) {
+                       case REL_X:
+                               accel_raw[0] = (int)accel_input.value;
+                               x = true;
+                               break;
+                       case REL_Y:
+                               accel_raw[1] = (int)accel_input.value;
+                               y = true;
+                               break;
+                       case REL_Z:
+                               accel_raw[2] = (int)accel_input.value;
+                               z = true;
+                               break;
+                       default:
+                               _E("accel_input event[type = %d, code = %d] is unknown.", accel_input.type, accel_input.code);
+                               return false;
+                               break;
+                       }
+               } else if (accel_input.type == EV_SYN) {
+                       syn = true;
+                       fired_time = util::get_timestamp(&accel_input.time);
+               } else {
+                       _E("accel_input event[type = %d, code = %d] is unknown.", accel_input.type, accel_input.code);
+                       return false;
+               }
+       }
+
+       if (syn == false) {
+               _E("EV_SYN didn't come until %d inputs had come", read_input_cnt);
+               return false;
+       }
+
+       if (x)
+               m_x =  accel_raw[0];
+       if (y)
+               m_y =  accel_raw[1];
+       if (z)
+               m_z =  accel_raw[2];
+
+       m_fired_time = fired_time;
+
+       _D("m_x = %d, m_y = %d, m_z = %d, time = %lluus", m_x, m_y, m_z, m_fired_time);
+
+       return true;
+}
+
+bool accel_device::update_value_iio(void)
+{
+       struct {
+               int16_t x;
+               int16_t y;
+               int16_t z;
+               int64_t timestamp;
+       } __attribute__((packed)) data;
+
+       struct pollfd pfd;
+
+       pfd.fd = m_node_handle;
+       pfd.events = POLLIN | POLLERR;
+       pfd.revents = 0;
+
+       int ret = poll(&pfd, 1, -1);
+
+       if (ret == -1) {
+               _ERRNO(errno, _E, "Failed to poll from m_node_handle:%d", m_node_handle);
+               return false;
+       } else if (!ret) {
+               _E("poll timeout m_node_handle:%d", m_node_handle);
+               return false;
+       }
+
+       if (pfd.revents & POLLERR) {
+               _E("poll exception occurred! m_node_handle:%d", m_node_handle);
+               return false;
+       }
+
+       if (!(pfd.revents & POLLIN)) {
+               _E("poll nothing to read! m_node_handle:%d, pfd.revents = %d", m_node_handle, pfd.revents);
+               return false;
+       }
+
+       int len = read(m_node_handle, &data, sizeof(data));
+
+       if (len != sizeof(data)) {
+               _E("Failed to read data, m_node_handle:%d read_len:%d", m_node_handle, len);
+               return false;
+       }
+
+       m_x = data.x;
+       m_y = data.y;
+       m_z = data.z;
+       m_fired_time = data.timestamp;
+
+       _D("m_x = %d, m_y = %d, m_z = %d, time = %lluus", m_x, m_y, m_z, m_fired_time);
+
+       return true;
+}
+
+int accel_device::read_fd(uint32_t **ids)
+{
+       if (!update_value()) {
+               _D("Failed to update value");
+               return false;
+       }
+
+       event_ids.clear();
+       event_ids.push_back(sensor_info.id);
+
+       *ids = &event_ids[0];
+
+       return event_ids.size();
+}
+
+int accel_device::get_data(uint32_t id, sensor_data_t **data, int *length)
+{
+       int remains = 1;
+       sensor_data_t *sensor_data;
+       sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
+       retvm_if(!sensor_data, -ENOMEM, "Memory allocation failed");
+
+       sensor_data->accuracy = SENSOR_ACCURACY_GOOD;
+       sensor_data->timestamp = m_fired_time;
+       sensor_data->value_count = 3;
+       sensor_data->values[0] = m_x;
+       sensor_data->values[1] = m_y;
+       sensor_data->values[2] = m_z;
+
+       raw_to_base(sensor_data);
+
+       *data = sensor_data;
+       *length = sizeof(sensor_data_t);
+
+       return --remains;
+}
+
+void accel_device::raw_to_base(sensor_data_t *data)
+{
+       data->value_count = 3;
+       data->values[0] = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(data->values[0] * m_raw_data_unit);
+       data->values[1] = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(data->values[1] * m_raw_data_unit);
+       data->values[2] = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(data->values[2] * m_raw_data_unit);
+}
diff --git a/src/accel/accel_device.h b/src/accel/accel_device.h
new file mode 100644 (file)
index 0000000..da406d2
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _ACCEL_DEVICE_H_
+#define _ACCEL_DEVICE_H_
+
+#include <sensor/sensor_hal.h>
+#include <string>
+#include <vector>
+#include <functional>
+
+class accel_device : public sensor_device {
+public:
+       accel_device();
+       virtual ~accel_device();
+
+       int get_poll_fd(void);
+       int get_sensors(const sensor_info_t **sensors);
+
+       bool enable(uint32_t id);
+       bool disable(uint32_t id);
+
+       bool set_interval(uint32_t id, unsigned long val);
+
+       int read_fd(uint32_t **ids);
+       int get_data(uint32_t id, sensor_data_t **data, int *length);
+
+private:
+       int m_node_handle;
+       int m_x;
+       int m_y;
+       int m_z;
+       unsigned long m_polling_interval;
+       unsigned long long m_fired_time;
+       bool m_sensorhub_controlled;
+
+       int m_method;
+       std::string m_data_node;
+       std::string m_enable_node;
+       std::string m_interval_node;
+
+       std::string m_model_id;
+       std::string m_vendor;
+       std::string m_chip_name;
+
+       int m_resolution;
+       float m_raw_data_unit;
+
+       std::function<bool (void)> update_value;
+
+       std::vector<uint32_t> event_ids;
+
+       bool update_value_input_event(void);
+       bool update_value_iio(void);
+
+       void raw_to_base(sensor_data_t *data);
+};
+#endif /* _ACCEL_DEVICE_H_ */
diff --git a/src/create.cpp b/src/create.cpp
new file mode 100644 (file)
index 0000000..db4f176
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <sensor/sensor_hal.h>
+#include <sensor_log.h>
+#include <vector>
+
+#ifdef ENABLE_ACCEL
+#include "accel/accel_device.h"
+#endif
+#ifdef ENABLE_GYRO
+#include "gyro/gyro_device.h"
+#endif
+#ifdef ENABLE_GYRO_UNCAL
+#include "gyro_uncal/gyro_uncal_device.h"
+#endif
+#ifdef ENABLE_GEOMAG
+#include "geomag/geomag_device.h"
+#endif
+#ifdef ENABLE_PRESSURE
+#include "pressure/pressure_device.h"
+#endif
+#ifdef ENABLE_UV
+#include "ultraviolet/uv_device.h"
+#endif
+#ifdef ENABLE_LIGHT
+#include "light/light_device.h"
+#endif
+#ifdef ENABLE_PROXIMITY
+#include "proxi/proxi_device.h"
+#endif
+#ifdef ENABLE_HRM_RAW
+#include "hrm_raw/hrm_raw_device.h"
+#endif
+#ifdef ENABLE_HRM
+#include "hrm/hrm_device.h"
+#endif
+#ifdef ENABLE_SENSORHUB
+#include "sensorhub/sensorhub.h"
+#endif
+
+static std::vector<sensor_device_t> devs;
+
+template<typename _sensor>
+void create_sensor(const char *name)
+{
+       sensor_device *instance = NULL;
+       try {
+               instance = new _sensor;
+       } catch (std::exception &e) {
+               ERR("Failed to create %s sensor device, exception: %s", name, e.what());
+               return;
+       } catch (int err) {
+               _ERRNO(err, _E, "Failed to create %s sensor device", name);
+               return;
+       }
+
+       devs.push_back(instance);
+}
+
+extern "C" int create(sensor_device_t **devices)
+{
+#ifdef ENABLE_ACCEL
+       create_sensor<accel_device>("Accelerometer");
+#endif
+#ifdef ENABLE_GYRO
+       create_sensor<gyro_device>("Gyroscope");
+#endif
+#ifdef ENABLE_GYRO_UNCAL
+       create_sensor<gyro_uncal_device>("Gyroscope Uncal");
+#endif
+#ifdef ENABLE_GEOMAG
+       create_sensor<geomag_device>("Geomagnetic");
+#endif
+#ifdef ENABLE_PRESSURE
+       create_sensor<pressure_device>("Pressure");
+#endif
+#ifdef ENABLE_UV
+       create_sensor<uv_device>("Ultra Violet");
+#endif
+#ifdef ENABLE_LIGHT
+       create_sensor<light_device>("Light");
+#endif
+#ifdef ENABLE_PROXIMITY
+       create_sensor<proxi_device>("Proximity");
+#endif
+#ifdef ENABLE_HRM_RAW
+       create_sensor<hrm_raw_device>("HRM Raw");
+#endif
+#ifdef ENABLE_HRM
+       create_sensor<hrm_device>("HRM");
+#endif
+#ifdef ENABLE_SENSORHUB
+       create_sensor<sensorhub_device>("Sensorhub");
+#endif
+
+       *devices = &devs[0];
+       return devs.size();
+}
diff --git a/src/geomag/geomag_device.cpp b/src/geomag/geomag_device.cpp
new file mode 100644 (file)
index 0000000..c4a562a
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/input.h>
+#include <sys/ioctl.h>
+#include <poll.h>
+
+#include <util.h>
+#include <sensor_common.h>
+#include <sensor_log.h>
+#include <sensor_config.h>
+#include "geomag_device.h"
+
+#define SENSOR_NAME "SENSOR_GEOMAGNETIC"
+#define SENSOR_TYPE_MAGNETIC   "MAGNETIC"
+
+#define INPUT_NAME     "geomagnetic_sensor"
+#define GEOMAG_SENSORHUB_POLL_NODE_NAME "mag_poll_delay"
+
+static sensor_info_t sensor_info = {
+       id: 0x1,
+       name: SENSOR_NAME,
+       type: SENSOR_DEVICE_GEOMAGNETIC,
+       event_type: (SENSOR_DEVICE_GEOMAGNETIC << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
+       model_name: UNKNOWN_NAME,
+       vendor: UNKNOWN_NAME,
+       min_range: 0,
+       max_range: 0,
+       resolution: 0,
+       min_interval: 0,
+       max_batch_count: 0,
+       wakeup_supported: false
+};
+
+geomag_device::geomag_device()
+: m_node_handle(-1)
+, m_x(-1)
+, m_y(-1)
+, m_z(-1)
+, m_hdst(0)
+, m_polling_interval(1000)
+, m_fired_time(0)
+, m_sensorhub_controlled(false)
+{
+       const std::string sensorhub_interval_node_name = GEOMAG_SENSORHUB_POLL_NODE_NAME;
+       config::sensor_config &config = config::sensor_config::get_instance();
+
+       node_info_query query;
+       node_info info;
+
+       if (!util::find_model_id(SENSOR_TYPE_MAGNETIC, m_model_id)) {
+               _E("Failed to find model id");
+               throw ENXIO;
+
+       }
+
+       query.sensorhub_controlled = m_sensorhub_controlled = util::is_sensorhub_controlled(sensorhub_interval_node_name);
+       query.sensor_type = SENSOR_TYPE_MAGNETIC;
+       query.key = INPUT_NAME;
+       query.iio_enable_node_name = "geomagnetic_enable";
+       query.sensorhub_interval_node_name = sensorhub_interval_node_name;
+
+       if (!util::get_node_info(query, info)) {
+               _E("Failed to get node info");
+               throw ENXIO;
+       }
+
+       util::show_node_info(info);
+
+       m_method = info.method;
+       m_data_node = info.data_node_path;
+       m_enable_node = info.enable_node_path;
+       m_interval_node = info.interval_node_path;
+
+       if (!config.get(SENSOR_TYPE_MAGNETIC, m_model_id, ELEMENT_VENDOR, m_vendor)) {
+               _E("[VENDOR] is empty\n");
+               throw ENXIO;
+       }
+
+       _I("m_vendor = %s", m_vendor.c_str());
+
+       if (!config.get(SENSOR_TYPE_MAGNETIC, m_model_id, ELEMENT_NAME, m_chip_name)) {
+               _E("[NAME] is empty\n");
+               throw ENXIO;
+       }
+
+       _I("m_chip_name = %s\n",m_chip_name.c_str());
+
+       double min_range;
+
+       if (!config.get(SENSOR_TYPE_MAGNETIC, m_model_id, ELEMENT_MIN_RANGE, min_range)) {
+               _E("[MIN_RANGE] is empty\n");
+               throw ENXIO;
+       }
+
+       m_min_range = (float)min_range;
+       _I("m_min_range = %f\n",m_min_range);
+
+       double max_range;
+
+       if (!config.get(SENSOR_TYPE_MAGNETIC, m_model_id, ELEMENT_MAX_RANGE, max_range)) {
+               _E("[MAX_RANGE] is empty\n");
+               throw ENXIO;
+       }
+
+       m_max_range = (float)max_range;
+       _I("m_max_range = %f\n",m_max_range);
+
+       double raw_data_unit;
+
+       if (!config.get(SENSOR_TYPE_MAGNETIC, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) {
+               _E("[RAW_DATA_UNIT] is empty\n");
+               throw ENXIO;
+       }
+
+       m_raw_data_unit = (float)(raw_data_unit);
+       _I("m_raw_data_unit = %f\n", m_raw_data_unit);
+
+       m_node_handle = open(m_data_node.c_str(), O_RDONLY);
+
+       if (m_node_handle < 0) {
+               _ERRNO(errno, _E, "geomag handle open fail for geomag device");
+               throw ENXIO;
+       }
+
+       if (m_method == INPUT_EVENT_METHOD) {
+               if (!util::set_monotonic_clock(m_node_handle))
+                       throw ENXIO;
+
+               update_value = [=]() {
+                       return this->update_value_input_event();
+               };
+       } else {
+               if (!info.buffer_length_node_path.empty())
+                       util::set_node_value(info.buffer_length_node_path, 480);
+
+               if (!info.buffer_enable_node_path.empty())
+                       util::set_node_value(info.buffer_enable_node_path, 1);
+
+               update_value = [=]() {
+                       return this->update_value_iio();
+               };
+       }
+
+       _I("geomag_device is created!\n");
+}
+
+geomag_device::~geomag_device()
+{
+       close(m_node_handle);
+       m_node_handle = -1;
+
+       _I("geomag_sensor is destroyed!\n");
+}
+
+int geomag_device::get_poll_fd(void)
+{
+       return m_node_handle;
+}
+
+int geomag_device::get_sensors(const sensor_info_t **sensors)
+{
+       sensor_info.model_name = m_chip_name.c_str();
+       sensor_info.vendor = m_vendor.c_str();
+       sensor_info.min_range = m_min_range;
+       sensor_info.max_range = m_max_range;
+       sensor_info.resolution = m_raw_data_unit;
+       sensor_info.min_interval = 1;
+       sensor_info.max_batch_count = 0;
+       *sensors = &sensor_info;
+
+       return 1;
+}
+
+bool geomag_device::enable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_GEOMAGNETIC_ENABLE_BIT);
+       set_interval(id, m_polling_interval);
+
+       m_fired_time = 0;
+       INFO("Enable geomagnetic sensor");
+       return true;
+}
+
+bool geomag_device::disable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_GEOMAGNETIC_ENABLE_BIT);
+
+       INFO("Disable geomagnetic sensor");
+       return true;
+}
+
+bool geomag_device::set_interval(uint32_t id, unsigned long val)
+{
+       unsigned long long polling_interval_ns;
+
+       polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
+
+       if (!util::set_node_value(m_interval_node, polling_interval_ns)) {
+               ERR("Failed to set polling resource: %s\n", m_interval_node.c_str());
+               return false;
+       }
+
+       INFO("Interval is changed from %dms to %dms", m_polling_interval, val);
+       m_polling_interval = val;
+       return true;
+}
+
+bool geomag_device::update_value_input_event(void)
+{
+       int geo_raw[4] = {0,};
+       bool x, y, z, hdst;
+       int read_input_cnt = 0;
+       const int INPUT_MAX_BEFORE_SYN = 10;
+       unsigned long long fired_time = 0;
+       bool syn = false;
+
+       x = y = z = hdst = false;
+
+       struct input_event geo_input;
+       _D("geo event detection!");
+
+       while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
+               int len = read(m_node_handle, &geo_input, sizeof(geo_input));
+               if (len != sizeof(geo_input)) {
+                       _E("geo_file read fail, read_len = %d\n",len);
+                       return false;
+               }
+
+               ++read_input_cnt;
+
+               if (geo_input.type == EV_REL) {
+                       switch (geo_input.code) {
+                               case REL_RX:
+                                       geo_raw[0] = (int)geo_input.value;
+                                       x = true;
+                                       break;
+                               case REL_RY:
+                                       geo_raw[1] = (int)geo_input.value;
+                                       y = true;
+                                       break;
+                               case REL_RZ:
+                                       geo_raw[2] = (int)geo_input.value;
+                                       z = true;
+                                       break;
+                               case REL_HWHEEL:
+                                       geo_raw[3] = (int)geo_input.value;
+                                       hdst = true;
+                                       break;
+                               default:
+                                       _E("geo_input event[type = %d, code = %d] is unknown.", geo_input.type, geo_input.code);
+                                       return false;
+                                       break;
+                       }
+               } else if (geo_input.type == EV_SYN) {
+                       syn = true;
+                       fired_time = util::get_timestamp(&geo_input.time);
+               } else {
+                       _E("geo_input event[type = %d, code = %d] is unknown.", geo_input.type, geo_input.code);
+                       return false;
+               }
+       }
+
+       if (syn == false) {
+               _E("EV_SYN didn't come until %d inputs had come", read_input_cnt);
+               return false;
+       }
+
+       if (x)
+               m_x =  geo_raw[0];
+       if (y)
+               m_y =  geo_raw[1];
+       if (z)
+               m_z =  geo_raw[2];
+       if (hdst)
+               m_hdst =  geo_raw[3] - 1; /* accuracy bias: -1 */
+
+       m_fired_time = fired_time;
+
+       _D("m_x = %d, m_y = %d, m_z = %d, m_hdst = %d, time = %lluus", m_x, m_y, m_z, m_hdst, m_fired_time);
+
+       return true;
+}
+
+
+bool geomag_device::update_value_iio(void)
+{
+       struct {
+               int16_t x;
+               int16_t y;
+               int16_t z;
+               int16_t hdst;
+               int64_t timestamp;
+       } __attribute__((packed)) data;
+
+       struct pollfd pfd;
+
+       pfd.fd = m_node_handle;
+       pfd.events = POLLIN | POLLERR;
+       pfd.revents = 0;
+
+       int ret = poll(&pfd, 1, -1);
+
+       if (ret == -1) {
+               _ERRNO(errno, _E, "Failed to poll from m_node_handle:%d", m_node_handle);
+               return false;
+       } else if (!ret) {
+               _E("poll timeout m_node_handle:%d", m_node_handle);
+               return false;
+       }
+
+       if (pfd.revents & POLLERR) {
+               _E("poll exception occurred! m_node_handle:%d", m_node_handle);
+               return false;
+       }
+
+       if (!(pfd.revents & POLLIN)) {
+               _E("poll nothing to read! m_node_handle:%d, pfd.revents = %d", m_node_handle, pfd.revents);
+               return false;
+       }
+
+       int len = read(m_node_handle, &data, sizeof(data));
+
+       if (len != sizeof(data)) {
+               _E("Failed to read data, m_node_handle:%d read_len:%d", m_node_handle, len);
+               return false;
+       }
+
+       m_x = data.x;
+       m_y = data.y;
+       m_z = data.z;
+       m_hdst = data.hdst - 1;
+       m_fired_time = data.timestamp;
+
+       _D("m_x = %d, m_y = %d, m_z = %d, m_hdst = %d, time = %lluus", m_x, m_y, m_z, m_hdst, m_fired_time);
+
+       return true;
+}
+
+int geomag_device::read_fd(uint32_t **ids)
+{
+       if (!update_value()) {
+               DBG("Failed to update value");
+               return false;
+       }
+
+       event_ids.clear();
+       event_ids.push_back(sensor_info.id);
+
+       *ids = &event_ids[0];
+
+       return event_ids.size();
+}
+
+int geomag_device::get_data(uint32_t id, sensor_data_t **data, int *length)
+{
+       int remains = 1;
+       sensor_data_t *sensor_data;
+       sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
+       retvm_if(!sensor_data, -ENOMEM, "Memory allocation failed");
+
+       sensor_data->accuracy = (m_hdst == 1)? 0 : m_hdst;
+       sensor_data->timestamp = m_fired_time;
+       sensor_data->value_count = 4;
+       sensor_data->values[0] = m_x;
+       sensor_data->values[1] = m_y;
+       sensor_data->values[2] = m_z;
+       sensor_data->values[3] = (m_hdst == 1)? 0 : m_hdst;
+
+       raw_to_base(sensor_data);
+
+       *data = sensor_data;
+       *length = sizeof(sensor_data_t);
+
+       return --remains;
+}
+
+void geomag_device::raw_to_base(sensor_data_t *data)
+{
+       data->values[0] = data->values[0] * m_raw_data_unit;
+       data->values[1] = data->values[1] * m_raw_data_unit;
+       data->values[2] = data->values[2] * m_raw_data_unit;
+}
diff --git a/src/geomag/geomag_device.h b/src/geomag/geomag_device.h
new file mode 100644 (file)
index 0000000..70d4d9a
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _GEOMAG_DEVICE_H_
+#define _GEOMAG_DEVICE_H_
+
+#include <sensor/sensor_hal.h>
+#include <string>
+#include <vector>
+#include <functional>
+
+class geomag_device : public sensor_device {
+public:
+       geomag_device();
+       virtual ~geomag_device();
+
+       int get_poll_fd(void);
+       int get_sensors(const sensor_info_t **sensors);
+
+       bool enable(uint32_t id);
+       bool disable(uint32_t id);
+
+       bool set_interval(uint32_t id, unsigned long val);
+
+       int read_fd(uint32_t **ids);
+       int get_data(uint32_t id, sensor_data_t **data, int *length);
+
+private:
+       int m_node_handle;
+       int m_x;
+       int m_y;
+       int m_z;
+       int m_hdst;
+       unsigned long m_polling_interval;
+       unsigned long long m_fired_time;
+       bool m_sensorhub_controlled;
+
+       int m_method;
+       std::string m_data_node;
+       std::string m_enable_node;
+       std::string m_interval_node;
+
+       std::string m_model_id;
+       std::string m_vendor;
+       std::string m_chip_name;
+
+       int m_resolution;
+       float m_min_range;
+       float m_max_range;
+       float m_raw_data_unit;
+
+       long a_x;
+       long a_y;
+       long a_z;
+
+       std::function<bool (void)> update_value;
+
+       std::vector<uint32_t> event_ids;
+
+       bool update_value_input_event(void);
+       bool update_value_iio(void);
+
+       void raw_to_base(sensor_data_t *data);
+};
+#endif /*_GEOMAG_DEVICE_H_*/
diff --git a/src/gyro/gyro_device.cpp b/src/gyro/gyro_device.cpp
new file mode 100644 (file)
index 0000000..d8146ab
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/input.h>
+#include <sys/ioctl.h>
+#include <poll.h>
+
+#include <util.h>
+#include <sensor_common.h>
+#include <sensor_log.h>
+#include <sensor_config.h>
+#include "gyro_device.h"
+
+#define DPS_TO_MDPS 1000
+#define RAW_DATA_TO_DPS_UNIT(X) ((float)(X)/((float)DPS_TO_MDPS))
+#define MIN_RANGE(RES) (-((1 << (RES))/2))
+#define MAX_RANGE(RES) (((1 << (RES))/2)-1)
+
+#define SENSOR_NAME "SENSOR_GYROSCOPE"
+#define SENSOR_TYPE_GYRO               "GYRO"
+
+#define INPUT_NAME     "gyro_sensor"
+#define GYRO_SENSORHUB_POLL_NODE_NAME "gyro_poll_delay"
+
+static sensor_info_t sensor_info = {
+       id: 0x1,
+       name: SENSOR_NAME,
+       type: SENSOR_DEVICE_GYROSCOPE,
+       event_type: (SENSOR_DEVICE_GYROSCOPE << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
+       model_name: UNKNOWN_NAME,
+       vendor: UNKNOWN_NAME,
+       min_range: 0,
+       max_range: 0,
+       resolution: 0,
+       min_interval: 0,
+       max_batch_count: 0,
+       wakeup_supported: false
+};
+
+gyro_device::gyro_device()
+: m_node_handle(-1)
+, m_x(-1)
+, m_y(-1)
+, m_z(-1)
+, m_polling_interval(1000)
+, m_fired_time(0)
+, m_sensorhub_controlled(false)
+{
+       const std::string sensorhub_interval_node_name = GYRO_SENSORHUB_POLL_NODE_NAME;
+       config::sensor_config &config = config::sensor_config::get_instance();
+
+       node_info_query query;
+       node_info info;
+
+       if (!util::find_model_id(SENSOR_TYPE_GYRO, m_model_id)) {
+               _E("Failed to find model id");
+               throw ENXIO;
+       }
+
+       query.sensorhub_controlled = m_sensorhub_controlled = util::is_sensorhub_controlled(sensorhub_interval_node_name);
+       query.sensor_type = SENSOR_TYPE_GYRO;
+       query.key = INPUT_NAME;
+       query.iio_enable_node_name = "gyro_enable";
+       query.sensorhub_interval_node_name = sensorhub_interval_node_name;
+
+       if (!util::get_node_info(query, info)) {
+               _E("Failed to get node info");
+               throw ENXIO;
+       }
+
+       util::show_node_info(info);
+
+       m_method = info.method;
+       m_data_node = info.data_node_path;
+       m_enable_node = info.enable_node_path;
+       m_interval_node = info.interval_node_path;
+
+       if (!config.get(SENSOR_TYPE_GYRO, m_model_id, ELEMENT_VENDOR, m_vendor)) {
+               _E("[VENDOR] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_vendor = %s", m_vendor.c_str());
+
+       if (!config.get(SENSOR_TYPE_GYRO, m_model_id, ELEMENT_NAME, m_chip_name)) {
+               _E("[NAME] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_chip_name = %s",m_chip_name.c_str());
+
+       long resolution;
+
+       if (!config.get(SENSOR_TYPE_GYRO, m_model_id, ELEMENT_RESOLUTION, resolution)) {
+               _E("[RESOLUTION] is empty");
+               throw ENXIO;
+       }
+
+       m_resolution = (int)resolution;
+       _I("m_resolution = %d",m_resolution);
+
+       double raw_data_unit;
+
+       if (!config.get(SENSOR_TYPE_GYRO, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) {
+               _E("[RAW_DATA_UNIT] is empty");
+               throw ENXIO;
+       }
+
+       m_raw_data_unit = (float)(raw_data_unit);
+       _I("m_raw_data_unit = %f", m_raw_data_unit);
+
+       m_node_handle = open(m_data_node.c_str(), O_RDONLY);
+
+       if (m_node_handle < 0) {
+               _ERRNO(errno, _E, "gyro handle open fail for gyro device");
+               throw ENXIO;
+       }
+
+       if (m_method == INPUT_EVENT_METHOD) {
+               if (!util::set_monotonic_clock(m_node_handle))
+                       throw ENXIO;
+
+               update_value = [=]() {
+                       return this->update_value_input_event();
+               };
+       } else {
+               if (!info.buffer_length_node_path.empty())
+                       util::set_node_value(info.buffer_length_node_path, 480);
+
+               if (!info.buffer_enable_node_path.empty())
+                       util::set_node_value(info.buffer_enable_node_path, 1);
+
+               update_value = [=]() {
+                       return this->update_value_iio();
+               };
+       }
+
+       _I("RAW_DATA_TO_DPS_UNIT(m_raw_data_unit) = [%f]",RAW_DATA_TO_DPS_UNIT(m_raw_data_unit));
+       _I("gyro_sensor is created!");
+}
+
+gyro_device::~gyro_device()
+{
+       close(m_node_handle);
+       m_node_handle = -1;
+
+       _I("gyro_sensor is destroyed!");
+}
+
+int gyro_device::get_poll_fd(void)
+{
+       return m_node_handle;
+}
+
+int gyro_device::get_sensors(const sensor_info_t **sensors)
+{
+       sensor_info.model_name = m_chip_name.c_str();
+       sensor_info.vendor = m_vendor.c_str();
+       sensor_info.min_range = MIN_RANGE(m_resolution) * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+       sensor_info.max_range = MAX_RANGE(m_resolution) * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+       sensor_info.resolution = RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+       sensor_info.min_interval = 1;
+       sensor_info.max_batch_count = 0;
+       *sensors = &sensor_info;
+
+       return 1;
+}
+
+bool gyro_device::enable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_GYROSCOPE_ENABLE_BIT);
+       set_interval(id, m_polling_interval);
+
+       m_fired_time = 0;
+       _I("Enable gyroscope sensor");
+       return true;
+}
+
+bool gyro_device::disable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_GYROSCOPE_ENABLE_BIT);
+
+       _I("Disable gyroscope sensor");
+       return true;
+}
+
+bool gyro_device::set_interval(uint32_t id, unsigned long val)
+{
+       unsigned long long polling_interval_ns;
+
+       polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
+
+       if (!util::set_node_value(m_interval_node, polling_interval_ns)) {
+               _E("Failed to set polling resource: %s", m_interval_node.c_str());
+               return false;
+       }
+
+       _I("Interval is changed from %dms to %dms", m_polling_interval, val);
+       m_polling_interval = val;
+       return true;
+}
+
+bool gyro_device::update_value_input_event(void)
+{
+       int gyro_raw[3] = {0,};
+       bool x,y,z;
+       int read_input_cnt = 0;
+       const int INPUT_MAX_BEFORE_SYN = 10;
+       unsigned long long fired_time = 0;
+       bool syn = false;
+
+       x = y = z = false;
+
+       struct input_event gyro_input;
+       _D("gyro event detection!");
+
+       while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
+               int len = read(m_node_handle, &gyro_input, sizeof(gyro_input));
+               if (len != sizeof(gyro_input)) {
+                       _E("gyro_file read fail, read_len = %d",len);
+                       return false;
+               }
+
+               ++read_input_cnt;
+
+               if (gyro_input.type == EV_REL) {
+                       switch (gyro_input.code) {
+                               case REL_RX:
+                                       gyro_raw[0] = (int)gyro_input.value;
+                                       x = true;
+                                       break;
+                               case REL_RY:
+                                       gyro_raw[1] = (int)gyro_input.value;
+                                       y = true;
+                                       break;
+                               case REL_RZ:
+                                       gyro_raw[2] = (int)gyro_input.value;
+                                       z = true;
+                                       break;
+                               default:
+                                       _E("gyro_input event[type = %d, code = %d] is unknown.", gyro_input.type, gyro_input.code);
+                                       return false;
+                                       break;
+                       }
+               } else if (gyro_input.type == EV_SYN) {
+                       syn = true;
+                       fired_time = util::get_timestamp(&gyro_input.time);
+               } else {
+                       _E("gyro_input event[type = %d, code = %d] is unknown.", gyro_input.type, gyro_input.code);
+                       return false;
+               }
+       }
+
+       if (syn == false) {
+               _E("EV_SYN didn't come until %d inputs had come", read_input_cnt);
+               return false;
+       }
+
+       if (x)
+               m_x =  gyro_raw[0];
+       if (y)
+               m_y =  gyro_raw[1];
+       if (z)
+               m_z =  gyro_raw[2];
+
+       m_fired_time = fired_time;
+
+       _D("m_x = %d, m_y = %d, m_z = %d, time = %lluus", m_x, m_y, m_z, m_fired_time);
+
+       return true;
+}
+
+bool gyro_device::update_value_iio(void)
+{
+       struct {
+               int16_t x;
+               int16_t y;
+               int16_t z;
+               int64_t timestamp;
+       } __attribute__((packed)) data;
+
+       struct pollfd pfd;
+
+       pfd.fd = m_node_handle;
+       pfd.events = POLLIN | POLLERR;
+       pfd.revents = 0;
+
+       int ret = poll(&pfd, 1, -1);
+
+       if (ret == -1) {
+               _ERRNO(errno, _E, "Failed to poll from m_node_handle:%d", m_node_handle);
+               return false;
+       } else if (!ret) {
+               _E("poll timeout m_node_handle:%d", m_node_handle);
+               return false;
+       }
+
+       if (pfd.revents & POLLERR) {
+               _E("poll exception occurred! m_node_handle:%d", m_node_handle);
+               return false;
+       }
+
+       if (!(pfd.revents & POLLIN)) {
+               _E("poll nothing to read! m_node_handle:%d, pfd.revents = %d", m_node_handle, pfd.revents);
+               return false;
+       }
+
+       int len = read(m_node_handle, &data, sizeof(data));
+
+       if (len != sizeof(data)) {
+               _E("Failed to read data, m_node_handle:%d read_len:%d", m_node_handle, len);
+               return false;
+       }
+
+       m_x = data.x;
+       m_y = data.y;
+       m_z = data.z;
+       m_fired_time = data.timestamp;
+
+       _D("m_x = %d, m_y = %d, m_z = %d, time = %lluus", m_x, m_y, m_z, m_fired_time);
+
+       return true;
+}
+
+int gyro_device::read_fd(uint32_t **ids)
+{
+       if (!update_value()) {
+               _D("Failed to update value");
+               return false;
+       }
+
+       event_ids.clear();
+       event_ids.push_back(sensor_info.id);
+
+       *ids = &event_ids[0];
+
+       return event_ids.size();
+}
+
+int gyro_device::get_data(uint32_t id, sensor_data_t **data, int *length)
+{
+       int remains = 1;
+       sensor_data_t *sensor_data;
+       sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
+       retvm_if(!sensor_data, -ENOMEM, "Memory allocation failed");
+
+       sensor_data->accuracy = SENSOR_ACCURACY_GOOD;
+       sensor_data->timestamp = m_fired_time;
+       sensor_data->value_count = 3;
+       sensor_data->values[0] = m_x;
+       sensor_data->values[1] = m_y;
+       sensor_data->values[2] = m_z;
+
+       raw_to_base(sensor_data);
+
+       *data = sensor_data;
+       *length = sizeof(sensor_data_t);
+
+       return --remains;
+}
+
+void gyro_device::raw_to_base(sensor_data_t *data)
+{
+       data->value_count = 3;
+       data->values[0] = data->values[0] * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+       data->values[1] = data->values[1] * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+       data->values[2] = data->values[2] * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+}
diff --git a/src/gyro/gyro_device.h b/src/gyro/gyro_device.h
new file mode 100644 (file)
index 0000000..69a5169
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _GYRO_DEVICE_H_
+#define _GYRO_DEVICE_H_
+
+#include <sensor/sensor_hal.h>
+#include <string>
+#include <vector>
+#include <functional>
+
+class gyro_device : public sensor_device {
+public:
+       gyro_device();
+       virtual ~gyro_device();
+
+       int get_poll_fd(void);
+       int get_sensors(const sensor_info_t **sensors);
+
+       bool enable(uint32_t id);
+       bool disable(uint32_t id);
+
+       bool set_interval(uint32_t id, unsigned long val);
+       int read_fd(uint32_t **ids);
+       int get_data(uint32_t id, sensor_data_t **data, int *length);
+
+private:
+       int m_node_handle;
+       int m_x;
+       int m_y;
+       int m_z;
+       unsigned long m_polling_interval;
+       unsigned long long m_fired_time;
+       bool m_sensorhub_controlled;
+
+       int m_method;
+       std::string m_data_node;
+       std::string m_enable_node;
+       std::string m_interval_node;
+
+       std::string m_model_id;
+       std::string m_vendor;
+       std::string m_chip_name;
+
+       int m_resolution;
+       float m_raw_data_unit;
+
+       std::function<bool (void)> update_value;
+
+       std::vector<uint32_t> event_ids;
+
+       bool update_value_input_event(void);
+       bool update_value_iio(void);
+
+       void raw_to_base(sensor_data_t *data);
+};
+#endif /* _GYRO_DEVICE_H_ */
diff --git a/src/gyro_uncal/gyro_uncal_device.cpp b/src/gyro_uncal/gyro_uncal_device.cpp
new file mode 100644 (file)
index 0000000..7564714
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/input.h>
+#include <sys/ioctl.h>
+#include <poll.h>
+
+#include <util.h>
+#include <sensor_common.h>
+#include <sensor_log.h>
+#include <sensor_config.h>
+#include "gyro_uncal_device.h"
+
+#define DPS_TO_MDPS 1000
+#define RAW_DATA_TO_DPS_UNIT(X) ((float)(X)/((float)DPS_TO_MDPS))
+#define MIN_RANGE(RES) (-((1 << (RES))/2))
+#define MAX_RANGE(RES) (((1 << (RES))/2)-1)
+
+#define SENSOR_NAME "SENSOR_GYROSCOPE_UNCALIBRATED"
+#define SENSOR_TYPE_GYRO_UNCAL  "GYRO"
+
+#define INPUT_NAME     "uncal_gyro_sensor"
+#define GYRO_UNCAL_SENSORHUB_POLL_NODE_NAME "uncal_gyro_poll_delay"
+
+static sensor_info_t sensor_info = {
+       id: 0x1,
+       name: SENSOR_NAME,
+       type: SENSOR_DEVICE_GYROSCOPE_UNCAL,
+       event_type: (SENSOR_DEVICE_GYROSCOPE_UNCAL << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
+       model_name: UNKNOWN_NAME,
+       vendor: UNKNOWN_NAME,
+       min_range: 0,
+       max_range: 0,
+       resolution: 0,
+       min_interval: 0,
+       max_batch_count: 0,
+       wakeup_supported: false
+};
+
+gyro_uncal_device::gyro_uncal_device()
+: m_node_handle(-1)
+, m_x(-1)
+, m_y(-1)
+, m_z(-1)
+, m_x_offset(-1)
+, m_y_offset(-1)
+, m_z_offset(-1)
+, m_polling_interval(1000)
+, m_fired_time(0)
+, m_sensorhub_controlled(false)
+{
+       const std::string sensorhub_interval_node_name = GYRO_UNCAL_SENSORHUB_POLL_NODE_NAME;
+       config::sensor_config &config = config::sensor_config::get_instance();
+
+       node_info_query query;
+       node_info info;
+
+       if (!util::find_model_id(SENSOR_TYPE_GYRO_UNCAL, m_model_id)) {
+               _E("Failed to find model id");
+               throw ENXIO;
+       }
+
+       query.sensorhub_controlled = m_sensorhub_controlled = util::is_sensorhub_controlled(sensorhub_interval_node_name);
+       query.sensor_type = SENSOR_TYPE_GYRO_UNCAL;
+       query.key = INPUT_NAME;
+       query.iio_enable_node_name = "uncal_gyro_enable";
+       query.sensorhub_interval_node_name = sensorhub_interval_node_name;
+
+       if (!util::get_node_info(query, info)) {
+               _E("Failed to get node info");
+               throw ENXIO;
+       }
+
+       util::show_node_info(info);
+
+       m_method = info.method;
+       m_data_node = info.data_node_path;
+       m_enable_node = info.enable_node_path;
+       m_interval_node = info.interval_node_path;
+
+       if (!config.get(SENSOR_TYPE_GYRO_UNCAL, m_model_id, ELEMENT_VENDOR, m_vendor)) {
+               _E("[VENDOR] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_vendor = %s", m_vendor.c_str());
+
+       if (!config.get(SENSOR_TYPE_GYRO_UNCAL, m_model_id, ELEMENT_NAME, m_chip_name)) {
+               _E("[NAME] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_chip_name = %s",m_chip_name.c_str());
+
+       long resolution;
+
+       if (!config.get(SENSOR_TYPE_GYRO_UNCAL, m_model_id, ELEMENT_RESOLUTION, resolution)) {
+               _E("[RESOLUTION] is empty");
+               throw ENXIO;
+       }
+
+       m_resolution = (int)resolution;
+       _I("m_resolution = %d",m_resolution);
+
+       double raw_data_unit;
+
+       if (!config.get(SENSOR_TYPE_GYRO_UNCAL, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) {
+               _E("[RAW_DATA_UNIT] is empty");
+               throw ENXIO;
+       }
+
+       m_raw_data_unit = (float)(raw_data_unit);
+       _I("m_raw_data_unit = %f",m_raw_data_unit);
+
+       double min_range;
+
+       if (!config.get(SENSOR_TYPE_GYRO_UNCAL, m_model_id, ELEMENT_MIN_RANGE, min_range))
+               min_range = MIN_RANGE(m_resolution)* RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+
+       m_min_range = (float)min_range;
+       _I("m_min_range = %f",m_min_range);
+
+       double max_range;
+
+       if (!config.get(SENSOR_TYPE_GYRO_UNCAL, m_model_id, ELEMENT_MAX_RANGE, max_range))
+               max_range = MAX_RANGE(m_resolution)* RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+
+       m_max_range = (float)max_range;
+       _I("m_max_range = %f",m_max_range);
+
+       m_node_handle = open(m_data_node.c_str(), O_RDONLY);
+
+       if (m_node_handle < 0) {
+               _ERRNO(errno, _E, "gyro_uncal handle open fail for gyro_uncal device");
+               throw ENXIO;
+       }
+
+       if (m_method == INPUT_EVENT_METHOD) {
+               if (!util::set_monotonic_clock(m_node_handle))
+                       throw ENXIO;
+
+               update_value = [=]() {
+                       return this->update_value_input_event();
+               };
+       }
+
+       _I("RAW_DATA_TO_DPS_UNIT(m_raw_data_unit) = [%f]",RAW_DATA_TO_DPS_UNIT(m_raw_data_unit));
+       _I("gyro_uncal_device is created!");
+}
+
+gyro_uncal_device::~gyro_uncal_device()
+{
+       close(m_node_handle);
+       m_node_handle = -1;
+
+       _I("gyro_uncal_device is destroyed!");
+}
+
+int gyro_uncal_device::get_poll_fd(void)
+{
+       return m_node_handle;
+}
+
+int gyro_uncal_device::get_sensors(const sensor_info_t **sensors)
+{
+       sensor_info.model_name = m_chip_name.c_str();
+       sensor_info.vendor = m_vendor.c_str();
+       sensor_info.min_range = MIN_RANGE(m_resolution) * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+       sensor_info.max_range = MAX_RANGE(m_resolution) * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+       sensor_info.resolution = RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+       sensor_info.min_interval = 1;
+       sensor_info.max_batch_count = 0;
+       *sensors = &sensor_info;
+
+       return 1;
+}
+
+bool gyro_uncal_device::enable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_GYRO_UNCALIB_ENABLE_BIT);
+       set_interval(id, m_polling_interval);
+
+       m_fired_time = 0;
+       INFO("Enable gyroscope uncalibration sensor");
+       return true;
+}
+
+bool gyro_uncal_device::disable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_GYRO_UNCALIB_ENABLE_BIT);
+
+       INFO("Disable gyroscope uncalibration sensor");
+       return true;
+}
+
+bool gyro_uncal_device::set_interval(uint32_t id, unsigned long val)
+{
+       unsigned long long polling_interval_ns;
+
+       polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
+
+       if (!util::set_node_value(m_interval_node, polling_interval_ns)) {
+               _E("Failed to set polling resource: %s", m_interval_node.c_str());
+               return false;
+       }
+
+       _I("Interval is changed from %dms to %dms", m_polling_interval, val);
+       m_polling_interval = val;
+       return true;
+}
+
+bool gyro_uncal_device::update_value_input_event(void)
+{
+       int gyro_uncal_raw[6] = {0,};
+       bool x,y,z,x_offset,y_offset,z_offset;
+       int read_input_cnt = 0;
+       const int INPUT_MAX_BEFORE_SYN = 10;
+       unsigned long long fired_time = 0;
+       bool syn = false;
+
+       x = y = z = x_offset = y_offset = z_offset = false;
+
+       struct input_event gyro_uncal_input;
+       _D("uncal gyro event detection!");
+
+       while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
+               int len = read(m_node_handle, &gyro_uncal_input, sizeof(gyro_uncal_input));
+               if (len != sizeof(gyro_uncal_input)) {
+                       _E("gyro_file read fail, read_len = %d",len);
+                       return false;
+               }
+
+               ++read_input_cnt;
+
+               if (gyro_uncal_input.type == EV_REL) {
+                       switch (gyro_uncal_input.code) {
+                               case REL_RX:
+                                       gyro_uncal_raw[0] = (int)gyro_uncal_input.value;
+                                       x = true;
+                                       break;
+                               case REL_RY:
+                                       gyro_uncal_raw[1] = (int)gyro_uncal_input.value;
+                                       y = true;
+                                       break;
+                               case REL_RZ:
+                                       gyro_uncal_raw[2] = (int)gyro_uncal_input.value;
+                                       z = true;
+                                       break;
+                               case REL_HWHEEL:
+                                       gyro_uncal_raw[3] = (int)gyro_uncal_input.value;
+                                       x_offset = true;
+                                       break;
+                               case REL_DIAL:
+                                       gyro_uncal_raw[4] = (int)gyro_uncal_input.value;
+                                       y_offset = true;
+                                       break;
+                               case REL_WHEEL:
+                                       gyro_uncal_raw[5] = (int)gyro_uncal_input.value;
+                                       z_offset= true;
+                                       break;
+                               default:
+                                       _E("gyro_uncal_input event[type = %d, code = %d] is unknown.", gyro_uncal_input.type, gyro_uncal_input.code);
+                                       return false;
+                                       break;
+                       }
+               } else if (gyro_uncal_input.type == EV_SYN) {
+                       syn = true;
+                       fired_time = util::get_timestamp(&gyro_uncal_input.time);
+               } else {
+                       _E("gyro_uncal_input event[type = %d, code = %d] is unknown.", gyro_uncal_input.type, gyro_uncal_input.code);
+                       return false;
+               }
+       }
+
+       if (syn == false) {
+               _E("EV_SYN didn't come until %d inputs had come", read_input_cnt);
+               return false;
+       }
+
+       if (x)
+               m_x =  gyro_uncal_raw[0];
+       if (y)
+               m_y =  gyro_uncal_raw[1];
+       if (z)
+               m_z =  gyro_uncal_raw[2];
+       if (x_offset)
+               m_x_offset=  gyro_uncal_raw[3];
+       if (y_offset)
+               m_y_offset=  gyro_uncal_raw[4];
+       if (z_offset)
+               m_z_offset=  gyro_uncal_raw[5];
+
+       m_fired_time = fired_time;
+
+       _D("m_x = %d, m_y = %d, m_z = %d, m_x_offset = %d, m_y_offset = %d, m_z_offset = %d, time = %lluus", m_x, m_y, m_z, m_x_offset, m_y_offset, m_z_offset, m_fired_time);
+
+       return true;
+}
+
+int gyro_uncal_device::read_fd(uint32_t **ids)
+{
+       if (!update_value()) {
+               _D("Failed to update value");
+               return false;
+       }
+
+       event_ids.clear();
+       event_ids.push_back(sensor_info.id);
+
+       *ids = &event_ids[0];
+
+       return event_ids.size();
+}
+
+int gyro_uncal_device::get_data(uint32_t id, sensor_data_t **data, int *length)
+{
+       int remains = 1;
+       sensor_data_t *sensor_data;
+       sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
+       retvm_if(!sensor_data, -ENOMEM, "Memory allocation failed");
+
+       sensor_data->accuracy = SENSOR_ACCURACY_GOOD;
+       sensor_data->timestamp = m_fired_time;
+       sensor_data->value_count = 6;
+       sensor_data->values[0] = m_x;
+       sensor_data->values[1] = m_y;
+       sensor_data->values[2] = m_z;
+       sensor_data->values[2] = m_x_offset;
+       sensor_data->values[2] = m_y_offset;
+       sensor_data->values[2] = m_z_offset;
+
+       raw_to_base(sensor_data);
+
+       *data = sensor_data;
+       *length = sizeof(sensor_data_t);
+
+       return --remains;
+}
+
+void gyro_uncal_device::raw_to_base(sensor_data_t *data)
+{
+       data->values[0] = data->values[0] * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+       data->values[1] = data->values[1] * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+       data->values[2] = data->values[2] * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+       data->values[3] = data->values[3] * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+       data->values[4] = data->values[4] * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+       data->values[5] = data->values[5] * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit);
+}
diff --git a/src/gyro_uncal/gyro_uncal_device.h b/src/gyro_uncal/gyro_uncal_device.h
new file mode 100644 (file)
index 0000000..66a8a4e
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _GYRO_UNCAL_DEVICE_H_
+#define _GYRO_UNCAL_DEVICE_H_
+
+#include <sensor/sensor_hal.h>
+#include <string>
+#include <vector>
+#include <functional>
+
+class gyro_uncal_device : public sensor_device {
+public:
+       gyro_uncal_device();
+       virtual ~gyro_uncal_device();
+
+       int get_poll_fd(void);
+       int get_sensors(const sensor_info_t **sensors);
+
+       bool enable(uint32_t id);
+       bool disable(uint32_t id);
+
+       bool set_interval(uint32_t id, unsigned long val);
+
+       int read_fd(uint32_t **ids);
+       int get_data(uint32_t id, sensor_data_t **data, int *length);
+
+private:
+       int m_node_handle;
+       int m_x;
+       int m_y;
+       int m_z;
+       int m_x_offset;
+       int m_y_offset;
+       int m_z_offset;
+       unsigned long m_polling_interval;
+       unsigned long long m_fired_time;
+       bool m_sensorhub_controlled;
+
+       int m_method;
+       std::string m_data_node;
+       std::string m_enable_node;
+       std::string m_interval_node;
+
+       std::string m_model_id;
+       std::string m_vendor;
+       std::string m_chip_name;
+
+       int m_resolution;
+       float m_raw_data_unit;
+       float m_min_range;
+       float m_max_range;
+
+       std::function<bool (void)> update_value;
+
+       std::vector<uint32_t> event_ids;
+
+       bool update_value_input_event(void);
+
+       void raw_to_base(sensor_data_t *data);
+};
+#endif /* _GYRO_UNCAL_DEVICE_H_ */
diff --git a/src/hrm/hrm_device.cpp b/src/hrm/hrm_device.cpp
new file mode 100644 (file)
index 0000000..a04c209
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/input.h>
+#include <sys/ioctl.h>
+#include <poll.h>
+
+#include <util.h>
+#include <sensor_common.h>
+#include <sensor_log.h>
+#include <sensor_config.h>
+#include "hrm_device.h"
+
+#define SENSOR_NAME "SENSOR_HRM"
+#define SENSOR_TYPE_HRM "HRM"
+
+#define INPUT_NAME     "hrm_lib_sensor"
+#define HRM_SENSORHUB_POLL_NODE_NAME "hrm_poll_delay"
+
+#define DEFAULT_RAW_DATA_UNIT 1
+
+static sensor_info_t sensor_info = {
+       id: 0x1,
+       name: SENSOR_NAME,
+       type: SENSOR_DEVICE_HRM,
+       event_type: (SENSOR_DEVICE_HRM << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
+       model_name: UNKNOWN_NAME,
+       vendor: UNKNOWN_NAME,
+       min_range: 0,
+       max_range: 1,
+       resolution: 1,
+       min_interval: 1,
+       max_batch_count: 0,
+       wakeup_supported: false
+};
+
+hrm_device::hrm_device()
+: m_node_handle(-1)
+, m_hr(0)
+, m_spo2(0)
+, m_peek_to_peek(0)
+, m_snr(0.0f)
+, m_raw_data_unit(DEFAULT_RAW_DATA_UNIT)
+, m_polling_interval(1000)
+, m_fired_time(0)
+, m_interval_supported(false)
+, m_sensorhub_controlled(false)
+{
+       double raw_data_unit = DEFAULT_RAW_DATA_UNIT;
+
+       const std::string sensorhub_interval_node_name = HRM_SENSORHUB_POLL_NODE_NAME;
+       config::sensor_config &config = config::sensor_config::get_instance();
+
+       node_info_query query;
+       node_info info;
+
+       if (!util::find_model_id(SENSOR_TYPE_HRM, m_model_id)) {
+               _E("Failed to find model id");
+               throw ENXIO;
+       }
+
+       query.sensorhub_controlled = m_sensorhub_controlled = util::is_sensorhub_controlled(sensorhub_interval_node_name);
+       query.sensor_type = SENSOR_TYPE_HRM;
+       query.key = INPUT_NAME;
+       query.iio_enable_node_name = "hrm_lib_enable";
+       query.sensorhub_interval_node_name = sensorhub_interval_node_name;
+
+       if (!util::get_node_info(query, info)) {
+               _E("Failed to get node info");
+               throw ENXIO;
+       }
+
+       util::show_node_info(info);
+
+       m_method = info.method;
+       m_data_node = info.data_node_path;
+       m_enable_node = info.enable_node_path;
+       m_interval_node = info.interval_node_path;
+
+       if (access(m_interval_node.c_str(), F_OK) == 0)
+               m_interval_supported = true;
+
+       if (!config.get(SENSOR_TYPE_HRM, m_model_id, ELEMENT_VENDOR, m_vendor)) {
+               _E("[VENDOR] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_vendor = %s", m_vendor.c_str());
+
+       if (!config.get(SENSOR_TYPE_HRM, m_model_id, ELEMENT_NAME, m_chip_name)) {
+               _E("[NAME] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_chip_name = %s",m_chip_name.c_str());
+
+       if (!config.get(SENSOR_TYPE_HRM, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) {
+               _I("[RAW_DATA_UNIT] is empty");
+       }
+
+       m_raw_data_unit = (float)(raw_data_unit);
+       _I("m_raw_data_unit = %f", m_raw_data_unit);
+
+       m_node_handle = open(m_data_node.c_str(), O_RDONLY);
+
+       if (m_node_handle < 0) {
+               _ERRNO(errno, _E, "Failed to open HRM handle");
+               throw ENXIO;
+       }
+
+       if (m_method != INPUT_EVENT_METHOD)
+               throw ENXIO;
+
+       if (!util::set_monotonic_clock(m_node_handle))
+               throw ENXIO;
+
+       update_value = [=]() {
+               return this->update_value_input_event();
+       };
+
+       _I("hrm_device is created!");
+}
+
+hrm_device::~hrm_device()
+{
+       close(m_node_handle);
+       m_node_handle = -1;
+
+       _I("hrm_device is destroyed!");
+}
+
+int hrm_device::get_poll_fd(void)
+{
+       return m_node_handle;
+}
+
+int hrm_device::get_sensors(const sensor_info_t **sensors)
+{
+       sensor_info.model_name = m_chip_name.c_str();
+       sensor_info.vendor = m_vendor.c_str();
+       *sensors = &sensor_info;
+
+       return 1;
+}
+
+bool hrm_device::enable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_HRM_LIB_ENABLE_BIT);
+       if (m_interval_supported)
+               set_interval(id, m_polling_interval);
+
+       m_fired_time = 0;
+       _I("Enable HRM sensor");
+       return true;
+}
+
+bool hrm_device::disable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_HRM_LIB_ENABLE_BIT);
+
+       _I("Disable HRM sensor");
+       return true;
+}
+
+bool hrm_device::set_interval(uint32_t id, unsigned long val)
+{
+       unsigned long long polling_interval_ns;
+
+       if (!m_interval_supported)
+               return true;
+
+       polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
+
+       if (!util::set_node_value(m_interval_node, polling_interval_ns)) {
+               _E("Failed to set polling resource: %s", m_interval_node.c_str());
+               return false;
+       }
+
+       _I("Interval is changed from %dms to %dms", m_polling_interval, val);
+       m_polling_interval = val;
+       return true;
+}
+
+bool hrm_device::update_value_input_event(void)
+{
+       const float SNR_SIG_FIGS = 10000.0f;
+       const int HR_MAX = 300;
+       int hrm_raw[4] = {0,};
+       unsigned long long fired_time = 0;
+       int read_input_cnt = 0;
+       const int INPUT_MAX_BEFORE_SYN = 10;
+       bool syn = false;
+
+       struct input_event hrm_input;
+       _D("hrm event detection!");
+
+       while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
+               int len = read(m_node_handle, &hrm_input, sizeof(hrm_input));
+               if (len != sizeof(hrm_input)) {
+                       _E("hrm_file read fail, read_len = %d", len);
+                       return false;
+               }
+
+               ++read_input_cnt;
+
+               if (hrm_input.type == EV_REL) {
+                       switch (hrm_input.code) {
+                       case REL_X:
+                               hrm_raw[0] = (int)hrm_input.value - 1;
+                               break;
+                       case REL_Y:
+                               hrm_raw[1] = (int)hrm_input.value - 1;
+                               break;
+                       case REL_Z:
+                               hrm_raw[2] = (int)hrm_input.value - 1;
+                               break;
+                       default:
+                               _E("hrm_input event[type = %d, code = %d] is unknown.", hrm_input.type, hrm_input.code);
+                               return false;
+                               break;
+                       }
+               } else if (hrm_input.type == EV_SYN) {
+                       syn = true;
+                       fired_time = util::get_timestamp(&hrm_input.time);
+               } else {
+                       _E("hrm_input event[type = %d, code = %d] is unknown.", hrm_input.type, hrm_input.code);
+                       return false;
+               }
+       }
+
+       if ((hrm_raw[0] * m_raw_data_unit) > HR_MAX) {
+               _E("Drop abnormal HR: %d", hrm_raw[0]);
+               return false;
+       }
+
+       m_hr = hrm_raw[0];
+       m_peek_to_peek = hrm_raw[1];
+       m_snr = ((float)hrm_raw[2] / SNR_SIG_FIGS);
+       m_spo2 = 0;
+       m_fired_time = fired_time;
+
+       return true;
+}
+
+int hrm_device::read_fd(uint32_t **ids)
+{
+       if (!update_value()) {
+               _D("Failed to update value");
+               return false;
+       }
+
+       event_ids.clear();
+       event_ids.push_back(sensor_info.id);
+
+       *ids = &event_ids[0];
+
+       return event_ids.size();
+}
+
+int hrm_device::get_data(uint32_t id, sensor_data_t **data, int *length)
+{
+       int remains = 1;
+       sensor_data_t *sensor_data;
+       sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
+       retvm_if(!sensor_data, -ENOMEM, "Memory allocation failed");
+
+       sensor_data->accuracy = SENSOR_ACCURACY_GOOD;
+       sensor_data->timestamp = m_fired_time;
+       sensor_data->value_count = 4;
+       sensor_data->values[0] = m_hr;
+       sensor_data->values[1] = m_spo2;
+       sensor_data->values[2] = m_peek_to_peek;
+       sensor_data->values[3] = m_snr;
+
+       raw_to_base(sensor_data);
+
+       *data = sensor_data;
+       *length = sizeof(sensor_data_t);
+
+       return --remains;
+}
+
+void hrm_device::raw_to_base(sensor_data_t *data)
+{
+       data->values[0] = data->values[0] * m_raw_data_unit;
+}
diff --git a/src/hrm/hrm_device.h b/src/hrm/hrm_device.h
new file mode 100644 (file)
index 0000000..324924b
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _HRM_DEVICE_H_
+#define _HRM_DEVICE_H_
+
+#include <sensor/sensor_hal.h>
+#include <string>
+#include <vector>
+#include <functional>
+
+class hrm_device : public sensor_device {
+public:
+       hrm_device();
+       virtual ~hrm_device();
+
+       int get_poll_fd(void);
+       int get_sensors(const sensor_info_t **sensors);
+
+       bool enable(uint32_t id);
+       bool disable(uint32_t id);
+
+       bool set_interval(uint32_t id, unsigned long val);
+
+       int read_fd(uint32_t **ids);
+       int get_data(uint32_t id, sensor_data_t **data, int *length);
+
+private:
+       int m_node_handle;
+       int m_hr;
+       int m_spo2;
+       int m_peek_to_peek;
+       float m_snr;
+       float m_raw_data_unit;
+       unsigned long m_polling_interval;
+       unsigned long long m_fired_time;
+       bool m_interval_supported;
+       bool m_sensorhub_controlled;
+
+       int m_method;
+       std::string m_data_node;
+       std::string m_enable_node;
+       std::string m_interval_node;
+
+       std::string m_model_id;
+       std::string m_vendor;
+       std::string m_chip_name;
+
+       std::function<bool (void)> update_value;
+
+       std::vector<uint32_t> event_ids;
+
+       bool update_value_input_event(void);
+
+       void raw_to_base(sensor_data_t *data);
+};
+#endif /*_HRM_DEVICE_H_*/
diff --git a/src/hrm_raw/hrm_raw_data_reader.cpp b/src/hrm_raw/hrm_raw_data_reader.cpp
new file mode 100644 (file)
index 0000000..3bb0682
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <sensor_log.h>
+#include "hrm_raw_data_reader.h"
+
+hrm_raw_data_reader::hrm_raw_data_reader()
+{
+}
+hrm_raw_data_reader::~hrm_raw_data_reader()
+{
+}
+
+bool hrm_raw_data_reader::open(void)
+{
+       return true;
+}
+
+bool hrm_raw_data_reader::close(void)
+{
+       return true;
+}
+
+
+bool hrm_raw_data_reader::start(void)
+{
+       return true;
+}
+
+bool hrm_raw_data_reader::stop(void)
+{
+       return true;
+}
diff --git a/src/hrm_raw/hrm_raw_data_reader.h b/src/hrm_raw/hrm_raw_data_reader.h
new file mode 100644 (file)
index 0000000..d515783
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _HRM_RAW_DATA_READER_H_
+#define _HRM_RAW_DATA_READER_H_
+
+#include <sys/time.h>
+#include <sensor/sensor_hal.h>
+
+class hrm_raw_data_reader {
+public:
+       hrm_raw_data_reader();
+       virtual ~hrm_raw_data_reader();
+
+       virtual bool open(void);
+       virtual bool close(void);
+       virtual bool start(void);
+       virtual bool stop(void);
+       virtual bool get_data(int handle, sensor_data_t &data) = 0;
+};
+#endif /* _HRM_RAW_DATA_READER_ */
diff --git a/src/hrm_raw/hrm_raw_data_reader_standard.cpp b/src/hrm_raw/hrm_raw_data_reader_standard.cpp
new file mode 100644 (file)
index 0000000..205579e
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <unistd.h>
+#include <linux/input.h>
+#include <util.h>
+#include <sensor_log.h>
+#include <sensor_common.h>
+#include "hrm_raw_data_reader_standard.h"
+
+#define INPUT_MAX_BEFORE_SYN   20
+#define INPUT_EVENT_BIAS       1
+#define INPUT_VALUE_COUNT      10
+
+hrm_raw_data_reader_standard::hrm_raw_data_reader_standard()
+{
+}
+
+hrm_raw_data_reader_standard::~hrm_raw_data_reader_standard()
+{
+}
+
+bool hrm_raw_data_reader_standard::get_data(int handle, sensor_data_t &data)
+{
+       bool syn = false;
+       int read_input_cnt = 0;
+       int index = 0;
+       struct input_event hrm_raw_input;
+
+       while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
+               int len = read(handle, &hrm_raw_input, sizeof(hrm_raw_input));
+               if (len != sizeof(hrm_raw_input)) {
+                       _E("hrm_raw_file read fail, read_len = %d", len);
+                       return false;
+               }
+
+               ++read_input_cnt;
+
+               if (hrm_raw_input.type == EV_REL) {
+                       index = hrm_raw_input.code - REL_X;
+
+                       /* Check an avaiable value REL_X(0x00) ~ REL_MISC(0x09) */
+                       if (index >= INPUT_VALUE_COUNT) {
+                               _E("hrm_raw_input event[type = %d, code = %d] is unknown.", hrm_raw_input.type, index);
+                               return false;
+                       }
+                       data.values[index] = (unsigned int)hrm_raw_input.value - INPUT_EVENT_BIAS;
+
+               } else if (hrm_raw_input.type == EV_SYN) {
+                       syn = true;
+                       data.timestamp = util::get_timestamp(&hrm_raw_input.time);
+                       data.value_count = INPUT_VALUE_COUNT;
+               } else {
+                       _E("hrm_raw_input event[type = %d, code = %d] is unknown.", hrm_raw_input.type, hrm_raw_input.code);
+                       return false;
+               }
+       }
+
+       if (!syn) {
+               _E("EV_SYN didn't come until %d inputs had come", read_input_cnt);
+               return false;
+       }
+       return true;
+}
diff --git a/src/hrm_raw/hrm_raw_data_reader_standard.h b/src/hrm_raw/hrm_raw_data_reader_standard.h
new file mode 100644 (file)
index 0000000..caa556a
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 "hrm_raw_data_reader.h"
+
+#ifndef _HRM_RAW_DATA_READER_STANDARD_H_
+#define _HRM_RAW_DATA_READER_STANDARD_H_
+
+class hrm_raw_data_reader_standard : public hrm_raw_data_reader {
+public:
+       hrm_raw_data_reader_standard();
+       ~hrm_raw_data_reader_standard();
+
+       virtual bool get_data(int handle, sensor_data_t &data);
+};
+#endif /* _HRM_RAW_DATA_READER_STANDARD_H_ */
diff --git a/src/hrm_raw/hrm_raw_device.cpp b/src/hrm_raw/hrm_raw_device.cpp
new file mode 100644 (file)
index 0000000..6f1d47f
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/input.h>
+#include <sys/ioctl.h>
+#include <poll.h>
+
+#include <macro.h>
+#include <util.h>
+#include <sensor_common.h>
+#include <sensor_log.h>
+#include <sensor_config.h>
+
+#include "hrm_raw_data_reader_standard.h"
+#include "hrm_raw_device.h"
+
+#define SENSOR_NAME "SENSOR_HRM_RAW"
+#define SENSOR_TYPE_HRM_RAW "HRM_RAW"
+
+#define INPUT_NAME     "hrm_raw_sensor"
+#define HRM_SENSORHUB_POLL_NODE_NAME "hrm_poll_delay"
+
+#define INDEX_HRM_RAW 0x1
+#define INDEX_HRM_LED_GREEN 0x2
+
+#define ELEMENT_READER                 "READER"
+#define POLL_1HZ_MS 1000
+
+static sensor_info_t sensor_info[] = {
+       {
+               id: INDEX_HRM_RAW,
+               name: SENSOR_NAME,
+               type: SENSOR_DEVICE_HRM_RAW,
+               event_type: (SENSOR_DEVICE_HRM_RAW << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
+               model_name: UNKNOWN_NAME,
+               vendor: UNKNOWN_NAME,
+               min_range: 0,
+               max_range: 1,
+               resolution: 1,
+               min_interval: 1,
+               max_batch_count: 0,
+               wakeup_supported: false
+       },
+       {
+               id: INDEX_HRM_LED_GREEN,
+               name: "HRM LED GREEN SENSOR",
+               type: SENSOR_DEVICE_HRM_LED_GREEN,
+               event_type: (SENSOR_DEVICE_HRM_LED_GREEN << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
+               model_name: UNKNOWN_NAME,
+               vendor: UNKNOWN_NAME,
+               min_range: 0,
+               max_range: 1,
+               resolution: 1,
+               min_interval: 1,
+               max_batch_count: 0,
+               wakeup_supported: false
+       }
+};
+
+hrm_raw_device::hrm_raw_device()
+: m_node_handle(-1)
+, m_polling_interval(POLL_1HZ_MS)
+, m_raw_interval(POLL_1HZ_MS)
+, m_led_green_interval(POLL_1HZ_MS)
+, m_interval_supported(false)
+, m_sensorhub_controlled(false)
+, m_enable(0)
+, m_reader(NULL)
+{
+       const std::string sensorhub_interval_node_name = HRM_SENSORHUB_POLL_NODE_NAME;
+       config::sensor_config &config = config::sensor_config::get_instance();
+
+       node_info_query query;
+       node_info info;
+
+       if (!util::find_model_id(SENSOR_TYPE_HRM_RAW, m_model_id)) {
+               _E("Failed to find model id");
+               throw ENXIO;
+       }
+
+       query.sensorhub_controlled = m_sensorhub_controlled = util::is_sensorhub_controlled(sensorhub_interval_node_name);
+       query.sensor_type = SENSOR_TYPE_HRM_RAW;
+       query.key = INPUT_NAME;
+       query.iio_enable_node_name = "hrm_raw_enable";
+       query.sensorhub_interval_node_name = sensorhub_interval_node_name;
+
+       if (!util::get_node_info(query, info)) {
+               _E("Failed to get node info");
+               throw ENXIO;
+       }
+
+       util::show_node_info(info);
+
+       m_method = info.method;
+       m_data_node = info.data_node_path;
+       m_enable_node = info.enable_node_path;
+       m_interval_node = info.interval_node_path;
+
+       if (access(m_interval_node.c_str(), F_OK) == 0)
+               m_interval_supported = true;
+
+       if (!config.get(SENSOR_TYPE_HRM_RAW, m_model_id, ELEMENT_VENDOR, m_vendor)) {
+               _E("[VENDOR] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_vendor = %s", m_vendor.c_str());
+
+       if (!config.get(SENSOR_TYPE_HRM_RAW, m_model_id, ELEMENT_NAME, m_chip_name)) {
+               _E("[NAME] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_chip_name = %s",m_chip_name.c_str());
+
+       std::string reader;
+
+       if (!config.get(SENSOR_TYPE_HRM_RAW, m_model_id, ELEMENT_READER, reader)) {
+               _E("[READER] is empty");
+               throw ENXIO;
+       }
+
+       _I("reader = %s", reader.c_str());
+
+       m_node_handle = open(m_data_node.c_str(), O_RDONLY);
+
+       if (m_node_handle < 0) {
+               _ERRNO(errno, _E, "hrm raw handle open fail for hrm raw sensor");
+               throw ENXIO;
+       }
+
+       if (m_method != INPUT_EVENT_METHOD)
+               throw ENXIO;
+
+       if (!util::set_monotonic_clock(m_node_handle))
+               throw ENXIO;
+
+       m_reader = get_reader(reader);
+
+       if (!m_reader) {
+               _E("Not supported HRM sensor: %s", m_model_id.c_str());
+               throw ENXIO;
+       }
+
+       if (!m_reader->open())
+               throw ENXIO;
+
+       _I("hrm_raw_device is created!");
+}
+
+hrm_raw_device::~hrm_raw_device()
+{
+       delete m_reader;
+       close(m_node_handle);
+       m_node_handle = -1;
+
+       _I("hrm_raw_device is destroyed!");
+}
+
+int hrm_raw_device::get_poll_fd()
+{
+       return m_node_handle;
+}
+
+int hrm_raw_device::get_sensors(const sensor_info_t **sensors)
+{
+       int size = ARRAY_SIZE(sensor_info);
+
+       for (int i = 0; i < size; ++i) {
+               sensor_info[i].model_name = m_chip_name.c_str();
+               sensor_info[i].vendor = m_vendor.c_str();
+       }
+
+       *sensors = sensor_info;
+
+       return size;
+}
+
+bool hrm_raw_device::enable(uint32_t id)
+{
+       ++m_enable;
+
+       if (m_enable > 1)
+               return true;
+
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_HRM_RAW_ENABLE_BIT);
+       if (m_interval_supported)
+               set_interval(id, m_polling_interval);
+
+       m_data.timestamp = 0;
+
+       m_reader->start();
+       _I("Enable HRM Raw sensor");
+       return true;
+}
+
+bool hrm_raw_device::disable(uint32_t id)
+{
+       --m_enable;
+
+       if (m_enable > 0)
+               return true;
+
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_HRM_RAW_ENABLE_BIT);
+
+       m_reader->stop();
+       m_enable = 0;
+       _I("Disable HRM Raw sensor");
+       return true;
+}
+
+bool hrm_raw_device::set_interval(uint32_t id, unsigned long val)
+{
+       unsigned long interval = 100;
+       unsigned long long polling_interval_ns;
+
+       if (!m_interval_supported)
+               return true;
+
+       if (id == INDEX_HRM_LED_GREEN)
+               interval = (val > m_raw_interval)?m_raw_interval:val;
+       else
+               interval = (val > m_led_green_interval)?m_led_green_interval:val;
+
+       polling_interval_ns = ((unsigned long long)(interval) * 1000llu * 1000llu);
+
+       if (!util::set_node_value(m_interval_node, polling_interval_ns)) {
+               _E("Failed to set polling resource: %s", m_interval_node.c_str());
+               return false;
+       }
+
+       _I("Interval is changed from %dms to %dms", m_polling_interval, interval);
+       m_polling_interval = interval;
+
+       if (id == INDEX_HRM_LED_GREEN)
+               m_led_green_interval = val;
+       else
+               m_raw_interval = val;
+
+       return true;
+}
+
+int hrm_raw_device::read_fd(uint32_t **ids)
+{
+       if (!m_reader->get_data(m_node_handle, m_data)) {
+               _D("Failed to update value");
+               return false;
+       }
+
+       int size = ARRAY_SIZE(sensor_info);
+
+       event_ids.clear();
+
+       for (int i = 0; i < size; ++i)
+               event_ids.push_back(sensor_info[i].id);
+
+       *ids = &event_ids[0];
+
+       return event_ids.size();
+}
+
+int hrm_raw_device::get_data(uint32_t id, sensor_data_t **data, int *length)
+{
+       int remains = 1;
+       sensor_data_t *sensor_data;
+       sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
+       retvm_if(!sensor_data, -ENOMEM, "Memory allocation failed");
+
+       sensor_data->accuracy = SENSOR_ACCURACY_GOOD;
+       sensor_data->timestamp = m_data.timestamp;
+
+       if (id == INDEX_HRM_LED_GREEN) {
+               sensor_data->value_count = 1;
+               sensor_data->values[0] = m_data.values[5];
+       } else {
+               sensor_data->value_count = m_data.value_count;
+               memcpy(sensor_data->values, m_data.values, m_data.value_count * sizeof(m_data.values[0]));
+       }
+
+       *data = sensor_data;
+       *length = sizeof(sensor_data_t);
+
+       return --remains;
+}
+
+hrm_raw_data_reader* hrm_raw_device::get_reader(const std::string& reader)
+{
+       return new(std::nothrow) hrm_raw_data_reader_standard();
+}
diff --git a/src/hrm_raw/hrm_raw_device.h b/src/hrm_raw/hrm_raw_device.h
new file mode 100644 (file)
index 0000000..6dfa7d3
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _HRM_RAW_DEVICE_H_
+#define _HRM_RAW_DEVICE_H_
+
+#include <sensor/sensor_hal.h>
+#include <string>
+#include <vector>
+#include <functional>
+#include "hrm_raw_data_reader.h"
+
+class hrm_raw_device : public sensor_device {
+public:
+       hrm_raw_device();
+       virtual ~hrm_raw_device();
+
+       int get_poll_fd(void);
+       int get_sensors(const sensor_info_t **sensors);
+
+       bool enable(uint32_t id);
+       bool disable(uint32_t id);
+
+       bool set_interval(uint32_t id, unsigned long val);
+
+       int read_fd(uint32_t **ids);
+       int get_data(uint32_t id, sensor_data_t **data, int *length);
+
+private:
+       int m_node_handle;
+       sensor_data_t m_data;
+       unsigned long m_polling_interval;
+       unsigned long m_raw_interval;
+       unsigned long m_led_green_interval;
+
+       bool m_interval_supported;
+       bool m_sensorhub_controlled;
+       int m_enable;
+
+       hrm_raw_data_reader *m_reader;
+
+       int m_method;
+       std::string m_data_node;
+       std::string m_enable_node;
+       std::string m_interval_node;
+
+       std::string m_model_id;
+       std::string m_vendor;
+       std::string m_chip_name;
+
+       std::vector<uint32_t> event_ids;
+
+       hrm_raw_data_reader* get_reader(const std::string& reader);
+};
+#endif /* _HRM_RAW_DEVICE_H_ */
diff --git a/src/light/light_device.cpp b/src/light/light_device.cpp
new file mode 100644 (file)
index 0000000..4a22bab
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <math.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/input.h>
+#include <sys/ioctl.h>
+#include <poll.h>
+
+#include <macro.h>
+#include <util.h>
+#include <sensor_common.h>
+#include <sensor_log.h>
+#include <sensor_config.h>
+#include "light_device.h"
+
+#define BIAS   1
+
+#define SENSOR_NAME "SENSOR_LIGHT"
+
+/* ADC value received from Kernel */
+#define MODEL_ID_CAPELLA               "CM36686"
+
+#define SENSOR_TYPE_LIGHT              "LIGHT"
+
+#define INPUT_NAME     "light_sensor"
+#define LIGHT_SENSORHUB_POLL_NODE_NAME "light_poll_delay"
+
+const static int light_level[] = {0, 1, 165, 288, 497, 869, 1532, 2692, 4692, 8280, 21428, 65535, 137852};
+
+static sensor_info_t sensor_info = {
+       id: 0x1,
+       name: SENSOR_NAME,
+       type: SENSOR_DEVICE_LIGHT,
+       event_type: (SENSOR_DEVICE_LIGHT << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
+       model_name: UNKNOWN_NAME,
+       vendor: UNKNOWN_NAME,
+       min_range: 0,
+       max_range: 65536,
+       resolution: 1,
+       min_interval: 1,
+       max_batch_count: 0,
+       wakeup_supported: false
+};
+
+light_device::light_device()
+: m_node_handle(-1)
+, m_lux(-1)
+, m_polling_interval(1000)
+, m_fired_time(0)
+, m_sensorhub_controlled(false)
+{
+       const std::string sensorhub_interval_node_name = LIGHT_SENSORHUB_POLL_NODE_NAME;
+       config::sensor_config &config = config::sensor_config::get_instance();
+
+       node_info_query query;
+       node_info info;
+
+       if (!util::find_model_id(SENSOR_TYPE_LIGHT, m_model_id)) {
+               _E("Failed to find model id");
+               throw ENXIO;
+       }
+
+       query.sensorhub_controlled = m_sensorhub_controlled = util::is_sensorhub_controlled(sensorhub_interval_node_name);
+       query.sensor_type = SENSOR_TYPE_LIGHT;
+       query.key = INPUT_NAME;
+       query.iio_enable_node_name = "light_enable";
+       query.sensorhub_interval_node_name = sensorhub_interval_node_name;
+
+       if (!util::get_node_info(query, info)) {
+               _E("Failed to get node info");
+               throw ENXIO;
+       }
+
+       util::show_node_info(info);
+
+       m_method = info.method;
+       m_data_node = info.data_node_path;
+       m_enable_node = info.enable_node_path;
+       m_interval_node = info.interval_node_path;
+
+       if (!config.get(SENSOR_TYPE_LIGHT, m_model_id, ELEMENT_VENDOR, m_vendor)) {
+               _E("[VENDOR] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_vendor = %s", m_vendor.c_str());
+
+       if (!config.get(SENSOR_TYPE_LIGHT, m_model_id, ELEMENT_NAME, m_chip_name)) {
+               _E("[NAME] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_chip_name = %s",m_chip_name.c_str());
+
+       m_node_handle = open(m_data_node.c_str(), O_RDONLY);
+
+       if (m_node_handle < 0) {
+               _ERRNO(errno, _E, "light handle open fail for light device");
+               throw ENXIO;
+       }
+
+       if (m_method == INPUT_EVENT_METHOD) {
+               if (!util::set_monotonic_clock(m_node_handle))
+                       throw ENXIO;
+
+               if (m_chip_name == MODEL_ID_CAPELLA) {
+                       update_value = [=]() {
+                               return this->update_value_adc();
+                       };
+               } else {
+                       update_value = [=]() {
+                               return this->update_value_lux();
+                       };
+               }
+       }
+
+       _I("light_device is created!");
+}
+
+light_device::~light_device()
+{
+       close(m_node_handle);
+       m_node_handle = -1;
+
+       _I("light_device is destroyed!");
+}
+
+int light_device::get_poll_fd()
+{
+       return m_node_handle;
+}
+
+int light_device::get_sensors(const sensor_info_t **sensors)
+{
+       sensor_info.model_name = m_chip_name.c_str();
+       sensor_info.vendor = m_vendor.c_str();
+       *sensors = &sensor_info;
+
+       return 1;
+}
+
+bool light_device::enable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_LIGHT_ENABLE_BIT);
+       set_interval(id, m_polling_interval);
+
+       m_fired_time = 0;
+       _I("Enable light sensor");
+       return true;
+}
+
+bool light_device::disable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_LIGHT_ENABLE_BIT);
+
+       INFO("Disable light sensor");
+       return true;
+}
+
+bool light_device::set_interval(uint32_t id, unsigned long val)
+{
+       unsigned long long polling_interval_ns;
+
+       polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
+
+       if (!util::set_node_value(m_interval_node, polling_interval_ns)) {
+               _E("Failed to set polling resource: %s", m_interval_node.c_str());
+               return false;
+       }
+
+       _I("Interval is changed from %dms to %dms", m_polling_interval, val);
+       m_polling_interval = val;
+       return true;
+}
+
+bool light_device::update_value_adc(void)
+{
+       int light_raw[2] = {0,};
+       int als = -1;
+       int w = -1;
+       int lux = -1;
+       float i_cf = 0.0f;
+       bool adc, white;
+       int read_input_cnt = 0;
+       const int INPUT_MAX_BEFORE_SYN = 10;
+       unsigned long long fired_time = 0;
+       bool syn = false;
+
+       adc = white = false;
+
+       struct input_event light_input;
+       _D("light event detection!");
+
+       while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
+               int len = read(m_node_handle, &light_input, sizeof(light_input));
+               if (len != sizeof(light_input)) {
+                       _E("light_file read fail, read_len = %d",len);
+                       return false;
+               }
+
+               ++read_input_cnt;
+
+               if (light_input.type == EV_REL) {
+                       switch (light_input.code) {
+                       case REL_DIAL:
+                               light_raw[0] = (int)light_input.value - BIAS;
+                               adc = true;
+                               break;
+                       case REL_WHEEL:
+                               light_raw[1] = (int)light_input.value - BIAS;
+                               white = true;
+                               break;
+                       default:
+                               _E("light_input event[type = %d, code = %d] is unknown.", light_input.type, light_input.code);
+                               return false;
+                               break;
+                       }
+               } else if (light_input.type == EV_SYN) {
+                       syn = true;
+                       fired_time = util::get_timestamp(&light_input.time);
+               } else {
+                       _E("light_input event[type = %d, code = %d] is unknown.", light_input.type, light_input.code);
+                       return false;
+               }
+       }
+
+       if (syn == false) {
+               _E("EV_SYN didn't come until %d inputs had come", read_input_cnt);
+               return false;
+       }
+
+       if (adc && white) {
+               als =  light_raw[0];
+               w = (light_raw[1])? light_raw[1] : 1;
+               i_cf = als / (float) w;
+               if (i_cf >= 0.33f) {
+                       lux = 0.6985f * pow(als, 0.9943f);
+               } else {
+                       lux = 0.25f * pow(als, 1.0552f);
+               }
+       }
+
+       _D("update_value_lux, lux : %d", lux);
+
+       m_fired_time = fired_time;
+       m_lux = lux;
+
+       return true;
+}
+
+bool light_device::update_value_lux(void)
+{
+       int lux = -1;
+       struct input_event light_event;
+       _D("light event detection!");
+
+       int len = read(m_node_handle, &light_event, sizeof(light_event));
+       if (len == -1) {
+               _ERRNO(errno, _E, "Failed to read from m_node_handle");
+               return false;
+       }
+
+       if (light_event.type == EV_ABS && light_event.code == ABS_MISC) {
+               lux = light_event.value;
+       } else if (light_event.type == EV_REL && light_event.code == REL_RX) {
+               lux = light_event.value - BIAS;
+       } else {
+               _D("light input event[type = %d, code = %d] is unknown.", light_event.type, light_event.code);
+               return false;
+       }
+
+       _D("read event, len : %d, type : %x, code : %x, value : %x",
+               len, light_event.type, light_event.code, light_event.value);
+
+       _D("update_value_lux, lux : %d", lux);
+
+       m_lux = lux;
+       m_fired_time = util::get_timestamp(&light_event.time);
+
+       return true;
+}
+
+int light_device::read_fd(uint32_t **ids)
+{
+       if (!update_value()) {
+               DBG("Failed to update value");
+               return false;
+       }
+
+       event_ids.clear();
+       event_ids.push_back(sensor_info.id);
+
+       *ids = &event_ids[0];
+
+       return event_ids.size();
+}
+
+int light_device::get_data(uint32_t id, sensor_data_t **data, int *length)
+{
+       int remains = 1;
+       sensor_data_t *sensor_data;
+       sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
+       retvm_if(!sensor_data, -ENOMEM, "Memory allocation failed");
+
+       sensor_data->accuracy = SENSOR_ACCURACY_GOOD;
+       sensor_data->timestamp = m_fired_time;
+       sensor_data->value_count = 1;
+       sensor_data->values[0] = (float)m_lux;
+
+       *data = sensor_data;
+       *length = sizeof(sensor_data_t);
+
+       return --remains;
+}
+
+int light_device::adc_to_light_level(int adc)
+{
+       int level_cnt = ARRAY_SIZE(light_level) - 1;
+
+       for (int i = 0; i < level_cnt; ++i) {
+               if (adc >= light_level[i] && adc < light_level[i + 1])
+                       return i;
+       }
+
+       return -1;
+}
diff --git a/src/light/light_device.h b/src/light/light_device.h
new file mode 100644 (file)
index 0000000..4a1a71c
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _LIGHT_DEVICE_H_
+#define _LIGHT_DEVICE_H_
+
+#include <sensor/sensor_hal.h>
+#include <string>
+#include <vector>
+#include <functional>
+
+class light_device : public sensor_device {
+public:
+       light_device();
+       virtual ~light_device();
+
+       int get_poll_fd(void);
+       int get_sensors(const sensor_info_t **sensors);
+
+       bool enable(uint32_t id);
+       bool disable(uint32_t id);
+
+       bool set_interval(uint32_t id, unsigned long val);
+
+       int read_fd(uint32_t **ids);
+       int get_data(uint32_t id, sensor_data_t **data, int *length);
+
+private:
+       int m_node_handle;
+       int m_lux;
+       unsigned long m_polling_interval;
+       unsigned long long m_fired_time;
+       bool m_sensorhub_controlled;
+
+       int m_method;
+       std::string m_enable_node;
+       std::string m_data_node;
+       std::string m_interval_node;
+
+       std::string m_model_id;
+       std::string m_vendor;
+       std::string m_chip_name;
+
+       std::function<bool (void)> update_value;
+
+       std::vector<uint32_t> event_ids;
+
+       bool update_value_adc(void);
+       bool update_value_lux(void);
+       int adc_to_light_level(int adc);
+};
+#endif /* _LIGHT_DEVICE_H_ */
diff --git a/src/macro.h b/src/macro.h
new file mode 100644 (file)
index 0000000..132b547
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 __MACRO_H__
+#define __MACRO_H__
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#endif /* __MACRO_H__ */
diff --git a/src/pressure/pressure_device.cpp b/src/pressure/pressure_device.cpp
new file mode 100644 (file)
index 0000000..c662636
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/input.h>
+#include <sys/ioctl.h>
+#include <poll.h>
+#include <math.h>
+
+#include <util.h>
+#include <sensor_common.h>
+#include <sensor_log.h>
+#include <sensor_config.h>
+#include "pressure_device.h"
+
+#define SEA_LEVEL_RESOLUTION 0.01
+#define SEA_LEVEL_PRESSURE 101325.0
+#define SEA_LEVEL_EPSILON 0.00001
+
+#define SENSOR_NAME "SENSOR_PRESSURE"
+#define SENSOR_TYPE_PRESSURE "PRESSURE"
+
+#define ELEMENT_TEMPERATURE_RESOLUTION "TEMPERATURE_RESOLUTION"
+#define ELEMENT_TEMPERATURE_OFFSET             "TEMPERATURE_OFFSET"
+
+#define INPUT_NAME "pressure_sensor"
+#define PRESSURE_SENSORHUB_POLL_NODE_NAME "pressure_poll_delay"
+
+static sensor_info_t sensor_info = {
+       id: 0x1,
+       name: SENSOR_NAME,
+       type: SENSOR_DEVICE_PRESSURE,
+       event_type: (SENSOR_DEVICE_PRESSURE << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
+       model_name: UNKNOWN_NAME,
+       vendor: UNKNOWN_NAME,
+       min_range: 0,
+       max_range: 0,
+       resolution: 0,
+       min_interval: 0,
+       max_batch_count: 0,
+       wakeup_supported: false
+};
+
+pressure_device::pressure_device()
+: m_node_handle(-1)
+, m_pressure(0)
+, m_resolution(0)
+, m_temperature(0)
+, m_sea_level_pressure(SEA_LEVEL_PRESSURE)
+, m_temperature_resolution(0)
+, m_temperature_offset(0)
+, m_polling_interval(1000)
+, m_fired_time(0)
+, m_sensorhub_controlled(false)
+{
+       const std::string sensorhub_interval_node_name = PRESSURE_SENSORHUB_POLL_NODE_NAME;
+       config::sensor_config &config = config::sensor_config::get_instance();
+
+       node_info_query query;
+       node_info info;
+
+       if (!util::find_model_id(SENSOR_TYPE_PRESSURE, m_model_id)) {
+               _E("Failed to find model id");
+               throw ENXIO;
+
+       }
+
+       query.sensorhub_controlled = m_sensorhub_controlled = util::is_sensorhub_controlled(sensorhub_interval_node_name);
+       query.sensor_type = SENSOR_TYPE_PRESSURE;
+       query.key = INPUT_NAME;
+       query.iio_enable_node_name = "pressure_enable";
+       query.sensorhub_interval_node_name = sensorhub_interval_node_name;
+
+       if (!util::get_node_info(query, info)) {
+               _E("Failed to get node info");
+               throw ENXIO;
+       }
+
+       util::show_node_info(info);
+
+       m_method = info.method;
+       m_data_node = info.data_node_path;
+       m_enable_node = info.enable_node_path;
+       m_interval_node = info.interval_node_path;
+
+       if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_VENDOR, m_vendor)) {
+               _E("[VENDOR] is empty\n");
+               throw ENXIO;
+       }
+
+       _I("m_vendor = %s", m_vendor.c_str());
+
+       if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_NAME, m_chip_name)) {
+               _E("[NAME] is empty\n");
+               throw ENXIO;
+       }
+
+       _I("m_chip_name = %s", m_chip_name.c_str());
+
+       double min_range;
+
+       if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_MIN_RANGE, min_range)) {
+               _E("[MIN_RANGE] is empty\n");
+               throw ENXIO;
+       }
+
+       m_min_range = (float)min_range;
+       _I("m_min_range = %f\n",m_min_range);
+
+       double max_range;
+
+       if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_MAX_RANGE, max_range)) {
+               _E("[MAX_RANGE] is empty\n");
+               throw ENXIO;
+       }
+
+       m_max_range = (float)max_range;
+       _I("m_max_range = %f\n",m_max_range);
+
+       double raw_data_unit;
+
+       if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) {
+               _E("[RAW_DATA_UNIT] is empty\n");
+               throw ENXIO;
+       }
+
+       m_raw_data_unit = (float)(raw_data_unit);
+       _I("m_raw_data_unit = %f\n", m_raw_data_unit);
+
+       double temperature_resolution;
+       if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_TEMPERATURE_RESOLUTION, temperature_resolution)) {
+               ERR("[TEMPERATURE_RESOLUTION] is empty\n");
+               throw ENXIO;
+       }
+
+       m_temperature_resolution = (float)temperature_resolution;
+       INFO("m_temperature_resolution = %f\n", m_temperature_resolution);
+
+       double temperature_offset;
+
+       if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_TEMPERATURE_OFFSET, temperature_offset)) {
+               ERR("[TEMPERATURE_OFFSET] is empty\n");
+               throw ENXIO;
+       }
+
+       m_temperature_offset = (float)temperature_offset;
+       INFO("m_temperature_offset = %f\n", m_temperature_offset);
+
+       m_node_handle = open(m_data_node.c_str(), O_RDONLY);
+
+       if (m_node_handle < 0) {
+               _ERRNO(errno, _E, "pressure handle open fail for pressure sensor");
+               throw ENXIO;
+       }
+
+       if (m_method == INPUT_EVENT_METHOD) {
+               if (!util::set_monotonic_clock(m_node_handle))
+                       throw ENXIO;
+
+               update_value = [=]() {
+                       return this->update_value_input_event();
+               };
+       }
+
+       _I("pressure_device is created!\n");
+}
+
+pressure_device::~pressure_device()
+{
+       close(m_node_handle);
+       m_node_handle = -1;
+
+       _I("pressure_device is destroyed!\n");
+}
+
+int pressure_device::get_poll_fd(void)
+{
+       return m_node_handle;
+}
+
+int pressure_device::get_sensors(const sensor_info_t **sensors)
+{
+       sensor_info.model_name = m_chip_name.c_str();
+       sensor_info.vendor = m_vendor.c_str();
+       sensor_info.min_range = m_min_range;
+       sensor_info.max_range = m_max_range;
+       sensor_info.resolution = m_raw_data_unit;
+       sensor_info.min_interval = 1;
+       sensor_info.max_batch_count = 0;
+       *sensors = &sensor_info;
+
+       return 1;
+}
+
+bool pressure_device::enable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_PRESSURE_ENABLE_BIT);
+       set_interval(id, m_polling_interval);
+
+       m_fired_time = 0;
+       INFO("Enable pressure sensor");
+       return true;
+}
+
+bool pressure_device::disable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_PRESSURE_ENABLE_BIT);
+
+       INFO("Disable pressure sensor");
+       return true;
+
+}
+
+bool pressure_device::set_interval(uint32_t id, unsigned long val)
+{
+       unsigned long long polling_interval_ns;
+
+       polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
+
+       if (!util::set_node_value(m_interval_node, polling_interval_ns)) {
+               ERR("Failed to set polling resource: %s\n", m_interval_node.c_str());
+               return false;
+       }
+
+       INFO("Interval is changed from %dms to %dms", m_polling_interval, val);
+       m_polling_interval = val;
+       return true;
+}
+
+bool pressure_device::update_value_input_event(void)
+{
+       int pressure_raw[3] = {0,};
+       bool pressure = false;
+       bool sea_level = false;
+       bool temperature = false;
+       int read_input_cnt = 0;
+       const int INPUT_MAX_BEFORE_SYN = 10;
+       unsigned long long fired_time = 0;
+       bool syn = false;
+
+       struct input_event pressure_event;
+       _D("pressure event detection!");
+
+       while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
+               int len = read(m_node_handle, &pressure_event, sizeof(pressure_event));
+               if (len != sizeof(pressure_event)) {
+                       _E("pressure_file read fail, read_len = %d\n",len);
+                       return false;
+               }
+
+               ++read_input_cnt;
+
+               if (pressure_event.type == EV_REL) {
+                       switch (pressure_event.code) {
+                               case REL_HWHEEL:
+                                       pressure_raw[0] = (int)pressure_event.value;
+                                       pressure = true;
+                                       break;
+                               case REL_DIAL:
+                                       pressure_raw[1] = (int)pressure_event.value;
+                                       sea_level = true;
+                                       break;
+                               case REL_WHEEL:
+                                       pressure_raw[2] = (int)pressure_event.value;
+                                       temperature = true;
+                                       break;
+                               default:
+                                       _E("pressure_event event[type = %d, code = %d] is unknown.", pressure_event.type, pressure_event.code);
+                                       return false;
+                                       break;
+                       }
+               } else if (pressure_event.type == EV_SYN) {
+                       syn = true;
+                       fired_time = util::get_timestamp(&pressure_event.time);
+               } else {
+                       _E("pressure_event event[type = %d, code = %d] is unknown.", pressure_event.type, pressure_event.code);
+                       return false;
+               }
+       }
+
+       if (syn == false) {
+               _E("EV_SYN didn't come until %d inputs had come", read_input_cnt);
+               return false;
+       }
+
+       if (pressure)
+               m_pressure = pressure_raw[0];
+       if (sea_level)
+               m_sea_level_pressure = pressure_raw[1];
+       if (temperature)
+               m_temperature = pressure_raw[2];
+
+       m_fired_time = fired_time;
+
+       _D("m_pressure = %d, sea_level = %d, temperature = %d, time = %lluus", m_pressure, m_sea_level_pressure, m_temperature, m_fired_time);
+
+       return true;
+}
+
+int pressure_device::read_fd(uint32_t **ids)
+{
+       if (!update_value()) {
+               DBG("Failed to update value");
+               return false;
+       }
+
+       event_ids.clear();
+       event_ids.push_back(sensor_info.id);
+
+       *ids = &event_ids[0];
+
+       return event_ids.size();
+}
+
+int pressure_device::get_data(uint32_t id, sensor_data_t **data, int *length)
+{
+       int remains = 1;
+       sensor_data_t *sensor_data;
+       sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
+       retvm_if(!sensor_data, -ENOMEM, "Memory allocation failed");
+
+       sensor_data->accuracy = SENSOR_ACCURACY_GOOD;
+       sensor_data->timestamp = m_fired_time;
+       sensor_data->value_count = 3;
+       sensor_data->values[0] = m_pressure;
+       sensor_data->values[1] = (float)m_sea_level_pressure;
+       sensor_data->values[2] = m_temperature;
+
+       raw_to_base(sensor_data);
+
+       *data = sensor_data;
+       *length = sizeof(sensor_data_t);
+
+       return --remains;
+}
+
+void pressure_device::raw_to_base(sensor_data_t *data)
+{
+       data->values[0] = data->values[0] * m_raw_data_unit;
+       m_sea_level_pressure = data->values[1] * SEA_LEVEL_RESOLUTION;
+       data->values[1] = pressure_to_altitude(data->values[0]);
+       data->values[2] = data->values[2] * m_temperature_resolution + m_temperature_offset;
+}
+
+float pressure_device::pressure_to_altitude(float pressure)
+{
+       float sea_level_pressure = m_sea_level_pressure;
+
+       if (sea_level_pressure < SEA_LEVEL_EPSILON && sea_level_pressure > -SEA_LEVEL_EPSILON)
+               sea_level_pressure = SEA_LEVEL_PRESSURE * SEA_LEVEL_RESOLUTION;
+
+       return 44330.0f * (1.0f - pow(pressure/sea_level_pressure, 1.0f/5.255f));
+}
+
diff --git a/src/pressure/pressure_device.h b/src/pressure/pressure_device.h
new file mode 100644 (file)
index 0000000..27f08bc
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _PRESSURE_DEVICE_H_
+#define _PRESSURE_DEVICE_H_
+
+#include <sensor/sensor_hal.h>
+#include <string>
+#include <vector>
+#include <functional>
+
+class pressure_device : public sensor_device {
+public:
+       pressure_device();
+       virtual ~pressure_device();
+
+       int get_poll_fd(void);
+       int get_sensors(const sensor_info_t **sensors);
+
+       bool enable(uint32_t id);
+       bool disable(uint32_t id);
+
+       bool set_interval(uint32_t id, unsigned long val);
+
+       int read_fd(uint32_t **ids);
+       int get_data(uint32_t id, sensor_data_t **data, int *length);
+
+private:
+       int m_node_handle;
+       int m_pressure;
+       int m_resolution;
+       int m_temperature;
+       float m_sea_level_pressure;
+       float m_temperature_resolution;
+       float m_temperature_offset;
+       unsigned long m_polling_interval;
+       unsigned long long m_fired_time;
+       bool m_sensorhub_controlled;
+
+       int m_method;
+       std::string m_data_node;
+       std::string m_enable_node;
+       std::string m_interval_node;
+
+       std::string m_model_id;
+       std::string m_vendor;
+       std::string m_chip_name;
+
+       float m_min_range;
+       float m_max_range;
+       float m_raw_data_unit;
+
+       std::function<bool (void)> update_value;
+
+       std::vector<uint32_t> event_ids;
+
+       bool update_value_input_event(void);
+       bool update_value_iio(void);
+
+       void raw_to_base(sensor_data_t *data);
+       float pressure_to_altitude(float pressure);
+};
+#endif /*_PRESSURE_DEVICE_H_*/
diff --git a/src/proxi/proxi_device.cpp b/src/proxi/proxi_device.cpp
new file mode 100644 (file)
index 0000000..6b46117
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/input.h>
+#include <sys/ioctl.h>
+#include <poll.h>
+
+#include <util.h>
+#include <sensor_common.h>
+#include <sensor_log.h>
+#include <sensor_config.h>
+#include "proxi_device.h"
+
+#define MODEL_NAME "UNKNOWN"
+#define VENDOR "UNKNOWN"
+#define MIN_RANGE 0
+#define MAX_RANGE 5
+#define RESOLUTION 1
+#define MIN_INTERVAL 1
+#define MAX_BATCH_COUNT 0
+
+#define SENSOR_NAME "SENSOR_PROXIMITY"
+#define SENSOR_TYPE_PROXI              "PROXI"
+
+#define INPUT_NAME     "proximity_sensor"
+#define PROXI_SENSORHUB_POLL_NODE_NAME "prox_poll_delay"
+
+#define RAW_DATA_TO_DISTANCE(x) ((x) * 5)
+
+static sensor_info_t sensor_info = {
+       id: 0x1,
+       name: SENSOR_NAME,
+       type: SENSOR_DEVICE_PROXIMITY,
+       event_type: (SENSOR_DEVICE_PROXIMITY << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
+       model_name: MODEL_NAME,
+       vendor: VENDOR,
+       min_range: MIN_RANGE,
+       max_range: MAX_RANGE,
+       resolution: RESOLUTION,
+       min_interval: MIN_INTERVAL,
+       max_batch_count: MAX_BATCH_COUNT,
+       wakeup_supported: false
+};
+
+proxi_device::proxi_device()
+: m_node_handle(-1)
+, m_state(PROXIMITY_NODE_STATE_FAR)
+, m_fired_time(0)
+, m_sensorhub_controlled(false)
+{
+       const std::string sensorhub_interval_node_name = PROXI_SENSORHUB_POLL_NODE_NAME;
+       config::sensor_config &config = config::sensor_config::get_instance();
+
+       node_info_query query;
+       node_info info;
+
+       if (!util::find_model_id(SENSOR_TYPE_PROXI, m_model_id)) {
+               _E("Failed to find model id");
+               throw ENXIO;
+
+       }
+
+       query.sensorhub_controlled = m_sensorhub_controlled = util::is_sensorhub_controlled(sensorhub_interval_node_name);
+       query.sensor_type = SENSOR_TYPE_PROXI;
+       query.key = INPUT_NAME;
+       query.iio_enable_node_name = "proximity_enable";
+       query.sensorhub_interval_node_name = sensorhub_interval_node_name;
+
+       if (!util::get_node_info(query, info)) {
+               _E("Failed to get node info");
+               throw ENXIO;
+       }
+
+       util::show_node_info(info);
+
+       m_method = info.method;
+       m_data_node = info.data_node_path;
+       m_enable_node = info.enable_node_path;
+
+       if (!config.get(SENSOR_TYPE_PROXI, m_model_id, ELEMENT_VENDOR, m_vendor)) {
+               _E("[VENDOR] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_vendor = %s", m_vendor.c_str());
+
+       if (!config.get(SENSOR_TYPE_PROXI, m_model_id, ELEMENT_NAME, m_chip_name)) {
+               _E("[NAME] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_chip_name = %s",m_chip_name.c_str());
+
+       m_node_handle = open(m_data_node.c_str(), O_RDONLY);
+
+       if (m_node_handle < 0) {
+               _ERRNO(errno, _E, "proxi handle open fail for proxi device");
+               throw ENXIO;
+       }
+
+       if (m_method == INPUT_EVENT_METHOD) {
+               if (!util::set_monotonic_clock(m_node_handle))
+                       throw ENXIO;
+
+               update_value = [=]() {
+                       return this->update_value_input_event();
+               };
+       }
+
+       _I("Proxi_sensor_hal is created!");
+}
+
+proxi_device::~proxi_device()
+{
+       close(m_node_handle);
+       m_node_handle = -1;
+
+       _I("Proxi_sensor_hal is destroyed!");
+}
+
+int proxi_device::get_poll_fd(void)
+{
+       return m_node_handle;
+}
+
+int proxi_device::get_sensors(const sensor_info_t **sensors)
+{
+       sensor_info.model_name = m_chip_name.c_str();
+       sensor_info.vendor = m_vendor.c_str();
+       *sensors = &sensor_info;
+
+       return 1;
+}
+
+bool proxi_device::enable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_PROXIMITY_ENABLE_BIT);
+
+       m_fired_time = 0;
+       INFO("Enable proxi sensor");
+       return true;
+}
+
+bool proxi_device::disable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_PROXIMITY_ENABLE_BIT);
+
+       INFO("Disable proxi sensor");
+       return true;
+}
+
+bool proxi_device::update_value_input_event(void)
+{
+       struct input_event proxi_event;
+       _I("proxi event detection!");
+
+       int len = read(m_node_handle, &proxi_event, sizeof(proxi_event));
+
+       if (len == -1) {
+               _ERRNO(errno, _E, "Failed to read from m_node_handle");
+               return false;
+       }
+
+       _D("read event,  len : %d , type : %x , code : %x , value : %x", len, proxi_event.type, proxi_event.code, proxi_event.value);
+       if ((proxi_event.type != EV_ABS) || (proxi_event.code != ABS_DISTANCE))
+               return false;
+
+       if (proxi_event.value != PROXIMITY_NODE_STATE_FAR && proxi_event.value != PROXIMITY_NODE_STATE_NEAR) {
+               _E("PROXIMITY_STATE Unknown: %d",proxi_event.value);
+               return false;
+       }
+
+       m_state = proxi_event.value;
+       m_fired_time = util::get_timestamp(&proxi_event.time);
+
+       return true;
+}
+
+int proxi_device::read_fd(uint32_t **ids)
+{
+       if (!update_value()) {
+               DBG("Failed to update value");
+               return false;
+       }
+
+       event_ids.clear();
+       event_ids.push_back(sensor_info.id);
+
+       *ids = &event_ids[0];
+
+       return event_ids.size();
+}
+
+int proxi_device::get_data(uint32_t id, sensor_data_t **data, int *length)
+{
+       int remains = 1;
+       sensor_data_t *sensor_data;
+       sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
+       retvm_if(!sensor_data, -ENOMEM, "Memory allocation failed");
+
+       sensor_data->accuracy = SENSOR_ACCURACY_GOOD;
+       sensor_data->timestamp = m_fired_time;
+       sensor_data->value_count = 1;
+       sensor_data->values[0] = RAW_DATA_TO_DISTANCE(m_state);
+
+       *data = sensor_data;
+       *length = sizeof(sensor_data_t);
+
+       return --remains;
+}
diff --git a/src/proxi/proxi_device.h b/src/proxi/proxi_device.h
new file mode 100644 (file)
index 0000000..93f9e9a
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _PROXI_DEVICE_H_
+#define _PROXI_DEVICE_H_
+
+#include <sensor/sensor_hal.h>
+#include <string>
+#include <vector>
+#include <functional>
+
+class proxi_device : public sensor_device {
+public:
+       enum proxi_node_state_event_t {
+               PROXIMITY_NODE_STATE_NEAR = 0,
+               PROXIMITY_NODE_STATE_FAR = 1,
+               PROXIMITY_NODE_STATE_UNKNOWN = 2,
+       };
+
+       proxi_device();
+       virtual ~proxi_device();
+
+       int get_poll_fd(void);
+       int get_sensors(const sensor_info_t **sensors);
+
+       bool enable(uint32_t id);
+       bool disable(uint32_t id);
+
+       int read_fd(uint32_t **ids);
+       int get_data(uint32_t id, sensor_data_t **data, int *length);
+
+private:
+       int m_node_handle;
+       unsigned int m_state;
+       unsigned long long m_fired_time;
+       bool m_sensorhub_controlled;
+
+       int m_method;
+       std::string m_data_node;
+       std::string m_enable_node;
+
+       std::string m_model_id;
+       std::string m_vendor;
+       std::string m_chip_name;
+
+       std::function<bool (void)> update_value;
+
+       std::vector<uint32_t> event_ids;
+
+       bool update_value_input_event(void);
+};
+
+#endif /* _PROXI_DEVICE_H_ */
diff --git a/src/sensor_common.h b/src/sensor_common.h
new file mode 100644 (file)
index 0000000..b549c96
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _SENSOR_COMMON_H_
+#define _SENSOR_COMMON_H_
+
+#define SENSOR_EVENT_SHIFT 16
+#define RAW_DATA_EVENT 0x0001
+
+#define UNKNOWN_NAME "UNKNOWN"
+
+enum sensorhub_enable_bit {
+       SENSORHUB_ACCELEROMETER_ENABLE_BIT = 0,
+       SENSORHUB_GYROSCOPE_ENABLE_BIT,
+       SENSORHUB_GEOMAGNETIC_UNCALIB_ENABLE_BIT,
+       SENSORHUB_GEOMAGNETIC_RAW_ENABLE_BIT,
+       SENSORHUB_GEOMAGNETIC_ENABLE_BIT,
+       SENSORHUB_PRESSURE_ENABLE_BIT,
+       SENSORHUB_GESTURE_ENABLE_BIT,
+       SENSORHUB_PROXIMITY_ENABLE_BIT,
+       SENSORHUB_TEMPERATURE_HUMIDITY_ENABLE_BIT,
+       SENSORHUB_LIGHT_ENABLE_BIT,
+       SENSORHUB_PROXIMITY_RAW_ENABLE_BIT,
+       SENSORHUB_ORIENTATION_ENABLE_BIT,
+       SENSORHUB_STEP_DETECTOR_ENABLE_BIT = 12,
+       SENSORHUB_SIG_MOTION_ENABLE_BIT,
+       SENSORHUB_GYRO_UNCALIB_ENABLE_BIT,
+       SENSORHUB_GAME_ROTATION_VECTOR_ENABLE_BIT = 15,
+       SENSORHUB_ROTATION_VECTOR_ENABLE_BIT,
+       SENSORHUB_STEP_COUNTER_ENABLE_BIT,
+       SENSORHUB_HRM_RAW_ENABLE_BIT,
+       SENSORHUB_HRM_RAW_FAC_ENABLE_BIT,
+       SENSORHUB_HRM_LIB_ENABLE_BIT,
+       SENSORHUB_TILT_MOTION,
+       SENSORHUB_UV_SENSOR,
+       SENSORHUB_PIR_ENABLE_BIT,
+       SENSORHUB_PIR_RAW_ENABLE_BIT,
+       SENSORHUB_GSR_ENABLE_BIT = 25,
+       SENSORHUB_ENABLE_BIT_MAX,
+};
+
+#endif /* _SENSOR_COMMON_H_ */
diff --git a/src/sensor_config.cpp b/src/sensor_config.cpp
new file mode 100644 (file)
index 0000000..d8b7c28
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <sensor_config.h>
+#include <sensor_log.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <sstream>
+#include <iostream>
+#include <fstream>
+#include <string>
+
+using namespace config;
+using std::ifstream;
+using std::string;
+using std::istringstream;
+
+#define ROOT_ELEMENT   "SENSOR"
+#define TEXT_ELEMENT   "text"
+#define MODEL_ID_ATTR  "id"
+#define DEFAULT_ATTR   "value"
+
+sensor_config::sensor_config()
+{
+}
+
+sensor_config& sensor_config::get_instance(void)
+{
+       static bool load_done = false;
+       static sensor_config inst;
+
+       if (load_done)
+               return inst;
+
+       inst.load_config();
+       inst.get_device_id();
+       if (!inst.m_device_id.empty())
+               _I("Device ID = %s", inst.m_device_id.c_str());
+       else
+               _E("Failed to get Device ID");
+       load_done = true;
+
+       return inst;
+}
+
+bool sensor_config::load_config(const string& config_path)
+{
+       xmlDocPtr doc;
+       xmlNodePtr cur;
+
+       _D("sensor_config::load_config(\"%s\") is called!\n",config_path.c_str());
+
+       doc = xmlParseFile(config_path.c_str());
+
+       if (doc == NULL) {
+               _E("There is no %s\n",config_path.c_str());
+               return false;
+       }
+
+       cur = xmlDocGetRootElement(doc);
+       if(cur == NULL) {
+               _E("There is no root element in %s\n",config_path.c_str());
+               xmlFreeDoc(doc);
+               return false;
+       }
+
+       if(xmlStrcmp(cur->name, (const xmlChar *)ROOT_ELEMENT)) {
+               _E("Wrong type document: there is no [%s] root element in %s\n",ROOT_ELEMENT,config_path.c_str());
+               xmlFreeDoc(doc);
+               return false;
+       }
+
+       xmlNodePtr model_list_node_ptr;
+       xmlNodePtr model_node_ptr;
+       xmlNodePtr element_node_ptr;
+       xmlAttrPtr attr_ptr;
+       char* prop = NULL;
+
+       model_list_node_ptr = cur->xmlChildrenNode;
+
+       while (model_list_node_ptr != NULL) {
+               //skip garbage element, [text]
+               if (!xmlStrcmp(model_list_node_ptr->name,(const xmlChar *)TEXT_ELEMENT)) {
+                       model_list_node_ptr = model_list_node_ptr->next;
+                       continue;
+               }
+
+               //insert Model_list to config map
+               m_sensor_config[(const char*)model_list_node_ptr->name];
+               _D("<%s>\n",(const char*)model_list_node_ptr->name);
+
+               model_node_ptr = model_list_node_ptr->xmlChildrenNode;
+               while (model_node_ptr != NULL){
+                       //skip garbage element, [text]
+                       if (!xmlStrcmp(model_node_ptr->name,(const xmlChar *)TEXT_ELEMENT)) {
+                               model_node_ptr = model_node_ptr->next;
+                               continue;
+                       }
+
+
+                       string model_id;
+                       prop = (char*)xmlGetProp(model_node_ptr,(const xmlChar*)MODEL_ID_ATTR);
+                       model_id = prop;
+                       free(prop);
+
+                       //insert Model to Model_list
+                       m_sensor_config[(const char*)model_list_node_ptr->name][model_id];
+                       _D("<%s id=\"%s\">\n",(const char*)model_list_node_ptr->name,model_id.c_str());
+
+                       element_node_ptr = model_node_ptr->xmlChildrenNode;
+                       while (element_node_ptr != NULL) {
+                               //skip garbage element, [text]
+                               if (!xmlStrcmp(element_node_ptr->name,(const xmlChar *)TEXT_ELEMENT)) {
+                                       element_node_ptr = element_node_ptr->next;
+                                       continue;
+                               }
+
+                               //insert Element to Model
+                               m_sensor_config[(const char*)model_list_node_ptr->name][model_id][(const char*)element_node_ptr->name];
+                               _D("<%s id=\"%s\"><%s>\n",(const char*)model_list_node_ptr->name,model_id.c_str(),(const char*)element_node_ptr->name);
+
+                               attr_ptr = element_node_ptr->properties;
+                               while (attr_ptr != NULL) {
+
+                                       string key,value;
+                                       key = (const char*)attr_ptr->name;
+                                       prop = (char*)xmlGetProp(element_node_ptr,attr_ptr->name);
+                                       value = prop;
+                                       free(prop);
+
+                                       //insert attribute to Element
+                                       m_sensor_config[(const char*)model_list_node_ptr->name][model_id][(const char*)element_node_ptr->name][key]=value;
+                                       _D("<%s id=\"%s\"><%s \"%s\"=\"%s\">\n",(const char*)model_list_node_ptr->name,model_id.c_str(),(const char*)element_node_ptr->name,key.c_str(),value.c_str());
+                                       attr_ptr = attr_ptr->next;
+                               }
+
+
+                               element_node_ptr = element_node_ptr->next;
+                       }
+
+                       _D("\n");
+                       model_node_ptr = model_node_ptr->next;
+               }
+
+               _D("\n");
+               model_list_node_ptr = model_list_node_ptr->next;
+       }
+
+       xmlFreeDoc(doc);
+       return true;
+}
+
+
+bool sensor_config::get(const string& sensor_type,const string& model_id, const string& element, const string& attr, string& value)
+{
+       auto it_model_list = m_sensor_config.find(sensor_type);
+
+       if (it_model_list == m_sensor_config.end())     {
+               _E("There is no <%s> element\n",sensor_type.c_str());
+               return false;
+       }
+
+       auto it_model = it_model_list->second.find(model_id);
+
+       if (it_model == it_model_list->second.end()) {
+               _E("There is no <%s id=\"%s\"> element\n",sensor_type.c_str(),model_id.c_str());
+               return false;
+       }
+
+       auto it_element = it_model->second.find(element);
+
+       if (it_element == it_model->second.end()) {
+               _D("There is no <%s id=\"%s\"><%s> element\n",sensor_type.c_str(),model_id.c_str(),element.c_str());
+               return false;
+       }
+
+       auto it_attr = it_element->second.find(attr);
+
+       if (it_attr == it_element->second.end()) {
+               _D("There is no <%s id=\"%s\"><%s \"%s\">\n",sensor_type.c_str(),model_id.c_str(),element.c_str(),attr.c_str());
+               return false;
+       }
+
+       value = it_attr->second;
+
+       return true;
+}
+
+bool sensor_config::get(const string& sensor_type, const string& model_id, const string& element, const string& attr, double& value)
+{
+       string str_value;
+
+       if (get(sensor_type,model_id,element,attr,str_value) == false)
+               return false;
+
+       istringstream convert(str_value);
+
+       if ( !(convert >> value))
+               value = 0;
+
+       return true;
+}
+
+bool sensor_config::get(const string& sensor_type, const string& model_id, const string& element, const string& attr, long& value)
+{
+       string str_value;
+
+       if (get(sensor_type,model_id,element,attr,str_value) == false)
+               return false;
+
+       istringstream convert(str_value);
+
+       if ( !(convert >> value))
+               value = 0;
+
+       return true;
+}
+
+bool sensor_config::get(const string& sensor_type, const string& model_id, const string& element, string& value)
+{
+       if (get(sensor_type, model_id, element, m_device_id, value))
+               return true;
+
+       if (get(sensor_type, model_id, element, DEFAULT_ATTR, value))
+               return true;
+
+       return false;
+}
+
+bool sensor_config::get(const string& sensor_type, const string& model_id, const string& element, double& value)
+{
+       if (get(sensor_type, model_id, element, m_device_id, value))
+               return true;
+
+       if (get(sensor_type, model_id, element, DEFAULT_ATTR, value))
+               return true;
+
+       return false;
+}
+
+bool sensor_config::get(const string& sensor_type, const string& model_id, const string& element, long& value)
+{
+       if (get(sensor_type, model_id, element, m_device_id, value))
+               return true;
+
+       if (get(sensor_type, model_id, element, DEFAULT_ATTR, value))
+               return true;
+
+       return false;
+}
+
+bool sensor_config::is_supported(const string& sensor_type,const string& model_id)
+{
+       auto it_model_list = m_sensor_config.find(sensor_type);
+
+       if (it_model_list == m_sensor_config.end())
+               return false;
+
+       auto it_model = it_model_list->second.find(model_id);
+
+       if (it_model == it_model_list->second.end())
+               return false;
+
+       return true;
+}
+
+bool sensor_config::get_device_id(void)
+{
+       const string INFO_INI_PATH = "/etc/info.ini";
+       const string START_DELIMETER = "Model=";
+       const string END_DELIMETER = ";";
+       string line;
+       ifstream in_file;
+       std::size_t start_pos, end_pos;
+       bool ret = false;
+
+       in_file.open(INFO_INI_PATH);
+
+       if (!in_file.is_open())
+               return false;
+
+       while (!in_file.eof()) {
+               getline(in_file, line);
+               start_pos = line.find(START_DELIMETER);
+
+               if (start_pos == std::string::npos)
+                       continue;
+
+               start_pos = start_pos + START_DELIMETER.size();
+               end_pos = line.find(END_DELIMETER, start_pos);
+
+               if (end_pos == std::string::npos)
+                       continue;
+
+               m_device_id = line.substr(start_pos, end_pos - start_pos);
+               ret = true;
+               break;
+       }
+
+       in_file.close();
+
+       return ret;
+}
diff --git a/src/sensor_config.h b/src/sensor_config.h
new file mode 100644 (file)
index 0000000..eadc8b9
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _SENSOR_CONFIG_H_
+#define _SENSOR_CONFIG_H_
+
+#include <string>
+#include <unordered_map>
+#include <sensor_log.h>
+
+#define CONFIG_FILE_PATH "/usr/etc/sensor.xml"
+
+#define ELEMENT_NAME                   "NAME"
+#define ELEMENT_VENDOR                 "VENDOR"
+#define ELEMENT_RAW_DATA_UNIT  "RAW_DATA_UNIT"
+#define ELEMENT_RESOLUTION             "RESOLUTION"
+#define ATTR_VALUE                             "value"
+#define ELEMENT_MIN_RANGE              "MIN_RANGE"
+#define ELEMENT_MAX_RANGE              "MAX_RANGE"
+
+typedef std::unordered_map<std::string,std::string> Element;
+/*
+* an Element  is a group of attributes
+* <Element value1 = "10.0", value2 =  "20.0"/>
+*
+* "value" -> "LSM330DLC"
+*
+*/
+
+typedef std::unordered_map<std::string,Element> Model;
+/*
+* a Model is a group of elements to consist of  specific vendor's one sensor configuration
+* <NAME value = "LSM330DLC" />
+* <VENDOR value = "ST Microelectronics"/>
+* <RAW_DATA_UNIT value = "1" />
+* <RESOLUTION value = "12" />
+*
+* <NAME> -> <value = "LSM330DLC"/>
+*
+*/
+
+typedef std::unordered_map<std::string,Model> Model_list;
+/*
+* a Model_list is  a group of Model
+* <MODEL id = "lsm330dlc_accel">
+* </MODEL>
+* <MODEL id = "mpu6500">
+* </MODEL>
+*
+* "lsm330dlc_accel" -> <Model>
+*
+*/
+
+typedef std::unordered_map<std::string,Model_list> Sensor_config;
+/*
+* a SensorConfig represents sensors.xml
+* <ACCEL/>
+* <GYRO/>
+* <PROXIMITY/>
+*
+* "ACCEL" -> Model_list
+*
+*/
+
+namespace config {
+       class sensor_config {
+       private:
+               sensor_config();
+               sensor_config(sensor_config const&) {};
+               sensor_config& operator=(sensor_config const&);
+               bool load_config(const std::string& config_path = CONFIG_FILE_PATH);
+               Sensor_config m_sensor_config;
+               std::string m_device_id;
+       public:
+               static sensor_config& get_instance(void);
+
+               bool get(const std::string& sensor_type, const std::string& model_id, const std::string& element, const std::string& attr, std::string& value);
+               bool get(const std::string& sensor_type, const std::string& model_id, const std::string& element, const std::string& attr, double& value);
+               bool get(const std::string& sensor_type, const std::string& model_id, const std::string& element, const std::string& attr, long& value);
+
+               bool get(const std::string& sensor_type, const std::string& model_id, const std::string& element, std::string& value);
+               bool get(const std::string& sensor_type, const std::string& model_id, const std::string& element, double& value);
+               bool get(const std::string& sensor_type, const std::string& model_id, const std::string& element, long& value);
+
+               bool is_supported(const std::string &sensor_type, const std::string &model_id);
+               bool get_device_id(void);
+       };
+}
+#endif /* _SENSOR_CONFIG_H_ */
diff --git a/src/sensor_log.h b/src/sensor_log.h
new file mode 100644 (file)
index 0000000..8e593e2
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _SENSOR_LOG_H_
+#define _SENSOR_LOG_H_
+
+#include <dlog.h>
+
+#ifndef NAME_MAX
+#define NAME_MAX 256
+#endif
+
+#ifdef LOG_TAG
+       #undef LOG_TAG
+#endif
+#define LOG_TAG        "SENSOR"
+
+#define LOG_DUMP(fp, fmt, arg...) do { if (fp) fprintf(fp, fmt, ##arg); else _E(fmt, ##arg); } while(0)
+
+#ifdef _DEBUG
+#define DBG SLOGD
+#else
+#define DBG(...) do{} while(0)
+#endif
+
+#define ERR SLOGE
+#define WARN SLOGW
+#define INFO SLOGI
+#define _E ERR
+#define _W WARN
+#define _I INFO
+#define _D DBG
+
+#define _ERRNO(errno, tag, fmt, arg...) do { \
+               char buf[1024]; \
+               char *error = strerror_r(errno, buf, 1024); \
+               if (!error) { \
+                       _E("Failed to strerror_r()"); \
+                       break; \
+               } \
+               tag(fmt" (%s[%d])", ##arg, error, errno); \
+       } while (0)
+
+#ifdef _DEBUG
+#define warn_if(expr, fmt, arg...) do { \
+               if(expr) { \
+                       _D("(%s) -> " fmt, #expr, ##arg); \
+               } \
+       } while (0)
+#define ret_if(expr) do { \
+               if(expr) { \
+                       _D("(%s) -> %s() return", #expr, __FUNCTION__); \
+                       return; \
+               } \
+       } while (0)
+#define retv_if(expr, val) do { \
+               if(expr) { \
+                       _D("(%s) -> %s() return", #expr, __FUNCTION__); \
+                       return (val); \
+               } \
+       } while (0)
+#define retm_if(expr, fmt, arg...) do { \
+               if(expr) { \
+                       _E(fmt, ##arg); \
+                       _D("(%s) -> %s() return", #expr, __FUNCTION__); \
+                       return; \
+               } \
+       } while (0)
+#define retvm_if(expr, val, fmt, arg...) do { \
+               if(expr) { \
+                       _E(fmt, ##arg); \
+                       _D("(%s) -> %s() return", #expr, __FUNCTION__); \
+                       return (val); \
+               } \
+       } while (0)
+
+#else
+#define warn_if(expr, fmt, arg...) do { \
+               if(expr) { \
+                       _E(fmt, ##arg); \
+               } \
+       } while (0)
+#define ret_if(expr) do { \
+               if(expr) { \
+                       return; \
+               } \
+       } while (0)
+#define retv_if(expr, val) do { \
+               if(expr) { \
+                       return (val); \
+               } \
+       } while (0)
+#define retm_if(expr, fmt, arg...) do { \
+               if(expr) { \
+                       _E(fmt, ##arg); \
+                       return; \
+               } \
+       } while (0)
+#define retvm_if(expr, val, fmt, arg...) do { \
+               if(expr) { \
+                       _E(fmt, ##arg); \
+                       return (val); \
+               } \
+       } while (0)
+
+#endif
+
+#endif /* _SENSOR_LOG_H_ */
diff --git a/src/ultraviolet/uv_device.cpp b/src/ultraviolet/uv_device.cpp
new file mode 100644 (file)
index 0000000..eec4f78
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/input.h>
+#include <sys/ioctl.h>
+#include <poll.h>
+
+#include <util.h>
+#include <sensor_common.h>
+#include <sensor_log.h>
+#include <sensor_config.h>
+#include "uv_device.h"
+
+#define UNKNOWN_NAME "UNKNOWN"
+#define SENSOR_NAME "ULTRAVIOLET_SENSOR"
+
+#define SENSOR_TYPE_ULTRAVIOLET                "ULTRAVIOLET"
+#define UV_SENSORHUB_POLL_NODE_NAME "uv_poll_dealy"
+#define INPUT_NAME "uv_sensor"
+#define IIO_ENABLE_NAME "uv_enable"
+
+#define BIAS   1
+
+static sensor_info_t sensor_info = {
+       id: 0x1,
+       name: SENSOR_NAME,
+       type: SENSOR_DEVICE_ULTRAVIOLET,
+       event_type: (SENSOR_DEVICE_ULTRAVIOLET << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
+       model_name: UNKNOWN_NAME,
+       vendor: UNKNOWN_NAME,
+       min_range: 0,
+       max_range: 0,
+       resolution: 0,
+       min_interval: 0,
+       max_batch_count: 0,
+       wakeup_supported: false
+};
+
+std::vector<uint32_t> uv_device::event_ids;
+
+uv_device::uv_device()
+: m_node_handle(-1)
+, m_ultraviolet(0)
+, m_polling_interval(1000)
+, m_fired_time(0)
+, m_raw_data_unit(0)
+, m_min_range(0)
+, m_max_range(0)
+, m_sensorhub_controlled(false)
+{
+       const std::string sensorhub_interval_node_name = UV_SENSORHUB_POLL_NODE_NAME;
+       config::sensor_config &config = config::sensor_config::get_instance();
+
+       node_info_query query;
+       node_info info;
+
+       if (!util::find_model_id(SENSOR_TYPE_ULTRAVIOLET, m_model_id)) {
+               _E("Failed to find model id");
+               throw ENXIO;
+       }
+
+       query.sensorhub_controlled = m_sensorhub_controlled = util::is_sensorhub_controlled(sensorhub_interval_node_name);
+       query.sensor_type = SENSOR_TYPE_ULTRAVIOLET;
+       query.key = INPUT_NAME;
+       query.iio_enable_node_name = IIO_ENABLE_NAME;
+       query.sensorhub_interval_node_name = sensorhub_interval_node_name;
+
+       if (!util::get_node_info(query, info)) {
+               _E("Failed to get node info");
+               throw ENXIO;
+       }
+
+       util::show_node_info(info);
+
+       m_method = info.method;
+       m_data_node = info.data_node_path;
+       m_enable_node = info.enable_node_path;
+       m_interval_node = info.interval_node_path;
+
+       if (!config.get(SENSOR_TYPE_ULTRAVIOLET, m_model_id, ELEMENT_VENDOR, m_vendor)) {
+               _E("[VENDOR] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_vendor = %s", m_vendor.c_str());
+
+       if (!config.get(SENSOR_TYPE_ULTRAVIOLET, m_model_id, ELEMENT_NAME, m_chip_name)) {
+               _E("[NAME] is empty");
+               throw ENXIO;
+       }
+
+       _I("m_chip_name = %s",m_chip_name.c_str());
+
+       double min_range;
+
+       if (!config.get(SENSOR_TYPE_ULTRAVIOLET, m_model_id, ELEMENT_MIN_RANGE, min_range)) {
+               ERR("[MIN_RANGE] is empty\n");
+               throw ENXIO;
+       }
+
+       m_min_range = (float)min_range;
+       INFO("m_min_range = %f\n",m_min_range);
+
+       double max_range;
+
+       if (!config.get(SENSOR_TYPE_ULTRAVIOLET, m_model_id, ELEMENT_MAX_RANGE, max_range)) {
+               ERR("[MAX_RANGE] is empty\n");
+               throw ENXIO;
+       }
+
+       m_max_range = (float)max_range;
+       INFO("m_max_range = %f\n",m_max_range);
+
+       double raw_data_unit;
+
+       if (!config.get(SENSOR_TYPE_ULTRAVIOLET, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) {
+               _E("[RAW_DATA_UNIT] is empty");
+               throw ENXIO;
+       }
+
+       m_raw_data_unit = (float)(raw_data_unit);
+       _I("m_raw_data_unit = %f", m_raw_data_unit);
+
+       m_node_handle = open(m_data_node.c_str(), O_RDONLY);
+
+       if (m_node_handle < 0) {
+               _ERRNO(errno, _E, "uv handle open fail for uv processor");
+               throw ENXIO;
+       }
+
+       if (m_method == INPUT_EVENT_METHOD) {
+               if (!util::set_monotonic_clock(m_node_handle))
+                       throw ENXIO;
+       }
+
+       update_value = [=]() {
+               return this->update_value_input_event();
+       };
+
+       _I("uv_sensor is created!");
+}
+
+uv_device::~uv_device()
+{
+       close(m_node_handle);
+       m_node_handle = -1;
+
+       _I("uv_sensor is destroyed!");
+}
+
+int uv_device::get_poll_fd()
+{
+       return m_node_handle;
+}
+
+int uv_device::get_sensors(const sensor_info_t **sensors)
+{
+       sensor_info.model_name = m_chip_name.c_str();
+       sensor_info.vendor = m_vendor.c_str();
+       sensor_info.min_range = m_min_range;
+       sensor_info.max_range = m_max_range;
+       sensor_info.resolution = m_raw_data_unit;
+       sensor_info.min_interval = 1;
+       sensor_info.max_batch_count = 0;
+       *sensors = &sensor_info;
+
+       return 1;
+}
+
+bool uv_device::enable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_UV_SENSOR);
+       set_interval(id, m_polling_interval);
+
+       m_fired_time = 0;
+       _I("Enable uverometer sensor");
+       return true;
+}
+
+bool uv_device::disable(uint32_t id)
+{
+       util::set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_UV_SENSOR);
+
+       _I("Disable uverometer sensor");
+       return true;
+}
+
+bool uv_device::set_interval(uint32_t id, unsigned long val)
+{
+       unsigned long long polling_interval_ns;
+
+       polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
+
+       if (!util::set_node_value(m_interval_node, polling_interval_ns)) {
+               _E("Failed to set polling resource: %s", m_interval_node.c_str());
+               return false;
+       }
+
+       _I("Interval is changed from %dms to %dms", m_polling_interval, val);
+       m_polling_interval = val;
+       return true;
+}
+
+bool uv_device::update_value_input_event(void)
+{
+       int ultraviolet_raw = -1;
+       bool ultraviolet = false;
+       int read_input_cnt = 0;
+       const int INPUT_MAX_BEFORE_SYN = 10;
+       unsigned long long fired_time = 0;
+       bool syn = false;
+
+       struct input_event ultraviolet_event;
+       _D("ultraviolet event detection!");
+
+       while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
+               int len = read(m_node_handle, &ultraviolet_event, sizeof(ultraviolet_event));
+               if (len != sizeof(ultraviolet_event)) {
+                       _E("ultraviolet file read fail, read_len = %d\n",len);
+                       return false;
+               }
+
+               ++read_input_cnt;
+
+               if (ultraviolet_event.type == EV_REL && ultraviolet_event.code == REL_MISC) {
+                       ultraviolet_raw = (int)ultraviolet_event.value - BIAS;
+                       ultraviolet = true;
+               } else if (ultraviolet_event.type == EV_SYN) {
+                       syn = true;
+                       fired_time = util::get_timestamp(&ultraviolet_event.time);
+               } else {
+                       _E("ultraviolet event[type = %d, code = %d] is unknown.", ultraviolet_event.type, ultraviolet_event.code);
+                       return false;
+               }
+       }
+
+       if (ultraviolet)
+               m_ultraviolet = ultraviolet_raw;
+
+       m_fired_time = fired_time;
+
+       _D("m_ultraviolet = %d, time = %lluus", m_ultraviolet, m_fired_time);
+
+       return true;
+}
+
+int uv_device::read_fd(uint32_t **ids)
+{
+       if (!update_value()) {
+               _D("Failed to update value");
+               return false;
+       }
+
+       event_ids.clear();
+       event_ids.push_back(sensor_info.id);
+
+       *ids = &event_ids[0];
+
+       return event_ids.size();
+}
+
+int uv_device::get_data(uint32_t id, sensor_data_t **data, int *length)
+{
+       int remains = 1;
+       sensor_data_t *sensor_data;
+       sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
+       retvm_if(!sensor_data, -ENOMEM, "Memory allocation failed");
+
+       sensor_data->accuracy = SENSOR_ACCURACY_GOOD;
+       sensor_data->timestamp = m_fired_time;
+       sensor_data->value_count = 1;
+       sensor_data->values[0] = m_ultraviolet;
+
+       raw_to_base(sensor_data);
+
+       *data = sensor_data;
+       *length = sizeof(sensor_data_t);
+
+       return --remains;
+}
+
+void uv_device::raw_to_base(sensor_data_t *data)
+{
+       data->values[0] = data->values[0] * m_raw_data_unit;
+}
diff --git a/src/ultraviolet/uv_device.h b/src/ultraviolet/uv_device.h
new file mode 100644 (file)
index 0000000..31106d5
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _UV_DEVICE_H_
+#define _UV_DEVICE_H_
+
+#include <sensor/sensor_hal.h>
+#include <string>
+#include <vector>
+#include <functional>
+
+class uv_device : public sensor_device {
+public:
+       uv_device();
+       virtual ~uv_device();
+
+       int get_poll_fd(void);
+       int get_sensors(const sensor_info_t **sensors);
+
+       bool enable(uint32_t id);
+       bool disable(uint32_t id);
+
+       bool set_interval(uint32_t id, unsigned long val);
+
+       int read_fd(uint32_t **ids);
+       int get_data(uint32_t id, sensor_data_t **data, int *length);
+
+private:
+       int m_node_handle;
+       int m_ultraviolet;
+       unsigned long m_polling_interval;
+       unsigned long long m_fired_time;
+       float m_raw_data_unit;
+       float m_min_range;
+       float m_max_range;
+       bool m_sensorhub_controlled;
+
+       int m_method;
+       std::string m_data_node;
+       std::string m_enable_node;
+       std::string m_interval_node;
+
+       std::string m_model_id;
+       std::string m_vendor;
+       std::string m_chip_name;
+
+       std::function<bool (void)> update_value;
+
+       static std::vector<uint32_t> event_ids;
+
+       bool update_value_input_event(void);
+
+       void raw_to_base(sensor_data_t *data);
+};
+#endif /* _UV_DEVICE_H_ */
diff --git a/src/util.cpp b/src/util.cpp
new file mode 100644 (file)
index 0000000..8b95cdb
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <unistd.h>
+#include <dirent.h>
+#include <string.h>
+#include <fstream>
+#include <util.h>
+#include <sensor_log.h>
+#include <sensor_config.h>
+
+using std::ifstream;
+using std::ofstream;
+using std::fstream;
+using std::string;
+
+#define PREFIX_EVENT "event"
+
+static bool get_event_num(const string &input_path, string &event_num)
+{
+       const string event_prefix = PREFIX_EVENT;
+       DIR *dir = NULL;
+       struct dirent dir_entry;
+       struct dirent *result = NULL;
+       std::string node_name;
+       int error;
+       bool find = false;
+
+       dir = opendir(input_path.c_str());
+       if (!dir) {
+               ERR("Failed to open dir: %s", input_path.c_str());
+               return false;
+       }
+
+       int prefix_size = event_prefix.size();
+
+       while (true) {
+               error = readdir_r(dir, &dir_entry, &result);
+
+               if (error != 0)
+                       continue;
+
+               if (result == NULL)
+                       break;
+
+               node_name = std::string(dir_entry.d_name);
+
+               if (node_name.compare(0, prefix_size, event_prefix) != 0)
+                       continue;
+
+               event_num = node_name.substr(prefix_size, node_name.size() - prefix_size);
+               find = true;
+               break;
+       }
+
+       closedir(dir);
+
+       return find;
+}
+
+static bool get_iio_node_info(const string& enable_node_name, const string& device_num, node_info &info)
+{
+       const string base_dir = string("/sys/bus/iio/devices/iio:device") + device_num + string("/");
+
+       info.data_node_path = string("/dev/iio:device") + device_num;
+       info.enable_node_path = base_dir + enable_node_name;
+       info.interval_node_path = base_dir + string("sampling_frequency");
+       info.buffer_enable_node_path = base_dir + string("buffer/enable");
+       info.buffer_length_node_path = base_dir + string("buffer/length");
+       info.trigger_node_path = base_dir + string("trigger/current_trigger");
+
+       return true;
+}
+
+static bool get_sensorhub_iio_node_info(const string &interval_node_name, const string& device_num, node_info &info)
+{
+       const string base_dir = string("/sys/bus/iio/devices/iio:device") + device_num + string("/");
+       const string hub_dir = "/sys/class/sensors/ssp_sensor/";
+
+       info.data_node_path = string("/dev/iio:device") + device_num;
+       info.enable_node_path = hub_dir + string("enable");
+       info.interval_node_path = hub_dir + interval_node_name;
+       info.buffer_enable_node_path = base_dir + string("buffer/enable");
+       info.buffer_length_node_path = base_dir + string("buffer/length");
+       return true;
+}
+
+static bool get_input_event_node_info(const string& device_num, node_info &info)
+{
+       string base_dir;
+       string event_num;
+
+       base_dir = string("/sys/class/input/input") + device_num + string("/");
+
+       if (!get_event_num(base_dir, event_num))
+               return false;
+
+       info.data_node_path = string("/dev/input/event") + event_num;
+
+       info.enable_node_path = base_dir + string("enable");
+       info.interval_node_path = base_dir + string("poll_delay");
+       return true;
+}
+
+static bool get_sensorhub_input_event_node_info(const string &interval_node_name, const string& device_num, node_info &info)
+{
+       const string base_dir = "/sys/class/sensors/ssp_sensor/";
+       string event_num;
+
+       string input_dir = string("/sys/class/input/input") + device_num + string("/");
+
+       if (!get_event_num(input_dir, event_num))
+               return false;
+
+       info.data_node_path = string("/dev/input/event") + event_num;
+       info.enable_node_path = base_dir + string("enable");
+       info.interval_node_path = base_dir + interval_node_name;
+       return true;
+}
+
+static bool get_node_value(const string &node_path, int &value)
+{
+       ifstream node(node_path, ifstream::binary);
+
+       if (!node)
+               return false;
+
+       node >> value;
+
+       return true;
+}
+
+static bool get_input_method(const string &key, int &method, string &device_num)
+{
+       input_method_info input_info[2] = {
+               {INPUT_EVENT_METHOD, "/sys/class/input/", "input"},
+               {IIO_METHOD, "/sys/bus/iio/devices/", "iio:device"}
+       };
+
+       const int input_info_len = sizeof(input_info)/sizeof(input_info[0]);
+       size_t prefix_size;
+       std::string name_node, name;
+       std::string d_name;
+       DIR *dir = NULL;
+       struct dirent dir_entry;
+       struct dirent *result = NULL;
+       int error;
+       bool find = false;
+
+       for (int i = 0; i < input_info_len; ++i) {
+
+               prefix_size = input_info[i].prefix.size();
+
+               dir = opendir(input_info[i].dir_path.c_str());
+               if (!dir) {
+                       ERR("Failed to open dir: %s", input_info[i].dir_path.c_str());
+                       return false;
+               }
+
+               find = false;
+
+               while (true) {
+                       error = readdir_r(dir, &dir_entry, &result);
+
+                       if (error != 0)
+                               continue;
+
+                       if (result == NULL)
+                               break;
+
+                       d_name = std::string(dir_entry.d_name);
+
+                       if (d_name.compare(0, prefix_size, input_info[i].prefix) != 0)
+                               continue;
+
+                       name_node = input_info[i].dir_path + d_name + string("/name");
+
+                       ifstream infile(name_node.c_str());
+                       if (!infile)
+                               continue;
+
+                       infile >> name;
+
+                       if (name != key)
+                               continue;
+
+                       device_num = d_name.substr(prefix_size, d_name.size() - prefix_size);
+                       find = true;
+                       method = input_info[i].method;
+                       break;
+               }
+
+               closedir(dir);
+
+               if (find)
+                       break;
+       }
+
+       return find;
+}
+
+bool util::set_monotonic_clock(int fd)
+{
+#ifdef EVIOCSCLOCKID
+       int clockId = CLOCK_MONOTONIC;
+       if (ioctl(fd, EVIOCSCLOCKID, &clockId) != 0) {
+               _E("Fail to set monotonic timestamp for fd[%d]", fd);
+               return false;
+       }
+#endif
+       return true;
+}
+
+bool util::find_model_id(const string &sensor_type, string &model_id)
+{
+       std::string dir_path = "/sys/class/sensors/";
+       std::string name_node, name;
+       std::string d_name;
+       DIR *dir = NULL;
+       struct dirent dir_entry;
+       struct dirent *result = NULL;
+       int error;
+       bool find = false;
+
+       dir = opendir(dir_path.c_str());
+       if (!dir) {
+               _D("Failed to open dir: %s", dir_path.c_str());
+               return false;
+       }
+
+       while (true) {
+               error = readdir_r(dir, &dir_entry, &result);
+
+               if (error != 0)
+                       continue;
+
+               if (result == NULL)
+                       break;
+
+               d_name = std::string(dir_entry.d_name);
+
+               if ((d_name == ".") || (d_name == "..") || (dir_entry.d_ino == 0))
+                       continue;
+
+               name_node = dir_path + d_name + string("/name");
+
+               ifstream infile(name_node.c_str());
+
+               if (!infile)
+                       continue;
+
+               infile >> name;
+
+               if (!config::sensor_config::get_instance().is_supported(sensor_type, name))
+                       continue;
+
+               model_id = name;
+               find = true;
+               break;
+       }
+
+       closedir(dir);
+
+       return find;
+}
+
+bool util::set_enable_node(const string &node_path, bool sensorhub_controlled, bool enable, int enable_bit)
+{
+       int prev_status, status;
+
+       if (!get_node_value(node_path, prev_status)) {
+               ERR("Failed to get node: %s", node_path.c_str());
+               return false;
+       }
+
+       int _enable_bit = sensorhub_controlled ? enable_bit : 0;
+
+       if (enable)
+               status = prev_status | (1 << _enable_bit);
+       else
+               status = prev_status & (~(1 << _enable_bit));
+
+       if (!set_node_value(node_path, status)) {
+               ERR("Failed to set node: %s", node_path.c_str());
+               return false;
+       }
+
+       return true;
+}
+
+unsigned long long util::get_timestamp(void)
+{
+       struct timespec t;
+       clock_gettime(CLOCK_MONOTONIC, &t);
+       return ((unsigned long long)(t.tv_sec)*1000000000LL + t.tv_nsec) / 1000;
+}
+
+unsigned long long util::get_timestamp(timeval *t)
+{
+       if (!t) {
+               ERR("t is NULL");
+               return 0;
+       }
+
+       return ((unsigned long long)(t->tv_sec)*1000000LL +t->tv_usec);
+}
+
+bool util::is_sensorhub_controlled(const string &key)
+{
+       string key_node = string("/sys/class/sensors/ssp_sensor/") + key;
+
+       if (access(key_node.c_str(), F_OK) == 0)
+               return true;
+
+       return false;
+}
+
+bool util::get_node_info(const node_info_query &query, node_info &info)
+{
+       int method;
+       string device_num;
+
+       if (!get_input_method(query.key, method, device_num)) {
+               ERR("Failed to get input method for %s", query.key.c_str());
+               return false;
+       }
+
+       info.method = method;
+
+       if (method == IIO_METHOD) {
+               if (query.sensorhub_controlled)
+                       return get_sensorhub_iio_node_info(query.sensorhub_interval_node_name, device_num, info);
+               else
+                       return get_iio_node_info(query.iio_enable_node_name, device_num, info);
+       } else {
+               if (query.sensorhub_controlled)
+                       return get_sensorhub_input_event_node_info(query.sensorhub_interval_node_name, device_num, info);
+               else
+                       return get_input_event_node_info(device_num, info);
+       }
+}
+
+void util::show_node_info(node_info &info)
+{
+       if (info.data_node_path.size())
+               INFO("Data node: %s", info.data_node_path.c_str());
+       if (info.enable_node_path.size())
+               INFO("Enable node: %s", info.enable_node_path.c_str());
+       if (info.interval_node_path.size())
+               INFO("Interval node: %s", info.interval_node_path.c_str());
+       if (info.buffer_enable_node_path.size())
+               INFO("Buffer enable node: %s", info.buffer_enable_node_path.c_str());
+       if (info.buffer_length_node_path.size())
+               INFO("Buffer length node: %s", info.buffer_length_node_path.c_str());
+       if (info.trigger_node_path.size())
+               INFO("Trigger node: %s", info.trigger_node_path.c_str());
+}
+
+bool util::set_node_value(const string &node_path, int value)
+{
+       ofstream node(node_path, ofstream::binary);
+
+       if (!node)
+               return false;
+
+       node << value;
+
+       return true;
+}
+
+bool util::set_node_value(const string &node_path, unsigned long long value)
+{
+       ofstream node(node_path, ofstream::binary);
+
+       if (!node)
+               return false;
+
+       node << value;
+
+       return true;
+}
diff --git a/src/util.h b/src/util.h
new file mode 100644 (file)
index 0000000..5c13a85
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _SENSOR_UTIL_H_
+#define _SENSOR_UTIL_H_
+
+#include <sys/time.h>
+#include <string>
+
+typedef struct {
+       int method;
+       std::string data_node_path;
+       std::string enable_node_path;
+       std::string interval_node_path;
+       std::string buffer_enable_node_path;
+       std::string buffer_length_node_path;
+       std::string trigger_node_path;
+} node_info;
+
+typedef struct {
+       bool sensorhub_controlled;
+       std::string sensor_type;
+       std::string key;
+       std::string iio_enable_node_name;
+       std::string sensorhub_interval_node_name;
+} node_info_query;
+
+enum input_method {
+       IIO_METHOD = 0,
+       INPUT_EVENT_METHOD = 1,
+};
+
+typedef struct {
+       int method;
+       std::string dir_path;
+       std::string prefix;
+} input_method_info;
+
+namespace util {
+       bool set_monotonic_clock(int fd);
+
+       bool find_model_id(const std::string &sensor_type, std::string &model_id);
+       bool set_enable_node(const std::string &node_path, bool sensorhub_controlled, bool enable, int enable_bit = 0);
+
+       unsigned long long get_timestamp(void);
+       unsigned long long get_timestamp(timeval *t);
+
+       bool is_sensorhub_controlled(const std::string &key);
+       bool get_node_info(const node_info_query &query, node_info &info);
+       void show_node_info(node_info &info);
+       bool set_node_value(const std::string &node_path, int value);
+       bool set_node_value(const std::string &node_path, unsigned long long value);
+}
+#endif /*_SENSOR_UTIL_H_*/