update the header for Doxygen
[platform/framework/native/bluetooth.git] / src / FNetBt_BluetoothHdpSystemAdapter.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
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
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17 // @file        FNetBt_BluetoothHdpSystemAdapter.cpp
18 // @brief       This is the implementation file for the _BluetoothHdpSystemAdapter class.
19 //
20
21 #include <pthread.h>
22 #include <FBaseByteBuffer.h>
23 #include <FBaseString.h>
24 #include <FBaseColHashMapT.h>
25 #include <FBaseColIComparerT.h>
26 #include <FBaseColIHashCodeProviderT.h>
27 #include <FBaseUtilStringUtil.h>
28 #include <FNetBtBluetoothDevice.h>
29 #include <FNetBtBluetoothTypes.h>
30 #include <FBaseSysLog.h>
31 #include <FBase_StringConverter.h>
32 #include "FNetBt_BluetoothHealthImpl.h"
33 #include "FNetBt_BluetoothHdpSystemAdapter.h"
34 #include "FNetBt_BluetoothGapSystemAdapter.h"
35 #include "FNetBt_BluetoothDeviceImpl.h"
36
37 using namespace std;
38 using namespace Tizen::Base;
39 using namespace Tizen::Base::Collection;
40 using namespace Tizen::Base::Utility;
41
42 namespace Tizen { namespace Net { namespace Bluetooth
43 {
44
45 /*
46  * @class               _BluetoothAddressComparer
47  * @brief               The _BluetoothAddressComparer class provides the comparer about two specified String
48  *              which consists of Bluetooth address and service UUID.
49  */
50 class _BluetoothAddressComparer
51         : public Tizen::Base::Collection::IComparerT <Tizen::Base::String>
52         , public Tizen::Base::Object
53 {
54 public:
55         _BluetoothAddressComparer(void) {}
56         virtual ~_BluetoothAddressComparer(void) {}
57
58         virtual result Compare(const Tizen::Base::String& obj1, const Tizen::Base::String& obj2, int& cmp) const
59         {
60                 cmp = obj1.CompareTo(obj2);
61                 return E_SUCCESS;
62         }
63
64 private:
65         _BluetoothAddressComparer(const _BluetoothAddressComparer& value);
66         _BluetoothAddressComparer& operator =(const _BluetoothAddressComparer& value);
67
68 };      //_BluetoothAddressComparer
69
70 /*
71  * @class               _BluetoothAddressHashCodeProviderT
72  * @brief               The _BluetoothAddressHashCodeProviderT class provides the hash code of a specified String
73  *              which consists of Bluetooth address and service UUID.
74  */
75 class _BluetoothAddressHashCodeProvider
76         : public Tizen::Base::Collection::IHashCodeProviderT <Tizen::Base::String>
77 {
78 public:
79         _BluetoothAddressHashCodeProvider(void) {}
80         virtual ~_BluetoothAddressHashCodeProvider(void) {}
81         virtual int GetHashCode(const Tizen::Base::String& obj) const
82         {
83                 return obj.GetHashCode();
84         }
85
86 private:
87         _BluetoothAddressHashCodeProvider(const _BluetoothAddressHashCodeProvider& value);
88         _BluetoothAddressHashCodeProvider& operator =(const _BluetoothAddressHashCodeProvider& value);
89
90 };      //_BluetoothAddressHashCodeProvider
91
92
93 static _BluetoothAddressComparer _btAddressComparer;
94 static _BluetoothAddressHashCodeProvider _btAddressHashCodeProvider;
95
96 _BluetoothHdpSystemAdapter* _BluetoothHdpSystemAdapter::__pInstance = null;
97
98 _BluetoothHdpSystemAdapter::_BluetoothHdpSystemAdapter(void)
99         : __pAppHealthMap(null)
100         , __pChannelHealthMap(null)
101         , __pChannelAddressMap(null)
102 {
103 }
104
105 _BluetoothHdpSystemAdapter::~_BluetoothHdpSystemAdapter(void)
106 {
107         // unregister the callback methods from the underlying layer
108         int err = bt_hdp_unset_connection_state_changed_cb();
109         SysLog(NID_NET_BT, "[0x%x] error in unregistering the connection state change callback method", err);
110
111         err = bt_hdp_unset_data_received_cb();
112         SysLog(NID_NET_BT, "[0x%x] error in unregistering the data received state change callback method", err);
113 }
114
115 void
116 _BluetoothHdpSystemAdapter::InitSingleton(void)
117 {
118         bool r = false;
119         static _BluetoothHdpSystemAdapter inst;
120
121         r = inst.Construct();
122         SysTryReturnVoidResult(NID_NET_BT, r == true, E_SYSTEM, "[E_SYSTEM] Propagating.");
123
124         __pInstance = &inst;
125 }
126
127 _BluetoothHdpSystemAdapter*
128 _BluetoothHdpSystemAdapter::GetInstance(void)
129 {
130         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
131
132         if (__pInstance == null)
133         {
134                 ClearLastResult();
135                 pthread_once(&onceBlock, InitSingleton);
136                 result r = GetLastResult();
137                 if (IsFailed(r))
138                 {
139                         onceBlock = PTHREAD_ONCE_INIT;
140                 }
141         }
142
143         return __pInstance;
144 }
145
146 bool
147 _BluetoothHdpSystemAdapter::Construct(void)
148 {
149         int err = BT_ERROR_NONE;
150         result r = E_SUCCESS;
151         unique_ptr<Tizen::Base::Collection::HashMapT< Tizen::Base::String, _BluetoothHealthImpl*> > pAppHealthMap;
152         unique_ptr<Tizen::Base::Collection::HashMapT< int, _BluetoothHealthImpl*> > pChannelHealthMap;
153         unique_ptr<Tizen::Base::Collection::HashMapT< int, Tizen::Base::String> > pChannelAddressMap;
154
155         pAppHealthMap.reset(new (std::nothrow) HashMapT<String, _BluetoothHealthImpl*>);
156         SysTryReturn(NID_NET_BT, pAppHealthMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
157
158         //Constructing the hashmap template with the default capacity(16) and loadFactor(0.75f)
159         r = pAppHealthMap->Construct(16, 0.75f, _btAddressHashCodeProvider, _btAddressComparer);
160         SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
161
162         pChannelHealthMap.reset(new (std::nothrow) HashMapT<int, _BluetoothHealthImpl*>);
163         SysTryReturn(NID_NET_BT, pChannelHealthMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
164
165         r = pChannelHealthMap->Construct();
166         SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
167
168         pChannelAddressMap.reset(new (std::nothrow) HashMapT<int, String>);
169         SysTryReturn(NID_NET_BT, pChannelAddressMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
170
171         r = pChannelAddressMap->Construct();
172         SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
173
174         //register a call back to be invoked when connection state of the Sink device changes
175         err = bt_hdp_set_connection_state_changed_cb(&OnHdpConnected, &OnHdpDisconnected, null);
176         SysTryReturn(NID_NET_BT, err == BT_ERROR_NONE, false, E_SYSTEM, "[E_SYSTEM] Registering the callback method has failed.");
177
178         //register a callback to be invoked when any health data is received by the Sink device
179         err = bt_hdp_set_data_received_cb(&OnHdpDataReceived, null);
180         if (err != BT_ERROR_NONE)
181         {
182                 int errUnset = bt_hdp_unset_connection_state_changed_cb();
183                 SysLog(NID_NET_BT, "[0x%x] error in unregistering the connection state change callback method", errUnset);
184         }
185         SysTryReturn(NID_NET_BT, err == BT_ERROR_NONE, false, E_SYSTEM, "[E_SYSTEM] Registering the callback method has failed.");
186
187         __pAppHealthMap = move(pAppHealthMap);
188         __pChannelHealthMap = move(pChannelHealthMap);
189         __pChannelAddressMap = move(pChannelAddressMap);
190
191         return true;
192 }
193
194 result
195 _BluetoothHdpSystemAdapter::StartSinkService(int dataType, _BluetoothHealthImpl& implListener, char** pAppId)
196 {
197         result r = E_OPERATION_FAILED;
198         int err = BT_ERROR_NONE;
199
200         char* pUuidStr;
201         bool isUsed = false;
202
203         // check HDP service availability
204         pUuidStr = _StringConverter::CopyToCharArrayN(UuId(BT_SVC_UUID_HDP).ToString());
205         err = bt_adapter_is_service_used(pUuidStr, &isUsed);
206         delete[] pUuidStr;
207         SysTryReturnResult(NID_NET_BT, (err == BT_ERROR_NONE) && !isUsed, E_SERVICE_UNAVAILABLE,
208                         "[E_SERVICE_UNAVAILABLE] HDP sink service for the specified UUID is not available.");
209
210         err = bt_hdp_register_sink_app(dataType, pAppId);
211         SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_OPERATION_FAILED,
212                         "[E_OPERATION_FAILED] Registering Sink role application for specified HDP data type is failed");
213         SysLog(NID_NET_BT, "Registering the HDP Sink role is successful [%d].", err);
214
215         String appIdString(*pAppId);
216
217         // Add the _BluetoothHealthImpl pointer to the event map using appIdString as the key.
218         r = __pAppHealthMap->Add(appIdString, &implListener);
219         SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
220                         "[E_OPERATION_FAILED] Failed to add the _BluetoothHealthImpl instance to the map");
221         return E_SUCCESS;
222 }
223
224 result
225 _BluetoothHdpSystemAdapter::StopService(const char* pAppId)
226 {
227         int err = BT_ERROR_NONE;
228         result r = E_OPERATION_FAILED;
229
230         String appIdString(pAppId);
231
232         err = bt_hdp_unregister_sink_app(pAppId);
233         SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_OPERATION_FAILED,
234                         "[E_OPERATION_FAILED] Failed to unregister the given Sink Role HDP application");
235         SysLog(NID_NET_BT, "The Sink role HDP app is successfully unregistered");
236
237         // remove the specified appIdString from the application event map.
238         r = __pAppHealthMap->Remove(appIdString);
239         SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
240                         "[E_OPERATION_FAILED] failed to remove the appId from the event map.");
241
242         return E_SUCCESS;
243 }
244
245 result
246 _BluetoothHdpSystemAdapter::ConnectToSource(const Tizen::Base::ByteBuffer& sourceAddress, const char* pAppId)
247 {
248         int err = BT_ERROR_NONE;
249         result r = E_OPERATION_FAILED;
250
251         char* pSourceAddress = null;
252
253         SysTryReturnResult(NID_NET_BT, sourceAddress.GetRemaining() == _BT_ADDRESS_LENGTH, E_OPERATION_FAILED,
254                                                 "The address of the remote Source device is incorrect.");
255
256         pSourceAddress = _StringConverter::CopyToCharArrayN(_BluetoothDeviceImpl::GetAddressString(sourceAddress));
257         SysTryReturnResult(NID_NET_BT, pSourceAddress != null, E_OPERATION_FAILED, "Converting address to char* fails.");
258
259         err = bt_hdp_connect_to_source(pSourceAddress, pAppId);
260         SysLog(NID_NET_BT, "Connecting to the remote source device  [%s] %s.", pSourceAddress,
261                                                 err == BT_ERROR_NONE ? "is successful" : "fails");
262         if (err == BT_ERROR_NONE)
263         {
264                 r = E_SUCCESS;
265         }
266
267         delete[] pSourceAddress;
268         return r;
269 }
270
271 result
272 _BluetoothHdpSystemAdapter::Disconnect(int channelId)
273 {
274         int err = BT_ERROR_NONE;
275         result r = E_OPERATION_FAILED;
276
277         String connectedAddress;
278         char* pSourceAddress = null;
279
280         r = __pChannelAddressMap->GetValue(channelId, connectedAddress);
281         SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "The channel ID is invalid.");
282
283         pSourceAddress = _StringConverter::CopyToCharArrayN(connectedAddress);
284         SysTryReturnResult(NID_NET_BT, pSourceAddress != null, E_OPERATION_FAILED, "Address converting fails.");
285
286         err = bt_hdp_disconnect(pSourceAddress, channelId);
287         SysLog(NID_NET_BT, "Disconnecting from the remote source device [%s] with channel id [%d] %s.", pSourceAddress, channelId,
288                                                 err == BT_ERROR_NONE ? "is successful" : "fails");
289         if (err == BT_ERROR_NONE)
290         {
291                 r = E_SUCCESS;
292         }
293
294         delete[] pSourceAddress;
295         return r;
296 }
297
298 result
299 _BluetoothHdpSystemAdapter::SendData(int channelId, const Tizen::Base::ByteBuffer& data)
300 {
301         int err = BT_ERROR_NONE;
302         result r = E_OPERATION_FAILED;
303
304         const byte* pHealthData = null;
305         int healthDataLength = 0;
306
307         pHealthData = data.GetPointer();
308         pHealthData += data.GetPosition();
309         healthDataLength = data.GetRemaining();
310
311         err = bt_hdp_send_data(channelId, (char*)pHealthData, healthDataLength);
312         SysLog(NID_NET_BT, "Sending data to the remote source with channel id [%d] of length [%d] %s.", channelId, healthDataLength,
313                                                 err == BT_ERROR_NONE ? "is successful" : "fails");
314         if (err == BT_ERROR_NONE)
315         {
316                 r = E_SUCCESS;
317         }
318
319         return r;
320 }
321
322 void
323 _BluetoothHdpSystemAdapter::OnHdpConnected(int status, const char* pRemoteAddress, const char* pAppId,
324                 bt_hdp_channel_type_e channelType, unsigned int channelId, void* pUserData)
325 {
326         result r = E_OPERATION_FAILED;
327
328         BluetoothDevice btDevice;
329         ByteBuffer deviceAddress;
330         String remoteDeviceAddrStr(pRemoteAddress);
331         BluetoothHealthDataChannelType hdpchannelType = BT_HEALTH_DATA_CHANNEL_NONE;
332
333         _BluetoothHealthImpl* pHealthImpl = null;
334         String appIdString(pAppId);
335
336         _BluetoothHdpSystemAdapter* pHdpAdapter = _BluetoothHdpSystemAdapter::GetInstance();
337
338         // retrieve the _BluetoothHealthImpl instance from the __pAppHealthMap by using appIdString as key
339         r = pHdpAdapter->__pAppHealthMap->GetValue(appIdString, pHealthImpl);
340         SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
341                         "[E_OPERATION_FAILED] The application Id is unknown.");
342
343         r = deviceAddress.Construct(_BT_ADDRESS_LENGTH);
344         SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
345                         "[E_OPERATION_FAILED] Failed to construct the address buffer");
346
347         (void) _BluetoothDeviceImpl::GetAddressByteBuffer(remoteDeviceAddrStr, L":", deviceAddress);
348
349         r = _BluetoothGapSystemAdapter::GetPairedDevice(deviceAddress, btDevice);
350         SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
351                         "[E_OPERATION_FAILED] Getting information of the source health device has failed.");
352
353         if (status == BT_ERROR_NONE)
354         {
355                 // insert the pHealthImpl into __pChannelHealthMap by using the specified channelId as key
356                 r = pHdpAdapter->__pChannelHealthMap->Add(channelId, pHealthImpl);
357                 if (r != E_SUCCESS)
358                 {
359                         SysLogException(NID_NET_BT, E_OPERATION_FAILED, "[%s] Propagating.", GetErrorMessage(r));
360                         r = E_OPERATION_FAILED;
361                 }
362
363                 // insert the pRemoteAddress into __pChannelAddressMap by using the specified channelId as key
364                 r = pHdpAdapter->__pChannelAddressMap->Add(channelId, remoteDeviceAddrStr);
365                 if (r != E_SUCCESS)
366                 {
367                         SysLogException(NID_NET_BT, E_OPERATION_FAILED, "[%s] Propagating.", GetErrorMessage(r));
368                         r = E_OPERATION_FAILED;
369                 }
370         }
371         else
372         {
373                 SysLog(NID_NET_BT, "[E_OPERATION_FAILED] Connection request failure is reported by the underlying system.");
374                 r = E_OPERATION_FAILED;
375         }
376
377         hdpchannelType = ((channelType == BT_HDP_CHANNEL_TYPE_RELIABLE)?
378                         BT_HEALTH_DATA_CHANNEL_RELIABLE : BT_HEALTH_DATA_CHANNEL_STREAMING);
379
380         // Fire the connect event using the _BluetoothHealthImpl handle
381         pHealthImpl->OnBluetoothHealthConnected(channelId, hdpchannelType, &btDevice, r);
382 }
383
384 void
385 _BluetoothHdpSystemAdapter::OnHdpDisconnected(int status, const char* pRemoteAddress, unsigned int channelId, void* pUserData)
386 {
387         result r = E_SYSTEM;
388
389         BluetoothDevice btDevice;
390         ByteBuffer deviceAddress;
391         String remoteDeviceAddrStr(pRemoteAddress);
392
393         _BluetoothHealthImpl* pHealthImpl = null;
394
395         _BluetoothHdpSystemAdapter* pHdpAdapter = _BluetoothHdpSystemAdapter::GetInstance();
396
397          // get the pointer of the _BluetoothHealthImpl from __pChannelHealthMap by using the specified channelId as a key
398         r = pHdpAdapter->__pChannelHealthMap->GetValue(channelId, pHealthImpl);
399         SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "[E_OPERATION_FAILED] The channel Id is unknown.");
400
401         if (status == BT_ERROR_NONE)
402         {
403                 (void) pHdpAdapter->__pChannelHealthMap->Remove(channelId);
404                 pHdpAdapter->__pChannelAddressMap->Remove(channelId);
405         }
406         else
407         {
408                 SysLog(NID_NET_BT, "[E_OPERATION_FAILED] Disconnection request failure is reported by the underlying system [%d].", status);
409                 r = E_OPERATION_FAILED;
410         }
411
412         // Fire the Disconnect event using the _BluetoothHealthImpl handle
413         pHealthImpl->OnBluetoothHealthDisconnected(channelId, r);
414 }
415
416 void
417 _BluetoothHdpSystemAdapter::OnHdpDataReceived(unsigned int channelId, const char* pData, unsigned int dataSize, void* pUserData)
418 {
419         result r = E_SUCCESS;
420         ByteBuffer dataBuffer;
421
422         _BluetoothHealthImpl* pHealthImpl = null;
423
424         _BluetoothHdpSystemAdapter* pHdpAdapter = _BluetoothHdpSystemAdapter::GetInstance();
425
426         // find the appropriate _BluetoothHealthImpl handle with the given channelId
427         r = pHdpAdapter->__pChannelHealthMap->GetValue(channelId, pHealthImpl);
428         SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "[E_OPERATION_FAILED] unknown channelId.");
429
430         dataBuffer.Construct(dataSize);
431         dataBuffer.SetArray((byte*) pData, 0, dataSize);
432         dataBuffer.SetPosition(0);
433
434         // Fire the data received event using the _BluetoothHealthImpl handle
435         pHealthImpl->OnBluetoothHealthDataReceived(channelId, dataBuffer);
436         SysLog(NID_NET_BT, " Received Health data of (%d bytes) through the channel (ID: %d) is received.",     dataSize, channelId);
437 }
438
439 } } }  // Tizen::Net::Bluetooth