From c1c9dd14ef60e8b3be7e03acb179242628b358d9 Mon Sep 17 00:00:00 2001 From: Jiwan Kim Date: Fri, 24 Feb 2017 11:00:45 +0900 Subject: [PATCH] Initial code sync up from private gerrit Signed-off-by: Jiwan Kim --- AUTHORS | 2 + CMakeLists.txt | 97 +++++++ LICENSE | 204 ++++++++++++++ capi-network-mesh.pc.in | 13 + include/mesh.h | 463 ++++++++++++++++++++++++++++++++ include/mesh_dbus.h | 57 ++++ include/mesh_log.h | 73 +++++ include/mesh_private.h | 87 ++++++ packaging/capi-network-mesh.manifest | 5 + packaging/capi-network-mesh.spec | 68 +++++ src/mesh.c | 280 ++++++++++++++++++++ src/mesh_dbus.c | 501 +++++++++++++++++++++++++++++++++++ src/mesh_internal.c | 58 ++++ test/CMakeLists.txt | 27 ++ test/common.h | 31 +++ test/main.c | 126 +++++++++ test/menu.c | 378 ++++++++++++++++++++++++++ test/menu.h | 121 +++++++++ test/mesh_device.c | 107 ++++++++ test/mesh_network.c | 67 +++++ 20 files changed, 2765 insertions(+) create mode 100644 AUTHORS create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 capi-network-mesh.pc.in create mode 100644 include/mesh.h create mode 100644 include/mesh_dbus.h create mode 100644 include/mesh_log.h create mode 100644 include/mesh_private.h create mode 100644 packaging/capi-network-mesh.manifest create mode 100644 packaging/capi-network-mesh.spec create mode 100644 src/mesh.c create mode 100644 src/mesh_dbus.c create mode 100644 src/mesh_internal.c create mode 100644 test/CMakeLists.txt create mode 100644 test/common.h create mode 100644 test/main.c create mode 100644 test/menu.c create mode 100644 test/menu.h create mode 100644 test/mesh_device.c create mode 100644 test/mesh_network.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..718b74f --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Saerome Kim +Jiwan Kim diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7b910e9 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,97 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(fw_name "capi-network-mesh") + +PROJECT(${fw_name}) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + +SET(LIB ${LIB_PATH}) +SET(LIBDIR ${PREFIX}/${LIB_PATH}) + +SET(INC_DIR include) +INCLUDE_DIRECTORIES(${INC_DIR}) + +SET(dependents "dlog capi-base-common capi-system-info glib-2.0 gio-2.0") +SET(pc_dependents "capi-base-common") + +INCLUDE(FindPkgConfig) +pkg_check_modules(${fw_name} REQUIRED ${dependents} ${APPFW_REQUIRED_PKGS}) +FOREACH(flag ${${fw_name}_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Werror -fvisibility=hidden") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") + +IF("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET") +ENDIF("${ARCH}" STREQUAL "arm") + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DTIZEN_DEBUG") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIBDIR}") + +aux_source_directory(src SOURCES) +ADD_LIBRARY(${fw_name} SHARED ${SOURCES}) + +TARGET_LINK_LIBRARIES(${fw_name} ${${fw_name}_LDFLAGS}) + +SET_TARGET_PROPERTIES(${fw_name} + PROPERTIES + VERSION ${FULLVER} + SOVERSION ${MAJORVER} + CLEAN_DIRECT_OUTPUT 1 +) + +INSTALL(TARGETS ${fw_name} DESTINATION ${LIB}) +INSTALL( + DIRECTORY ${INC_DIR}/ DESTINATION include/network + FILES_MATCHING + PATTERN "mesh_*.h" EXCLUDE + PATTERN "${INC_DIR}/*.h" + ) + +SET(PC_NAME ${fw_name}) +SET(PC_REQUIRED ${pc_dependents}) +SET(PC_LDFLAGS -l${fw_name}) + +CONFIGURE_FILE( + ${fw_name}.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc + @ONLY +) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION ${LIB}/pkgconfig) + +ADD_SUBDIRECTORY(test) + +IF(UNIX) + +ADD_CUSTOM_TARGET (distclean @echo cleaning for source distribution) +ADD_CUSTOM_COMMAND( + DEPENDS clean + COMMENT "distribution clean" + COMMAND find + ARGS . + -not -name config.cmake -and \( + -name tester.c -or + -name Testing -or + -name CMakeFiles -or + -name cmake.depends -or + -name cmake.check_depends -or + -name CMakeCache.txt -or + -name cmake.check_cache -or + -name *.cmake -or + -name Makefile -or + -name core -or + -name core.* -or + -name gmon.out -or + -name install_manifest.txt -or + -name *.pc -or + -name *~ \) + | grep -v TC | xargs rm -rf + TARGET distclean + VERBATIM +) + +ENDIF(UNIX) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d45e772 --- /dev/null +++ b/LICENSE @@ -0,0 +1,204 @@ +Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/capi-network-mesh.pc.in b/capi-network-mesh.pc.in new file mode 100644 index 0000000..737aa72 --- /dev/null +++ b/capi-network-mesh.pc.in @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=/usr +libdir=@LIBDIR@ +includedir=/usr/include/network + +Name: @PC_NAME@ +Description: @PACKAGE_DESCRIPTION@ +Version: @VERSION@ +Requires: @PC_REQUIRED@ +Libs: -L${libdir} @PC_LDFLAGS@ +Cflags: -I${includedir}/network diff --git a/include/mesh.h b/include/mesh.h new file mode 100644 index 0000000..f237e88 --- /dev/null +++ b/include/mesh.h @@ -0,0 +1,463 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __TIZEN_MESH_H__ +#define __TIZEN_MESH_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file mesh.h + */ + +/** +* @addtogroup CAPI_NETWORK_MESH_MODULE +* @{ +*/ + +/** + * @brief The mesh handle. + * @since_tizen 4.0 +*/ +typedef void *mesh_h; + +/*********************************************************************** + TEMP +***********************************************************************/ +#ifndef TIZEN_ERROR_MESH +#define TIZEN_ERROR_MESH -0x02F60000 +#endif + +/** + * @brief Enumeration for the Mesh error type. + * @since_tizen 4.0 + */ +typedef enum { + MESH_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ + MESH_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + MESH_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory error */ + MESH_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION, /**< Invalid operation */ + MESH_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED = TIZEN_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED, /**< Address family not supported */ + MESH_ERROR_NOW_IN_PROGRESS = TIZEN_ERROR_NOW_IN_PROGRESS, /**< Now in progress */ + MESH_ERROR_OPERATION_FAILED = TIZEN_ERROR_MESH|0x01, /**< Operation failed */ + MESH_ERROR_OPERATION_ABORTED = TIZEN_ERROR_MESH|0x02, /**< Operation is aborted */ + MESH_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission Denied */ + MESH_ERROR_IO_ERROR = TIZEN_ERROR_IO_ERROR, /**< DBus error */ + MESH_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED /**< Not Supported */ +} mesh_error_e; + +/** + * @brief Events for mesh_event_cb + * + * @since_tizen 4.0 + */ +typedef enum { + MESH_EVENT_ENABLED = 0x00, /**< This event is received after enabling mesh network service */ + MESH_EVENT_SCAN_DONE = 0x01, /**< This event comes from coming mesh network scan completed */ + MESH_EVENT_STATION_JOINED = 0x02, /**< This event takes place when new mesh station joined */ + MESH_EVENT_STATION_DISJOINED = 0x03, /**< This event takes place when new mesh station dis-joined */ +} mesh_event_e; + +/** +* @} +*/ + + +/** +* @addtogroup CAPI_NETWORK_MESH_MONITOR_MODULE +* @{ +*/ + +/** + * @brief Enumeration for the state of the Mesh network. + * @since_tizen 4.0 + */ +typedef enum { + MESH_STATE_DEACTIVATED = 0, /**< Mesh network is Deactivated */ + MESH_STATE_ACTIVATED = 1, /**< Mesh network is activated */ +} mesh_state_e; + +/** +* @} +*/ + +/** +* @addtogroup CAPI_NETWORK_MESH_MODULE +* @{ +*/ + +/** + * @brief Initializes Mesh network. + * @since_tizen 4.0 + * @privlevel public + * @privilege %http://tizen.org/privilege/network.get + * @remarks You must release @a handle using mesh_deinitialize(). + * @param[out] handle The mesh handle + * @return @c 0 on success, otherwise negative error value + * @retval #MESH_ERROR_NONE Successful + * @retval #WIFI_MANAGER_ERROR_ALREADY_INITIALIZED Already initialized + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_INVALID_OPERATION Invalid operation + * @retval #MESH_ERROR_OPERATION_FAILED Operation failed + * @retval #MESH_ERROR_PERMISSION_DENIED Permission Denied + * @retval #MESH_ERROR_OUT_OF_MEMORY Out of memory + * @retval #MESH_ERROR_NOT_SUPPORTED Not supported + */ +int mesh_initialize(mesh_h *handle); + +/** + * @brief Deinitializes Mesh network. + * @since_tizen 4.0 + * @param[in] mesh The mesh handle + * @return 0 on success, otherwise negative error value + * @retval #WIFI_MANAGER_ERROR_NONE Successful + * @retval #WIFI_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #WIFI_MANAGER_ERROR_INVALID_OPERATION Invalid operation + * @retval #WIFI_MANAGER_ERROR_OPERATION_FAILED Operation failed + * @retval #WIFI_MANAGER_ERROR_NOT_SUPPORTED Not supported + */ +int mesh_deinitialize(mesh_h handle); + +/** + * @brief Specifies the type of function passed to mesh_enable() + * @details This function can receive events from mesh network. + * ex) enabled state, scan result + * + * @since_tizen 4.0 + * + * @remarks You can receive below events. + * @see #MESH_EVENT_ENABLED + * @see #MESH_EVENT_SCAN_DONE + * @see #MESH_EVENT_STATION_JOINED + * @see #MESH_EVENT_STATION_DISJOINED + * + * @param[out] event_type The event identification + * @param[out] param parameter data pointer + * + * @pre The callback must be registered with mesh_enable() + * + * @see mesh_enable() + */ +typedef void (*mesh_event_cb)(mesh_event_e event_type, void* param); + +/** + * @brief Enable the mesh service. + * @details All this function to start mesh service + * + * @since_tizen 4.0 + * + * @remarks You must free all resources of the mesh by calling mesh_deinitialize() + * if mesh service is no longer needed. + * + * @param[in] handle The mesh handle + * @param[in] interface The interface name of mesh network + * @param[in] event_handler The event handler + * + * @return 0 on success, otherwise a negative error value. + * @retval #MESH_ERROR_NONE Successful + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_IO_ERROR Unexpected d-bus error + * + * @see mesh_initialize() + * @see mesh_deinitialize() + * @see mesh_event_cb() + * @see mesh_disable() + * + */ +int mesh_enable(mesh_h handle, const char* interface, mesh_event_cb event_handler); + +/** + * @brief disable the mesh service. + * @details all this function to stop mesh service + * + * @since_tizen 4.0 + * + * @param[in] handle The mesh handle + * + * @remarks You must free all resources of the mesh by calling mesh_deinitialize() + * if mesh service is no longer needed. + * + * + * @return 0 on success, otherwise a negative error value. + * @retval #MESH_ERROR_NONE Successful + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_IO_ERROR Unexpected d-bus error + * + * @see mesh_initialize() + * @see mesh_deinitialize() + * @see mesh_enable() + * + */ +int mesh_disable(mesh_h handle); + +/** + * @brief Scan the mesh network. + * @details Scan all mesh network to get network state. + * + * @since_tizen 4.0 + * + * @param[in] handle The mesh handle + * + * + * @return 0 on success, otherwise a negative error value. + * @retval #MESH_ERROR_NONE Successful + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_IO_ERROR Unexpected d-bus error + * + * @see mesh_initialize() + * @see mesh_deinitialize() + * @see mesh_enable() + * + */ +int mesh_scan(mesh_h handle); + +/** + * @brief Scan for the specific mesh network. + * @details Scan specific SSID and channel to get network state. + * + * @since_tizen 4.0 + * + * @param[in] handle The mesh handle + * @param[in] ssid Specific SSID to scan + * @param[in] channel The channel number to scan + * + * + * @return 0 on success, otherwise a negative error value. + * @retval #MESH_ERROR_NONE Successful + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_IO_ERROR Unexpected d-bus error + * + * @see mesh_initialize() + * @see mesh_deinitialize() + * + */ +int mesh_specific_scan(mesh_h handle, const char* ssid, int channel); + +/** + * @brief Cancel scanning for the mesh network. + * @details Stop scanning process of mesh network. + * + * @since_tizen 4.0 + * + * @param[in] handle The mesh handle + * + * + * @return 0 on success, otherwise a negative error value. + * @retval #MESH_ERROR_NONE Successful + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_IO_ERROR Unexpected d-bus error + * + * @see mesh_initialize() + * @see mesh_deinitialize() + * @see mesh_scan() + * + */ +int mesh_cancel_scan(mesh_h handle); + +/** + * @brief Get information of all connected stations. + * @details Get information about all stations present in the currently connected mesh network. + * + * @since_tizen 4.0 + * + * @param[in] handle The mesh handle + * + * + * @return 0 on success, otherwise a negative error value. + * @retval #MESH_ERROR_NONE Successful + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_IO_ERROR Unexpected d-bus error + * + * @see mesh_initialize() + * @see mesh_deinitialize() + * + */ +int mesh_get_station_info(mesh_h handle); + +/** + * @brief Get information of all mesh paths. + * @details Get information about all mesh paths present in the currently connected mesh network. + * + * @since_tizen 4.0 + * + * @param[in] handle The mesh handle + * + * + * @return 0 on success, otherwise a negative error value. + * @retval #MESH_ERROR_NONE Successful + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_IO_ERROR Unexpected d-bus error + * + * @see mesh_initialize() + * @see mesh_deinitialize() + * + */ +int mesh_get_mpath_info(mesh_h handle); + +/** + * @brief Join into specific mesh network. + * @details Join into specific mesh network with given SSID. + * + * @since_tizen 4.0 + * + * @param[in] handle The mesh handle + * @param[in] ssid Specific SSID to scan + * + * + * @return 0 on success, otherwise a negative error value. + * @retval #MESH_ERROR_NONE Successful + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_IO_ERROR Unexpected d-bus error + * + * @see mesh_initialize() + * @see mesh_deinitialize() + * @see mesh_is_joined() + * @see mesh_disjoin() + * + */ +int mesh_join(mesh_h handle, const char* ssid); + +/** + * @brief Get the mesh connection state. + * @details Check if current device is joined mesh network. + * + * @since_tizen 4.0 + * + * @param[in] handle The mesh handle + * @param[in] is_joined The state of mesh network connection. + * + * + * @return 0 on success, otherwise a negative error value. + * @retval #MESH_ERROR_NONE Successful + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_IO_ERROR Unexpected d-bus error + * + * @see mesh_initialize() + * @see mesh_deinitialize() + * @see mesh_join() + * + */ +int mesh_is_joined(mesh_h handle, int is_joined); + +/** + * @brief Disconnect from joined mesh network. + * @details Disconnect mesh network connection from current mesh network. + * + * @since_tizen 4.0 + * + * @param[in] handle The mesh handle + * + * + * @return 0 on success, otherwise a negative error value. + * @retval #MESH_ERROR_NONE Successful + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_IO_ERROR Unexpected d-bus error + * + * @see mesh_initialize() + * @see mesh_deinitialize() + * @see mesh_join() + * @see mesh_is_joined() + * + */ +int mesh_disjoin(mesh_h handle); + +/** + * @brief Set AP setting with given parameters. + * @details Set SoftAP parameters to use configured AP settings. + * + * @since_tizen 4.0 + * + * @param[in] handle The mesh handle + * @param[in] ssid SSID for SoftAP + * @param[in] key The key for SoftAP + * @param[in] mode SoftAP mode + * @param[in] channel The channel number + * @param[in] visibility The visibility of SoftAP + * @param[in] max_stations Max acceptable station number. + * @param[in] security Security type of SoftAP + * + * + * @return 0 on success, otherwise a negative error value. + * @retval #MESH_ERROR_NONE Successful + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_IO_ERROR Unexpected d-bus error + * + * @see mesh_initialize() + * @see mesh_deinitialize() + * + */ +int mesh_load_softap_settings(mesh_h handle, const char* ssid, + const char* key, const char* mode, + int channel, int visibility, + int max_stations, int security); + +/** + * @brief Start bridging for mesh network. + * @details For mesh gate, network bridging is required to communicate with external network. + * + * @since_tizen 4.0 + * + * @param[in] handle The mesh handle + * @param[in] interface The interface name of bridge. + * @param[in] mode Mode + * + * + * @return 0 on success, otherwise a negative error value. + * @retval #MESH_ERROR_NONE Successful + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_IO_ERROR Unexpected d-bus error + * + * @see mesh_initialize() + * @see mesh_deinitialize() + * @see mesh_stop_bridge() + * + */ +int mesh_start_bridge(mesh_h handle, const char* interface, int mode); + +/** + * @brief Stop bridging for mesh network. + * @details For mesh gate, network bridging is required to communicate with external network. + * + * @since_tizen 4.0 + * + * @param[in] handle The mesh handle + * + * + * @return 0 on success, otherwise a negative error value. + * @retval #MESH_ERROR_NONE Successful + * @retval #MESH_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MESH_ERROR_IO_ERROR Unexpected d-bus error + * + * @see mesh_initialize() + * @see mesh_deinitialize() + * @see mesh_start_bridge() + * + */ +int mesh_stop_bridge(mesh_h handle); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_MESH_H__ */ diff --git a/include/mesh_dbus.h b/include/mesh_dbus.h new file mode 100644 index 0000000..70d4fc3 --- /dev/null +++ b/include/mesh_dbus.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __MESH_DBUS_H__ +#define __MESH_DBUS_H__ + +#include "mesh.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MESH_SERVER_NAME "net.mesh" +#define MESH_OBJECT_PATH "/net/mesh" + +#define MESH_SERVICE_INTERFACE "net.mesh" + +#define MESH_DBUS_PROXY_TIMEOUT ((9.5 + 2) * 1000) /**< default timeout for GDBus */ + +int _mesh_dbus_start(mesh_h m); +int _mesh_dbus_stop(mesh_h m); + +int _mesh_enable(mesh_h handle, const char* interface, mesh_event_cb event_handler); +int _mesh_disable(mesh_h handle); +int _mesh_scan(mesh_h handle); +int _mesh_specific_scan(mesh_h handle, const char* ssid, int channel); +int _mesh_cancel_scan(mesh_h handle); +int _mesh_get_station_info(mesh_h handle); +int _mesh_get_mpath_info(mesh_h handle); +int _mesh_join(mesh_h handle, const char* ssid); +int _mesh_is_joined(mesh_h handle, int is_joined); +int _mesh_disjoin(mesh_h handle); +int _mesh_load_softap_settings(mesh_h handle, const char* ssid, + const char* key, const char* mode, + int channel, int visibility, + int max_stations, int security); +int _mesh_start_bridge(mesh_h handle, const char* interface, int mode); +int _mesh_stop_bridge(mesh_h handle); + +#ifdef __cplusplus +} +#endif + +#endif /** __MESH_DBUS_H__ */ diff --git a/include/mesh_log.h b/include/mesh_log.h new file mode 100644 index 0000000..3006544 --- /dev/null +++ b/include/mesh_log.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __CAPI_MESH_LOG_H__ +#define __CAPI_MESH_LOG_H__ + +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "CAPI_MESH" + +#define RET_IF(expr) \ + do { \ + if (expr) { \ + LOGE("(%s)", #expr); \ + return; \ + }\ + } while(0) + +#define RETV_IF(expr, val) \ + do {\ + if (expr) { \ + LOGE("(%s)", #expr); \ + return (val); \ + } \ + } while(0) + +#define RETM_IF(expr, fmt, arg...) \ + do {\ + if (expr) { \ + LOGE(fmt, ##arg); \ + return; \ + }\ + } while(0) + +#define RETVM_IF(expr, val, fmt, arg...) \ + do {\ + if (expr) { \ + LOGE(fmt, ##arg); \ + return (val); \ + } \ + } while(0) + +#define ERR_IF(expr) \ + do { \ + if (expr) { \ + LOGE("(%s)", #expr); \ + } \ + } while (0) + +#define WARN_IF(expr, fmt, arg...) \ + do { \ + if (expr) { \ + LOGW(fmt, ##arg); \ + } \ + } while (0) + +#endif /* __CAPI_MESH_LOG_H__ */ diff --git a/include/mesh_private.h b/include/mesh_private.h new file mode 100644 index 0000000..1822506 --- /dev/null +++ b/include/mesh_private.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __CAPI_MESH_PRIVATE_H__ +#define __CAPI_MESH_PRIVATE_H__ + +#include +#include +#include + +#include "mesh.h" + +#define MESH_FEATURE "http://tizen.org/feature/network.mesh" + +#define CHECK_INPUT_PARAMETER(arg) \ + if (arg == NULL) { \ + LOGE("INVALID_PARAMETER"); \ + return MESH_ERROR_INVALID_PARAMETER; \ + } + +#if 0 +#define CHECK_FEATURE_SUPPORTED(feature_name) { \ + bool mesh_supported = FALSE; \ + if (!system_info_get_platform_bool(feature_name, &mesh_supported)) { \ + if (mesh_supported == FALSE) { \ + LOGE("mesh feature is disabled"); \ + return MESH_ERROR_NOT_SUPPORTED; \ + } \ + } else { \ + LOGE("Error - Feature getting from System Info"); \ + return MESH_ERROR_OPERATION_FAILED; \ + } \ +} +#else +#define CHECK_FEATURE_SUPPORTED(feature_name) { \ + LOGE("Should be check !"); \ + } +#endif + +/** + * Enumeration for the Mesh internal error types. + */ +typedef enum { + MESH_ITNL_ERR_NONE = 0x0, + + MESH_ITNL_ERR_UNKNOWN = -0xFF, /**< Unknown error */ + + MESH_ITNL_ERR_ALREADY_REGISTERED = -0xF0, /**< Application is already registered */ + MESH_ITNL_ERR_OUT_OF_MEMORY = -0xF1, /**< Out of memory */ + MESH_ITNL_ERR_OPERATION_FAILED = -0xF2, /**< Operation failed */ + MESH_ITNL_ERR_NOT_SUPPORTED = -0xF3, /**< Not Supported */ + MESH_ITNL_ERR_INVALID_PARAM = -0xF4, /** Invalid value of API parameter */ + MESH_ITNL_ERR_IO_ERROR = -0xF5, /** DBus error */ +} mesh_internal_err_e; + +struct mesh_handle { + gpointer dbus_connection; + GCancellable *ca; + mesh_event_cb event_handler; +/* TODO: Below members are related with event callback + * Need to be considered + */ +#if 0 + char *path; + GHashTable *evt_list; + + GHashTable *cache_property; + guint prop_callback_evt_id; +#endif +} mesh_handle_s; + +const char* _mesh_internal_error_to_string(mesh_internal_err_e err); + +#endif /* __CAPI_MESH_PRIVATE_H__ */ diff --git a/packaging/capi-network-mesh.manifest b/packaging/capi-network-mesh.manifest new file mode 100644 index 0000000..97e8c31 --- /dev/null +++ b/packaging/capi-network-mesh.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/capi-network-mesh.spec b/packaging/capi-network-mesh.spec new file mode 100644 index 0000000..4ea0a38 --- /dev/null +++ b/packaging/capi-network-mesh.spec @@ -0,0 +1,68 @@ +%define major 0 +%define minor 1 +%define patchlevel 1 + +Name: capi-network-mesh +Version: %{major}.%{minor}.%{patchlevel} +Release: 1 +License: Apache-2.0 +Summary: Mesh Core API +Group: System/Libraries +Source0: %{name}-%{version}.tar.gz +Source1001: %{name}.manifest +BuildRequires: cmake +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(gio-2.0) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(capi-base-common) +BuildRequires: pkgconfig(capi-system-info) +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +%description +Mesh network Core API library + +%package devel +Summary: Mesh Core API +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +Mesh Core API library (development library) + +%prep +%setup -q +cp %{SOURCE1001} . + +%build +MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \ + -DLIB_INSTALL_DIR=%{_libdir} \ + -DBIN_INSTALL_DIR=%{_bindir} \ + -DLIB_PATH=%{_lib} \ + -DFULLVER=%{version} \ + -DMAJORVER=${MAJORVER} + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +mkdir -p %{buildroot}%{_datadir}/license +cp LICENSE %{buildroot}%{_datadir}/license/%{name} + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%manifest capi-network-mesh.manifest +%attr(644,-,-) %{_libdir}/libcapi-network-mesh.so.* +/usr/share/license/capi-network-mesh +%{_bindir}/mesh_test + +%files devel +%{_includedir}/network/*.h +%{_libdir}/pkgconfig/*.pc +%{_libdir}/libcapi-network-mesh.so diff --git a/src/mesh.c b/src/mesh.c new file mode 100644 index 0000000..c5f89be --- /dev/null +++ b/src/mesh.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "mesh.h" +#include "mesh_log.h" +#include "mesh_private.h" +#include "mesh_dbus.h" + +/** + * Mesh network CAPI + */ +EXPORT_API int mesh_initialize(mesh_h *mesh) +{ + int rv; + struct mesh_handle* handle; + + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + if (mesh == NULL) { + LOGE("Invalid parameter"); //LCOV_EXCL_LINE + return MESH_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE + } + +#if 0 + rv = _mesh_init(); + if (rv != MESH_ERROR_NONE) { + LOGE("Failed to initialize mesh network");//LCOV_EXCL_LINE + return rv; //LCOV_EXCL_LINE + } +#endif + +#if !GLIB_CHECK_VERSION(2, 35, 0) + g_type_init(); +#endif + + handle = g_new0(struct mesh_handle, 1); + if (NULL == handle) { + LOGE("Failed to create handle"); + return MESH_ERROR_OUT_OF_MEMORY; + } + *mesh = handle; + + rv = _mesh_dbus_start(*mesh); + if (rv != MESH_ERROR_NONE) { + LOGD("D-Bus init: [%s](0x%X)", _mesh_internal_error_to_string(rv), rv); + } + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_deinitialize(mesh_h mesh) +{ + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + _mesh_dbus_stop(mesh); + + LOGI("Destroy handle: %p", mesh); + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_enable(mesh_h handle, const char* interface, + mesh_event_cb event_handler) +{ + int rv = 0; + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + RETV_IF(NULL == interface, MESH_ERROR_INVALID_PARAMETER); + RETV_IF(NULL == handle, MESH_ERROR_INVALID_PARAMETER); + + rv = _mesh_enable(handle, interface, event_handler); + if (rv == MESH_ITNL_ERR_IO_ERROR) { + return MESH_ERROR_IO_ERROR; + } + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_disable(mesh_h handle) +{ + int rv = 0; + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + RETV_IF(NULL == handle, MESH_ERROR_INVALID_PARAMETER); + + rv = _mesh_disable(handle); + if (rv == MESH_ITNL_ERR_IO_ERROR) { + return MESH_ERROR_IO_ERROR; + } + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_scan(mesh_h handle) +{ + int rv = 0; + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + RETV_IF(NULL == handle, MESH_ERROR_INVALID_PARAMETER); + + rv = _mesh_scan(handle); + if (rv == MESH_ITNL_ERR_IO_ERROR) { + return MESH_ERROR_IO_ERROR; + } + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_specific_scan(mesh_h handle, const char* ssid, int channel) +{ + int rv = 0; + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + RETV_IF(NULL == ssid, MESH_ERROR_INVALID_PARAMETER); + RETV_IF(NULL == handle, MESH_ERROR_INVALID_PARAMETER); + + rv = _mesh_specific_scan(handle, ssid, channel); + if (rv == MESH_ITNL_ERR_IO_ERROR) { + return MESH_ERROR_IO_ERROR; + } + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_cancel_scan(mesh_h handle) +{ + int rv = 0; + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + RETV_IF(NULL == handle, MESH_ERROR_INVALID_PARAMETER); + + rv = _mesh_cancel_scan(handle); + if (rv == MESH_ITNL_ERR_IO_ERROR) { + return MESH_ERROR_IO_ERROR; + } + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_get_station_info(mesh_h handle) +{ + int rv = 0; + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + RETV_IF(NULL == handle, MESH_ERROR_INVALID_PARAMETER); + + rv = _mesh_get_station_info(handle); + if (rv == MESH_ITNL_ERR_IO_ERROR) { + return MESH_ERROR_IO_ERROR; + } + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_get_mpath_info(mesh_h handle) +{ + int rv = 0; + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + RETV_IF(NULL == handle, MESH_ERROR_INVALID_PARAMETER); + + rv = _mesh_get_station_info(handle); + if (rv == MESH_ITNL_ERR_IO_ERROR) { + return MESH_ERROR_IO_ERROR; + } + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_join(mesh_h handle, const char* ssid) +{ + int rv = 0; + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + RETV_IF(NULL == ssid, MESH_ERROR_INVALID_PARAMETER); + RETV_IF(NULL == handle, MESH_ERROR_INVALID_PARAMETER); + + rv = _mesh_join(handle, ssid); + if (rv == MESH_ITNL_ERR_IO_ERROR) { + return MESH_ERROR_IO_ERROR; + } + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_is_joined(mesh_h handle, int is_joined) +{ + int rv = 0; + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + RETV_IF(NULL == handle, MESH_ERROR_INVALID_PARAMETER); + + rv = _mesh_is_joined(handle, is_joined); + if (rv == MESH_ITNL_ERR_IO_ERROR) { + return MESH_ERROR_IO_ERROR; + } + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_disjoin(mesh_h handle) +{ + int rv = 0; + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + RETV_IF(NULL == handle, MESH_ERROR_INVALID_PARAMETER); + + rv = _mesh_disjoin(handle); + if (rv == MESH_ITNL_ERR_IO_ERROR) { + return MESH_ERROR_IO_ERROR; + } + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_load_softap_settings(mesh_h handle, const char* ssid, + const char* key, const char* mode, + int channel, int visibility, + int max_stations, int security) +{ + int rv = 0; + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + RETV_IF(NULL == handle, MESH_ERROR_INVALID_PARAMETER); + RETV_IF(NULL == ssid, MESH_ERROR_INVALID_PARAMETER); + RETV_IF(NULL == key, MESH_ERROR_INVALID_PARAMETER); + RETV_IF(NULL == mode, MESH_ERROR_INVALID_PARAMETER); + + rv = _mesh_load_softap_settings(handle, ssid, key, mode, channel, + visibility, max_stations, security); + if (rv == MESH_ITNL_ERR_IO_ERROR) { + return MESH_ERROR_IO_ERROR; + } + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_start_bridge(mesh_h handle, const char* interface, int mode) +{ + int rv = 0; + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + RETV_IF(NULL == interface, MESH_ERROR_INVALID_PARAMETER); + RETV_IF(NULL == handle, MESH_ERROR_INVALID_PARAMETER); + + rv = _mesh_start_bridge(handle, interface, mode); + if (rv == MESH_ITNL_ERR_IO_ERROR) { + return MESH_ERROR_IO_ERROR; + } + + return MESH_ERROR_NONE; +} + +EXPORT_API int mesh_stop_bridge(mesh_h handle) +{ + int rv = 0; + CHECK_FEATURE_SUPPORTED(MESH_FEATURE); + + RETV_IF(NULL == handle, MESH_ERROR_INVALID_PARAMETER); + + rv = _mesh_stop_bridge(handle); + if (rv == MESH_ITNL_ERR_IO_ERROR) { + return MESH_ERROR_IO_ERROR; + } + + return MESH_ERROR_NONE; +} diff --git a/src/mesh_dbus.c b/src/mesh_dbus.c new file mode 100644 index 0000000..ea01a38 --- /dev/null +++ b/src/mesh_dbus.c @@ -0,0 +1,501 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "mesh.h" +#include "mesh_log.h" +#include "mesh_dbus.h" +#include "mesh_private.h" + +static GDBusProxy *_gproxy_mesh_service = NULL; + +static int _mesh_close_gdbus_call(mesh_h m); + +static GDBusProxy *_proxy_get_mesh_service(struct mesh_handle *handle) +{ + GDBusProxy *proxy = NULL; + RETVM_IF(NULL == handle, NULL, "Connection Object is invalid"); + + if (NULL == _gproxy_mesh_service) { + proxy = g_dbus_proxy_new_sync(handle->dbus_connection, + G_DBUS_PROXY_FLAGS_NONE, NULL, + MESH_SERVER_NAME, + MESH_OBJECT_PATH, + MESH_SERVICE_INTERFACE, + NULL, NULL); + } else + proxy = _gproxy_mesh_service; + + return proxy; +} + +static void _dbus_name_owner_notify(GObject *object, GParamSpec *pspec, + gpointer *user_data) +{ + GDBusProxy *proxy = G_DBUS_PROXY(object); + gchar *name_owner = g_dbus_proxy_get_name_owner(proxy); + mesh_h handle = (mesh_h)user_data; + + if (name_owner) + return; + + LOGE("name_owner is not exists !"); + _mesh_close_gdbus_call(handle); +} + +static int _mesh_create_gdbus_call(mesh_h handle) +{ + int id; + GError *error = NULL; + struct mesh_handle *h = handle; + + if (NULL == h) + return MESH_ITNL_ERR_INVALID_PARAM; + + if (h->dbus_connection != NULL) + return MESH_ITNL_ERR_ALREADY_REGISTERED; + + h->dbus_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (h->dbus_connection == NULL) { + if (error != NULL) { + LOGE("Failed to connect to the D-BUS daemon [%s]", error->message); + g_error_free(error); + } + return MESH_ITNL_ERR_UNKNOWN; + } + + id = g_signal_connect(h->dbus_connection, "notify::g-name-owner", + G_CALLBACK(_dbus_name_owner_notify), h); + if (0 == id) { + LOGE("g_signal_connect() Fail"); + g_object_unref(h->dbus_connection); + h->dbus_connection = NULL; + return MESH_ITNL_ERR_IO_ERROR; + } + + return MESH_ITNL_ERR_NONE; +} + +static int _mesh_close_gdbus_call(mesh_h handle) +{ + struct mesh_handle *h = handle; + + /* CHECK: is connection ref count required? */ + g_object_unref(h->dbus_connection); + h->dbus_connection = NULL; + + return MESH_ITNL_ERR_NONE; +} + +int _mesh_dbus_start(mesh_h handle) +{ + struct mesh_handle *h = handle; + int rv; + + rv = _mesh_create_gdbus_call(handle); + if (MESH_ITNL_ERR_NONE != rv) + return rv; + + h->ca = g_cancellable_new(); + + /* Create all proxies here */ + _gproxy_mesh_service = _proxy_get_mesh_service(h); + RETVM_IF(NULL == _gproxy_mesh_service, + MESH_ITNL_ERR_IO_ERROR, "Couldn't get _gproxy_mesh_service"); + g_dbus_proxy_set_default_timeout( + G_DBUS_PROXY(_gproxy_mesh_service), MESH_DBUS_PROXY_TIMEOUT); + + return MESH_ITNL_ERR_NONE; +} + +int _mesh_dbus_stop(mesh_h handle) +{ + struct mesh_handle *h = handle; + int rv; + + if (NULL == h) + return MESH_ITNL_ERR_INVALID_PARAM; + + /* Unref all proxies here */ + if (_gproxy_mesh_service) { + g_object_unref(_gproxy_mesh_service); + _gproxy_mesh_service = NULL; + } + + g_cancellable_cancel(h->ca); + g_object_unref(h->ca); + h->ca = NULL; + + rv = _mesh_close_gdbus_call(handle); + return rv; +} + +int _mesh_enable(mesh_h handle, const char* interface, mesh_event_cb event_handler) +{ + GVariant *variant = NULL; + unsigned int result; + GError *error = NULL; + struct mesh_handle *h = handle; + + RETV_IF(NULL == h->dbus_connection, MESH_ITNL_ERR_IO_ERROR); + RETV_IF(NULL == _gproxy_mesh_service, MESH_ITNL_ERR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_mesh_service, "enable", + g_variant_new("(s)", interface), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + if (variant) { + g_variant_get(variant, "(u)", &result); + LOGD("Mesh enabled status 0x%x", result); + } else if (error) { + LOGE("Failed DBus call [%s]", error->message); + g_error_free(error); + return MESH_ITNL_ERR_IO_ERROR; + } + h->event_handler = event_handler; + + return MESH_ITNL_ERR_NONE; +} + +int _mesh_disable(mesh_h handle) +{ + GVariant *variant = NULL; + unsigned int result; + GError *error = NULL; + struct mesh_handle *h = handle; + + RETV_IF(NULL == h->dbus_connection, MESH_ITNL_ERR_IO_ERROR); + RETV_IF(NULL == _gproxy_mesh_service, MESH_ITNL_ERR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_mesh_service, "disable", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + if (variant) { + g_variant_get(variant, "(u)", &result); + LOGD("Mesh disabled status 0x%x", result); + } else if (error) { + LOGE("Failed DBus call [%s]", error->message); + g_error_free(error); + return MESH_ITNL_ERR_IO_ERROR; + } + h->event_handler = NULL; + + return MESH_ITNL_ERR_NONE; +} + +int _mesh_scan(mesh_h handle) +{ + GVariant *variant = NULL; + unsigned int result; + GError *error = NULL; + struct mesh_handle *h = handle; + + RETV_IF(NULL == h->dbus_connection, MESH_ITNL_ERR_IO_ERROR); + RETV_IF(NULL == _gproxy_mesh_service, MESH_ITNL_ERR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_mesh_service, "scan", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + if (variant) { + g_variant_get(variant, "(u)", &result); + LOGD("Mesh scan status 0x%x", result); + } else if (error) { + LOGE("Failed DBus call [%s]", error->message); + g_error_free(error); + return MESH_ITNL_ERR_IO_ERROR; + } + + return MESH_ITNL_ERR_NONE; +} + +int _mesh_specific_scan(mesh_h handle, const char* ssid, int channel) +{ + GVariant *variant = NULL; + unsigned int result; + GError *error = NULL; + struct mesh_handle *h = handle; + + RETV_IF(NULL == h->dbus_connection, MESH_ITNL_ERR_IO_ERROR); + RETV_IF(NULL == _gproxy_mesh_service, MESH_ITNL_ERR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_mesh_service, "specific_scan", + g_variant_new("(si)", ssid, channel), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + if (variant) { + g_variant_get(variant, "(u)", &result); + LOGD("Mesh specific scan status 0x%x", result); + } else if (error) { + LOGE("Failed DBus call [%s]", error->message); + g_error_free(error); + return MESH_ITNL_ERR_IO_ERROR; + } + + return MESH_ITNL_ERR_NONE; +} + +int _mesh_cancel_scan(mesh_h handle) +{ + GVariant *variant = NULL; + unsigned int result; + GError *error = NULL; + struct mesh_handle *h = handle; + + RETV_IF(NULL == h->dbus_connection, MESH_ITNL_ERR_IO_ERROR); + RETV_IF(NULL == _gproxy_mesh_service, MESH_ITNL_ERR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_mesh_service, "cancle_scan", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + if (variant) { + g_variant_get(variant, "(u)", &result); + LOGD("Mesh scan canceling status 0x%x", result); + } else if (error) { + LOGE("Failed DBus call [%s]", error->message); + g_error_free(error); + return MESH_ITNL_ERR_IO_ERROR; + } + + return MESH_ITNL_ERR_NONE; +} + +int _mesh_get_station_info(mesh_h handle) +{ + GVariant *variant = NULL; +// unsigned int result; + GError *error = NULL; + struct mesh_handle *h = handle; + + RETV_IF(NULL == h->dbus_connection, MESH_ITNL_ERR_IO_ERROR); + RETV_IF(NULL == _gproxy_mesh_service, MESH_ITNL_ERR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_mesh_service, "get_station_info", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + if (variant) { + //g_variant_get(variant, "(a(a{sv})", &result); + /* TODO: handle station list here */ + } else if (error) { + LOGE("Failed DBus call [%s]", error->message); + g_error_free(error); + return MESH_ITNL_ERR_IO_ERROR; + } + + return MESH_ITNL_ERR_NONE; +} + +int _mesh_get_mpath_info(mesh_h handle) +{ + GVariant *variant = NULL; +// unsigned int result; + GError *error = NULL; + struct mesh_handle *h = handle; + + RETV_IF(NULL == h->dbus_connection, MESH_ITNL_ERR_IO_ERROR); + RETV_IF(NULL == _gproxy_mesh_service, MESH_ITNL_ERR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_mesh_service, "get_mpath_info", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + if (variant) { + //g_variant_get(variant, "(a(a{sv})", &result); + /* TODO: handle mpath list here */ + } else if (error) { + LOGE("Failed DBus call [%s]", error->message); + g_error_free(error); + return MESH_ITNL_ERR_IO_ERROR; + } + + return MESH_ITNL_ERR_NONE; +} + +int _mesh_join(mesh_h handle, const char* ssid) +{ + GVariant *variant = NULL; + unsigned int result; + GError *error = NULL; + struct mesh_handle *h = handle; + + RETV_IF(NULL == h->dbus_connection, MESH_ITNL_ERR_IO_ERROR); + RETV_IF(NULL == _gproxy_mesh_service, MESH_ITNL_ERR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_mesh_service, "join", + g_variant_new("(s)", ssid), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + if (variant) { + g_variant_get(variant, "(u)", &result); + LOGD("Mesh join status 0x%x", result); + } else if (error) { + LOGE("Failed DBus call [%s]", error->message); + g_error_free(error); + return MESH_ITNL_ERR_IO_ERROR; + } + + return MESH_ITNL_ERR_NONE; +} + +/* TODO: Parameter verification required */ +int _mesh_is_joined(mesh_h handle, int is_joined) +{ + GVariant *variant = NULL; + unsigned int result; + GError *error = NULL; + struct mesh_handle *h = handle; + + RETV_IF(NULL == h->dbus_connection, MESH_ITNL_ERR_IO_ERROR); + RETV_IF(NULL == _gproxy_mesh_service, MESH_ITNL_ERR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_mesh_service, "is_joined", + g_variant_new("(b)", (is_joined==0) ? FALSE : TRUE), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + if (variant) { + g_variant_get(variant, "(u)", &result); + LOGD("Mesh is_joined status 0x%x", result); + } else if (error) { + LOGE("Failed DBus call [%s]", error->message); + g_error_free(error); + return MESH_ITNL_ERR_IO_ERROR; + } + + return MESH_ITNL_ERR_NONE; +} + +int _mesh_disjoin(mesh_h handle) +{ + GVariant *variant = NULL; + unsigned int result; + GError *error = NULL; + struct mesh_handle *h = handle; + + RETV_IF(NULL == h->dbus_connection, MESH_ITNL_ERR_IO_ERROR); + RETV_IF(NULL == _gproxy_mesh_service, MESH_ITNL_ERR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_mesh_service, "disjoin", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + if (variant) { + g_variant_get(variant, "(u)", &result); + LOGD("Mesh disjoin status 0x%x", result); + } else if (error) { + LOGE("Failed DBus call [%s]", error->message); + g_error_free(error); + return MESH_ITNL_ERR_IO_ERROR; + } + + return MESH_ITNL_ERR_NONE; +} + +int _mesh_load_softap_settings(mesh_h handle, const char* ssid, + const char* key, const char* mode, + int channel, int visibility, + int max_stations, int security) +{ + GVariant *variant = NULL; + unsigned int result; + GError *error = NULL; + struct mesh_handle *h = handle; + + RETV_IF(NULL == h->dbus_connection, MESH_ITNL_ERR_IO_ERROR); + RETV_IF(NULL == _gproxy_mesh_service, MESH_ITNL_ERR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_mesh_service, "load_softap_settings", + g_variant_new("(sssiiii)", ssid, key, mode, + channel, visibility, max_stations, security), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + if (variant) { + g_variant_get(variant, "(u)", &result); + LOGD("Mesh softap setting status 0x%x", result); + } else if (error) { + LOGE("Failed DBus call [%s]", error->message); + g_error_free(error); + return MESH_ITNL_ERR_IO_ERROR; + } + + return MESH_ITNL_ERR_NONE; +} + +int _mesh_start_bridge(mesh_h handle, const char* interface, int mode) +{ + GVariant *variant = NULL; + unsigned int result; + GError *error = NULL; + struct mesh_handle *h = handle; + + RETV_IF(NULL == h->dbus_connection, MESH_ITNL_ERR_IO_ERROR); + RETV_IF(NULL == _gproxy_mesh_service, MESH_ITNL_ERR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_mesh_service, "start_bridge", + g_variant_new("(is)", mode, interface), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + if (variant) { + g_variant_get(variant, "(u)", &result); + LOGD("Mesh bridge start status 0x%x", result); + } else if (error) { + LOGE("Failed DBus call [%s]", error->message); + g_error_free(error); + return MESH_ITNL_ERR_IO_ERROR; + } + + return MESH_ITNL_ERR_NONE; +} + +int _mesh_stop_bridge(mesh_h handle) +{ + GVariant *variant = NULL; + unsigned int result; + GError *error = NULL; + struct mesh_handle *h = handle; + + RETV_IF(NULL == h->dbus_connection, MESH_ITNL_ERR_IO_ERROR); + RETV_IF(NULL == _gproxy_mesh_service, MESH_ITNL_ERR_IO_ERROR); + + variant = g_dbus_proxy_call_sync(_gproxy_mesh_service, "stop_bridge", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + if (variant) { + g_variant_get(variant, "(u)", &result); + LOGD("Mesh bridge stop status 0x%x", result); + } else if (error) { + LOGE("Failed DBus call [%s]", error->message); + g_error_free(error); + return MESH_ITNL_ERR_IO_ERROR; + } + + return MESH_ITNL_ERR_NONE; +} diff --git a/src/mesh_internal.c b/src/mesh_internal.c new file mode 100644 index 0000000..cc2789d --- /dev/null +++ b/src/mesh_internal.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "mesh.h" +#include "mesh_log.h" +#include "mesh_private.h" + +/** + * Mesh network CAPI + */ + +int _mesh_init(mesh_h *mesh) +{ + /* Initialize mesh network here. + If initialized already, does nothing */ + + return MESH_ERROR_NONE; +} + +int _mesh_deinit(mesh_h mesh) +{ + /* De-initialize mesh network here. + If De-initialized already, does nothing */ + + return MESH_ERROR_NONE; +} + +#define CASE_TO_STR(x) case x: return #x; + +const char* _mesh_internal_error_to_string(mesh_internal_err_e err) +{ + switch (err) { + /* CHECK: List all enum values here */ + CASE_TO_STR(MESH_ITNL_ERR_NONE) + CASE_TO_STR(MESH_ITNL_ERR_UNKNOWN) + CASE_TO_STR(MESH_ITNL_ERR_ALREADY_REGISTERED) + CASE_TO_STR(MESH_ITNL_ERR_OUT_OF_MEMORY) + CASE_TO_STR(MESH_ITNL_ERR_OPERATION_FAILED) + CASE_TO_STR(MESH_ITNL_ERR_NOT_SUPPORTED) + CASE_TO_STR(MESH_ITNL_ERR_INVALID_PARAM) + CASE_TO_STR(MESH_ITNL_ERR_IO_ERROR) + default : + return "MESH_ITNL_ERROR_UNKNOWN"; + } +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..56b9833 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,27 @@ +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +SET(test "mesh_test") + +INCLUDE(FindPkgConfig) +pkg_check_modules(${test} REQUIRED dlog glib-2.0 gio-2.0) +LINK_DIRECTORIES(${${test}_pkgs_LIBRARY_DIR}) + +FOREACH(flag ${${test}_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +#SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall") +# Temporary debug info enable : -O0 -g +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall") +SET(CMAKE_EXE_LINKER_FLAGS "-lpthread") + +SET(NEW_SOURCES + main.c + menu.c + mesh_device.c + mesh_network.c +) + +# mesh test tool +ADD_EXECUTABLE(mesh_test ${NEW_SOURCES}) +TARGET_LINK_LIBRARIES(mesh_test ${${fw_name}_LDFLAGS} ${pkgs_LDFLAGS} capi-network-mesh) +INSTALL(TARGETS mesh_test DESTINATION ${BIN_INSTALL_DIR}) diff --git a/test/common.h b/test/common.h new file mode 100644 index 0000000..a044877 --- /dev/null +++ b/test/common.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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 __COMMON_H__ +#define __COMMON_H__ + +#include + +__BEGIN_DECLS + +#define CASE_TO_STR(x) case x: return #x; + +const char* mesh_error_to_string(mesh_error_e err); + +__END_DECLS + +#endif /** __COMMON_H__ */ diff --git a/test/main.c b/test/main.c new file mode 100644 index 0000000..14d0116 --- /dev/null +++ b/test/main.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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 "menu.h" +#include "common.h" + +mesh_h mesh = NULL; + +extern struct menu_data menu_mesh_device[]; +extern struct menu_data menu_mesh_network[]; + +const char* mesh_error_to_string(mesh_error_e err) +{ + switch (err) { + /* CHECK: List all enum values here */ + CASE_TO_STR(MESH_ERROR_NONE) + CASE_TO_STR(MESH_ERROR_INVALID_PARAMETER) + CASE_TO_STR(MESH_ERROR_OUT_OF_MEMORY) + CASE_TO_STR(MESH_ERROR_INVALID_OPERATION) + CASE_TO_STR(MESH_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED) + CASE_TO_STR(MESH_ERROR_NOW_IN_PROGRESS) + CASE_TO_STR(MESH_ERROR_OPERATION_FAILED) + CASE_TO_STR(MESH_ERROR_OPERATION_ABORTED) + CASE_TO_STR(MESH_ERROR_PERMISSION_DENIED) + CASE_TO_STR(MESH_ERROR_NOT_SUPPORTED) + default : + return "MESH_ERROR_UNKNOWN"; + } +} + +void event_cb(mesh_event_e event_type, void* param) +{ + +} + +static int __init_func(MManager *mm, struct menu_data *menu) +{ + int ret = -1; + + ret = mesh_initialize(&mesh); + if (ret != 0) { + msg("Failed to initialize mesh: [%s(0x%X)]", + mesh_error_to_string(ret), ret); + return RET_FAILURE; + } + + return RET_SUCCESS; +} + +static struct menu_data menu_main[] = { + { "1", "Device", menu_mesh_device, NULL, NULL }, + { "2", "Mesh network", menu_mesh_network, NULL, NULL }, + { NULL, NULL, }, +}; + +static gboolean __create_init_menu(struct menu_data init_menu[1]) +{ + init_menu[0].key = "1"; + init_menu[0].title = "Init"; + init_menu[0].sub_menu = menu_main; + init_menu[0].callback = __init_func; + init_menu[0].data = NULL; + + return TRUE; +} + +int main(int arg, char **argv) +{ + GMainLoop *mainloop = NULL; + GIOChannel *channel = g_io_channel_unix_new(STDIN_FILENO); + MManager *manager; + struct menu_data init_menu[1+1] = { {NULL, NULL, } }; + +#if !GLIB_CHECK_VERSION(2, 35, 0) + g_type_init(); +#endif + mainloop = g_main_loop_new(NULL, FALSE); + + msg(""); + msg("* Mesh Test application "); + msg("* Build On: %s %s", __DATE__, __TIME__); + + if (__create_init_menu(init_menu) == FALSE) + goto OUT; + + manager = menu_manager_new(init_menu, mainloop); + if (!manager) + goto OUT; + + menu_manager_run(manager); + + g_io_add_watch(channel, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL), + on_menu_manager_keyboard, manager); + g_main_loop_run(mainloop); + +OUT: + g_main_loop_unref(mainloop); + msg("******* Bye bye *******"); + + return 0; +} diff --git a/test/menu.c b/test/menu.c new file mode 100644 index 0000000..7dfab33 --- /dev/null +++ b/test/menu.c @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#include "menu.h" + +#define DEFAULT_MENU_MENU "m" +#define DEFAULT_MENU_PREV "p" +#define DEFAULT_MENU_QUIT "q" +#define DEFAULT_MENU_NONE "-" +#define TAB_SPACE " " + +struct menu_manager { + GQueue *stack; + GQueue *title_stack; + + struct menu_data *menu; + + char *buf; + + void *user_data; + GMainLoop *mainloop; +}; + + +char key_buffer[MENU_DATA_SIZE]; +int flag_pid_display = 1; + +extern unsigned short dest_addr16; +extern struct menu_data menu_sel_device[]; + +static void _show_prompt(void) +{ + msgn("(%5d) >> ", get_tid()); +} + +static void _show_reserved_menu(void) +{ + msg(ANSI_COLOR_DARKGRAY HR_SINGLE2 ANSI_COLOR_NORMAL); + msg(ANSI_COLOR_DARKGRAY HR_SINGLE2 ANSI_COLOR_NORMAL); + msg(ANSI_COLOR_DARKGRAY " [ " ANSI_COLOR_NORMAL "%s" ANSI_COLOR_DARKGRAY + " ] " ANSI_COLOR_NORMAL "Previous menu " , DEFAULT_MENU_PREV); + msg(ANSI_COLOR_DARKGRAY " [ " ANSI_COLOR_NORMAL "%s" ANSI_COLOR_DARKGRAY + " ] " ANSI_COLOR_NORMAL "Show Menu " , DEFAULT_MENU_MENU); + msg(ANSI_COLOR_DARKGRAY " [ " ANSI_COLOR_NORMAL "%s" ANSI_COLOR_DARKGRAY + " ] " ANSI_COLOR_NORMAL "Quit " , DEFAULT_MENU_QUIT); +} + +static void _show_input_ok(void) +{ + msg("OK."); +} + +static void _show_menu(MManager *m, struct menu_data menu[]) +{ + int i = 0; + int len = 0; + struct menu_data *item; + char title_buf[256] = { 0, }; + + if (!menu) + return; + + msg(""); + msg(HR_DOUBLE); + + len = g_queue_get_length(m->title_stack); + msgn(ANSI_COLOR_YELLOW " Main"); + if (len > 0) { + for (i = 0; i < len; i++) { + msgn(ANSI_COLOR_NORMAL " >> " ANSI_COLOR_YELLOW "%s", + (char *)g_queue_peek_nth(m->title_stack, i)); + } + } + msg(ANSI_COLOR_NORMAL); + msg(HR_SINGLE); + + hide_pid(); + i = 0; + + while (1) { + item = menu + i; + if (item->key == NULL) + break; + + if (!g_strcmp0(item->key, "-")) { + msgn(" "); + } else if (!g_strcmp0(item->key, "_")) { + msg(ANSI_COLOR_DARKGRAY HR_SINGLE2 ANSI_COLOR_NORMAL); + + if (item->callback) + item->callback(m, item); + + i++; + + continue; + } else if (!g_strcmp0(item->key, "*")) { + msg(" %s", item->title); + if (item->callback) + item->callback(m, item); + } else { + msgn(ANSI_COLOR_DARKGRAY " [" ANSI_COLOR_NORMAL "%3s" + ANSI_COLOR_DARKGRAY "] " ANSI_COLOR_NORMAL, item->key); + } + + memset(title_buf, 0, 256); + if (item->title) { + snprintf(title_buf, MAX_TITLE, "%s", item->title); + + if (strlen(item->title) >= MAX_TITLE) { + title_buf[MAX_TITLE - 2] = '.'; + title_buf[MAX_TITLE - 1] = '.'; + } + } + + if (item->data) { + msg("%s " ANSI_COLOR_LIGHTBLUE "(%s)" ANSI_COLOR_NORMAL, + title_buf, item->data); + } else if (!g_strcmp0(item->key, "*")) { + /* none */ + } else { + msg("%s", title_buf); + } + + if (item->sub_menu) + msg("\e[1A\e[%dC >", (int)POS_MORE); + + i++; + } + + show_pid(); + + _show_reserved_menu(); + + msg(HR_DOUBLE); + + _show_prompt(); +} + +static void _show_item_data_input_msg(struct menu_data *item) +{ + msg(""); + msg(HR_DOUBLE); + msg(" Input [%s] data ", item->title); + msg(HR_SINGLE); + msg(" current = [%s]", item->data); + msgn(" new >> "); +} + +static void _move_menu(MManager *mm, struct menu_data menu[], char *key) +{ + struct menu_data *item; + int i = 0; + + if (!mm->menu) + return; + + if (!g_strcmp0(DEFAULT_MENU_PREV, key)) { + if (g_queue_get_length(mm->stack) > 0) { + mm->menu = g_queue_pop_tail(mm->stack); + g_queue_pop_tail(mm->title_stack); + } + + _show_menu(mm, mm->menu); + mm->buf = key_buffer; + + return; + } else if (!g_strcmp0(DEFAULT_MENU_MENU, key)) { + _show_menu(mm, mm->menu); + return; + } else if (!g_strcmp0(DEFAULT_MENU_QUIT, key)) { + g_main_loop_quit(mm->mainloop); + return; + } else if (!g_strcmp0(DEFAULT_MENU_NONE, key)) { + _show_prompt(); + return; + } + + while (1) { + int ret = RET_SUCCESS; + item = menu + i; + if (item->key == NULL) + break; + + if (!g_strcmp0(item->key, key)) { + if (item->callback) { + ret = item->callback(mm, item); + _show_prompt(); + } + + if (RET_SUCCESS == ret) { + if (item->sub_menu) { + g_queue_push_tail(mm->stack, mm->menu); + g_queue_push_tail(mm->title_stack, (gpointer *)item->title); + + mm->menu = item->sub_menu; + _show_menu(mm, mm->menu); + mm->buf = key_buffer; + } + + if (item->data) { + _show_item_data_input_msg(item); + mm->buf = item->data; + } + } + + return; + } + + i++; + } + + _show_prompt(); +} + +MManager *menu_manager_new(struct menu_data items[], GMainLoop *mainloop) +{ + MManager *mm; + + mm = calloc(sizeof(struct menu_manager), 1); + if (!mm) + return NULL; + + mm->stack = g_queue_new(); + mm->title_stack = g_queue_new(); + mm->menu = items; + mm->mainloop = mainloop; + + return mm; +} + +int menu_manager_run(MManager *mm) +{ + _show_menu(mm, mm->menu); + + mm->buf = key_buffer; + + return 0; +} + +int menu_manager_set_user_data(MManager *mm, void *user_data) +{ + if (!mm) + return -1; + + mm->user_data = user_data; + + return 0; +} + +void *menu_manager_ref_user_data(MManager *mm) +{ + if (!mm) + return NULL; + + return mm->user_data; +} + +gboolean on_menu_manager_keyboard(GIOChannel *src, GIOCondition con, + gpointer data) +{ + MManager *mm = data; + char local_buf[MENU_DATA_SIZE + 1] = { 0, }; + + if (fgets(local_buf, MENU_DATA_SIZE, stdin) == NULL) + return TRUE; + + if (strlen(local_buf) > 0) { + if (local_buf[strlen(local_buf) - 1] == '\n') + local_buf[strlen(local_buf) - 1] = '\0'; + } + + if (mm->buf == key_buffer) { + if (strlen(local_buf) < 1) { + _show_prompt(); + return TRUE; + } + + _move_menu(mm, mm->menu, local_buf); + } else { + if (mm->buf) { + memset(mm->buf, 0, MENU_DATA_SIZE); + memcpy(mm->buf, local_buf, MENU_DATA_SIZE); + _show_input_ok(); + } + mm->buf = key_buffer; + _move_menu(mm, mm->menu, (char *)DEFAULT_MENU_MENU); + } + + return TRUE; +} + +pid_t get_tid() +{ + return syscall(__NR_gettid); +} + +void hide_pid() +{ + flag_pid_display = 0; +} + +void show_pid() +{ + flag_pid_display = 1; +} + +int is_pid_show() +{ + return flag_pid_display; +} + +static void _hex_dump(const char *pad, int size, const void *data) +{ + char buf[255] = {0, }; + char hex[4] = {0, }; + int i; + unsigned char *p; + + if (size <= 0) { + msg("%sno data", pad); + return; + } + p = (unsigned char *)data; + + snprintf(buf, 255, "%s%04X: ", pad, 0); + for (i = 0; i < size; i++) { + snprintf(hex, 4, "%02X ", p[i]); + strncat(buf, hex, strlen(hex)); + + if ((i + 1) % 8 == 0) { + if ((i + 1) % 16 == 0) { + msg("%s", buf); + memset(buf, 0, 255); + snprintf(buf, 255, "%s%04X: ", pad, i + 1); + } else { + strncat(buf, TAB_SPACE, strlen(TAB_SPACE)); + } + } + } + + msg("%s", buf); +} + +void menu_print_dump(int data_len, void *data) +{ + if (!data) + return; + + msg(""); + msg(" \tlen=%d", data_len); + _hex_dump(" ", data_len, data); + + msg(""); +} diff --git a/test/menu.h b/test/menu.h new file mode 100644 index 0000000..95c4453 --- /dev/null +++ b/test/menu.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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 __MENU_H__ +#define __MENU_H__ + +__BEGIN_DECLS + +#define ANSI_COLOR_NORMAL "\e[0m" + +#define ANSI_COLOR_BLACK "\e[0;30m" +#define ANSI_COLOR_RED "\e[0;31m" +#define ANSI_COLOR_GREEN "\e[0;32m" +#define ANSI_COLOR_BROWN "\e[0;33m" +#define ANSI_COLOR_BLUE "\e[0;34m" +#define ANSI_COLOR_MAGENTA "\e[0;35m" +#define ANSI_COLOR_CYAN "\e[0;36m" +#define ANSI_COLOR_LIGHTGRAY "\e[0;37m" + +#define ANSI_COLOR_DARKGRAY "\e[1;30m" +#define ANSI_COLOR_LIGHTRED "\e[1;31m" +#define ANSI_COLOR_LIGHTGREEN "\e[1;32m" +#define ANSI_COLOR_YELLOW "\e[1;33m" +#define ANSI_COLOR_LIGHTBLUE "\e[1;34m" +#define ANSI_COLOR_LIGHTMAGENTA "\e[1;35m" +#define ANSI_COLOR_LIGHTCYAN "\e[1;36m" +#define ANSI_COLOR_WHITE "\e[1;37m" + + +#define msg(fmt,args...) do { fprintf(stdout, fmt "\n", ##args); \ + fflush(stdout); } while (0) +#define msgn(fmt,args...) do { fprintf(stdout, fmt, ##args); \ + fflush(stdout); } while (0) + +/* Bold (green) */ +#define msgb(fmt,args...) do { fprintf(stdout, ANSI_COLOR_LIGHTGREEN fmt \ + ANSI_COLOR_NORMAL "\n", ##args); fflush(stdout); } while (0) + +/* Property message */ +#define msgp(fmt,args...) do { fprintf(stdout, ANSI_COLOR_LIGHTMAGENTA fmt \ + ANSI_COLOR_NORMAL "\n", ##args); fflush(stdout); } while (0) + +#define msgt(n,fmt,args...) do { fprintf(stdout, "\e[%dC" fmt "\n", \ + 3 + ((n) * 2), ##args); fflush(stdout); } while (0) + +#define pmsg(fmt,args...) do { \ + if (is_pid_show()) { fprintf(stdout, "(%5d) ", get_tid()); } \ + fprintf(stdout, fmt "\n", ##args); fflush(stdout); } while (0) + +#define pmsgb(fmt,args...) do { \ + if (is_pid_show()) { fprintf(stdout, "(%5d) ", get_tid()); } \ + fprintf(stdout, ANSI_COLOR_LIGHTGREEN fmt \ + ANSI_COLOR_NORMAL "\n", ##args); fflush(stdout); } while (0) + +#define pmsgt(n,fmt,args...) do { \ + if (is_pid_show()) { fprintf(stdout, "(%5d) ", get_tid()); } \ + fprintf(stdout, "\e[%dC" fmt "\n", \ + 3 + ((n) * 2), ##args); fflush(stdout); } while (0) + +#define MENU_DATA_SIZE 255 + + + +/* + * Horizontal Line - width: 65 + * .12345678901234567890123456789012345678901234567890. + */ +#define HR_SINGLE "----------------------------------------" \ + "-------------------------" +#define HR_DOUBLE "========================================" \ + "=========================" +#define HR_SINGLE2 " ---------------------------------------" \ + "------------------------ " + +#define MAX_WIDTH strlen (HR_SINGLE) +#define MAX_TITLE ((MAX_WIDTH) - 10) +#define POS_MORE ((MAX_WIDTH) - 3) +#define RET_SUCCESS 0 +#define RET_FAILURE -1 + +typedef struct menu_manager MManager; + +struct menu_data { + const char *key; + const char *title; + struct menu_data *sub_menu; + int (*callback)(MManager *mm, struct menu_data *menu); + char *data; +}; + +MManager* menu_manager_new(struct menu_data items[], GMainLoop *mainloop); +int menu_manager_run(MManager *mm); +int menu_manager_set_user_data(MManager *mm, void *user_data); +void* menu_manager_ref_user_data(MManager *mm); + +gboolean on_menu_manager_keyboard(GIOChannel *src, GIOCondition con, + gpointer data); + +pid_t get_tid (); +void hide_pid (); +void show_pid (); +int is_pid_show (); +void menu_print_dump(int data_len, void *data); + +__END_DECLS + +#endif diff --git a/test/mesh_device.c b/test/mesh_device.c new file mode 100644 index 0000000..5196672 --- /dev/null +++ b/test/mesh_device.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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 "menu.h" +#include "common.h" + +extern mesh_h mesh; +extern void event_cb(mesh_event_e event_type, void* param); + +static char data_mesh_interface[MENU_DATA_SIZE + 1] = "mesh0"; + +static int run_mesh_create(MManager *mm, struct menu_data *menu) +{ + int ret; + msg("create"); + + ret = mesh_initialize(&mesh); + if (ret != 0) { + msg("Failed to initialize mesh: [%s(0x%X)]", + mesh_error_to_string(ret), ret); + return RET_FAILURE; + } + + return RET_SUCCESS; +} + +static int run_mesh_destroy(MManager *mm, struct menu_data *menu) +{ + int ret; + msg("destroy"); + + ret = mesh_deinitialize(mesh); + if (ret != 0) { + msg("Failed to de-initialize mesh: [%s(0x%X)]", + mesh_error_to_string(ret), ret); + return RET_FAILURE; + } + + return RET_SUCCESS; +} + +static int run_mesh_enable(MManager *mm, struct menu_data *menu) +{ + int ret; + msg("enable"); + + ret = mesh_enable(mesh, data_mesh_interface, event_cb); + if (ret != 0) { + msg("Failed to enable mesh network: [%s(0x%X)]", + mesh_error_to_string(ret), ret); + return RET_FAILURE; + } + + return RET_SUCCESS; +} + +static int run_mesh_disable(MManager *mm, struct menu_data *menu) +{ + int ret; + msg("disable"); + + ret = mesh_disable(mesh); + if (ret != 0) { + msg("Failed to disable mesh network: [%s(0x%X)]", + mesh_error_to_string(ret), ret); + return RET_FAILURE; + } + + return RET_SUCCESS; +} + +static struct menu_data menu_mesh_enable[] = { + { "1", "interface", NULL, NULL, data_mesh_interface }, + { "2", "enable", NULL, run_mesh_enable, NULL }, + { NULL, NULL, }, +}; + +struct menu_data menu_mesh_device[] = { + { "1", "create", NULL, run_mesh_create, NULL }, + { "2", "destroy", NULL, run_mesh_destroy, NULL }, + { "3", "enable", menu_mesh_enable, NULL, NULL }, + { "4", "disable", NULL, run_mesh_disable, NULL }, + { NULL, NULL, }, +}; diff --git a/test/mesh_network.c b/test/mesh_network.c new file mode 100644 index 0000000..7c96bf3 --- /dev/null +++ b/test/mesh_network.c @@ -0,0 +1,67 @@ + +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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 "menu.h" +#include "common.h" + +static int run_mesh_scan(MManager *mm, struct menu_data *menu) +{ + msg("Scan"); + return RET_SUCCESS; +} + +static int run_mesh_specific_scan(MManager *mm, struct menu_data *menu) +{ + msg("Specific scan"); + return RET_SUCCESS; +} + +static int run_mesh_cancel_scan(MManager *mm, struct menu_data *menu) +{ + msg("Cancel scan"); + return RET_SUCCESS; +} + +static int run_mesh_join(MManager *mm, struct menu_data *menu) +{ + msg("Join"); + return RET_SUCCESS; +} + +static int run_mesh_disjoin(MManager *mm, struct menu_data *menu) +{ + msg("Disjoin"); + return RET_SUCCESS; +} + +struct menu_data menu_mesh_network[] = { + { "1", "Scan", NULL, run_mesh_scan, NULL }, + { "2", "Specific scan", NULL, run_mesh_specific_scan, NULL }, + { "3", "cancel scan", NULL, run_mesh_cancel_scan, NULL }, + { "4", "Join", NULL, run_mesh_join, NULL }, + { "5", "Disjoin", NULL, run_mesh_disjoin, NULL }, + { NULL, NULL, }, +}; -- 2.7.4