From d439bbb82c222a3577dc14249650f19cb064739b Mon Sep 17 00:00:00 2001 From: Kibum Kim Date: Sat, 7 Jan 2012 00:48:39 +0900 Subject: [PATCH] Git init --- AUTHORS | 4 + CMakeLists.txt | 60 + LICENSE | 204 +++ TC/build.sh | 20 + TC/execute.sh | 19 + TC/tet_code | 12 + TC/tet_scen | 7 + TC/tetbuild.cfg | 3 + TC/tetclean.cfg | 2 + TC/tetexec.cfg | 1 + TC/unit/Makefile | 32 + TC/unit/tc_gen.sh | 28 + TC/unit/tslist | 11 + TC/unit/utc_MODULE_API_func.c.in | 64 + TC/unit/utc_SensorFW_sf_check_rotation_func.c | 67 + TC/unit/utc_SensorFW_sf_connect_func.c | 66 + TC/unit/utc_SensorFW_sf_disconnect_func.c | 73 + TC/unit/utc_SensorFW_sf_get_data_func.c | 79 ++ TC/unit/utc_SensorFW_sf_get_properties_func.c | 67 + ...tc_SensorFW_sf_is_sensor_event_available_func.c | 66 + TC/unit/utc_SensorFW_sf_read_raw_data_func.c | 73 + TC/unit/utc_SensorFW_sf_register_event_func.c | 75 + TC/unit/utc_SensorFW_sf_start_func.c | 69 + TC/unit/utc_SensorFW_sf_stop_func.c | 72 + TC/unit/utc_SensorFW_sf_unregister_event_func.c | 74 + build.sh | 20 + debian/changelog | 15 + debian/compat | 1 + debian/control | 27 + debian/control.libs | 18 + debian/dirs | 2 + debian/docs | 1 + debian/libslp-sensor-0.install.in | 1 + debian/libslp-sensor-0.postinst.in | 10 + debian/libslp-sensor-dev.install.in | 10 + debian/rules | 124 ++ image/SLP_SensorFW_PG_image1.png | Bin 0 -> 75165 bytes image/SLP_SensorFW_PG_image2.png | Bin 0 -> 58397 bytes include/SLP_SensorFW_PG.h | 832 ++++++++++++ include/sensor.h | 254 ++++ include/sensor_accel.h | 96 ++ include/sensor_geomag.h | 78 ++ include/sensor_gyro.h | 73 + include/sensor_light.h | 73 + include/sensor_motion.h | 87 ++ include/sensor_proxi.h | 74 + packaging/sensor.spec | 68 + report.txt | 35 + sensor.pc.in | 13 + src/client.cpp | 1436 ++++++++++++++++++++ 50 files changed, 4596 insertions(+) create mode 100644 AUTHORS create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100755 TC/build.sh create mode 100755 TC/execute.sh create mode 100755 TC/tet_code create mode 100755 TC/tet_scen create mode 100755 TC/tetbuild.cfg create mode 100755 TC/tetclean.cfg create mode 100755 TC/tetexec.cfg create mode 100755 TC/unit/Makefile create mode 100755 TC/unit/tc_gen.sh create mode 100755 TC/unit/tslist create mode 100755 TC/unit/utc_MODULE_API_func.c.in create mode 100755 TC/unit/utc_SensorFW_sf_check_rotation_func.c create mode 100755 TC/unit/utc_SensorFW_sf_connect_func.c create mode 100755 TC/unit/utc_SensorFW_sf_disconnect_func.c create mode 100755 TC/unit/utc_SensorFW_sf_get_data_func.c create mode 100755 TC/unit/utc_SensorFW_sf_get_properties_func.c create mode 100755 TC/unit/utc_SensorFW_sf_is_sensor_event_available_func.c create mode 100755 TC/unit/utc_SensorFW_sf_read_raw_data_func.c create mode 100755 TC/unit/utc_SensorFW_sf_register_event_func.c create mode 100755 TC/unit/utc_SensorFW_sf_start_func.c create mode 100755 TC/unit/utc_SensorFW_sf_stop_func.c create mode 100755 TC/unit/utc_SensorFW_sf_unregister_event_func.c create mode 100755 build.sh create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/control.libs create mode 100644 debian/dirs create mode 100644 debian/docs create mode 100644 debian/libslp-sensor-0.install.in create mode 100644 debian/libslp-sensor-0.postinst.in create mode 100644 debian/libslp-sensor-dev.install.in create mode 100755 debian/rules create mode 100755 image/SLP_SensorFW_PG_image1.png create mode 100755 image/SLP_SensorFW_PG_image2.png create mode 100755 include/SLP_SensorFW_PG.h create mode 100755 include/sensor.h create mode 100755 include/sensor_accel.h create mode 100755 include/sensor_geomag.h create mode 100755 include/sensor_gyro.h create mode 100755 include/sensor_light.h create mode 100755 include/sensor_motion.h create mode 100755 include/sensor_proxi.h create mode 100644 packaging/sensor.spec create mode 100644 report.txt create mode 100644 sensor.pc.in create mode 100755 src/client.cpp diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..4a9d6ba --- /dev/null +++ b/AUTHORS @@ -0,0 +1,4 @@ +Taesoo Jun +Jonghoon Han +JuHyun Kim + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e59ad71 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,60 @@ +cmake_minimum_required(VERSION 2.6) +project(sensor CXX) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include") +SET(VERSION_MAJOR 1) +SET(VERSION "${VERSION_MAJOR}.1.0") + +include(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED sf_common vconf glib-2.0) +add_definitions(${rpkgs_CFLAGS}) + +#add_definitions(-Wall -O3 -omit-frame-pointer -lm) +#add_definitions(-Wall -g -lma -DUSE_FILE_DEBUG) +add_definitions(-Wall -g -lma -D_DEBUG) +#add_definitions(-fvisibility=hidden -lm -DUSE_DLOG_LOG) +#add_definitions(-fvisibility=hidden -lm) + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" STREQUAL "arm") +# ADD_DEFINITIONS("-DTARGET -DHWREV_CHECK -DUSE_MPU3050_GYRO") + ADD_DEFINITIONS("-DTARGET -DHWREV_CHECK") + MESSAGE("add -DTARGET") +ELSE("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DSIMULATOR") + MESSAGE("add -DSIMULATOR") +ENDIF("${ARCH}" STREQUAL "arm") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +add_library(${PROJECT_NAME} SHARED + src/client.cpp +) + +#add_dependencies(${PROJECT_NAME} sf_common) +# to install pkgconfig setup file. + +target_link_libraries(${PROJECT_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION}) + +configure_file(${PROJECT_NAME}.pc.in ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc @ONLY) + +#install(DIRECTORY include/ DESTINATION include/ FILES_MATCHING PATTERN "*.h") +install(TARGETS ${PROJECT_NAME} DESTINATION lib COMPONENT RuntimeLibraries) + +install(FILES include/sensor.h DESTINATION include/sensor/) +install(FILES include/sensor_accel.h DESTINATION include/sensor/) +install(FILES include/sensor_geomag.h DESTINATION include/sensor/) +install(FILES include/sensor_proxi.h DESTINATION include/sensor/) +install(FILES include/sensor_motion.h DESTINATION include/sensor/) +install(FILES include/sensor_light.h DESTINATION include/sensor/) +install(FILES include/sensor_gyro.h DESTINATION include/sensor/) + + + +install(FILES ${PROJECT_NAME}.pc DESTINATION lib/pkgconfig) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9c13a9b --- /dev/null +++ b/LICENSE @@ -0,0 +1,204 @@ +Copyright (c) 2000 - 2011 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/TC/build.sh b/TC/build.sh new file mode 100755 index 0000000..5b3e818 --- /dev/null +++ b/TC/build.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +export TET_INSTALL_PATH=/home/kim/sbs-install/ # local tetware path +export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target +export PATH=$TET_TARGET_PATH/bin:$PATH +export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH +export TET_ROOT=$TET_TARGET_PATH + +export TET_SUITE_ROOT=`pwd` +FILE_NAME_EXTENSION=`date +%s` + +RESULT_DIR=results +HTML_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.html +JOURNAL_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.journal + +mkdir -p $RESULT_DIR + +tcc -c -p ./ +tcc -b -j $JOURNAL_RESULT -p ./ +grw -c 3 -f chtml -o $HTML_RESULT $JOURNAL_RESULT diff --git a/TC/execute.sh b/TC/execute.sh new file mode 100755 index 0000000..6720da0 --- /dev/null +++ b/TC/execute.sh @@ -0,0 +1,19 @@ +#!/bin/sh +export TET_INSTALL_PATH=/mnt/nfs/tetware +export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target +export PATH=$TET_TARGET_PATH/bin:$PATH +export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH + +export TET_ROOT=$TET_TARGET_PATH + +export TET_SUITE_ROOT=`pwd` +FILE_NAME_EXTENSION=`date +%s` + +RESULT_DIR=results +HTML_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.html +JOURNAL_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.journal + +mkdir -p $RESULT_DIR + +tcc -e -j $JOURNAL_RESULT -p ./ +grw -c 3 -f chtml -o $HTML_RESULT $JOURNAL_RESULT diff --git a/TC/tet_code b/TC/tet_code new file mode 100755 index 0000000..a2cf6c1 --- /dev/null +++ b/TC/tet_code @@ -0,0 +1,12 @@ +# TET reserved codes +0 "PASS" +1 "FAIL" +2 "UNRESOLVED" +3 "NOTINUSE" +4 "UNSUPPORTED" +5 "UNTESTED" +6 "UNINITIATED" +7 "NORESULT" + +# Test suite additional codes +33 "INSPECT" diff --git a/TC/tet_scen b/TC/tet_scen new file mode 100755 index 0000000..43cbc9b --- /dev/null +++ b/TC/tet_scen @@ -0,0 +1,7 @@ +all + ^TEST +##### Scenarios for TEST ##### + +# Test scenario +TEST + :include:/unit/tslist diff --git a/TC/tetbuild.cfg b/TC/tetbuild.cfg new file mode 100755 index 0000000..6192c78 --- /dev/null +++ b/TC/tetbuild.cfg @@ -0,0 +1,3 @@ +TET_OUTPUT_CAPTURE=False +TET_BUILD_TOOL=make +TET_PASS_TC_NAME=True diff --git a/TC/tetclean.cfg b/TC/tetclean.cfg new file mode 100755 index 0000000..c66eda4 --- /dev/null +++ b/TC/tetclean.cfg @@ -0,0 +1,2 @@ +TET_OUTPUT_CAPTURE=False +TET_CLEAN_TOOL=make clean diff --git a/TC/tetexec.cfg b/TC/tetexec.cfg new file mode 100755 index 0000000..0d9d39a --- /dev/null +++ b/TC/tetexec.cfg @@ -0,0 +1 @@ +TET_OUTPUT_CAPTURE=False diff --git a/TC/unit/Makefile b/TC/unit/Makefile new file mode 100755 index 0000000..31e9016 --- /dev/null +++ b/TC/unit/Makefile @@ -0,0 +1,32 @@ +CC ?= gcc + +TARGETS = utc_SensorFW_sf_get_properties_func \ + utc_SensorFW_sf_is_sensor_event_available_func \ + utc_SensorFW_sf_connect_func \ + utc_SensorFW_sf_disconnect_func \ + utc_SensorFW_sf_start_func \ + utc_SensorFW_sf_stop_func \ + utc_SensorFW_sf_register_event_func \ + utc_SensorFW_sf_unregister_event_func \ + utc_SensorFW_sf_get_data_func \ + utc_SensorFW_sf_check_rotation_func \ + utc_SensorFW_sf_read_raw_data_func + +PKGS = sf_common sensor + +LDFLAGS = `pkg-config --libs $(PKGS)` +LDFLAGS += $(TET_ROOT)/lib/tet3/tcm_s.o +LDFLAGS += -L$(TET_ROOT)/lib/tet3 -ltcm_s +LDFLAGS += -L$(TET_ROOT)/lib/tet3 -lapi_s + +CFLAGS = -I. `pkg-config --cflags $(PKGS)` +CFLAGS += -I$(TET_ROOT)/inc/tet3 +CFLAGS += -Wall + +all: $(TARGETS) + +$(TARGETS): %: %.c + $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) + +clean: + rm -f $(TARGETS) diff --git a/TC/unit/tc_gen.sh b/TC/unit/tc_gen.sh new file mode 100755 index 0000000..54f482d --- /dev/null +++ b/TC/unit/tc_gen.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +TMPSTR=$0 +SCRIPT=${TMPSTR##*/} + +if [ $# -lt 2 ]; then + echo "Usage) $SCRIPT module_name api_name" + exit 1 +fi + +MODULE=$1 +API=$2 +TEMPLATE=utc_MODULE_API_func.c.in +TESTCASE=utc_${MODULE}_${API}_func + +sed -e ' + s^@API@^'"$API"'^g + s^@MODULE@^'"$MODULE"'^g + ' $TEMPLATE > $TESTCASE.c + +if [ ! -e "$TESTCASE.c" ]; then + echo "Failed" + exit 1 +fi +echo "Testcase file is $TESTCASE.c" +echo "Done" +echo "please put \"$TESTCASE\" as Target in Makefile" +echo "please put \"/unit/$TESTCASE\" in tslist" diff --git a/TC/unit/tslist b/TC/unit/tslist new file mode 100755 index 0000000..d7c0eff --- /dev/null +++ b/TC/unit/tslist @@ -0,0 +1,11 @@ +/unit/utc_SensorFW_sf_is_sensor_event_available_func +/unit/utc_SensorFW_sf_get_properties_func +/unit/utc_SensorFW_sf_connect_func +/unit/utc_SensorFW_sf_disconnect_func +/unit/utc_SensorFW_sf_start_func +/unit/utc_SensorFW_sf_stop_func +/unit/utc_SensorFW_sf_register_event_func +/unit/utc_SensorFW_sf_unregister_event_func +/unit/utc_SensorFW_sf_get_data_func +/unit/utc_SensorFW_sf_check_rotation_func +/unit/utc_SensorFW_sf_read_raw_data_func diff --git a/TC/unit/utc_MODULE_API_func.c.in b/TC/unit/utc_MODULE_API_func.c.in new file mode 100755 index 0000000..b235fa3 --- /dev/null +++ b/TC/unit/utc_MODULE_API_func.c.in @@ -0,0 +1,64 @@ +#include + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_@MODULE@_@API@_func_01(void); +static void utc_@MODULE@_@API@_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_@MODULE@_@API@_func_01, POSITIVE_TC_IDX }, + { utc_@MODULE@_@API@_func_02, NEGATIVE_TC_IDX }, +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of @API@() + */ +static void utc_@MODULE@_@API@_func_01(void) +{ + int r = 0; + +/* + r = @API@(...); +*/ + if (r) { + tet_infoline("@API@() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init @API@() + */ +static void utc_@MODULE@_@API@_func_02(void) +{ + int r = 0; + +/* + r = @API@(...); +*/ + if (r) { + tet_infoline("@API@() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_SensorFW_sf_check_rotation_func.c b/TC/unit/utc_SensorFW_sf_check_rotation_func.c new file mode 100755 index 0000000..512b087 --- /dev/null +++ b/TC/unit/utc_SensorFW_sf_check_rotation_func.c @@ -0,0 +1,67 @@ +#include +#include + +int handle = 0; + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_SensorFW_sf_check_rotation_func_01(void); +static void utc_SensorFW_sf_check_rotation_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_SensorFW_sf_check_rotation_func_01, POSITIVE_TC_IDX }, + { utc_SensorFW_sf_check_rotation_func_02, NEGATIVE_TC_IDX }, + { NULL, 0}, +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of sf_check_rotation() + */ +static void utc_SensorFW_sf_check_rotation_func_01(void) +{ + int r = 0; + unsigned long event; + + r = sf_check_rotation(&event); + + if (r < 0) { + tet_infoline("sf_check_rotation() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init sf_check_rotation() + */ +static void utc_SensorFW_sf_check_rotation_func_02(void) +{ + int r = 0; + + r = sf_check_rotation(NULL); + + if (r > 0) { + tet_infoline("sf_check_rotation() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_SensorFW_sf_connect_func.c b/TC/unit/utc_SensorFW_sf_connect_func.c new file mode 100755 index 0000000..746880c --- /dev/null +++ b/TC/unit/utc_SensorFW_sf_connect_func.c @@ -0,0 +1,66 @@ +#include +#include + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_SensorFW_sf_connect_func_01(void); +static void utc_SensorFW_sf_connect_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_SensorFW_sf_connect_func_01, POSITIVE_TC_IDX }, + { utc_SensorFW_sf_connect_func_02, NEGATIVE_TC_IDX }, + { NULL, 0}, +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of sf_connect() + */ +static void utc_SensorFW_sf_connect_func_01(void) +{ + int r = 0; + + + r = sf_connect(ACCELEROMETER_SENSOR); + + if (r < 0) { + tet_infoline("sf_connect() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init sf_connect() + */ +static void utc_SensorFW_sf_connect_func_02(void) +{ + int r = 0; + + + r = sf_connect(100); + + if (r > 0 ) { + tet_infoline("sf_connect() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_SensorFW_sf_disconnect_func.c b/TC/unit/utc_SensorFW_sf_disconnect_func.c new file mode 100755 index 0000000..85d13f2 --- /dev/null +++ b/TC/unit/utc_SensorFW_sf_disconnect_func.c @@ -0,0 +1,73 @@ +#include +#include + + +int handle; + + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_SensorFW_sf_disconnect_func_01(void); +static void utc_SensorFW_sf_disconnect_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_SensorFW_sf_disconnect_func_01, POSITIVE_TC_IDX }, + { utc_SensorFW_sf_disconnect_func_02, NEGATIVE_TC_IDX }, + { NULL, 0}, +}; + +static void startup(void) +{ + handle = sf_connect(ACCELEROMETER_SENSOR); +} + +static void cleanup(void) +{ + sf_disconnect(handle); +} + + +/** + * @brief Positive test case of sf_disconnect() + */ +static void utc_SensorFW_sf_disconnect_func_01(void) +{ + int r = 0; + + + r = sf_disconnect(handle); + + if (r != 0) { + tet_infoline("sf_disconnect() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init sf_disconnect() + */ +static void utc_SensorFW_sf_disconnect_func_02(void) +{ + int r = 0; + + + r = sf_disconnect(100); + + if (r == 0) { + tet_infoline("sf_disconnect() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_SensorFW_sf_get_data_func.c b/TC/unit/utc_SensorFW_sf_get_data_func.c new file mode 100755 index 0000000..e1f5a12 --- /dev/null +++ b/TC/unit/utc_SensorFW_sf_get_data_func.c @@ -0,0 +1,79 @@ +#include +#include +#include + +int handle = 0; +sensor_data_t* values; + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_SensorFW_sf_get_data_func_01(void); +static void utc_SensorFW_sf_get_data_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_SensorFW_sf_get_data_func_01, POSITIVE_TC_IDX }, + { utc_SensorFW_sf_get_data_func_02, NEGATIVE_TC_IDX }, + { NULL, 0}, +}; + +static void startup(void) +{ + handle = sf_connect(ACCELEROMETER_SENSOR); + sf_start(handle,0); + +} + +static void cleanup(void) +{ + sf_stop(handle); + sf_disconnect(handle); +} + +/** + * @brief Positive test case of sf_get_data() + */ +static void utc_SensorFW_sf_get_data_func_01(void) +{ + int r = 0; + + values = (sensor_data_t*)malloc(sizeof(sensor_data_t)); + + r = sf_get_data(handle, ACCELEROMETER_BASE_DATA_SET, values); + + if (r < 0) { + tet_infoline("sf_get_data() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init sf_get_data() + */ +static void utc_SensorFW_sf_get_data_func_02(void) +{ + int r = 0; + +// values = (sensor_data_t*)malloc(sizeof(sensor_data_t)); + + r = sf_get_data(300, NULL, values); + + printf("n r = %d\n", r); + + if (r > 0) { + tet_infoline("sf_get_data() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_SensorFW_sf_get_properties_func.c b/TC/unit/utc_SensorFW_sf_get_properties_func.c new file mode 100755 index 0000000..1a1c857 --- /dev/null +++ b/TC/unit/utc_SensorFW_sf_get_properties_func.c @@ -0,0 +1,67 @@ +#include +#include + +sensor_properties_t accel_property; + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_SensorFW_sf_get_properties_func_01(void); +static void utc_SensorFW_sf_get_properties_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_SensorFW_sf_get_properties_func_01, POSITIVE_TC_IDX }, + { utc_SensorFW_sf_get_properties_func_02, NEGATIVE_TC_IDX }, + { NULL, 0}, +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of sf_get_properties() + */ +static void utc_SensorFW_sf_get_properties_func_01(void) +{ + int r = 0; + + + r = sf_get_properties(ACCELEROMETER_SENSOR, &accel_property); + + if (r < 0) { + tet_infoline("sf_get_properties() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init sf_get_properties() + */ +static void utc_SensorFW_sf_get_properties_func_02(void) +{ + int r = 0; + + r = sf_get_properties(ACCELEROMETER_SENSOR, NULL); + + if (r > 0) { + tet_infoline("sf_get_properties() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_SensorFW_sf_is_sensor_event_available_func.c b/TC/unit/utc_SensorFW_sf_is_sensor_event_available_func.c new file mode 100755 index 0000000..02804f9 --- /dev/null +++ b/TC/unit/utc_SensorFW_sf_is_sensor_event_available_func.c @@ -0,0 +1,66 @@ +#include +#include + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_SensorFW_sf_is_sensor_event_available_func_01(void); +static void utc_SensorFW_sf_is_sensor_event_available_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_SensorFW_sf_is_sensor_event_available_func_01, POSITIVE_TC_IDX }, + { utc_SensorFW_sf_is_sensor_event_available_func_02, NEGATIVE_TC_IDX }, + { NULL, 0}, +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of sf_is_sensor_event_available() + */ +static void utc_SensorFW_sf_is_sensor_event_available_func_01(void) +{ + int r = 0; + + + r = sf_is_sensor_event_available(ACCELEROMETER_SENSOR, 0); + + if (r < 0) { + tet_infoline("sf_is_sensor_event_available() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init sf_is_sensor_event_available() + */ +static void utc_SensorFW_sf_is_sensor_event_available_func_02(void) +{ + int r = 0; + + + r = sf_is_sensor_event_available(UNKNOWN_SENSOR, 0); + + if (r > 0) { + tet_infoline("sf_is_sensor_event_available() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_SensorFW_sf_read_raw_data_func.c b/TC/unit/utc_SensorFW_sf_read_raw_data_func.c new file mode 100755 index 0000000..924a288 --- /dev/null +++ b/TC/unit/utc_SensorFW_sf_read_raw_data_func.c @@ -0,0 +1,73 @@ +#include +#include + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_SensorFW_sf_read_raw_data_func_01(void); +static void utc_SensorFW_sf_read_raw_data_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_SensorFW_sf_read_raw_data_func_01, POSITIVE_TC_IDX }, + { utc_SensorFW_sf_read_raw_data_func_02, NEGATIVE_TC_IDX }, + { NULL, 0}, +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of sf_read_raw_data() + */ +static void utc_SensorFW_sf_read_raw_data_func_01(void) +{ + int r = 0; + + float values[3]; + size_t values_size; + + values_size = sizeof(values); + + r = sf_read_raw_data(ACCELEROMETER_SENSOR , values, &values_size); + + if (r < 0) { + tet_infoline("sf_read_raw_data() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init sf_read_raw_data() + */ +static void utc_SensorFW_sf_read_raw_data_func_02(void) +{ + int r = 0; + + float values[3]; + size_t values_size; + values_size = sizeof(values);; + + r = sf_read_raw_data(UNKNOWN_SENSOR , values, &values_size); + + if (r > 0) { + tet_infoline("sf_read_raw_data() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_SensorFW_sf_register_event_func.c b/TC/unit/utc_SensorFW_sf_register_event_func.c new file mode 100755 index 0000000..dc7548e --- /dev/null +++ b/TC/unit/utc_SensorFW_sf_register_event_func.c @@ -0,0 +1,75 @@ +#include +#include + +int handle = 0; + +void my_callback_func(unsigned int event_type, sensor_event_data_t *event , void *data) +{ +} + + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_SensorFW_sf_register_event_func_01(void); +static void utc_SensorFW_sf_register_event_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_SensorFW_sf_register_event_func_01, POSITIVE_TC_IDX }, + { utc_SensorFW_sf_register_event_func_02, NEGATIVE_TC_IDX }, + { NULL, 0}, +}; + +static void startup(void) +{ + handle = sf_connect(ACCELEROMETER_SENSOR); + +} + +static void cleanup(void) +{ + sf_disconnect(handle); +} + +/** + * @brief Positive test case of sf_register_event() + */ +static void utc_SensorFW_sf_register_event_func_01(void) +{ + int r = 0; + + + r = sf_register_event(handle, ACCELEROMETER_EVENT_ROTATION_CHECK, NULL, my_callback_func,NULL); + + if (r < 0) { + tet_infoline("sf_register_event() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init sf_register_event() + */ +static void utc_SensorFW_sf_register_event_func_02(void) +{ + int r = 0; + + r = sf_register_event(400, ACCELEROMETER_EVENT_ROTATION_CHECK, NULL, my_callback_func,NULL); + + if (r > 0) { + tet_infoline("sf_register_event() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_SensorFW_sf_start_func.c b/TC/unit/utc_SensorFW_sf_start_func.c new file mode 100755 index 0000000..c35871f --- /dev/null +++ b/TC/unit/utc_SensorFW_sf_start_func.c @@ -0,0 +1,69 @@ +#include +#include + +int handle = 0; + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_SensorFW_sf_start_func_01(void); +static void utc_SensorFW_sf_start_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_SensorFW_sf_start_func_01, POSITIVE_TC_IDX }, + { utc_SensorFW_sf_start_func_02, NEGATIVE_TC_IDX }, + { NULL, 0}, +}; + +static void startup(void) +{ + handle = sf_connect(ACCELEROMETER_SENSOR); +} + +static void cleanup(void) +{ + sf_disconnect(handle); +} + +/** + * @brief Positive test case of sf_start() + */ +static void utc_SensorFW_sf_start_func_01(void) +{ + int r = 0; + + + r = sf_start(handle, 0); + + if (r < 0) { + tet_infoline("sf_start() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init sf_start() + */ +static void utc_SensorFW_sf_start_func_02(void) +{ + int r = 0; + + r = sf_start(-1, 0); + + if (r > 0) { + tet_infoline("sf_start() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_SensorFW_sf_stop_func.c b/TC/unit/utc_SensorFW_sf_stop_func.c new file mode 100755 index 0000000..d8aee0b --- /dev/null +++ b/TC/unit/utc_SensorFW_sf_stop_func.c @@ -0,0 +1,72 @@ +#include +#include + +int handle = 0; + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_SensorFW_sf_stop_func_01(void); +static void utc_SensorFW_sf_stop_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_SensorFW_sf_stop_func_01, POSITIVE_TC_IDX }, + { utc_SensorFW_sf_stop_func_02, NEGATIVE_TC_IDX }, + { NULL, 0}, +}; + +static void startup(void) +{ + handle = sf_connect(ACCELEROMETER_SENSOR); + sf_start(handle, 0); +} + +static void cleanup(void) +{ + sf_stop(handle); + sf_disconnect(handle); +} + +/** + * @brief Positive test case of sf_stop() + */ +static void utc_SensorFW_sf_stop_func_01(void) +{ + int r = 0; + + + r = sf_stop(handle); + + if (r < 0) { + tet_infoline("sf_stop() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init sf_stop() + */ +static void utc_SensorFW_sf_stop_func_02(void) +{ + int r = 0; + + + r = sf_stop(-1); + + if (r > 0) { + tet_infoline("sf_stop() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_SensorFW_sf_unregister_event_func.c b/TC/unit/utc_SensorFW_sf_unregister_event_func.c new file mode 100755 index 0000000..bbe9437 --- /dev/null +++ b/TC/unit/utc_SensorFW_sf_unregister_event_func.c @@ -0,0 +1,74 @@ +#include +#include + +int handle = 0; + +void my_callback_func(unsigned int event_type, sensor_event_data_t *event , void *data) +{ +} + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_SensorFW_sf_unregister_event_func_01(void); +static void utc_SensorFW_sf_unregister_event_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_SensorFW_sf_unregister_event_func_01, POSITIVE_TC_IDX }, + { utc_SensorFW_sf_unregister_event_func_02, NEGATIVE_TC_IDX }, + { NULL, 0}, +}; + +static void startup(void) +{ + handle = sf_connect(ACCELEROMETER_SENSOR); + sf_register_event(handle, ACCELEROMETER_EVENT_ROTATION_CHECK, NULL, my_callback_func,NULL); + +} + +static void cleanup(void) +{ + sf_disconnect(handle); +} +/** + * @brief Positive test case of sf_unregister_event() + */ +static void utc_SensorFW_sf_unregister_event_func_01(void) +{ + int r = 0; + + + r = sf_unregister_event(handle, ACCELEROMETER_EVENT_ROTATION_CHECK); + + if (r < 0) { + tet_infoline("sf_unregister_event() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init sf_unregister_event() + */ +static void utc_SensorFW_sf_unregister_event_func_02(void) +{ + int r = 0; + + r = sf_unregister_event(handle, NULL); + + if (r > 0) { + tet_infoline("sf_unregister_event() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..fc2ce3a --- /dev/null +++ b/build.sh @@ -0,0 +1,20 @@ +#!/bin/bash +x +# +# Written by nicesj.park + +BASE="." +CWD=`dirname $0` +cd "$CWD" + +. ../../../../setup.conf || exit 1 + +echo "Current working directory is \"$CWD\"" +if ! [ -d $BASE ]; then + echo "This is not proper package" + exit 1; +fi + +cd $BASE + +. ${TPLDIR}/cmake.tpl +run diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..4583faa --- /dev/null +++ b/debian/changelog @@ -0,0 +1,15 @@ +libslp-sensor (0.5.6-41) unstable; urgency=low + + * version sync + * Git:165.213.180.114:pkgs/l/libslp-sensor + * Tag:libslp-sensor_0.5.6-41 + + -- JuHyun Kim Thu, 15 Dec 2011 10:54:47 +0900 + +libslp-sensor (0.0.1-1) unstable; urgency=low + + * Initial Release. + * Git:165.213.180.114:pkgs/l/libslp-sensor + * Tag:libslp-sensor_0.0.0-1 + + -- JuHyun Kim Wed, 07 Dec 2011 12:51:28 +0900 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..aebabc1 --- /dev/null +++ b/debian/control @@ -0,0 +1,27 @@ +Source: libslp-sensor +Section: libs +Priority: extra +Maintainer: Jonghoon Han , Juhyun Kim , Taesoo Jun +Build-Depends: debhelper (>= 5), autotools-dev, libsf-common-dev, libslp-setting-dev, libglib2.0-dev +Standards-Version: 0.1.0 +Homepage: N/A + +Package: libslp-sensor-dev +XB-Public-Package: yes +Architecture: any +Depends: libslp-sensor-0 (= ${Source-Version}) +Description: Sensor framework client library + Sensor framework client library. + +Package: libslp-sensor-0 +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libsf-common-0 +Description: Sensor framework client library + Sensor framework client library. + +Package: libslp-sensor-dbg +Section: debug +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libslp-sensor-0(= ${Source-Version}) +Description:Sensor framework client library(unstripped) + Easy Sensor framework client library for SLP(not recommended) diff --git a/debian/control.libs b/debian/control.libs new file mode 100644 index 0000000..bd07b5f --- /dev/null +++ b/debian/control.libs @@ -0,0 +1,18 @@ +Source: +Section: unknown +Priority: extra +Maintainer: unknown +Build-Depends: debhelper (>= 5), autotools-dev +Standards-Version: 0.1.0 + +Package: -dev +Section: libs +Architecture: any +Depends: (= ${Source-Version}) +Description: + +Package: +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..ca882bb --- /dev/null +++ b/debian/dirs @@ -0,0 +1,2 @@ +usr/bin +usr/sbin diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..a0f0008 --- /dev/null +++ b/debian/docs @@ -0,0 +1 @@ +CMakeLists.txt diff --git a/debian/libslp-sensor-0.install.in b/debian/libslp-sensor-0.install.in new file mode 100644 index 0000000..bf766f0 --- /dev/null +++ b/debian/libslp-sensor-0.install.in @@ -0,0 +1 @@ +@PREFIX@/lib/*.so* diff --git a/debian/libslp-sensor-0.postinst.in b/debian/libslp-sensor-0.postinst.in new file mode 100644 index 0000000..8e2fad5 --- /dev/null +++ b/debian/libslp-sensor-0.postinst.in @@ -0,0 +1,10 @@ +#!/bin/sh +#if [ ${USER} == "root" ];then + # change file owner + # 1.libraries + #chown root:root /usr/lib/libsensor.so +#fi +# change file permissions +# 1.libraries +#chmod 644 /usr/lib/libsensor.so + diff --git a/debian/libslp-sensor-dev.install.in b/debian/libslp-sensor-dev.install.in new file mode 100644 index 0000000..b3d4413 --- /dev/null +++ b/debian/libslp-sensor-dev.install.in @@ -0,0 +1,10 @@ +@PREFIX@/include/sensor/sensor.h +@PREFIX@/include/sensor/sensor_accel.h +@PREFIX@/include/sensor/sensor_geomag.h +@PREFIX@/include/sensor/sensor_proxi.h +@PREFIX@/include/sensor/sensor_motion.h +@PREFIX@/include/sensor/sensor_light.h +@PREFIX@/include/sensor/sensor_gyro.h +@PREFIX@/lib/pkgconfig/*.pc + + diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..7841ecc --- /dev/null +++ b/debian/rules @@ -0,0 +1,124 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +CFLAGS ?= -Wall -g +CXXFLAGS ?= -Wall -g +LDFLAGS ?= +PREFIX ?= /usr +DATADIR ?= /opt + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 + CXXFLAGS += -O0 +else + CFLAGS += -O2 + CXXFLAGS += -O2 +endif + +LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--as-needed + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" cmake . -DCMAKE_INSTALL_PREFIX=$(PREFIX) + + touch configure-stamp + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + dh_buildinfo generate cat + + # Add here commands to compile the package. + $(MAKE) + #docbook-to-man debian/wavplayer.sgml > wavplayer.1 + + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + cat $$f > $${f%.in}; \ + sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \ + sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \ + done + + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + -$(MAKE) clean + rm -rf CMakeCache.txt + rm -rf CMakeFiles + rm -rf cmake_install.cmake + rm -rf Makefile + rm -rf install_manifest.txt + rm -rf *.so + rm -rf *.pc + rm -rf $(CURDIR)/debian/buildinfo + + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + rm -f $${f%.in}; \ + done + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/wavplayer. + $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_buildinfo install + dh_installexamples + dh_install --sourcedir=debian/tmp +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip --dbg-package=libslp-sensor-dbg + dh_compress + dh_fixperms +# dh_perl + dh_makeshlibs -plibslp-sensor-0 + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/image/SLP_SensorFW_PG_image1.png b/image/SLP_SensorFW_PG_image1.png new file mode 100755 index 0000000000000000000000000000000000000000..7971662f793b7bd6147c4cedc8bb3ac834036e4d GIT binary patch literal 75165 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 literal 0 HcmV?d00001 diff --git a/image/SLP_SensorFW_PG_image2.png b/image/SLP_SensorFW_PG_image2.png new file mode 100755 index 0000000000000000000000000000000000000000..dd9621939866f98d89e31a6d96c9819e8dc92208 GIT binary patch literal 58397 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 literal 0 HcmV?d00001 diff --git a/include/SLP_SensorFW_PG.h b/include/SLP_SensorFW_PG.h new file mode 100755 index 0000000..91a4671 --- /dev/null +++ b/include/SLP_SensorFW_PG.h @@ -0,0 +1,832 @@ +/* + * libslp-sensor + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JuHyun Kim + * + * 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. + * + */ + + + +/** + * + * @ingroup SLP_PG + * @defgroup SENSOR_FRAMEWORK_PG SensorFW +@{ + + +

Introduction

+

Purpose

+ +The purpose of this document is to describe how applications can use the Sensor Framework APIs to perform different operations on different supported sensors through the sensor-server. This document gives programming guidelines to application engineers. + + + +

Scope

+ +The scope of this document is limited to Sensor framework library API usage. + +

Abbreviations

+ + + + + + + + + + +
+ API + + Application Programming Interface +
+ TCP + + Transmission Control Protocol +
+ +

Sensor Framework Overview

+ +

What is sensor framework

+ +Sensor devices are used widely in mobile devices to enhance user experience. Most modern mobile OS have a framework which manages sensor hardware on the platform and provides convenient APIs for applications. + +Sensors Framework is a middleware, which provides a sensor server for creating plug-ins and a medium through which the client applications are connected with the sensor hardware to exchange sensor data. The sensor plug-ins retrieve data from sensor hardware and enable the client applications to use the data for specific requirements. + +The following sensor types are supported by the sensor framework provided that the device supports them: + + +Accelerometer sensor
+Geomagnetic sensor
+Proximity sensor
+Light sensor
+Gyroscope sensor
+ +@} +@defgroup SENSOR_Architecture 1.Architecture +@ingroup SENSOR_FRAMEWORK_PG +@{ + +

Sensor Framework Architecture

+ +Sensor framework is basically a client-server architecture. It is mainly composed of two parts: +- Sensor Server: Sensor server is a daemon, which uniquely talks to sensor drivers in the system and dispatches sensor data to applications. Sensor server takes care of interacting with sensor driver in hardware initialization, driver configuration and data fetching, to manage all sensors on platform. + +- Sensor API Library (also called as client library): Applications wanting to access sensor services should communicate with the daemon through the sensor API library. An API library allows application to access sensor service. As shown in the diagram applications/middleware frameworks can have the sensor-framework client library in their process context. + +Unix Socket is used as IPC for communication between API library and daemon, including data transportation and command exchange. + + +The client library provides different functionality to the application like attaching an application to a sensor, getting data from it, getting updates if a value is changed etc. It contains API's designed to fulfill these features. + +@image html SLP_SensorFW_PG_image1.png +@} +@defgroup SENSOR_Feature 2.Feature +@ingroup SENSOR_FRAMEWORK_PG +@{ + +

Sensor Framework Features

+Sensor framework client features +-# Available in shared library form. +-# Provides set of APIs for accessing data from sensors. +-# Provide unique access control mechanism through client server architecture. +-# Provision to get processed/raw data from sensors. +-# Provides functionality for application to register its own callback for the case of a sensor value change. +-# Provides information about a sensor like maximum/minimum polling time. +-# Direct knowledge of rotation status with raw data access. + +Sensor framework server features +-# The actual implementation of the features supported by sensor-framework library is done in the sensor-server. +-# Sensor-server checks the devices periodically and if there is an event that meets any conditions that are being monitored, the event is reported to applications which have registered for it. +-# Sensor framework maintains a separate thread for every connection request which is called a "ipc worker". +-# IPC Workers extract the work to be done in the form of command packets. +-# These command packets are maintained in a command queue in server. +-# This queue is further fed to a command executer which extracts the command from the packets. +-# As per the command, the server allocates a plug-in worker which interacts with the device-driver interfaces. +-# Server has predefined information about the sensor. + +@} +

Sensor Framework Functions

+ +@defgroup Use_Cases1 Getting Information about available sensors +@ingroup SENSOR_UC Use Cases +@{ + +

Getting Information about available sensors

+ +API : sf_is_sensor_event_available
+Parameter In : sensor_type_t desired_sensor_type , unsigned int desired_event_type
+Parameter Return : int
+Functionality : This API checks the availability of the sensor type and event type specified by the input parameters. Some of the supported sensor types are ACCELEROMETER_SENSOR_TYPE, GEOMAGNETIC_SENSOR_TYPE etc. This API will return 0 when the event is available and negative value when it is not available.
+ + +API : sf_get_properties
+Parameter In : sensor_type_t sensor_type
+Parameter Out : sensor_properties_t *sensor_properties
+Parameter Return : int
+Functionality This API retrieves the properties of a sensor type, such as unit of sensor data, max/min range of sensor data and sensor resolution to the output parameter sensor_properties.
+ + + + +Sample Code (Showing how to get basic information about available sensors) + +@code +#include +#include +#include +int main() +{ + printf("\n Sensor test : Start of the program \n"); + int ret_val=0; + sensor_properties_t *sensor_properties; + sensor_type_t sensor_type = ACCELEROMETER_SENSOR; + int event_type = ACCELEROMETER_EVENT_ROTATION_CHECK; + + //Check whether the sensor type and the event is available + + ret_val = sf_is_sensor_event_available (sensor_type,event_type); + printf("\n Sensor Error : Return value is %d \n",ret_val); + if(ret_val != 0) + { + printf("\n Sensor test : sensor %d is not present\n ", + sensor_type); + return -1; + } + printf("\n Sensor test : Sensor type is available and valid \n"); + + //Get the sensor properties + sensor_properties = (sensor_properties_t *)malloc(sizeof(sensor_properties_t)); + + ret_val = sf_get_properties (sensor_type, sensor_properties); + if(ret_val != 0) + { + printf("\n Sensor Error : sensor_property get FAILED with code %d",ret_val); + return -1; + } + printf("\nSensor test : sensor_properties are \n unit ID : %d \n max range : %f \n + min range : %f \n sensor_resolution : %f \n ", + sensor_properties->sensor_unit_idx, sensor_properties->sensor_min_range, + sensor_properties->sensor_max_range, sensor_properties->sensor_resolution); + + if(sensor_properties) + free(sensor_properties); + + return 0; +@endcode + + +@} +@defgroup Use_Cases2 Connecting and disconnecting a sensor +@ingroup SENSOR_UC Use Cases +@{ + + +

Connecting and disconnecting a sensor

+ +Accelerometer sensor:
+The accelerometer sensor is used to measure the acceleration of the device. The three dimensional coordinate system is used to illustrate direction of the acceleration as shown in figure 2 below. The X- and Y- axis defines a plane where Z-axis direction is perpendicular to the XY plane. When a phone is moving along an axis, the acceleration is positive if movement is towards positive direction and negative if movement is on negative direction. E.g. when a phone is moving along x-axis to the direction of -x, the acceleration is negative. + +Geomagnetic sensor:
+Geomagnetic sensor indicates the strength of the geomagnetic flux density in the X, Y and Z axes. This sensor is used to finds the orientation or attitude of a body is a description of how it is aligned to the space it is in. + +Proximity sensor:
+A proximity sensor is a sensor able to detect the presence of nearby objects without any physical contact. i.e. It indicates if the device is close or not close to the user. +A proximity sensor often emits an electromagnetic or electrostatic field, or a beam of electromagnetic radiation (infrared, for instance), and looks for changes in the field or return signal. The object being sensed is often referred to as the proximity sensor's target + +Light sensor
+Light sensor measures the amount of light that it receives or the surrounding light conditions. The ambient light state is measured as a step value, where 0 is very dark and 10 is bright sunlight. A number of predefined brightness level constants are specified in the data class reference. + +Gyroscope sensor:
+A gyroscope is a device used primarily for navigation and measurement of angular velocity. Gyroscopes, also called angular rate sensors, measure how quickly an object rotates. This rate of rotation can be measured along any of the three axes X, Y and Z. 3-axis gyroscopes are often implemented with a 3-axis accelerometer to provide a full 6 degree-of-freedom (DoF) motion tracking system. + +@image html SLP_SensorFW_PG_image2.png + +API : sf_connect
+Parameter In: sensor_type_t sensor_type
+Parameter Return: int
+Functionality: This API connects a sensor type to respective sensor. The application calls this API with the type of the sensor (e.g. ACCELEROMETER_SENSOR) on the basis that the server takes the decision of which plug-in is to be connected. Once the sensor is connected, the application can proceed with data processing. +This API returns a positive handle which should be used by application to communicate on sensor type. +
+API : sf_disconnect
+Parameter In: int handle
+Parameter Return: int
+Functionality: This API disconnects an attached sensor from an application. Application must use the handle retuned after attaching the sensor. After detaching, the corresponding handle will be released.
+ +@} +@defgroup Use_Cases3 Processing data after connecting to a sensor +@ingroup SENSOR_UC Use Cases +@{ + +

Processing data after connecting to a sensor

+Once the application is connected to a sensor, data processing can be done using these API's + +API : sf_start
+Parameter In: Int handle, int option
+Parameter Return: int
+Functionality: This API sends a start command to the sensor server. This informs the server that the client side is ready to handle data and start processing. The option input parameter should be set to '0' for current usage.
+ + +API : sf_get_data
+Parameter In: int handle, int data_id
+Parameter Out:sensor_data_t* values
+Parameter Return: int
+Functionality: This API gets the processed data (sensor information) from a sensor through the sensor server. The data is loaded in the values output parameter.
+ + +API : sf_stop
+Parameter In: int handle
+Parameter Return: int
+Functionality: This API sends a stop command to the Sensor server indicating that the data processing has stopped from the application side for this time.
+ +@} +@defgroup Use_Cases4 Processing data without connecting to a sensor +@ingroup SENSOR_UC Use Cases +@{ + +

Processing data without connecting to a sensor

+ +API : sf_read_raw_data
+Parameter In: sensor_type_t sensor_type
+Parameter Out: float values[] , size_t *values_size
+Parameter Return: int
+Functionality: This API gets raw data from a sensor without connecting to the sensor-server. This doesn't need a connection handle. The type of sensor is supplied and return data is stored in the output parameter values [].
+ + + +API : sf_check_rotation
+Parameter Out: unsigned long *state
+Parameter Return: int
+Functionality: This API used to get the current rotation state. (i.e. ROTATION_EVENT_0, ROTATION_EVENT_90, ROTATION_EVENT_180 & ROTATION_EVENT_270 ). This API will directly access the sensor without connecting the process with the sensor-server. Result will be stored in the output parameter state.
+ + + + +Sample Code (Showing how to connect to server and get data (processed/raw)) + +@code +#include +#include +#include + +int main() +{ + printf("\n Sensor test : Start of the program \n"); + + int ret_val=0; + int my_handle = 0; + int get_data_id =ACCELEROMETER_BASE_DATA_SET; + + float raw_data[3]; + size_t size = 3; + + unsigned long rotaion_state = 0; + sensor_data_t *sensor_data = (sensor_data_t*)malloc(sizeof(sensor_data_t)); + sensor_properties_t *sensor_properties = NULL; + + sensor_type_t sensor_type = ACCELEROMETER_SENSOR; + int event_type = ACCELEROMETER_EVENT_ROTATION_CHECK; + + //Check whether the Accelerometer sensor type and the event is available + ret_val = sf_is_sensor_event_available (sensor_type,event_type); + + printf("\n Sensor Error : Return value is %d \n",ret_val); + if(ret_val != 0) + { + printf("\n Sensor test : sensor %d is not present\n ", sensor_type); + return -1; + } + printf("\n Sensor test : Sensor type is available and valid \n"); + + //Get the sensor properties + sensor_properties = (sensor_properties_t *)malloc(sizeof(sensor_properties_t)); + + ret_val = sf_get_properties (sensor_type, sensor_properties); + if(ret_val != 0) + { + printf("\n Sensor Error : sf_get_property get FAILED with code %d",ret_val); + return -1; + } + printf("\nSensor test : sensor_properties are \n unit ID : %d \n max range : %f \n + min range : %f \n sensor_resolution : %f \n ", + sensor_properties->sensor_unit_idx, sensor_properties->sensor_min_range, + sensor_properties->sensor_max_range, sensor_properties->sensor_resolution); + + + //Connect to the sensor through server . + my_handle = sf_connect(sensor_type); + if(my_handle < 0) + { + printf("\n Sensor Error : sf_connect FAILED with code %d",my_handle); + return -1; + } + + printf("\n Sensor test : sf_connect : handle is %d",my_handle); + + + //Start the communication + ret_val = sf_start(my_handle,0); + if(ret_val != 0) + { + printf("\n Sensor Error : sensor_start FAILED with code %d",ret_val); + return -1; + } + + + //Get the processed data from server + ret_val = sf_get_data(my_handle,get_data_id,sensor_data); + if(ret_val != 0) + { + printf("\n Sensor Error : sensor_get_data FAILED with code %d",ret_val); + return -1; + } + printf("\n Sensor Test: Gathered Data : \n X : %f \n Y : %f \n Z : %f \n Accuracy : %d \n + Unit ID : %d \n Time Stamp : %lld", sensor_data->values[0], sensor_data->values[1], + sensor_data->values[2], sensor_data->data_accuracy, sensor_data->data_unit_idx, + sensor_data->time_stamp); + + + //Get the Raw Data(Bypass server) + ret_val = sf_read_raw_data(sensor_type,(float *)raw_data, &size); + if(ret_val != 0) + { + printf("\n Sensor Error : sensor_get_data FAILED with code %d",ret_val); + return -1; + } + + printf("\n Seneor test : My raw data is x= %f y= %f and z= %f \n", + raw_data[0], raw_data[1], raw_data[2]); + + + //Get the rotation/orientation + ret_val = sf_check_rotation(&rotaion_state); + + if(ret_val != 0) + { + printf("\n Sensor Error : sf_check_rotation FAILED with code %d",ret_val); + return -1; + } + + switch(rotaion_state) + { + case ROTATION_EVENT_0 : + printf("\n Sensor test : Rotation ROTATION_EVENT_0 \n"); + break; + case ROTATION_EVENT_90: + printf("\n Sensor test : Rotation is ROTATION_EVENT_90 \n"); + break; + case ROTATION_EVENT_180 : + printf("\n Sensor test : Rotation is ROTATION_EVENT_180 \n"); + break; + case ROTATION_EVENT_270 : + printf("\n Sensor test : Rotation ROTATION_EVENT_270 \n"); + break; + default : + printf("\n Sensor test : Rotation is ROTATION_UNKNOWN \n"); + + } + + if(sensor_properties) + free(sensor_properties); + + if(sensor_data) + free(sensor_data); + + return 0; +} +@endcode + + +@} +@defgroup Use_Cases5 Subscribing and unsubscribing a Callback function for sensor events +@ingroup SENSOR_UC Use Cases +@{ + +

Subscribing and unsubscribing a Callback function for sensor events

+ +API : sf_register_event
+Parameter In : int handle , unsigned int event_type , event_conditon_t *event_condition , sensor_callback_func_t cb , void *cb_data
+Parameter Return : int
+Functionality : This API registers a user defined callback function with a connected sensor for a particular event. This callback function will be called when there is a change in the state of respective sensor. cb_data will be the parameter used during the callback call. Callback interval can be adjusted using the event_condition_t argument.
+ + + +API : sf_unregister_event
+Parameter In : int handle, unsigned int event_type
+Parameter Return : int
+Functionality : This API de-registers a user defined callback function with a sensor registered with the specified handle. After unsubscribing, no event will be sent to the application.
+ + +Sample code (This is an example showing how rotation event can be handled easily just by using these sensor framework API's) + + + +@code +#include +#include +#include + +static GMainLoop *mainloop; + +void my_callback_func(unsigned int event_type, sensor_event_data_t *event, void *data) +{ + int *my_event_data; + + if (event_type != ACCELEROMETER_EVENT_ROTATION_CHECK) { + printf("my_callback_func received data fail\n"); + return; + } + my_event_data = (int *)(event); + + switch( *my_event_data ) { + case ROTATION_EVENT_0: + printf("my_callback_func received data ROTATION_EVENT_0\n"); + break; + case ROTATION_EVENT_90: + printf("my_callback_func received data ROTATION_EVENT_90\n"); + break; + case ROTATION_EVENT_180: + printf("my_callback_func received data ROTATION_EVENT_180\n"); + break; + case ROTATION_EVENT_270: + printf("my_callback_func received data ROTATION_EVENT_270\n"); + break; + + default: + printf("my_callback_func received data unexpected\n"); + break; + } + +} + +static void sig_quit(int signo) +{ + if (mainloop) + { + g_main_loop_quit(mainloop); + } +} + +int main(int argc, char *argv[]) +{ + int handle; + int state; + + signal(SIGINT, sig_quit); + signal(SIGTERM, sig_quit); + signal(SIGQUIT, sig_quit); + + mainloop = g_main_loop_new(NULL, FALSE); + + handle = sf_connect( ACCELEROMETER_SENSOR ); + if (handle<0) { + printf("sensor attach fail\n"); + return -1; + + } + + + state = sf_register_event(handle, ACCELEROMETER_EVENT_ROTATION_CHECK, NULL , my_callback_func,NULL); + if (state<0) { + printf("sensor_register_cb fail\n"); + + } + + printf("Start SF\n"); + state = sf_start(handle, 0); + if (state<0) { + printf("SLP_sensor_start fail\n"); + + } + printf("Start SF done\n"); + + g_main_loop_run(mainloop); + g_main_loop_unref(mainloop); + + state = sf_unregister_event(handle, ACCELEROMETER_EVENT_ROTATION_CHECK ); + if (handle<0) { + printf("t sensor_unregister_cb fail\n"); + } + sf_stop(handle); + sf_disconnect(handle); + return 0; +} +@endcode + + + +@} +@defgroup Reference +@ingroup SENSOR_FRAMEWORK_PG +@{ + +Also see [ @ref SENSOR_FRAMEWORK API reference] + +

Appendixes

+ +

API Overview

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
S NoAPI NAMEIn parameterFunctionality
1sf_is_sensor_event_availablesensor_type_t desired_sensor_type , unsigned int desired_event_typeThis checks the availability of the sensor type and event type specified by the input parameters.
2sf_get_propertiessensor_type_t sensor_type, sensor_properties_t *return_propertiesThis API retrieves the properties of a sensor type like data unit ID, max range, min range and resolution
3sf_connectsensor_type_t sensor_typeThis API attaches/connects to a supplied type of sensor and returns an handle
4sf_disconnectsensor_type_t sensor_typeThis API detaches/disconnects the handle from the sensor
5sf_startInt handleThis API sends start command to the sensor
6sf_stopInt handleThis API sends stop command to the sensor
7sf_register_eventint handle , unsigned int event_type , event_conditon_t *event_condition , sensor_callback_func_t cb , void *cb_dataThis API registers a user callback function with sensor . Whenever there is a change in the sensor state on a predefined event, this callback will be called
8sf_unregister_eventint handle, unsigned int event_typeThis API de-registers the user callback function for the change in stage of a predefined event
9sf_get_dataint handle , unsigned int data_id , sensor_data_t* valuesThis API gets tje data (processed)from a sensor through the sensor server
10sf_check_rotationunsigned long *curr_stateThis API gets the current rotation value such as ROTATION_LANDSCAPE_LEFT , ROTATION_PORTRAIT_TOP etc
11sf_read_raw_datasensor_type_t sensor_type , float values[] , size_t *values_sizeThis API reads raw data without connecting the process with the sensor
+ + + +

Data structures

+Few reference sample codes are attached for application developer to well understand the System Framework Module. + +Sensor Type: +@code +typedef enum { + UNKNOWN_SENSOR = 0x0000, + ACCELEROMETER_SENSOR = 0x0001, + GEOMAGNETIC_SENSOR = 0x0002, + LIGHT_SENSOR = 0x0004, + PROXIMITY_SENSOR = 0x0008, + THERMOMETER_SENSOR = 0x0010, + GYROSCOPE_SENSOR = 0x0020, + PRESSURE_SENSOR = 0x0040 +} sensor_type_t; +@endcode + +Event Condition: +@code +typedef enum { + CONDITION_NO_OP, + CONDITION_EQUAL, + CONDITION_GREAT_THAN, + CONDITION_LESS_THAN, +} condition_op_t; + +typedef struct { + condition_op_t cond_op; + float cond_value1; +} event_conditon_t; +@endcode + +Sensor Event Data: +@code +typedef struct { + size_t event_data_size; + void *event_data; +} sensor_event_data_t; +@endcode + + +Call back function: +@code +typedef void (*sensor_callback_func_t)(unsigned int, sensor_event_data_t *, void *); + +Sensor Data: +@code +typedef struct { + int data_accuracy; + int data_unit_idx; + unsigned long long time_stamp; + int values_num; + float values[12]; +} sensor_data_t; +@endcode + + +Sensor Properties: +@code +typedef struct { + int sensor_unit_idx; + float sensor_min_range; + float sensor_max_range; + float sensor_resolution; +} sensor_properties_t; +@endcode + + +Sensor data unit index: +@code +enum sensor_data_unit_idx { + SENSOR_UNDEFINED_UNIT, + SENSOR_UNIT_METRE_PER_SECOND_SQUARED, + SENSOR_UNIT_MICRO_TESLA, + SENSOR_UNIT_DEGREE, + SENSOR_UNIT_LUX, + SENSOR_UNIT_CENTIMETER, + SENSOR_UNIT_LEVEL_1_TO_10, + SENSOR_UNIT_STATE_ON_OFF, + SENSOR_UNIT_DEGREE_PER_SECOND, + SENSOR_UNIT_IDX_END +}; +@endcode + + +Accelerometer Data ID: +@code +enum accelerometer_data_id { + ACCELEROMETER_BASE_DATA_SET = (ACCELEROMETER_SENSOR<<16) | 0x0001, +}; +@endcode + + +Accelerometer Event Type: +@code +enum accelerometer_evet_type { + ACCELEROMETER_EVENT_ROTATION_CHECK + = (ACCELEROMETER_SENSOR<<16) |0x0001, + ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME + = (ACCELEROMETER_SENSOR<<16) |0x0002, + ACCELEROMETER_EVENT_CALIBRATION_NEEDED + = (ACCELEROMETER_SENSOR<<16) |0x0004, +}; +@endcode + + +Accelerometer Rotate state: +@code +enum accelerometer_rotate_state { + ROTATION_UNKNOWN = 0, + ROTATION_LANDSCAPE_LEFT = 1, + ROTATION_PORTRAIT_TOP = 2, + ROTATION_PORTRAIT_BTM = 3, + ROTATION_LANDSCAPE_RIGHT = 4, + ROTATION_EVENT_0 = 2, + ROTATION_EVENT_90 = 1, + ROTATION_EVENT_180 = 3, + ROTATION_EVENT_270 = 4, +}; +@endcode + + +Geo Magnetic Data ID: +@code +enum geomag_data_id { + GEOMAGNETIC_BASE_DATA_SET = (GEOMAGNETIC_SENSOR<<16) | 0x0001, + GEOMAGNETIC_RAW_DATA_SET = (GEOMAGNETIC_SENSOR<<16) | 0x0002, +}; +@endcode + + +Geo Magnetic Event Type: +@code +enum geomag_evet_type { + GEOMAGNETIC_EVENT_CALIBRATION_NEEDED = (GEOMAGNETIC_SENSOR<<16) |0x0001, + GEOMAGNETIC_EVENT_ATTITUDE_DATA_REPORT_ON_TIME = (GEOMAGNETIC_SENSOR<<16) |0x0002, + GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME = (GEOMAGNETIC_SENSOR<<16) |0x0004, +}; +@endcode + + +Gyro Data ID: +@code +enum gyro_data_id { + GYRO_BASE_DATA_SET = (GYROSCOPE_SENSOR<<16) | 0x0001, +}; +@endcode + + +Gyro Event Type: +@code +enum gyro_evet_type { + GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME = (GYROSCOPE_SENSOR<<16) |0x0001, +}; +@endcode + + +Light Data ID: +@code +enum light_data_id { + LIGHT_BASE_DATA_SET = (LIGHT_SENSOR<<16) | 0x0001, +}; +@endcode + + +Light Event Type: +@code +enum light_evet_type { + LIGHT_EVENT_CHANGE_LEVEL = (LIGHT_SENSOR<<16) |0x0001, + LIGHT_EVENT_LEVEL_DATA_REPORT_ON_TIME = (LIGHT_SENSOR<<16) |0x0002, +}; +@endcode + + +Proximity Data ID: +@code +enum proxi_data_id { + PROXIMITY_BASE_DATA_SET = (PROXIMITY_SENSOR<<16) | 0x0001, +}; +@endcode + + +Proximity Event Type: +@code +enum proxi_evet_type { + PROXIMITY_EVENT_CHANGE_STATE = (PROXIMITY_SENSOR<<16) |0x0001, + PROXIMITY_EVENT_STATE_REPORT_ON_TIME = (PROXIMITY_SENSOR<<16) |0x0002, +}; +@endcode + + +Proximity Change State: +@code +enum proxi_change_state { + PROXIMITY_STATE_FAR = 0, + PROXIMITY_STATE_NEAR = 1, +}; +@endcode + + + +*/ +/** +*@} +*/ + +/** + * @defgroup SENSOR_UC Use Cases + * @ingroup SENSOR_FRAMEWORK_PG +*/ diff --git a/include/sensor.h b/include/sensor.h new file mode 100755 index 0000000..cb20ece --- /dev/null +++ b/include/sensor.h @@ -0,0 +1,254 @@ +/* + * libslp-sensor + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JuHyun Kim + * + * 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 __SAMSUNG_LINUX_SENSOR_COMMON_H__ +#define __SAMSUNG_LINUX_SENSOR_COMMON_H__ + +#ifndef DEPRECATED +#define DEPRECATED __attribute__((deprecated)) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/** + * @defgroup SENSOR_FRAMEWORK SensorFW + * To support the unified API for the various sensors + */ + +/** + * @defgroup SENSOR_FRAMEWORK_COMMON Sensor Framework Common API + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the sensors. + * @{ + */ + +/** + * @file sensor.h + * @brief Sensor Framework common API header file + * for supporting application layer and communicate between App and Sensor Framework + * server. + * + * @author JuHyun Kim(jh8212.kim@samsung.com) + * @version 1.0 +*/ + + +typedef enum { + UNKNOWN_SENSOR = 0x0000, + ACCELEROMETER_SENSOR = 0x0001, + GEOMAGNETIC_SENSOR = 0x0002, + LIGHT_SENSOR = 0x0004, + PROXIMITY_SENSOR = 0x0008, + THERMOMETER_SENSOR = 0x0010, + GYROSCOPE_SENSOR = 0x0020, + PRESSURE_SENSOR = 0x0040, + MOTION_SENSOR = 0x0080, +} sensor_type_t; + +/*header for each sensor type*/ +#include +#include +#include +#include +#include +#include + +typedef enum { + CONDITION_NO_OP, + CONDITION_EQUAL, + CONDITION_GREAT_THAN, + CONDITION_LESS_THAN, +} condition_op_t; + +typedef struct { + condition_op_t cond_op; + float cond_value1; +} event_condition_t; + + +typedef struct { + size_t event_data_size; + void *event_data; +} sensor_event_data_t; + +typedef void (*sensor_callback_func_t)(unsigned int, sensor_event_data_t *, void *); /**/ + +enum sensor_data_unit_idx { + SENSOR_UNDEFINED_UNIT, + SENSOR_UNIT_METRE_PER_SECOND_SQUARED, + SENSOR_UNIT_MICRO_TESLA, + SENSOR_UNIT_DEGREE, + SENSOR_UNIT_LUX, + SENSOR_UNIT_CENTIMETER, + SENSOR_UNIT_LEVEL_1_TO_10, + SENSOR_UNIT_STATE_ON_OFF, + SENSOR_UNIT_DEGREE_PER_SECOND, + + SENSOR_UNIT_IDX_END +}; + +enum sensor_data_accuracy { + SENSOR_ACCURACY_UNDEFINED = -1, + SENSOR_ACCURACY_BAD = 0, + SENSOR_ACCURACY_NORMAL =1, + SENSOR_ACCURACY_GOOD = 2, + SENSOR_ACCURACY_VERYGOOD = 3 +}; + +typedef struct { + int data_accuracy; + int data_unit_idx; + unsigned long long time_stamp; + int values_num; + float values[12]; +} sensor_data_t; + +typedef struct { + int x; + int y; +} sensor_panning_data_t; + + +typedef struct { + int sensor_unit_idx; + float sensor_min_range; + float sensor_max_range; + float sensor_resolution; +} sensor_properties_t; + + +/** + * @fn int sf_is_sensor_event_available ( sensor_type_t desired_sensor_type , unsigned int desired_event_type ) + * @brief This API loads the in parameter available list with the type of sensor available for operation . Some of the supported types are ACCELEROMETER_SENSOR_TYPE, GEOMAGNETIC_SENSOR_TYPE etc. This API will return 0 when it is available and negative value when it does not available. + * @param[in] desired_sensor_type your desired sensor type to check + * @param[in] desired_event_type your desired event type to check , if you want to check only sensor-available , set "0" value + * @return if it succeed, it return zero value(available) , otherwise negative value return (not available) + */ +int sf_is_sensor_event_available ( sensor_type_t desired_sensor_type , unsigned int desired_event_type ); + + +/** + * @fn int sf_get_properties(sensor_type_t sensor_type, sensor_properties_t *return_properties) + * @brief This API loads the properties of sensor type like unit of sensor data, max/min range of sensor data etc to the output parameter sensor_properties. + * @param[in] sensor_type your desired sensor type + * @param[out] return_properties property information of your desired sensor + * @return if it succeed, it return zero value , otherwise negative value return + */ +int sf_get_properties(sensor_type_t sensor_type, sensor_properties_t *return_properties); + + +/** + * @fn int sf_connect(sensor_type_t sensor_type) + * @brief This API connects a sensor type to respective sensor. The application calls with the type of the sensor (ex. ACCELEROMETER_SENSOR) and on basis of that server takes decision of which plug-in to be connected. Once sensor connected application can proceed for data processing. This API returns a positive handle which should be used by application to communicate on sensor type. + * @param[in] sensor_type your desired sensor type + * @return if it succeed, it return handle value( >=0 ) , otherwise negative value return + */ +int sf_connect(sensor_type_t sensor_type); + + +/** + * @fn int sf_disconnect(int handle) + * @brief This API disconnects an attached sensor from an application. Application must use the handle retuned after attaching the sensor. After detaching, the corresponding handle will be released. + * @param[in] handle received handle value by sf_connect() + * @return if it succeed, it return zero value , otherwise negative value return + */ +int sf_disconnect(int handle); + + +/** + * @fn int sf_start(int handle , int option) + * @brief This API sends a start command to sensor server. This intimates server that the client side is ready to handle data and start processing. The parameter option should be '0' for current usages. + * @param[in] handle received handle value by sf_connect() + * @param[in] option just set a "0" value (not support current , reserved for future + * @return if it succeed, it return zero value , otherwise negative value return + */ +int sf_start(int handle , int option); + + +/** + * @fn int sf_stop(int handle) + * @brief This API sends a stop command to the Sensor server indicating that the data processing is stopped from application side for this time. + * @param[in] handle received handle value by sf_connect() + * @return if it succeed, it return zero value , otherwise negative value return + */ +int sf_stop(int handle); + +/** + * @fn int sf_register_event(int handle , unsigned int event_type , event_conditon_t *event_condition , sensor_callback_func_t cb , void *cb_data ) + * @brief This API registers a user defined callback function with a connected sensor for a particular event. This callback function will be called when there is a change in the state of respective sensor. cb_data will be the parameter used during the callback call. Callback interval can be adjusted using even_contion_t argument. + * @param[in] handle received handle value by sf_connect() + * @param[in] event_type your desired event_type to register it + * @param[in] event_condition input event_condition for special event. if you want to register without event_condition, just use a NULL value + * @param[in] cb your define callback function + * @param[in] cb_data your option data that will be send when your define callback function called. if you don't have any option data, just use a NULL value + * @return if it succeed, it return zero value , otherwise negative value return + */ +int sf_register_event(int handle , unsigned int event_type , event_condition_t *event_condition , sensor_callback_func_t cb , void *cb_data ); + + +/** + * @fn int sf_unregister_event(int handle, unsigned int event_type) + * @brief This API de-registers a user defined callback function with a sensor registered with the specified handle. After unsubscribe, no event will be sent to the application. + * @param[in] handle received handle value by sf_connect() + * @param[in] event_type your desired event_type that you want to unregister event + * @return if it succeed, it return zero value , otherwise negative value return + */ +int sf_unregister_event(int handle, unsigned int event_type); + + +/** + * @fn int sf_get_data(int handle , unsigned int data_id , sensor_data_t* values) + * @brief This API gets raw data from a sensor with connecting the sensor-server. The type of sensor is supplied and return data is stored in the output parameter values []. + * @param[in] handle received handle value by sf_connect() + * @param[in] data_id predefined data_ID as every sensor in own header - sensor_xxx.h , enum xxx_data_id {} + * @param[out] values return values + * @return if it succeed, it return zero value , otherwise negative value return + */ +int sf_get_data(int handle , unsigned int data_id , sensor_data_t* values); + + +/** + * @fn int sf_check_rotation( unsigned long *curr_state) + * @brief This API used to get the current rotation state. (i.e. ROTATION_EVENT_0, ROTATION_EVENT_90, ROTATION_EVENT_180 & ROTATION_EVENT_270 ). This API will directly access the sensor without connection process with the sensor-server. Result will be stored in the output parameter state. + * @param[out] curr_state it will return enum accelerometer_rotate_state value + * @return if it succeed, it return zero value , otherwise negative value return + */ +int sf_check_rotation( unsigned long *curr_state); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif +//! End of a file diff --git a/include/sensor_accel.h b/include/sensor_accel.h new file mode 100755 index 0000000..04e695f --- /dev/null +++ b/include/sensor_accel.h @@ -0,0 +1,96 @@ +/* + * libslp-sensor + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JuHyun Kim + * + * 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 __SAMSUNG_LINUX_SENSOR_ACCEL_H__ +#define __SAMSUNG_LINUX_SENSOR_ACCEL_H__ + + +//! Pre-defined events for the accelometer sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @defgroup SENSOR_ACCEL Accelerometer Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the Accelerometer sensor. + * @{ + */ + +/** + * @file sensor_accel.h + * @brief This file contains the prototypes of the Accelerometer sensor API + * @author JuHyun Kim(jh8212.kim@samsung.com) + * @date 2010-01-24 + * @version 0.1 + */ + + +enum accelerometer_data_id { + ACCELEROMETER_BASE_DATA_SET = (ACCELEROMETER_SENSOR<<16) | 0x0001, + ACCELEROMETER_ORIENTATION_DATA_SET = (ACCELEROMETER_SENSOR<<16) | 0x0002, +}; + +enum accelerometer_event_type { + ACCELEROMETER_EVENT_ROTATION_CHECK = (ACCELEROMETER_SENSOR<<16) | 0x0001, + ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME = (ACCELEROMETER_SENSOR<<16) | 0x0002, + ACCELEROMETER_EVENT_CALIBRATION_NEEDED = (ACCELEROMETER_SENSOR<<16) | 0x0004, + ACCELEROMETER_EVENT_SET_HORIZON = (ACCELEROMETER_SENSOR<<16) | 0x0008, + ACCELEROMETER_EVENT_SET_WAKEUP = (ACCELEROMETER_SENSOR<<16) | 0x0010, + ACCELEROMETER_EVENT_ORIENTATION_DATA_REPORT_ON_TIME = (ACCELEROMETER_SENSOR<<16) | 0x0011, +}; + + +enum accelerometer_rotate_state { + ROTATION_UNKNOWN = 0, + ROTATION_LANDSCAPE_LEFT = 1, + ROTATION_PORTRAIT_TOP = 2, + ROTATION_PORTRAIT_BTM = 3, + ROTATION_LANDSCAPE_RIGHT = 4, + ROTATION_EVENT_0 = 2, /*CCW base*/ + ROTATION_EVENT_90 = 1, /*CCW base*/ + ROTATION_EVENT_180 = 3, /*CCW base*/ + ROTATION_EVENT_270 = 4, /*CCW base*/ +}; + + +struct rotation_event { + enum accelerometer_rotate_state rotation; + enum accelerometer_rotate_state rm[2]; +}; + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif +//! End of a file diff --git a/include/sensor_geomag.h b/include/sensor_geomag.h new file mode 100755 index 0000000..42589f6 --- /dev/null +++ b/include/sensor_geomag.h @@ -0,0 +1,78 @@ +/* + * libslp-sensor + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JuHyun Kim + * + * 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 __SAMSUNG_LINUX_SENSOR_GEOMAG_H__ +#define __SAMSUNG_LINUX_SENSOR_GEOMAG_H__ + +//! Pre-defined events for the geomagnetic sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** + * @defgroup SENSOR_GEOMAG Geomagnetic Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the Geomagnatic sensor. + * @{ + */ + +/** + * @file sensor_geomag.h + * @brief This file contains the prototypes of the Geomagnatic sensor API + * @author JuHyun Kim(jh8212.kim@samsung.com) + * @date 2010-01-24 + * @version 0.1 + */ + + + +enum geomag_data_id { + GEOMAGNETIC_BASE_DATA_SET = (GEOMAGNETIC_SENSOR<<16) | 0x0001, + GEOMAGNETIC_RAW_DATA_SET = (GEOMAGNETIC_SENSOR<<16) | 0x0002, +}; + + +enum geomag_evet_type { + GEOMAGNETIC_EVENT_CALIBRATION_NEEDED = (GEOMAGNETIC_SENSOR<<16) |0x0001, + GEOMAGNETIC_EVENT_ATTITUDE_DATA_REPORT_ON_TIME = (GEOMAGNETIC_SENSOR<<16) |0x0002, + GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME = (GEOMAGNETIC_SENSOR<<16) |0x0004, +}; + + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif +//! End of a file diff --git a/include/sensor_gyro.h b/include/sensor_gyro.h new file mode 100755 index 0000000..90a3d66 --- /dev/null +++ b/include/sensor_gyro.h @@ -0,0 +1,73 @@ +/* + * libslp-sensor + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JuHyun Kim + * + * 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 __SAMSUNG_LINUX_SENSOR_GYRO_H__ +#define __SAMSUNG_LINUX_SENSOR_GYRO_H__ + +//! Pre-defined events for the gyroscope sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** + * @defgroup SENSOR_GYRO Gyro Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the gyro sensor. + * @{ + */ + +/** + * @file sensor_gyro.h + * @brief This file contains the prototypes of the gyro sensor API + * @author JuHyun Kim(jh8212.kim@samsung.com) + * @date 2010-01-24 + * @version 0.1 + */ + + +enum gyro_data_id { + GYRO_BASE_DATA_SET = (GYROSCOPE_SENSOR<<16) | 0x0001, +}; + + +enum gyro_evet_type { + GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME = (GYROSCOPE_SENSOR<<16) |0x0001, +}; + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif +//! End of a file diff --git a/include/sensor_light.h b/include/sensor_light.h new file mode 100755 index 0000000..7ec3c59 --- /dev/null +++ b/include/sensor_light.h @@ -0,0 +1,73 @@ +/* + * libslp-sensor + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JuHyun Kim + * + * 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 __SAMSUNG_LINUX_SENSOR_LIGHT_H__ +#define __SAMSUNG_LINUX_SENSOR_LIGHT_H__ + +//! Pre-defined events for the light sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @defgroup SENSOR_LIGHT Light Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the light sensor. + * @{ + */ + +/** + * @file sensor_light.h + * @brief This file contains the prototypes of the light sensor API + * @author JuHyun Kim(jh8212.kim@samsung.com) + * @date 2010-01-24 + * @version 0.1 + */ + + +enum light_data_id { + LIGHT_BASE_DATA_SET = (LIGHT_SENSOR<<16) | 0x0001, +}; + + +enum light_evet_type { + LIGHT_EVENT_CHANGE_LEVEL = (LIGHT_SENSOR<<16) |0x0001, + LIGHT_EVENT_LEVEL_DATA_REPORT_ON_TIME = (LIGHT_SENSOR<<16) |0x0002, +}; + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif +//! End of a file diff --git a/include/sensor_motion.h b/include/sensor_motion.h new file mode 100755 index 0000000..7edb61b --- /dev/null +++ b/include/sensor_motion.h @@ -0,0 +1,87 @@ +/* + * libslp-sensor + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JuHyun Kim + * + * 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 __SAMSUNG_LINUX_SENSOR_MOTION_H__ +#define __SAMSUNG_LINUX_SENSOR_MOTION_H__ + + +//! Pre-defined events for the motion sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif + + +enum motion_evet_type { + MOTION_ENGINE_EVENT_SNAP = (MOTION_SENSOR<<16) |0x0001, + MOTION_ENGINE_EVENT_SHAKE = (MOTION_SENSOR<<16) |0x0002, + MOTION_ENGINE_EVENT_DOUBLETAP = (MOTION_SENSOR<<16) |0x0004, + MOTION_ENGINE_EVENT_PANNING = (MOTION_SENSOR<<16) |0x0008, + MOTION_ENGINE_EVENT_TOP_TO_BOTTOM = (MOTION_SENSOR<<16) |0x0010, +}; + +enum motion_snap_event { + MOTION_ENGIEN_SNAP_NONE, + MOTION_ENGIEN_NEGATIVE_SNAP_X, + MOTION_ENGIEN_POSITIVE_SNAP_X, + MOTION_ENGIEN_NEGATIVE_SNAP_Y, + MOTION_ENGIEN_POSITIVE_SNAP_Y, + MOTION_ENGIEN_NEGATIVE_SNAP_Z, + MOTION_ENGIEN_POSITIVE_SNAP_Z, + MOTION_ENGIEN_SNAP_LEFT = MOTION_ENGIEN_NEGATIVE_SNAP_X, + MOTION_ENGIEN_SNAP_RIGHT = MOTION_ENGIEN_POSITIVE_SNAP_X, + +}; + +enum motion_shake_event { + MOTION_ENGIEN_SHAKE_NONE, + MOTION_ENGIEN_SHAKE_DETECTION, + MOTION_ENGIEN_SHAKE_CONTINUING, + MOTION_ENGIEN_SHAKE_FINISH, + MOTION_ENGINE_SHAKE_BREAK, +}; + +enum motion_doubletap_event { + MOTION_ENGIEN_DOUBLTAP_NONE, + MOTION_ENGIEN_DOUBLTAP_DETECTION, +}; + +enum motion_top_to_bottom_event { + MOTION_ENGIEN_TOP_TO_BOTTOM_NONE, + MOTION_ENGIEN_TOP_TO_BOTTOM_WAIT, + MOTION_ENGIEN_TOP_TO_BOTTOM_DETECTION, +}; + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif +//! End of a file diff --git a/include/sensor_proxi.h b/include/sensor_proxi.h new file mode 100755 index 0000000..73f2455 --- /dev/null +++ b/include/sensor_proxi.h @@ -0,0 +1,74 @@ +/* + * libslp-sensor + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JuHyun Kim + * + * 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 __SAMSUNG_LINUX_SENSOR_PROXI_H__ +#define __SAMSUNG_LINUX_SENSOR_PROXI_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** + * @defgroup SENSOR_PROXY Proximity Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the Proxymaty sensor. + * @{ + */ + +/** + * @file sensor_proxi.h + * @brief This file contains the prototypes of the proximaty sensor API + * @author JuHyun Kim(jh8212.kim@samsung.com) + * @date 2010-01-24 + * @version 0.1 + */ + + +enum proxi_data_id { + PROXIMITY_BASE_DATA_SET = (PROXIMITY_SENSOR<<16) | 0x0001, +}; + +enum proxi_evet_type { + PROXIMITY_EVENT_CHANGE_STATE = (PROXIMITY_SENSOR<<16) |0x0001, + PROXIMITY_EVENT_STATE_REPORT_ON_TIME = (PROXIMITY_SENSOR<<16) |0x0002, +}; + +enum proxi_change_state { + PROXIMITY_STATE_FAR = 0, + PROXIMITY_STATE_NEAR = 1, +}; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif +//! End of a file diff --git a/packaging/sensor.spec b/packaging/sensor.spec new file mode 100644 index 0000000..8fea81a --- /dev/null +++ b/packaging/sensor.spec @@ -0,0 +1,68 @@ + +Name: sensor +Summary: Sensor framework client library +Version: 0.5.6 +Release: 1 +Group: TO_BE/FILLED_IN +License: TO BE FILLED IN +Source0: sensor-%{version}.tar.gz +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig +BuildRequires: cmake +BuildRequires: vconf-keys-devel +BuildRequires: pkgconfig(sf_common) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(glib-2.0) + + +%description +Sensor framework client library + + + +%package devel +Summary: Sensor framework library (devel) +Group: System/Sensor Framework +Requires: %{name} = %{version}-%{release} + +%description devel +Sensor framework client library (devel) + + +%prep +%setup -q -n %{name}-%{version} + + +%build +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} + + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + + + + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + + + + + +%files +%defattr(-,root,root,-) +%doc COPYING +%{_libdir}/libsensor.so.* + + +%files devel +%defattr(-,root,root,-) +%{_includedir}/sensor/*.h +%{_libdir}/libsensor.so +%{_libdir}/pkgconfig/sensor.pc + diff --git a/report.txt b/report.txt new file mode 100644 index 0000000..584e53f --- /dev/null +++ b/report.txt @@ -0,0 +1,35 @@ +============================================================== +Package: src +============================================================== +1: You don't have either of COPYING and LICENSE. After adding one of them, re-do the sanity checking. +============================================================== + + +============================================================== +Package: include +============================================================== +1: You don't have either of COPYING and LICENSE. After adding one of them, re-do the sanity checking. +============================================================== + + +============================================================== +Package: image +============================================================== +1: You don't have either of COPYING and LICENSE. After adding one of them, re-do the sanity checking. +============================================================== + + +============================================================== +Package: .git +============================================================== +1: You don't have either of COPYING and LICENSE. After adding one of them, re-do the sanity checking. +============================================================== + + +============================================================== +Package: debian +============================================================== +1: You don't have either of COPYING and LICENSE. After adding one of them, re-do the sanity checking. +============================================================== + + diff --git a/sensor.pc.in b/sensor.pc.in new file mode 100644 index 0000000..abac8eb --- /dev/null +++ b/sensor.pc.in @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@/sensor + +Name: libsensor +Description: Sensor framework client library +Version: @VERSION@ +Requires: +Libs: -L${libdir} -lsensor +Cflags: -I${includedir} diff --git a/src/client.cpp b/src/client.cpp new file mode 100755 index 0000000..faf4d67 --- /dev/null +++ b/src/client.cpp @@ -0,0 +1,1436 @@ +/* + * libslp-sensor + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JuHyun Kim + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +extern int errno; + +#ifndef EXTAPI +#define EXTAPI __attribute__((visibility("default"))) +#endif + +#define MAX_BIND_SLOT 16 +#define MAX_CB_SLOT_PER_BIND 16 +#define MAX_CB_BIND_SLOT 64 + +#define PITCH_MIN 35 +#define PITCH_MAX 145 + +#define MAX_CHANNEL_NAME_LEN 50 +#define BASE_GATHERING_INTERVAL 100 + +#define ACCEL_SENSOR_BASE_CHANNEL_NAME "accel_datastream" +#define GEOMAG_SENSOR_BASE_CHANNEL_NAME "geomag_datastream" +#define LIGHT_SENSOR_BASE_CHANNEL_NAME "lumin_datastream" +#define PROXI_SENSOR_BASE_CHANNEL_NAME "proxi_datastream" +#define MOTION_ENGINE_BASE_CHANNEL_NAME "motion_datastream" +#define GYRO_SENSOR_BASE_CHANNEL_NAME "gyro_datastream" + +#define ROTATION_0 0 +#define ROTATION_90 90 +#define ROTATION_180 180 +#define ROTATION_270 270 +#define ROTATION_360 360 +#define ROTATION_THD 45 + +#define RADIAN_VALUE (57.2957) + + + +const char *STR_SF_CLIENT_IPC_SOCKET = "/tmp/sf_socket"; +const char *LCD_TYPE_KEY = "memory/sensor/lcd_type"; + +static cmutex _lock; + +enum _sensor_current_state { + SENSOR_STATE_UNKNOWN = -1, + SENSOR_STATE_STOPPED = 0, + SENSOR_STATE_STARTED = 1, +}; + +struct sf_bind_table_t { + csock *ipc; + sensor_type_t sensor_type; + int cb_event_max_num; /*limit by MAX_BIND_PER_CB_SLOT*/ + int cb_slot_num[MAX_CB_SLOT_PER_BIND]; + int my_handle; + int sensor_state; +}; + +struct cb_bind_table_t { + char call_back_key[MAX_KEY_LEN]; + void *client_data; + void (*sensor_callback_func_t)(unsigned int, sensor_event_data_t *, void *); + unsigned int cb_event_type; + int my_cb_handle; + int my_sf_handle; + + unsigned int request_count; + unsigned int request_data_id; + void *collected_data; + unsigned int current_collected_idx; + + GSource *source; + guint gsource_interval; + guint gID; +}; + +static struct rotation_event rotation_mode[] = +{ + { + ROTATION_UNKNOWN, + { + ROTATION_UNKNOWN, + ROTATION_UNKNOWN + }, + }, + { + ROTATION_EVENT_90, + { + ROTATION_LANDSCAPE_LEFT, + ROTATION_PORTRAIT_BTM + }, + }, + { + ROTATION_EVENT_0, + { + ROTATION_PORTRAIT_TOP, + ROTATION_LANDSCAPE_LEFT + }, + }, + { + ROTATION_EVENT_180, + { + ROTATION_PORTRAIT_BTM, + ROTATION_LANDSCAPE_RIGHT + }, + }, + { + ROTATION_EVENT_270, + { + ROTATION_LANDSCAPE_RIGHT, + ROTATION_PORTRAIT_TOP + }, + }, +}; + + +static sf_bind_table_t g_bind_table[MAX_BIND_SLOT]; + +static cb_bind_table_t g_cb_table[MAX_CB_BIND_SLOT]; + +inline static int acquire_handle(void) +{ + register int i; + _lock.lock(); + for (i = 0; i < MAX_BIND_SLOT; i ++) { + if (g_bind_table[i].ipc == NULL) break; + } + _lock.unlock(); + + return i; +} + + +inline static int cb_acquire_handle(void) +{ + register int i; + _lock.lock(); + for (i = 0; i < MAX_CB_BIND_SLOT; i ++) { + if (g_cb_table[i].sensor_callback_func_t == NULL) break; + } + _lock.unlock(); + + return i; +} + + +inline static void release_handle(int i) +{ + register int j; + + _lock.lock(); + delete g_bind_table[i].ipc; + g_bind_table[i].ipc = NULL; + g_bind_table[i].sensor_type = UNKNOWN_SENSOR; + + g_bind_table[i].my_handle = -1; + g_bind_table[i].sensor_state = SENSOR_STATE_UNKNOWN; + + for (j=0; j -1) ) { + g_cb_table[g_bind_table[i].cb_slot_num[j]].client_data= NULL; + g_cb_table[g_bind_table[i].cb_slot_num[j]].sensor_callback_func_t = NULL; + g_cb_table[g_bind_table[i].cb_slot_num[j]].cb_event_type = 0x00; + g_cb_table[g_bind_table[i].cb_slot_num[j]].my_cb_handle = -1; + g_bind_table[i].cb_slot_num[j] = -1; + } + } + + g_bind_table[i].cb_event_max_num = 0; + + _lock.unlock(); +} + +inline static void cb_release_handle(int i) +{ + _lock.lock(); + g_cb_table[i].client_data= NULL; + g_cb_table[i].sensor_callback_func_t = NULL; + g_cb_table[i].cb_event_type = 0x00; + g_cb_table[i].my_cb_handle = -1; + g_cb_table[i].my_sf_handle = -1; + + g_cb_table[i].request_count = 0; + g_cb_table[i].request_data_id = 0; + + if ( g_cb_table[i].collected_data ) + free (g_cb_table[i].collected_data); + + g_cb_table[i].collected_data = NULL; + g_cb_table[i].current_collected_idx = 0; + + g_cb_table[i].source = NULL; + g_cb_table[i].gsource_interval = 0; + g_cb_table[i].gID = 0; + + _lock.unlock(); +} + +static void sensor_changed_cb (keynode_t *node, void *data) +{ + int *cb_handle = (int*)(data); + int val; + sensor_event_data_t cb_data; + sensor_panning_data_t panning_data; + + if (g_cb_table[*cb_handle].sensor_callback_func_t) { + + if ( vconf_keynode_get_type(node) != VCONF_TYPE_INT ) { + ERR("Err invaild key_type , incomming key_type : %d , key_name : %s , key_value : %d", + vconf_keynode_get_type(node), vconf_keynode_get_name(node),vconf_keynode_get_int(node)); + return; + } + + val = vconf_keynode_get_int(node); + + if(g_cb_table[*cb_handle].cb_event_type == MOTION_ENGINE_EVENT_PANNING) + { + if(val != 0) + { + panning_data.x = (short)(val >> 16); + panning_data.y = (short)(val & 0x0000FFFF); + cb_data.event_data_size = sizeof(sensor_panning_data_t); + cb_data.event_data = (void *)&panning_data; + g_cb_table[*cb_handle].sensor_callback_func_t(g_cb_table[*cb_handle].cb_event_type, &cb_data , g_cb_table[*cb_handle].client_data); + } + } + else if ( val<0 ) { + ERR("vconf_keynode_get_int fail for key : %s , handle_num : %d , get_value : %d\n", g_cb_table[*cb_handle].call_back_key,*cb_handle , val); + } else { + switch (g_cb_table[*cb_handle].cb_event_type) { + case ACCELEROMETER_EVENT_ROTATION_CHECK : + /* fall through */ + case ACCELEROMETER_EVENT_SET_HORIZON : + /* fall through */ + case ACCELEROMETER_EVENT_SET_WAKEUP : + /* fall through */ + case GEOMAGNETIC_EVENT_CALIBRATION_NEEDED : + /* fall through */ + case LIGHT_EVENT_CHANGE_LEVEL : + /* fall through */ + case PROXIMITY_EVENT_CHANGE_STATE: + /* fall through */ + case MOTION_ENGINE_EVENT_SNAP: + /* fall through */ + case MOTION_ENGINE_EVENT_SHAKE: + /* fall through */ + case MOTION_ENGINE_EVENT_DOUBLETAP: + /* fall through */ + case MOTION_ENGINE_EVENT_TOP_TO_BOTTOM: + /* fall through */ + cb_data.event_data_size = sizeof(val); + cb_data.event_data = (void *)&val ; + break; + default : + ERR("Undefined cb_event_type"); + return ; + break; + } + + + g_cb_table[*cb_handle].sensor_callback_func_t(g_cb_table[*cb_handle].cb_event_type , &cb_data , g_cb_table[*cb_handle].client_data); + } + + } else { + ERR("Empty Callback func in cb_handle : %d\n", *cb_handle); + } + +} + +static gboolean sensor_timeout_handler(gpointer data) +{ + int *cb_handle = (int*)(data); + int state; + sensor_event_data_t cb_data; + + if ( g_bind_table[g_cb_table[*cb_handle].my_sf_handle].sensor_state != SENSOR_STATE_STARTED ) { + ERR("Check sensor_state, current sensor state : %d",g_bind_table[g_cb_table[*cb_handle].my_sf_handle].sensor_state); + return TRUE; + } + + DBG("sensor_timeout_handler started , cb_handle value : %d\n", *cb_handle); + + if (g_cb_table[*cb_handle].sensor_callback_func_t) { + + if ( ((g_cb_table[*cb_handle].request_data_id & 0xFFFF) > 0) && ((g_cb_table[*cb_handle].request_data_id & 0xFFFF) < 10) ) { + sensor_data_t *base_data_values; + base_data_values =(sensor_data_t *)g_cb_table[*cb_handle].collected_data; + + if ( !base_data_values ) { + ERR("ERR get saved_gather_data stuct fail in sensor_timeout_handler \n"); + return FALSE; + } + state = sf_get_data(g_cb_table[*cb_handle].my_sf_handle, g_cb_table[*cb_handle].request_data_id, base_data_values); + + if ( state < 0 ) { + ERR("ERR sensor_get_struct_data fail in sensor_timeout_handler : %d\n",state); + return TRUE; + } + + cb_data.event_data_size = sizeof (sensor_data_t); + cb_data.event_data = g_cb_table[*cb_handle].collected_data; + + g_cb_table[*cb_handle].sensor_callback_func_t( g_cb_table[*cb_handle].cb_event_type , &cb_data , g_cb_table[*cb_handle].client_data); + + + } else { + ERR("Does not support data_type"); + return TRUE; + } + + + } else { + ERR("Empty Callback func in cb_handle : %d\n", *cb_handle); + } + + return TRUE; +} + +///////////////////////////////////for internal /////////////////////////////////// +static int server_get_properties(int handle , sensor_properties_t *return_properties ) +{ + cpacket packet(sizeof(cmd_return_property_t) + sizeof(base_property_struct)+ 4); + cmd_get_property_t *cmd_payload; + INFO("server_get_properties called with handle : %d \n", handle); + if (handle < 0) { + ERR("Invalid handle\n"); + errno = EINVAL; + return -1; + } + + cmd_payload = (cmd_get_property_t*)packet.data(); + if (!cmd_payload) { + ERR("cannot find memory for send packet.data"); + errno = ENOMEM; + return -2; + } + + packet.set_version(PROTOCOL_VERSION); + packet.set_cmd(CMD_GET_PROPERTY); + packet.set_payload_size(sizeof(cmd_get_property_t)); + + cmd_payload->get_level = ((unsigned int)g_bind_table[handle].sensor_type<<16) | 0x0001; + + + INFO("Send CMD_GET_PROPERTY command\n"); + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->send(packet.packet(), packet.size()) == false) { + ERR("Faield to send a packet\n"); + release_handle(handle); + errno = ECOMM; + return -2; + } + + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv(packet.packet(), packet.header_size()) == false) { + ERR("Faield to receive a packet\n"); + release_handle(handle); + errno = ECOMM; + return -2; + } + + if (packet.payload_size()) { + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv((char*)packet.packet() + packet.header_size(), packet.payload_size()) == false) { + ERR("Faield to receive a packet\n"); + release_handle(handle); + errno = ECOMM; + return -2; + } + + if (packet.cmd() == CMD_GET_PROPERTY) { + cmd_return_property_t *return_payload; + return_payload = (cmd_return_property_t*)packet.data(); + if (return_payload->state < 0) { + ERR("sever get property fail , return state : %d\n",return_payload->state); + errno = EBADE; + return -2; + } else { + base_property_struct *base_return_property; + base_return_property = (base_property_struct *)return_payload->property_struct; + + return_properties->sensor_unit_idx = base_return_property->sensor_unit_idx ; + return_properties->sensor_min_range= base_return_property->sensor_min_range; + return_properties->sensor_max_range= base_return_property->sensor_max_range; + return_properties->sensor_resolution = base_return_property->sensor_resolution; + } + } else { + ERR("unexpected server cmd\n"); + errno = EBADE; + return -2; + } + } + + return 0; +} + + + +///////////////////////////////////for external /////////////////////////////////// + +EXTAPI int sf_is_sensor_event_available ( sensor_type_t desired_sensor_type , unsigned int desired_event_type ) +{ + int handle; + cpacket packet(sizeof(cmd_reg_t)+4); + cmd_reg_t *payload; + + handle = sf_connect(desired_sensor_type); + if ( handle < 0 ) { + errno = ENODEV; + return -2; + } + + if ( desired_event_type != 0 ) { + + payload = (cmd_reg_t*)packet.data(); + if (!payload) { + ERR("cannot find memory for send packet.data"); + errno = ENOMEM; + return -2; + } + + packet.set_version(PROTOCOL_VERSION); + packet.set_cmd(CMD_REG); + packet.set_payload_size(sizeof(cmd_reg_t)); + payload->type = REG_CHK; + payload->event_type = desired_event_type; + + INFO("Send CMD_REG command\n"); + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->send(packet.packet(), packet.size()) == false) { + ERR("Faield to send a packet\n"); + release_handle(handle); + errno = ECOMM; + return -2; + } + + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv(packet.packet(), packet.header_size()) == false) { + ERR("Faield to receive a packet\n"); + release_handle(handle); + errno = ECOMM; + return -2; + } + + if (packet.payload_size()) { + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv((char*)packet.packet() + packet.header_size(), packet.payload_size()) == false) { + ERR("Faield to receive a packet\n"); + release_handle(handle); + errno = ECOMM; + return -2; + } + + if (packet.cmd() == CMD_DONE) { + cmd_done_t *payload; + payload = (cmd_done_t*)packet.data(); + if (payload->value == -1) { + ERR("sever check fail\n"); + errno = ENODEV; + return -2; + } + } else { + ERR("unexpected server cmd\n"); + errno = ECOMM; + return -2; + } + } + + } + + sf_disconnect(handle); + + return 0; +} + + +EXTAPI int sf_get_properties(sensor_type_t sensor_type, sensor_properties_t *return_properties) +{ + int handle; + int state = -1; + + retvm_if( (!return_properties ) , -1 , "Invalid return properties pointer : %p", return_properties); + + handle = sf_connect(sensor_type); + if ( handle < 0 ) { + ERR("Sensor connet fail !! for : %x \n", sensor_type); + return -1; + } else { + state = server_get_properties( handle , return_properties ); + if ( state < 0 ) { + ERR("server_get_properties fail , state : %d \n",state); + } + sf_disconnect(handle); + } + + return state; +} + +EXTAPI int sf_connect(sensor_type_t sensor_type) +{ + register int i, j; + cpacket packet(sizeof(cmd_hello_t)+MAX_CHANNEL_NAME_LEN+4); //need to check real payload size !!! + cmd_hello_t *payload; + cmd_done_t *return_payload; + + pid_t cpid; + size_t channel_name_length; + + const char *sf_channel_name = NULL; + + cpid = getpid(); + + INFO("Sensor_attach_channel from pid : %d , to sensor_type : %x",cpid ,sensor_type); + + i = acquire_handle(); + if (i == MAX_BIND_SLOT) { + ERR("MAX_BIND_SLOT, Too many slot required"); + errno = ENOMEM; + return -2; + } + + INFO("Empty slot : %d\n", i); + + switch (sensor_type) { + case ACCELEROMETER_SENSOR : + sf_channel_name = (char *)ACCEL_SENSOR_BASE_CHANNEL_NAME; + g_bind_table[i].cb_event_max_num = 6; + + for(j = 0 ; j < g_bind_table[i].cb_event_max_num ; j++) + g_bind_table[i].cb_slot_num[j] = -1; + + break; + + case GEOMAGNETIC_SENSOR : + sf_channel_name = (char *)GEOMAG_SENSOR_BASE_CHANNEL_NAME; + g_bind_table[i].cb_event_max_num = 3; + + for(j = 0 ; j < g_bind_table[i].cb_event_max_num ; j++) + g_bind_table[i].cb_slot_num[j] = -1; + + break; + + case LIGHT_SENSOR: + sf_channel_name = (char *)LIGHT_SENSOR_BASE_CHANNEL_NAME; + g_bind_table[i].cb_event_max_num = 2; + + for(j = 0 ; j < g_bind_table[i].cb_event_max_num ; j++) + g_bind_table[i].cb_slot_num[j] = -1; + + break; + + case PROXIMITY_SENSOR: + sf_channel_name = (char *)PROXI_SENSOR_BASE_CHANNEL_NAME; + g_bind_table[i].cb_event_max_num = 2; + + for(j = 0 ; j < g_bind_table[i].cb_event_max_num ; j++) + g_bind_table[i].cb_slot_num[j] = -1; + + break; + + case MOTION_SENSOR: + sf_channel_name = (char *)MOTION_ENGINE_BASE_CHANNEL_NAME; + g_bind_table[i].cb_event_max_num = 7; + + for(j = 0 ; j < g_bind_table[i].cb_event_max_num ; j++) + g_bind_table[i].cb_slot_num[j] = -1; + + break; + + case GYROSCOPE_SENSOR: + sf_channel_name = (char *)GYRO_SENSOR_BASE_CHANNEL_NAME; + g_bind_table[i].cb_event_max_num = 1; + + for(j = 0 ; j < g_bind_table[i].cb_event_max_num ; j++) + g_bind_table[i].cb_slot_num[j] = -1; + + break; + + case THERMOMETER_SENSOR: + case PRESSURE_SENSOR: + case UNKNOWN_SENSOR: + default : + ERR("Undefined sensor_type"); + release_handle(i); + errno = ENODEV; + return -2; + break; + } + + g_bind_table[i].sensor_type = sensor_type ; + g_bind_table[i].my_handle = i; + g_bind_table[i].sensor_state = SENSOR_STATE_STOPPED; + + try { + g_bind_table[i].ipc = new csock( (char *)STR_SF_CLIENT_IPC_SOCKET, csock::SOCK_TCP|csock::SOCK_IPC|csock::SOCK_WORKER, 0, 0); + } catch (...) { + release_handle(i); + errno = ECOMM; + return -2; + } + + if (g_bind_table[i].ipc && g_bind_table[i].ipc->connect_to_server() == false) { + delete g_bind_table[i].ipc; + g_bind_table[i].ipc = NULL; + release_handle(i); + errno = ECOMM; + return -2; + } + + + INFO("Connected to server\n"); + payload = (cmd_hello_t*)packet.data(); + if (!payload) { + ERR("cannot find memory for send packet.data"); + release_handle(i); + errno = ENOMEM; + return -2; + } + + if (!sf_channel_name ) { + ERR("cannot find matched-sensor name!!!"); + release_handle(i); + errno = ENODEV; + return -2; + } else { + channel_name_length = strlen(sf_channel_name); + if ( channel_name_length > MAX_CHANNEL_NAME_LEN ) { + ERR("error, channel_name_length too long !!!"); + release_handle(i); + errno = EINVAL; + return -1; + } + } + + packet.set_version(PROTOCOL_VERSION); + packet.set_cmd(CMD_HELLO); + packet.set_payload_size(sizeof(cmd_hello_t) + channel_name_length); + strcpy(payload->name, sf_channel_name); + + if (g_bind_table[i].ipc && g_bind_table[i].ipc->send(packet.packet(), packet.size()) == false) { + ERR("Failed to send a hello packet\n"); + release_handle(i); + errno = ECOMM; + return -2; + } + + INFO("Wait for recv a reply packet\n"); + if (g_bind_table[i].ipc && g_bind_table[i].ipc->recv(packet.packet(), packet.header_size()) == false) { + release_handle(i); + errno = ECOMM; + return -2; + } + + if (packet.payload_size()) { + if (g_bind_table[i].ipc && g_bind_table[i].ipc->recv((char*)packet.packet() + packet.header_size(), packet.payload_size()) == false) { + release_handle(i); + errno = ECOMM; + return -2; + } + } + + return_payload = (cmd_done_t*)packet.data(); + if (!return_payload) { + ERR("cannot find memory for return packet.data"); + release_handle(i); + return -1; + } + + if ( return_payload->value < 0) { + ERR("There is no sensor \n"); + release_handle(i); + return -1; + } + + INFO("Connected sensor type : %x , handle : %d \n", sensor_type , i); + return i; +} + +EXTAPI int sf_disconnect(int handle) +{ + cpacket packet(sizeof(cmd_byebye_t)+4); + cmd_byebye_t *payload; + + retvm_if( (g_bind_table[handle].ipc == NULL) ||(handle < 0) , -1 , "sensor_detach_channel fail , invalid handle value : %d",handle); + + INFO("Detach, so remove %d from the table\n", handle); + + payload = (cmd_byebye_t*)packet.data(); + if (!payload) { + ERR("cannot find memory for send packet.data"); + errno = ENOMEM; + return -2; + } + + packet.set_version(PROTOCOL_VERSION); + packet.set_cmd(CMD_BYEBYE); + packet.set_payload_size(sizeof(cmd_byebye_t)); + + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->send(packet.packet(), packet.size()) == false) { + ERR("Failed to send, but delete handle\n"); + errno = ECOMM; + goto out; + } + + INFO("Recv a reply packet\n"); + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv(packet.packet(), packet.header_size()) == false) { + ERR("Send to reply packet fail\n"); + errno = ECOMM; + goto out; + } + + if (packet.payload_size()) { + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv((char*)packet.packet() + packet.header_size(), packet.payload_size()) == false) { + ERR("Failed to recv packet\n"); + errno = ECOMM; + } + } + +out: + release_handle(handle); + return 0; + +} + +EXTAPI int sf_start(int handle , int option) +{ + cpacket packet(sizeof(cmd_start_t)+4); + cmd_start_t *payload; + + retvm_if( (g_bind_table[handle].ipc == NULL) ||(handle < 0) , -1 , "sensor_start fail , invalid handle value : %d",handle); + retvm_if( option != 0 , -1 , "sensor_start fail , invalid option value : %d",option); + + + INFO("Sensor S/F Started\n"); + + payload = (cmd_start_t*)packet.data(); + if (!payload) { + ERR("cannot find memory for send packet.data"); + errno = ENOMEM; + return -2; + } + + packet.set_version(PROTOCOL_VERSION); + packet.set_cmd(CMD_START); + packet.set_payload_size(sizeof(cmd_start_t)); + payload->option = option; + + INFO("Send CMD_START command\n"); + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->send(packet.packet(), packet.size()) == false) { + ERR("Faield to send a packet\n"); + release_handle(handle); + errno = ECOMM; + return -2; + } + + INFO("Recv a reply packet\n"); + + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv(packet.packet(), packet.header_size()) == false) { + ERR("Send to reply packet fail\n"); + errno = ECOMM; + return -2; + } + + DBG("packet received\n"); + if (packet.payload_size()) { + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv((char*)packet.packet() + packet.header_size(), packet.payload_size()) == false) { + errno = ECOMM; + return -2; + } + + if (packet.cmd() == CMD_DONE) { + cmd_done_t *payload; + payload = (cmd_done_t*)packet.data(); + if (payload->value < 0) { + ERR("Error from sensor server [-1 or -2 : socket error, -3 : stopped by sensor plugin] value = [%d]\n", payload->value); + errno = ECOMM; + return payload->value; + } + } else { + ERR("unexpected server cmd\n"); + errno = ECOMM; + return -2; + } + } + + g_bind_table[handle].sensor_state = SENSOR_STATE_STARTED; + + return 0; + +} + +EXTAPI int sf_stop(int handle) +{ + cpacket packet(sizeof(cmd_stop_t)+4); + cmd_stop_t *payload; + + retvm_if( (g_bind_table[handle].ipc == NULL) ||(handle < 0) , -1 , "sensor_stop fail , invalid handle value : %d",handle); + + + INFO("Sensor S/F Stopped\n"); + + payload = (cmd_stop_t*)packet.data(); + if (!payload) { + ERR("cannot find memory for send packet.data"); + errno = ENOMEM; + return -2; + } + + packet.set_version(PROTOCOL_VERSION); + packet.set_cmd(CMD_STOP); + packet.set_payload_size(sizeof(cmd_stop_t)); + + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->send(packet.packet(), packet.size()) == false) { + ERR("Failed to send a packet\n"); + release_handle(handle); + errno = ECOMM; + return -2; + } + + g_bind_table[handle].sensor_state = SENSOR_STATE_STOPPED; + + return 0; + +} + +EXTAPI int sf_register_event(int handle , unsigned int event_type , event_condition_t *event_condition , sensor_callback_func_t cb , void *cb_data ) +{ + cpacket packet(sizeof(cmd_reg_t)+4); + cmd_reg_t *payload; + int i; + int avail_cb_slot_idx = -1; + + int collect_data_flag = 0; + + retvm_if( (g_bind_table[handle].ipc == NULL) ||(handle < 0) , -1 , "sensor_register_cb fail , invalid handle value : %d",handle); + + payload = (cmd_reg_t*)packet.data(); + if (!payload) { + ERR("cannot find memory for send packet.data"); + errno = ENOMEM; + return -2; + } + + DBG("Current handle's(%d) cb_event_max_num : %d\n", handle , g_bind_table[handle].cb_event_max_num); + + for ( i=0 ; i>i) == 0x0001) { + if ( (g_bind_table[handle].cb_slot_num[i] == -1) ||(!(g_cb_table[ g_bind_table[handle].cb_slot_num[i] ].sensor_callback_func_t)) ) { + DBG("Find available slot in g_bind_table for cb\n"); + avail_cb_slot_idx = i; + break; + } + } + } + + if (avail_cb_slot_idx < 0 ) { + ERR("Find cb_slot fail, There is already callback function!!\n"); + errno = ENOMEM; + return -2; + } + + i = cb_acquire_handle(); + if (i == MAX_CB_BIND_SLOT) { + ERR("MAX_BIND_SLOT, Too many slot required"); + errno = ENOMEM; + return -2; + } + INFO("Empty cb_slot : %d\n", i); + + g_cb_table[i].my_cb_handle = i; + g_cb_table[i].my_sf_handle = handle; + + INFO("Sensor S/F register cb\n"); + + packet.set_version(PROTOCOL_VERSION); + packet.set_cmd(CMD_REG); + packet.set_payload_size(sizeof(cmd_reg_t)); + payload->type = REG_ADD; + payload->event_type = event_type; + + if(!event_condition) + payload->interval = BASE_GATHERING_INTERVAL; + else if((event_condition->cond_op == CONDITION_EQUAL) && (event_condition->cond_value1 > 0 )) + payload->interval = event_condition->cond_value1; + else + payload->interval = BASE_GATHERING_INTERVAL; + + + INFO("Send CMD_REG command with reg_type : %x , event_typ : %x\n",payload->type , payload->event_type ); + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->send(packet.packet(), packet.size()) == false) { + ERR("Faield to send a packet\n"); + cb_release_handle(i); + release_handle(handle); + errno = ECOMM; + return -2; + } + + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv(packet.packet(), packet.header_size()) == false) { + ERR("Faield to receive a packet\n"); + cb_release_handle(i); + release_handle(handle); + errno = ECOMM; + return -2; + } + + if (packet.payload_size()) { + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv((char*)packet.packet() + packet.header_size(), packet.payload_size()) == false) { + ERR("Faield to receive a packet\n"); + cb_release_handle(i); + release_handle(handle); + errno = ECOMM; + return -2; + } + + if (packet.cmd() == CMD_DONE) { + cmd_done_t *payload; + payload = (cmd_done_t*)packet.data(); + if (payload->value == -1) { + ERR("server register fail\n"); + cb_release_handle(i); + errno = ECOMM; + return -2; + } + } else { + ERR("unexpected server cmd\n"); + cb_release_handle(i); + errno = ECOMM; + return -2; + } + } + + memset(g_cb_table[i].call_back_key,'\0',MAX_KEY_LEN); + snprintf(g_cb_table[i].call_back_key,(MAX_KEY_LEN-1),"%s%x",DEFAULT_SENSOR_KEY_PREFIX, event_type); + + g_cb_table[i].cb_event_type = event_type; + g_cb_table[i].client_data = cb_data; + g_cb_table[i].sensor_callback_func_t = cb; + + switch (event_type ) { + case ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME: + /* fall through */ + case GEOMAGNETIC_EVENT_ATTITUDE_DATA_REPORT_ON_TIME: + /* fall through */ + case PROXIMITY_EVENT_STATE_REPORT_ON_TIME: + /* fall through */ + case GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME: + collect_data_flag = 1; + g_cb_table[i].request_count = 1; //support only 1 + g_cb_table[i].request_data_id = (event_type & (0xFFFF<<16)) |0x0001; + if (!event_condition) { + g_cb_table[i].gsource_interval = BASE_GATHERING_INTERVAL; + } else { + if ( (event_condition->cond_op == CONDITION_EQUAL) && (event_condition->cond_value1 > 0 ) ) { + g_cb_table[i].gsource_interval = (guint)event_condition->cond_value1; + } else { + ERR("Invaild input_condition interval , input_interval : %f\n", event_condition->cond_value1); + cb_release_handle(i); + errno = EINVAL; + return -1; + } + } + + break; + + case LIGHT_EVENT_LEVEL_DATA_REPORT_ON_TIME: + collect_data_flag = 1; + g_cb_table[i].request_count = 1; //support only 1 + g_cb_table[i].request_data_id = LIGHT_BASE_DATA_SET; + if (!event_condition) { + g_cb_table[i].gsource_interval = (BASE_GATHERING_INTERVAL*5); + } else { + if ( (event_condition->cond_op == CONDITION_EQUAL) && (event_condition->cond_value1 > 0 ) ) { + g_cb_table[i].gsource_interval = (guint)event_condition->cond_value1; + } else { + ERR("Invaild input_condition interval , input_interval : %f\n", event_condition->cond_value1); + cb_release_handle(i); + errno = EINVAL; + return -1; + } + } + break; + + case GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME: + collect_data_flag = 1; + g_cb_table[i].request_count = 1; //support only 1 + g_cb_table[i].request_data_id = GEOMAGNETIC_RAW_DATA_SET; + if (!event_condition) { + g_cb_table[i].gsource_interval = (BASE_GATHERING_INTERVAL); + } else { + if ( (event_condition->cond_op == CONDITION_EQUAL) && (event_condition->cond_value1 > 0 ) ) { + g_cb_table[i].gsource_interval = (guint)event_condition->cond_value1; + } else { + ERR("Invaild input_condition interval , input_interval : %f\n", event_condition->cond_value1); + cb_release_handle(i); + errno = EINVAL; + return -1; + } + } + break; + + case ACCELEROMETER_EVENT_ORIENTATION_DATA_REPORT_ON_TIME: + collect_data_flag = 1; + g_cb_table[i].request_count = 1; //support only 1 + g_cb_table[i].request_data_id = ACCELEROMETER_ORIENTATION_DATA_SET; + if (!event_condition) { + g_cb_table[i].gsource_interval = BASE_GATHERING_INTERVAL; + } else { + if ( (event_condition->cond_op == CONDITION_EQUAL) && (event_condition->cond_value1 > 0 ) ) { + g_cb_table[i].gsource_interval = (guint)event_condition->cond_value1; + } else { + ERR("Invaild input_condition interval , input_interval : %f\n", event_condition->cond_value1); + cb_release_handle(i); + errno = EINVAL; + return -1; + } + } + + break; + + + } + + INFO("key : %s(p:%p), cb_handle value : %d\n", g_cb_table[i].call_back_key ,g_cb_table[i].call_back_key, i ); + + if ( collect_data_flag ) { + sensor_data_t *collected_data_set; + + collected_data_set = new sensor_data_t [g_cb_table[i].request_count]; + if ( !collected_data_set ) { + ERR("memory allocation fail for gathering datas\n"); + cb_release_handle(i); + errno = ECOMM; + return -2; + } + g_cb_table[i].collected_data = (void *)collected_data_set; + g_cb_table[i].current_collected_idx = 0; + + if ( g_cb_table[i].gsource_interval != 0 ) { + g_cb_table[i].source = g_timeout_source_new(g_cb_table[i].gsource_interval); + } else { + ERR("Error , gsource_interval value : %u",g_cb_table[i].gsource_interval); + cb_release_handle(i); + errno = EINVAL; + return -1; + } + g_source_set_callback (g_cb_table[i].source, sensor_timeout_handler, (gpointer)&g_cb_table[i].my_cb_handle,NULL); + g_cb_table[i].gID = g_source_attach (g_cb_table[i].source, NULL); + + }else { + g_cb_table[i].request_count = 0; + g_cb_table[i].request_data_id = 0; + g_cb_table[i].collected_data = NULL; + + if (vconf_notify_key_changed( g_cb_table[i].call_back_key, + sensor_changed_cb, (void *)&g_cb_table[i].my_cb_handle) < 0 ) { + ERR("vconf_add_changed_cb fail, for key : %s , my_cb_handle value : %d\n", g_cb_table[i].call_back_key, g_cb_table[i].my_cb_handle); + cb_release_handle(i); + errno = ENODEV; + return -2; + } + + } + + g_bind_table[handle].cb_slot_num[avail_cb_slot_idx] = i; + + return 0; +} + + +EXTAPI int sf_unregister_event(int handle, unsigned int event_type) +{ + int state = 0; + cpacket packet(sizeof(cmd_reg_t)+4); + cmd_reg_t *payload; + int find_cb_handle =-1; + int i; + + int collect_data_flag = 0; + + retvm_if( (g_bind_table[handle].ipc == NULL) ||(handle < 0) , -1 , "sensor_unregister_cb fail , invalid handle value : %d",handle); + + payload = (cmd_reg_t*)packet.data(); + if (!payload) { + ERR("cannot find memory for send packet.data"); + errno = ENOMEM; + return -2; + } + + for ( i=0 ; itype = REG_DEL; + payload->event_type = event_type; + + switch (event_type ) { + case ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME: + /* fall through */ + case ACCELEROMETER_EVENT_ORIENTATION_DATA_REPORT_ON_TIME: + /* fall through */ + case GEOMAGNETIC_EVENT_ATTITUDE_DATA_REPORT_ON_TIME: + /* fall through */ + case PROXIMITY_EVENT_STATE_REPORT_ON_TIME: + /* fall through */ + case GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME: + /* fall through */ + case LIGHT_EVENT_LEVEL_DATA_REPORT_ON_TIME: + /* fall through */ + case GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME: + collect_data_flag = 1; + break; + } + + INFO("Send CMD_REG command\n"); + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->send(packet.packet(), packet.size()) == false) { + ERR("Faield to send a packet\n"); + release_handle(handle); + errno = ECOMM; + return -2; + } + + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv(packet.packet(), packet.header_size()) == false) { + ERR("Failed to recv packet_header\n"); + release_handle(handle); + errno = ECOMM; + return -2; + } + + if (packet.payload_size()) { + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv((char*)packet.packet() + packet.header_size(), packet.payload_size()) == false) { + ERR("Failed to recv packet\n"); + release_handle(handle); + errno = ECOMM; + return -2; + } + + } + + if ( collect_data_flag ) { + g_source_destroy(g_cb_table[find_cb_handle].source); + g_source_unref(g_cb_table[find_cb_handle].source); + g_cb_table[find_cb_handle].request_count = 0; + g_cb_table[find_cb_handle].request_data_id = 0; + g_cb_table[find_cb_handle].gsource_interval = 0; + + } else { + state = vconf_ignore_key_changed(g_cb_table[find_cb_handle].call_back_key, sensor_changed_cb); + if ( state < 0 ) { + ERR("Failed to del callback using by vconf_del_changed_cb for key : %s\n",g_cb_table[find_cb_handle].call_back_key); + errno = ENODEV; + state = -2; + } + } + + cb_release_handle(find_cb_handle); + g_bind_table[handle].cb_slot_num[i] = -1; + + return state; + + +} + + +EXTAPI int sf_get_data(int handle , unsigned int data_id , sensor_data_t* values) +{ + cpacket packet(sizeof(cmd_get_struct_t)+sizeof(base_data_struct)+4); + cmd_get_data_t *payload; + cmd_get_struct_t *return_payload; + int i; + struct timeval sv; + + + retvm_if( (!values) , -1 , "sf_get_data fail , invalid get_values pointer %p", values); + retvm_if( ( (data_id & 0xFFFF) < 1) || ( (data_id & 0xFFFF) > 0xFFF), -1 , "sf_get_data fail , invalid data_id %d", data_id); + retvm_if( (g_bind_table[handle].ipc == NULL) ||(handle < 0) , -1 , "sf_get_data fail , invalid handle value : %d",handle); + + if(g_bind_table[handle].sensor_state != SENSOR_STATE_STARTED) + { + ERR("sensor framewoker doesn't started"); + values->data_accuracy = SENSOR_ACCURACY_UNDEFINED; + values->data_unit_idx = SENSOR_UNDEFINED_UNIT; + values->time_stamp = 0; + values->values_num = 0; + errno = ECOMM; + return -2; + } + + payload = (cmd_get_data_t*)packet.data(); + if (!payload) { + ERR("cannot find memory for send packet.data"); + errno = ENOMEM; + return -2; + } + + packet.set_version(PROTOCOL_VERSION); + packet.set_cmd(CMD_GET_STRUCT); + packet.set_payload_size(sizeof(cmd_get_data_t)); + payload->data_id = data_id; + + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->send(packet.packet(), packet.size()) == false) { + release_handle(handle); + errno = ECOMM; + return -2; + } + + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv(packet.packet(), packet.header_size()) == false) { + release_handle(handle); + errno = ECOMM; + return -2; + } + + if (packet.payload_size()) { + if (g_bind_table[handle].ipc && g_bind_table[handle].ipc->recv((char*)packet.packet() + packet.header_size(), packet.payload_size()) == false) { + release_handle(handle); + errno = ECOMM; + return -2; + } + } + + return_payload = (cmd_get_struct_t*)packet.data(); + if (!return_payload) { + ERR("cannot find memory for return packet.data"); + errno = ENOMEM; + return -2; + } + + if ( return_payload->state < 0 ) { + ERR("get values fail from server \n"); + values->data_accuracy = SENSOR_ACCURACY_UNDEFINED; + values->data_unit_idx = SENSOR_UNDEFINED_UNIT; + values->time_stamp = 0; + values->values_num = 0; + errno = ECOMM; + return -2; + } + + base_data_struct *base_return_data; + base_return_data = (base_data_struct *)return_payload->data_struct; + + gettimeofday(&sv, NULL); + values->time_stamp = MICROSECONDS(sv); + + values->data_accuracy = base_return_data->data_accuracy; + values->data_unit_idx = base_return_data->data_unit_idx; + values->values_num = base_return_data->values_num; + for ( i = 0 ; i < base_return_data->values_num ; i++ ) { + values->values[i] = base_return_data->values[i]; + DBG("client , get_data_value , [%d] : %f \n", i , values->values[i]); + } + + + return 0; + +} + +EXTAPI int sf_check_rotation( unsigned long *curr_state) +{ + int state = -1; + + double raw_z; + double atan_value, norm_z; + int acc_theta , acc_pitch; + int handle = 0; + int lcd_type = 0; + + sensor_data_t *base_data_values = (sensor_data_t*)malloc(sizeof(sensor_data_t)); + + retvm_if( curr_state==NULL , -1 , "sf_check_rotation fail , invalid curr_state"); + + *curr_state = ROTATION_UNKNOWN; + + INFO("Sensor_attach_channel from pid : %d",getpid()); + + handle = sf_connect( ACCELEROMETER_SENSOR); + if (handle<0) + { + ERR("sensor attach fail\n"); + return 0; + } + + state = sf_start(handle, 0); + if(state < 0) + { + ERR("sf_start fail\n"); + return 0; + } + + state = sf_get_data(handle, ACCELEROMETER_BASE_DATA_SET, base_data_values); + if(state < 0) + { + ERR("sf_get_data fail\n"); + return 0; + } + + state = sf_stop(handle); + if(state < 0) + { + ERR("sf_stop fail\n"); + return 0; + } + + state = sf_disconnect(handle); + if(state < 0) + { + ERR("sf_disconnect fail\n"); + return 0; + } + + if(vconf_get_int(LCD_TYPE_KEY, &lcd_type) != 0) + lcd_type = 0; + + atan_value = atan2(base_data_values->values[1],base_data_values->values[0]); + + acc_theta = (int)(atan_value * (RADIAN_VALUE) + 270)%360; + + raw_z = (double)(base_data_values->values[2]/(0.004 * 9.81)); + + if ( raw_z > 250 ) { + norm_z = 1.0; + } + else if ( raw_z < -250 ) { + norm_z = -1.0; + } + else { + norm_z = ((double)raw_z)/250; + } + acc_pitch = (int)( acos(norm_z) *(RADIAN_VALUE)); + + INFO( "cal value [acc_theta] : %d , [acc_pitch] : %d\n",acc_theta ,acc_pitch); + + if( (acc_pitch>PITCH_MIN) && (acc_pitch= ROTATION_360 - ROTATION_THD && acc_theta <= ROTATION_360 ) || (acc_theta >= ROTATION_0 && acc_theta < ROTATION_0 + ROTATION_THD)) + { + *curr_state = rotation_mode[ROTATION_EVENT_0].rm[lcd_type]; + } + else if(acc_theta >= ROTATION_90 - ROTATION_THD && acc_theta < ROTATION_90 + ROTATION_THD) + { + *curr_state = rotation_mode[ROTATION_EVENT_90].rm[lcd_type]; + } + else if(acc_theta >= ROTATION_180 - ROTATION_THD && acc_theta < ROTATION_180 + ROTATION_THD) + { + *curr_state = rotation_mode[ROTATION_EVENT_180].rm[lcd_type]; + } + else if(acc_theta >= ROTATION_270 - ROTATION_THD && acc_theta < ROTATION_270 + ROTATION_THD) + { + *curr_state = rotation_mode[ROTATION_EVENT_270].rm[lcd_type]; + } + else { + ERR("Wrong acc_theta : %d , cannot detect current state of ACCEL_SENSOR",acc_theta); + *curr_state = rotation_mode[ROTATION_UNKNOWN].rm[lcd_type]; + } + }else { + INFO("Cannot detect current state of ACCEL_SENSOR"); + *curr_state = rotation_mode[ROTATION_UNKNOWN].rm[lcd_type]; + } + + state = 0; + if(base_data_values) + free(base_data_values); + + return state; + +} + +EXTAPI int sf_read_raw_data(sensor_type_t sensor_type , float values[] , size_t *values_size) +{ + return -1; +} +//! End of a file -- 2.7.4