diff options
Diffstat (limited to 'src/FNetBt_BluetoothHdpSystemAdapter.cpp')
-rwxr-xr-x | src/FNetBt_BluetoothHdpSystemAdapter.cpp | 439 |
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 |