// // 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 #include #include #include #include #include #include #include #include #include #include #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 , 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 { 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) { } void _BluetoothHdpSystemAdapter::InitSingleton(void) { bool r = false; std::unique_ptr<_BluetoothHdpSystemAdapter> pInst; pInst.reset(new (std::nothrow) _BluetoothHdpSystemAdapter()); r = pInst->Construct(); SysTryReturnVoidResult(NID_NET_BT, r == true, E_SYSTEM, "[E_SYSTEM] Propagating."); __pInstance = pInst.release(); std::atexit(DeinitializeSingleton); } void _BluetoothHdpSystemAdapter::DeinitializeSingleton(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); } _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 > pAppHealthMap; unique_ptr > pChannelHealthMap; unique_ptr > pChannelAddressMap; pAppHealthMap.reset(new (std::nothrow) HashMapT); 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); 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); 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); SysSecureLog(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); SysSecureLog(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); SysSecureLog(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); SysSecureLog(NID_NET_BT, " Received Health data of (%d bytes) through the channel (ID: %d) is received.", dataSize, channelId); } } } } // Tizen::Net::Bluetooth