2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
20 #include <JSWebAPIErrorFactory.h>
22 #include <TimeTracer.h>
24 #include "BluetoothHealthProfileHandler.h"
25 #include "BluetoothHealthProfileHandlerCallback.h"
26 #include "JSBluetoothHealthApplication.h"
27 #include "JSBluetoothDevice.h"
28 #include "JSBluetoothHealthChannel.h"
29 #include "BluetoothHealthChannel.h"
31 using namespace DeviceAPI::Common;
36 void BluetoothHealthProfileHandler::onConnected(int result, const char *remote_address, const char *app_id,
37 bt_hdp_channel_type_e type, unsigned int channel, void *userData)
40 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
42 HealthProfileHandlerPtr object = static_cast<HealthProfileHandlerPtr>(userData);
44 LoggerW("userData is NULL");
48 if(result != BT_ERROR_NONE) {
49 LoggerD("Not BT_ERROR_NONE");
52 LoggerD("Connected app: " << app_id);
53 LoggerD("Connected channel: " << channel);
55 std::string appID(app_id);
56 RegisteredHealthAppMapT::iterator iter = object->mRegisteredHealthAppMap.find(appID);
57 if(iter == object->mRegisteredHealthAppMap.end()) {
58 LoggerW("This app is not registered");
61 BluetoothHealthApplicationSharedPtr application = iter->second;
63 bool isChannelInserted = false;
64 BluetoothHealthChannelPtr healthChannel = NULL;
66 // call BluetoothHealthApplication.onconnect
67 if(result == BT_ERROR_NONE) {
68 Common::MultiCallbackUserDataPtr callback = application->getOnConnect();
70 bt_device_info_s *deviceInfo = NULL;
71 if(bt_adapter_get_bonded_device_info(remote_address, &deviceInfo) == BT_ERROR_NONE &&
73 BluetoothDeviceSharedPtr device(new BluetoothDevice(deviceInfo));
74 bt_adapter_free_device_info(deviceInfo);
76 LoggerD("invoke BluetoothHealthApplication.onconnect");
77 healthChannel = new BluetoothHealthChannel(channel, device, type, application);
78 object->mConnectedSocketMap.insert(std::pair<unsigned int, BluetoothHealthChannelPtr>(channel, healthChannel));
79 isChannelInserted = true;
80 callback->invokeCallback("onconnect", JSBluetoothHealthChannel::createJSObject(callback->getContext(), healthChannel));
83 LoggerE("Can't call BluetoothHealthApplication.onconnect because failed to get device info");
87 LoggerD("BluetoothHealthApplication.onconnect is not set");
91 // in case of connectToSource()
92 HealthConnReqMapT::iterator i = object->mHealthConnReqMap.find(application);
93 if(i != object->mHealthConnReqMap.end()) {
94 LoggerD("Requested connection");
95 Common::MultiCallbackUserDataPtr callback = i->second->mUserData;
97 if(result == BT_ERROR_NONE) {
98 if(isChannelInserted == false) {
99 healthChannel = new BluetoothHealthChannel(channel, i->second->mRemoteDevice, type, application);
100 object->mConnectedSocketMap.insert(std::pair<unsigned int, BluetoothHealthChannelPtr>(channel, healthChannel));
102 callback->invokeCallback("success", JSBluetoothHealthChannel::createJSObject(callback->getContext(), healthChannel));
105 LoggerE("Failed to establish a connection with health profile");
106 callback->invokeCallback("error",
107 JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), UnknownException("Failed to establish a connection with health profile")));
111 // Update mHealthConnReqMap
112 object->mHealthConnReqMap.erase(i);
115 LoggerD("There is no connection request");
118 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
121 void BluetoothHealthProfileHandler::onDisconnected(int result, const char *remote_address, unsigned int channel, void *userData)
124 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
126 HealthProfileHandlerPtr object = static_cast<HealthProfileHandlerPtr>(userData);
128 LoggerW("userData is NULL");
132 LoggerD("Disconnected channel: " << channel);
133 HealthConnectedSocketMapT::iterator iter = object->mConnectedSocketMap.find(channel);
134 if(iter == object->mConnectedSocketMap.end()) {
135 LoggerW("Unexpected health disconnection event");
139 if(result == BT_ERROR_NONE) {
140 BluetoothHealthChannelPtr healthChannel = iter->second;
141 object->mConnectedSocketMap.erase(iter);
143 healthChannel->setConnectionState(false);
144 MultiCallbackUserDataPtr callback = healthChannel->getListener();
146 callback->invokeCallback("onclose");
149 LoggerW("Failed to disconnect a connection");
152 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
156 void BluetoothHealthProfileHandler::onDataReceivedCB(unsigned int channel, const char *data, unsigned int size, void *userData)
160 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
162 HealthProfileHandlerPtr object = static_cast<HealthProfileHandlerPtr>(userData);
164 LoggerW("userData is NULL");
168 LoggerD("data channel: " << channel);
169 LoggerD("sent data size: " << size);
170 HealthConnectedSocketMapT::iterator iter = object->mConnectedSocketMap.find(channel);
171 if(iter == object->mConnectedSocketMap.end()) {
172 LoggerW("Unexpected health data received event");
176 BluetoothHealthChannelPtr healthChannel = iter->second;
177 MultiCallbackUserDataPtr callback = healthChannel->getListener();
179 std::vector<signed char> receivedData;
180 for(unsigned int i = 0; i < size; i++) {
181 receivedData.push_back(static_cast<signed char>(data[i]));
183 callback->invokeCallback("onmessage", JSUtil::toJSValueRef_(callback->getContext(), receivedData));
186 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
189 BluetoothHealthProfileHandler* BluetoothHealthProfileHandler::getInstance()
191 static BluetoothHealthProfileHandler instance;
195 BluetoothHealthProfileHandler::BluetoothHealthProfileHandler()
197 if(bt_hdp_set_connection_state_changed_cb(onConnected, onDisconnected, this) != BT_ERROR_NONE) {
198 LoggerE("bt_hdp_set_connection_state_changed_cb() failed");
201 if(bt_hdp_set_data_received_cb(onDataReceivedCB, this) != BT_ERROR_NONE) {
202 LoggerE("bt_hdp_set_data_received_cb() failed");
206 BluetoothHealthProfileHandler::~BluetoothHealthProfileHandler()
208 // unset platform callback
209 bt_hdp_unset_connection_state_changed_cb();
210 bt_hdp_unset_data_received_cb();
212 mHealthConnReqMap.clear();
213 mConnectedSocketMap.clear();
214 mRegisteredHealthAppMap.clear();
217 void BluetoothHealthProfileHandler::registerSinkApp(unsigned short dataType, std::string name, Common::MultiCallbackUserDataPtr callback)
219 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
220 BluetoothHealthProfileHandlerCallback::syncToAsyncRegisterCB(callback, dataType, name);
221 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
224 void BluetoothHealthProfileHandler::returnRegisteringSinkAppResult(unsigned short dataType, std::string name, Common::MultiCallbackUserDataPtr callback)
227 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
230 int ret = bt_hdp_register_sink_app(dataType, &app_id);
234 LoggerD("Registered app: " << app_id);
235 std::string appID(app_id);
237 BluetoothHealthApplicationSharedPtr application(new BluetoothHealthApplication(appID, name, dataType));
238 mRegisteredHealthAppMap.insert(std::pair<std::string, BluetoothHealthApplicationSharedPtr>(appID, application));
240 callback->invokeCallback("success", JSBluetoothHealthApplication::createJSObject(callback->getContext(), application));
243 case BT_ERROR_NOT_ENABLED:
246 callback->invokeCallback("error",
247 JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), ServiceNotAvailableException("Bluetooth device is turned off")));
254 callback->invokeCallback("error",
255 JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), UnknownException("Unknown error")));
260 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
264 void BluetoothHealthProfileHandler::unregisterSinkApplication(JSObjectRef appObj, Common::MultiCallbackUserDataPtr callback)
266 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
267 BluetoothHealthProfileHandlerCallback::syncToAsyncUnregisterCB(callback, appObj);
268 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
271 void BluetoothHealthProfileHandler::returnUnregisteringResult(JSObjectRef appObj, Common::MultiCallbackUserDataPtr callback)
273 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
275 BluetoothHealthApplicationSharedPtr app = JSBluetoothHealthApplication::toBluetoothHealthApplication(appObj);
276 int ret = bt_hdp_unregister_sink_app(app->getAppID().c_str());
280 //app->setRegistrationState(false);
281 BluetoothHealthProfileHandlerCallback::syncToAsyncSuccessCB(callback);
284 case BT_ERROR_NOT_ENABLED:
286 ServiceNotAvailableException *error = new ServiceNotAvailableException("Bluetooth device is turned off");
287 BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
292 UnknownException *error = new UnknownException("Unknown error");
293 BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
297 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
301 void BluetoothHealthProfileHandler::unregisterApp(std::string appID, Common::MultiCallbackUserDataPtr callback)
303 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
304 BluetoothHealthProfileHandlerCallback::syncToAsyncUnregisterCB(callback, appID);
305 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
308 void BluetoothHealthProfileHandler::returnUnregisteringAppResult(std::string appID, Common::MultiCallbackUserDataPtr callback)
310 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
312 RegisteredHealthAppMapT::iterator iter = mRegisteredHealthAppMap.find(appID);
313 BluetoothHealthApplicationSharedPtr application;
314 if(iter != mRegisteredHealthAppMap.end()) {
315 LoggerE("registered Health Application is found");
316 application = iter->second;
319 LoggerD("Already unregistered");
321 callback->invokeCallback("success");
325 int ret = bt_hdp_unregister_sink_app(appID.c_str());
329 mRegisteredHealthAppMap.erase(iter);
330 application->setRegistrationState(false);
332 callback->invokeCallback("success");
335 case BT_ERROR_NOT_ENABLED:
338 callback->invokeCallback("error",
339 JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), ServiceNotAvailableException("Bluetooth device is turned off")));
346 callback->invokeCallback("error",
347 JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), UnknownException("Unknown error")));
352 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
355 void BluetoothHealthProfileHandler::connectToSource(JSObjectRef remoteDeviceObj, JSObjectRef appObj, Common::MultiCallbackUserDataPtr callback)
359 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
361 BluetoothDeviceSharedPtr device = JSBluetoothDevice::toBluetoothDevice(remoteDeviceObj);
362 BluetoothHealthApplicationSharedPtr app = JSBluetoothHealthApplication::toBluetoothHealthApplication(appObj);
363 LoggerD("address: " << device->getAddress().c_str());
364 LoggerD("app ID: " << app->getAppID().c_str());
365 int ret = bt_hdp_connect_to_source(device->getAddress().c_str(), app->getAppID().c_str());
370 HealthConnReqPtr connReq = new HealthConnReq(device, callback);
371 mHealthConnReqMap.insert(std::pair<BluetoothHealthApplicationSharedPtr, HealthConnReqPtr>(app, connReq));
374 case BT_ERROR_NOT_ENABLED:
376 LoggerD("Not Enabled");
377 ServiceNotAvailableException *error = new ServiceNotAvailableException("Bluetooth device is turned off");
378 BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
381 case BT_ERROR_INVALID_PARAMETER:
382 case BT_ERROR_REMOTE_DEVICE_NOT_BONDED:
384 LoggerD("invalid value");
385 InvalidValuesException *error = new InvalidValuesException("Invalid value");
386 BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
391 LoggerD("Unknown error");
392 UnknownException *error = new UnknownException("Unknown error");
393 BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
397 TIME_TRACER_ITEM_END(__FUNCTION__, 1);