summaryrefslogtreecommitdiff
path: root/src/FNetBt_BluetoothHdpSystemAdapter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/FNetBt_BluetoothHdpSystemAdapter.cpp')
-rwxr-xr-xsrc/FNetBt_BluetoothHdpSystemAdapter.cpp439
1 files changed, 439 insertions, 0 deletions
diff --git a/src/FNetBt_BluetoothHdpSystemAdapter.cpp b/src/FNetBt_BluetoothHdpSystemAdapter.cpp
new file mode 100755
index 0000000..0ea320a
--- /dev/null
+++ b/src/FNetBt_BluetoothHdpSystemAdapter.cpp
@@ -0,0 +1,439 @@
+//
+// Open Service Platform
+// Copyright (c) 2012-2013 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.
+//
+// @file FNetBt_BluetoothHdpSystemAdapter.cpp
+// @brief This is the implementation file for the _BluetoothHdpSystemAdapter class.
+//
+
+#include <pthread.h>
+#include <FBaseByteBuffer.h>
+#include <FBaseString.h>
+#include <FBaseColHashMapT.h>
+#include <FBaseColIComparerT.h>
+#include <FBaseColIHashCodeProviderT.h>
+#include <FBaseUtilStringUtil.h>
+#include <FNetBtBluetoothDevice.h>
+#include <FNetBtBluetoothTypes.h>
+#include <FBaseSysLog.h>
+#include <FBase_StringConverter.h>
+#include "FNetBt_BluetoothHealthImpl.h"
+#include "FNetBt_BluetoothHdpSystemAdapter.h"
+#include "FNetBt_BluetoothGapSystemAdapter.h"
+#include "FNetBt_BluetoothDeviceImpl.h"
+
+using namespace std;
+using namespace Tizen::Base;
+using namespace Tizen::Base::Collection;
+using namespace Tizen::Base::Utility;
+
+namespace Tizen { namespace Net { namespace Bluetooth
+{
+
+/*
+ * @class _BluetoothAddressComparer
+ * @brief The _BluetoothAddressComparer class provides the comparer about two specified String
+ * which consists of Bluetooth address and service UUID.
+ */
+class _BluetoothAddressComparer
+ : public Tizen::Base::Collection::IComparerT <Tizen::Base::String>
+ , public Tizen::Base::Object
+{
+public:
+ _BluetoothAddressComparer(void) {}
+ virtual ~_BluetoothAddressComparer(void) {}
+
+ virtual result Compare(const Tizen::Base::String& obj1, const Tizen::Base::String& obj2, int& cmp) const
+ {
+ cmp = obj1.CompareTo(obj2);
+ return E_SUCCESS;
+ }
+
+private:
+ _BluetoothAddressComparer(const _BluetoothAddressComparer& value);
+ _BluetoothAddressComparer& operator =(const _BluetoothAddressComparer& value);
+
+}; //_BluetoothAddressComparer
+
+/*
+ * @class _BluetoothAddressHashCodeProviderT
+ * @brief The _BluetoothAddressHashCodeProviderT class provides the hash code of a specified String
+ * which consists of Bluetooth address and service UUID.
+ */
+class _BluetoothAddressHashCodeProvider
+ : public Tizen::Base::Collection::IHashCodeProviderT <Tizen::Base::String>
+{
+public:
+ _BluetoothAddressHashCodeProvider(void) {}
+ virtual ~_BluetoothAddressHashCodeProvider(void) {}
+ virtual int GetHashCode(const Tizen::Base::String& obj) const
+ {
+ return obj.GetHashCode();
+ }
+
+private:
+ _BluetoothAddressHashCodeProvider(const _BluetoothAddressHashCodeProvider& value);
+ _BluetoothAddressHashCodeProvider& operator =(const _BluetoothAddressHashCodeProvider& value);
+
+}; //_BluetoothAddressHashCodeProvider
+
+
+static _BluetoothAddressComparer _btAddressComparer;
+static _BluetoothAddressHashCodeProvider _btAddressHashCodeProvider;
+
+_BluetoothHdpSystemAdapter* _BluetoothHdpSystemAdapter::__pInstance = null;
+
+_BluetoothHdpSystemAdapter::_BluetoothHdpSystemAdapter(void)
+ : __pAppHealthMap(null)
+ , __pChannelHealthMap(null)
+ , __pChannelAddressMap(null)
+{
+}
+
+_BluetoothHdpSystemAdapter::~_BluetoothHdpSystemAdapter(void)
+{
+ // unregister the callback methods from the underlying layer
+ int err = bt_hdp_unset_connection_state_changed_cb();
+ SysLog(NID_NET_BT, "[0x%x] error in unregistering the connection state change callback method", err);
+
+ err = bt_hdp_unset_data_received_cb();
+ SysLog(NID_NET_BT, "[0x%x] error in unregistering the data received state change callback method", err);
+}
+
+void
+_BluetoothHdpSystemAdapter::InitSingleton(void)
+{
+ bool r = false;
+ static _BluetoothHdpSystemAdapter inst;
+
+ r = inst.Construct();
+ SysTryReturnVoidResult(NID_NET_BT, r == true, E_SYSTEM, "[E_SYSTEM] Propagating.");
+
+ __pInstance = &inst;
+}
+
+_BluetoothHdpSystemAdapter*
+_BluetoothHdpSystemAdapter::GetInstance(void)
+{
+ static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
+
+ if (__pInstance == null)
+ {
+ ClearLastResult();
+ pthread_once(&onceBlock, InitSingleton);
+ result r = GetLastResult();
+ if (IsFailed(r))
+ {
+ onceBlock = PTHREAD_ONCE_INIT;
+ }
+ }
+
+ return __pInstance;
+}
+
+bool
+_BluetoothHdpSystemAdapter::Construct(void)
+{
+ int err = BT_ERROR_NONE;
+ result r = E_SUCCESS;
+ unique_ptr<Tizen::Base::Collection::HashMapT< Tizen::Base::String, _BluetoothHealthImpl*> > pAppHealthMap;
+ unique_ptr<Tizen::Base::Collection::HashMapT< int, _BluetoothHealthImpl*> > pChannelHealthMap;
+ unique_ptr<Tizen::Base::Collection::HashMapT< int, Tizen::Base::String> > pChannelAddressMap;
+
+ pAppHealthMap.reset(new (std::nothrow) HashMapT<String, _BluetoothHealthImpl*>);
+ SysTryReturn(NID_NET_BT, pAppHealthMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
+
+ //Constructing the hashmap template with the default capacity(16) and loadFactor(0.75f)
+ r = pAppHealthMap->Construct(16, 0.75f, _btAddressHashCodeProvider, _btAddressComparer);
+ SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
+
+ pChannelHealthMap.reset(new (std::nothrow) HashMapT<int, _BluetoothHealthImpl*>);
+ SysTryReturn(NID_NET_BT, pChannelHealthMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
+
+ r = pChannelHealthMap->Construct();
+ SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
+
+ pChannelAddressMap.reset(new (std::nothrow) HashMapT<int, String>);
+ SysTryReturn(NID_NET_BT, pChannelAddressMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
+
+ r = pChannelAddressMap->Construct();
+ SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
+
+ //register a call back to be invoked when connection state of the Sink device changes
+ err = bt_hdp_set_connection_state_changed_cb(&OnHdpConnected, &OnHdpDisconnected, null);
+ SysTryReturn(NID_NET_BT, err == BT_ERROR_NONE, false, E_SYSTEM, "[E_SYSTEM] Registering the callback method has failed.");
+
+ //register a callback to be invoked when any health data is received by the Sink device
+ err = bt_hdp_set_data_received_cb(&OnHdpDataReceived, null);
+ if (err != BT_ERROR_NONE)
+ {
+ int errUnset = bt_hdp_unset_connection_state_changed_cb();
+ SysLog(NID_NET_BT, "[0x%x] error in unregistering the connection state change callback method", errUnset);
+ }
+ SysTryReturn(NID_NET_BT, err == BT_ERROR_NONE, false, E_SYSTEM, "[E_SYSTEM] Registering the callback method has failed.");
+
+ __pAppHealthMap = move(pAppHealthMap);
+ __pChannelHealthMap = move(pChannelHealthMap);
+ __pChannelAddressMap = move(pChannelAddressMap);
+
+ return true;
+}
+
+result
+_BluetoothHdpSystemAdapter::StartSinkService(int dataType, _BluetoothHealthImpl& implListener, char** pAppId)
+{
+ result r = E_OPERATION_FAILED;
+ int err = BT_ERROR_NONE;
+
+ char* pUuidStr;
+ bool isUsed = false;
+
+ // check HDP service availability
+ pUuidStr = _StringConverter::CopyToCharArrayN(UuId(BT_SVC_UUID_HDP).ToString());
+ err = bt_adapter_is_service_used(pUuidStr, &isUsed);
+ delete[] pUuidStr;
+ SysTryReturnResult(NID_NET_BT, (err == BT_ERROR_NONE) && !isUsed, E_SERVICE_UNAVAILABLE,
+ "[E_SERVICE_UNAVAILABLE] HDP sink service for the specified UUID is not available.");
+
+ err = bt_hdp_register_sink_app(dataType, pAppId);
+ SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_OPERATION_FAILED,
+ "[E_OPERATION_FAILED] Registering Sink role application for specified HDP data type is failed");
+ SysLog(NID_NET_BT, "Registering the HDP Sink role is successful [%d].", err);
+
+ String appIdString(*pAppId);
+
+ // Add the _BluetoothHealthImpl pointer to the event map using appIdString as the key.
+ r = __pAppHealthMap->Add(appIdString, &implListener);
+ SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
+ "[E_OPERATION_FAILED] Failed to add the _BluetoothHealthImpl instance to the map");
+ return E_SUCCESS;
+}
+
+result
+_BluetoothHdpSystemAdapter::StopService(const char* pAppId)
+{
+ int err = BT_ERROR_NONE;
+ result r = E_OPERATION_FAILED;
+
+ String appIdString(pAppId);
+
+ err = bt_hdp_unregister_sink_app(pAppId);
+ SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_OPERATION_FAILED,
+ "[E_OPERATION_FAILED] Failed to unregister the given Sink Role HDP application");
+ SysLog(NID_NET_BT, "The Sink role HDP app is successfully unregistered");
+
+ // remove the specified appIdString from the application event map.
+ r = __pAppHealthMap->Remove(appIdString);
+ SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
+ "[E_OPERATION_FAILED] failed to remove the appId from the event map.");
+
+ return E_SUCCESS;
+}
+
+result
+_BluetoothHdpSystemAdapter::ConnectToSource(const Tizen::Base::ByteBuffer& sourceAddress, const char* pAppId)
+{
+ int err = BT_ERROR_NONE;
+ result r = E_OPERATION_FAILED;
+
+ char* pSourceAddress = null;
+
+ SysTryReturnResult(NID_NET_BT, sourceAddress.GetRemaining() == _BT_ADDRESS_LENGTH, E_OPERATION_FAILED,
+ "The address of the remote Source device is incorrect.");
+
+ pSourceAddress = _StringConverter::CopyToCharArrayN(_BluetoothDeviceImpl::GetAddressString(sourceAddress));
+ SysTryReturnResult(NID_NET_BT, pSourceAddress != null, E_OPERATION_FAILED, "Converting address to char* fails.");
+
+ err = bt_hdp_connect_to_source(pSourceAddress, pAppId);
+ SysLog(NID_NET_BT, "Connecting to the remote source device [%s] %s.", pSourceAddress,
+ err == BT_ERROR_NONE ? "is successful" : "fails");
+ if (err == BT_ERROR_NONE)
+ {
+ r = E_SUCCESS;
+ }
+
+ delete[] pSourceAddress;
+ return r;
+}
+
+result
+_BluetoothHdpSystemAdapter::Disconnect(int channelId)
+{
+ int err = BT_ERROR_NONE;
+ result r = E_OPERATION_FAILED;
+
+ String connectedAddress;
+ char* pSourceAddress = null;
+
+ r = __pChannelAddressMap->GetValue(channelId, connectedAddress);
+ SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "The channel ID is invalid.");
+
+ pSourceAddress = _StringConverter::CopyToCharArrayN(connectedAddress);
+ SysTryReturnResult(NID_NET_BT, pSourceAddress != null, E_OPERATION_FAILED, "Address converting fails.");
+
+ err = bt_hdp_disconnect(pSourceAddress, channelId);
+ SysLog(NID_NET_BT, "Disconnecting from the remote source device [%s] with channel id [%d] %s.", pSourceAddress, channelId,
+ err == BT_ERROR_NONE ? "is successful" : "fails");
+ if (err == BT_ERROR_NONE)
+ {
+ r = E_SUCCESS;
+ }
+
+ delete[] pSourceAddress;
+ return r;
+}
+
+result
+_BluetoothHdpSystemAdapter::SendData(int channelId, const Tizen::Base::ByteBuffer& data)
+{
+ int err = BT_ERROR_NONE;
+ result r = E_OPERATION_FAILED;
+
+ const byte* pHealthData = null;
+ int healthDataLength = 0;
+
+ pHealthData = data.GetPointer();
+ pHealthData += data.GetPosition();
+ healthDataLength = data.GetRemaining();
+
+ err = bt_hdp_send_data(channelId, (char*)pHealthData, healthDataLength);
+ SysLog(NID_NET_BT, "Sending data to the remote source with channel id [%d] of length [%d] %s.", channelId, healthDataLength,
+ err == BT_ERROR_NONE ? "is successful" : "fails");
+ if (err == BT_ERROR_NONE)
+ {
+ r = E_SUCCESS;
+ }
+
+ return r;
+}
+
+void
+_BluetoothHdpSystemAdapter::OnHdpConnected(int status, const char* pRemoteAddress, const char* pAppId,
+ bt_hdp_channel_type_e channelType, unsigned int channelId, void* pUserData)
+{
+ result r = E_OPERATION_FAILED;
+
+ BluetoothDevice btDevice;
+ ByteBuffer deviceAddress;
+ String remoteDeviceAddrStr(pRemoteAddress);
+ BluetoothHealthDataChannelType hdpchannelType = BT_HEALTH_DATA_CHANNEL_NONE;
+
+ _BluetoothHealthImpl* pHealthImpl = null;
+ String appIdString(pAppId);
+
+ _BluetoothHdpSystemAdapter* pHdpAdapter = _BluetoothHdpSystemAdapter::GetInstance();
+
+ // retrieve the _BluetoothHealthImpl instance from the __pAppHealthMap by using appIdString as key
+ r = pHdpAdapter->__pAppHealthMap->GetValue(appIdString, pHealthImpl);
+ SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
+ "[E_OPERATION_FAILED] The application Id is unknown.");
+
+ r = deviceAddress.Construct(_BT_ADDRESS_LENGTH);
+ SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
+ "[E_OPERATION_FAILED] Failed to construct the address buffer");
+
+ (void) _BluetoothDeviceImpl::GetAddressByteBuffer(remoteDeviceAddrStr, L":", deviceAddress);
+
+ r = _BluetoothGapSystemAdapter::GetPairedDevice(deviceAddress, btDevice);
+ SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
+ "[E_OPERATION_FAILED] Getting information of the source health device has failed.");
+
+ if (status == BT_ERROR_NONE)
+ {
+ // insert the pHealthImpl into __pChannelHealthMap by using the specified channelId as key
+ r = pHdpAdapter->__pChannelHealthMap->Add(channelId, pHealthImpl);
+ if (r != E_SUCCESS)
+ {
+ SysLogException(NID_NET_BT, E_OPERATION_FAILED, "[%s] Propagating.", GetErrorMessage(r));
+ r = E_OPERATION_FAILED;
+ }
+
+ // insert the pRemoteAddress into __pChannelAddressMap by using the specified channelId as key
+ r = pHdpAdapter->__pChannelAddressMap->Add(channelId, remoteDeviceAddrStr);
+ if (r != E_SUCCESS)
+ {
+ SysLogException(NID_NET_BT, E_OPERATION_FAILED, "[%s] Propagating.", GetErrorMessage(r));
+ r = E_OPERATION_FAILED;
+ }
+ }
+ else
+ {
+ SysLog(NID_NET_BT, "[E_OPERATION_FAILED] Connection request failure is reported by the underlying system.");
+ r = E_OPERATION_FAILED;
+ }
+
+ hdpchannelType = ((channelType == BT_HDP_CHANNEL_TYPE_RELIABLE)?
+ BT_HEALTH_DATA_CHANNEL_RELIABLE : BT_HEALTH_DATA_CHANNEL_STREAMING);
+
+ // Fire the connect event using the _BluetoothHealthImpl handle
+ pHealthImpl->OnBluetoothHealthConnected(channelId, hdpchannelType, &btDevice, r);
+}
+
+void
+_BluetoothHdpSystemAdapter::OnHdpDisconnected(int status, const char* pRemoteAddress, unsigned int channelId, void* pUserData)
+{
+ result r = E_SYSTEM;
+
+ BluetoothDevice btDevice;
+ ByteBuffer deviceAddress;
+ String remoteDeviceAddrStr(pRemoteAddress);
+
+ _BluetoothHealthImpl* pHealthImpl = null;
+
+ _BluetoothHdpSystemAdapter* pHdpAdapter = _BluetoothHdpSystemAdapter::GetInstance();
+
+ // get the pointer of the _BluetoothHealthImpl from __pChannelHealthMap by using the specified channelId as a key
+ r = pHdpAdapter->__pChannelHealthMap->GetValue(channelId, pHealthImpl);
+ SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "[E_OPERATION_FAILED] The channel Id is unknown.");
+
+ if (status == BT_ERROR_NONE)
+ {
+ (void) pHdpAdapter->__pChannelHealthMap->Remove(channelId);
+ pHdpAdapter->__pChannelAddressMap->Remove(channelId);
+ }
+ else
+ {
+ SysLog(NID_NET_BT, "[E_OPERATION_FAILED] Disconnection request failure is reported by the underlying system [%d].", status);
+ r = E_OPERATION_FAILED;
+ }
+
+ // Fire the Disconnect event using the _BluetoothHealthImpl handle
+ pHealthImpl->OnBluetoothHealthDisconnected(channelId, r);
+}
+
+void
+_BluetoothHdpSystemAdapter::OnHdpDataReceived(unsigned int channelId, const char* pData, unsigned int dataSize, void* pUserData)
+{
+ result r = E_SUCCESS;
+ ByteBuffer dataBuffer;
+
+ _BluetoothHealthImpl* pHealthImpl = null;
+
+ _BluetoothHdpSystemAdapter* pHdpAdapter = _BluetoothHdpSystemAdapter::GetInstance();
+
+ // find the appropriate _BluetoothHealthImpl handle with the given channelId
+ r = pHdpAdapter->__pChannelHealthMap->GetValue(channelId, pHealthImpl);
+ SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "[E_OPERATION_FAILED] unknown channelId.");
+
+ dataBuffer.Construct(dataSize);
+ dataBuffer.SetArray((byte*) pData, 0, dataSize);
+ dataBuffer.SetPosition(0);
+
+ // Fire the data received event using the _BluetoothHealthImpl handle
+ pHealthImpl->OnBluetoothHealthDataReceived(channelId, dataBuffer);
+ SysLog(NID_NET_BT, " Received Health data of (%d bytes) through the channel (ID: %d) is received.", dataSize, channelId);
+}
+
+} } } // Tizen::Net::Bluetooth