Initial commit for Bluetooth plugin for HTML5 UI 11/17711/1 accepted/tizen/ivi/20140308.072222 accepted/tizen/ivi/20140321.174123 accepted/tizen/ivi/20140321.175244 accepted/tizen/ivi/20140321.180914 accepted/tizen/ivi/panda/20140321.020405 accepted/tizen/ivi/panda/20140321.210853 accepted/tizen/ivi/release/20140315.041628 submit/tizen/20140307.222226 submit/tizen/20140320.035024 submit/tizen/20140321.003050 submit/tizen/20140321.171938 submit/tizen/20140321.180538 submit/tizen_ivi_release/20140315.041346
authorbrianjjones <brian.j.jones@intel.com>
Fri, 7 Mar 2014 21:37:04 +0000 (13:37 -0800)
committerbrianjjones <brian.j.jones@intel.com>
Fri, 7 Mar 2014 21:38:41 +0000 (13:38 -0800)
Change-Id: Iaa8eef1bce585d17884e75b9e9f4fb43bcda4534

50 files changed:
CMakeLists.txt [new file with mode: 0644]
config.dtd [new file with mode: 0644]
packaging/wrt-plugins-tizen-bt.changes [new file with mode: 0644]
packaging/wrt-plugins-tizen-bt.spec [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-bt.pc.in [new file with mode: 0644]
src/BluetoothAdapter.cpp [new file with mode: 0644]
src/BluetoothAdapter.h [new file with mode: 0644]
src/BluetoothCallbackUtil.cpp [new file with mode: 0644]
src/BluetoothCallbackUtil.h [new file with mode: 0644]
src/BluetoothClass.cpp [new file with mode: 0644]
src/BluetoothClass.h [new file with mode: 0644]
src/BluetoothClassDeviceMajor.cpp [new file with mode: 0644]
src/BluetoothClassDeviceMajor.h [new file with mode: 0644]
src/BluetoothClassDeviceMinor.cpp [new file with mode: 0644]
src/BluetoothClassDeviceMinor.h [new file with mode: 0644]
src/BluetoothClassDeviceService.cpp [new file with mode: 0644]
src/BluetoothClassDeviceService.h [new file with mode: 0644]
src/BluetoothDevice.cpp [new file with mode: 0644]
src/BluetoothDevice.h [new file with mode: 0644]
src/BluetoothServiceHandler.cpp [new file with mode: 0644]
src/BluetoothServiceHandler.h [new file with mode: 0644]
src/BluetoothSocket.cpp [new file with mode: 0644]
src/BluetoothSocket.h [new file with mode: 0644]
src/CMakeLists.txt [new file with mode: 0644]
src/JSBluetoothAdapter.cpp [new file with mode: 0644]
src/JSBluetoothAdapter.h [new file with mode: 0644]
src/JSBluetoothClass.cpp [new file with mode: 0644]
src/JSBluetoothClass.h [new file with mode: 0644]
src/JSBluetoothClassDeviceMajor.cpp [new file with mode: 0644]
src/JSBluetoothClassDeviceMajor.h [new file with mode: 0644]
src/JSBluetoothClassDeviceMinor.cpp [new file with mode: 0644]
src/JSBluetoothClassDeviceMinor.h [new file with mode: 0644]
src/JSBluetoothClassDeviceService.cpp [new file with mode: 0644]
src/JSBluetoothClassDeviceService.h [new file with mode: 0644]
src/JSBluetoothDevice.cpp [new file with mode: 0644]
src/JSBluetoothDevice.h [new file with mode: 0644]
src/JSBluetoothManager.cpp [new file with mode: 0644]
src/JSBluetoothManager.h [new file with mode: 0644]
src/JSBluetoothServiceHandler.cpp [new file with mode: 0644]
src/JSBluetoothServiceHandler.h [new file with mode: 0644]
src/JSBluetoothSocket.cpp [new file with mode: 0644]
src/JSBluetoothSocket.h [new file with mode: 0644]
src/config.xml [new file with mode: 0644]
src/plugin_config.cpp [new file with mode: 0644]
src/plugin_config.h [new file with mode: 0644]
src/plugin_initializer.cpp [new file with mode: 0644]
src/utils.cpp [new file with mode: 0644]
src/utils.h [new file with mode: 0644]
tizen.bt.h [new file with mode: 0644]
wrt-plugins-tizen-bt.manifest [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..20fa9b6
--- /dev/null
@@ -0,0 +1,177 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(wrt-plugins-tizen-bt)
+
+SET(CMAKE_INSTALL_PREFIX "/usr")
+
+# -----------------------------------------------------------------------------
+# Required platform modules
+# -----------------------------------------------------------------------------
+INCLUDE(FindPkgConfig)
+
+PKG_CHECK_MODULES(dpl REQUIRED dpl-efl)
+PKG_CHECK_MODULES(wrt-plugins-types REQUIRED wrt-plugins-types)
+PKG_CHECK_MODULES(wrt-deviceapis-commons-javascript REQUIRED wrt-plugins-commons-javascript)
+PKG_CHECK_MODULES(wrt-plugins-tizen-common REQUIRED wrt-plugins-tizen-common)
+PKG_CHECK_MODULES(json-glib REQUIRED json-glib-1.0)
+PKG_CHECK_MODULES(capi-system-info REQUIRED capi-system-info)
+PKG_CHECK_MODULES(capi-network-bluetooth REQUIRED capi-network-bluetooth)
+
+INCLUDE_DIRECTORIES(
+  ${dpl_INCLUDE_DIRS}
+  ${wrt-plugins-types_INCLUDE_DIRS}
+  ${wrt-deviceapis-commons-javascript_INCLUDE_DIRS}
+  ${wrt-plugins-tizen-common_INCLUDE_DIRS}
+  ${json-glib_INCLUDE_DIRS}
+  ${capi-system-info_INCLUDE_DIRS}
+  ${capi-network-bluetooth_INCLUDE_DIRS}
+  /usr/include/wrt-plugins-tizen/common/TimeTracer
+)
+
+# -----------------------------------------------------------------------------
+# Determine the log option
+# -----------------------------------------------------------------------------
+
+OPTION(DPL_LOG "DPL logs status" ON)
+
+IF(DPL_LOG)
+    MESSAGE(STATUS "Logging enabled for DPL")
+    ADD_DEFINITIONS("-DDPL_LOGS_ENABLED")
+ELSE(DPL_LOG)
+    MESSAGE(STATUS "Logging disabled for DPL")
+ENDIF(DPL_LOG)
+
+# -----------------------------------------------------------------------------
+# Determine the time tracing option
+# -----------------------------------------------------------------------------
+
+OPTION(ENABLE_TIME_TRACER "TIME TRACING" OFF)
+
+IF(ENABLE_TIME_TRACER)
+    MESSAGE(STATUS "Time tracer enabled")
+    ADD_DEFINITIONS("-DENABLE_TIME_TRACER")
+ELSE(ENABLE_TIME_TRACER)
+    MESSAGE(STATUS "Time tracer disabled")
+ENDIF(ENABLE_TIME_TRACER)
+
+# -----------------------------------------------------------------------------
+# Set build type (Release by default)
+# -----------------------------------------------------------------------------
+IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+     SET(CMAKE_BUILD_TYPE Release)
+ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+
+MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
+
+# -----------------------------------------------------------------------------
+# CFlags
+# -----------------------------------------------------------------------------
+SET(CMAKE_C_FLAGS_PROFILING    "-O0 -g -pg")
+SET(CMAKE_CXX_FLAGS_PROFILING  "-O0 -std=c++0x -g -pg")
+SET(CMAKE_C_FLAGS_DEBUG        "-O0 -g")
+SET(CMAKE_CXX_FLAGS_DEBUG      "-O0 -std=c++0x -g")
+SET(CMAKE_C_FLAGS_RELEASE      "-O2 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE    "-O2 -std=c++0x -g")
+ADD_DEFINITIONS("-DCLIENT_IPC_THREAD")
+ADD_DEFINITIONS("-DEXPORT_API=")
+ADD_DEFINITIONS("-Wall")
+ADD_DEFINITIONS("-D_FILE_OFFSET_BITS=64")
+#ADD_DEFINITIONS("-Werror")
+#ADD_DEFINITIONS("-Wextra")
+ADD_DEFINITIONS("-DAPPLICATION_API_BACKWARD_COMPATIBILITY")
+ADD_DEFINITIONS("-std=c++11")
+
+
+# -----------------------------------------------------------------------------
+# Schema of plugin's configuration file
+# -----------------------------------------------------------------------------
+SET(COMMON_CONFIG_DTD ${CMAKE_CURRENT_SOURCE_DIR}/config.dtd)
+SET(COMMON_CONFIG_DTD_DST /usr/etc/tizen-apis)
+INSTALL(FILES ${COMMON_CONFIG_DTD} DESTINATION ${COMMON_CONFIG_DTD_DST})
+
+# -----------------------------------------------------------------------------
+# Global variables
+# -----------------------------------------------------------------------------
+
+SET(DESTINATION_LIB_PREFIX lib/wrt-plugins)
+
+SET(DESTINATION_HEADER_PREFIX include/${PROJECT_NAME})
+
+SET(LIBS_WIDGETDB ${wrt-plugins-widgetdb_LIBRARIES})
+
+# -----------------------------------------------------------------------------
+# Macros for pkgconfig
+# -----------------------------------------------------------------------------
+SET(PKGCONFIG_DIR ${CMAKE_SOURCE_DIR}/pkgconfigs)
+#SET(PKGCONFIG_DIR ${CMAKE_SOURCE_DIR})
+
+MACRO(configure_and_install_pkg PKG_FILE)
+    CONFIGURE_FILE(${PKGCONFIG_DIR}/${PKG_FILE}.in
+               ${PKGCONFIG_DIR}/${PKG_FILE} @ONLY)
+    INSTALL(FILES ${PKGCONFIG_DIR}/${PKG_FILE} DESTINATION lib/pkgconfig)
+ENDMACRO(configure_and_install_pkg)
+
+SET(TARGET_NAME wrt-plugins-tizen-bt)
+SET(DESTINATION_NAME tizen-bt)
+SET(TARGET_IMPL_NAME wrt-plugins-tizen-bt-impl)
+
+configure_and_install_pkg(wrt-plugins-tizen-bt.pc)
+
+SET(CMAKE_INSTALL_RPATH
+       ${CMAKE_INSTALL_RPATH}
+       ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+       ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+        src/BluetoothAdapter.cpp
+        src/BluetoothCallbackUtil.cpp
+        src/BluetoothClass.cpp
+        src/BluetoothClassDeviceMajor.cpp
+        src/BluetoothClassDeviceMinor.cpp
+        src/BluetoothClassDeviceService.cpp
+        src/BluetoothDevice.cpp
+        src/BluetoothServiceHandler.cpp
+        src/BluetoothSocket.cpp
+        src/JSBluetoothAdapter.cpp
+        src/JSBluetoothClass.cpp
+        src/JSBluetoothClassDeviceMajor.cpp
+        src/JSBluetoothClassDeviceMinor.cpp
+        src/JSBluetoothClassDeviceService.cpp
+        src/JSBluetoothDevice.cpp
+        src/JSBluetoothManager.cpp
+        src/JSBluetoothServiceHandler.cpp
+        src/JSBluetoothSocket.cpp
+        src/plugin_config.cpp
+        src/utils.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+        ${dpl_LDFLAGS}
+        ${dpl-event_LDFLAGS}
+        ${wrt-deviceapis-commons-javascript_LDFLAGS}
+       ${wrt-plugins-tizen-common_LDFLAGS}
+        ${json-glib_LDFLAGS}
+        ${capi-system-info_LDFLAGS}
+        ${capi-network-bluetooth_LDFLAGS}
+       -L/usr/lib/wrt-plugins/tizen-tizen/
+)
+
+SET(SRCS
+       src/plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+       ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+       DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/ DESTINATION ${DESTINATION_HEADER_PREFIX}/bt
+       FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
+
diff --git a/config.dtd b/config.dtd
new file mode 100644 (file)
index 0000000..f1a1de4
--- /dev/null
@@ -0,0 +1,32 @@
+<!ELEMENT plugin-properties (library-name, feature-install-uri?,
+  feature-key-cn?, feature-root-cn?,
+  feature-root-fingerprint?, feature-set*, api-feature+) >
+
+<!ELEMENT library-name (#PCDATA)>
+
+<!ELEMENT feature-set (api-feature-ref+)>
+<!ATTLIST feature-set name CDATA #REQUIRED >
+
+<!ELEMENT api-feature-ref EMPTY>
+<!ATTLIST api-feature-ref name CDATA #REQUIRED >
+
+<!ELEMENT api-feature (name, device-capability*, Object*, Function*, Property* )>
+
+<!ELEMENT name (#PCDATA) >
+<!ELEMENT device-capability (#PCDATA )>
+
+<!ELEMENT Object (Function*, Property*)>
+<!ATTLIST Object name CDATA #REQUIRED >
+
+<!ELEMENT Function (#PCDATA )>
+<!ATTLIST Function name CDATA #REQUIRED >
+<!ATTLIST Function restricted CDATA #IMPLIED >
+
+<!ELEMENT Property (#PCDATA )>
+
+
+<!ELEMENT feature-install-uri (#PCDATA)>
+<!ELEMENT feature-key-cn (#PCDATA)>
+<!ELEMENT feature-root-cn (#PCDATA)>
+<!ELEMENT feature-root-fingerprint (#PCDATA)>
+
diff --git a/packaging/wrt-plugins-tizen-bt.changes b/packaging/wrt-plugins-tizen-bt.changes
new file mode 100644 (file)
index 0000000..56db9d4
--- /dev/null
@@ -0,0 +1,3 @@
+* Fri Mar 07 2014 brianjjones <brian.j.jones@intel.com> cd7fd57
+- Initial commit for Bluetooth plugin for HTML5 UI
+
diff --git a/packaging/wrt-plugins-tizen-bt.spec b/packaging/wrt-plugins-tizen-bt.spec
new file mode 100644 (file)
index 0000000..730ccaf
--- /dev/null
@@ -0,0 +1,62 @@
+Name:       wrt-plugins-tizen-bt
+Summary:    JavaScript plugin to access BT for WebRuntime
+Version:    0.8.5
+Release:    1
+Group:      Development/Libraries
+License:    Apache-2.0
+Source0:    %{name}-%{version}.tar.gz
+
+BuildRequires:  pkgconfig(ewebkit2)
+BuildRequires:  pkgconfig(dpl-efl)
+BuildRequires:  pkgconfig(dpl-event-efl)
+BuildRequires:  pkgconfig(wrt-plugins-commons)
+BuildRequires:  pkgconfig(wrt-plugins-commons-javascript)
+BuildRequires:  pkgconfig(capi-system-info)
+BuildRequires:  boost-devel
+BuildRequires:  wrt-plugins-tizen-devel
+BuildRequires:  expat-devel
+BuildRequires:  cmake
+BuildRequires:  gettext-devel
+BuildRequires:  pkgconfig(json-glib-1.0)
+
+%description
+JavaScript plugin to access BT for WebRuntime
+
+%package devel
+Summary:    Wrt-plugins-tizen-bt development headers
+Group:      Development/Libraries
+Requires:   %{name} = %{version}
+
+%description devel
+Wrt-plugins-tizen-bt development headers
+
+%prep
+%setup -q
+
+%build
+
+%define PREFIX "%{_libdir}/wrt-plugins"
+
+export LDFLAGS+="-Wl,--rpath=%{PREFIX} -Wl,--as-needed"
+
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DDPL_LOG="ON" -DENABLE_TIME_TRACER="OFF"
+
+make %{?jobs:-j%jobs} VERBOSE=1
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+%post
+wrt-installer -p
+
+%postun
+
+%files
+%manifest wrt-plugins-tizen-bt.manifest
+%{_libdir}/wrt-plugins/*
+/usr/etc/tizen-apis/*
+
+%files devel
+%{_includedir}/*
+%{_libdir}/pkgconfig/*
diff --git a/pkgconfigs/wrt-plugins-tizen-bt.pc.in b/pkgconfigs/wrt-plugins-tizen-bt.pc.in
new file mode 100644 (file)
index 0000000..2f840cf
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=bt
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: icu-i18n icu-io icu-le icu-lx icu-uc
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
diff --git a/src/BluetoothAdapter.cpp b/src/BluetoothAdapter.cpp
new file mode 100644 (file)
index 0000000..e1a4e8e
--- /dev/null
@@ -0,0 +1,2235 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <pcrecpp.h>
+
+#include <Logger.h>
+#include <JSWebAPIErrorFactory.h>
+#include <system_info.h>
+#include <JSUtil.h>
+
+#include "BluetoothAdapter.h"
+#include "BluetoothCallbackUtil.h"
+#include "JSBluetoothDevice.h"
+#include "JSBluetoothServiceHandler.h"
+#include "JSBluetoothSocket.h"
+#include "GlobalContextManager.h"
+
+// BLUEZ
+#include "utils.h"
+
+#define BLUEZ_PREFIX            "org.bluez"
+#define BLUEZ_SERVICE           BLUEZ_PREFIX
+#define BLUEZ_MANAGER_IFACE     BLUEZ_PREFIX ".Manager"
+#define BLUEZ_ADAPTER_IFACE     BLUEZ_PREFIX ".Adapter"
+#define BLUEZ_DEVICE_IFACE      BLUEZ_PREFIX ".Device"
+#define BLUEZ_AGENT_IFACE       BLUEZ_PREFIX ".Agent"
+
+#define AGENT_PATH              "/org/bluez/agent_pairing"
+#define AGENT_CAPABILITIES      "KeyboardDisplay"
+
+#define AGENT_INTERFACE_XML                                 \
+    "<node>"                                                \
+    "  <interface name='" BLUEZ_AGENT_IFACE "'>"            \
+    "    <method name='Release'>"                           \
+    "    </method>"                                         \
+    "    <method name='Authorize'>"                         \
+    "      <arg type='o' name='device' direction='in'/>"    \
+    "      <arg type='s' name='uuid' direction='in'/>"      \
+    "    </method>"                                         \
+    "    <method name='RequestPinCode'>"                    \
+    "      <arg type='o' name='device' direction='in'/>"    \
+    "      <arg type='s' name='pincode' direction='out'/>"  \
+    "    </method>"                                         \
+    "    <method name='RequestPasskey'>"                    \
+    "      <arg type='o' name='device' direction='in'/>"    \
+    "      <arg type='u' name='passkey' direction='out'/>"  \
+    "    </method>"                                         \
+    "    <method name='DisplayPasskey'>"                    \
+    "      <arg type='o' name='device' direction='in'/>"    \
+    "      <arg type='u' name='passkey' direction='in'/>"   \
+    "    </method>"                                         \
+    "    <method name='DisplayPinCode'>"                    \
+    "      <arg type='o' name='device' direction='in'/>"    \
+    "      <arg type='s' name='pincode' direction='in'/>"   \
+    "    </method>"                                         \
+    "    <method name='RequestConfirmation'>"               \
+    "      <arg type='o' name='device' direction='in'/>"    \
+    "      <arg type='u' name='passkey' direction='in'/>"   \
+    "    </method>"                                         \
+    "    <method name='ConfirmModeChange'>"                 \
+    "      <arg type='s' name='mode' direction='in'/>"      \
+    "    </method>"                                         \
+    "    <method name='Cancel'>"                            \
+    "    </method>"                                         \
+    "  </interface>"                                        \
+    "</node>"
+
+#define PINCODE        "123456"
+#define PASSKEY         123456
+
+#define CONNMAN_PREFIX                     "net.connman"
+#define CONNMAN_SERVICE                    CONNMAN_PREFIX
+#define CONNMAN_MANAGER_IFACE              CONNMAN_PREFIX ".Manager"
+#define CONNMAN_TECHNOLOGY_IFACE           CONNMAN_PREFIX ".Technology"
+// BLUEZ
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+bool BluetoothAdapter::foreachBondedDevicesCB(bt_device_info_s *deviceInfo, void *userData)
+{
+    BluetoothAdapterPtr adapter = static_cast<BluetoothAdapterPtr>(userData);
+    if(!adapter) {
+        LoggerW("userData is NULL");
+        return true;
+    }
+
+    if(deviceInfo == NULL) {
+        LoggerW("deviceInfo is NULL");
+        return true;
+    }
+
+    std::vector<BluetoothDeviceSharedPtr>::iterator iter;
+    for(iter = adapter->knownDevices.begin(); iter != adapter->knownDevices.end(); ++iter) {
+        BluetoothDeviceSharedPtr foundDevice = *iter;
+
+        if(!strcmp(foundDevice->getAddress().c_str(), deviceInfo->remote_address)) {
+            foundDevice->updateInfo(deviceInfo);
+            break;
+        }
+    }
+
+    if(iter == adapter->knownDevices.end()) {
+        BluetoothDeviceSharedPtr device(new BluetoothDevice(deviceInfo));
+        adapter->knownDevices.push_back(device);
+    }
+
+    return true;
+}
+
+void BluetoothAdapter::onSocketConnected(int result, bt_socket_connection_state_e state, bt_socket_connection_s *connection, void *userData)
+{
+    BluetoothAdapterPtr object = static_cast<BluetoothAdapterPtr>(userData);
+    if(!object) {
+        LoggerW("userData is NULL");
+        return;
+    }
+
+    if(!connection) {
+        LoggerW("connection is NULL");
+        return;
+    }
+
+    if(connection->local_role == BT_SOCKET_SERVER) {
+        RegisteredUUIDMapT::iterator iter = object->mRegisteredUUID.find(connection->service_uuid);
+        if(iter == object->mRegisteredUUID.end()) {
+            LoggerW("Connection state is changed unexpectedly");
+            return;
+        }
+
+        if(state == BT_SOCKET_CONNECTED) {  // connected when Server
+            if(result == BT_ERROR_NONE) {
+                // Update BluetoothServiceHandler
+                BluetoothServiceHandlerPtr service = iter->second;
+                service->setConnectionState(true);
+
+                // Call BluetoothServiceHandler.onconnect
+                BluetoothSocketPtr socket = new BluetoothSocket(connection);
+                MultiCallbackUserDataPtr callback = service->getOnConnect();
+                JSContextRef context = callback->getContext();
+                JSObjectRef socketObj = JSBluetoothSocket::createJSObject(context, socket);
+                if(callback)
+                    callback->invokeCallback("onconnect", socketObj);
+
+                // Update mConnectedSocket
+                object->mConnectedSocket.insert(std::pair<int, BluetoothSocketPtr>(connection->socket_fd, socket));
+                bt_socket_set_data_received_cb(onSocketReceivedCB, userData);
+            }
+            else {
+                LoggerW("Establishing a connection failed");
+            }
+            return;
+        }
+        else {  // disconnected when Server
+            if(result == BT_ERROR_NONE) {
+                // Update BluetoothServiceHandler
+                BluetoothServiceHandlerPtr service = iter->second;
+                service->setConnectionState(false);
+
+                // call BluetoothSocket.onclose;
+                ConnectedSocketMapT::iterator i = object->mConnectedSocket.find(connection->socket_fd);
+                if(i == object->mConnectedSocket.end()) {
+                    LoggerW("Unknown connected socket");
+                    return;
+                }
+                //BluetoothSocketSharedPtr socket = i->second;
+                BluetoothSocketPtr socket = i->second;
+                socket->setConnectionState(false);
+                MultiCallbackUserDataPtr callback = socket->getOnClose();
+                if(callback)
+                    callback->invokeCallback("onclose");
+
+                // Update mConnectedSocket
+                object->mConnectedSocket.erase(i);
+            }
+            else {
+                LoggerW("Disconnecting a connection failed");
+            }
+        }
+    }
+    else if(connection->local_role == BT_SOCKET_CLIENT) {
+
+        if(state == BT_SOCKET_CONNECTED) {  // connected when Client
+            std::string remoteAddress(connection->remote_address);
+            ConnReqMultiMapT::iterator iter;
+            do {
+                iter = object->mConnReqMap.find(remoteAddress);
+                if(iter != object->mConnReqMap.end() && !strcmp(iter->second->mUUID.c_str(), connection->service_uuid)) {
+                    break;
+                }
+            } while(iter != object->mConnReqMap.end());
+
+            if(iter == object->mConnReqMap.end()) {
+                LoggerW("Connection state is changed unexpectedly");
+                return;
+            }
+
+            MultiCallbackUserDataPtr callback = static_cast<MultiCallbackUserDataPtr>(iter->second->mUserData);
+
+            if(result == BT_ERROR_NONE) {
+                // Update mConnectedSocket
+                BluetoothSocketPtr socket = new BluetoothSocket(connection);
+                object->mConnectedSocket.insert(std::pair<int, BluetoothSocketPtr>(connection->socket_fd, socket));
+                bt_socket_set_data_received_cb(onSocketReceivedCB, userData);
+
+                // Call successcallback of connectToServiceByUUID
+                JSContextRef context = callback->getContext();
+                JSObjectRef socketObj = JSBluetoothSocket::createJSObject(context, socket);
+                if(callback)
+                    callback->invokeCallback("success", socketObj);
+
+                // Update mConnReqMap
+                object->mConnReqMap.erase(iter);
+            }
+            else {
+                // Call errorcallback of connectToServiceByUUID
+                JSContextRef context = callback->getContext();
+                NotFoundException error("Not found");
+                if(callback)
+                    callback->invokeCallback("error", JSWebAPIErrorFactory::makeErrorObject(context, error));
+
+                // Update mConnReqMap
+                object->mConnReqMap.erase(iter);
+            }
+            return;
+        }
+        else {  // disconnected when Client
+            if(result == BT_ERROR_NONE) {
+                // call BluetoothSocket.onclose;
+                ConnectedSocketMapT::iterator i = object->mConnectedSocket.find(connection->socket_fd);
+                if(i == object->mConnectedSocket.end()) {
+                    LoggerW("Unknown connected socket");
+                    return;
+                }
+
+                BluetoothSocketPtr socket = i->second;
+                socket->setConnectionState(false);
+                MultiCallbackUserDataPtr callback = socket->getOnClose();
+                if(callback)
+                    callback->invokeCallback("onclose");
+
+                // Update mConnectedSocket
+                object->mConnectedSocket.erase(i);
+            }
+            else {
+                LoggerW("Disconnecting a connection failed");
+            }
+        }
+    }
+    else {
+        LoggerW("Unknown role");
+        return;
+    }
+
+    if(object->mConnectedSocket.size() == 0) {
+        bt_socket_unset_data_received_cb();
+    }
+
+    if(object->mRegisteredUUID.size() == 0 && object->mConnReqMap.size() == 0 && object->mConnectedSocket.size() == 0) {
+        bt_socket_unset_connection_state_changed_cb();
+    }
+}
+
+void BluetoothAdapter::onSocketReceivedCB(bt_socket_received_data_s *data, void *userData)
+{
+    BluetoothAdapterPtr object = static_cast<BluetoothAdapterPtr>(userData);
+    if(!object) {
+        LoggerW("userData is NULL");
+        return;
+    }
+
+    if(!data) {
+        LoggerW("data is NULL");
+        return;
+    }
+
+    ConnectedSocketMapT::iterator i = object->mConnectedSocket.find(data->socket_fd);
+    if(i == object->mConnectedSocket.end()) {
+        LoggerW("Unknown connected socket");
+        return;
+    }
+
+    // Store received data
+    BluetoothSocketPtr socket = i->second;
+    socket->storeRecivedData(data->data, static_cast<unsigned long>(data->data_size));
+
+    // Call BluetoothSocket.onmessage
+    MultiCallbackUserDataPtr callback = socket->getOnMessage();
+    if(callback)
+        callback->invokeCallback("onmessage");
+}
+
+BluetoothAdapter::BluetoothAdapter():
+    mAdapterPath(NULL),
+    mAgentRegistrationId(-1),
+    mAgentIntrospectionData(NULL),
+    mBluetoothTechnology(NULL),
+    mEnabled(false)
+{
+
+
+    mBluetoothTechnology = getBluetoothTechnology();
+    if(!mBluetoothTechnology) {
+        LoggerE("Failed to get BT technology");
+    }
+
+    mAdapterPath = getDefaultAdapter();
+    if(!mAdapterPath) {
+        LoggerE("Unable to get default adapter");
+    }
+    Utils::setSignalListener(G_BUS_TYPE_SYSTEM, BLUEZ_SERVICE, BLUEZ_MANAGER_IFACE,
+                             "/", "AdapterAdded", BluetoothAdapter::handleSignal,
+                             this);
+    Utils::setSignalListener(G_BUS_TYPE_SYSTEM, BLUEZ_SERVICE, BLUEZ_MANAGER_IFACE,
+                             "/", "AdapterRemoved", BluetoothAdapter::handleSignal,
+                             this);
+    memset(&mAgentIfaceVTable, 0, sizeof(mAgentIfaceVTable));
+
+    if(isAdapterPowered()) {
+        //LoggerD("Adapter is powered");
+        mEnabled = true;
+    }
+    //else {
+    //    LoggerD("Adapter is not powered");
+    //}
+
+    if(mAdapterPath) {
+        Utils::setSignalListener(G_BUS_TYPE_SYSTEM, BLUEZ_SERVICE, BLUEZ_ADAPTER_IFACE,
+                                 mAdapterPath, "PropertyChanged", BluetoothAdapter::handleSignal,
+                                 this);
+    }
+}
+
+BluetoothAdapter::~BluetoothAdapter()
+{
+    // unset platform callback
+    bt_socket_unset_connection_state_changed_cb();
+    bt_socket_unset_data_received_cb();
+
+    for(int i = 0; i <= DESTROY_BONDING; i++) {
+        mUserDataList[i].reset();
+    }
+    mRegisteredUUID.clear();
+    mConnReqMap.clear();
+    mFoundDevices.clear();
+    mConnectedSocket.clear();
+}
+
+void BluetoothAdapter::unloadFrame(JSContextRef context)
+{
+    LoggerD("Clean mUserDataList");
+    for(int i = 0; i <= DESTROY_BONDING; i++) {
+        if(mUserDataList[i]) {
+            MultiCallbackUserDataPtr callback = mUserDataList[i];
+            if(!GlobalContextManager::getInstance()->isAliveGlobalContext(callback->getContext())) {
+                mUserDataList[i].reset();
+            }
+        }
+    }
+
+    LoggerD("Clean mConnReqMap");
+    for(ConnReqMultiMapT::iterator iter = mConnReqMap.begin(); iter != mConnReqMap.end(); ) {
+        ConnReqMultiMapT::iterator temp = iter++;
+        MultiCallbackUserDataPtr callback = temp->second->mUserData;
+        if(!callback && !GlobalContextManager::getInstance()->isAliveGlobalContext(callback->getContext())) {
+            mConnReqMap.erase(temp);
+        }
+    }
+}
+
+void BluetoothAdapter::unregisterUUID(std::string &uuid)
+{
+    mRegisteredUUID.erase(mRegisteredUUID.find(uuid));
+    if(mRegisteredUUID.size() == 0 && mConnReqMap.size() == 0 && mConnectedSocket.size() == 0) {
+        bt_socket_unset_connection_state_changed_cb();
+    }
+}
+
+bool BluetoothAdapter::closeConnectedSocket(int socket)
+{
+    if(mEnabled == true) {
+        ConnectedSocketMapT::iterator iter = mConnectedSocket.find(socket);
+        if(iter == mConnectedSocket.end()) {
+            LoggerW("Already disconnected");
+            return true;
+        }
+
+        mConnectedSocket.erase(iter);
+        if(mConnectedSocket.size() == 0) {
+            bt_socket_unset_data_received_cb();
+        }
+
+        if(mRegisteredUUID.size() == 0 && mConnReqMap.size() == 0 && mConnectedSocket.size() == 0) {
+            bt_socket_unset_connection_state_changed_cb();
+        }
+
+        return true;
+    }
+    else {
+        LoggerE("Bluetooth is not powered");
+        return false;
+    }
+}
+
+void BluetoothAdapter::removeConnReq(std::string &remoteAddress)
+{
+    mConnReqMap.erase(remoteAddress);
+
+    if(mRegisteredUUID.size() == 0 && mConnReqMap.size() == 0 && mConnectedSocket.size() == 0) {
+        if(bt_socket_unset_connection_state_changed_cb() != BT_ERROR_NONE) {
+            LoggerW("Unsetting connection event callback failed");
+        }
+    }
+}
+
+BluetoothAdapter* BluetoothAdapter::getInstance()
+{
+    static BluetoothAdapter instance;
+    return &instance;
+}
+
+bool BluetoothAdapter::isBluetoothSupported()
+{
+    bool isSupported = false;
+
+/*    if(system_info_get_value_bool(SYSTEM_INFO_KEY_BLUETOOTH_SUPPORTED, &isSupported) != SYSTEM_INFO_ERROR_NONE) {
+        LoggerE("Can't know whether Bluetooth is supported or not");
+    }
+*/
+    return isSupported;
+}
+
+bool BluetoothAdapter::isValidAddress(std::string &address)
+{
+    pcrecpp::RE re("(([0-9a-zA-Z]+):)+([0-9a-zA-Z]+)");
+    std::string compareAddress = "00:12:47:08:9A:A6";
+
+    if (!re.FullMatch(address)) {
+        LoggerE("Invalid address");
+        return false;
+    }
+
+    if (address.size() != compareAddress.size())
+    {
+        LoggerE("Invalid size");
+        return false;
+    }
+
+    return true;
+}
+
+bool BluetoothAdapter::isValidUUID(std::string &uuid)
+{
+    pcrecpp::RE re("(([0-9a-zA-Z]+)-)+([0-9a-zA-Z]+)");
+    std::string compareUUID = "00001101-0000-1000-8000-00805F9B34FB";
+
+    if (!re.FullMatch(uuid))
+    {
+        LoggerE("Invalid UUID");
+        return false;
+    }
+
+    if (uuid.size() != compareUUID.size())
+    {
+        LoggerE("Invalid size");
+        return false;
+    }
+
+    return true;
+}
+
+std::string BluetoothAdapter::getName() const
+{
+    const char* name = NULL;
+    std::string str = "";
+
+    if(!mAdapterPath) {
+        LoggerD("No BT adapter");
+        return str;
+    }
+
+    // get adapter properties and check Name property
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                         BLUEZ_SERVICE,
+                                         mAdapterPath,
+                                         BLUEZ_ADAPTER_IFACE,
+                                         "GetProperties",
+                                         NULL,
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+    if(err || !reply) {
+        if(err)
+            g_error_free(err);
+        LoggerE("Failed to get 'Name' property");
+        return str;
+    }
+
+    GVariantIter *iter;
+    g_variant_get(reply, "(a{sv})", &iter);
+    const char *key;
+    GVariant *value;
+    while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+        if(!strcmp(key, "Name")) {
+            name = g_variant_get_string(value, NULL);
+            if(name)
+                str = name;
+            break;
+        }
+    }
+
+    g_variant_unref(reply);
+
+    return str;
+}
+
+void BluetoothAdapter::setName(std::string &name, MultiCallbackUserDataPtr userData)
+{
+    if(mEnabled == true) {
+        std::string adapterName = getName();
+        if(adapterName == name) {   // in case of same name
+            LoggerD("same name");
+            BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+            return;
+        }
+
+        if(mAdapterPath) {
+            GError *err = NULL;
+            g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL,NULL),
+                                         BLUEZ_SERVICE,
+                                         mAdapterPath,
+                                         BLUEZ_ADAPTER_IFACE,
+                                         "SetProperty",
+                                         g_variant_new ("(sv)", // floating parameters are consumed, no cleanup/unref needed
+                                             "Name",
+                                             g_variant_new("s", name.c_str()) // floating parameters are consumed, no cleanup/unref needed
+                                         ),
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+
+            if(err) {
+                LoggerE("Failed to call \"SetProperty\" DBUS method: " << err->message);
+                UnknownException *error = new UnknownException(err->message);
+                BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+                g_error_free(err);
+                return;
+            }
+
+            if(userData)
+                userData->invokeCallback("success");
+        }
+        else {
+            LoggerE("No BT adapter");
+            UnknownException *error = new UnknownException("No BT adapter");
+            BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+            return;
+        }
+    }
+}
+
+std::string BluetoothAdapter::getAddress() const
+{
+    const char* address = NULL;
+    std::string str = "";
+
+    if(!mAdapterPath) {
+        LoggerD("No BT adapter");
+        return str;
+    }
+
+    // get adapter properties and check Address property
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                         BLUEZ_SERVICE,
+                                         mAdapterPath,
+                                         BLUEZ_ADAPTER_IFACE,
+                                         "GetProperties",
+                                         NULL,
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+    if(err || !reply) {
+        if(err)
+            g_error_free(err);
+        LoggerE("Failed to get 'Address' property");
+        return str;
+    }
+
+    GVariantIter *iter;
+    g_variant_get(reply, "(a{sv})", &iter);
+    const char *key;
+    GVariant *value;
+    while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+        if(!strcmp(key, "Address")) {
+            address = g_variant_get_string(value, NULL);
+            if(address)
+                str = address;
+            break;
+        }
+    }
+
+    g_variant_unref(reply);
+
+    return str;
+}
+
+bool BluetoothAdapter::getPowered() const
+{
+    return mEnabled;
+}
+
+void BluetoothAdapter::setPowered(bool powered, MultiCallbackUserDataPtr userData)
+{
+    LoggerD("entered");
+
+    bool btTechnologyPowered = isBtTechnologyPowered();
+    if(!powered) { // Powering OFF BT. It is enough to take down BT technology - it will take down Adapter as well
+        if(!btTechnologyPowered) { // already powered OFF
+            LoggerD("BT already powered OFF ... calling success callback.");
+            BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+            return;
+        }
+        else {
+            if(setBluetoothPowered(powered)) { // BT powered OFF successfuly
+                BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+            }
+            else {
+                LoggerD("Failed to Power OFF BT technology - trying to Power OFF the Adapter directly");
+                if(setAdapterPowered(powered)) {
+                    BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+                }
+                else {
+                    LoggerE("Failed to Power OFF both, BT and adapter as well ... calling error callback");
+                    UnknownException *error = new UnknownException("Failed to Power OFF BT/Adapter");
+                    BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+                }
+            }
+        }
+    }
+    else { // Powering ON BT
+        if(btTechnologyPowered) { // already Powered ON
+            if(mEnabled) { // already Powered On
+                LoggerD("BT/Adapter already powered ON ... calling success callback.");
+                BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+            }
+            else { // BT powered, but Adapter is not - try to power it ON
+                LoggerD("BT technology is Powered ON, but adapter is not, trying to Power it ON");
+                if(setAdapterPowered(powered)) { // successfuly powered ON ... calling success callback
+                    BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+                }
+                else {
+                    LoggerE("Failed to Power ON BT adapter ... calling error callback");
+                    UnknownException *error = new UnknownException("Failed to Power ON BT adapter");
+                    BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+                }
+            }
+        }
+        else {
+            if(!setBluetoothPowered(powered)) {
+                LoggerE("Failed to Power ON BT technology ... calling error callback");
+                UnknownException *error = new UnknownException("Failed to Power ON BT technology");
+                BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+            }
+            /*
+            else { // BT technology powered ON (it should power ON adapter as well, but just in case, call Power ON on adapter as well)
+                if(setAdapterPowered(powered)) {
+                    BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+                }
+                else {
+                    LoggerE("Failed to Power ON BT adapter ... calling error callback");
+                    UnknownException *error = new UnknownException("Failed to Power ON BT adapter");
+                    BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+                }
+            }
+            */
+            else {
+                BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+            }
+        }
+    }
+
+    mUserDataList[SET_POWERED].reset();
+}
+
+bool BluetoothAdapter::getVisible() const
+{
+    if(!mAdapterPath) {
+        LoggerD("No BT adapter");
+        return false;
+    }
+
+    // get adapter properties and check Discoverable property
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                         BLUEZ_SERVICE,
+                                         mAdapterPath,
+                                         BLUEZ_ADAPTER_IFACE,
+                                         "GetProperties",
+                                         NULL,
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+    if(err || !reply) {
+        if(err)
+            g_error_free(err);
+        LoggerE("Failed to get 'Discoverable' property");
+        return false;
+    }
+
+    bool visible = false;
+    GVariantIter *iter;
+    g_variant_get(reply, "(a{sv})", &iter);
+    const char *key;
+    GVariant *value;
+    while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+        if(!strcmp(key, "Discoverable")) {
+            visible = g_variant_get_boolean(value);
+            break;
+        }
+    }
+
+    g_variant_unref(reply);
+
+    return visible;
+}
+
+void BluetoothAdapter::setVisible(bool visible, unsigned int timeout, MultiCallbackUserDataPtr userData)
+{
+    //TODO: implementation needed
+    UnknownException *error = new UnknownException("NOT IMPLEMENTED");
+    BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+    /*
+    if(mEnabled == true) {
+        bt_adapter_visibility_mode_e discoverable_mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
+        if(visible == true) {
+            if(timeout == 0)
+                discoverable_mode = BT_ADAPTER_VISIBILITY_MODE_GENERAL_DISCOVERABLE;
+            else
+                discoverable_mode = BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE;
+        }
+
+        bt_adapter_visibility_mode_e current = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
+        int time = 0;
+        if(bt_adapter_get_visibility(&current , &time) != BT_ERROR_NONE) {
+            LoggerE("bt_adapter_get_visibility() failed");
+            UnknownException *error = new UnknownException("Can't get current visibility");
+            BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+            return;
+        }
+
+        if(discoverable_mode == current) {
+            if(discoverable_mode != BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE) {
+                LoggerD("same visibility");
+                BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+                return;
+            }
+            else if((unsigned int)time == timeout) {
+                LoggerD("same visibility");
+                BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+                return;
+            }
+        }
+
+        if(mUserDataList[SET_VISIBLE] == NULL) {
+            bt_adapter_set_visibility_mode_changed_cb(onVisibilityChangedCB, this);
+            mUserDataList[SET_VISIBLE] = userData;
+        } else {
+            UnknownException *error = new UnknownException("Already requested");
+            BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+            return;
+        }
+
+        mRequestedVisibility = discoverable_mode;
+        int ret = bt_adapter_set_visibility(discoverable_mode, timeout);
+        switch(ret) {
+            case BT_ERROR_NONE:
+            {
+                LoggerD("bt_adapter_set_visibility() succeeded");
+                return;
+            }
+            case BT_ERROR_INVALID_PARAMETER:
+            {
+                InvalidValuesException *error = new InvalidValuesException("Invalid value");
+                BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+                break;
+            }
+            default:
+            {
+                UnknownException *error = new UnknownException("Unknown error");
+                BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+            }
+        }
+
+        bt_adapter_unset_visibility_mode_changed_cb();
+        mUserDataList[SET_VISIBLE].reset();
+    } else {   // Not enabled
+        ServiceNotAvailableException *error =  new ServiceNotAvailableException("Bluetooth device is turned off");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+    }
+*/
+}
+
+void BluetoothAdapter::setChangeListener(MultiCallbackUserDataPtr userData)
+{
+    if(mChangeListener == NULL)
+        mChangeListener = userData;
+}
+
+void BluetoothAdapter::unsetChangeListener()
+{
+    if(mChangeListener != NULL)
+        mChangeListener.reset();
+}
+
+
+void BluetoothAdapter::discoverDevices(MultiCallbackUserDataPtr userData)
+{
+    if(!mAdapterPath) {
+        LoggerE("No BT adapter");
+        UnknownException *error = new UnknownException("No BT adapter");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+        return;
+    }
+
+    if(mUserDataList[DISCOVER_DEVICES] == NULL) {
+        mUserDataList[DISCOVER_DEVICES] = userData;
+    } else {
+        LoggerE("Already requested");
+        UnknownException *error = new UnknownException("Already requested");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+        return;
+    }
+
+    if(mEnabled == true) {
+        GError *err = NULL;
+        g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                     BLUEZ_SERVICE,
+                                     mAdapterPath,
+                                     BLUEZ_ADAPTER_IFACE,
+                                     "StartDiscovery",
+                                     NULL,
+                                     NULL,
+                                     G_DBUS_CALL_FLAGS_NONE,
+                                     -1,
+                                     NULL,
+                                     &err);
+        if(err) {
+            LoggerE("Failed to 'StartDiscovery' on adapter " << mAdapterPath << " : " << err->message);
+            UnknownException *error = new UnknownException(err->message);
+            BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+            g_error_free(err);
+            mUserDataList[DISCOVER_DEVICES].reset();
+        }
+        else {
+            LoggerD("Call to 'StartDiscovery' succeeded");
+
+            // store MAC address of previously found device into mDisappearedDevices
+            mDisappearedDevices.clear();
+            for(auto iter = mFoundDevices.begin();
+                    iter != mFoundDevices.end(); iter++) {
+                BluetoothDeviceSharedPtr foundDevice = *iter;
+                mDisappearedDevices.push_back(foundDevice->getAddress());
+            }
+
+            mFoundDevices.clear();
+
+            // 'onstarted' callback is called after receiving 'Discovering' property changed to 'true' ... see handleSignal() method
+            //if(userData)
+            //    userData->invokeCallback("onstarted");
+
+            Utils::setSignalListener(G_BUS_TYPE_SYSTEM, BLUEZ_SERVICE, BLUEZ_ADAPTER_IFACE,
+                                     mAdapterPath, "DeviceFound", BluetoothAdapter::handleSignal,
+                                     this);
+
+            return;
+        }
+    } else {   // Not enabled
+        LoggerE("Bluetooth device is turned off");
+        ServiceNotAvailableException *error =  new ServiceNotAvailableException("Bluetooth device is turned off");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+    }
+
+    mUserDataList[DISCOVER_DEVICES].reset();
+}
+
+void BluetoothAdapter::stopDiscovery(MultiCallbackUserDataPtr userData)
+{
+    if(mUserDataList[DISCOVER_DEVICES] == NULL) { // not doing discovery
+        BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+        return;
+    }
+
+    if(!mAdapterPath) {
+        LoggerE("No BT adapter");
+        UnknownException *error = new UnknownException("No BT adapter");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+    }
+    else if(mEnabled == true) {
+        GError *err = NULL;
+        g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                     BLUEZ_SERVICE,
+                                     mAdapterPath,
+                                     BLUEZ_ADAPTER_IFACE,
+                                     "StopDiscovery",
+                                     NULL,
+                                     NULL,
+                                     G_DBUS_CALL_FLAGS_NONE,
+                                     -1,
+                                     NULL,
+                                     &err);
+        if(err) {
+            LoggerE("Failed to 'StopDiscovery': " << err->message);
+            UnknownException *error = new UnknownException(err->message);
+            BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+            g_error_free(err);
+        } else {
+            BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+            return;
+        }
+    } else {   // Not enabled
+        ServiceNotAvailableException *error =  new ServiceNotAvailableException("Bluetooth device is turned off");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+    }
+
+    mUserDataList[DISCOVER_DEVICES].reset();
+}
+
+void BluetoothAdapter::getKnownDevices(MultiCallbackUserDataPtr userData)
+{
+    BluetoothCallbackUtil::syncToAsyncDeviceArrayCallback(userData);
+}
+
+void BluetoothAdapter::getDevice(std::string &address, MultiCallbackUserDataPtr userData)
+{
+    BluetoothCallbackUtil::syncToAsyncDeviceCallback(userData, address);
+}
+
+void BluetoothAdapter::createBonding(std::string &address, MultiCallbackUserDataPtr userData)
+{
+    if(!isValidAddress(address)) {
+        LoggerE("Wrong address");
+        NotFoundException *error = new NotFoundException("Wrong address");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+        return;
+    }
+
+    if(!mAdapterPath) {
+        LoggerE("No BT adapter");
+        NotFoundException *error = new NotFoundException("No BT adapter");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+        return;
+    }
+
+    if(mUserDataList[CREATE_BONDING] == NULL) {
+        mCreateBondingAddress = address;
+        mUserDataList[CREATE_BONDING] = userData;
+    } else {
+        LoggerE("Already requested");
+        UnknownException *error = new UnknownException("Already requested");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+        return;
+    }
+
+    // remove the device first, so the pairing can be initiated, otherwise pairing will fail
+    bool ok = removeDevice(address.c_str());
+    if(!ok)
+        LoggerD("Failed to remove device: " << address);
+
+    if(mEnabled == true) {
+        if(setupAgent(AGENT_PATH)) {
+            // CreatePairedDevice has to be ASYNC DBUS call
+            g_dbus_connection_call( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                    BLUEZ_SERVICE,
+                                    mAdapterPath,
+                                    BLUEZ_ADAPTER_IFACE,
+                                    "CreatePairedDevice",
+                                    g_variant_new("(sos)", address.c_str(), AGENT_PATH, AGENT_CAPABILITIES),
+                                    NULL,
+                                    G_DBUS_CALL_FLAGS_NONE,
+                                    -1,
+                                    NULL,
+                                    BluetoothAdapter::asyncCreatePairedDeviceCallback,
+                                    this);
+            LoggerD("Called 'CreatePairedDevice'");
+        } else {
+            LoggerE("Failed to set-up Bluez Agent for pairing");
+            ServiceNotAvailableException *error =  new ServiceNotAvailableException("Failed to set-up Bluez Agent for pairing");
+            BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+        }
+    } else {   // Not enabled
+        LoggerE("Bluetooth device is turned off");
+        ServiceNotAvailableException *error =  new ServiceNotAvailableException("Bluetooth device is turned off");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+    }
+}
+
+void BluetoothAdapter::destroyBonding(std::string &address, MultiCallbackUserDataPtr userData)
+{
+    if(!isValidAddress(address)) {
+        LoggerE("Wrong address");
+        NotFoundException *error = new NotFoundException("Wrong address");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+        return;
+    }
+
+    // get device info before removing, 'cause after removing you loose access to it ('FindDevice' will not find it)
+    bt_device_info_s deviceInfo;
+    bool hasDeviceInfo = getDeviceInfoByAddress(&deviceInfo, address.c_str());
+
+    if(!removeDevice(address.c_str())) {
+        if(userData) {
+            JSContextRef context = userData->getContext();
+            UnknownException error("Failed to remove device");
+            userData->invokeCallback("error", JSWebAPIErrorFactory::makeErrorObject(context, error));
+        }
+
+        return;
+    }
+
+    if(userData) {
+        if(hasDeviceInfo) {
+            BluetoothDeviceSharedPtr device(new BluetoothDevice(&deviceInfo));
+            JSContextRef context = userData->getContext();
+            JSObjectRef deviceObj = JSBluetoothDevice::createJSObject(context, device);
+            userData->invokeCallback("success", deviceObj);
+        } else {
+            JSContextRef context = userData->getContext();
+            UnknownException error("Failed to get device info");
+            userData->invokeCallback("error", JSWebAPIErrorFactory::makeErrorObject(context, error));
+        }
+        freeDeviceInfo(&deviceInfo);
+    }
+}
+
+void BluetoothAdapter::registerRFCOMMServiceByUUID(std::string &uuid, std::string &name, MultiCallbackUserDataPtr userData)
+{
+    BluetoothCallbackUtil::syncToAsyncServiceCallback(userData, uuid, name);
+}
+
+void BluetoothAdapter::connectToServiceByUUID(std::string &remoteAddress, std::string &uuid, Common::MultiCallbackUserDataPtr userData)
+{
+    if(!isValidUUID(uuid)) {
+        LoggerE("Wrong UUID");
+        InvalidValuesException *error = new InvalidValuesException("Wrong UUID");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+        return;
+    }
+
+
+    if(mEnabled == true) {
+        int ret = bt_socket_connect_rfcomm(remoteAddress.c_str(), uuid.c_str());
+
+        switch(ret) {
+            case BT_ERROR_NONE:
+            {
+                LoggerD("bt_socket_connect_rfcomm() succeeded");
+                bt_socket_set_connection_state_changed_cb(onSocketConnected, this);
+
+                BluetoothConnReqPtr connReq = new BluetoothConnReq(uuid, userData);
+                mConnReqMap.insert(std::pair<std::string, BluetoothConnReqPtr>(remoteAddress, connReq));
+                break;
+            }
+            case BT_ERROR_INVALID_PARAMETER:
+            case BT_ERROR_REMOTE_DEVICE_NOT_BONDED:
+            {
+                InvalidValuesException *error = new InvalidValuesException("Invalid value");
+                BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+                break;
+            }
+            default:
+            {
+                UnknownException *error = new UnknownException("Unknown error");
+                BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+            }
+        }
+    } else {   // Not enabled
+        ServiceNotAvailableException *error =  new ServiceNotAvailableException("Bluetooth device is turned off");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+    }
+}
+
+void BluetoothAdapter::returnKnownDevices(Common::MultiCallbackUserDataPtr userData)
+{
+    if(mEnabled == true) {
+        knownDevices = mFoundDevices;
+
+        // Get a list of paired/bonded devices
+        GError *err = NULL;
+        GVariant *reply = NULL;
+        reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                             BLUEZ_SERVICE,
+                                             mAdapterPath,
+                                             BLUEZ_ADAPTER_IFACE,
+                                             "GetProperties",
+                                             NULL,
+                                             NULL,
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1,
+                                             NULL,
+                                             &err);
+        if(err || !reply) {
+            if(err)
+                g_error_free(err);
+        } else {
+            GVariantIter *iter;
+            g_variant_get(reply, "(a{sv})", &iter);
+            const char *key;
+            GVariant *value;
+            while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+                if(!strcmp(key, "Devices")) {
+                    g_variant_get(value, "ao", &iter);
+                    const char *device = NULL;
+                    while(g_variant_iter_next(iter, "o", &device)) {
+                        if(isDevicePaired(device)) {
+                            bt_device_info_s deviceInfo;
+                            if(getDeviceInfo(&deviceInfo, device))
+                                foreachBondedDevicesCB(&deviceInfo, this);
+                            freeDeviceInfo(&deviceInfo);
+                        }
+                    }
+                    break;
+                }
+            }
+
+            g_variant_unref(reply);
+        }
+
+        if(knownDevices.size() > 0) { // There are found devices
+            //LoggerD("There are found devices");
+            int num = knownDevices.size();
+            JSObjectRef devices[num];
+            for(int i = 0; i < num; i++) {
+                JSObjectRef deviceObj = JSBluetoothDevice::createJSObject(userData->getContext(), knownDevices[i]);
+                devices[i] = deviceObj;
+            }
+
+            userData->invokeCallback("success", JSObjectMakeArray(userData->getContext(), num, devices, NULL));
+        }
+        else {  // There is no found device
+            userData->invokeCallback("success", JSObjectMakeArray(userData->getContext(), 0, NULL, NULL) );
+        }
+    } else {   // Not enabled
+        LoggerE("Bluetooth device is turned off");
+        userData->invokeCallback(
+                "error",
+                JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), ServiceNotAvailableException("Bluetooth device is turned off"))
+        );
+    }
+}
+
+void BluetoothAdapter::returnDevice(std::string &address, Common::MultiCallbackUserDataPtr userData)
+{
+    if(!isValidAddress(address)) {
+        LoggerE("Wrong address");
+        userData->invokeCallback("error", JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), NotFoundException("Wrong address")));
+        return;
+    }
+
+    if(mEnabled == true) {
+        bt_device_info_s deviceInfo;
+        bool success = getDeviceInfoByAddress(&deviceInfo, address.c_str());
+
+        if(success) {
+            BluetoothDeviceSharedPtr device(new BluetoothDevice(&deviceInfo));
+            LoggerD("invoke successCallback");
+            userData->invokeCallback("success", JSBluetoothDevice::createJSObject(userData->getContext(), device));
+            return;
+        } else {
+            JSContextRef context = userData->getContext();
+            UnknownException error("Failed to get device info");
+            userData->invokeCallback("error", JSWebAPIErrorFactory::makeErrorObject(context, error));
+        }
+        freeDeviceInfo(&deviceInfo);
+
+        std::vector<BluetoothDeviceSharedPtr>::iterator iter;
+        for(iter = mFoundDevices.begin(); iter != mFoundDevices.end(); ++iter) {
+                BluetoothDeviceSharedPtr foundDevice = *iter;
+            if(!strcmp(foundDevice->getAddress().c_str(), address.c_str())) {
+                LoggerD("Found in mFoundDevices");
+                userData->invokeCallback("success", JSBluetoothDevice::createJSObject(userData->getContext(), foundDevice));
+                break;
+            }
+        }
+
+        if(iter == mFoundDevices.end()) {
+            LoggerE("Can't find this device");
+
+            userData->invokeCallback(
+                    "error",
+                    JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), NotFoundException("There is no device with the given address"))
+            );
+        }
+    } else {   // Not enabled
+        LoggerE("Bluetooth device is turned off");
+        userData->invokeCallback(
+                "error",
+                JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), ServiceNotAvailableException("Bluetooth device is turned off"))
+        );
+    }
+}
+
+void BluetoothAdapter::returnRegisteredService(std::string &uuid, std::string &name, Common::MultiCallbackUserDataPtr userData)
+{
+    if(!isValidUUID(uuid)) {
+        LoggerE("Wrong UUID");
+        userData->invokeCallback("error", JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), InvalidValuesException("Wrong UUID")));
+        return;
+    }
+
+    if(mEnabled == true) {
+
+        bool isRegistered;
+        if(bt_adapter_is_service_used(uuid.c_str(), &isRegistered) == BT_ERROR_NONE && isRegistered == true) {
+            LoggerD("Already registered");
+            userData->invokeCallback("error", JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), InvalidValuesException("Already registered")));
+            return;
+        }
+
+        int socket = -1;
+        int ret = bt_socket_create_rfcomm(uuid.c_str(), &socket);
+
+        switch(ret) {
+            case BT_ERROR_NONE:
+            {
+                LoggerD("bt_socket_create_rfcomm() succeeded");
+                int ret = bt_socket_listen_and_accept_rfcomm(socket, 0);
+                switch(ret) {
+                    case BT_ERROR_NONE:
+                    {
+                        LoggerD("bt_socket_listen() succeeded");
+                        bt_socket_set_connection_state_changed_cb(onSocketConnected, this);
+
+                        BluetoothServiceHandlerPtr serviceHandler = new BluetoothServiceHandler(uuid, name, socket);
+                        mRegisteredUUID.insert(std::pair<std::string, BluetoothServiceHandlerPtr>(uuid, serviceHandler));
+
+                        JSObjectRef serviceObj = JSBluetoothServiceHandler::createJSObject(userData->getContext(), serviceHandler);
+                        userData->invokeCallback("success", serviceObj);
+                        break;
+                    }
+                    case BT_ERROR_INVALID_PARAMETER:
+                    {
+                        LoggerD("Invalid value");
+                        userData->invokeCallback("error", JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), InvalidValuesException("Invalid value")));
+                        break;
+                    }
+                    default:
+                    {
+                        LoggerD("Unknown exception");
+                        userData->invokeCallback("error", JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), UnknownException("Unknown exception")));
+                    }
+                }
+
+                break;
+            }
+            case BT_ERROR_INVALID_PARAMETER:
+            {
+                LoggerD("Invalid value");
+                userData->invokeCallback("error", JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), InvalidValuesException("Invalid value")));
+                break;
+            }
+            default:
+            {
+                LoggerD("Unknown exception");
+                userData->invokeCallback("error", JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), UnknownException("Unknown exception")));
+            }
+        }
+    } else {   // Not enabled
+        LoggerE("Bluetooth device is turned off");
+        userData->invokeCallback(
+                "error",
+                JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), ServiceNotAvailableException("Bluetooth device is turned off"))
+        );
+    }
+}
+
+bool BluetoothAdapter::isBtTechnologyPowered() {
+    if(!mBluetoothTechnology) {
+        LoggerE("Invalid BT technology to get 'Powered' state.");
+        return false;
+    }
+
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                         CONNMAN_SERVICE,
+                                         mBluetoothTechnology,
+                                         CONNMAN_TECHNOLOGY_IFACE,
+                                         "GetProperties",
+                                         NULL,
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+    if(err || !reply) {
+        if(err)
+            g_error_free(err);
+        return false;
+    }
+
+    GVariantIter *iter;
+    g_variant_get(reply, "(a{sv})", &iter);
+    const char *key;
+    GVariant *value;
+    bool powered = false;
+    while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+        if(!strcmp(key, "Powered")) {
+            powered = g_variant_get_boolean(value);
+            break;
+        }
+    }
+
+    g_variant_unref(reply);
+
+    return powered;
+}
+
+gchar* BluetoothAdapter::getDefaultAdapter() const
+{
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                         BLUEZ_SERVICE,
+                                         "/",
+                                         BLUEZ_MANAGER_IFACE,
+                                         "DefaultAdapter",
+                                         NULL,
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+    if(err || !reply) {
+        if(err) {
+            LoggerE("Failed to get default adapter: " << err->message);
+            g_error_free(err);
+        }
+        if(!reply)
+            LoggerE("Reply from 'DefaultAdapter' is null");
+        return NULL;
+    }
+
+    char *adapter = NULL;
+    g_variant_get(reply, "(o)", &adapter);
+    LoggerD("DefaultAdapter: " << adapter);
+
+    // make a copy of adapter, 'cause it will be destroyed when 'reply' is un-refed
+    char *result = adapter?strdup(adapter):NULL;
+
+    g_variant_unref(reply);
+
+    return result;
+}
+
+bool BluetoothAdapter::isAdapterPowered() {
+    if(!mAdapterPath)
+        return false;
+
+    // get adapter properties and check if it's Powered
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                         BLUEZ_SERVICE,
+                                         mAdapterPath,
+                                         BLUEZ_ADAPTER_IFACE,
+                                         "GetProperties",
+                                         NULL,
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+    if(err || !reply) {
+        if(err)
+            g_error_free(err);
+        return false;
+    }
+
+    GVariantIter *iter;
+    g_variant_get(reply, "(a{sv})", &iter);
+    const char *key;
+    GVariant *value;
+    bool powered = false;
+    while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+        if(!strcmp(key, "Powered")) {
+            powered = g_variant_get_boolean(value);
+            break;
+        }
+    }
+
+    g_variant_unref(reply);
+
+    return powered;
+}
+
+void BluetoothAdapter::handleSignal(GDBusConnection  *connection,
+                         const gchar      *sender,
+                         const gchar      *object_path,
+                         const gchar      *interface_name,
+                         const gchar      *signal_name,
+                         GVariant         *parameters,
+                         gpointer          user_data)
+{
+    LoggerD("signal received: '" << interface_name << "' -> '" << signal_name << "' -> '" << object_path << "'");
+
+    BluetoothAdapter *ctx = static_cast<BluetoothAdapter*>(user_data);
+    if(!ctx) {
+        LoggerD("Failed to cast to BluetoothAdapter");
+        return;
+    }
+
+
+    if(!strcmp(interface_name, BLUEZ_MANAGER_IFACE)) {
+        if(!strcmp(signal_name, "AdapterAdded")) {
+            const char *adapter = NULL;
+            g_variant_get(parameters, "(o)", &adapter);
+            if(adapter) {
+                LoggerD("Adapter added: " << adapter);
+                gchar * adapterPath = ctx->getDefaultAdapter();
+                free(ctx->mAdapterPath);
+                ctx->mAdapterPath = adapterPath;
+                if(adapterPath) {
+                    Utils::setSignalListener(G_BUS_TYPE_SYSTEM, BLUEZ_SERVICE, BLUEZ_ADAPTER_IFACE,
+                            adapterPath, "PropertyChanged", BluetoothAdapter::handleSignal,
+                            ctx);
+                }
+            }
+        }
+        else if(!strcmp(signal_name, "AdapterRemoved")) {
+            const char *adapter = NULL;
+            g_variant_get(parameters, "(o)", &adapter);
+            if(adapter) {
+                LoggerD("Adapter removed: " << adapter);
+            }
+        }
+    }
+    else if(!strcmp(interface_name, BLUEZ_ADAPTER_IFACE)) {
+        if(!strcmp(signal_name, "PropertyChanged")) {
+            const char *name;
+            GVariant *var;
+            g_variant_get(parameters, "(sv)", &name, &var);
+            LoggerD("\tname=" << name);
+            if(!strcmp(name, "Name")) {
+                const char *_name = g_variant_get_string(var, NULL);
+                ctx->onNameChanged(_name);
+            }
+            else if(!strcmp(name, "Powered")) {
+                bool powered = g_variant_get_boolean(var);
+                ctx->onPoweredChanged(powered);
+            }
+            else if(!strcmp(name, "Discoverable")) {
+                bool visible = g_variant_get_boolean(var);
+                ctx->onVisibilityChanged(visible);
+            }
+            else if(!strcmp(name, "Discovering")) {
+                bool discovering = g_variant_get_boolean(var);
+                if(discovering) { // discovery started
+                        MultiCallbackUserDataPtr callback = static_cast<MultiCallbackUserDataPtr>(ctx->mUserDataList[DISCOVER_DEVICES]);
+                        if(callback) {
+                            callback->invokeCallback("onstarted");
+                        }
+                }
+                else { // discovery completed
+                    LoggerD("Discovery completed");
+                    if(ctx->mUserDataList[DISCOVER_DEVICES] != NULL) {
+                        MultiCallbackUserDataPtr callback =
+                                static_cast<MultiCallbackUserDataPtr>(ctx->mUserDataList[DISCOVER_DEVICES]);
+
+                        if(callback) {
+                            if(ctx->mDisappearedDevices.size() > 0) {
+                                LoggerD("There are disappeared devices");
+                                for(auto iter = ctx->mDisappearedDevices.begin();
+                                        iter != ctx->mDisappearedDevices.end(); iter++) {
+
+                                    callback->invokeCallback("ondevicedisappeared",
+                                            JSUtil::toJSValueRef(callback->getContext(), *iter));
+                                }
+                            }
+
+                            if(ctx->mFoundDevices.size() > 0) { // There are found devices
+                                LoggerD("There are found devices");
+                                int num = ctx->mFoundDevices.size();
+                                JSObjectRef devices[num];
+                                for(int i = 0; i < num; i++) {
+                                    JSObjectRef deviceObj = JSBluetoothDevice::createJSObject(callback->getContext(), ctx->mFoundDevices[i]);
+                                    devices[i] = deviceObj;
+                                }
+
+                                ctx->mUserDataList[DISCOVER_DEVICES].reset();
+
+                                callback->invokeCallback(
+                                        "onfinished",
+                                        JSObjectMakeArray(callback->getContext(), num, devices, NULL) );
+                            }
+                            else {  // There is no found device
+                                LoggerD("There is no found device");
+                                ctx->mUserDataList[DISCOVER_DEVICES].reset();
+
+                                callback->invokeCallback(
+                                        "onfinished",
+                                        JSObjectMakeArray(callback->getContext(), 0, NULL, NULL) );
+                            }
+                        }
+
+                        Utils::removeSignalListener(G_BUS_TYPE_SYSTEM, BLUEZ_SERVICE, BLUEZ_ADAPTER_IFACE, object_path, "DeviceFound");
+
+                        GError *err = NULL;
+                        g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                                     BLUEZ_SERVICE,
+                                                     ctx->mAdapterPath,
+                                                     BLUEZ_ADAPTER_IFACE,
+                                                     "StopDiscovery",
+                                                     NULL,
+                                                     NULL,
+                                                     G_DBUS_CALL_FLAGS_NONE,
+                                                     -1,
+                                                     NULL,
+                                                     &err);
+                        if(err)
+                            g_error_free(err);
+                    }
+                }
+            }
+        }
+        else if(!strcmp(signal_name, "DeviceFound")) { // found remote BT device
+            bt_adapter_device_discovery_info_s discoveryInfo;
+            discoveryInfo.remote_name = NULL;
+            discoveryInfo.remote_address = NULL;
+            discoveryInfo.service_uuid = NULL;
+            discoveryInfo.service_count = 0;
+
+            const char *address;
+            GVariantIter *iter;
+            g_variant_get(parameters, "(sa{sv})", &address, &iter);
+            discoveryInfo.remote_address = address?strdup(address):NULL;
+            const char *key;
+            GVariant *value;
+            while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+                //LoggerD("KEY: " << key);
+                if(!strcmp(key, "Name")) {
+                    const char *name = g_variant_get_string(value, NULL);
+                    discoveryInfo.remote_name = name?strdup(name):NULL;
+                }
+                else if(!strcmp(key, "Paired")) {
+                    discoveryInfo.is_bonded = g_variant_get_boolean(value);
+                }
+                else if(!strcmp(key, "Class")) {
+                    guint32 _class = g_variant_get_uint32(value);
+                    uint8_t minor = _class & 0xff;
+                    uint8_t major = (_class >> 8) & 0xff;
+                    discoveryInfo.bt_class.minor_device_class = (bt_minor_device_class_e) minor;
+                    discoveryInfo.bt_class.major_device_class = (bt_major_device_class_e) major;
+                    //discoveryInfo.bt_class.major_service_class_mask =
+                }
+                else if(!strcmp(key, "UUIDs")) {
+                    GVariantIter *iter;
+                    const char *uuid = NULL;
+                    g_variant_get(value, "as", &iter);
+                    discoveryInfo.service_count = g_variant_iter_n_children(iter);
+                    discoveryInfo.service_uuid = (char**)malloc(discoveryInfo.service_count*sizeof(char*));
+                    char **uuids = discoveryInfo.service_uuid; // make a copy of ptr, since we will modify the pointer
+                    while(g_variant_iter_next(iter, "s", &uuid)) {
+                        *uuids++ = uuid?strdup(uuid):NULL;
+                    }
+                }
+            }
+
+            if(!discoveryInfo.remote_address) {
+                LoggerD("discovery info ... remote_address is null");
+                ctx->freeDiscoveryInfo(&discoveryInfo);
+                return;
+            }
+
+            if(!discoveryInfo.remote_name) {
+                LoggerD("discovery info ... remote_name is null for " << discoveryInfo.remote_address);
+                discoveryInfo.remote_name = strdup("");
+            }
+
+            LoggerD("Found BT device: " << discoveryInfo.remote_address << " ... " << (discoveryInfo.remote_name?discoveryInfo.remote_name:""));
+
+            if(ctx->mUserDataList[DISCOVER_DEVICES] != NULL) {  // requested event
+                MultiCallbackUserDataPtr callback =
+                        static_cast<MultiCallbackUserDataPtr>(ctx->mUserDataList[DISCOVER_DEVICES]);
+
+                if(callback) {
+                    if(!ctx->isDeviceInList(ctx->mFoundDevices, discoveryInfo.remote_address)) {
+                        // create BluetoothDevice
+                        BluetoothDeviceSharedPtr device(new BluetoothDevice(&discoveryInfo));
+                        JSContextRef context = callback->getContext();
+                        JSObjectRef deviceObj = JSBluetoothDevice::createJSObject(context, device);
+                        ctx->mFoundDevices.push_back(device);
+
+                        // remove MAC address of found device from mDisappearedDevices
+                        for(auto iter = ctx->mDisappearedDevices.begin(); iter != ctx->mDisappearedDevices.end(); iter++) {
+                            if(!strcmp(discoveryInfo.remote_address, (*iter).c_str())) {
+                                ctx->mDisappearedDevices.erase(iter);
+                                break;
+                            }
+                        }
+
+                        callback->invokeCallback("ondevicefound", deviceObj);
+                    }
+                }
+            }
+
+            ctx->freeDiscoveryInfo(&discoveryInfo);
+        }
+    }
+    /*
+    else if(!strcmp(interface_name, CONNMAN_TECHNOLOGY_IFACE)) {
+        if(!strcmp(signal_name, "PropertyChanged")) {
+            const char *name;
+            GVariant *value;
+            g_variant_get(parameters, "(sv)", &name, &value);
+            if(!strcmp(name, "Powered")) {
+                bool powered = g_variant_get_boolean(value);
+                ctx->onPoweredChanged(powered);
+            }
+        }
+    }
+    */
+}
+
+bool BluetoothAdapter::isDeviceInList(std::vector<BluetoothDeviceSharedPtr> list, const char *address) {
+    bool exists = false;
+    for(auto iter = list.begin(); iter != list.end(); iter++) {
+        if(!strcmp((*iter)->getAddress().c_str(), address)) {
+            exists = true;
+            break;
+        }
+    }
+
+    return exists;
+}
+
+bool BluetoothAdapter::setAdapterPowered(bool value)
+{
+    LoggerD("entered");
+
+    if(mAdapterPath) {
+        GError *err = NULL;
+        g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL,NULL),
+                                     BLUEZ_SERVICE,
+                                     mAdapterPath,
+                                     BLUEZ_ADAPTER_IFACE,
+                                     "SetProperty",
+                                     g_variant_new ("(sv)", // floating parameters are consumed, no cleanup/unref needed
+                                         "Powered",
+                                         //g_variant_new("b", &value)
+                                         g_variant_new_boolean(value)
+                                     ),
+                                     NULL,
+                                     G_DBUS_CALL_FLAGS_NONE,
+                                     -1,
+                                     NULL,
+                                     &err);
+
+        if(err) {
+            LoggerE("Failed to call \"SetProperty\" DBUS method: " << err->message);
+            g_error_free(err);
+            return false;
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+void BluetoothAdapter::onPoweredChanged(bool powered)
+{
+    mEnabled = powered;
+
+    if(mChangeListener != NULL) {
+        MultiCallbackUserDataPtr callback = static_cast<MultiCallbackUserDataPtr>(mChangeListener);
+        if(callback) {
+            JSContextRef context = callback->getContext();
+            JSValueRef value =  JSValueMakeBoolean(context, powered);
+
+            callback->invokeCallback("onstatechanged", value);
+        }
+    }
+
+    if(!powered && mUserDataList[DISCOVER_DEVICES] != NULL)
+        mUserDataList[DISCOVER_DEVICES].reset();
+}
+
+void BluetoothAdapter::onNameChanged(const char *name)
+{
+    if(mUserDataList[SET_NAME] != NULL) {  // requested event
+        MultiCallbackUserDataPtr callback = static_cast<MultiCallbackUserDataPtr>(mUserDataList[SET_NAME]);
+        mUserDataList[SET_NAME].reset();
+        if(callback)
+            callback->invokeCallback("success");
+    }
+    else {  // unexpected event
+        LoggerW("Bluetooth name is changed unexpectedly");
+    }
+
+    if(mChangeListener != NULL) {
+        MultiCallbackUserDataPtr callback = static_cast<MultiCallbackUserDataPtr>(mChangeListener);
+        if(callback) {
+            JSContextRef context = callback->getContext();
+            JSStringRef nameRef = JSStringCreateWithUTF8CString(name);
+            JSValueRef value = JSValueMakeString(context, nameRef);
+
+            callback->invokeCallback("onnamechanged", value);
+        }
+    }
+}
+
+void BluetoothAdapter::onVisibilityChanged(bool visible)
+{
+    if(mChangeListener != NULL) {
+        MultiCallbackUserDataPtr callback = static_cast<MultiCallbackUserDataPtr>(mChangeListener);
+        if(callback) {
+            JSContextRef context = callback->getContext();
+            JSValueRef value =  JSValueMakeBoolean(context, visible);
+
+            callback->invokeCallback("onvisibilitychanged", value);
+        }
+    }
+}
+
+void BluetoothAdapter::asyncCreatePairedDeviceCallback(GObject *source, GAsyncResult *result, gpointer user_data) {
+    BluetoothAdapter *ctx = static_cast<BluetoothAdapter*>(user_data);
+    if(!ctx) {
+        LoggerE("Failed to cast to BluetoothAdapter");
+        return;
+    }
+
+    GError *err = NULL;
+    GVariant *reply;
+    reply = g_dbus_connection_call_finish(g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL), result, &err);
+    if(err || !reply) {
+        LoggerD("Failed to CreatePairedDevice: " << (err?err->message:"Invalid reply"));
+        if(ctx->mUserDataList[CREATE_BONDING] != NULL) {
+            MultiCallbackUserDataPtr callback = static_cast<MultiCallbackUserDataPtr>(ctx->mUserDataList[CREATE_BONDING]);
+            if(callback) {
+                NotFoundException *error = new NotFoundException("Failed to CreatePairedDevice");
+                BluetoothCallbackUtil::syncToAsyncErrorCallback(callback, error);
+            }
+        }
+        if(err)
+            g_error_free(err);
+    } else {
+        LoggerD("Got reply from CreatePairedDevice");
+        if(ctx->mUserDataList[CREATE_BONDING] != NULL) {
+            MultiCallbackUserDataPtr callback = static_cast<MultiCallbackUserDataPtr>(ctx->mUserDataList[CREATE_BONDING]);
+            if(callback) {
+                bt_device_info_s deviceInfo;
+                if(ctx->getDeviceInfoByAddress(&deviceInfo, ctx->mCreateBondingAddress.c_str())) {
+                    BluetoothDeviceSharedPtr device(new BluetoothDevice(&deviceInfo));
+                    JSContextRef context = callback->getContext();
+                    JSObjectRef deviceObj = JSBluetoothDevice::createJSObject(context, device);
+                    callback->invokeCallback("success", deviceObj);
+                } else {
+                    JSContextRef context = callback->getContext();
+                    UnknownException error("Failed to get device info");
+                    callback->invokeCallback("error", JSWebAPIErrorFactory::makeErrorObject(context, error));
+                }
+                ctx->freeDeviceInfo(&deviceInfo);
+            }
+        }
+    }
+
+    ctx->mCreateBondingAddress.clear();
+    ctx->mUserDataList[CREATE_BONDING].reset();
+
+    g_variant_unref(reply);
+}
+
+bool BluetoothAdapter::setupAgent(const char *agent)
+{
+    if(!agent) {
+        LoggerE("Invalid agent path");
+        return false;
+    }
+
+    LoggerD("entered: registering agent " << agent);
+
+    GError *err = NULL;
+
+    mAgentIfaceVTable.method_call = BluetoothAdapter::agentHandleMethodCall;
+    mAgentIntrospectionData = g_dbus_node_info_new_for_xml(AGENT_INTERFACE_XML, NULL);
+
+    if (mAgentIntrospectionData == NULL) {
+        LoggerD("failed to create introspection data.");
+        return false;
+    }
+    LoggerD("introspection data parsed OK");
+
+    if(mAgentRegistrationId > 0) { // already registered
+        LoggerD("Bluez agent for pairing already registered ... possibly not Released after previous pairing");
+
+        // unregister Agent
+        bool unregistered = g_dbus_connection_unregister_object(g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL), mAgentRegistrationId);
+        if(unregistered)
+            mAgentRegistrationId = -1;
+    }
+
+    mAgentRegistrationId = g_dbus_connection_register_object( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                                  agent,
+                                                  mAgentIntrospectionData->interfaces[0],
+                                                  &mAgentIfaceVTable, //const GDBusInterfaceVTable *vtable,
+                                                  this, //user_data
+                                                  NULL, //GDestroyNotify
+                                                  &err);
+
+    if(err) {
+        LoggerD("Failed to register object: " << agent << " : " << err->message);
+        g_error_free(err);
+        return false;
+    }
+    LoggerD("object registered with id=" << mAgentRegistrationId);
+
+    return true;
+}
+
+void BluetoothAdapter::agentHandleMethodCall( GDBusConnection       *connection,
+                                              const gchar           *sender,
+                                              const gchar           *object_path,
+                                              const gchar           *interface_name,
+                                              const gchar           *method_name,
+                                              GVariant              *parameters,
+                                              GDBusMethodInvocation *invocation,
+                                              gpointer               user_data)
+{
+    LoggerD("entered\n\tsender=" << sender << "\n\tobject_path=" << object_path << "\n\tinterface_name=" << interface_name << "\n\tmethod_name=" << method_name);
+
+    BluetoothAdapter *ctx = static_cast<BluetoothAdapter*>(user_data);
+    if(!ctx) {
+        LoggerD("Failed to cast to BluetoothAdapter");
+        g_dbus_method_invocation_return_value(invocation, NULL);
+        return;
+    }
+
+    if(!strcmp(method_name, "Authorize")) {
+        g_dbus_method_invocation_return_value(invocation, NULL);
+    }
+    else if(!strcmp(method_name, "RequestPinCode")) {
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", PINCODE));
+    }
+    else if(!strcmp(method_name, "RequestPasskey")) {
+        g_dbus_method_invocation_return_value(invocation, g_variant_new("(u)", PASSKEY));
+    }
+    else if (!strcmp(method_name, "Release")) {
+        if(!strcmp(object_path, AGENT_PATH)) { // released agent for pairing
+            bool unregistered = g_dbus_connection_unregister_object(g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL), ctx->mAgentRegistrationId);
+            if(unregistered)
+                ctx->mAgentRegistrationId = -1;
+        }
+        g_dbus_method_invocation_return_value(invocation, NULL);
+    }
+    else {
+        // DisplayPasskey, DisplayPinCode, RequestConfirmation, ConfirmModeChange, Cancel
+        g_dbus_method_invocation_return_value(invocation, NULL);
+    }
+}
+
+bool BluetoothAdapter::isDevicePaired(const char *device) {
+    if(!device)
+        return false;
+
+    // get device properties and check if it's Paired
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                         BLUEZ_SERVICE,
+                                         device,
+                                         BLUEZ_DEVICE_IFACE,
+                                         "GetProperties",
+                                         NULL,
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+    if(err || !reply) {
+        if(err)
+            g_error_free(err);
+        return false;
+    }
+
+    GVariantIter *iter;
+    g_variant_get(reply, "(a{sv})", &iter);
+    const char *key;
+    GVariant *value;
+    bool paired = false;
+    while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+        if(!strcmp(key, "Paired")) {
+            paired = g_variant_get_boolean(value);
+            break;
+        }
+    }
+
+    g_variant_unref(reply);
+
+    return paired;
+}
+
+bool BluetoothAdapter::getDeviceInfoByAddress(bt_device_info_s *deviceInfo, const char *address) {
+
+    // to assure that when leaving the method, these fields
+    // will be either set/allocated, or NULL
+    deviceInfo->remote_name = NULL;
+    deviceInfo->remote_address = NULL;
+    deviceInfo->service_uuid = NULL;
+    deviceInfo->service_count = 0;
+
+    if(!deviceInfo || !address)
+        return false;
+
+    if(!mAdapterPath)
+        return false;
+
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+            BLUEZ_SERVICE,
+            mAdapterPath,
+            BLUEZ_ADAPTER_IFACE,
+            "FindDevice",
+            g_variant_new("(s)", address),
+            NULL,
+            G_DBUS_CALL_FLAGS_NONE,
+            -1,
+            NULL,
+            &err);
+
+    if(err || !reply) {
+        LoggerE("Failed to find " << address << " device: " << (err?err->message:"Invalid reply"));
+        if(err)
+            g_error_free(err);
+        return false;
+    }
+
+    bool success = false;
+    const char *device = NULL;
+    g_variant_get(reply, "(o)", &device);
+    if(device) {
+        success = getDeviceInfo(deviceInfo, device);
+    }
+
+    g_variant_unref(reply);
+
+    return success;
+}
+
+// don't forget to free memory of remote_name and remote_address
+bool BluetoothAdapter::getDeviceInfo(bt_device_info_s *deviceInfo, const char *device) {
+
+    // to assure that when leaving the method, these fields
+    // will be either set/allocated, or NULL
+    deviceInfo->remote_name = NULL;
+    deviceInfo->remote_address = NULL;
+    deviceInfo->service_uuid = NULL;
+    deviceInfo->service_count = 0;
+
+    if(!deviceInfo || !device)
+        return false;
+
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+            BLUEZ_SERVICE,
+            device,
+            BLUEZ_DEVICE_IFACE,
+            "GetProperties",
+            NULL,
+            NULL,
+            G_DBUS_CALL_FLAGS_NONE,
+            -1,
+            NULL,
+            &err);
+    if(err || !reply) {
+        LoggerE("Failed to 'GetProperties': " << err->message);
+        if(err)
+            g_error_free(err);
+        return false;
+    }
+
+    GVariantIter *iter;
+    g_variant_get(reply, "(a{sv})", &iter);
+    const char *key;
+    GVariant *value;
+    while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+        //LoggerD("KEY: " << key);
+        if(!strcmp(key, "Name")) {
+            const char *name = g_variant_get_string(value, NULL);
+            deviceInfo->remote_name = strdup(name);
+        }
+        else if(!strcmp(key, "Address")) {
+            const char *address = g_variant_get_string(value, NULL);
+            deviceInfo->remote_address = strdup(address);
+        }
+        else if(!strcmp(key, "Paired")) {
+            deviceInfo->is_bonded = g_variant_get_boolean(value);
+        }
+        else if(!strcmp(key, "Connected")) {
+            deviceInfo->is_connected = g_variant_get_boolean(value);
+        }
+        else if(!strcmp(key, "Trusted")) {
+            deviceInfo->is_authorized = g_variant_get_boolean(value);
+        }
+        else if(!strcmp(key, "Class")) {
+            guint32 _class = g_variant_get_uint32(value);
+            uint8_t minor = _class & 0xff;
+            uint8_t major = (_class >> 8) & 0xff;
+            deviceInfo->bt_class.minor_device_class = (bt_minor_device_class_e) minor;
+            deviceInfo->bt_class.major_device_class = (bt_major_device_class_e) major;
+            //deviceInfo->bt_class.major_service_class_mask =
+        }
+        else if(!strcmp(key, "UUIDs")) {
+            GVariantIter *iter;
+            const char *uuid = NULL;
+            g_variant_get(value, "as", &iter);
+            deviceInfo->service_count = g_variant_iter_n_children(iter);
+            deviceInfo->service_uuid = (char**)malloc(deviceInfo->service_count*sizeof(char*));
+            char **uuids = deviceInfo->service_uuid; // make a copy of ptr, since we will modify the pointer
+            while(g_variant_iter_next(iter, "s", &uuid)) {
+                *uuids++ = uuid?strdup(uuid):NULL;
+            }
+        }
+    }
+
+    g_variant_unref(reply);
+
+    return true;
+}
+
+// frees allocated memory by its members
+// Doesn't free/delete deviceInfo itself
+void BluetoothAdapter::freeDeviceInfo(bt_device_info_s *deviceInfo) {
+    if(!deviceInfo)
+        return;
+
+    free(deviceInfo->remote_address);
+    free(deviceInfo->remote_name);
+    for(int i=0; i<deviceInfo->service_count; i++) {
+        free(deviceInfo->service_uuid[i]);
+    }
+    free(deviceInfo->service_uuid);
+}
+
+// frees allocated memory by its members
+// Doesn't free/delete discoveryInfo itself
+void BluetoothAdapter::freeDiscoveryInfo(bt_adapter_device_discovery_info_s *discoveryInfo) {
+    if(!discoveryInfo)
+        return;
+
+    free(discoveryInfo->remote_address);
+    free(discoveryInfo->remote_name);
+    for(int i=0; i<discoveryInfo->service_count; i++) {
+        free(discoveryInfo->service_uuid[i]);
+    }
+    free(discoveryInfo->service_uuid);
+}
+
+bool BluetoothAdapter::removeDevice(const char *address) {
+    if(!address)
+        return false;
+
+    if(!mAdapterPath)
+        return false;
+
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                         BLUEZ_SERVICE,
+                                         mAdapterPath,
+                                         BLUEZ_ADAPTER_IFACE,
+                                         "FindDevice",
+                                         g_variant_new("(s)", address),
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+    if(err || !reply) {
+        LoggerE("Failed to find " << address << " device: " << err->message);
+        if(err)
+            g_error_free(err);
+
+        return false;
+    }
+
+    const char *device = NULL;
+    g_variant_get(reply, "(o)", &device);
+
+    // now we can remove the device
+    bool success = true;
+    if(device) {
+        g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                BLUEZ_SERVICE,
+                mAdapterPath,
+                BLUEZ_ADAPTER_IFACE,
+                "RemoveDevice",
+                g_variant_new("(o)", device), // floating variants are consumed
+                NULL,
+                G_DBUS_CALL_FLAGS_NONE,
+                -1,
+                NULL,
+                &err);
+        if(err) {
+            LoggerE("Failed to 'RemoveDevice': " << err->message);
+            g_error_free(err);
+            success = false;
+        }
+    }
+
+    g_variant_unref(reply);
+
+    return success;
+}
+
+// CONNMAN
+char *BluetoothAdapter::getBluetoothTechnology() {
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL,NULL),
+                                         CONNMAN_SERVICE,
+                                         "/",
+                                         CONNMAN_MANAGER_IFACE,
+                                         "GetTechnologies",
+                                         NULL,
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+
+    if(err || !reply) {
+        LoggerE("Failed to call 'GetTechnologies' DBUS method: " << (err?err->message:"reply is null"));
+        if(err)
+            g_error_free(err);
+        return NULL;
+    }
+
+    char *technology = NULL, *result = NULL;
+    GVariantIter *props = NULL;
+    GVariantIter *technologies = NULL;
+    g_variant_get(reply, "(a(oa{sv}))", &technologies);
+    while(g_variant_iter_next(technologies, "(oa{sv})", &technology, &props)) {
+        if(technology && strstr(technology, "bluetooth")) {
+            result = strdup(technology);
+            /*
+            // get the current Powered state
+            const char *key;
+            GVariant *value;
+            while(g_variant_iter_next(props, "{sv}", &key, &value)) {
+                if(!strcmp(key, "Powered")) {
+                    bool powered = g_variant_get_boolean(value);
+                    mEnabled = powered;
+                    LoggerD("Bluetooth is initially Powered " << (powered?"ON":"OFF"));
+                    break;
+                }
+            }
+            */
+            break;
+        }
+    }
+
+    g_variant_unref(reply);
+    return result;
+}
+
+bool BluetoothAdapter::setBluetoothPowered(bool value) {
+    if(mBluetoothTechnology) {
+        GError *err = NULL;
+        g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL,NULL),
+                                     CONNMAN_SERVICE,
+                                     mBluetoothTechnology,
+                                     CONNMAN_TECHNOLOGY_IFACE,
+                                     "SetProperty",
+                                     g_variant_new ("(sv)", // floating parameters are consumed, no cleanup/unref needed
+                                         "Powered",
+                                         g_variant_new_boolean(value)
+                                     ),
+                                     NULL,
+                                     G_DBUS_CALL_FLAGS_NONE,
+                                     -1,
+                                     NULL,
+                                     &err);
+
+        if(err) {
+            if((value  && strstr(err->message, "Already enabled")) || // it's not an error, 'casue the BT is already Powered ON
+               (!value && strstr(err->message, "Already disabled")))  // it's not an error, 'cause the BT is already Powered OFF
+            {
+                g_error_free(err);
+                return true;
+            }
+            LoggerE("Failed to call \"SetProperty\" DBUS method: " << err->message);
+            g_error_free(err);
+            return false;
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+} // Bluetooth
+} // DeviceAPI
+
diff --git a/src/BluetoothAdapter.h b/src/BluetoothAdapter.h
new file mode 100644 (file)
index 0000000..2c11d30
--- /dev/null
@@ -0,0 +1,190 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_ADAPTER_H__
+#define __TIZEN_BLUETOOTH_ADAPTER_H__
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include <bluetooth.h>
+
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+#include "BluetoothDevice.h"
+#include "BluetoothServiceHandler.h"
+#include "BluetoothSocket.h"
+
+// BLUEZ
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <gio/gio.h>
+// BLUEZ
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothConnReq
+{
+public:
+    BluetoothConnReq(std::string uuid, Common::MultiCallbackUserDataPtr userData)
+    {
+        mUUID = uuid;
+        mUserData = userData;
+    };
+
+    std::string mUUID;
+    Common::MultiCallbackUserDataPtr mUserData;
+};
+typedef BluetoothConnReq* BluetoothConnReqPtr;
+
+class BluetoothAdapter
+{
+public:
+    enum adapterAsyncE
+    {
+        SET_POWERED = 0,
+        SET_NAME,
+        SET_VISIBLE,
+        DISCOVER_DEVICES,
+        STOP_DISCOVERY,
+        CREATE_BONDING,
+        DESTROY_BONDING,
+    };
+
+    bool getPowered() const;
+    void setPowered(bool powered, Common::MultiCallbackUserDataPtr userData);
+    std::string getName() const;
+    void setName(std::string &name, Common::MultiCallbackUserDataPtr userData);
+    std::string getAddress() const;
+    bool getVisible() const;
+    void setVisible(bool visible, unsigned int timeout, Common::MultiCallbackUserDataPtr userData);
+    void setChangeListener(Common::MultiCallbackUserDataPtr userData);
+    void unsetChangeListener();
+    void discoverDevices(Common::MultiCallbackUserDataPtr userData);
+    void stopDiscovery(Common::MultiCallbackUserDataPtr userData);
+    void getKnownDevices(Common::MultiCallbackUserDataPtr userData);
+    void getDevice(std::string &address, Common::MultiCallbackUserDataPtr userData);
+    void createBonding(std::string &address, Common::MultiCallbackUserDataPtr userData);
+    void destroyBonding(std::string &address, Common::MultiCallbackUserDataPtr userData);
+    void registerRFCOMMServiceByUUID(std::string &uuid, std::string &name, Common::MultiCallbackUserDataPtr userData);
+    void connectToServiceByUUID(std::string &remoteAddress, std::string &uuid, Common::MultiCallbackUserDataPtr userData);
+
+    void returnKnownDevices(Common::MultiCallbackUserDataPtr userData);
+    void returnDevice(std::string &address, Common::MultiCallbackUserDataPtr userData);
+    void returnRegisteredService(std::string &uuid, std::string &name, Common::MultiCallbackUserDataPtr userData);
+
+    void unregisterUUID(std::string &uuid);
+    bool closeConnectedSocket(int socket);
+    void removeConnReq(std::string &remoteAddress);
+
+    static BluetoothAdapter* getInstance();
+    static bool isBluetoothSupported();
+    static bool isValidAddress(std::string &address);
+    static bool isValidUUID(std::string &uuid);
+    void unloadFrame(JSContextRef context);
+
+private:
+    BluetoothAdapter();
+    virtual ~BluetoothAdapter();
+
+    // BLUEZ
+    gchar* getDefaultAdapter() const;
+    bool isAdapterPowered();
+    bool isDevicePaired(const char *device);
+    bool setAdapterPowered(bool value);
+    bool getDeviceInfo(bt_device_info_s *deviceInfo, const char *device);
+    bool getDeviceInfoByAddress(bt_device_info_s *deviceInfo, const char *address);
+    static void handleSignal(GDBusConnection *connection,
+                             const gchar     *sender,
+                             const gchar     *object_path,
+                             const gchar     *interface_name,
+                             const gchar     *signal_name,
+                             GVariant        *parameters,
+                             gpointer         user_data);
+    void onPoweredChanged(bool powered);
+    void onNameChanged(const char *name);
+    void onVisibilityChanged(bool visible);
+    bool setupAgent(const char *agent);
+    static void agentHandleMethodCall( GDBusConnection       *connection,
+                                       const gchar           *sender,
+                                       const gchar           *object_path,
+                                       const gchar           *interface_name,
+                                       const gchar           *method_name,
+                                       GVariant              *parameters,
+                                       GDBusMethodInvocation *invocation,
+                                       gpointer               user_data);
+    static void asyncCreatePairedDeviceCallback(GObject *source, GAsyncResult *result, gpointer user_data);
+    bool removeDevice(const char *address);
+
+    char *getBluetoothTechnology(); // ConnMan
+    bool setBluetoothPowered(bool value); // ConnMan
+    bool isBtTechnologyPowered(); // ConnMan
+    // BLUEZ
+
+    void freeDeviceInfo(bt_device_info_s *deviceInfo);
+    void freeDiscoveryInfo(bt_adapter_device_discovery_info_s *discoveryInfo);
+
+    // checks whther a device given by its MAC address is in the list, or not
+    bool isDeviceInList(std::vector<BluetoothDeviceSharedPtr> list, const char *address);
+
+    //static void onStateChangedCB(int result, bt_adapter_state_e adapterState, void *userData);
+    //static void onNameChangedCB(char *name, void *userData);
+    //static void onVisibilityChangedCB(int result, bt_adapter_visibility_mode_e visibilityMode, void *userData);
+    //static void  onDiscoveryStateChangedCB(int result, bt_adapter_device_discovery_state_e discoveryState,
+    //        bt_adapter_device_discovery_info_s *discoveryInfo, void *userData);
+    static bool foreachBondedDevicesCB(bt_device_info_s *deviceInfo, void *userData);
+    //static void onBondCreatedCB(int result, bt_device_info_s *deviceInfo, void *userData);
+    //static void onBondDestroyedCB(int result, char *remoteAddress, void *userData);
+    static void onSocketConnected(int result, bt_socket_connection_state_e state, bt_socket_connection_s *connection, void *userData);
+    static void onSocketReceivedCB(bt_socket_received_data_s *data, void *userData);
+
+    typedef std::multimap<std::string, BluetoothConnReqPtr> ConnReqMultiMapT;   // <remoteAddress, BluetoothConnReqPtr>
+    typedef std::map<std::string, BluetoothServiceHandlerPtr> RegisteredUUIDMapT;   // <UUID, BluetoothServiceHandlerPtr>
+    typedef std::map<int, BluetoothSocketPtr> ConnectedSocketMapT;   // <socketFD, BluetoothSocketPtr>
+
+    // BLUEZ
+    gchar* mAdapterPath;
+    int mAgentRegistrationId;
+    GDBusInterfaceVTable mAgentIfaceVTable;
+    GDBusNodeInfo   *mAgentIntrospectionData;
+    char *mBluetoothTechnology;
+    //
+    Common::MultiCallbackUserDataPtr mChangeListener;
+    bool mEnabled;
+    ConnReqMultiMapT mConnReqMap;
+    RegisteredUUIDMapT mRegisteredUUID;
+    ConnectedSocketMapT mConnectedSocket;
+    //bool mRequestedState;
+    std::string mRequestedName;
+    bt_adapter_visibility_mode_e mRequestedVisibility;
+    std::string mCreateBondingAddress;
+    std::string mDestroyBondingAddress;
+    Common::MultiCallbackUserDataPtr mUserDataList[DESTROY_BONDING + 1];
+    std::vector<std::string> mDisappearedDevices;
+    std::vector<BluetoothDeviceSharedPtr> mFoundDevices;
+    std::vector<BluetoothDeviceSharedPtr> knownDevices;
+};
+
+typedef BluetoothAdapter* BluetoothAdapterPtr;
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_ADAPTER_H__
diff --git a/src/BluetoothCallbackUtil.cpp b/src/BluetoothCallbackUtil.cpp
new file mode 100644 (file)
index 0000000..1c10078
--- /dev/null
@@ -0,0 +1,120 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Ecore.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+
+#include "BluetoothCallbackUtil.h"
+#include "BluetoothAdapter.h"
+
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+static Eina_Bool jobCompleteCB(void *userData){
+    BluetoothCallbackUserDataPtr data = static_cast<BluetoothCallbackUserDataPtr>(userData);
+
+    if(!data) {
+        LoggerW("BluetoothCallbackUserDataPtr is NULL");
+        return false;
+    }
+
+    if(!(data->mUserData)) {
+        LoggerW("MulticallbackUserData is NULL");
+        delete data;
+        return false;
+    }
+
+    switch(data->mCBType) {
+        case BluetoothCallbackUserData::BT_CB_SUCCESS:
+        {
+            LoggerD("BT_CB_SUCCESS");
+            data->mUserData->invokeCallback("success");
+            break;
+        }
+        case BluetoothCallbackUserData::BT_CB_ERROR:
+        {
+            LoggerD("BT_CB_ERROR");
+            data->mUserData->invokeCallback("error", JSWebAPIErrorFactory::makeErrorObject(data->mUserData->getContext(), *(data->mError)));
+            break;
+        }
+        case BluetoothCallbackUserData::BT_CB_DEVICE:
+        {
+            LoggerD("BT_CB_DEVICE");
+            BluetoothAdapter::getInstance()->returnDevice(data->mAddress, data->mUserData);
+            break;
+        }
+        case BluetoothCallbackUserData::BT_CB_DEVICES:
+        {
+            LoggerD("BT_CB_DEVICES");
+            BluetoothAdapter::getInstance()->returnKnownDevices(data->mUserData);
+            break;
+        }
+        case BluetoothCallbackUserData::BT_CB_SERVICE:
+        {
+            LoggerD("BT_CB_SERVICE");
+            BluetoothAdapter::getInstance()->returnRegisteredService(data->mUUID, data->mName, data->mUserData);
+            break;
+        }
+        default:
+        {
+            LoggerW("Unknown callback type");
+        }
+    }
+
+    delete data;
+    return false;
+}
+
+void BluetoothCallbackUtil::syncToAsyncSuccessCallback(Common::MultiCallbackUserDataPtr userData)
+{
+    BluetoothCallbackUserDataPtr data = new BluetoothCallbackUserData(userData, BluetoothCallbackUserData::BT_CB_SUCCESS);
+    ecore_idler_add(jobCompleteCB, data);
+}
+
+void BluetoothCallbackUtil::syncToAsyncErrorCallback(DeviceAPI::Common::MultiCallbackUserDataPtr userData, Common::BasePlatformException *error)
+{
+    BluetoothCallbackUserDataPtr data = new BluetoothCallbackUserData(userData, error);
+    ecore_idler_add(jobCompleteCB, data);
+}
+
+void BluetoothCallbackUtil::syncToAsyncDeviceCallback(Common::MultiCallbackUserDataPtr userData, std::string &address)
+{
+    BluetoothCallbackUserDataPtr data = new BluetoothCallbackUserData(userData, address);
+    ecore_idler_add(jobCompleteCB, data);
+}
+
+void BluetoothCallbackUtil::syncToAsyncDeviceArrayCallback(Common::MultiCallbackUserDataPtr userData)
+{
+    BluetoothCallbackUserDataPtr data = new BluetoothCallbackUserData(userData, BluetoothCallbackUserData::BT_CB_DEVICES);
+    ecore_idler_add(jobCompleteCB, data);
+}
+
+void BluetoothCallbackUtil::syncToAsyncServiceCallback(Common::MultiCallbackUserDataPtr userData, std::string &uuid, std::string &name)
+{
+    BluetoothCallbackUserDataPtr data = new BluetoothCallbackUserData(userData, uuid, name);
+    ecore_idler_add(jobCompleteCB, data);
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/BluetoothCallbackUtil.h b/src/BluetoothCallbackUtil.h
new file mode 100644 (file)
index 0000000..e795f42
--- /dev/null
@@ -0,0 +1,105 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_CALLBACK_UTIL_H__
+#define __TIZEN_BLUETOOTH_CALLBACK_UTIL_H__
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+
+class BluetoothCallbackUserData
+{
+public:
+    typedef enum {
+        BT_CB_SUCCESS,
+        BT_CB_ERROR,
+        BT_CB_DEVICE,
+        BT_CB_DEVICES,
+        BT_CB_SERVICE
+    } callbackTypeE;
+
+
+    BluetoothCallbackUserData(DeviceAPI::Common::MultiCallbackUserDataPtr userData, callbackTypeE type)
+    {
+        mUserData = userData;
+        mCBType = type;
+    };
+
+    BluetoothCallbackUserData(DeviceAPI::Common::MultiCallbackUserDataPtr userData, Common::BasePlatformException *error)
+    {
+        mUserData = userData;
+        mError = error;
+        mCBType = BT_CB_ERROR;
+    };
+
+    BluetoothCallbackUserData(DeviceAPI::Common::MultiCallbackUserDataPtr userData, std::string &uuid, std::string &name)
+    {
+        mUserData = userData;
+        mCBType = BT_CB_SERVICE;
+        mUUID = uuid;
+        mName = name;
+    };
+
+    BluetoothCallbackUserData(DeviceAPI::Common::MultiCallbackUserDataPtr userData, std::string &address)
+    {
+        mUserData = userData;
+        mCBType = BT_CB_DEVICE;
+        mAddress = address;
+    };
+
+    virtual ~BluetoothCallbackUserData()
+    {
+        if(mCBType == BT_CB_ERROR)
+            delete mError;
+    };
+
+
+    callbackTypeE mCBType;
+    DeviceAPI::Common::MultiCallbackUserDataPtr mUserData;
+    Common::BasePlatformException *mError;
+    std::string mUUID;
+    std::string mName;
+    std::string mAddress;
+};
+
+typedef BluetoothCallbackUserData* BluetoothCallbackUserDataPtr;
+
+
+class BluetoothCallbackUtil
+{
+public:
+    static void syncToAsyncSuccessCallback(DeviceAPI::Common::MultiCallbackUserDataPtr userData);
+    static void syncToAsyncErrorCallback(DeviceAPI::Common::MultiCallbackUserDataPtr userData, Common::BasePlatformException *error);
+    static void syncToAsyncDeviceCallback(DeviceAPI::Common::MultiCallbackUserDataPtr userData, std::string &address);
+    static void syncToAsyncDeviceArrayCallback(DeviceAPI::Common::MultiCallbackUserDataPtr userData);
+    static void syncToAsyncServiceCallback(DeviceAPI::Common::MultiCallbackUserDataPtr userData, std::string &uuid, std::string &name);
+};
+
+
+} // Bluetooth
+} // DeviceAPI
+
+
+
+#endif // __TIZEN_BLUETOOTH_CALLBACK_UTIL_H__
diff --git a/src/BluetoothClass.cpp b/src/BluetoothClass.cpp
new file mode 100644 (file)
index 0000000..e1e23d8
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <JSUtil.h>
+
+#include "plugin_config.h"
+#include "BluetoothClass.h"
+#include "BluetoothClassDeviceMajor.h"
+#include "BluetoothClassDeviceMinor.h"
+#include "BluetoothClassDeviceService.h"
+#include "JSBluetoothClassDeviceService.h"
+
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothClass::BluetoothClass(bt_class_s bluetoothClass)
+{
+    mMajor = BluetoothClassDeviceMajor::getInstance()->getMajorValue(bluetoothClass.major_device_class);
+    mMinor = BluetoothClassDeviceMinor::getInstance()->getMinorValue(bluetoothClass.minor_device_class);
+    mServices= BluetoothClassDeviceService::getInstance()->getServiceValues(bluetoothClass.major_service_class_mask);
+}
+
+BluetoothClass::~BluetoothClass()
+{
+}
+
+unsigned long BluetoothClass::getMajor() const
+{
+    return mMajor;
+}
+
+unsigned long BluetoothClass::getMinor() const
+{
+    return mMinor;
+}
+
+JSValueRef BluetoothClass::getServices(JSContextRef context)
+{
+/*
+    JSValueRef service = mLocalProperty.getProperty(context, BLUETOOTH_CLASS_SERVICES);
+    if(service == NULL) {
+        service = JSUtil::toJSValueRef_(context, mServices);
+        mLocalProperty.setProperty(context, BLUETOOTH_CLASS_SERVICES, service);
+    }
+
+    return service;
+*/
+    return JSUtil::toJSValueRef_(context, mServices);
+}
+
+bool BluetoothClass::hasService(unsigned long service)
+{
+    for(std::vector<unsigned long>::iterator iter = mServices.begin(); iter != mServices.end(); ++iter) {
+        if((*iter) == service) {
+            return true;
+        }
+    }
+    return false;
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/BluetoothClass.h b/src/BluetoothClass.h
new file mode 100644 (file)
index 0000000..b4915bb
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_CLASS_H__
+#define __TIZEN_BLUETOOTH_CLASS_H__
+
+#include <string>
+#include <vector>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <bluetooth.h>
+
+#include <boost/shared_ptr.hpp>
+#include <PropertyBag.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothClass
+{
+public:
+    BluetoothClass(bt_class_s bluetoothClass);
+    virtual ~BluetoothClass();
+
+    unsigned long getMajor() const;
+    unsigned long getMinor() const;
+    JSValueRef getServices(JSContextRef context);
+
+    bool hasService(unsigned long service);
+
+private:
+    unsigned long mMajor;
+    unsigned long mMinor;
+    std::vector<unsigned long> mServices;
+    //Common::PropertyBag mLocalProperty;
+};
+
+typedef boost::shared_ptr<BluetoothClass> BluetoothClassSharedPtr;
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_CLASS_H__
diff --git a/src/BluetoothClassDeviceMajor.cpp b/src/BluetoothClassDeviceMajor.cpp
new file mode 100644 (file)
index 0000000..fb7f03d
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+
+#include "BluetoothClassDeviceMajor.h"
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothClassDeviceMajor::BluetoothClassDeviceMajor()
+{
+    mMajorStringMap.insert(std::pair<std::string, unsigned long>("MISC", 0x00));
+    mMajorStringMap.insert(std::pair<std::string, unsigned long>("COMPUTER", 0x01));
+    mMajorStringMap.insert(std::pair<std::string, unsigned long>("PHONE", 0x02));
+    mMajorStringMap.insert(std::pair<std::string, unsigned long>("NETWORK", 0x03));
+    mMajorStringMap.insert(std::pair<std::string, unsigned long>("AUDIO_VIDEO", 0x04));
+    mMajorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL", 0x05));
+    mMajorStringMap.insert(std::pair<std::string, unsigned long>("IMAGING", 0x06));
+    mMajorStringMap.insert(std::pair<std::string, unsigned long>("WEARABLE", 0x07));
+    mMajorStringMap.insert(std::pair<std::string, unsigned long>("TOY", 0x08));
+    mMajorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH", 0x09));
+    mMajorStringMap.insert(std::pair<std::string, unsigned long>("UNCATEGORIZED", 0x1F));
+
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(BT_MAJOR_DEVICE_CLASS_MISC, 0x00));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(BT_MAJOR_DEVICE_CLASS_COMPUTER, 0x01));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(BT_MAJOR_DEVICE_CLASS_PHONE, 0x02));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(BT_MAJOR_DEVICE_CLASS_LAN_NETWORK_ACCESS_POINT, 0x03));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(BT_MAJOR_DEVICE_CLASS_AUDIO_VIDEO, 0x04));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(BT_MAJOR_DEVICE_CLASS_PERIPHERAL, 0x05));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(BT_MAJOR_DEVICE_CLASS_IMAGING, 0x06));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(BT_MAJOR_DEVICE_CLASS_WEARABLE, 0x07));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(BT_MAJOR_DEVICE_CLASS_TOY, 0x08));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(BT_MAJOR_DEVICE_CLASS_HEALTH, 0x09));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(BT_MAJOR_DEVICE_CLASS_UNCATEGORIZED, 0x1F));
+}
+
+BluetoothClassDeviceMajor::~BluetoothClassDeviceMajor()
+{
+}
+
+BluetoothClassDeviceMajor* BluetoothClassDeviceMajor::getInstance()
+{
+    static BluetoothClassDeviceMajor instance;
+    return &instance;
+}
+
+unsigned long BluetoothClassDeviceMajor::getMajorValue(std::string major)
+{
+    return mMajorStringMap.find(major)->second;
+}
+
+unsigned long BluetoothClassDeviceMajor::getMajorValue(bt_major_device_class_e major)
+{
+    return mMajorEnumMap.find(major)->second;
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/BluetoothClassDeviceMajor.h b/src/BluetoothClassDeviceMajor.h
new file mode 100644 (file)
index 0000000..e57c927
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_CLASS_DEVICE_MAJOR_H__
+#define __TIZEN_BLUETOOTH_CLASS_DEVICE_MAJOR_H__
+
+#include <string>
+#include <map>
+#include <bluetooth.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothClassDeviceMajor
+{
+public:
+
+    BluetoothClassDeviceMajor();
+    virtual ~BluetoothClassDeviceMajor();
+
+    static BluetoothClassDeviceMajor* getInstance();
+    unsigned long getMajorValue(std::string major);
+    unsigned long getMajorValue(bt_major_device_class_e major);
+
+private:
+    std::map<std::string, unsigned long> mMajorStringMap;
+    std::map<bt_major_device_class_e, unsigned long> mMajorEnumMap;
+};
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_CLASS_DEVICE_MAJOR_H__
diff --git a/src/BluetoothClassDeviceMinor.cpp b/src/BluetoothClassDeviceMinor.cpp
new file mode 100644 (file)
index 0000000..5d77223
--- /dev/null
@@ -0,0 +1,203 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+
+#include "BluetoothClassDeviceMinor.h"
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothClassDeviceMinor::BluetoothClassDeviceMinor()
+{
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("COMPUTER_UNCATEGORIZED", 0x00));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("COMPUTER_DESKTOP", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("COMPUTER_SERVER", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("COMPUTER_LAPTOP", 0x03));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("COMPUTER_HANDHELD_PC_OR_PDA", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("COMPUTER_PALM_PC_OR_PDA", 0x5));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("COMPUTER_WEARABLE", 0x06));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PHONE_UNCATEGORIZED", 0x00));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PHONE_CELLULAR", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PHONE_CORDLESS", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PHONE_SMARTPHONE", 0x03));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PHONE_MODEM_OR_GATEWAY", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PHONE_ISDN", 0x05));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_UNRECOGNIZED", 0x00));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_WEARABLE_HEADSET", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_HANDSFREE", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_MICROPHONE", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_LOUDSPEAKER", 0x05));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_HEADPHONES", 0x06));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_PORTABLE_AUDIO", 0x07));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_CAR_AUDIO", 0x08));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_SETTOP_BOX", 0x09));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_HIFI", 0x0a));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_VCR", 0x0b));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_VIDEO_CAMERA", 0x0c));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_CAMCORDER", 0x0d));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_MONITOR", 0x0e));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_DISPLAY_AND_LOUDSPEAKER", 0x0f));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_VIDEO_CONFERENCING", 0x10));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("AV_GAMING_TOY", 0x12));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL_UNCATEGORIZED", 0));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL_KEYBOARD", 0x10));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL_POINTING_DEVICE", 0x20));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL_KEYBOARD_AND_POINTING_DEVICE", 0x30));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL_JOYSTICK", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL_GAMEPAD", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL_REMOTE_CONTROL", 0x03));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL_SENSING_DEVICE", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL_DEGITIZER_TABLET", 0x05));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL_CARD_READER", 0x06));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL_DIGITAL_PEN", 0x07));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL_HANDHELD_SCANNER", 0x08));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("PERIPHERAL_HANDHELD_INPUT_DEVICE", 0x09));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("IMAGING_UNCATEGORIZED", 0x00));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("IMAGING_DISPLAY", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("IMAGING_CAMERA", 0x08));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("IMAGING_SCANNER", 0x10));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("IMAGING_PRINTER", 0x20));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("WEARABLE_WRITST_WATCH", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("WEARABLE_PAGER", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("WEARABLE_JACKET", 0x03));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("WEARABLE_HELMET", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("WEARABLE_GLASSES", 0x05));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("TOY_ROBOT", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("TOY_VEHICLE", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("TOY_DOLL", 0x03));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("TOY_CONTROLLER", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("TOY_GAME", 0x05));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_UNDEFINED", 0x00));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_BLOOD_PRESSURE_MONITOR", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_THERMOMETER", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_WEIGHING_SCALE", 0x03));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_GLUCOSE_METER", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_PULSE_OXIMETER", 0x05));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_PULSE_RATE_MONITOR", 0x06));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_DATA_DISPLAY", 0x07));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_STEP_COUNTER", 0x08));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_BODY_COMPOSITION_ANALYZER", 0x09));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_PEAK_FLOW_MONITOR", 0x0a));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_MEDICATION_MONITOR", 0x0b));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_KNEE_PROSTHESIS", 0x0c));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>("HEALTH_ANKLE_PROSTHESIS", 0x0d));
+
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_COMPUTER_UNCATEGORIZED, 0x00));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_COMPUTER_DESKTOP_WORKSTATION , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_COMPUTER_SERVER_CLASS , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_COMPUTER_LAPTOP , 0x03));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_COMPUTER_HANDHELD_PC_OR_PDA , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_COMPUTER_PALM_SIZED_PC_OR_PDA, 0x5));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_COMPUTER_WEARABLE_COMPUTER , 0x06));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PHONE_UNCATEGORIZED , 0x00));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PHONE_CELLULAR , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PHONE_CORDLESS , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PHONE_SMART_PHONE , 0x03));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PHONE_WIRED_MODEM_OR_VOICE_GATEWAY , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PHONE_COMMON_ISDN_ACCESS , 0x05));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_UNCATEGORIZED , 0x00));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_WEARABLE_HEADSET , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_HANDS_FREE , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_MICROPHONE , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_LOUDSPEAKER , 0x05));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_HEADPHONES , 0x06));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_PORTABLE_AUDIO , 0x07));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_CAR_AUDIO , 0x08));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_SET_TOP_BOX , 0x09));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_HIFI_AUDIO_DEVICE , 0x0a));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VCR , 0x0b));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_CAMERA , 0x0c));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_CAMCORDER , 0x0d));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_MONITOR , 0x0e));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_DISPLAY_LOUDSPEAKER , 0x0f));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_CONFERENCING , 0x10));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_GAMING_TOY , 0x12));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PERIPHERA_UNCATEGORIZED , 0));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PERIPHERAL_KEY_BOARD , 0x10));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PERIPHERAL_POINTING_DEVICE , 0x20));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PERIPHERAL_COMBO_KEYBOARD_POINTING_DEVICE , 0x30));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PERIPHERAL_JOYSTICK , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PERIPHERAL_GAME_PAD , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PERIPHERAL_REMOTE_CONTROL , 0x03));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PERIPHERAL_SENSING_DEVICE , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PERIPHERAL_DIGITIZER_TABLET , 0x05));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PERIPHERAL_CARD_READER , 0x06));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PERIPHERAL_DIGITAL_PEN , 0x07));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PERIPHERAL_HANDHELD_SCANNER , 0x08));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_PERIPHERAL_HANDHELD_GESTURAL_INPUT_DEVICE , 0x09));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_IMAGING_DISPLAY , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_IMAGING_CAMERA , 0x08));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_IMAGING_SCANNER , 0x10));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_IMAGING_PRINTER, 0x20));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_WEARABLE_WRIST_WATCH , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_WEARABLE_PAGER , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_WEARABLE_JACKET , 0x03));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_WEARABLE_HELMET , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_WEARABLE_GLASSES , 0x05));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_TOY_ROBOT , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_TOY_VEHICLE , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_TOY_DOLL_ACTION , 0x03));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_TOY_CONTROLLER , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_TOY_GAME , 0x05));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_UNCATEGORIZED , 0x00));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_BLOOD_PRESSURE_MONITOR , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_THERMOMETER , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_WEIGHING_SCALE , 0x03));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_GLUCOSE_METER , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_PULSE_OXIMETER , 0x05));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_HEART_PULSE_RATE_MONITOR , 0x06));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_DATA_DISPLAY , 0x07));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_STEP_COUNTER , 0x08));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_BODY_COMPOSITION_ANALYZER , 0x09));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_PEAK_FLOW_MONITOR , 0x0a));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_MEDICATION_MONITOR , 0x0b));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_KNEE_PROSTHESIS , 0x0c));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(BT_MINOR_DEVICE_CLASS_HEATH_ANKLE_PROSTHESIS , 0x0d));
+}
+
+BluetoothClassDeviceMinor::~BluetoothClassDeviceMinor()
+{
+}
+
+BluetoothClassDeviceMinor* BluetoothClassDeviceMinor::getInstance()
+{
+    static BluetoothClassDeviceMinor instance;
+    return &instance;
+}
+
+unsigned long BluetoothClassDeviceMinor::getMinorValue(std::string minor)
+{
+    return mMinorStringMap.find(minor)->second;
+}
+
+unsigned long BluetoothClassDeviceMinor::getMinorValue(bt_minor_device_class_e minor)
+{
+    // F/W provides more minor deivce class
+    std::map<bt_minor_device_class_e, unsigned long>::iterator iter = mMinorEnumMap.find(minor);
+    if(iter != mMinorEnumMap.end()) {
+        return iter->second;
+    }
+
+    return 0;
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/BluetoothClassDeviceMinor.h b/src/BluetoothClassDeviceMinor.h
new file mode 100644 (file)
index 0000000..90f62da
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_CLASS_DEVICE_MINOR_H__
+#define __TIZEN_BLUETOOTH_CLASS_DEVICE_MINOR_H__
+
+#include <string>
+#include <map>
+#include <bluetooth.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothClassDeviceMinor
+{
+public:
+    BluetoothClassDeviceMinor();
+    virtual ~BluetoothClassDeviceMinor();
+
+    static BluetoothClassDeviceMinor* getInstance();
+    unsigned long getMinorValue(std::string minor);
+    unsigned long getMinorValue(bt_minor_device_class_e minor);
+
+private:
+    std::map<std::string, unsigned long> mMinorStringMap;
+    std::map<bt_minor_device_class_e, unsigned long> mMinorEnumMap;
+};
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_CLASS_DEVICE_MINOR_H__
diff --git a/src/BluetoothClassDeviceService.cpp b/src/BluetoothClassDeviceService.cpp
new file mode 100644 (file)
index 0000000..9163af3
--- /dev/null
@@ -0,0 +1,84 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+
+#include "BluetoothClassDeviceService.h"
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothClassDeviceService::BluetoothClassDeviceService()
+{
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>("LIMITED_DISCOVERABILITY", 0x0001));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>("POSITIONING", 0x0008));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>("NETWORKING", 0x0010));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>("RENDERING", 0x0020));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>("CAPTURING", 0x0040));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>("OBJECT_TRANSFER", 0x0080));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>("AUDIO", 0x0100));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>("TELEPHONY", 0x0200));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>("INFORMATION", 0x0400));
+
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(BT_MAJOR_SERVICE_CLASS_LIMITED_DISCOVERABLE_MODE, 0x0001));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(BT_MAJOR_SERVICE_CLASS_POSITIONING, 0x0008));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(BT_MAJOR_SERVICE_CLASS_NETWORKING, 0x0010));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(BT_MAJOR_SERVICE_CLASS_RENDERING, 0x0020));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(BT_MAJOR_SERVICE_CLASS_CAPTURING, 0x0040));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(BT_MAJOR_SERVICE_CLASS_OBJECT_TRANSFER, 0x0080));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(BT_MAJOR_SERVICE_CLASS_AUDIO, 0x0100));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(BT_MAJOR_SERVICE_CLASS_TELEPHONY, 0x0200));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(BT_MAJOR_SERVICE_CLASS_INFORMATION, 0x0400));
+}
+
+BluetoothClassDeviceService::~BluetoothClassDeviceService()
+{
+}
+
+BluetoothClassDeviceService* BluetoothClassDeviceService::getInstance()
+{
+    static BluetoothClassDeviceService instance;
+    return &instance;
+}
+
+unsigned long BluetoothClassDeviceService::getServiceValue(std::string service)
+{
+    return mServiceStringMap.find(service)->second;
+}
+
+unsigned long BluetoothClassDeviceService::getServiceValue(bt_major_service_class_e service)
+{
+    return mServiceEnumMap.find(service)->second;
+}
+
+std::vector<unsigned long> BluetoothClassDeviceService::getServiceValues(int serviceMask)
+{
+    std::vector<unsigned long> ret;
+    for(std::map<bt_major_service_class_e, unsigned long>::iterator iter = mServiceEnumMap.begin(); iter != mServiceEnumMap.end(); iter++) {
+        if(iter->first & serviceMask) {
+            ret.push_back(iter->second);
+        }
+    }
+
+    return ret;
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/BluetoothClassDeviceService.h b/src/BluetoothClassDeviceService.h
new file mode 100644 (file)
index 0000000..7d05f9b
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_CLASS_DEVICE_SERVICE_H__
+#define __TIZEN_BLUETOOTH_CLASS_DEVICE_SERVICE_H__
+
+#include <string>
+#include <map>
+#include <vector>
+#include <bluetooth.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothClassDeviceService
+{
+public:
+    BluetoothClassDeviceService();
+    virtual ~BluetoothClassDeviceService();
+
+    static BluetoothClassDeviceService* getInstance();
+    unsigned long getServiceValue(std::string service);
+    unsigned long getServiceValue(bt_major_service_class_e service);
+    std::vector<unsigned long> getServiceValues(int serviceMask);
+
+private:
+    std::map<std::string, unsigned long> mServiceStringMap;
+    std::map<bt_major_service_class_e, unsigned long> mServiceEnumMap;
+};
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_CLASS_DEVICE_SERVICE_H__
diff --git a/src/BluetoothDevice.cpp b/src/BluetoothDevice.cpp
new file mode 100644 (file)
index 0000000..4f97bbb
--- /dev/null
@@ -0,0 +1,324 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <JSUtil.h>
+
+#include "plugin_config.h"
+#include "BluetoothDevice.h"
+#include "BluetoothAdapter.h"
+#include "JSBluetoothClass.h"
+
+#include <Logger.h>
+
+//BLUEZ
+#define BLUEZ_PREFIX            "org.bluez"
+#define BLUEZ_SERVICE           BLUEZ_PREFIX
+#define BLUEZ_MANAGER_IFACE     BLUEZ_PREFIX ".Manager"
+#define BLUEZ_ADAPTER_IFACE     BLUEZ_PREFIX ".Adapter"
+#define BLUEZ_DEVICE_IFACE      BLUEZ_PREFIX ".Device"
+//BLUEZ
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothDevice::BluetoothDevice(bt_adapter_device_discovery_info_s *discoveryInfo)
+{
+    mName = std::string(discoveryInfo->remote_name);
+    mAddress = std::string(discoveryInfo->remote_address);
+    mDeviceClass = BluetoothClassSharedPtr(new BluetoothClass(discoveryInfo->bt_class));
+    for(int i = 0; i < discoveryInfo->service_count; i++) {
+        mUUIDs.push_back(std::string(discoveryInfo->service_uuid[i]));
+    }
+    isUpdated = true;
+}
+
+BluetoothDevice::BluetoothDevice(bt_device_info_s *deviceInfo)
+{
+    mName = std::string(deviceInfo->remote_name);
+    mAddress = std::string(deviceInfo->remote_address);
+    mDeviceClass = BluetoothClassSharedPtr(new BluetoothClass(deviceInfo->bt_class));
+    for(int i = 0; i < deviceInfo->service_count; i++) {
+        mUUIDs.push_back(std::string(deviceInfo->service_uuid[i]));
+    }
+    isUpdated = true;
+}
+
+BluetoothDevice::~BluetoothDevice()
+{
+    BluetoothAdapter::getInstance()->removeConnReq(mAddress);
+}
+
+void BluetoothDevice::updateInfo(bt_device_info_s *deviceInfo)
+{
+    mName = std::string(deviceInfo->remote_name);
+    mUUIDs.clear();
+    for(int i = 0; i < deviceInfo->service_count; i++) {
+        mUUIDs.push_back(std::string(deviceInfo->service_uuid[i]));
+    }
+    isUpdated = true;
+}
+
+std::string BluetoothDevice::getName() const
+{
+    return mName;
+}
+
+std::string BluetoothDevice::getAddress() const
+{
+    return mAddress;
+}
+
+JSValueRef BluetoothDevice::getDeviceClass(JSContextRef context)
+{
+    return JSBluetoothClass::createJSObject(context, mDeviceClass);
+}
+
+gchar* BluetoothDevice::getDefaultAdapter() const
+{
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                         BLUEZ_SERVICE,
+                                         "/",
+                                         BLUEZ_MANAGER_IFACE,
+                                         "DefaultAdapter",
+                                         NULL,
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+    if(err || !reply) {
+        if(err) {
+            LoggerE("Failed to get default adapter: " << err->message);
+            g_error_free(err);
+        }
+        if(!reply)
+            LoggerE("Reply from 'DefaultAdapter' is null");
+        return NULL;
+    }
+
+    char *adapter = NULL;
+    g_variant_get(reply, "(o)", &adapter);
+
+    // make a copy of adapter, 'cause it will be destroyed when 'reply' is un-refed
+    char *result = adapter?strdup(adapter):NULL;
+
+    g_variant_unref(reply);
+
+    return result;
+}
+
+char *BluetoothDevice::getDevice() const
+{
+    if(!strcmp(mAddress.c_str(), "")) {
+        LoggerE("Invalid address");
+        return NULL;
+    }
+
+    char *adapter = getDefaultAdapter();
+    if(!adapter) {
+        LoggerE("Failed to get default adapter");
+        return NULL;
+    }
+
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+            BLUEZ_SERVICE,
+            adapter,
+            BLUEZ_ADAPTER_IFACE,
+            "FindDevice",
+            g_variant_new("(s)", mAddress.c_str()),
+            NULL,
+            G_DBUS_CALL_FLAGS_NONE,
+            -1,
+            NULL,
+            &err);
+
+    if(err || !reply) {
+        //LoggerE("Failed to find " << mAddress << " device: " << (err?err->message:"Invalid reply"));
+        if(err)
+            g_error_free(err);
+        free(adapter);
+        return NULL;
+    }
+
+    char *device = NULL;
+    g_variant_get(reply, "(o)", &device);
+
+    // make a copy of adapter, 'cause it will be destroyed when 'reply' is un-refed
+    char *result = device?strdup(device):NULL;
+
+    g_variant_unref(reply);
+    free(adapter);
+
+    return result;
+}
+
+bool BluetoothDevice::isBonded() const
+{
+    char *device = getDevice();
+    if(!device) {
+        //LoggerE("Failed to get device object");
+        return false;
+    }
+
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                         BLUEZ_SERVICE,
+                                         device,
+                                         BLUEZ_DEVICE_IFACE,
+                                         "GetProperties",
+                                         NULL,
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+    if(err || !reply) {
+        if(err)
+            g_error_free(err);
+
+        free(device);
+        return false;
+    }
+
+    GVariantIter *iter;
+    g_variant_get(reply, "(a{sv})", &iter);
+    const char *key;
+    GVariant *value;
+    bool paired = false;
+    while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+        if(!strcmp(key, "Paired")) {
+            paired = g_variant_get_boolean(value);
+            break;
+        }
+    }
+
+    g_variant_unref(reply);
+    free(device);
+
+    return paired;
+}
+
+bool BluetoothDevice::isTrusted() const
+{
+    char *device = getDevice();
+    if(!device) {
+        //LoggerE("Failed to get device object");
+        return false;
+    }
+
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                         BLUEZ_SERVICE,
+                                         device,
+                                         BLUEZ_DEVICE_IFACE,
+                                         "GetProperties",
+                                         NULL,
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+    if(err || !reply) {
+        if(err)
+            g_error_free(err);
+
+        free(device);
+        return false;
+    }
+
+    GVariantIter *iter;
+    g_variant_get(reply, "(a{sv})", &iter);
+    const char *key;
+    GVariant *value;
+    bool trusted = false;
+    while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+        if(!strcmp(key, "Trusted")) {
+            trusted = g_variant_get_boolean(value);
+            break;
+        }
+    }
+
+    g_variant_unref(reply);
+    free(device);
+
+    return trusted;
+}
+
+bool BluetoothDevice::isConnected() const
+{
+    char *device = getDevice();
+    if(!device) {
+        //LoggerE("Failed to get device object");
+        return false;
+    }
+
+    GError *err = NULL;
+    GVariant *reply = NULL;
+    reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
+                                         BLUEZ_SERVICE,
+                                         device,
+                                         BLUEZ_DEVICE_IFACE,
+                                         "GetProperties",
+                                         NULL,
+                                         NULL,
+                                         G_DBUS_CALL_FLAGS_NONE,
+                                         -1,
+                                         NULL,
+                                         &err);
+    if(err || !reply) {
+        if(err)
+            g_error_free(err);
+
+        free(device);
+        return false;
+    }
+
+    GVariantIter *iter;
+    g_variant_get(reply, "(a{sv})", &iter);
+    const char *key;
+    GVariant *value;
+    bool connected = false;
+    while(g_variant_iter_next(iter, "{sv}", &key, &value)) {
+        if(!strcmp(key, "Connected")) {
+            connected = g_variant_get_boolean(value);
+            break;
+        }
+    }
+
+    g_variant_unref(reply);
+    free(device);
+
+    return connected;
+}
+
+JSValueRef BluetoothDevice::getUUIDs(JSContextRef context)
+{
+    return JSUtil::toJSValueRef(context, mUUIDs);
+}
+
+} // Bluetooth
+} // DeviceAPI
+
diff --git a/src/BluetoothDevice.h b/src/BluetoothDevice.h
new file mode 100644 (file)
index 0000000..86429ac
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_DEVICE_H__
+#define __TIZEN_BLUETOOTH_DEVICE_H__
+
+#include <string>
+#include <vector>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <bluetooth.h>
+#include <boost/shared_ptr.hpp>
+#include <PropertyBag.h>
+
+#include "BluetoothClass.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothDevice
+{
+public:
+    BluetoothDevice(bt_adapter_device_discovery_info_s *discoveryInfo);
+    BluetoothDevice(bt_device_info_s *deviceInfo);
+    virtual ~BluetoothDevice();
+
+    void updateInfo(bt_device_info_s *deviceInfo);
+    std::string getName() const;
+    std::string getAddress() const;
+    JSValueRef getDeviceClass(JSContextRef context);
+    bool isBonded() const;
+    bool isTrusted() const;
+    bool isConnected() const;
+    JSValueRef getUUIDs(JSContextRef context);
+
+private:
+    char *getDefaultAdapter() const;
+    char *getDevice() const;
+
+private:
+    std::string mName;
+    std::string mAddress;
+    BluetoothClassSharedPtr mDeviceClass;
+    std::vector<std::string> mUUIDs;
+    //Common::PropertyBag mLocalProperty;
+    bool isUpdated;
+};
+
+typedef boost::shared_ptr<BluetoothDevice> BluetoothDeviceSharedPtr;
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_DEVICE_H__
diff --git a/src/BluetoothServiceHandler.cpp b/src/BluetoothServiceHandler.cpp
new file mode 100644 (file)
index 0000000..253bb15
--- /dev/null
@@ -0,0 +1,126 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+
+#include "BluetoothServiceHandler.h"
+#include "BluetoothAdapter.h"
+#include "BluetoothCallbackUtil.h"
+#include "plugin_config.h"
+
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothServiceHandler::BluetoothServiceHandler(std::string uuid, std::string name, int registeredSocket)
+{
+    mUUID = uuid;
+    mName = name;
+    mRegisteredSocket = registeredSocket;
+    mIsRegistered = true;
+    mIsConnected = false;
+}
+
+BluetoothServiceHandler::~BluetoothServiceHandler()
+{
+    if(mIsRegistered) {
+        BluetoothAdapter::getInstance()->unregisterUUID(mUUID);
+        if(bt_socket_destroy_rfcomm(mRegisteredSocket) != BT_ERROR_NONE) {
+            LoggerW("Already destroyed");
+        }
+    }
+}
+
+bool BluetoothServiceHandler::setOnConnect(JSContextRef context, JSObjectRef onConnect)
+{
+    MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+    if(!callback){
+        LoggerW("Can't create MultiCallbackUserData");
+        return false;
+    }
+    callback->setCallback("onconnect", onConnect);
+    mOnConnect = callback;
+
+    return mLocalProperty.setProperty(context, BLUETOOTH_SERVICE_HANDLER_ONCONNECT, onConnect);
+}
+
+std::string BluetoothServiceHandler::getUUID() const
+{
+    return mUUID;
+}
+
+std::string BluetoothServiceHandler::getName() const
+{
+    return mName;
+}
+
+int BluetoothServiceHandler::getRegisteredSocket() const
+{
+    return mRegisteredSocket;
+}
+
+MultiCallbackUserDataPtr BluetoothServiceHandler::getOnConnect() const
+{
+    return mOnConnect;
+}
+
+JSValueRef BluetoothServiceHandler::getOnConnect(JSContextRef context)
+{
+    JSValueRef onConnect = mLocalProperty.getProperty(context, BLUETOOTH_SERVICE_HANDLER_ONCONNECT);
+    if(onConnect == NULL) {
+        LoggerD("onconnect is null");
+        return JSValueMakeNull(context);
+    }
+
+    return onConnect;
+}
+
+void BluetoothServiceHandler::setConnectionState(bool isConnected)
+{
+    mIsConnected = isConnected;
+}
+
+bool BluetoothServiceHandler::getConnectionState()
+{
+    return mIsConnected;
+}
+
+void BluetoothServiceHandler::unregister(MultiCallbackUserDataPtr userData)
+{
+    if(BluetoothAdapter::getInstance()->getPowered() == true) {
+        if(bt_socket_destroy_rfcomm(mRegisteredSocket) == BT_ERROR_NONE) {
+            mIsRegistered = false;
+            BluetoothAdapter::getInstance()->unregisterUUID(mUUID);
+            BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+        }
+        else {
+            UnknownException *error = new UnknownException("Unknown exception");
+            BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+        }
+    } else {   // Not enabled
+        ServiceNotAvailableException *error = new ServiceNotAvailableException("Bluetooth device is turned off");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, error);
+    }
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/BluetoothServiceHandler.h b/src/BluetoothServiceHandler.h
new file mode 100644 (file)
index 0000000..11dc506
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_SERVICE_HANDLER_H__
+#define __TIZEN_BLUETOOTH_SERVICE_HANDLER_H__
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+
+//#include <boost/shared_ptr.hpp>
+#include <MultiCallbackUserData.h>
+#include <PropertyBag.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothServiceHandler
+{
+public:
+    BluetoothServiceHandler(std::string uuid, std::string name, int registeredSocket);
+    virtual ~BluetoothServiceHandler();
+
+    std::string getUUID() const;
+    std::string getName() const;
+    int getRegisteredSocket() const;
+    bool getConnectionState();
+    Common::MultiCallbackUserDataPtr getOnConnect() const;
+    JSValueRef getOnConnect(JSContextRef context);
+
+    void setConnectionState(bool isConnected);
+    bool setOnConnect(JSContextRef context, JSObjectRef onConnect);
+
+    void unregister(Common::MultiCallbackUserDataPtr userData);
+
+private:
+    std::string mUUID;
+    std::string mName;
+    int mRegisteredSocket;
+    bool mIsConnected;
+    bool mIsRegistered;
+    Common::MultiCallbackUserDataPtr mOnConnect;
+    Common::PropertyBag mLocalProperty;
+};
+
+typedef BluetoothServiceHandler* BluetoothServiceHandlerPtr;
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_SERVICE_HANDLER_H__
diff --git a/src/BluetoothSocket.cpp b/src/BluetoothSocket.cpp
new file mode 100644 (file)
index 0000000..018cbc1
--- /dev/null
@@ -0,0 +1,225 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+
+#include "BluetoothSocket.h"
+#include "BluetoothAdapter.h"
+#include "plugin_config.h"
+#include "JSBluetoothDevice.h"
+
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothSocket::BluetoothSocket(bt_socket_connection_s *connection)
+{
+    mConnectedSocket = connection->socket_fd;
+    mUUID = std::string(connection->service_uuid);
+    mIsConnected = true;
+
+    bt_device_info_s *deviceInfo = NULL;
+    if(bt_adapter_get_bonded_device_info(connection->remote_address, &deviceInfo) == BT_ERROR_NONE && deviceInfo != NULL) {
+        BluetoothDeviceSharedPtr device(new BluetoothDevice(deviceInfo));
+        mPeer = device;
+        bt_adapter_free_device_info(deviceInfo);
+    }
+}
+
+BluetoothSocket::~BluetoothSocket()
+{
+    if(mIsConnected) {
+        if(bt_socket_disconnect_rfcomm(mConnectedSocket) != BT_ERROR_NONE) {
+            LoggerW("Already disconnected");
+        }
+
+        if(!BluetoothAdapter::getInstance()->closeConnectedSocket(mConnectedSocket)) {
+            LoggerW("Already done");
+        }
+    }
+}
+
+bool BluetoothSocket::setOnMessage(JSContextRef context, JSObjectRef onMessage)
+{
+    MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+    if(!callback){
+        LoggerW("Can't create MultiCallbackUserData");
+        return false;
+    }
+    callback->setCallback("onmessage", onMessage);
+    mOnMessage = callback;
+
+    return mLocalProperty.setProperty(context, BLUETOOTH_SOCKET_ONMESSAGE, onMessage);
+}
+
+bool BluetoothSocket::setOnClose(JSContextRef context, JSObjectRef onClose)
+{
+    MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+    if(!callback){
+        LoggerW("Can't create MultiCallbackUserData");
+        return false;
+    }
+    callback->setCallback("onclose", onClose);
+    mOnClose = callback;
+
+    return mLocalProperty.setProperty(context, BLUETOOTH_SOCKET_ONCLOSE, onClose);
+}
+
+bool BluetoothSocket::setOnError(JSContextRef context, JSObjectRef onError)
+{
+    MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+    if(!callback){
+        LoggerW("Can't create MultiCallbackUserData");
+        return false;
+    }
+    callback->setCallback("onerror", onError);
+    mOnError = callback;
+
+    return mLocalProperty.setProperty(context, BLUETOOTH_SOCKET_ONERROR, onError);
+}
+
+std::string BluetoothSocket::getUUID() const
+{
+    return mUUID;
+}
+
+void BluetoothSocket::setConnectionState(bool isConnected)
+{
+    mIsConnected = isConnected;
+}
+
+bool BluetoothSocket::getConnectionState()
+{
+    return mIsConnected;
+}
+
+JSValueRef BluetoothSocket::getPeer(JSContextRef context)
+{
+    /*
+    JSValueRef peer = mLocalProperty.getProperty(context, BLUETOOTH_SOCKET_PEER);
+    if(peer == NULL && mPeer != NULL) {
+        peer = JSBluetoothDevice::createJSObject(context, mPeer);
+        mLocalProperty.setProperty(context, BLUETOOTH_DEVICE_DEVICE_CLASS, peer);
+    }
+
+    return peer;
+    */
+    return JSBluetoothDevice::createJSObject(context, mPeer);
+}
+
+MultiCallbackUserDataPtr BluetoothSocket::getOnMessage() const
+{
+    return mOnMessage;
+}
+
+JSValueRef BluetoothSocket::getOnMessage(JSContextRef context)
+{
+    JSValueRef onMessage = mLocalProperty.getProperty(context, BLUETOOTH_SOCKET_ONMESSAGE);
+    if(onMessage == NULL) {
+        LoggerD("onmessage is null");
+        return JSValueMakeNull(context);
+    }
+
+    return onMessage;
+}
+
+MultiCallbackUserDataPtr BluetoothSocket::getOnClose() const
+{
+    return mOnClose;
+}
+
+JSValueRef BluetoothSocket::getOnClose(JSContextRef context)
+{
+    JSValueRef onClose = mLocalProperty.getProperty(context, BLUETOOTH_SOCKET_ONCLOSE);
+    if(onClose == NULL) {
+        LoggerD("onclose is null");
+        return JSValueMakeNull(context);
+    }
+
+    return onClose;
+}
+
+MultiCallbackUserDataPtr BluetoothSocket::getOnError() const
+{
+    return mOnError;
+}
+
+JSValueRef BluetoothSocket::getOnError(JSContextRef context)
+{
+    JSValueRef onError = mLocalProperty.getProperty(context, BLUETOOTH_SOCKET_ONERROR);
+    if(onError == NULL) {
+        LoggerD("onerror is null");
+        return JSValueMakeNull(context);
+    }
+
+    return onError;
+}
+
+unsigned long BluetoothSocket::writeData(char* data, unsigned long size)
+{
+    unsigned long ret = 0;
+    if(bt_socket_send_data(mConnectedSocket, data, static_cast<int>(size)) == BT_ERROR_NONE) {
+        LoggerD("bt_socket_send_data() succeeded");
+        ret = size;
+    }
+    else {
+        throw UnknownException("Unknown error");
+    }
+
+    delete data;
+    return ret;
+}
+
+void BluetoothSocket::storeRecivedData(char *data, unsigned long size)
+{
+    for(unsigned long i = 0; i < size; i++) {
+        mReceivedData.push_back(static_cast<signed char>(data[i]));
+    }
+}
+
+std::vector<signed char> BluetoothSocket::readData()
+{
+    std::vector<signed char> result (mReceivedData);
+    mReceivedData.clear();
+
+    return result;
+}
+
+void BluetoothSocket::close()
+{
+    if(!mIsConnected) {
+        LoggerD("Already disconnected");
+        return;
+    }
+
+    if(bt_socket_disconnect_rfcomm(mConnectedSocket) != BT_ERROR_NONE) {
+        LoggerE("bt_socket_disconnect_rfcomm() failed");
+        throw UnknownException("Unknown error");
+    }
+
+    mIsConnected = false;
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/BluetoothSocket.h b/src/BluetoothSocket.h
new file mode 100644 (file)
index 0000000..a5d4662
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_SOCKET_H__
+#define __TIZEN_BLUETOOTH_SOCKET_H__
+
+#include <string>
+#include <bluetooth.h>
+#include <JavaScriptCore/JavaScript.h>
+
+//#include <boost/shared_ptr.hpp>
+#include <MultiCallbackUserData.h>
+#include <PropertyBag.h>
+
+#include "BluetoothDevice.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothSocket
+{
+public:
+    BluetoothSocket(bt_socket_connection_s *connection);
+    virtual ~BluetoothSocket();
+
+    std::string getUUID() const;
+    bool getConnectionState();
+    JSValueRef getPeer(JSContextRef context);
+    Common::MultiCallbackUserDataPtr getOnMessage() const;
+    JSValueRef getOnMessage(JSContextRef context);
+    Common::MultiCallbackUserDataPtr getOnClose() const;
+    JSValueRef getOnClose(JSContextRef context);
+    Common::MultiCallbackUserDataPtr getOnError() const;
+    JSValueRef getOnError(JSContextRef context);
+    bool setOnMessage(JSContextRef context, JSObjectRef onMessage);
+    bool setOnClose(JSContextRef context, JSObjectRef onClose);
+    bool setOnError(JSContextRef context, JSObjectRef onError);
+    void storeRecivedData(char *data, unsigned long size);
+    void setConnectionState(bool isConnected);
+
+    unsigned long writeData(char* data, unsigned long size);
+    std::vector<signed char> readData();
+    void close();
+
+private:
+    std::string mUUID;
+    int mConnectedSocket;
+    bool mIsConnected;
+    BluetoothDeviceSharedPtr mPeer;
+    std::vector<signed char> mReceivedData;
+    Common::MultiCallbackUserDataPtr mOnMessage;
+    Common::MultiCallbackUserDataPtr mOnClose;
+    Common::MultiCallbackUserDataPtr mOnError;
+    Common::PropertyBag mLocalProperty;
+};
+
+typedef BluetoothSocket* BluetoothSocketPtr;
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_SOCKET_H__
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e64d8bf
--- /dev/null
@@ -0,0 +1,67 @@
+SET(TARGET_NAME ${bluetooth_target})
+SET(DESTINATION_NAME ${bluetooth_dest})
+SET(TARGET_IMPL_NAME ${bluetooth_impl})
+
+IF(ENABLE_OPTIONAL_BT)
+PKG_SEARCH_MODULE(bluetooth REQUIRED capi-network-bluetooth)
+PKG_SEARCH_MODULE(system-info REQUIRED capi-system-info)
+
+SET(CMAKE_INSTALL_RPATH
+       ${CMAKE_INSTALL_RPATH}
+       ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSBluetoothManager.cpp
+    JSBluetoothAdapter.cpp
+    JSBluetoothDevice.cpp
+    JSBluetoothSocket.cpp
+    JSBluetoothClass.cpp
+    JSBluetoothClassDeviceMajor.cpp
+    JSBluetoothClassDeviceMinor.cpp
+    JSBluetoothClassDeviceService.cpp
+    JSBluetoothServiceHandler.cpp
+    BluetoothAdapter.cpp
+    BluetoothDevice.cpp
+    BluetoothSocket.cpp
+    BluetoothClass.cpp
+    BluetoothClassDeviceMajor.cpp
+    BluetoothClassDeviceMinor.cpp
+    BluetoothClassDeviceService.cpp
+    BluetoothServiceHandler.cpp
+    BluetoothCallbackUtil.cpp
+)
+#   BluetoothManager.cpp
+
+INCLUDE_DIRECTORIES(
+       ${INCLUDE_COMMON}
+       ${bluetooth_INCLUDE_DIRS}
+       ${system-info_INCLUDE_DIRS}
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+       ${LIBS_COMMON}
+       ${bluetooth_LIBRARIES}
+       ${system-info_LIBRARIES}
+)
+
+SET(SRCS
+       plugin_config.cpp
+       plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+       ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+ENDIF(ENABLE_OPTIONAL_BT)
+INSTALL(
+        DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/bluetooth
+        FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/JSBluetoothAdapter.cpp b/src/JSBluetoothAdapter.cpp
new file mode 100644 (file)
index 0000000..1e6dd36
--- /dev/null
@@ -0,0 +1,737 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+
+#include "plugin_config.h"
+#include "JSBluetoothAdapter.h"
+#include "BluetoothAdapter.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothAdapter::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothAdapter",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothAdapter::m_property[] = {
+    { BLUETOOTH_ADAPTER_NAME, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_ADAPTER_POWERED, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_ADAPTER_VISIBLE, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_ADAPTER_ADDRESS, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothAdapter::m_function[] = {
+    { BLUETOOTH_ADAPTER_API_SET_CHANGE_LISTENER, setChangeListener, kJSPropertyAttributeNone },
+    { BLUETOOTH_ADAPTER_API_UNSET_CHANGE_LISTENER, unsetChangeListener, kJSPropertyAttributeNone },
+    { BLUETOOTH_ADAPTER_API_SET_NAME, setName, kJSPropertyAttributeNone },
+    { BLUETOOTH_ADAPTER_API_SET_POWERED, setPowered, kJSPropertyAttributeNone },
+    { BLUETOOTH_ADAPTER_API_SET_VISIBLE, setVisible, kJSPropertyAttributeNone },
+    { BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES, discoverDevices, kJSPropertyAttributeNone },
+    { BLUETOOTH_ADAPTER_API_STOP_DISCOVERY, stopDiscovery, kJSPropertyAttributeNone },
+    { BLUETOOTH_ADAPTER_API_GET_KNOWN_DEVICES, getKnownDevices, kJSPropertyAttributeNone },
+    { BLUETOOTH_ADAPTER_API_GET_DEVICE, getDevice, kJSPropertyAttributeNone },
+    { BLUETOOTH_ADAPTER_API_CREATE_BONDING, createBonding, kJSPropertyAttributeNone },
+    { BLUETOOTH_ADAPTER_API_DESTROY_BONDING, destroyBonding, kJSPropertyAttributeNone },
+    { BLUETOOTH_ADAPTER_API_REGISTER_RFCOMMSERVICE_BY_UUID, registerRFCOMMServiceByUUID, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothAdapter::m_jsClassRef = JSClassCreate(JSBluetoothAdapter::getClassInfo());
+
+const JSClassRef JSBluetoothAdapter::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothAdapter::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothAdapter::createJSObject(JSContextRef context)
+{
+    return JSObjectMake(context, getClassRef(), NULL);
+}
+
+void JSBluetoothAdapter::initialize(JSContextRef context, JSObjectRef object)
+{
+    // do nothing
+}
+
+
+void JSBluetoothAdapter::finalize(JSObjectRef object)
+{
+    // do nothing
+}
+
+JSValueRef JSBluetoothAdapter::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_ADAPTER_NAME)) {
+            std::string name = BluetoothAdapter::getInstance()->getName();
+            return JSUtil::toJSValueRef(context, name);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_ADAPTER_POWERED)) {
+            return JSUtil::toJSValueRef(context, BluetoothAdapter::getInstance()->getPowered());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_ADAPTER_VISIBLE)) {
+            return JSUtil::toJSValueRef(context, BluetoothAdapter::getInstance()->getVisible());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_DEVICE_ADDRESS)) {
+            std::string address = BluetoothAdapter::getInstance()->getAddress();
+            return JSUtil::toJSValueRef(context, address);
+        }
+    } catch (const BasePlatformException &err) {
+        LoggerW("Getting property is failed" << err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+JSValueRef JSBluetoothAdapter::setName(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_ADAPTER_API_SET_NAME);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::string name = validator.toString(0);  // name
+        JSObjectRef successCallback = validator.toFunction(1, true);  // successCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);  // errorCallback
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+                new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if(!callback){
+            LoggerW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->setName(name, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothAdapter.setName().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::setPowered(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_ADAPTER_API_SET_POWERED);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+        bool state = validator.toBool(0);  // state
+        JSObjectRef successCallback = validator.toFunction(1, true);  // successCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);  // errorCallback
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+                new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if(!callback){
+            LoggerW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->setPowered(state, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothAdapter.setPowered().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::setVisible(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_ADAPTER_API_SET_VISIBLE);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+        bool mode = validator.toBool(0);  // mode
+        JSObjectRef successCallback = validator.toFunction(1, true);  // successCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);  // errorCallback
+        unsigned long timeout = validator.toULong(3, true);  // timeout
+        if(timeout > 65535)
+            timeout = 180;
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+                new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if(!callback){
+            LoggerW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->setVisible(mode, timeout, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothAdapter.setVisible().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::setChangeListener(JSContextRef context,
+                                                 JSObjectRef object,
+                                                 JSObjectRef thisObject,
+                                                 size_t argumentCount,
+                                                 const JSValueRef arguments[],
+                                                 JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // callback
+        JSObjectRef listener = validator.toCallbackObject(0, false, "onstatechanged", "onnamechanged", "onvisibilitychanged", NULL);
+
+        MultiCallbackUserDataPtr callback(new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if(!callback){
+            LoggerW("Can't create MultiMultiCallbackUserData");
+        }
+        else {
+            // onstatechanged
+            JSValueRef onstatechanged = JSUtil::getProperty(context , listener, "onstatechanged");
+            if(!JSValueIsUndefined(context, onstatechanged)) {
+                LoggerD("There is a onstatechanged()");
+                callback->setCallback("onstatechanged", JSUtil::JSValueToObject(context, onstatechanged));
+            }
+
+            // onnamechanged
+            JSValueRef onnamechanged = JSUtil::getProperty(context , listener, "onnamechanged");
+            if(!JSValueIsUndefined(context, onnamechanged)) {
+                LoggerD("There is a onnamechanged()");
+                callback->setCallback("onnamechanged", JSUtil::JSValueToObject(context, onnamechanged));
+            }
+
+            // onvisibilitychanged
+            JSValueRef onvisibilitychanged = JSUtil::getProperty(context , listener, "onvisibilitychanged");
+            if(!JSValueIsUndefined(context, onvisibilitychanged)) {
+                LoggerD("There is a onvisibilitychanged()");
+                callback->setCallback("onvisibilitychanged", JSUtil::JSValueToObject(context, onvisibilitychanged));
+            }
+
+            BluetoothAdapter::getInstance()->setChangeListener(callback);
+        }
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothAdapter.discoverDevices().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::unsetChangeListener(JSContextRef context,
+                                                 JSObjectRef object,
+                                                 JSObjectRef thisObject,
+                                                 size_t argumentCount,
+                                                 const JSValueRef arguments[],
+                                                 JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    BluetoothAdapter::getInstance()->unsetChangeListener();
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSBluetoothAdapter::discoverDevices(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toCallbackObject(0, false, "onstarted", "ondevicefound", "ondevicedisappeared", "onfinished", NULL);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(1, true);
+
+        MultiCallbackUserDataPtr callback(
+                new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if(!callback){
+            LoggerW("Can't create MultiMultiCallbackUserData");
+        }
+        else {
+            // onstarted
+            JSValueRef onstartedValue = JSUtil::getProperty(context , successCallback, "onstarted");
+            if(!JSValueIsUndefined(context, onstartedValue)) {
+                LoggerD("There is a onstarted()");
+                callback->setCallback("onstarted", JSUtil::JSValueToObject(context, onstartedValue));
+            }
+
+            // ondevicefound
+            JSValueRef ondevicefoundValue = JSUtil::getProperty(context , successCallback, "ondevicefound");
+            if(!JSValueIsUndefined(context, ondevicefoundValue)) {
+                LoggerD("There is a ondevicefound()");
+                callback->setCallback("ondevicefound", JSUtil::JSValueToObject(context, ondevicefoundValue));
+            }
+
+            // ondevicedisappeared
+            JSValueRef ondevicedisappearedValue = JSUtil::getProperty(context , successCallback, "ondevicedisappeared");
+            if(!JSValueIsUndefined(context, ondevicedisappearedValue)) {
+                LoggerD("There is a ondevicedisappeared()");
+                callback->setCallback("ondevicedisappeared", JSUtil::JSValueToObject(context, ondevicedisappearedValue));
+            }
+
+            // onfinished
+            JSValueRef onfinishedValue = JSUtil::getProperty(context , successCallback, "onfinished");
+            if(!JSValueIsUndefined(context, onfinishedValue)) {
+                LoggerD("There is a onfinished()");
+                callback->setCallback("onfinished", JSUtil::JSValueToObject(context, onfinishedValue));
+            }
+
+            callback->setCallback("error", errorCallback);
+        }
+
+        // perform
+        BluetoothAdapter::getInstance()->discoverDevices(callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothAdapter.discoverDevices().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::stopDiscovery(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_ADAPTER_API_STOP_DISCOVERY);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCallback = validator.toFunction(0, true);  // successCallback
+        JSObjectRef errorCallback = validator.toFunction(1, true);  // errorCallback
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+                new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if(!callback){
+            LoggerW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->stopDiscovery(callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothAdapter.stopDiscovery().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::getKnownDevices(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_ADAPTER_API_GET_KNOWN_DEVICES);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCallback = validator.toFunction(0);  // successCallback
+        JSObjectRef errorCallback = validator.toFunction(1, true);  // errorCallback
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+                new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if(!callback){
+            LoggerW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->getKnownDevices(callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothAdapter.getKnownDevices().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::getDevice(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_ADAPTER_API_GET_DEVICE);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::string address = validator.toString(0);  // address
+        JSObjectRef successCallback = validator.toFunction(1);  // successCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);  // errorCallback
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+                new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if(!callback){
+            LoggerW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->getDevice(address, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothAdapter.getDevice().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::createBonding(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_ADAPTER_API_CREATE_BONDING);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::string address = validator.toString(0);  // address
+        JSObjectRef successCallback = validator.toFunction(1);  // successCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);  // errorCallback
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+                new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if(!callback){
+            LoggerW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->createBonding(address, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothAdapter.createBonding().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::destroyBonding(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_ADAPTER_API_DESTROY_BONDING);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::string address = validator.toString(0);  // address
+        JSObjectRef successCallback = validator.toFunction(1, true);  // successCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);  // errorCallback
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+                new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if(!callback){
+            LoggerW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->destroyBonding(address, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothAdapter.destroyBonding().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::registerRFCOMMServiceByUUID(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_ADAPTER_API_REGISTER_RFCOMMSERVICE_BY_UUID);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::string uuid = validator.toString(0);  // uuid
+        std::string name = validator.toString(1);  // name
+        JSObjectRef successCallback = validator.toFunction(2);  // successCallback
+        JSObjectRef errorCallback = validator.toFunction(3, true);  // errorCallback
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+                new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if(!callback){
+            LoggerW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->registerRFCOMMServiceByUUID(uuid, name, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothAdapter.registerRFCOMMServiceByUUID().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/JSBluetoothAdapter.h b/src/JSBluetoothAdapter.h
new file mode 100644 (file)
index 0000000..a4edc63
--- /dev/null
@@ -0,0 +1,161 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_ADAPTER_H__
+#define __TIZEN_JS_BLUETOOTH_ADAPTER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothAdapter
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef setName(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setPowered(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setVisible(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef discoverDevices(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef stopDiscovery(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getKnownDevices(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getDevice(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef createBonding(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef destroyBonding(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef registerRFCOMMServiceByUUID(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/JSBluetoothClass.cpp b/src/JSBluetoothClass.cpp
new file mode 100644 (file)
index 0000000..7a505b2
--- /dev/null
@@ -0,0 +1,175 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+
+#include "plugin_config.h"
+
+#include "JSBluetoothClass.h"
+#include "BluetoothAdapter.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothClass::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothClass",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothClass::m_property[] = {
+    { BLUETOOTH_CLASS_MAJOR, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_CLASS_MINOR, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_CLASS_SERVICES, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothClass::m_function[] = {
+    { BLUETOOTH_CLASS_API_HAS_SERVICE, hasService, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothClass::m_jsClassRef = JSClassCreate(JSBluetoothClass::getClassInfo());
+
+const JSClassRef JSBluetoothClass::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothClass::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothClass::createJSObject(JSContextRef context, BluetoothClassSharedPtr bluetoothClass)
+{
+    BluetoothClassHolderPtr holder = new BluetoothClassHolder(bluetoothClass);
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(holder));
+}
+
+void JSBluetoothClass::initialize(JSContextRef context, JSObjectRef object)
+{
+    // do nothing
+}
+
+void JSBluetoothClass::finalize(JSObjectRef object)
+{
+    BluetoothClassHolderPtr priv = static_cast<BluetoothClassHolderPtr>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSBluetoothClass::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        BluetoothClassHolderPtr priv = static_cast<BluetoothClassHolderPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_CLASS_MAJOR)) {
+            return JSUtil::toJSValueRef(context, priv->mClass->getMajor());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_CLASS_MINOR)) {
+            return JSUtil::toJSValueRef(context, priv->mClass->getMinor());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_CLASS_SERVICES)) {
+            return priv->mClass->getServices(context);
+        }
+    } catch (const BasePlatformException &err) {
+        LoggerW("Getting property is failed: " << err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+JSValueRef JSBluetoothClass::hasService(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_CLASS_API_HAS_SERVICE);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Private Object
+        BluetoothClassHolderPtr priv = static_cast<BluetoothClassHolderPtr>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        unsigned long service = validator.toULong(0);  // uuid
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSUtil::toJSValueRef(context, priv->mClass->hasService(service));
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothClass.hasService().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/JSBluetoothClass.h b/src/JSBluetoothClass.h
new file mode 100644 (file)
index 0000000..ebd8862
--- /dev/null
@@ -0,0 +1,93 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_CLASS_H__
+#define __TIZEN_JS_BLUETOOTH_CLASS_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "BluetoothClass.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothClassHolder
+{
+public:
+    BluetoothClassHolder(BluetoothClassSharedPtr bluetoothClass) {mClass = bluetoothClass;}
+    BluetoothClassSharedPtr mClass;
+};
+typedef BluetoothClassHolder* BluetoothClassHolderPtr;
+
+class JSBluetoothClass
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context, BluetoothClassSharedPtr bluetoothClass);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef hasService(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/JSBluetoothClassDeviceMajor.cpp b/src/JSBluetoothClassDeviceMajor.cpp
new file mode 100644 (file)
index 0000000..2e38412
--- /dev/null
@@ -0,0 +1,114 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSUtil.h>
+#include "plugin_config.h"
+#include "JSBluetoothClassDeviceMajor.h"
+#include "BluetoothClassDeviceMajor.h"
+
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothClassDeviceMajor::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothClassDeviceMajor",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSClassRef JSBluetoothClassDeviceMajor::m_jsClassRef = JSClassCreate(JSBluetoothClassDeviceMajor::getClassInfo());
+
+JSStaticValue JSBluetoothClassDeviceMajor::m_property[] = {
+    { "MISC", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "COMPUTER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "PHONE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "NETWORK", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "AUDIO_VIDEO", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "PERIPHERAL", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "IMAGING", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "WEARABLE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "TOY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "HEALTH", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "UNCATEGORIZED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { 0, 0, 0, 0 }
+};
+
+
+const JSClassRef JSBluetoothClassDeviceMajor::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothClassDeviceMajor::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothClassDeviceMajor::createJSObject(JSContextRef context)
+{
+    return JSObjectMake(context, getClassRef(), NULL);
+}
+
+void JSBluetoothClassDeviceMajor::initialize(JSContextRef context, JSObjectRef object)
+{
+    // Do nothing
+}
+
+void JSBluetoothClassDeviceMajor::finalize(JSObjectRef object)
+{
+    // Do nothing
+}
+
+JSValueRef JSBluetoothClassDeviceMajor::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        std::string name = JSUtil::JSStringToString(context, propertyName);
+        return JSUtil::toJSValueRef(context, BluetoothClassDeviceMajor::getInstance()->getMajorValue(name));
+    } catch (const BasePlatformException &err) {
+        LoggerW("Getting property is failed: " << err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/JSBluetoothClassDeviceMajor.h b/src/JSBluetoothClassDeviceMajor.h
new file mode 100644 (file)
index 0000000..b61d84f
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_CLASS_DEVICE_MAJOR_H__
+#define __TIZEN_JS_BLUETOOTH_CLASS_DEVICE_MAJOR_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothClassDeviceMajor
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/JSBluetoothClassDeviceMinor.cpp b/src/JSBluetoothClassDeviceMinor.cpp
new file mode 100644 (file)
index 0000000..d17729f
--- /dev/null
@@ -0,0 +1,175 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSUtil.h>
+#include "plugin_config.h"
+#include "JSBluetoothClassDeviceMinor.h"
+#include "BluetoothClassDeviceMinor.h"
+
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothClassDeviceMinor::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothClassDeviceMinor",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+
+JSClassRef JSBluetoothClassDeviceMinor::m_jsClassRef = JSClassCreate(JSBluetoothClassDeviceMinor::getClassInfo());
+
+JSStaticValue JSBluetoothClassDeviceMinor::m_property[] = {
+    {"COMPUTER_UNCATEGORIZED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"COMPUTER_DESKTOP", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"COMPUTER_SERVER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"COMPUTER_LAPTOP", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"COMPUTER_HANDHELD_PC_OR_PDA", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"COMPUTER_PALM_PC_OR_PDA", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"COMPUTER_WEARABLE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PHONE_UNCATEGORIZED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PHONE_CELLULAR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PHONE_CORDLESS", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PHONE_SMARTPHONE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PHONE_MODEM_OR_GATEWAY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PHONE_ISDN", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_UNRECOGNIZED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_WEARABLE_HEADSET", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_HANDSFREE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_MICROPHONE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_LOUDSPEAKER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_HEADPHONES", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_PORTABLE_AUDIO", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_CAR_AUDIO", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_SETTOP_BOX", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_HIFI", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_VCR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_VIDEO_CAMERA", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_CAMCORDER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_MONITOR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_DISPLAY_AND_LOUDSPEAKER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_VIDEO_CONFERENCING", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_GAMING_TOY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_UNCATEGORIZED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_KEYBOARD", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_POINTING_DEVICE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_KEYBOARD_AND_POINTING_DEVICE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_JOYSTICK", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_GAMEPAD", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_REMOTE_CONTROL", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_SENSING_DEVICE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_DEGITIZER_TABLET", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_CARD_READER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_DIGITAL_PEN", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_HANDHELD_SCANNER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_HANDHELD_INPUT_DEVICE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"IMAGING_UNCATEGORIZED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"IMAGING_DISPLAY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"IMAGING_CAMERA", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"IMAGING_SCANNER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"IMAGING_PRINTER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"WEARABLE_WRITST_WATCH", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"WEARABLE_PAGER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"WEARABLE_JACKET", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"WEARABLE_HELMET", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"WEARABLE_GLASSES", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"TOY_ROBOT", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"TOY_VEHICLE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"TOY_DOLL", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"TOY_CONTROLLER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"TOY_GAME", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_UNDEFINED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_BLOOD_PRESSURE_MONITOR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_THERMOMETER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_WEIGHING_SCALE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_GLUCOSE_METER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_PULSE_OXIMETER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_PULSE_RATE_MONITOR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_DATA_DISPLAY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_STEP_COUNTER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_BODY_COMPOSITION_ANALYZER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_PEAK_FLOW_MONITOR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_MEDICATION_MONITOR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_KNEE_PROSTHESIS", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_ANKLE_PROSTHESIS", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { 0, 0, 0, 0 }
+};
+
+const JSClassRef JSBluetoothClassDeviceMinor::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothClassDeviceMinor::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothClassDeviceMinor::createJSObject(JSContextRef context)
+{
+    return JSObjectMake(context, getClassRef(), NULL);
+}
+
+void JSBluetoothClassDeviceMinor::initialize(JSContextRef context, JSObjectRef object)
+{
+    // do nothing
+}
+
+void JSBluetoothClassDeviceMinor::finalize(JSObjectRef object)
+{
+    // do nothing
+}
+
+JSValueRef JSBluetoothClassDeviceMinor::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        std::string name = JSUtil::JSStringToString(context, propertyName);
+        return JSUtil::toJSValueRef(context, BluetoothClassDeviceMinor::getInstance()->getMinorValue(name));
+    } catch (const BasePlatformException &err) {
+        LoggerW("Getting property is failed: " << err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/JSBluetoothClassDeviceMinor.h b/src/JSBluetoothClassDeviceMinor.h
new file mode 100644 (file)
index 0000000..1877cc5
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_CLASS_DEVICE_MINOR_H__
+#define __TIZEN_JS_BLUETOOTH_CLASS_DEVICE_MINOR_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothClassDeviceMinor
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/JSBluetoothClassDeviceService.cpp b/src/JSBluetoothClassDeviceService.cpp
new file mode 100644 (file)
index 0000000..cbf363b
--- /dev/null
@@ -0,0 +1,113 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSUtil.h>
+#include "plugin_config.h"
+#include "JSBluetoothClassDeviceService.h"
+#include "BluetoothClassDeviceService.h"
+
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothClassDeviceService::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothClassDeviceService",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+
+
+JSClassRef JSBluetoothClassDeviceService::m_jsClassRef = JSClassCreate(JSBluetoothClassDeviceService::getClassInfo());
+
+JSStaticValue JSBluetoothClassDeviceService::m_property[] = {
+    { "LIMITED_DISCOVERABILITY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "POSITIONING", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "NETWORKING", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "RENDERING", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "CAPTURING", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "OBJECT_TRANSFER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "AUDIO", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "TELEPHONY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "INFORMATION", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { 0, 0, 0, 0 }
+};
+
+const JSClassRef JSBluetoothClassDeviceService::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothClassDeviceService::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothClassDeviceService::createJSObject(JSContextRef context)
+{
+    return JSObjectMake(context, getClassRef(), NULL);
+}
+
+void JSBluetoothClassDeviceService::initialize(JSContextRef context, JSObjectRef object)
+{
+    // do nothing
+}
+
+void JSBluetoothClassDeviceService::finalize(JSObjectRef object)
+{
+    // do nothing
+}
+
+JSValueRef JSBluetoothClassDeviceService::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        std::string name = JSUtil::JSStringToString(context, propertyName);
+        return JSUtil::toJSValueRef(context, BluetoothClassDeviceService::getInstance()->getServiceValue(name));
+    } catch (const BasePlatformException &err) {
+        LoggerW("Getting property is failed: " << err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/JSBluetoothClassDeviceService.h b/src/JSBluetoothClassDeviceService.h
new file mode 100644 (file)
index 0000000..5ae6fce
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_CLASS_DEVICE_SERVICE_H__
+#define __TIZEN_JS_BLUETOOTH_CLASS_DEVICE_SERVICE_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothClassDeviceService
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/JSBluetoothDevice.cpp b/src/JSBluetoothDevice.cpp
new file mode 100644 (file)
index 0000000..31323a9
--- /dev/null
@@ -0,0 +1,207 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+#include <MultiCallbackUserData.h>
+
+#include "plugin_config.h"
+#include "JSBluetoothDevice.h"
+#include "BluetoothDevice.h"
+#include "BluetoothAdapter.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothDevice::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothDevice",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothDevice::m_property[] = {
+    { BLUETOOTH_DEVICE_NAME, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_DEVICE_ADDRESS, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_DEVICE_DEVICE_CLASS, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_DEVICE_IS_BONDED, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_DEVICE_IS_TRUSTED, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_DEVICE_IS_CONNECTED, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_DEVICE_UUIDS, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothDevice::m_function[] = {
+    { BLUETOOTH_DEVICE_API_CONNECT_TO_SERVICE_BY_UUID, connectToServiceByUUID, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothDevice::m_jsClassRef = JSClassCreate(JSBluetoothDevice::getClassInfo());
+
+const JSClassRef JSBluetoothDevice::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothDevice::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothDevice::createJSObject(JSContextRef context, BluetoothDeviceSharedPtr device)
+{
+    BluetoothDeviceHolderPtr holder = new BluetoothDeviceHolder(device);
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(holder));
+}
+
+void JSBluetoothDevice::initialize(JSContextRef context, JSObjectRef object)
+{
+    // Do nothing
+}
+
+void JSBluetoothDevice::finalize(JSObjectRef object)
+{
+    BluetoothDeviceHolderPtr priv = static_cast<BluetoothDeviceHolderPtr>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSBluetoothDevice::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        BluetoothDeviceHolderPtr priv = static_cast<BluetoothDeviceHolderPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_DEVICE_NAME)) {
+            return JSUtil::toJSValueRef(context, priv->mDevice->getName());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_DEVICE_ADDRESS)) {
+            return JSUtil::toJSValueRef(context, priv->mDevice->getAddress());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_DEVICE_DEVICE_CLASS)) {
+            return priv->mDevice->getDeviceClass(context);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_DEVICE_IS_BONDED)) {
+            return JSUtil::toJSValueRef(context, priv->mDevice->isBonded());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_DEVICE_IS_TRUSTED)) {
+            return JSUtil::toJSValueRef(context, priv->mDevice->isTrusted());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_DEVICE_IS_CONNECTED)) {
+            return JSUtil::toJSValueRef(context, priv->mDevice->isConnected());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_DEVICE_UUIDS)) {
+            return priv->mDevice->getUUIDs(context);
+        }
+    } catch (const BasePlatformException &err) {
+        LoggerW("Getting property is failed: " << err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+JSValueRef JSBluetoothDevice::connectToServiceByUUID(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_DEVICE_API_CONNECT_TO_SERVICE_BY_UUID);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Private Object
+        BluetoothDeviceHolderPtr priv = static_cast<BluetoothDeviceHolderPtr>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::string uuid = validator.toString(0);  // uuid
+        JSObjectRef successCallback = validator.toFunction(1);  // successCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);  // errorCallback
+        std::string remoteAddress = priv->mDevice->getAddress();    // remote address
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+                new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if(!callback){
+            LoggerW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->connectToServiceByUUID(remoteAddress, uuid, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothDevice.connectToServiceByUUID().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/JSBluetoothDevice.h b/src/JSBluetoothDevice.h
new file mode 100644 (file)
index 0000000..ba02bd7
--- /dev/null
@@ -0,0 +1,94 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_DEVICE_H__
+#define __TIZEN_JS_BLUETOOTH_DEVICE_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "BluetoothDevice.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothDeviceHolder
+{
+public:
+    BluetoothDeviceHolder(BluetoothDeviceSharedPtr device) {mDevice = device;}
+    BluetoothDeviceSharedPtr mDevice;
+};
+typedef BluetoothDeviceHolder* BluetoothDeviceHolderPtr;
+
+class JSBluetoothDevice
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context, BluetoothDeviceSharedPtr device);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef connectToServiceByUUID(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/JSBluetoothManager.cpp b/src/JSBluetoothManager.cpp
new file mode 100644 (file)
index 0000000..ff4d7e8
--- /dev/null
@@ -0,0 +1,173 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+#include <PropertyBag.h>
+
+#include "plugin_config.h"
+#include "JSBluetoothManager.h"
+#include "JSBluetoothClassDeviceMajor.h"
+#include "JSBluetoothClassDeviceMinor.h"
+#include "JSBluetoothClassDeviceService.h"
+//#include "BluetoothManager.h"
+#include "JSBluetoothAdapter.h"
+#include "BluetoothAdapter.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothManager",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothManager::m_property[] = {
+    { BLUETOOTH_MANAGER_DEVICE_MAJOR, getReadOnlyProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { BLUETOOTH_MANAGER_DEVICE_MINOR, getReadOnlyProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { BLUETOOTH_MANAGER_DEVICE_SERVICE, getReadOnlyProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothManager::m_function[] = {
+    { BLUETOOTH_MANAGER_API_GET_DEFAULT_ADAPTER, getDefaultAdapter, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothManager::m_jsClassRef = JSClassCreate(JSBluetoothManager::getClassInfo());
+
+const JSClassRef JSBluetoothManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSBluetoothManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        PropertyBag *priv = new PropertyBag();
+        if(priv) {
+            // deviceMajor
+            priv->setProperty(context, BLUETOOTH_MANAGER_DEVICE_MAJOR,
+                    JSBluetoothClassDeviceMajor::createJSObject(context));
+
+            // deviceMinor
+            priv->setProperty(context, BLUETOOTH_MANAGER_DEVICE_MINOR,
+                    JSBluetoothClassDeviceMinor::createJSObject(context));
+
+            // deviceService
+            priv->setProperty(context, BLUETOOTH_MANAGER_DEVICE_SERVICE,
+                    JSBluetoothClassDeviceService::createJSObject(context));
+
+            if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+                LoggerW("Failed to set private data");
+                delete priv;
+            }
+        }
+        else {
+            LoggerW("Failed to create private data");
+        }
+    }
+    else {
+        LoggerW("Private data already exists");
+    }
+}
+
+void JSBluetoothManager::finalize(JSObjectRef object)
+{
+    PropertyBag *priv = static_cast<PropertyBag*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSBluetoothManager::getReadOnlyProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) {
+    PropertyBag *priv = static_cast<PropertyBag*>(JSObjectGetPrivate(object));
+    if(!priv) {
+        LoggerW("There is no private data");
+        return NULL;
+    }
+
+    std::string name = JSUtil::JSStringToString(context, propertyName);
+    return priv->getProperty(context, propertyName);
+}
+
+JSValueRef JSBluetoothManager::getDefaultAdapter(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_MANAGER_API_GET_DEFAULT_ADAPTER);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSBluetoothAdapter::createJSObject(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothManager.getDefaultAdapter().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/JSBluetoothManager.h b/src/JSBluetoothManager.h
new file mode 100644 (file)
index 0000000..99e579e
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_MANAGER_H__
+#define __TIZEN_JS_BLUETOOTH_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothManager
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getReadOnlyProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+
+    static JSValueRef getDefaultAdapter(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/JSBluetoothServiceHandler.cpp b/src/JSBluetoothServiceHandler.cpp
new file mode 100644 (file)
index 0000000..2a74954
--- /dev/null
@@ -0,0 +1,233 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+#include <MultiCallbackUserData.h>
+
+#include "plugin_config.h"
+#include "JSBluetoothServiceHandler.h"
+#include "BluetoothAdapter.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothServiceHandler::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothServiceHandler",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothServiceHandler::m_property[] = {
+    { BLUETOOTH_SERVICE_HANDLER_UUID, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_SERVICE_HANDLER_NAME, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_SERVICE_HANDLER_IS_CONNECTED, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_SERVICE_HANDLER_ONCONNECT, getProperty, setProperty, kJSPropertyAttributeNone|kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothServiceHandler::m_function[] = {
+    { BLUETOOTH_SERVICE_HANDLER_API_UNREGISTER, unregister, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothServiceHandler::m_jsClassRef = JSClassCreate(JSBluetoothServiceHandler::getClassInfo());
+
+const JSClassRef JSBluetoothServiceHandler::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothServiceHandler::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothServiceHandler::createJSObject(JSContextRef context, BluetoothServiceHandlerPtr service)
+{
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(service));
+}
+
+void JSBluetoothServiceHandler::initialize(JSContextRef context, JSObjectRef object)
+{
+    // do nothing
+}
+
+void JSBluetoothServiceHandler::finalize(JSObjectRef object)
+{
+    BluetoothServiceHandlerPtr priv = static_cast<BluetoothServiceHandlerPtr>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSBluetoothServiceHandler::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        BluetoothServiceHandlerPtr priv = static_cast<BluetoothServiceHandlerPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SERVICE_HANDLER_UUID)) {
+            return JSUtil::toJSValueRef(context, priv->getUUID());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SERVICE_HANDLER_NAME)) {
+            return JSUtil::toJSValueRef(context, priv->getName());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SERVICE_HANDLER_IS_CONNECTED)) {
+            return JSUtil::toJSValueRef(context, priv->getConnectionState());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SERVICE_HANDLER_ONCONNECT)) {
+            return priv->getOnConnect(context);
+        }
+    } catch (const BasePlatformException &err) {
+        LoggerW("Getting property is failed: " << err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+bool JSBluetoothServiceHandler::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    try {
+        BluetoothServiceHandlerPtr priv = static_cast<BluetoothServiceHandlerPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SERVICE_HANDLER_ONCONNECT)) {
+            JSObjectRef object = NULL;
+            if(!JSValueIsNull(context, value)) {
+                if(!JSValueIsObject(context, value)) {
+                    throw TypeMismatchException("Value is not Object");
+                }
+
+                JSValueRef ex = NULL;
+                object = JSValueToObject(context, value, &ex);
+                if(ex){
+                    throw TypeMismatchException("Can't convert to Object");
+                }
+
+                if(!JSObjectIsFunction(context, object)) {
+                    throw TypeMismatchException("Not function");
+                }
+            }
+            else {
+                LoggerD("onconnect() is NULL");
+            }
+
+            return priv->setOnConnect(context, object);
+        }
+    } catch (const BasePlatformException &err) {
+        JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return false;
+}
+
+JSValueRef JSBluetoothServiceHandler::unregister(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_SERVICE_HANDLER_API_UNREGISTER);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Private Object
+        BluetoothServiceHandlerPtr priv = static_cast<BluetoothServiceHandlerPtr>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCallback = validator.toFunction(0, true);  // successCallback
+        JSObjectRef errorCallback = validator.toFunction(1, true);  // errorCallback
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+                new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if(!callback){
+            LoggerW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        priv->unregister(callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothServiceHandler.unregister().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/JSBluetoothServiceHandler.h b/src/JSBluetoothServiceHandler.h
new file mode 100644 (file)
index 0000000..c59540d
--- /dev/null
@@ -0,0 +1,91 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_SERVICE_HANDLER_H__
+#define __TIZEN_JS_BLUETOOTH_SERVICE_HANDLER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "BluetoothServiceHandler.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothServiceHandler
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context, BluetoothServiceHandlerPtr service);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef unregister(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/JSBluetoothSocket.cpp b/src/JSBluetoothSocket.cpp
new file mode 100644 (file)
index 0000000..1332d7a
--- /dev/null
@@ -0,0 +1,367 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <vector>
+
+#include <SecurityExceptions.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+#include <MultiCallbackUserData.h>
+
+#include "plugin_config.h"
+#include "JSBluetoothSocket.h"
+#include "BluetoothSocket.h"
+#include "BluetoothAdapter.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothSocket::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothSocket",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothSocket::m_property[] = {
+    { BLUETOOTH_SOCKET_UUID, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_SOCKET_STATE, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_SOCKET_PEER, getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_SOCKET_ONMESSAGE, getProperty, setProperty, kJSPropertyAttributeNone|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_SOCKET_ONCLOSE, getProperty, setProperty, kJSPropertyAttributeNone|kJSPropertyAttributeDontDelete },
+    { BLUETOOTH_SOCKET_ONERROR, getProperty, setProperty, kJSPropertyAttributeNone|kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothSocket::m_function[] = {
+    { BLUETOOTH_SOCKET_API_WRITE_DATA, writeData, kJSPropertyAttributeNone },
+    { BLUETOOTH_SOCKET_API_READ_DATA, readData, kJSPropertyAttributeNone },
+    { BLUETOOTH_SOCKET_API_CLOSE, close, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothSocket::m_jsClassRef = JSClassCreate(JSBluetoothSocket::getClassInfo());
+
+const JSClassRef JSBluetoothSocket::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothSocket::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothSocket::createJSObject(JSContextRef context, BluetoothSocketPtr socket)
+{
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(socket));
+}
+
+void JSBluetoothSocket::initialize(JSContextRef context, JSObjectRef object)
+{
+    // do nothing
+}
+
+void JSBluetoothSocket::finalize(JSObjectRef object)
+{
+    BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSBluetoothSocket::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_UUID)) {
+            return JSUtil::toJSValueRef(context, priv->getUUID());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_STATE)) {
+            LoggerD("get state");
+            std::string state;
+            if(priv->getConnectionState()) {
+                state = "OPEN";
+            }
+            else {
+                state = "CLOSED";
+            }
+            LoggerD("state: " << state);
+            return JSUtil::toJSValueRef(context, state);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_PEER)) {
+            return priv->getPeer(context);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONMESSAGE)) {
+            return priv->getOnMessage(context);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONCLOSE)) {
+            return priv->getOnClose(context);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONERROR)) {
+            return priv->getOnError(context);
+        }
+    } catch (const BasePlatformException &err) {
+        LoggerW("Getting property is failed: " << err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+bool JSBluetoothSocket::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    try {
+        BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONMESSAGE)) {
+            JSObjectRef object = NULL;
+            if(!JSValueIsNull(context, value)) {
+                if(!JSValueIsObject(context, value)) {
+                    throw TypeMismatchException("Value is not Object");
+                }
+
+                JSValueRef ex;
+                object = JSValueToObject(context, value, &ex);
+                if(ex){
+                    throw TypeMismatchException("Can't convert to Object");
+                }
+
+                if(!JSObjectIsFunction(context, object)) {
+                    throw TypeMismatchException("Not function");
+                }
+            }
+            else {
+                LoggerD("onmessage() is NULL");
+            }
+
+            return priv->setOnMessage(context, object);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONCLOSE)) {
+            JSObjectRef object = NULL;
+            if(!JSValueIsNull(context, value)) {
+                if(!JSValueIsObject(context, value)) {
+                    throw TypeMismatchException("Value is not Object");
+                }
+
+                JSValueRef ex;
+                object = JSValueToObject(context, value, &ex);
+                if(ex){
+                    throw TypeMismatchException("Can't convert to Object");
+                }
+
+                if(!JSObjectIsFunction(context, object)) {
+                    throw TypeMismatchException("Not function");
+                }
+            }
+            else {
+                LoggerD("onclose() is NULL");
+            }
+
+            return priv->setOnClose(context, object);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_ONERROR)) {
+            JSObjectRef object = NULL;
+            if(!JSValueIsNull(context, value)) {
+                if(!JSValueIsObject(context, value)) {
+                    throw TypeMismatchException("Value is not Object");
+                }
+
+                JSValueRef ex;
+                object = JSValueToObject(context, value, &ex);
+                if(ex){
+                    throw TypeMismatchException("Can't convert to Object");
+                }
+
+                if(!JSObjectIsFunction(context, object)) {
+                    throw TypeMismatchException("Not function");
+                }
+            }
+            else {
+                LoggerD("onerror() is NULL");
+            }
+
+            return priv->setOnError(context, object);
+        }
+    } catch (const BasePlatformException &err) {
+        JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return false;
+}
+
+JSValueRef JSBluetoothSocket::writeData(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_SOCKET_API_WRITE_DATA);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Private Object
+        BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw DeviceAPI::Common::UnknownException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSObjectRef dataArrayObj  = validator.toArrayObject(0);  // data
+        size_t size = JSGetArrayLength(context, dataArrayObj);
+        char *buffer = new char[size];
+        for(size_t i = 0; i < size; ++i) {
+            JSValueRef element = JSGetArrayElement(context, dataArrayObj, i);
+            buffer[i] = static_cast<char>(JSUtil::JSValueToByte(context, element));
+        }
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSUtil::toJSValueRef(context, priv->writeData(buffer, size));
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothSocket.writeData().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothSocket::readData(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_SOCKET_API_READ_DATA);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Private Object
+        BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw DeviceAPI::Common::UnknownException("Private object is NULL.");
+        }
+
+        std::vector<signed char> data = priv->readData();
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSUtil::toJSValueRef_(context, data);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothSocket.readData().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothSocket::close(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    // Access Check
+    //AceSecurityStatus status = BLUETOOTH_CHECK_ACCESS(BLUETOOTH_SOCKET_API_CLOSE);
+    //TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Check whether Bluetooth is supported or not
+        if(!BluetoothAdapter::isBluetoothSupported()) {
+            throw DeviceAPI::Common::NotSupportedException("Bluetooth is not supported");
+        }
+
+        // Private Object
+        BluetoothSocketPtr priv = static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw DeviceAPI::Common::UnknownException("Private object is NULL.");
+        }
+
+        priv->close();
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in BluetoothSocket.close().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/JSBluetoothSocket.h b/src/JSBluetoothSocket.h
new file mode 100644 (file)
index 0000000..26ec403
--- /dev/null
@@ -0,0 +1,105 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_SOCKET_H__
+#define __TIZEN_JS_BLUETOOTH_SOCKET_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "BluetoothSocket.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothSocket
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context, BluetoothSocketPtr socket);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef writeData(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef readData(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef close(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/config.xml b/src/config.xml
new file mode 100644 (file)
index 0000000..adb2bd0
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-bt.so</library-name>
+    <feature-install-uri>bt.install.uri</feature-install-uri>
+    <feature-key-cn>SAMSUNG plugin group</feature-key-cn>
+    <feature-root-cn>SAMSUNG certificate authority</feature-root-cn>
+    <feature-root-fingerprint>AAAABBBBCCCCDDDEEEE0000</feature-root-fingerprint>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/bluetooth.gap</name>
+        <device-capability>bluetooth.gap</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/bluetooth.admin</name>
+        <device-capability>bluetooth.admin</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/bluetoothmanager</name>
+        <device-capability>bluetoothmanager</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/bluetooth.spp</name>
+        <device-capability>bluetooth.spp</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/plugin_config.cpp b/src/plugin_config.cpp
new file mode 100644 (file)
index 0000000..6783626
--- /dev/null
@@ -0,0 +1,310 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <map>
+
+#include "plugin_config.h"
+
+#define BLUETOOTH_FEATURE_API_ADMIN "http://tizen.org/privilege/bluetooth.admin"
+#define BLUETOOTH_FEATURE_API_GAP "http://tizen.org/privilege/bluetooth.gap"
+#define BLUETOOTH_FEATURE_API_SPP "http://tizen.org/privilege/bluetooth.spp"
+#define BLUETOOTH_FEATURE_API_MANAGER "http://tizen.org/privilege/bluetoothmanager"
+
+#define BLUETOOTH_DEVICE_CAP_ADMIN "bluetooth.admin"
+#define BLUETOOTH_DEVICE_CAP_GAP "bluetooth.gap"
+#define BLUETOOTH_DEVICE_CAP_SPP "bluetooth.spp"
+#define BLUETOOTH_DEVICE_CAP_MANAGER "bluetoothmanager"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+static FunctionMapping createBluetoothFunctions();
+static FunctionMapping BluetoothFunctions = createBluetoothFunctions();
+
+#pragma GCC visibility push(default)
+
+DEFINE_FUNCTION_GETTER(Bluetooth, BluetoothFunctions);
+
+#pragma GCC visibility pop
+
+static FunctionMapping createBluetoothFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_BLUETOOTH_ADMIN, BLUETOOTH_DEVICE_CAP_ADMIN);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_BLUETOOTH_ADMIN);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_BLUETOOTH_ADMIN, DEVICE_CAP_BLUETOOTH_ADMIN);
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_BLUETOOTH_GAP, BLUETOOTH_DEVICE_CAP_GAP);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_BLUETOOTH_GAP);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_BLUETOOTH_GAP, DEVICE_CAP_BLUETOOTH_GAP);
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_BLUETOOTH_SPP, BLUETOOTH_DEVICE_CAP_SPP);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_BLUETOOTH_SPP);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_BLUETOOTH_SPP, DEVICE_CAP_BLUETOOTH_SPP);
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_BLUETOOTH_MANAGER, BLUETOOTH_DEVICE_CAP_MANAGER);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_BLUETOOTH_MANAGER);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_BLUETOOTH_MANAGER, DEVICE_CAP_BLUETOOTH_MANAGER);
+
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_ADMIN, BLUETOOTH_FEATURE_API_ADMIN);
+    ACE_CREATE_FEATURE_LIST(BLUETOOTH_FEATURES_BLUETOOTH_ADMIN);
+    ACE_ADD_API_FEATURE(BLUETOOTH_FEATURES_BLUETOOTH_ADMIN, FEATURE_ADMIN);
+
+    ACE_CREATE_FEATURE(FEATURE_GAP, BLUETOOTH_FEATURE_API_GAP);
+    ACE_CREATE_FEATURE_LIST(BLUETOOTH_FEATURES_BLUETOOTH_GAP);
+    ACE_ADD_API_FEATURE(BLUETOOTH_FEATURES_BLUETOOTH_GAP, FEATURE_GAP);
+
+    ACE_CREATE_FEATURE(FEATURE_SPP, BLUETOOTH_FEATURE_API_SPP);
+    ACE_CREATE_FEATURE_LIST(BLUETOOTH_FEATURES_BLUETOOTH_SPP);
+    ACE_ADD_API_FEATURE(BLUETOOTH_FEATURES_BLUETOOTH_SPP, FEATURE_SPP);
+
+    ACE_CREATE_FEATURE(FEATURE_MANAGER, BLUETOOTH_FEATURE_API_MANAGER);
+    ACE_CREATE_FEATURE_LIST(BLUETOOTH_FEATURES_BLUETOOTH_MANAGER);
+    ACE_ADD_API_FEATURE(BLUETOOTH_FEATURES_BLUETOOTH_MANAGER, FEATURE_MANAGER);
+    ACE_ADD_API_FEATURE(BLUETOOTH_FEATURES_BLUETOOTH_MANAGER, FEATURE_ADMIN);   // for backward compatibility
+
+
+    /**
+     * Functions
+     */
+    FunctionMapping BluetoothMapping;
+
+    // getDefaultAdapter()
+    AceFunction getDefaultAdapterFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_MANAGER_API_GET_DEFAULT_ADAPTER,
+            BLUETOOTH_MANAGER_API_GET_DEFAULT_ADAPTER,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_MANAGER_API_GET_DEFAULT_ADAPTER,
+            getDefaultAdapterFunc));
+
+    // setChangeListener()
+    AceFunction setChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_SET_CHANGE_LISTENER,
+            BLUETOOTH_ADAPTER_API_SET_CHANGE_LISTENER,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_SET_CHANGE_LISTENER,
+            setChangeListenerFunc));
+
+    // setChangeListener()
+    AceFunction unsetChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_UNSET_CHANGE_LISTENER,
+            BLUETOOTH_ADAPTER_API_UNSET_CHANGE_LISTENER,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_UNSET_CHANGE_LISTENER,
+            unsetChangeListenerFunc));
+
+    // setName()
+    AceFunction setNameFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_SET_NAME,
+            BLUETOOTH_ADAPTER_API_SET_NAME,
+            BLUETOOTH_FEATURES_BLUETOOTH_ADMIN,
+            DEVICE_LIST_BLUETOOTH_ADMIN);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_SET_NAME,
+            setNameFunc));
+
+    // setPowered()
+    AceFunction setPoweredFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_SET_POWERED,
+            BLUETOOTH_ADAPTER_API_SET_POWERED,
+            BLUETOOTH_FEATURES_BLUETOOTH_ADMIN,
+            DEVICE_LIST_BLUETOOTH_ADMIN);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_SET_POWERED,
+            setPoweredFunc));
+
+    // setVisible()
+    AceFunction setVisibleFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_SET_VISIBLE,
+            BLUETOOTH_ADAPTER_API_SET_VISIBLE,
+            BLUETOOTH_FEATURES_BLUETOOTH_MANAGER,
+            DEVICE_LIST_BLUETOOTH_MANAGER);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_SET_VISIBLE,
+            setVisibleFunc));
+
+    // discoverDevices()
+    AceFunction discoverDevicesFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES,
+            BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES,
+            discoverDevicesFunc));
+
+    //  stopDiscovery()
+    AceFunction  stopDiscoveryFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_STOP_DISCOVERY,
+            BLUETOOTH_ADAPTER_API_STOP_DISCOVERY,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_STOP_DISCOVERY,
+            stopDiscoveryFunc));
+
+    //  getKnownDevices()
+    AceFunction  getKnownDevicesFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_GET_KNOWN_DEVICES,
+            BLUETOOTH_ADAPTER_API_GET_KNOWN_DEVICES,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_GET_KNOWN_DEVICES,
+            getKnownDevicesFunc));
+
+    //  getDevice()
+    AceFunction  getDeviceFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_GET_DEVICE,
+            BLUETOOTH_ADAPTER_API_GET_DEVICE,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_GET_DEVICE,
+            getDeviceFunc));
+
+    //  createBonding()
+    AceFunction  createBondingFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_CREATE_BONDING,
+            BLUETOOTH_ADAPTER_API_CREATE_BONDING,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_CREATE_BONDING,
+            createBondingFunc));
+
+    //  destroyBonding()
+    AceFunction  destroyBondingFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_DESTROY_BONDING,
+            BLUETOOTH_ADAPTER_API_DESTROY_BONDING,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_DESTROY_BONDING,
+            destroyBondingFunc));
+
+    //  registerRFCOMMServiceByUUID()
+    AceFunction  registerRFCOMMServiceByUUIDFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_REGISTER_RFCOMMSERVICE_BY_UUID,
+            BLUETOOTH_ADAPTER_API_REGISTER_RFCOMMSERVICE_BY_UUID,
+            BLUETOOTH_FEATURES_BLUETOOTH_SPP,
+            DEVICE_LIST_BLUETOOTH_SPP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_REGISTER_RFCOMMSERVICE_BY_UUID,
+            registerRFCOMMServiceByUUIDFunc));
+
+    //  connectToServiceByUUID()
+    AceFunction  connectToServiceByUUIDFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_DEVICE_API_CONNECT_TO_SERVICE_BY_UUID,
+            BLUETOOTH_DEVICE_API_CONNECT_TO_SERVICE_BY_UUID,
+            BLUETOOTH_FEATURES_BLUETOOTH_SPP,
+            DEVICE_LIST_BLUETOOTH_SPP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_DEVICE_API_CONNECT_TO_SERVICE_BY_UUID,
+            connectToServiceByUUIDFunc));
+
+    //  writeData()
+    AceFunction  writeDataFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_SOCKET_API_WRITE_DATA,
+            BLUETOOTH_SOCKET_API_WRITE_DATA,
+            BLUETOOTH_FEATURES_BLUETOOTH_SPP,
+            DEVICE_LIST_BLUETOOTH_SPP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_SOCKET_API_WRITE_DATA,
+            writeDataFunc));
+
+    //  readData()
+    AceFunction  readDataFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_SOCKET_API_READ_DATA,
+            BLUETOOTH_SOCKET_API_READ_DATA,
+            BLUETOOTH_FEATURES_BLUETOOTH_SPP,
+            DEVICE_LIST_BLUETOOTH_SPP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_SOCKET_API_READ_DATA,
+            readDataFunc));
+
+    //  close()
+    AceFunction  closeFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_SOCKET_API_CLOSE,
+            BLUETOOTH_SOCKET_API_CLOSE,
+            BLUETOOTH_FEATURES_BLUETOOTH_SPP,
+            DEVICE_LIST_BLUETOOTH_SPP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_SOCKET_API_CLOSE,
+            closeFunc));
+
+    //  hasService()
+    AceFunction  hasServiceFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_CLASS_API_HAS_SERVICE,
+            BLUETOOTH_CLASS_API_HAS_SERVICE,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_CLASS_API_HAS_SERVICE,
+            hasServiceFunc));
+
+    //  unregister()
+    AceFunction  unregisterFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_SERVICE_HANDLER_API_UNREGISTER,
+            BLUETOOTH_SERVICE_HANDLER_API_UNREGISTER,
+            BLUETOOTH_FEATURES_BLUETOOTH_SPP,
+            DEVICE_LIST_BLUETOOTH_SPP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_SERVICE_HANDLER_API_UNREGISTER,
+            unregisterFunc));
+
+    return BluetoothMapping;
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/plugin_config.h b/src/plugin_config.h
new file mode 100644 (file)
index 0000000..bb99878
--- /dev/null
@@ -0,0 +1,90 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _BLUETOOTH_PLUGIN_CONFIG_H_
+#define _BLUETOOTH_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+// attributes
+#define BLUETOOTH_MANAGER_DEVICE_MAJOR "deviceMajor"
+#define BLUETOOTH_MANAGER_DEVICE_MINOR "deviceMinor"
+#define BLUETOOTH_MANAGER_DEVICE_SERVICE "deviceService"
+#define BLUETOOTH_ADAPTER_NAME "name"
+#define BLUETOOTH_ADAPTER_ADDRESS "address"
+#define BLUETOOTH_ADAPTER_POWERED "powered"
+#define BLUETOOTH_ADAPTER_VISIBLE "visible"
+#define BLUETOOTH_DEVICE_NAME "name"
+#define BLUETOOTH_DEVICE_ADDRESS "address"
+#define BLUETOOTH_DEVICE_DEVICE_CLASS "deviceClass"
+#define BLUETOOTH_DEVICE_IS_BONDED "isBonded"
+#define BLUETOOTH_DEVICE_IS_TRUSTED "isTrusted"
+#define BLUETOOTH_DEVICE_IS_CONNECTED "isConnected"
+#define BLUETOOTH_DEVICE_UUIDS "uuids"
+#define BLUETOOTH_SOCKET_UUID "uuid"
+#define BLUETOOTH_SOCKET_STATE "state"
+#define BLUETOOTH_SOCKET_PEER "peer"
+#define BLUETOOTH_SOCKET_ONMESSAGE "onmessage"
+#define BLUETOOTH_SOCKET_ONCLOSE "onclose"
+#define BLUETOOTH_SOCKET_ONERROR "onerror"
+#define BLUETOOTH_CLASS_MAJOR "major"
+#define BLUETOOTH_CLASS_MINOR "minor"
+#define BLUETOOTH_CLASS_SERVICES "services"
+#define BLUETOOTH_SERVICE_HANDLER_UUID "uuid"
+#define BLUETOOTH_SERVICE_HANDLER_NAME "name"
+#define BLUETOOTH_SERVICE_HANDLER_IS_CONNECTED "isConnected"
+#define BLUETOOTH_SERVICE_HANDLER_ONCONNECT "onconnect"
+
+// functions
+#define BLUETOOTH_MANAGER_API_GET_DEFAULT_ADAPTER "getDefaultAdapter"
+#define BLUETOOTH_ADAPTER_API_SET_CHANGE_LISTENER "setChangeListener"
+#define BLUETOOTH_ADAPTER_API_UNSET_CHANGE_LISTENER "unsetChangeListener"
+#define BLUETOOTH_ADAPTER_API_SET_NAME "setName"
+#define BLUETOOTH_ADAPTER_API_SET_POWERED "setPowered"
+#define BLUETOOTH_ADAPTER_API_SET_VISIBLE "setVisible"
+#define BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES "discoverDevices"
+#define BLUETOOTH_ADAPTER_API_STOP_DISCOVERY "stopDiscovery"
+#define BLUETOOTH_ADAPTER_API_GET_KNOWN_DEVICES "getKnownDevices"
+#define BLUETOOTH_ADAPTER_API_GET_DEVICE "getDevice"
+#define BLUETOOTH_ADAPTER_API_CREATE_BONDING "createBonding"
+#define BLUETOOTH_ADAPTER_API_DESTROY_BONDING "destroyBonding"
+#define BLUETOOTH_ADAPTER_API_REGISTER_RFCOMMSERVICE_BY_UUID "registerRFCOMMServiceByUUID"
+#define BLUETOOTH_DEVICE_API_CONNECT_TO_SERVICE_BY_UUID "connectToServiceByUUID"
+#define BLUETOOTH_SOCKET_API_WRITE_DATA "writeData"
+#define BLUETOOTH_SOCKET_API_READ_DATA "readData"
+#define BLUETOOTH_SOCKET_API_CLOSE "close"
+#define BLUETOOTH_CLASS_API_HAS_SERVICE "hasService"
+#define BLUETOOTH_SERVICE_HANDLER_API_UNREGISTER "unregister"
+
+DECLARE_FUNCTION_GETTER(Bluetooth);
+
+#define BLUETOOTH_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getBluetoothFunctionData, \
+    functionName)
+
+}
+}
+
+#endif // _BLUETOOTH_PLUGIN_CONFIG_H_
diff --git a/src/plugin_initializer.cpp b/src/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..7ac7ef1
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <GlobalContextManager.h>
+
+#include "JSBluetoothManager.h"
+#include "BluetoothAdapter.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+
+void on_widget_start_callback(int widgetId)
+{
+    LoggerD("[Tizen\\Bluetooth] on_widget_start_callback (%d)", widgetId);
+       TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LoggerE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LoggerD("[Tizen\\Bluetooth] on_widget_stop_callback (%d)", widgetId);
+       TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE,"Bluetooth");
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+        LoggerE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void *context)
+{
+    LoggerD("[Tizen\\Bluetooth] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void *context)
+{
+    LoggerD("[Tizen\\Bluetooth] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+    BluetoothAdapter::getInstance()->unloadFrame(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "bt",
+        (js_class_template_getter)JSBluetoothManager::getClassRef,
+        NULL)
+PLUGIN_CLASS_MAP_END
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/utils.cpp b/src/utils.cpp
new file mode 100644 (file)
index 0000000..6853816
--- /dev/null
@@ -0,0 +1,133 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+
+#include "utils.h"
+
+#include "Logger.h"
+
+GQuark g_phone_error_quark(void)
+{
+    return g_quark_from_static_string("g-phone-error-quark");
+}
+
+std::map<std::string, guint> Utils::mSubsIdsMap;
+
+bool Utils::setSignalListener(GBusType type, const char *service,
+                              const char *iface, const char *path,
+                              const char *name, GDBusSignalCallback cb,
+                              void *data)
+{
+    // key is of form: BUS_TYPE:SERVICE:IFACE:OBJ_PATH:SIGNAL
+    const char *bus_type = (type == G_BUS_TYPE_SYSTEM) ? "SYSTEM" : (type == G_BUS_TYPE_SESSION) ? "SESSION" : "";
+    std::string key = std::string(bus_type) + ":" + service + ":" + iface + ":" + path + ":" + name;
+    LoggerD("subscribing for DBUS signal: " << key);
+
+    // only one listener (subscription on DBUS signal) allowed for specific signal
+    if(mSubsIdsMap[key] <= 0) { // not yet subscribed for DBUS signal
+        guint id = 0;
+        id = g_dbus_connection_signal_subscribe(g_bus_get_sync(type, NULL, NULL),
+                                                service,
+                                                iface,
+                                                name,
+                                                path,
+                                                NULL,
+                                                G_DBUS_SIGNAL_FLAGS_NONE,
+                                                cb,
+                                                data,
+                                                NULL);
+
+        if(id == 0) {
+            LoggerE("Failed to subscribe to: " << key);
+            return false;
+        }
+
+        mSubsIdsMap[key] = id;
+
+        return true; // success
+    }
+
+    // already subscribed for DBUS signal
+    return false;
+}
+
+void Utils::removeSignalListener(GBusType type, const char *service,
+                                 const char* iface, const char* path,
+                                 const char* name)
+{
+
+    // key is of form: BUS_TYPE:SERVICE:IFACE:OBJ_PATH:SIGNAL
+    const char *bus_type = (type == G_BUS_TYPE_SYSTEM) ? "SYSTEM" : (type == G_BUS_TYPE_SESSION) ? "SESSION" : "";
+    std::string key = std::string(bus_type) + ":" + service + ":" + iface + ":" + path + ":" + name;
+    LoggerD("unsubscribing from DBUS signal: " << key);
+
+    std::map<std::string, guint>::iterator iter = mSubsIdsMap.begin();
+    while(iter != mSubsIdsMap.end()) {
+        if(!strcmp(key.c_str(), (*iter).first.c_str())) {
+            g_dbus_connection_signal_unsubscribe(g_bus_get_sync(type, NULL, NULL), (*iter).second);
+            mSubsIdsMap.erase(iter);
+            break;
+        }
+        iter++;
+    }
+}
+
+// makes AABBCCDDEEFF from AA:BB:CC:DD:EE:FF
+bool makeRawMAC(std::string &address) {
+    address.erase(std::remove_if(address.begin(), address.end(), isnxdigit), address.end());
+    return (address.length() == 12);
+}
+
+// makes AA:BB:CC:DD:EE:FF from AABBCCDDEEFF
+bool makeMACFromRawMAC(std::string &address) {
+    if(address.length() == 12) {
+        address.insert(10,":");
+        address.insert(8,":");
+        address.insert(6,":");
+        address.insert(4,":");
+        address.insert(2,":");
+        return true;
+    }
+    return false;
+}
+
+// makes AA:BB:CC:DD:EE:FF from device path, eg: /org/bluez/223/hci0/dev_AA_BB_CC_DD_EE_FF
+bool makeMACFromDevicePath(std::string &device) {
+    size_t idx = device.find( "dev_" ) + 4;
+    device = device.substr (idx, device.length()-idx);
+    device.erase(std::remove_if(device.begin(), device.end(), isnxdigit), device.end());
+    return makeMACFromRawMAC(device);
+}
+
+// don't use a reference for address - we need a copy
+bool isValidMAC(std::string address) {
+    // expect MAC address in form: AA:BB:CC:DD:EE:FF
+    if( (address[2] != ':') || (address[5] != ':') || (address[8] != ':') ||
+        (address[11] != ':') || (address[14] != ':'))
+        return false;
+
+    // remove all non HEX digits
+    address.erase(std::remove_if(address.begin(), address.end(), isnxdigit), address.end());
+
+    // after removing, there should be exactly 12 remaining characters/digits
+    return (address.length() == 12);
+}
+
+int isndigit(int x) {
+    return !std::isdigit(x);
+}
+
+// will remove all non-digit characters, except leading '+'
+void formatPhoneNumber(std::string &phoneNumber) {
+    bool leadingPlusSign = (phoneNumber[0] == '+');
+    phoneNumber.erase(std::remove_if(phoneNumber.begin(), phoneNumber.end(), isndigit), phoneNumber.end());
+    if(leadingPlusSign)
+        phoneNumber.insert(0, "+");
+}
+
+int isnxdigit(int x) {
+    return !std::isxdigit(x);
+}
+
diff --git a/src/utils.h b/src/utils.h
new file mode 100644 (file)
index 0000000..f5c34d9
--- /dev/null
@@ -0,0 +1,135 @@
+
+#ifndef UTILS_H_
+#define UTILS_H_
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <gio/gio.h>
+#include <string>
+#include <map>
+
+/**
+ * Formatter function. Extracts MAC address from device path, eg. from \b /org/bluez/223/hci0/dev_AA_BB_CC_DD_EE_FF makes \b AA:BB:CC:DD:EE:FF.
+ * @param[in,out] device The path of the device.
+ * @return True if the formatted MAC is valid.
+ */
+bool makeMACFromDevicePath(std::string &device);
+
+/**
+ * Formatter function. Formats given MAC address in RAW format, eg. \b AABBCCDDEEFF into 'colon' format: \b AA:BB:CC:DD:EE:FF.
+ * @param[in,out] address MAC address to be formatted.
+ * @return True if the formatted MAC is valid.
+ */
+bool makeMACFromRawMAC(std::string &address);
+
+/**
+ * Formatter function. Formats given MAC address in 'colon' format, eg. \b AA:BB:CC:DD:EE:FF into RAW format: \b AABBCCDDEEFF.
+ * @param[in,out] address MAC address to be formatted.
+ * @return True if the formatted MAC is valid.
+ */
+bool makeRawMAC(std::string &address);
+
+/**
+ * Formatter function. Formats given phone number to one specific format, ie. it removes all non-HEX digit characters and replaces leadin '00' by '+' character.
+ * \li 00421123456  -> +421123456
+ * \li +421-123-456 -> +421123456
+ * @param[in,out] phoneNumber Phone number to be formatted.
+ */
+void formatPhoneNumber(std::string &phoneNumber);
+
+/**
+ * Function to check wthether given MAC address is valid or not. It expects MAC address to be in 'full' format, eg. \b AA:BB:CC:DD:EE:FF. It doesn't support abbreviated MAC addresses, eg. \b AA:B:C:DD:EE:F. First it check whether ':' are at correct positions (2,5,8,11,14), then removes all non-HEX characters from the string and checks its length. If the length is 12, the given MAC address is valid.
+ * @param[in] address MAC address to perform validation on.
+ * @return \bTrue, if the MAC address is valid, otherwise returns \b false.
+ */
+bool isValidMAC(std::string address);
+
+/**
+ * The function to check if the input character is not hexa digit, ie. is not any of: 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
+ * @param [in] x Input character to check.
+ * @return The function returns \b true if x is not hexa digit, otherwise it returns \b false.
+ */
+int isndigit(int x);
+
+/**
+ * The function to check if the input character is not digit, ie. is not any of: 0 1 2 3 4 5 6 7 8 9
+ * @param [in] x Input character to check.
+ * @return The function returns \b true if x is not digit, otherwise it returns \b false.
+ */
+int isnxdigit(int x);
+
+#define G_PHONE_ERROR  g_phone_error_quark()
+GQuark g_phone_error_quark(void);
+
+/*! \class Utils
+ *  \brief Utility class providing helper functions for operating with Phone.
+ */
+class Utils {
+    public:
+        /**
+         * A default constructor.
+         */
+        Utils () {}
+
+        /**
+         * A destructor.
+         */
+        virtual ~Utils () {}
+
+        /**
+         * A helper method to subscribe for DBUS siganl.
+         * @param[in] type A type of the bus that the signal should be subscribed on. See <a href="https://developer.gnome.org/gio/2.35/GDBusConnection.html#GBusType">GBusType</a> documentation.
+         * @param[in] service Service name to match on (unique or well-known name).
+         * @param[in] iface D-Bus interface name to match on.
+         * @param[in] path Object path to match on.
+         * @param[in] name D-Bus signal name to match on.
+         * @param[in] cb Callback to invoke when there is a signal matching the requested data. See <a href="https://developer.gnome.org/gio/2.35/GDBusConnection.html#GDBusSignalCallback">GDBusSignalCallback</a> documentation.
+         * @param[in] data User data to pass to \b cb.
+         * @return a bool indicating success of setting listener
+         */
+        static bool setSignalListener(GBusType type, const char *service, const char *iface,
+                                      const char *path, const char *name, GDBusSignalCallback cb,
+                                      void *data);
+        /**
+         * A helper method to unsubscribe from DBUS siganl.
+         * @param[in] type A type of the bus that the signal is subscribed to. See <a href="https://developer.gnome.org/gio/2.35/GDBusConnection.html#GBusType">GBusType</a> documentation.
+         * @param[in] service Service name to match on (unique or well-known name).
+         * @param[in] iface D-Bus interface name to match on.
+         * @param[in] path Object path to match on.
+         * @param[in] name D-Bus signal name to match on.
+         */
+        static void removeSignalListener(GBusType type, const char *service, const char *iface,
+                                         const char *path,   const char *name);
+
+    private: // viriables
+        static std::map<std::string, guint> mSubsIdsMap; /*! A map that holds ids of subscriptions to DBUS signals */
+};
+
+/*! \class CtxCbData
+ *  \brief A class to store data for asynchronous operation.
+ *
+ *  A class to store data for asynchronous operation: context, callback function and two pointers to user data.
+ */
+class CtxCbData {
+    public:
+        /**
+         * A default constructor, allowing to pass the data in the construction phase.
+         * @param[in] ctx A pointer to the instance of an object that the asynchronous call was made on.
+         * @param[in] cb A pointer to store callback method. It is usually used when there is a need for multiple level of aynchronous calls.
+         * @param[in] data1 User data to pass to \b cb.
+         * @param[in] data2 User data to pass to \b cb.
+         */
+        CtxCbData(void *ctx, void *cb, void *data1, void *data2) {
+            this->ctx = ctx;
+            this->cb = cb;
+            this->data1 = data1;
+            this->data2 = data2;
+        }
+        void *ctx;     /*!< to store current context */
+        void *cb;      /*!< to store pointer to callback function */
+        void *data1;   /*!< to store user data 1 */
+        void *data2;   /*!< to store user data 2 */
+};
+
+#endif /* UTILS_H_ */
+
diff --git a/tizen.bt.h b/tizen.bt.h
new file mode 100644 (file)
index 0000000..401360e
--- /dev/null
@@ -0,0 +1,43 @@
+
+/**
+ * @defgroup wrt-plugins-tizen-bt wrt-plugins-tizen-bt shared library
+ * \brief WebAPI to replace \b tizen.bluetooth due to missing functionality.
+ *
+ * This module represents a replacement for <a href="https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/bluetooth.html">tizen.bluetooth</a>. The reason for implementing another, by API interface identical bluetooth WebAPI wrt plugin, is due to an issue reported <a href="https://bugs.tizen.org/jira/browse/TIVI-2418">here</a>. If \b tizen.bluetooth is used together with direct calls to Bluez's D-Bus methods, an unpredictable behavior is observed, eg. discoverDevices method call fails to complete, or doesn't start at all.  As a solution, a replacing \b tizen.bt WebAPI is implemented, which is implementing direct calls to Bluez's D-Bus methods, rather than a calls to \b capi-network-bluetooth API methods.
+ *
+ * The following Bluetooth functionalities are provided:
+ *
+ * <ul>
+ *     <li> Controls local Bluetooth device, that is, turn Bluetooth on/off, etc. </li>
+ *     <li> Sets visibility </li>
+ *     <li> Discovers nearby Bluetooth devices (Device discovery). </li>
+ *     <li> Gets bonded devices information. </li>
+ *     <li> Controls bonding. </li>
+ * </ul>
+ *
+ * Comparing to original \b tizen.bluetooth functionalities listed <a href="https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/bluetooth.html">here</a>, it is missing implementation of following functionalities:
+ * <ul>
+ *     <li> Connects to a service on a remote device and exchanges data. </li>
+ *     <li> Registers a service (RFCOMM) on a local device, which can be consumed by remote devices to exchange data. </li>
+ * </ul>
+ *
+ * For more information on the Bluetooth features, see the <a href="https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/bluetooth.html">documentation</a> of offical API.
+ *
+ * The <a href="https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/bluetooth.html#::Bluetooth::BluetoothAdapter">BluetoothAdapter</a> documentations defines <a href="https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/bluetooth.html#setChangeListeneridp215896">setChangeListener</a> and <a href="https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/bluetooth.html#unsetChangeListeneridp221928">unsetChangeListener</a> methods, however these two methods are not implemented in <a href="https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/bluetooth.html">tizen.bluetooth</a>. Tizen.bt implements these two methods as they are defined in <a href="https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/bluetooth.html">tizen.bluetooth</a> documentation.\n
+ * Additionaly it fixes an issues with <a href="https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/bluetooth.html#createBondingidp276872">createBonding</a> method. When a method is called, it registers \b org.bluez.Agent and implements its methods in the following way:
+ * <ul>
+ *     <li>Release - does nothing. </li>
+ *     <li>Authorize - automatically authorizes. </li>
+ *     <li>RequestPinCode - uses default pin code \b "123456". </li>
+ *     <li>RequestPasskey - uses default passkey \b 123456. </li>
+ *     <li>DisplayPasskey - does nothing. </li>
+ *     <li>RequestConfirmation - automatically confirms. </li>
+ *     <li>ConfirmModeChange - automatically confirms. </li>
+ *     <li>Cancel - does nothing. </li>
+ * </ul>
+ *
+ * @{
+ */
+
+/** @} */
+
diff --git a/wrt-plugins-tizen-bt.manifest b/wrt-plugins-tizen-bt.manifest
new file mode 100644 (file)
index 0000000..81ace0c
--- /dev/null
@@ -0,0 +1,6 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>
+