summaryrefslogtreecommitdiff
path: root/mobile_src/Bluetooth/BluetoothHealthProfileHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mobile_src/Bluetooth/BluetoothHealthProfileHandler.cpp')
-rw-r--r--mobile_src/Bluetooth/BluetoothHealthProfileHandler.cpp411
1 files changed, 411 insertions, 0 deletions
diff --git a/mobile_src/Bluetooth/BluetoothHealthProfileHandler.cpp b/mobile_src/Bluetooth/BluetoothHealthProfileHandler.cpp
new file mode 100644
index 0000000..8299baa
--- /dev/null
+++ b/mobile_src/Bluetooth/BluetoothHealthProfileHandler.cpp
@@ -0,0 +1,411 @@
+//
+// 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 <Logger.h>
+#include <JSWebAPIErrorFactory.h>
+#include <JSUtil.h>
+#include <TimeTracer.h>
+
+#include "BluetoothHealthProfileHandler.h"
+#include "BluetoothHealthProfileHandlerCallback.h"
+#include "JSBluetoothHealthApplication.h"
+#include "JSBluetoothDevice.h"
+#include "JSBluetoothHealthChannel.h"
+#include "BluetoothHealthChannel.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+void BluetoothHealthProfileHandler::onConnected(int result, const char *remote_address, const char *app_id,
+ bt_hdp_channel_type_e type, unsigned int channel, void *userData)
+{
+ LoggerD("Enter");
+ TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+ HealthProfileHandlerPtr object = static_cast<HealthProfileHandlerPtr>(userData);
+ if(!object) {
+ LoggerW("userData is NULL");
+ return;
+ }
+
+ if(result != BT_ERROR_NONE) {
+ LoggerD("Not BT_ERROR_NONE");
+ }
+
+ LoggerD("Connected app: " << app_id);
+ LoggerD("Connected channel: " << channel);
+
+ std::string appID(app_id);
+ RegisteredHealthAppMapT::iterator iter = object->mRegisteredHealthAppMap.find(appID);
+ if(iter == object->mRegisteredHealthAppMap.end()) {
+ LoggerW("This app is not registered");
+ return;
+ }
+ BluetoothHealthApplicationSharedPtr application = iter->second;
+
+ bool isChannelInserted = false;
+ BluetoothHealthChannelPtr healthChannel = NULL;
+
+ // call BluetoothHealthApplication.onconnect
+ if(result == BT_ERROR_NONE) {
+ Common::MultiCallbackUserDataPtr callback = application->getOnConnect();
+ if(callback) {
+ bt_device_info_s *deviceInfo = NULL;
+ if(bt_adapter_get_bonded_device_info(remote_address, &deviceInfo) == BT_ERROR_NONE &&
+ deviceInfo != NULL) {
+ BluetoothDeviceSharedPtr device(new BluetoothDevice(deviceInfo));
+ // need to check
+ device->copyAceCheckAccessFunction(getInstance());
+ bt_adapter_free_device_info(deviceInfo);
+
+ LoggerD("invoke BluetoothHealthApplication.onconnect");
+ healthChannel = new BluetoothHealthChannel(channel, device, type, application);
+ healthChannel->copyAceCheckAccessFunction(getInstance());
+ object->mConnectedSocketMap.insert(std::pair<unsigned int, BluetoothHealthChannelPtr>(channel, healthChannel));
+ isChannelInserted = true;
+ callback->invokeCallback("onconnect", JSBluetoothHealthChannel::createJSObject(callback->getContext(), healthChannel));
+ }
+ else {
+ LoggerE("Can't call BluetoothHealthApplication.onconnect because failed to get device info");
+ }
+ }
+ else {
+ LoggerD("BluetoothHealthApplication.onconnect is not set");
+ }
+ }
+
+ // in case of connectToSource()
+ HealthConnReqMapT::iterator i = object->mHealthConnReqMap.find(application);
+ if(i != object->mHealthConnReqMap.end()) {
+ LoggerD("Requested connection");
+ Common::MultiCallbackUserDataPtr callback = i->second->mUserData;
+ if(callback) {
+ if(result == BT_ERROR_NONE) {
+ if(isChannelInserted == false) {
+ healthChannel = new BluetoothHealthChannel(channel, i->second->mRemoteDevice, type, application);
+ healthChannel->copyAceCheckAccessFunction(getInstance());
+ object->mConnectedSocketMap.insert(std::pair<unsigned int, BluetoothHealthChannelPtr>(channel, healthChannel));
+ }
+ callback->invokeCallback("success", JSBluetoothHealthChannel::createJSObject(callback->getContext(), healthChannel));
+ }
+ else {
+ LoggerE("Failed to establish a connection with health profile");
+ callback->invokeCallback("error",
+ JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), UnknownException("Failed to establish a connection with health profile")));
+ }
+ }
+
+ // Update mHealthConnReqMap
+ object->mHealthConnReqMap.erase(i);
+ }
+ else {
+ LoggerD("There is no connection request");
+ }
+
+ TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothHealthProfileHandler::onDisconnected(int result, const char *remote_address, unsigned int channel, void *userData)
+{
+ LoggerD("Enter");
+ TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+ HealthProfileHandlerPtr object = static_cast<HealthProfileHandlerPtr>(userData);
+ if(!object) {
+ LoggerW("userData is NULL");
+ return;
+ }
+
+ LoggerD("Disconnected channel: " << channel);
+ HealthConnectedSocketMapT::iterator iter = object->mConnectedSocketMap.find(channel);
+ if(iter == object->mConnectedSocketMap.end()) {
+ LoggerW("Unexpected health disconnection event");
+ return;
+ }
+
+ if(result == BT_ERROR_NONE) {
+ BluetoothHealthChannelPtr healthChannel = iter->second;
+ object->mConnectedSocketMap.erase(iter);
+
+ healthChannel->setConnectionState(false);
+ MultiCallbackUserDataPtr callback = healthChannel->getListener();
+ if(callback)
+ callback->invokeCallback("onclose");
+ }
+ else {
+ LoggerW("Failed to disconnect a connection");
+ }
+
+ TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+ LoggerD("End");
+}
+
+void BluetoothHealthProfileHandler::onDataReceivedCB(unsigned int channel, const char *data, unsigned int size, void *userData)
+{
+ LoggerD("Enter");
+
+ TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+ HealthProfileHandlerPtr object = static_cast<HealthProfileHandlerPtr>(userData);
+ if(!object) {
+ LoggerW("userData is NULL");
+ return;
+ }
+
+ LoggerD("data channel: " << channel);
+ LoggerD("sent data size: " << size);
+ HealthConnectedSocketMapT::iterator iter = object->mConnectedSocketMap.find(channel);
+ if(iter == object->mConnectedSocketMap.end()) {
+ LoggerW("Unexpected health data received event");
+ return;
+ }
+
+ BluetoothHealthChannelPtr healthChannel = iter->second;
+ MultiCallbackUserDataPtr callback = healthChannel->getListener();
+ if(callback) {
+ std::vector<signed char> receivedData;
+ for(unsigned int i = 0; i < size; i++) {
+ receivedData.push_back(static_cast<signed char>(data[i]));
+ }
+ callback->invokeCallback("onmessage", JSUtil::toJSValueRef_(callback->getContext(), receivedData));
+ }
+
+ TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+BluetoothHealthProfileHandler* BluetoothHealthProfileHandler::getInstance()
+{
+ static BluetoothHealthProfileHandler instance;
+ return &instance;
+}
+
+BluetoothHealthProfileHandler::BluetoothHealthProfileHandler()
+{
+ Common::SecurityAccessor();
+
+ if(bt_hdp_set_connection_state_changed_cb(onConnected, onDisconnected, this) != BT_ERROR_NONE) {
+ LoggerE("bt_hdp_set_connection_state_changed_cb() failed");
+ }
+
+ if(bt_hdp_set_data_received_cb(onDataReceivedCB, this) != BT_ERROR_NONE) {
+ LoggerE("bt_hdp_set_data_received_cb() failed");
+ }
+}
+
+
+BluetoothHealthProfileHandler::~BluetoothHealthProfileHandler()
+{
+ // unset platform callback
+ bt_hdp_unset_connection_state_changed_cb();
+ bt_hdp_unset_data_received_cb();
+
+ mHealthConnReqMap.clear();
+ mConnectedSocketMap.clear();
+ mRegisteredHealthAppMap.clear();
+}
+
+void BluetoothHealthProfileHandler::registerSinkApp(unsigned short dataType, std::string name, Common::MultiCallbackUserDataPtr callback)
+{
+ TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+ BluetoothHealthProfileHandlerCallback::syncToAsyncRegisterCB(callback, dataType, name);
+ TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothHealthProfileHandler::returnRegisteringSinkAppResult(unsigned short dataType, std::string name, Common::MultiCallbackUserDataPtr callback)
+{
+ LoggerD("Enter");
+ TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+ char *app_id = NULL;
+ int ret = bt_hdp_register_sink_app(dataType, &app_id);
+ switch(ret) {
+ case BT_ERROR_NONE:
+ {
+ LoggerD("Registered app: " << app_id);
+ std::string appID(app_id);
+ //free(app_id);
+ BluetoothHealthApplicationSharedPtr application(new BluetoothHealthApplication(appID, name, dataType));
+ application->copyAceCheckAccessFunction(getInstance());
+
+ mRegisteredHealthAppMap.insert(std::pair<std::string, BluetoothHealthApplicationSharedPtr>(appID, application));
+ if(callback)
+ callback->invokeCallback("success", JSBluetoothHealthApplication::createJSObject(callback->getContext(), application));
+ break;
+ }
+ case BT_ERROR_NOT_ENABLED:
+ {
+ if(callback) {
+ callback->invokeCallback("error",
+ JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), ServiceNotAvailableException("Bluetooth device is turned off")));
+ }
+ break;
+ }
+ default:
+ {
+ if(callback) {
+ callback->invokeCallback("error",
+ JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), UnknownException("Unknown error")));
+ }
+ }
+ }
+
+ TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+/*
+void BluetoothHealthProfileHandler::unregisterSinkApplication(JSObjectRef appObj, Common::MultiCallbackUserDataPtr callback)
+{
+ TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+ BluetoothHealthProfileHandlerCallback::syncToAsyncUnregisterCB(callback, appObj);
+ TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothHealthProfileHandler::returnUnregisteringResult(JSObjectRef appObj, Common::MultiCallbackUserDataPtr callback)
+{
+ TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+ BluetoothHealthApplicationSharedPtr app = JSBluetoothHealthApplication::toBluetoothHealthApplication(appObj);
+ int ret = bt_hdp_unregister_sink_app(app->getAppID().c_str());
+ switch(ret) {
+ case BT_ERROR_NONE:
+ {
+ //app->setRegistrationState(false);
+ BluetoothHealthProfileHandlerCallback::syncToAsyncSuccessCB(callback);
+ break;
+ }
+ case BT_ERROR_NOT_ENABLED:
+ {
+ ServiceNotAvailableException *error = new ServiceNotAvailableException("Bluetooth device is turned off");
+ BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
+ break;
+ }
+ default:
+ {
+ UnknownException *error = new UnknownException("Unknown error");
+ BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
+ }
+ }
+
+ TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+*/
+
+void BluetoothHealthProfileHandler::unregisterApp(std::string appID, Common::MultiCallbackUserDataPtr callback)
+{
+ TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+ BluetoothHealthProfileHandlerCallback::syncToAsyncUnregisterCB(callback, appID);
+ TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothHealthProfileHandler::returnUnregisteringAppResult(std::string appID, Common::MultiCallbackUserDataPtr callback)
+{
+ TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+ RegisteredHealthAppMapT::iterator iter = mRegisteredHealthAppMap.find(appID);
+ BluetoothHealthApplicationSharedPtr application;
+ if(iter != mRegisteredHealthAppMap.end()) {
+ LoggerE("registered Health Application is found");
+ application = iter->second;
+ }
+ else {
+ LoggerD("Already unregistered");
+ if(callback)
+ callback->invokeCallback("success");
+ return;
+ }
+
+ int ret = bt_hdp_unregister_sink_app(appID.c_str());
+ switch(ret) {
+ case BT_ERROR_NONE:
+ {
+ mRegisteredHealthAppMap.erase(iter);
+ application->setRegistrationState(false);
+ if(callback)
+ callback->invokeCallback("success");
+ break;
+ }
+ case BT_ERROR_NOT_ENABLED:
+ {
+ if(callback) {
+ callback->invokeCallback("error",
+ JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), ServiceNotAvailableException("Bluetooth device is turned off")));
+ }
+ break;
+ }
+ default:
+ {
+ if(callback) {
+ callback->invokeCallback("error",
+ JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), UnknownException("Unknown error")));
+ }
+ }
+ }
+
+ TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothHealthProfileHandler::connectToSource(JSObjectRef remoteDeviceObj, JSObjectRef appObj, Common::MultiCallbackUserDataPtr callback)
+{
+ LoggerD("Enter");
+
+ TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+ BluetoothDeviceSharedPtr device = JSBluetoothDevice::toBluetoothDevice(remoteDeviceObj);
+ BluetoothHealthApplicationSharedPtr app = JSBluetoothHealthApplication::toBluetoothHealthApplication(appObj);
+ LoggerD("address: " << device->getAddress().c_str());
+ LoggerD("app ID: " << app->getAppID().c_str());
+ int ret = bt_hdp_connect_to_source(device->getAddress().c_str(), app->getAppID().c_str());
+ switch(ret) {
+ case BT_ERROR_NONE:
+ {
+ LoggerD("NONE");
+ HealthConnReqPtr connReq = new HealthConnReq(device, callback);
+ mHealthConnReqMap.insert(std::pair<BluetoothHealthApplicationSharedPtr, HealthConnReqPtr>(app, connReq));
+ break;
+ }
+ case BT_ERROR_NOT_ENABLED:
+ {
+ LoggerD("Not Enabled");
+ ServiceNotAvailableException *error = new ServiceNotAvailableException("Bluetooth device is turned off");
+ BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
+ break;
+ }
+ case BT_ERROR_INVALID_PARAMETER:
+ case BT_ERROR_REMOTE_DEVICE_NOT_BONDED:
+ {
+ LoggerD("invalid value");
+ InvalidValuesException *error = new InvalidValuesException("Invalid value");
+ BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
+ break;
+ }
+ default:
+ {
+ LoggerD("Unknown error");
+ UnknownException *error = new UnknownException("Unknown error");
+ BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
+ }
+ }
+
+ TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+
+} // Bluetooth
+} // DeviceAPI