From 14971be0cbbcbe5b3aa79f7216e3846aef57dbd1 Mon Sep 17 00:00:00 2001 From: brianjjones Date: Fri, 7 Mar 2014 13:37:04 -0800 Subject: [PATCH 1/1] Initial commit for Bluetooth plugin for HTML5 UI Change-Id: Iaa8eef1bce585d17884e75b9e9f4fb43bcda4534 --- CMakeLists.txt | 177 +++ config.dtd | 32 + packaging/wrt-plugins-tizen-bt.changes | 3 + packaging/wrt-plugins-tizen-bt.spec | 62 + pkgconfigs/wrt-plugins-tizen-bt.pc.in | 13 + src/BluetoothAdapter.cpp | 2235 ++++++++++++++++++++++++++++++++ src/BluetoothAdapter.h | 190 +++ src/BluetoothCallbackUtil.cpp | 120 ++ src/BluetoothCallbackUtil.h | 105 ++ src/BluetoothClass.cpp | 82 ++ src/BluetoothClass.h | 57 + src/BluetoothClassDeviceMajor.cpp | 76 ++ src/BluetoothClassDeviceMajor.h | 47 + src/BluetoothClassDeviceMinor.cpp | 203 +++ src/BluetoothClassDeviceMinor.h | 46 + src/BluetoothClassDeviceService.cpp | 84 ++ src/BluetoothClassDeviceService.h | 48 + src/BluetoothDevice.cpp | 324 +++++ src/BluetoothDevice.h | 68 + src/BluetoothServiceHandler.cpp | 126 ++ src/BluetoothServiceHandler.h | 64 + src/BluetoothSocket.cpp | 225 ++++ src/BluetoothSocket.h | 76 ++ src/CMakeLists.txt | 67 + src/JSBluetoothAdapter.cpp | 737 +++++++++++ src/JSBluetoothAdapter.h | 161 +++ src/JSBluetoothClass.cpp | 175 +++ src/JSBluetoothClass.h | 93 ++ src/JSBluetoothClassDeviceMajor.cpp | 114 ++ src/JSBluetoothClassDeviceMajor.h | 73 ++ src/JSBluetoothClassDeviceMinor.cpp | 175 +++ src/JSBluetoothClassDeviceMinor.h | 73 ++ src/JSBluetoothClassDeviceService.cpp | 113 ++ src/JSBluetoothClassDeviceService.h | 73 ++ src/JSBluetoothDevice.cpp | 207 +++ src/JSBluetoothDevice.h | 94 ++ src/JSBluetoothManager.cpp | 173 +++ src/JSBluetoothManager.h | 76 ++ src/JSBluetoothServiceHandler.cpp | 233 ++++ src/JSBluetoothServiceHandler.h | 91 ++ src/JSBluetoothSocket.cpp | 367 ++++++ src/JSBluetoothSocket.h | 105 ++ src/config.xml | 30 + src/plugin_config.cpp | 310 +++++ src/plugin_config.h | 90 ++ src/plugin_initializer.cpp | 87 ++ src/utils.cpp | 133 ++ src/utils.h | 135 ++ tizen.bt.h | 43 + wrt-plugins-tizen-bt.manifest | 6 + 50 files changed, 8497 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 config.dtd create mode 100644 packaging/wrt-plugins-tizen-bt.changes create mode 100644 packaging/wrt-plugins-tizen-bt.spec create mode 100644 pkgconfigs/wrt-plugins-tizen-bt.pc.in create mode 100644 src/BluetoothAdapter.cpp create mode 100644 src/BluetoothAdapter.h create mode 100644 src/BluetoothCallbackUtil.cpp create mode 100644 src/BluetoothCallbackUtil.h create mode 100644 src/BluetoothClass.cpp create mode 100644 src/BluetoothClass.h create mode 100644 src/BluetoothClassDeviceMajor.cpp create mode 100644 src/BluetoothClassDeviceMajor.h create mode 100644 src/BluetoothClassDeviceMinor.cpp create mode 100644 src/BluetoothClassDeviceMinor.h create mode 100644 src/BluetoothClassDeviceService.cpp create mode 100644 src/BluetoothClassDeviceService.h create mode 100644 src/BluetoothDevice.cpp create mode 100644 src/BluetoothDevice.h create mode 100644 src/BluetoothServiceHandler.cpp create mode 100644 src/BluetoothServiceHandler.h create mode 100644 src/BluetoothSocket.cpp create mode 100644 src/BluetoothSocket.h create mode 100644 src/CMakeLists.txt create mode 100644 src/JSBluetoothAdapter.cpp create mode 100644 src/JSBluetoothAdapter.h create mode 100644 src/JSBluetoothClass.cpp create mode 100644 src/JSBluetoothClass.h create mode 100644 src/JSBluetoothClassDeviceMajor.cpp create mode 100644 src/JSBluetoothClassDeviceMajor.h create mode 100644 src/JSBluetoothClassDeviceMinor.cpp create mode 100644 src/JSBluetoothClassDeviceMinor.h create mode 100644 src/JSBluetoothClassDeviceService.cpp create mode 100644 src/JSBluetoothClassDeviceService.h create mode 100644 src/JSBluetoothDevice.cpp create mode 100644 src/JSBluetoothDevice.h create mode 100644 src/JSBluetoothManager.cpp create mode 100644 src/JSBluetoothManager.h create mode 100644 src/JSBluetoothServiceHandler.cpp create mode 100644 src/JSBluetoothServiceHandler.h create mode 100644 src/JSBluetoothSocket.cpp create mode 100644 src/JSBluetoothSocket.h create mode 100644 src/config.xml create mode 100644 src/plugin_config.cpp create mode 100644 src/plugin_config.h create mode 100644 src/plugin_initializer.cpp create mode 100644 src/utils.cpp create mode 100644 src/utils.h create mode 100644 tizen.bt.h create mode 100644 wrt-plugins-tizen-bt.manifest diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..20fa9b6 --- /dev/null +++ b/CMakeLists.txt @@ -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 index 0000000..f1a1de4 --- /dev/null +++ b/config.dtd @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packaging/wrt-plugins-tizen-bt.changes b/packaging/wrt-plugins-tizen-bt.changes new file mode 100644 index 0000000..56db9d4 --- /dev/null +++ b/packaging/wrt-plugins-tizen-bt.changes @@ -0,0 +1,3 @@ +* Fri Mar 07 2014 brianjjones 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 index 0000000..730ccaf --- /dev/null +++ b/packaging/wrt-plugins-tizen-bt.spec @@ -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 index 0000000..2f840cf --- /dev/null +++ b/pkgconfigs/wrt-plugins-tizen-bt.pc.in @@ -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 index 0000000..e1a4e8e --- /dev/null +++ b/src/BluetoothAdapter.cpp @@ -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 + +#include +#include +#include +#include + +#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 \ + "" \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + "" + +#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(userData); + if(!adapter) { + LoggerW("userData is NULL"); + return true; + } + + if(deviceInfo == NULL) { + LoggerW("deviceInfo is NULL"); + return true; + } + + std::vector::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(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(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(iter->second->mUserData); + + if(result == BT_ERROR_NONE) { + // Update mConnectedSocket + BluetoothSocketPtr socket = new BluetoothSocket(connection); + object->mConnectedSocket.insert(std::pair(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(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(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(¤t , &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(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::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(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(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(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(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(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 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(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(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(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(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(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(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(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(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; iservice_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; iservice_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 index 0000000..2c11d30 --- /dev/null +++ b/src/BluetoothAdapter.h @@ -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 +#include +#include + +#include + +#include +#include + +#include "BluetoothDevice.h" +#include "BluetoothServiceHandler.h" +#include "BluetoothSocket.h" + +// BLUEZ +#include +#include +#include +// 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 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 ConnReqMultiMapT; // + typedef std::map RegisteredUUIDMapT; // + typedef std::map ConnectedSocketMapT; // + + // 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 mDisappearedDevices; + std::vector mFoundDevices; + std::vector 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 index 0000000..1c10078 --- /dev/null +++ b/src/BluetoothCallbackUtil.cpp @@ -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 + +#include +#include + +#include "BluetoothCallbackUtil.h" +#include "BluetoothAdapter.h" + +#include + +using namespace DeviceAPI::Common; + +namespace DeviceAPI { +namespace Bluetooth { + +static Eina_Bool jobCompleteCB(void *userData){ + BluetoothCallbackUserDataPtr data = static_cast(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 index 0000000..e795f42 --- /dev/null +++ b/src/BluetoothCallbackUtil.h @@ -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 +#include +#include +#include + + +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 index 0000000..e1e23d8 --- /dev/null +++ b/src/BluetoothClass.cpp @@ -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 +#include + +#include "plugin_config.h" +#include "BluetoothClass.h" +#include "BluetoothClassDeviceMajor.h" +#include "BluetoothClassDeviceMinor.h" +#include "BluetoothClassDeviceService.h" +#include "JSBluetoothClassDeviceService.h" + +#include + +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::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 index 0000000..b4915bb --- /dev/null +++ b/src/BluetoothClass.h @@ -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 +#include + +#include +#include + +#include +#include + +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 mServices; + //Common::PropertyBag mLocalProperty; +}; + +typedef boost::shared_ptr BluetoothClassSharedPtr; + +} // Bluetooth +} // DeviceAPI + +#endif // __TIZEN_BLUETOOTH_CLASS_H__ diff --git a/src/BluetoothClassDeviceMajor.cpp b/src/BluetoothClassDeviceMajor.cpp new file mode 100644 index 0000000..fb7f03d --- /dev/null +++ b/src/BluetoothClassDeviceMajor.cpp @@ -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 + +#include "BluetoothClassDeviceMajor.h" + +#include + +namespace DeviceAPI { +namespace Bluetooth { + +BluetoothClassDeviceMajor::BluetoothClassDeviceMajor() +{ + mMajorStringMap.insert(std::pair("MISC", 0x00)); + mMajorStringMap.insert(std::pair("COMPUTER", 0x01)); + mMajorStringMap.insert(std::pair("PHONE", 0x02)); + mMajorStringMap.insert(std::pair("NETWORK", 0x03)); + mMajorStringMap.insert(std::pair("AUDIO_VIDEO", 0x04)); + mMajorStringMap.insert(std::pair("PERIPHERAL", 0x05)); + mMajorStringMap.insert(std::pair("IMAGING", 0x06)); + mMajorStringMap.insert(std::pair("WEARABLE", 0x07)); + mMajorStringMap.insert(std::pair("TOY", 0x08)); + mMajorStringMap.insert(std::pair("HEALTH", 0x09)); + mMajorStringMap.insert(std::pair("UNCATEGORIZED", 0x1F)); + + mMajorEnumMap.insert(std::pair(BT_MAJOR_DEVICE_CLASS_MISC, 0x00)); + mMajorEnumMap.insert(std::pair(BT_MAJOR_DEVICE_CLASS_COMPUTER, 0x01)); + mMajorEnumMap.insert(std::pair(BT_MAJOR_DEVICE_CLASS_PHONE, 0x02)); + mMajorEnumMap.insert(std::pair(BT_MAJOR_DEVICE_CLASS_LAN_NETWORK_ACCESS_POINT, 0x03)); + mMajorEnumMap.insert(std::pair(BT_MAJOR_DEVICE_CLASS_AUDIO_VIDEO, 0x04)); + mMajorEnumMap.insert(std::pair(BT_MAJOR_DEVICE_CLASS_PERIPHERAL, 0x05)); + mMajorEnumMap.insert(std::pair(BT_MAJOR_DEVICE_CLASS_IMAGING, 0x06)); + mMajorEnumMap.insert(std::pair(BT_MAJOR_DEVICE_CLASS_WEARABLE, 0x07)); + mMajorEnumMap.insert(std::pair(BT_MAJOR_DEVICE_CLASS_TOY, 0x08)); + mMajorEnumMap.insert(std::pair(BT_MAJOR_DEVICE_CLASS_HEALTH, 0x09)); + mMajorEnumMap.insert(std::pair(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 index 0000000..e57c927 --- /dev/null +++ b/src/BluetoothClassDeviceMajor.h @@ -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 +#include +#include + +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 mMajorStringMap; + std::map mMajorEnumMap; +}; + +} // Bluetooth +} // DeviceAPI + +#endif // __TIZEN_BLUETOOTH_CLASS_DEVICE_MAJOR_H__ diff --git a/src/BluetoothClassDeviceMinor.cpp b/src/BluetoothClassDeviceMinor.cpp new file mode 100644 index 0000000..5d77223 --- /dev/null +++ b/src/BluetoothClassDeviceMinor.cpp @@ -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 + +#include "BluetoothClassDeviceMinor.h" + +#include + +namespace DeviceAPI { +namespace Bluetooth { + +BluetoothClassDeviceMinor::BluetoothClassDeviceMinor() +{ + mMinorStringMap.insert(std::pair("COMPUTER_UNCATEGORIZED", 0x00)); + mMinorStringMap.insert(std::pair("COMPUTER_DESKTOP", 0x01)); + mMinorStringMap.insert(std::pair("COMPUTER_SERVER", 0x02)); + mMinorStringMap.insert(std::pair("COMPUTER_LAPTOP", 0x03)); + mMinorStringMap.insert(std::pair("COMPUTER_HANDHELD_PC_OR_PDA", 0x04)); + mMinorStringMap.insert(std::pair("COMPUTER_PALM_PC_OR_PDA", 0x5)); + mMinorStringMap.insert(std::pair("COMPUTER_WEARABLE", 0x06)); + mMinorStringMap.insert(std::pair("PHONE_UNCATEGORIZED", 0x00)); + mMinorStringMap.insert(std::pair("PHONE_CELLULAR", 0x01)); + mMinorStringMap.insert(std::pair("PHONE_CORDLESS", 0x02)); + mMinorStringMap.insert(std::pair("PHONE_SMARTPHONE", 0x03)); + mMinorStringMap.insert(std::pair("PHONE_MODEM_OR_GATEWAY", 0x04)); + mMinorStringMap.insert(std::pair("PHONE_ISDN", 0x05)); + mMinorStringMap.insert(std::pair("AV_UNRECOGNIZED", 0x00)); + mMinorStringMap.insert(std::pair("AV_WEARABLE_HEADSET", 0x01)); + mMinorStringMap.insert(std::pair("AV_HANDSFREE", 0x02)); + mMinorStringMap.insert(std::pair("AV_MICROPHONE", 0x04)); + mMinorStringMap.insert(std::pair("AV_LOUDSPEAKER", 0x05)); + mMinorStringMap.insert(std::pair("AV_HEADPHONES", 0x06)); + mMinorStringMap.insert(std::pair("AV_PORTABLE_AUDIO", 0x07)); + mMinorStringMap.insert(std::pair("AV_CAR_AUDIO", 0x08)); + mMinorStringMap.insert(std::pair("AV_SETTOP_BOX", 0x09)); + mMinorStringMap.insert(std::pair("AV_HIFI", 0x0a)); + mMinorStringMap.insert(std::pair("AV_VCR", 0x0b)); + mMinorStringMap.insert(std::pair("AV_VIDEO_CAMERA", 0x0c)); + mMinorStringMap.insert(std::pair("AV_CAMCORDER", 0x0d)); + mMinorStringMap.insert(std::pair("AV_MONITOR", 0x0e)); + mMinorStringMap.insert(std::pair("AV_DISPLAY_AND_LOUDSPEAKER", 0x0f)); + mMinorStringMap.insert(std::pair("AV_VIDEO_CONFERENCING", 0x10)); + mMinorStringMap.insert(std::pair("AV_GAMING_TOY", 0x12)); + mMinorStringMap.insert(std::pair("PERIPHERAL_UNCATEGORIZED", 0)); + mMinorStringMap.insert(std::pair("PERIPHERAL_KEYBOARD", 0x10)); + mMinorStringMap.insert(std::pair("PERIPHERAL_POINTING_DEVICE", 0x20)); + mMinorStringMap.insert(std::pair("PERIPHERAL_KEYBOARD_AND_POINTING_DEVICE", 0x30)); + mMinorStringMap.insert(std::pair("PERIPHERAL_JOYSTICK", 0x01)); + mMinorStringMap.insert(std::pair("PERIPHERAL_GAMEPAD", 0x02)); + mMinorStringMap.insert(std::pair("PERIPHERAL_REMOTE_CONTROL", 0x03)); + mMinorStringMap.insert(std::pair("PERIPHERAL_SENSING_DEVICE", 0x04)); + mMinorStringMap.insert(std::pair("PERIPHERAL_DEGITIZER_TABLET", 0x05)); + mMinorStringMap.insert(std::pair("PERIPHERAL_CARD_READER", 0x06)); + mMinorStringMap.insert(std::pair("PERIPHERAL_DIGITAL_PEN", 0x07)); + mMinorStringMap.insert(std::pair("PERIPHERAL_HANDHELD_SCANNER", 0x08)); + mMinorStringMap.insert(std::pair("PERIPHERAL_HANDHELD_INPUT_DEVICE", 0x09)); + mMinorStringMap.insert(std::pair("IMAGING_UNCATEGORIZED", 0x00)); + mMinorStringMap.insert(std::pair("IMAGING_DISPLAY", 0x04)); + mMinorStringMap.insert(std::pair("IMAGING_CAMERA", 0x08)); + mMinorStringMap.insert(std::pair("IMAGING_SCANNER", 0x10)); + mMinorStringMap.insert(std::pair("IMAGING_PRINTER", 0x20)); + mMinorStringMap.insert(std::pair("WEARABLE_WRITST_WATCH", 0x01)); + mMinorStringMap.insert(std::pair("WEARABLE_PAGER", 0x02)); + mMinorStringMap.insert(std::pair("WEARABLE_JACKET", 0x03)); + mMinorStringMap.insert(std::pair("WEARABLE_HELMET", 0x04)); + mMinorStringMap.insert(std::pair("WEARABLE_GLASSES", 0x05)); + mMinorStringMap.insert(std::pair("TOY_ROBOT", 0x01)); + mMinorStringMap.insert(std::pair("TOY_VEHICLE", 0x02)); + mMinorStringMap.insert(std::pair("TOY_DOLL", 0x03)); + mMinorStringMap.insert(std::pair("TOY_CONTROLLER", 0x04)); + mMinorStringMap.insert(std::pair("TOY_GAME", 0x05)); + mMinorStringMap.insert(std::pair("HEALTH_UNDEFINED", 0x00)); + mMinorStringMap.insert(std::pair("HEALTH_BLOOD_PRESSURE_MONITOR", 0x01)); + mMinorStringMap.insert(std::pair("HEALTH_THERMOMETER", 0x02)); + mMinorStringMap.insert(std::pair("HEALTH_WEIGHING_SCALE", 0x03)); + mMinorStringMap.insert(std::pair("HEALTH_GLUCOSE_METER", 0x04)); + mMinorStringMap.insert(std::pair("HEALTH_PULSE_OXIMETER", 0x05)); + mMinorStringMap.insert(std::pair("HEALTH_PULSE_RATE_MONITOR", 0x06)); + mMinorStringMap.insert(std::pair("HEALTH_DATA_DISPLAY", 0x07)); + mMinorStringMap.insert(std::pair("HEALTH_STEP_COUNTER", 0x08)); + mMinorStringMap.insert(std::pair("HEALTH_BODY_COMPOSITION_ANALYZER", 0x09)); + mMinorStringMap.insert(std::pair("HEALTH_PEAK_FLOW_MONITOR", 0x0a)); + mMinorStringMap.insert(std::pair("HEALTH_MEDICATION_MONITOR", 0x0b)); + mMinorStringMap.insert(std::pair("HEALTH_KNEE_PROSTHESIS", 0x0c)); + mMinorStringMap.insert(std::pair("HEALTH_ANKLE_PROSTHESIS", 0x0d)); + + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_COMPUTER_UNCATEGORIZED, 0x00)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_COMPUTER_DESKTOP_WORKSTATION , 0x01)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_COMPUTER_SERVER_CLASS , 0x02)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_COMPUTER_LAPTOP , 0x03)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_COMPUTER_HANDHELD_PC_OR_PDA , 0x04)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_COMPUTER_PALM_SIZED_PC_OR_PDA, 0x5)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_COMPUTER_WEARABLE_COMPUTER , 0x06)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PHONE_UNCATEGORIZED , 0x00)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PHONE_CELLULAR , 0x01)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PHONE_CORDLESS , 0x02)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PHONE_SMART_PHONE , 0x03)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PHONE_WIRED_MODEM_OR_VOICE_GATEWAY , 0x04)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PHONE_COMMON_ISDN_ACCESS , 0x05)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_UNCATEGORIZED , 0x00)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_WEARABLE_HEADSET , 0x01)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_HANDS_FREE , 0x02)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_MICROPHONE , 0x04)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_LOUDSPEAKER , 0x05)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_HEADPHONES , 0x06)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_PORTABLE_AUDIO , 0x07)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_CAR_AUDIO , 0x08)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_SET_TOP_BOX , 0x09)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_HIFI_AUDIO_DEVICE , 0x0a)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VCR , 0x0b)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_CAMERA , 0x0c)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_CAMCORDER , 0x0d)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_MONITOR , 0x0e)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_DISPLAY_LOUDSPEAKER , 0x0f)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_CONFERENCING , 0x10)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_GAMING_TOY , 0x12)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PERIPHERA_UNCATEGORIZED , 0)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PERIPHERAL_KEY_BOARD , 0x10)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PERIPHERAL_POINTING_DEVICE , 0x20)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PERIPHERAL_COMBO_KEYBOARD_POINTING_DEVICE , 0x30)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PERIPHERAL_JOYSTICK , 0x01)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PERIPHERAL_GAME_PAD , 0x02)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PERIPHERAL_REMOTE_CONTROL , 0x03)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PERIPHERAL_SENSING_DEVICE , 0x04)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PERIPHERAL_DIGITIZER_TABLET , 0x05)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PERIPHERAL_CARD_READER , 0x06)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PERIPHERAL_DIGITAL_PEN , 0x07)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PERIPHERAL_HANDHELD_SCANNER , 0x08)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_PERIPHERAL_HANDHELD_GESTURAL_INPUT_DEVICE , 0x09)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_IMAGING_DISPLAY , 0x04)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_IMAGING_CAMERA , 0x08)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_IMAGING_SCANNER , 0x10)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_IMAGING_PRINTER, 0x20)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_WEARABLE_WRIST_WATCH , 0x01)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_WEARABLE_PAGER , 0x02)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_WEARABLE_JACKET , 0x03)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_WEARABLE_HELMET , 0x04)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_WEARABLE_GLASSES , 0x05)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_TOY_ROBOT , 0x01)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_TOY_VEHICLE , 0x02)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_TOY_DOLL_ACTION , 0x03)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_TOY_CONTROLLER , 0x04)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_TOY_GAME , 0x05)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_HEATH_UNCATEGORIZED , 0x00)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_HEATH_BLOOD_PRESSURE_MONITOR , 0x01)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_HEATH_THERMOMETER , 0x02)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_HEATH_WEIGHING_SCALE , 0x03)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_HEATH_GLUCOSE_METER , 0x04)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_HEATH_PULSE_OXIMETER , 0x05)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_HEATH_HEART_PULSE_RATE_MONITOR , 0x06)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_HEATH_DATA_DISPLAY , 0x07)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_HEATH_STEP_COUNTER , 0x08)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_HEATH_BODY_COMPOSITION_ANALYZER , 0x09)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_HEATH_PEAK_FLOW_MONITOR , 0x0a)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_HEATH_MEDICATION_MONITOR , 0x0b)); + mMinorEnumMap.insert(std::pair(BT_MINOR_DEVICE_CLASS_HEATH_KNEE_PROSTHESIS , 0x0c)); + mMinorEnumMap.insert(std::pair(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::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 index 0000000..90f62da --- /dev/null +++ b/src/BluetoothClassDeviceMinor.h @@ -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 +#include +#include + +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 mMinorStringMap; + std::map mMinorEnumMap; +}; + +} // Bluetooth +} // DeviceAPI + +#endif // __TIZEN_BLUETOOTH_CLASS_DEVICE_MINOR_H__ diff --git a/src/BluetoothClassDeviceService.cpp b/src/BluetoothClassDeviceService.cpp new file mode 100644 index 0000000..9163af3 --- /dev/null +++ b/src/BluetoothClassDeviceService.cpp @@ -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 + +#include "BluetoothClassDeviceService.h" + +#include + +namespace DeviceAPI { +namespace Bluetooth { + +BluetoothClassDeviceService::BluetoothClassDeviceService() +{ + mServiceStringMap.insert(std::pair("LIMITED_DISCOVERABILITY", 0x0001)); + mServiceStringMap.insert(std::pair("POSITIONING", 0x0008)); + mServiceStringMap.insert(std::pair("NETWORKING", 0x0010)); + mServiceStringMap.insert(std::pair("RENDERING", 0x0020)); + mServiceStringMap.insert(std::pair("CAPTURING", 0x0040)); + mServiceStringMap.insert(std::pair("OBJECT_TRANSFER", 0x0080)); + mServiceStringMap.insert(std::pair("AUDIO", 0x0100)); + mServiceStringMap.insert(std::pair("TELEPHONY", 0x0200)); + mServiceStringMap.insert(std::pair("INFORMATION", 0x0400)); + + mServiceEnumMap.insert(std::pair(BT_MAJOR_SERVICE_CLASS_LIMITED_DISCOVERABLE_MODE, 0x0001)); + mServiceEnumMap.insert(std::pair(BT_MAJOR_SERVICE_CLASS_POSITIONING, 0x0008)); + mServiceEnumMap.insert(std::pair(BT_MAJOR_SERVICE_CLASS_NETWORKING, 0x0010)); + mServiceEnumMap.insert(std::pair(BT_MAJOR_SERVICE_CLASS_RENDERING, 0x0020)); + mServiceEnumMap.insert(std::pair(BT_MAJOR_SERVICE_CLASS_CAPTURING, 0x0040)); + mServiceEnumMap.insert(std::pair(BT_MAJOR_SERVICE_CLASS_OBJECT_TRANSFER, 0x0080)); + mServiceEnumMap.insert(std::pair(BT_MAJOR_SERVICE_CLASS_AUDIO, 0x0100)); + mServiceEnumMap.insert(std::pair(BT_MAJOR_SERVICE_CLASS_TELEPHONY, 0x0200)); + mServiceEnumMap.insert(std::pair(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 BluetoothClassDeviceService::getServiceValues(int serviceMask) +{ + std::vector ret; + for(std::map::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 index 0000000..7d05f9b --- /dev/null +++ b/src/BluetoothClassDeviceService.h @@ -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 +#include +#include +#include + +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 getServiceValues(int serviceMask); + +private: + std::map mServiceStringMap; + std::map mServiceEnumMap; +}; + +} // Bluetooth +} // DeviceAPI + +#endif // __TIZEN_BLUETOOTH_CLASS_DEVICE_SERVICE_H__ diff --git a/src/BluetoothDevice.cpp b/src/BluetoothDevice.cpp new file mode 100644 index 0000000..4f97bbb --- /dev/null +++ b/src/BluetoothDevice.cpp @@ -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 +#include + +#include "plugin_config.h" +#include "BluetoothDevice.h" +#include "BluetoothAdapter.h" +#include "JSBluetoothClass.h" + +#include + +//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 index 0000000..86429ac --- /dev/null +++ b/src/BluetoothDevice.h @@ -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 +#include + +#include +#include +#include +#include + +#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 mUUIDs; + //Common::PropertyBag mLocalProperty; + bool isUpdated; +}; + +typedef boost::shared_ptr BluetoothDeviceSharedPtr; + +} // Bluetooth +} // DeviceAPI + +#endif // __TIZEN_BLUETOOTH_DEVICE_H__ diff --git a/src/BluetoothServiceHandler.cpp b/src/BluetoothServiceHandler.cpp new file mode 100644 index 0000000..253bb15 --- /dev/null +++ b/src/BluetoothServiceHandler.cpp @@ -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 +#include + +#include "BluetoothServiceHandler.h" +#include "BluetoothAdapter.h" +#include "BluetoothCallbackUtil.h" +#include "plugin_config.h" + +#include + +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 index 0000000..11dc506 --- /dev/null +++ b/src/BluetoothServiceHandler.h @@ -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 +#include + +//#include +#include +#include + +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 index 0000000..018cbc1 --- /dev/null +++ b/src/BluetoothSocket.cpp @@ -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 +#include + +#include "BluetoothSocket.h" +#include "BluetoothAdapter.h" +#include "plugin_config.h" +#include "JSBluetoothDevice.h" + +#include + +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(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(data[i])); + } +} + +std::vector BluetoothSocket::readData() +{ + std::vector 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 index 0000000..a5d4662 --- /dev/null +++ b/src/BluetoothSocket.h @@ -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 +#include +#include + +//#include +#include +#include + +#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 readData(); + void close(); + +private: + std::string mUUID; + int mConnectedSocket; + bool mIsConnected; + BluetoothDeviceSharedPtr mPeer; + std::vector 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 index 0000000..e64d8bf --- /dev/null +++ b/src/CMakeLists.txt @@ -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 index 0000000..1e6dd36 --- /dev/null +++ b/src/JSBluetoothAdapter.cpp @@ -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 + +#include +#include +#include + +#include "plugin_config.h" +#include "JSBluetoothAdapter.h" +#include "BluetoothAdapter.h" + +#include +#include + +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 index 0000000..a4edc63 --- /dev/null +++ b/src/JSBluetoothAdapter.h @@ -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 + +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 index 0000000..7a505b2 --- /dev/null +++ b/src/JSBluetoothClass.cpp @@ -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 + +#include +#include +#include +#include + +#include "plugin_config.h" + +#include "JSBluetoothClass.h" +#include "BluetoothAdapter.h" + +#include +#include + +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(holder)); +} + +void JSBluetoothClass::initialize(JSContextRef context, JSObjectRef object) +{ + // do nothing +} + +void JSBluetoothClass::finalize(JSObjectRef object) +{ + BluetoothClassHolderPtr priv = static_cast(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(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(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 index 0000000..ebd8862 --- /dev/null +++ b/src/JSBluetoothClass.h @@ -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 +#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 index 0000000..2e38412 --- /dev/null +++ b/src/JSBluetoothClassDeviceMajor.cpp @@ -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 +#include "plugin_config.h" +#include "JSBluetoothClassDeviceMajor.h" +#include "BluetoothClassDeviceMajor.h" + +#include + +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 index 0000000..b61d84f --- /dev/null +++ b/src/JSBluetoothClassDeviceMajor.h @@ -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 + +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 index 0000000..d17729f --- /dev/null +++ b/src/JSBluetoothClassDeviceMinor.cpp @@ -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 +#include "plugin_config.h" +#include "JSBluetoothClassDeviceMinor.h" +#include "BluetoothClassDeviceMinor.h" + +#include + +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 index 0000000..1877cc5 --- /dev/null +++ b/src/JSBluetoothClassDeviceMinor.h @@ -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 + +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 index 0000000..cbf363b --- /dev/null +++ b/src/JSBluetoothClassDeviceService.cpp @@ -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 +#include "plugin_config.h" +#include "JSBluetoothClassDeviceService.h" +#include "BluetoothClassDeviceService.h" + +#include + +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 index 0000000..5ae6fce --- /dev/null +++ b/src/JSBluetoothClassDeviceService.h @@ -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 + +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 index 0000000..31323a9 --- /dev/null +++ b/src/JSBluetoothDevice.cpp @@ -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 + +#include +#include +#include +#include +#include + +#include "plugin_config.h" +#include "JSBluetoothDevice.h" +#include "BluetoothDevice.h" +#include "BluetoothAdapter.h" + +#include +#include + +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(holder)); +} + +void JSBluetoothDevice::initialize(JSContextRef context, JSObjectRef object) +{ + // Do nothing +} + +void JSBluetoothDevice::finalize(JSObjectRef object) +{ + BluetoothDeviceHolderPtr priv = static_cast(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(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(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 index 0000000..ba02bd7 --- /dev/null +++ b/src/JSBluetoothDevice.h @@ -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 + +#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 index 0000000..ff4d7e8 --- /dev/null +++ b/src/JSBluetoothManager.cpp @@ -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 + +#include +#include +#include +#include +#include + +#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 +#include + +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(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(JSObjectGetPrivate(object)); + if (priv) { + JSObjectSetPrivate(object, NULL); + delete priv; + } +} + +JSValueRef JSBluetoothManager::getReadOnlyProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) { + PropertyBag *priv = static_cast(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 index 0000000..99e579e --- /dev/null +++ b/src/JSBluetoothManager.h @@ -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 + +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 index 0000000..2a74954 --- /dev/null +++ b/src/JSBluetoothServiceHandler.cpp @@ -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 + +#include +#include +#include +#include +#include + +#include "plugin_config.h" +#include "JSBluetoothServiceHandler.h" +#include "BluetoothAdapter.h" + +#include +#include + +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(service)); +} + +void JSBluetoothServiceHandler::initialize(JSContextRef context, JSObjectRef object) +{ + // do nothing +} + +void JSBluetoothServiceHandler::finalize(JSObjectRef object) +{ + BluetoothServiceHandlerPtr priv = static_cast(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(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(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(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 index 0000000..c59540d --- /dev/null +++ b/src/JSBluetoothServiceHandler.h @@ -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 +#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 index 0000000..1332d7a --- /dev/null +++ b/src/JSBluetoothSocket.cpp @@ -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 + +#include +#include +#include +#include +#include +#include + +#include "plugin_config.h" +#include "JSBluetoothSocket.h" +#include "BluetoothSocket.h" +#include "BluetoothAdapter.h" + +#include +#include + +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(socket)); +} + +void JSBluetoothSocket::initialize(JSContextRef context, JSObjectRef object) +{ + // do nothing +} + +void JSBluetoothSocket::finalize(JSObjectRef object) +{ + BluetoothSocketPtr priv = static_cast(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(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(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(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(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(JSObjectGetPrivate(thisObject)); + if (!priv) { + throw DeviceAPI::Common::UnknownException("Private object is NULL."); + } + + std::vector 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(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 index 0000000..26ec403 --- /dev/null +++ b/src/JSBluetoothSocket.h @@ -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 +#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 index 0000000..adb2bd0 --- /dev/null +++ b/src/config.xml @@ -0,0 +1,30 @@ + + + + libwrt-plugins-tizen-bt.so + bt.install.uri + SAMSUNG plugin group + SAMSUNG certificate authority + AAAABBBBCCCCDDDEEEE0000 + + + http://tizen.org/privilege/bluetooth.gap + bluetooth.gap + + + + http://tizen.org/privilege/bluetooth.admin + bluetooth.admin + + + + http://tizen.org/privilege/bluetoothmanager + bluetoothmanager + + + + http://tizen.org/privilege/bluetooth.spp + bluetooth.spp + + + diff --git a/src/plugin_config.cpp b/src/plugin_config.cpp new file mode 100644 index 0000000..6783626 --- /dev/null +++ b/src/plugin_config.cpp @@ -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 +#include +#include + +#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 index 0000000..bb99878 --- /dev/null +++ b/src/plugin_config.h @@ -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 +#include + +#include + +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 >( \ + getBluetoothFunctionData, \ + functionName) + +} +} + +#endif // _BLUETOOTH_PLUGIN_CONFIG_H_ diff --git a/src/plugin_initializer.cpp b/src/plugin_initializer.cpp new file mode 100644 index 0000000..7ac7ef1 --- /dev/null +++ b/src/plugin_initializer.cpp @@ -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 +#include + +#include + +#include "JSBluetoothManager.h" +#include "BluetoothAdapter.h" + +#include +#include + +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(context)); +} + +void on_frame_unload_callback(const void *context) +{ + LoggerD("[Tizen\\Bluetooth] on_frame_unload_callback (%p)", context); + GlobalContextManager::getInstance()->removeGlobalContext(static_cast(context)); + BluetoothAdapter::getInstance()->unloadFrame(static_cast(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 index 0000000..6853816 --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,133 @@ + +#include +#include +#include +#include + +#include "utils.h" + +#include "Logger.h" + +GQuark g_phone_error_quark(void) +{ + return g_quark_from_static_string("g-phone-error-quark"); +} + +std::map 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::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 index 0000000..f5c34d9 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,135 @@ + +#ifndef UTILS_H_ +#define UTILS_H_ + +#include +#include +#include +#include +#include + +/** + * 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 GBusType 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 GDBusSignalCallback 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 GBusType 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 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 index 0000000..401360e --- /dev/null +++ b/tizen.bt.h @@ -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 tizen.bluetooth. The reason for implementing another, by API interface identical bluetooth WebAPI wrt plugin, is due to an issue reported here. 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: + * + *
    + *
  • Controls local Bluetooth device, that is, turn Bluetooth on/off, etc.
  • + *
  • Sets visibility
  • + *
  • Discovers nearby Bluetooth devices (Device discovery).
  • + *
  • Gets bonded devices information.
  • + *
  • Controls bonding.
  • + *
+ * + * Comparing to original \b tizen.bluetooth functionalities listed here, it is missing implementation of following functionalities: + *
    + *
  • Connects to a service on a remote device and exchanges data.
  • + *
  • Registers a service (RFCOMM) on a local device, which can be consumed by remote devices to exchange data.
  • + *
+ * + * For more information on the Bluetooth features, see the documentation of offical API. + * + * The BluetoothAdapter documentations defines setChangeListener and unsetChangeListener methods, however these two methods are not implemented in tizen.bluetooth. Tizen.bt implements these two methods as they are defined in tizen.bluetooth documentation.\n + * Additionaly it fixes an issues with createBonding method. When a method is called, it registers \b org.bluez.Agent and implements its methods in the following way: + *
    + *
  • Release - does nothing.
  • + *
  • Authorize - automatically authorizes.
  • + *
  • RequestPinCode - uses default pin code \b "123456".
  • + *
  • RequestPasskey - uses default passkey \b 123456.
  • + *
  • DisplayPasskey - does nothing.
  • + *
  • RequestConfirmation - automatically confirms.
  • + *
  • ConfirmModeChange - automatically confirms.
  • + *
  • Cancel - does nothing.
  • + *
+ * + * @{ + */ + +/** @} */ + diff --git a/wrt-plugins-tizen-bt.manifest b/wrt-plugins-tizen-bt.manifest new file mode 100644 index 0000000..81ace0c --- /dev/null +++ b/wrt-plugins-tizen-bt.manifest @@ -0,0 +1,6 @@ + + + + + + -- 2.7.4