Adding Retry logic for LUX disconnection issue
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / tizen / caleclient.c
1 /* ****************************************************************
2 *
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
4 *
5 *
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************/
20
21 #include "caleclient.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <arpa/inet.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <pthread.h>
31 #include <gio/gio.h>
32
33 #include "octhread.h"
34 #include "uarraylist.h"
35 #include "caqueueingthread.h"
36 #include "caadapterutils.h"
37 #include "cagattservice.h"
38 #include "oic_string.h"
39 #include "oic_malloc.h"
40
41 /**
42  * Logging tag for module name.
43  */
44 #define TAG "OIC_CA_LE_CLIENT"
45
46 #define RETRY_COUNT 1
47 #define MICROSECS_PER_SEC 1000000
48 #define WAIT_TIME_WRITE_CHARACTERISTIC 10 * MICROSECS_PER_SEC
49
50 //For custom uuid ble server
51 #define CA_GATT_CUSTOM_UUID "4209"
52 #define CA_GATT_CUSTOM_UUID2 "4204"
53 #define CUSTOM_UUID_LEN 4
54 #define MICROSECS_PER_SEC 1000000
55
56 static const int samsung_code = 117;
57 static int g_retrycount = 0;
58 static int retry_flag = 0;
59 uint64_t const TIMEOUT = 30 * MICROSECS_PER_SEC;
60
61 /**
62  * Mutex to call connect only after disconnect during retry
63  */
64 static oc_mutex g_isDisconnectedMutex = NULL;
65
66 /**
67  * Condition for calling connect during connection retry
68  */
69 static oc_cond g_LEDisconnectedCond = NULL;
70
71 /**
72  * Flag to check if scanning is in progress
73  */
74 static bool g_isScanningInProgress = false;
75
76 /**
77  * Mutex to synchronize access to g_isScanningInProgress
78  */
79 static oc_mutex g_isScanningInProgressMutex = NULL;
80
81 /**
82  * Flag to check if connection is in progress
83  */
84 static bool g_isConnectionInProgress = false;
85
86 /**
87  * Mutex to synchronize access to g_isConnectionInProgress
88  */
89 static oc_mutex g_isConnectionInProgressMutex = NULL;
90
91 /**
92  * Flag to check if multicast is already in progress.
93  */
94 static bool g_isMulticastInProgress = false;
95
96 /**
97  * Flag to check if unicast scan is in progress
98  */
99 static bool g_isUnicastScanInProgress = false;
100
101 /**
102  * Mutex to synchronize access to g_isMulticastInProgress
103  * and g_isUnicastScanInProgress
104  */
105 static oc_mutex g_scanMutex = NULL;
106
107 /**
108  * Pending multicast data list to be sent.
109  */
110 static u_arraylist_t *g_multicastDataList = NULL;
111
112 /**
113  * Mutex to synchronize the access to Pending multicast data list.
114  */
115 static oc_mutex g_multicastDataListMutex = NULL;
116
117 /**
118  * Condition to start the timer for scanning.
119  */
120 static oc_cond g_startTimerCond = NULL;
121
122 /**
123  * Condition for scanning Time interval.
124  */
125 static oc_cond g_scanningTimeCond = NULL;
126
127 /**
128  * This contains the list of OIC services a client connect tot.
129  */
130 static LEServerInfoList *g_LEServerList = NULL;
131
132 /**
133  * Mutex to synchronize access to BleServiceList.
134  */
135 static oc_mutex g_LEServerListMutex = NULL;
136
137 /**
138  * Boolean variable to keep the state of the GATT Client.
139  */
140 static bool g_isLEGattClientStarted = false;
141
142 /**
143  * Mutex to synchronize access to the requestResponse callback to be called
144  * when the data needs to be sent from GATTClient.
145  */
146 static oc_mutex g_LEReqRespClientCbMutex = NULL;
147
148 /**
149  * Mutex to synchronize access to the requestResponse callback to be called
150  * when the data needs to be sent from GATTClient.
151  */
152 static oc_mutex g_LEClientConnectMutex = NULL;
153
154 /**
155  * Mutex to synchronize the calls to be done to the platform from GATTClient
156  * interfaces from different threads.
157  */
158 static oc_mutex g_LEClientStateMutex = NULL;
159
160 /**
161  * Mutex to synchronize the task to be pushed to thread pool.
162  */
163 static oc_mutex g_LEClientThreadPoolMutex = NULL;
164
165 /**
166  * Mutex to synchronize the task to write characteristic one packet after another.
167  */
168 static oc_mutex g_threadWriteCharacteristicMutex = NULL;
169
170 /**
171  * Condition for Writing characteristic.
172  */
173 static oc_cond g_threadWriteCharacteristicCond = NULL;
174
175 /**
176  * Mutex to synchronize the task for MTU Changed.
177  */
178 static oc_mutex g_threadMTUChangedMutex = NULL;
179
180 /**
181  * Condition for MTU Changed.
182  */
183 static oc_cond g_threadMTUChangedCond = NULL;
184
185 /**
186  * Flag to check status of write characteristic.
187  */
188 static bool g_isSignalSetFlag = false;
189
190 /**
191  * Maintains the callback to be notified on receival of network packets from other
192  *           BLE devices
193  */
194 static CABLEDataReceivedCallback g_LEClientDataReceivedCallback = NULL;
195
196 /**
197  * callback to update the error to le adapter
198  */
199 static CABLEErrorHandleCallback g_clientErrorCallback;
200
201 /**
202  * gmainLoop to manage the threads to receive the callback from the platfrom.
203  */
204 static GMainLoop *g_eventLoop = NULL;
205
206 /**
207  * Reference to threadpool
208  */
209 static ca_thread_pool_t g_LEClientThreadPool = NULL;
210
211 void CALEGattCharacteristicChangedCb(bt_gatt_h characteristic,
212                                      char *value,
213                                      int valueLen, void *userData)
214 {
215     (void)characteristic;
216
217     OIC_LOG(DEBUG, TAG, "IN");
218     OIC_LOG_V(DEBUG, TAG, "Changed characteristic value length [%d]", valueLen);
219
220     oc_mutex_lock(g_LEReqRespClientCbMutex);
221     if (NULL == g_LEClientDataReceivedCallback)
222     {
223         OIC_LOG(ERROR, TAG, "Request response callback is not set");
224         oc_mutex_unlock(g_LEReqRespClientCbMutex);
225         return;
226     }
227
228     uint32_t sentLength = 0;
229     g_LEClientDataReceivedCallback(userData, (uint8_t *)value, valueLen, &sentLength);
230
231     OIC_LOG_V(DEBUG, TAG, "Recv data Length is %d", sentLength);
232
233     oc_mutex_unlock(g_LEReqRespClientCbMutex);
234
235     OIC_LOG(DEBUG, TAG, "OUT");
236 }
237
238 void CALEGattClientMTUChangedCb(bt_gatt_client_h client_handle, const bt_gatt_client_att_mtu_info_s *mtu_info, void *user_data)
239 {
240     OIC_LOG(DEBUG, TAG, "IN");
241     oc_mutex_lock(g_threadMTUChangedMutex);
242     OIC_LOG(DEBUG, TAG, "MTU changed signal");
243     oc_cond_signal(g_threadMTUChangedCond);
244     oc_mutex_unlock(g_threadMTUChangedMutex);
245     OIC_LOG(DEBUG, TAG, "OUT");
246 }
247
248
249 void CALEGattCharacteristicWriteCb(int result, bt_gatt_h reqHandle, void *userData)
250 {
251     (void)reqHandle;
252     (void)userData;
253
254     OIC_LOG(DEBUG, TAG, "IN ");
255
256     if (BT_ERROR_NONE != result)
257     {
258         CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, "", 0, -1,
259                            false, "writeChar failure");
260
261         OIC_LOG(ERROR, TAG, "Write failed Need Retry ");
262         //Need to Implement retry mechanism
263     }
264     else
265     {
266         oc_mutex_lock(g_threadWriteCharacteristicMutex);
267         OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
268         g_isSignalSetFlag = true;
269         oc_cond_signal(g_threadWriteCharacteristicCond);
270         oc_mutex_unlock(g_threadWriteCharacteristicMutex);
271
272         CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, "", 0, -1,
273                            true, "writeChar success");
274     }
275
276     OIC_LOG(DEBUG, TAG, "OUT ");
277 }
278
279 CAResult_t CALEGattInitiateConnection(const char *remoteAddress)
280 {
281     OIC_LOG(DEBUG, TAG, "IN");
282
283     oc_mutex_lock(g_isConnectionInProgressMutex);
284     if (g_isConnectionInProgress)
285     {
286         oc_mutex_unlock(g_isConnectionInProgressMutex);
287         OIC_LOG(DEBUG, TAG, "Connection already in progress, cannot initiate new connection");
288         return CA_STATUS_FAILED;
289     }
290     g_isConnectionInProgress = true;
291     // Set gatt connect retry count
292     g_retrycount = RETRY_COUNT;
293     oc_mutex_unlock(g_isConnectionInProgressMutex);
294
295     // Pause the scanning
296     CALEGattStopDeviceScanning();
297
298     OIC_LOG_V(DEBUG, TAG,
299               "Trying to do Gatt connection to [%s]", remoteAddress);
300
301     oc_mutex_lock(g_LEClientThreadPoolMutex);
302     if (NULL == g_LEClientThreadPool)
303     {
304         oc_mutex_unlock(g_LEClientThreadPoolMutex);
305         OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
306         return CA_STATUS_FAILED;
307     }
308
309     char *addr = OICStrdup(remoteAddress);
310     if (NULL == addr)
311     {
312         oc_mutex_unlock(g_LEClientThreadPoolMutex);
313         OIC_LOG(ERROR, TAG, "OICStrdup failed");
314         return CA_STATUS_FAILED;
315     }
316
317     CAResult_t res = ca_thread_pool_add_task(g_LEClientThreadPool, CAGattConnectThread, addr, NULL);
318     oc_mutex_unlock(g_LEClientThreadPoolMutex);
319     if (CA_STATUS_OK != res)
320     {
321         OIC_LOG_V(ERROR, TAG,
322                   "ca_thread_pool_add_task failed with ret [%d]", res);
323         OICFree(addr);
324         return CA_STATUS_FAILED;
325     }
326     OIC_LOG(DEBUG, TAG, "OUT");
327     return CA_STATUS_OK;
328 }
329
330 void CALEGattConnectionStateChanged(bool connected, const char *remoteAddress)
331 {
332     OIC_LOG(DEBUG, TAG, "IN ");
333
334     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
335
336     if (!connected)
337     {
338         OIC_LOG_V(DEBUG, TAG, "DisConnected from [%s] ", remoteAddress);
339         if(!retry_flag)
340         {
341             oc_mutex_lock(g_LEServerListMutex);
342             CARemoveLEServerInfoFromList(&g_LEServerList, remoteAddress);
343             oc_mutex_unlock(g_LEServerListMutex);
344         }
345         else
346         {
347             oc_mutex_lock(g_isDisconnectedMutex);
348             oc_cond_signal(g_LEDisconnectedCond);
349             oc_mutex_unlock(g_isDisconnectedMutex);
350         }
351         retry_flag = 0;
352     }
353     else
354     {
355         OIC_LOG_V(DEBUG, TAG, "Connected to [%s] ", remoteAddress);
356
357         oc_mutex_lock(g_isConnectionInProgressMutex);
358         g_isConnectionInProgress = false;
359         oc_mutex_unlock(g_isConnectionInProgressMutex);
360
361         LEServerInfo *serverInfo = NULL;
362         oc_mutex_lock(g_LEServerListMutex);
363         if (CA_STATUS_OK != CAGetLEServerInfo(g_LEServerList, remoteAddress, &serverInfo))
364         {
365             oc_mutex_unlock(g_LEServerListMutex);
366             OIC_LOG_V(ERROR, TAG, "Could not get server info!");
367             return;
368         }
369
370         serverInfo->status = LE_STATUS_CONNECTED;
371         oc_mutex_unlock(g_LEServerListMutex);
372         oc_mutex_lock(g_LEClientThreadPoolMutex);
373         if (NULL == g_LEClientThreadPool)
374         {
375             oc_mutex_unlock(g_LEClientThreadPoolMutex);
376             OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
377             return;
378         }
379
380         char *addr = OICStrdup(remoteAddress);
381         if (NULL == addr)
382         {
383             oc_mutex_unlock(g_LEClientThreadPoolMutex);
384             OIC_LOG(ERROR, TAG, "addr is NULL");
385             return;
386         }
387         CAResult_t ret = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread,
388                                                  addr, NULL);
389         oc_mutex_unlock(g_LEClientThreadPoolMutex);
390         if (CA_STATUS_OK != ret)
391         {
392             OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", ret);
393             OICFree(addr);
394         }
395     }
396     OIC_LOG(DEBUG, TAG, "OUT");
397 }
398
399 static bool CALEIsHaveServiceImpl(bt_adapter_le_device_scan_result_info_s *scanInfo,
400                                   const char *service_uuid,
401                                   bt_adapter_le_packet_type_e pkt_type)
402 {
403     bool ret = false;
404     char **uuids = NULL;
405     int count = 0;
406     int result = 0;
407
408     result = bt_adapter_le_get_scan_result_service_uuids(scanInfo,
409              pkt_type, &uuids, &count);
410     if (result == BT_ERROR_NONE && NULL != uuids)
411     {
412         for (int i = 0; i < count; i++)
413         {
414             if (0 == strcasecmp(uuids[i], service_uuid))
415             {
416                 OIC_LOG_V(DEBUG, TAG, "Service[%s] Found in %s",
417                           uuids[i], scanInfo->remote_address);
418                 ret = true;
419             }
420             OICFree(uuids[i]);
421         }
422         OICFree(uuids);
423     }
424
425     if(ret == false){
426         char *man_data = NULL;
427         int man_data_len;
428         int man_id;
429         result = bt_adapter_le_get_scan_result_manufacturer_data(scanInfo,
430                               pkt_type, &man_id, &man_data, &man_data_len);
431         
432         if (result == BT_ERROR_NONE && NULL != man_data)
433         {
434             char *compare_man_data = OICMalloc((man_data_len*2)+1);
435             int pos =0;
436             for(int i=0;i<man_data_len;i++){
437                 pos += sprintf(compare_man_data+pos, "%.2x", man_data[i]);
438             }
439             compare_man_data[(man_data_len*2)+1]='\0';
440             OIC_LOG_V(DEBUG, TAG, "Manufacture Id %d Manufacture Data[%s]" ,man_id,compare_man_data);
441             if (man_id == samsung_code && 0 == strncasecmp(compare_man_data, service_uuid, CUSTOM_UUID_LEN))
442             {
443                 OIC_LOG_V(DEBUG, TAG, "Manufacture Data[%s] Found in %s",
444                                        compare_man_data, scanInfo->remote_address);
445                 ret = true;
446             }
447             OICFree(compare_man_data);
448             OICFree(man_data);
449         }
450     }
451     return ret;
452 }
453
454 static bool CALEIsHaveService(bt_adapter_le_device_scan_result_info_s *scanInfo,
455                               const char *service_uuid)
456 {
457     return
458         // For arduino servers, scan response will give the UUIDs advertised.
459         CALEIsHaveServiceImpl(scanInfo, service_uuid,
460                               BT_ADAPTER_LE_PACKET_SCAN_RESPONSE) ||
461         // For android/tizen servers, advertising packet will give the UUIDs.
462         CALEIsHaveServiceImpl(scanInfo, service_uuid,
463                               BT_ADAPTER_LE_PACKET_ADVERTISING);
464 }
465
466 void CALEAdapterScanResultCb(int result, bt_adapter_le_device_scan_result_info_s *scanInfo,
467                              void *userData)
468 {
469     (void)userData;
470
471     OIC_LOG(DEBUG, TAG, "IN");
472
473     VERIFY_NON_NULL_VOID(scanInfo, TAG, "scanInfo");
474     VERIFY_NON_NULL_VOID(scanInfo->remote_address, TAG, "scanInfo->remote_address");
475
476     OIC_LOG_V(DEBUG, TAG, "Remote Address [%s]", scanInfo->remote_address);
477     OIC_LOG_V(DEBUG, TAG, "Scan Result [%d]", result);
478     OIC_LOG_V(DEBUG, TAG,
479               " Adv data len [%d] Scan data len[%d]RSSI [%d] Addr_type [%d] ",
480               scanInfo->adv_data_len, scanInfo->scan_data_len, scanInfo->rssi,
481               scanInfo->address_type);
482
483     // Check if scanning was stopped (since this callback is
484     // being triggered even after stopping the scan)
485     oc_mutex_lock(g_isScanningInProgressMutex);
486     if (!g_isScanningInProgress)
487     {
488         oc_mutex_unlock(g_isScanningInProgressMutex);
489         OIC_LOG(DEBUG, TAG, "Scanning not in progress, so ignoring callback");
490         return;
491     }
492     oc_mutex_unlock(g_isScanningInProgressMutex);
493
494     if (CALEIsHaveService(scanInfo, CA_GATT_SERVICE_UUID) ||
495         CALEIsHaveService(scanInfo, CA_GATT_CUSTOM_UUID)||
496         CALEIsHaveService(scanInfo, CA_GATT_CUSTOM_UUID2))
497     {
498         OIC_LOG_V(DEBUG, TAG, "Device [%s] supports OIC or custom service", scanInfo->remote_address);
499
500         LEServerInfo *serverInfo = NULL;
501         oc_mutex_lock(g_LEServerListMutex);
502         CAResult_t ret = CAGetLEServerInfo(g_LEServerList, scanInfo->remote_address, &serverInfo);
503         if (CA_STATUS_OK != ret)
504         {
505             OIC_LOG_V(DEBUG, TAG,
506                       "Newly discovered device with address [%s] ", scanInfo->remote_address);
507
508             char *addr = OICStrdup(scanInfo->remote_address);
509             if (NULL == addr)
510             {
511                 oc_mutex_unlock(g_LEServerListMutex);
512                 OIC_LOG(ERROR, TAG, "Device address is NULL");
513                 return;
514             }
515             serverInfo = (LEServerInfo *)OICCalloc(1, sizeof(LEServerInfo));
516             if (NULL == serverInfo)
517             {
518                 oc_mutex_unlock(g_LEServerListMutex);
519                 OIC_LOG(ERROR, TAG, "Calloc failed");
520                 OICFree(addr);
521                 return;
522             }
523             serverInfo->remoteAddress = addr;
524             serverInfo->status = LE_STATUS_DISCOVERED;
525
526             if (CA_STATUS_OK != CAAddLEServerInfoToList(&g_LEServerList, serverInfo))
527             {
528                 oc_mutex_unlock(g_LEServerListMutex);
529                 OIC_LOG_V(ERROR, TAG, "Could not add [%s] to server list", scanInfo->remote_address);
530                 CAFreeLEServerInfo(serverInfo);
531                 return;
532             }
533         }else {
534             OIC_LOG_V(DEBUG, TAG,
535                       "Device Present with address [%s] ", scanInfo->remote_address);
536
537             if(serverInfo->status == LE_STATUS_UNICAST_PENDING){
538                 bt_gatt_client_h clientHandle = NULL;
539                 int32_t ret = bt_gatt_client_create(serverInfo->remoteAddress, &clientHandle);
540                 if (BT_ERROR_NONE != ret || NULL == clientHandle)
541                 {
542                     OIC_LOG_V(ERROR, TAG,
543                               "bt_gatt_client_create Failed with ret value [%s] ", CALEGetErrorMsg(ret));
544                     CALEGattDisConnect(serverInfo->remoteAddress);
545                     oc_mutex_unlock(g_LEServerListMutex);
546                     return ;
547                 }
548                 serverInfo->clientHandle = clientHandle;
549
550                 serverInfo->status = LE_STATUS_CONNECTION_INITIATED;
551                 if (CA_STATUS_OK != CALEGattInitiateConnection(serverInfo->remoteAddress))
552                 {
553                     OIC_LOG_V(ERROR, TAG, "Could not initiate connection to [%s]", serverInfo->remoteAddress);
554                     serverInfo->status = LE_STATUS_DISCOVERED;
555                     CADestroyLEDataList(&serverInfo->pendingDataList);
556                     oc_mutex_unlock(g_LEServerListMutex);
557                     return ;
558                 }
559             }
560         }
561         oc_mutex_unlock(g_LEServerListMutex);
562     }
563
564
565     OIC_LOG(DEBUG, TAG, "OUT");
566 }
567
568 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
569 {
570     OIC_LOG(DEBUG, TAG, "IN");
571
572     oc_mutex_lock(g_LEClientThreadPoolMutex);
573     g_LEClientThreadPool = handle;
574     oc_mutex_unlock(g_LEClientThreadPoolMutex);
575
576     OIC_LOG(DEBUG, TAG, "OUT");
577 }
578
579 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
580 {
581     OIC_LOG(DEBUG, TAG, "IN");
582
583     oc_mutex_lock(g_LEReqRespClientCbMutex);
584
585     g_LEClientDataReceivedCallback = callback;
586
587     oc_mutex_unlock(g_LEReqRespClientCbMutex);
588
589     OIC_LOG(DEBUG, TAG, "OUT");
590 }
591
592 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
593 {
594     g_clientErrorCallback = callback;
595 }
596
597 CAResult_t CAStartLEGattClient()
598 {
599     OIC_LOG(DEBUG, TAG, "IN");
600
601     oc_mutex_lock(g_LEClientStateMutex);
602     if (true  == g_isLEGattClientStarted)
603     {
604         OIC_LOG(ERROR, TAG, "Gatt Client is already running!!");
605         oc_mutex_unlock(g_LEClientStateMutex);
606         return CA_STATUS_FAILED;
607     }
608
609     CAResult_t  result = CALEGattSetCallbacks();
610     if (CA_STATUS_OK != result)
611     {
612         OIC_LOG(ERROR, TAG, "CABleGattSetCallbacks Failed");
613         oc_mutex_unlock(g_LEClientStateMutex);
614         CATerminateLEGattClient();
615         return CA_STATUS_FAILED;
616     }
617
618     g_isLEGattClientStarted = true;
619     oc_mutex_unlock(g_LEClientStateMutex);
620
621     oc_mutex_lock(g_LEClientThreadPoolMutex);
622     if (NULL == g_LEClientThreadPool)
623     {
624         OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL");
625         CATerminateGattClientMutexVariables();
626         oc_mutex_unlock(g_LEClientThreadPoolMutex);
627         return CA_STATUS_FAILED;
628     }
629
630     result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartTimerThread,
631                                      NULL, NULL);
632     if (CA_STATUS_OK != result)
633     {
634         OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed");
635         CATerminateGattClientMutexVariables();
636         oc_mutex_unlock(g_LEClientThreadPoolMutex);
637         return CA_STATUS_FAILED;
638     }
639     oc_mutex_unlock(g_LEClientThreadPoolMutex);
640
641     OIC_LOG(DEBUG, TAG, "OUT");
642     return CA_STATUS_OK;
643 }
644
645 void CAStartTimerThread(void *data)
646 {
647     (void)data;
648
649     OIC_LOG(DEBUG, TAG, "IN");
650     while (g_isLEGattClientStarted)
651     {
652         oc_mutex_lock(g_scanMutex);
653         if (!g_isMulticastInProgress && !g_isUnicastScanInProgress)
654         {
655             OIC_LOG(DEBUG, TAG, "waiting....");
656             oc_cond_wait(g_startTimerCond, g_scanMutex);
657             OIC_LOG(DEBUG, TAG, "Wake up");
658         }
659
660         // Timed conditional wait for stopping the scan.
661         OCWaitResult_t ret = oc_cond_wait_for(g_scanningTimeCond, g_scanMutex,
662                                               TIMEOUT);
663         if (OC_WAIT_TIMEDOUT == ret)
664         {
665             OIC_LOG(DEBUG, TAG, "Scan is timed Out");
666             // Call stop scan.
667             CALEGattStopDeviceScanning();
668
669             if (g_isMulticastInProgress)
670             {
671                 oc_mutex_lock(g_multicastDataListMutex);
672                 // Clear the data list and device list.
673                 u_arraylist_destroy(g_multicastDataList);
674                 g_multicastDataList = NULL;
675                 oc_mutex_unlock(g_multicastDataListMutex);
676                 g_isMulticastInProgress = false;
677             }
678             g_isUnicastScanInProgress = false;
679         }
680         oc_mutex_unlock(g_scanMutex);
681     }
682
683     OIC_LOG(DEBUG, TAG, "OUT");
684 }
685
686 void CAStopLEGattClient()
687 {
688     OIC_LOG(DEBUG,  TAG, "IN");
689
690     oc_mutex_lock(g_LEClientStateMutex);
691
692     if (false == g_isLEGattClientStarted)
693     {
694         OIC_LOG(ERROR, TAG, "Gatt Client is not running to stop");
695         oc_mutex_unlock(g_LEClientStateMutex);
696         return;
697     }
698
699     CALEGattUnSetCallbacks();
700
701     CALEGattStopDeviceScanning();
702
703     g_isLEGattClientStarted = false;
704
705     // Signal the conditions waiting in Start timer.
706     oc_cond_signal(g_startTimerCond);
707     oc_cond_signal(g_scanningTimeCond);
708
709     // Destroy the multicast data list and device list if not empty.
710     if (NULL != g_multicastDataList)
711     {
712         oc_mutex_lock(g_multicastDataListMutex);
713         u_arraylist_destroy(g_multicastDataList);
714         g_multicastDataList = NULL;
715         oc_mutex_unlock(g_multicastDataListMutex);
716     }
717
718     oc_mutex_lock(g_LEServerListMutex);
719     CAFreeLEServerList(g_LEServerList);
720     g_LEServerList = NULL;
721     oc_mutex_unlock(g_LEServerListMutex);
722
723     oc_mutex_lock(g_threadWriteCharacteristicMutex);
724     oc_cond_signal(g_threadWriteCharacteristicCond);
725     oc_mutex_unlock(g_threadWriteCharacteristicMutex);
726
727     GMainContext  *context_event_loop = NULL;
728     // Required for waking up the thread which is running in gmain loop
729     if (NULL != g_eventLoop)
730     {
731         context_event_loop = g_main_loop_get_context(g_eventLoop);
732     }
733     if (context_event_loop)
734     {
735         OIC_LOG_V(DEBUG,  TAG, "g_eventLoop context %p", (void *)context_event_loop);
736         g_main_context_wakeup(context_event_loop);
737
738         // Kill g main loops and kill threads.
739         g_main_loop_quit(g_eventLoop);
740     }
741     else
742     {
743         OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL");
744     }
745
746     oc_mutex_unlock(g_LEClientStateMutex);
747
748     OIC_LOG(DEBUG,  TAG, "OUT");
749 }
750
751 CAResult_t CAInitializeLEGattClient()
752 {
753     OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
754     CAResult_t res = CAInitGattClientMutexVariables();
755     if (CA_STATUS_OK != res)
756     {
757         OIC_LOG(ERROR, TAG, "CAInitGattClientMutexVariables failed!");
758         CATerminateGattClientMutexVariables();
759         return CA_STATUS_FAILED;
760     }
761     return res;
762 }
763
764 void CATerminateLEGattClient()
765 {
766     OIC_LOG(DEBUG,  TAG, "IN");
767
768     CATerminateGattClientMutexVariables();
769
770     OIC_LOG(DEBUG,  TAG, "OUT");
771 }
772
773 CAResult_t CAInitGattClientMutexVariables()
774 {
775     OIC_LOG(DEBUG,  TAG, "IN");
776     if (NULL == g_LEClientStateMutex)
777     {
778         g_LEClientStateMutex = oc_mutex_new();
779         if (NULL == g_LEClientStateMutex)
780         {
781             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
782             return CA_STATUS_FAILED;
783         }
784     }
785
786     if (NULL == g_LEServerListMutex)
787     {
788         g_LEServerListMutex = oc_mutex_new();
789         if (NULL == g_LEServerListMutex)
790         {
791             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
792             return CA_STATUS_FAILED;
793         }
794     }
795
796     if (NULL == g_LEReqRespClientCbMutex)
797     {
798         g_LEReqRespClientCbMutex = oc_mutex_new();
799         if (NULL == g_LEReqRespClientCbMutex)
800         {
801             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
802             return CA_STATUS_FAILED;
803         }
804     }
805
806     if (NULL == g_LEClientThreadPoolMutex)
807     {
808         g_LEClientThreadPoolMutex = oc_mutex_new();
809         if (NULL == g_LEClientThreadPoolMutex)
810         {
811             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
812             return CA_STATUS_FAILED;
813         }
814     }
815
816     if (NULL == g_LEClientConnectMutex)
817     {
818         g_LEClientConnectMutex = oc_mutex_new();
819         if (NULL == g_LEClientConnectMutex)
820         {
821             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
822             return CA_STATUS_FAILED;
823         }
824     }
825
826     if (NULL == g_isScanningInProgressMutex)
827     {
828         g_isScanningInProgressMutex = oc_mutex_new();
829         if (NULL == g_isScanningInProgressMutex)
830         {
831             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
832             return CA_STATUS_FAILED;
833         }
834     }
835
836     if (NULL == g_isConnectionInProgressMutex)
837     {
838         g_isConnectionInProgressMutex = oc_mutex_new();
839         if (NULL == g_isConnectionInProgressMutex)
840         {
841             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
842             return CA_STATUS_FAILED;
843         }
844     }
845
846     if (NULL == g_multicastDataListMutex)
847     {
848         g_multicastDataListMutex = oc_mutex_new();
849         if (NULL == g_multicastDataListMutex)
850         {
851             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
852             return CA_STATUS_FAILED;
853         }
854     }
855
856     if (NULL == g_scanMutex)
857     {
858         g_scanMutex = oc_mutex_new();
859         if (NULL == g_scanMutex)
860         {
861             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
862             return CA_STATUS_FAILED;
863         }
864     }
865
866     if (NULL == g_threadWriteCharacteristicMutex)
867     {
868         g_threadWriteCharacteristicMutex = oc_mutex_new();
869         if (NULL == g_threadWriteCharacteristicMutex)
870         {
871             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
872             return CA_STATUS_FAILED;
873         }
874     }
875
876     if (NULL == g_threadMTUChangedMutex)
877     {
878         g_threadMTUChangedMutex = oc_mutex_new();
879         if (NULL == g_threadMTUChangedMutex)
880         {
881             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
882             return CA_STATUS_FAILED;
883         }
884     }
885
886     if (NULL == g_isDisconnectedMutex)
887     {
888         g_isDisconnectedMutex = oc_mutex_new();
889         if (NULL == g_isDisconnectedMutex)
890         {
891             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
892             return CA_STATUS_FAILED;
893         }
894     }
895
896     if (NULL == g_LEDisconnectedCond)
897     {
898         g_LEDisconnectedCond = oc_cond_new();
899         if (NULL == g_LEDisconnectedCond)
900         {
901             OIC_LOG(ERROR, TAG, "oc_cond_new failed");
902             return CA_STATUS_FAILED;
903         }
904     }
905
906     if (NULL == g_startTimerCond)
907     {
908         g_startTimerCond = oc_cond_new();
909         if (NULL == g_startTimerCond)
910         {
911             OIC_LOG(ERROR, TAG, "oc_cond_new failed");
912             return CA_STATUS_FAILED;
913         }
914     }
915
916     if (NULL == g_scanningTimeCond)
917     {
918         g_scanningTimeCond = oc_cond_new();
919         if (NULL == g_scanningTimeCond)
920         {
921             OIC_LOG(ERROR, TAG, "oc_cond_new failed");
922             return CA_STATUS_FAILED;
923         }
924     }
925
926     if (NULL == g_threadWriteCharacteristicCond)
927     {
928         g_threadWriteCharacteristicCond = oc_cond_new();
929         if (NULL == g_threadWriteCharacteristicCond)
930         {
931             OIC_LOG(ERROR, TAG, "oc_cond_new failed");
932             return CA_STATUS_FAILED;
933         }
934     }
935
936     if (NULL == g_threadMTUChangedCond)
937     {
938         g_threadMTUChangedCond = oc_cond_new();
939         if (NULL == g_threadMTUChangedCond)
940         {
941             OIC_LOG(ERROR, TAG, "oc_cond_new failed");
942             return CA_STATUS_FAILED;
943         }
944     }
945
946
947     OIC_LOG(DEBUG,  TAG, "OUT");
948     return CA_STATUS_OK;
949 }
950
951 void CATerminateGattClientMutexVariables()
952 {
953     OIC_LOG(DEBUG,  TAG, "IN");
954
955     oc_mutex_free(g_LEClientStateMutex);
956     g_LEClientStateMutex = NULL;
957
958     oc_mutex_free(g_LEServerListMutex);
959     g_LEServerListMutex = NULL;
960
961     oc_mutex_free(g_LEReqRespClientCbMutex);
962     g_LEReqRespClientCbMutex = NULL;
963
964     oc_mutex_free(g_LEClientConnectMutex);
965     g_LEClientConnectMutex = NULL;
966
967     oc_mutex_free(g_LEClientThreadPoolMutex);
968     g_LEClientThreadPoolMutex = NULL;
969
970     oc_mutex_free(g_isScanningInProgressMutex);
971     g_isScanningInProgressMutex = NULL;
972
973     oc_mutex_free(g_isConnectionInProgressMutex);
974     g_isConnectionInProgressMutex = NULL;
975
976     oc_mutex_free(g_multicastDataListMutex);
977     g_multicastDataListMutex = NULL;
978
979     oc_mutex_free(g_scanMutex);
980     g_scanMutex = NULL;
981
982     oc_mutex_free(g_threadWriteCharacteristicMutex);
983     g_threadWriteCharacteristicMutex = NULL;
984
985     oc_mutex_free(g_threadMTUChangedMutex);
986     g_threadMTUChangedMutex = NULL;
987
988     oc_mutex_free(g_isDisconnectedMutex);
989     g_isDisconnectedMutex = NULL;
990
991     oc_cond_free(g_LEDisconnectedCond);
992     g_LEDisconnectedCond = NULL;
993
994     oc_cond_free(g_startTimerCond);
995     g_startTimerCond = NULL;
996
997     oc_cond_free(g_scanningTimeCond);
998     g_scanningTimeCond = NULL;
999
1000     oc_cond_free(g_threadWriteCharacteristicCond);
1001     g_threadWriteCharacteristicCond = NULL;
1002     g_isSignalSetFlag = false;
1003
1004     oc_cond_free(g_threadMTUChangedCond);
1005     g_threadMTUChangedCond = NULL;
1006
1007     OIC_LOG(DEBUG,  TAG, "OUT");
1008 }
1009
1010 CAResult_t CALEGattSetCallbacks()
1011 {
1012     OIC_LOG(DEBUG, TAG, "IN");
1013
1014     OIC_LOG(DEBUG, TAG, "OUT");
1015     return CA_STATUS_OK;
1016 }
1017
1018 void CALEGattUnSetCallbacks()
1019 {
1020     OIC_LOG(DEBUG, TAG, "IN");
1021
1022     bt_gatt_unset_connection_state_changed_cb();
1023
1024     oc_mutex_lock(g_LEServerListMutex);
1025     LEServerInfoList *curNode = g_LEServerList;
1026     while (curNode)
1027     {
1028         LEServerInfo *serverInfo = curNode->serverInfo;
1029         if (serverInfo->status >= LE_STATUS_SERVICES_DISCOVERED)
1030         {
1031             bt_gatt_client_unset_characteristic_value_changed_cb(serverInfo->readChar);
1032         }
1033         curNode = curNode->next;
1034     }
1035     oc_mutex_unlock(g_LEServerListMutex);
1036
1037     OIC_LOG(DEBUG, TAG, "OUT");
1038 }
1039
1040 CAResult_t CALEGattStartDeviceScanning()
1041 {
1042     OIC_LOG(DEBUG, TAG, "IN");
1043
1044     oc_mutex_lock(g_isScanningInProgressMutex);
1045     if (!g_isScanningInProgress)
1046     {
1047         int ret = bt_adapter_le_start_scan(CALEAdapterScanResultCb, NULL);
1048         if (BT_ERROR_NONE != ret)
1049         {
1050             oc_mutex_unlock(g_isScanningInProgressMutex);
1051             OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_scan failed[%s]",
1052                       CALEGetErrorMsg(ret));
1053             return CA_STATUS_FAILED;
1054         }
1055         g_isScanningInProgress = true;
1056     }
1057     else
1058     {
1059         OIC_LOG(DEBUG, TAG, "Ignore, scanning already in progress");
1060     }
1061     oc_mutex_unlock(g_isScanningInProgressMutex);
1062
1063     OIC_LOG(DEBUG, TAG, "OUT");
1064     return CA_STATUS_OK;
1065 }
1066
1067 void CALEGattStopDeviceScanning()
1068 {
1069     OIC_LOG(DEBUG, TAG, "IN");
1070
1071     oc_mutex_lock(g_isScanningInProgressMutex);
1072     if (g_isScanningInProgress)
1073     {
1074         int ret = bt_adapter_le_stop_scan();
1075         if (BT_ERROR_NONE != ret)
1076         {
1077             oc_mutex_unlock(g_isScanningInProgressMutex);
1078             OIC_LOG_V(ERROR, TAG, "bt_adapter_le_stop_scan failed[%s]",
1079                       CALEGetErrorMsg(ret));
1080             return;
1081         }
1082         g_isScanningInProgress = false;
1083         g_isUnicastScanInProgress= false;
1084     }
1085     else
1086     {
1087         OIC_LOG(DEBUG, TAG, "Ignore, scanning not in progress");
1088     }
1089     oc_mutex_unlock(g_isScanningInProgressMutex);
1090
1091     OIC_LOG(DEBUG, TAG, "OUT");
1092 }
1093
1094 void CAGattConnectThread (void *remoteAddress)
1095 {
1096     OIC_LOG(DEBUG, TAG, "IN ");
1097
1098     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
1099
1100     char *address  = (char *)remoteAddress;
1101
1102     OIC_LOG_V(DEBUG, TAG, "remote address is [%s]", address);
1103
1104     CAResult_t result = CALEGattConnect(address);
1105
1106     if (CA_STATUS_OK != result)
1107     {
1108         OIC_LOG_V(ERROR, TAG, "bt_gatt_connect failed for [%s]", address);
1109     }
1110
1111     OICFree(address);
1112
1113     OIC_LOG(DEBUG, TAG, "OUT");
1114 }
1115
1116 CAResult_t CALEGattConnect(const char *remoteAddress)
1117 {
1118     OIC_LOG(DEBUG, TAG, "IN");
1119
1120     VERIFY_NON_NULL_RET(remoteAddress, TAG,
1121                         "remote address is NULL", CA_STATUS_FAILED);
1122
1123     oc_mutex_lock(g_LEClientConnectMutex);
1124     CAResult_t result = CA_STATUS_OK;
1125
1126     int ret = bt_gatt_connect(remoteAddress, false);
1127     if (BT_ERROR_NONE != ret)
1128     {
1129         OIC_LOG_V(ERROR, TAG, "bt_gatt_connect Failed with ret value [%s] ",
1130                   CALEGetErrorMsg(ret));
1131         oc_mutex_unlock(g_LEClientConnectMutex);
1132         return CA_STATUS_FAILED;
1133     }
1134
1135     oc_mutex_unlock(g_LEClientConnectMutex);
1136
1137     OIC_LOG(DEBUG, TAG, "OUT");
1138     return result;
1139 }
1140
1141 CAResult_t CALEGattDisConnect(const char *remoteAddress)
1142 {
1143     OIC_LOG(DEBUG, TAG, "IN");
1144
1145     VERIFY_NON_NULL_RET(remoteAddress, TAG,
1146                         "remote address is NULL", CA_STATUS_FAILED);
1147
1148     int ret = bt_gatt_disconnect(remoteAddress);
1149
1150     if (BT_ERROR_NONE != ret)
1151     {
1152         OIC_LOG_V(ERROR, TAG, "bt_gatt_disconnect Failed with ret value [%s] ",
1153                   CALEGetErrorMsg(ret));
1154         return CA_STATUS_FAILED;
1155     }
1156
1157     OIC_LOG(DEBUG, TAG, "OUT");
1158     return CA_STATUS_OK;
1159 }
1160
1161 CAResult_t CAUpdateCharacteristicsToGattServerImpl(LEServerInfo *serverInfo,
1162         const uint8_t *data, const uint32_t dataLen)
1163 {
1164     OIC_LOG(DEBUG, TAG, "IN");
1165
1166     VERIFY_NON_NULL(serverInfo, TAG, "Server Info is NULL");
1167
1168     CALEGattStopDeviceScanning();
1169
1170     OIC_LOG_V(DEBUG, TAG, "Updating the data of length [%d] to [%s] ", dataLen,
1171               serverInfo->remoteAddress);
1172
1173     int result = bt_gatt_set_value(serverInfo->writeChar, (char *)data, dataLen);
1174
1175     if (BT_ERROR_NONE != result)
1176     {
1177         OIC_LOG_V(ERROR, TAG,
1178                   "bt_gatt_set_value Failed with return val [%s]",
1179                   CALEGetErrorMsg(result));
1180         goto exit;
1181     }
1182
1183     result = bt_gatt_client_write_value(serverInfo->writeChar, CALEGattCharacteristicWriteCb,
1184                                         NULL);
1185     if (BT_ERROR_NONE != result)
1186     {
1187         OIC_LOG_V(ERROR, TAG,
1188                   "bt_gatt_client_write_value Failed with return val [%s]",
1189                   CALEGetErrorMsg(result));
1190         goto exit;
1191     }
1192
1193     // wait for callback for write Characteristic with success to sent data
1194     OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
1195     oc_mutex_lock(g_threadWriteCharacteristicMutex);
1196     if (!g_isSignalSetFlag)
1197     {
1198         OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success");
1199         if (OC_WAIT_SUCCESS != oc_cond_wait_for(g_threadWriteCharacteristicCond,
1200                                                 g_threadWriteCharacteristicMutex,
1201                                                 WAIT_TIME_WRITE_CHARACTERISTIC))
1202         {
1203             g_isSignalSetFlag = false;
1204             oc_mutex_unlock(g_threadWriteCharacteristicMutex);
1205             OIC_LOG(ERROR, TAG, "there is no response. write has failed");
1206             goto exit;
1207         }
1208     }
1209     // reset flag set by writeCharacteristic Callback
1210     g_isSignalSetFlag = false;
1211     oc_mutex_unlock(g_threadWriteCharacteristicMutex);
1212
1213     oc_mutex_lock(g_scanMutex);
1214     if (g_isMulticastInProgress || g_isUnicastScanInProgress)
1215     {
1216         if (CA_STATUS_OK != CALEGattStartDeviceScanning())
1217         {
1218             OIC_LOG(ERROR, TAG, "Could not start device scanning");
1219         }
1220     }
1221     oc_mutex_unlock(g_scanMutex);
1222     OIC_LOG(DEBUG, TAG, "OUT");
1223     return CA_STATUS_OK;
1224
1225 exit:
1226     oc_mutex_lock(g_scanMutex);
1227     if (g_isMulticastInProgress || g_isUnicastScanInProgress)
1228     {
1229         if (CA_STATUS_OK != CALEGattStartDeviceScanning())
1230         {
1231             OIC_LOG(ERROR, TAG, "Could not start device scanning");
1232         }
1233     }
1234     oc_mutex_unlock(g_scanMutex);
1235
1236     OIC_LOG(DEBUG, TAG, "OUT");
1237     return CA_STATUS_FAILED;
1238 }
1239
1240 void CADiscoverLEServicesThread(void *remoteAddress)
1241 {
1242     OIC_LOG(DEBUG, TAG, "IN");
1243
1244     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
1245
1246     char *address  = (char *)remoteAddress;
1247
1248     CAResult_t result = CALEGattDiscoverServices(address);
1249     if (CA_STATUS_OK != result)
1250     {
1251         OIC_LOG(ERROR, TAG, "CALEGattDiscoverServices failed");
1252     }
1253
1254     OICFree(address);
1255     OIC_LOG(DEBUG, TAG, "OUT");
1256 }
1257
1258 static int CALEWaittillDisconnect(oc_mutex mutex, oc_cond cv, int wait_seconds)
1259 {
1260     OIC_LOG(DEBUG, TAG, "Waiting for server to be disconnected...");
1261     oc_mutex_lock(mutex);
1262     uint64_t wait_time = wait_seconds * MICROSECS_PER_SEC;
1263     int ret = oc_cond_wait_for(cv, mutex, wait_time);
1264     oc_mutex_unlock(mutex);
1265     return ret;
1266 }
1267
1268 static CAResult_t CALEGattConnectionRetry(const char *remoteAddress)
1269 {
1270     OIC_LOG(DEBUG, TAG, "IN");
1271
1272     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL")
1273
1274     CALEGattDisConnect(remoteAddress);
1275     CALEWaittillDisconnect(g_isDisconnectedMutex, g_LEDisconnectedCond, 10);
1276     CAResult_t result = CALEGattConnect(remoteAddress);
1277     OIC_LOG(DEBUG, TAG, "OUT");
1278     return result;
1279 }
1280
1281 CAResult_t CALEGattDiscoverServices(const char *remoteAddress)
1282 {
1283     OIC_LOG(DEBUG, TAG, "IN");
1284
1285     VERIFY_NON_NULL_RET(remoteAddress, TAG,
1286                         "remote address is NULL", CA_STATUS_FAILED);
1287
1288     LEServerInfo *serverInfo = NULL;
1289     unsigned int mtu_size;
1290     oc_mutex_lock(g_LEServerListMutex);
1291     if (CA_STATUS_OK != CAGetLEServerInfo(g_LEServerList, remoteAddress, &serverInfo))
1292     {
1293         oc_mutex_unlock(g_LEServerListMutex);
1294         OIC_LOG_V(ERROR, TAG, "Could not get server info for [%s]", remoteAddress);
1295         CALEGattDisConnect(remoteAddress);
1296         return CA_STATUS_FAILED;
1297     }
1298
1299     bt_gatt_h serviceHandle = NULL;
1300     int32_t ret = bt_gatt_client_get_service(serverInfo->clientHandle, CA_GATT_SERVICE_UUID, &serviceHandle);
1301     if (BT_ERROR_NONE != ret || NULL == serviceHandle)
1302     {
1303         OIC_LOG_V(ERROR, TAG,
1304                   "bt_gatt_client_get_service Failed with ret value [%s] ", CALEGetErrorMsg(ret));
1305         if(g_retrycount)
1306         {
1307             OIC_LOG(DEBUG, TAG, "Retry will be attempted to connect Gatt Server");
1308             g_retrycount--;
1309             retry_flag = 1;
1310             OIC_LOG_V(DEBUG, TAG, "Retry count left %d time(s)", g_retrycount);
1311             CAResult_t result = CALEGattConnectionRetry(remoteAddress);
1312             if(result == CA_STATUS_FAILED)
1313             {
1314                 goto error_exit;
1315             }
1316             else
1317             {
1318                 oc_mutex_unlock(g_LEServerListMutex);
1319                 OIC_LOG(ERROR, TAG, "Previous connection attempt failed, attempting to retry again");
1320                 OIC_LOG_V(DEBUG, TAG, "Retry count left %d time(s)", g_retrycount);
1321                 return CA_STATUS_FAILED;
1322             }
1323         }
1324     }
1325
1326     retry_flag = 0;
1327     // Server will read data on this characteristic.
1328     bt_gatt_h writeChrHandle = NULL;
1329     ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_REQUEST_CHRC_UUID,
1330             &writeChrHandle);
1331     if (BT_ERROR_NONE != ret || NULL == writeChrHandle)
1332     {
1333         OIC_LOG_V(ERROR, TAG,
1334                   "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
1335                   CALEGetErrorMsg(ret));
1336         goto error_exit;
1337     }
1338
1339     // Server will notify data on this characteristic.
1340     bt_gatt_h readChrHandle = NULL;
1341     ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_RESPONSE_CHRC_UUID,
1342             &readChrHandle);
1343     if (BT_ERROR_NONE != ret || NULL == readChrHandle)
1344     {
1345         OIC_LOG_V(ERROR, TAG,
1346                   "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
1347                   CALEGetErrorMsg(ret));
1348         goto error_exit;
1349     }
1350
1351
1352     //TODO: This data has to be freed while unsetting the callback.
1353     char *addr = OICStrdup(remoteAddress);
1354     if (NULL == addr)
1355     {
1356         OIC_LOG(ERROR, TAG, "addr is NULL");
1357         goto error_exit;
1358     }
1359
1360     ret = bt_gatt_client_set_characteristic_value_changed_cb(readChrHandle,
1361             CALEGattCharacteristicChangedCb,
1362             (void *)addr);
1363     if (BT_ERROR_NONE != ret)
1364     {
1365         OIC_LOG_V(ERROR, TAG,
1366                   "bt_gatt_client_set_characteristic_value_changed_cb Failed with ret value [%s]",
1367                   CALEGetErrorMsg(ret));
1368         goto error_exit;
1369     }
1370
1371     ret = bt_gatt_client_set_att_mtu_changed_cb(serverInfo->clientHandle,
1372             CALEGattClientMTUChangedCb,
1373             (void *)serverInfo->remoteAddress);
1374     if (BT_ERROR_NONE != ret)
1375     {
1376         OIC_LOG_V(ERROR, TAG,
1377                   "bt_gatt_client_set_att_mtu_changed_cb Failed with ret value [%s]",
1378                   CALEGetErrorMsg(ret));
1379         goto error_exit;
1380     }
1381
1382     oc_mutex_lock(g_threadMTUChangedMutex);
1383     ret = bt_gatt_client_request_att_mtu_change(serverInfo->clientHandle, CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_MTU_HEADER_SIZE);
1384     if (BT_ERROR_NONE != ret)
1385     {
1386         OIC_LOG_V(ERROR, TAG,
1387                   "bt_gatt_client_request_att_mtu_change Failed with ret value [%s]",
1388                   CALEGetErrorMsg(ret));
1389         oc_mutex_unlock(g_threadMTUChangedMutex);
1390         goto error_exit;
1391     }
1392
1393     OIC_LOG(DEBUG, TAG, "wait for callback to notify MTU Changed Callback");
1394     oc_cond_wait(g_threadMTUChangedCond, g_threadMTUChangedMutex);
1395     oc_mutex_unlock(g_threadMTUChangedMutex);
1396
1397     OIC_LOG(DEBUG, TAG, "Done MTU");
1398     ret = bt_gatt_client_get_att_mtu(serverInfo->clientHandle, &mtu_size);
1399     if (BT_ERROR_NONE != ret)
1400     {
1401         OIC_LOG_V(ERROR, TAG,
1402                   "bt_gatt_client_get_att_mtu Failed with ret value [%s]",
1403                   CALEGetErrorMsg(ret));
1404         goto error_exit;
1405     }
1406     OIC_LOG_V(DEBUG, TAG,"Negotiated MTU Size %d",mtu_size);
1407
1408     serverInfo->serviceHandle = serviceHandle;
1409     serverInfo->readChar = readChrHandle;
1410     serverInfo->writeChar = writeChrHandle;
1411     serverInfo->status = LE_STATUS_SERVICES_DISCOVERED;
1412     serverInfo->mtu_size = mtu_size;
1413
1414     while (serverInfo->pendingDataList)
1415     {
1416         LEData *leData = serverInfo->pendingDataList->data;
1417         if (CA_STATUS_OK != CAUpdateCharacteristicsToGattServerImpl(
1418                 serverInfo, leData->data, leData->dataLength))
1419         {
1420             OIC_LOG_V(ERROR, TAG, "Failed to send pending data to [%s]",
1421                       serverInfo->remoteAddress);
1422
1423             CADestroyLEDataList(&serverInfo->pendingDataList);
1424             break;
1425         }
1426         CARemoveLEDataFromList(&serverInfo->pendingDataList);
1427     }
1428     oc_mutex_unlock(g_LEServerListMutex);
1429
1430     OIC_LOG(DEBUG, TAG, "OUT");
1431     return CA_STATUS_OK;
1432
1433 error_exit:
1434     bt_gatt_client_destroy(serverInfo->clientHandle);
1435     serverInfo->clientHandle = NULL;
1436     oc_mutex_unlock(g_LEServerListMutex);
1437     CALEGattDisConnect(remoteAddress);
1438     return CA_STATUS_FAILED;
1439 }
1440
1441 CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress,
1442         const uint8_t *data, const uint32_t dataLen,
1443         CALETransferType_t type, const int32_t position)
1444 {
1445     OIC_LOG(DEBUG, TAG, "IN");
1446
1447     VERIFY_NON_NULL(data, TAG, "data is NULL");
1448
1449     if (0 >= dataLen)
1450     {
1451         OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input!");
1452         return CA_STATUS_INVALID_PARAM;
1453     }
1454
1455     LEServerInfo *serverInfo = NULL;
1456     oc_mutex_lock(g_LEServerListMutex);
1457     if (LE_UNICAST == type)
1458     {
1459         if (CA_STATUS_OK != CAGetLEServerInfo(g_LEServerList, remoteAddress, &serverInfo))
1460         {
1461             OIC_LOG_V(DEBUG, TAG,
1462                       "Device with address [%s] not yet found, initiating scan",
1463                       remoteAddress);
1464
1465             char *addr = OICStrdup(remoteAddress);
1466             if (NULL == addr)
1467             {
1468                 oc_mutex_unlock(g_LEServerListMutex);
1469                 OIC_LOG(ERROR, TAG, "Device address is NULL");
1470                 return CA_STATUS_FAILED;
1471             }
1472
1473             serverInfo = (LEServerInfo *)OICCalloc(1, sizeof(LEServerInfo));
1474             if (NULL == serverInfo)
1475             {
1476                 oc_mutex_unlock(g_LEServerListMutex);
1477                 OIC_LOG(ERROR, TAG, "Calloc failed");
1478                 OICFree(addr);
1479                 return CA_STATUS_FAILED;
1480             }
1481
1482             serverInfo->remoteAddress = addr;
1483             serverInfo->status = LE_STATUS_UNICAST_PENDING;
1484
1485             if (CA_STATUS_OK != CAAddLEServerInfoToList(&g_LEServerList, serverInfo))
1486             {
1487                 oc_mutex_unlock(g_LEServerListMutex);
1488                 OIC_LOG_V(ERROR, TAG, "Could not add [%s] to server list", remoteAddress);
1489                 CAFreeLEServerInfo(serverInfo);
1490                 return CA_STATUS_FAILED;
1491             }
1492
1493             if (CA_STATUS_OK != CAAddLEDataToList(&serverInfo->pendingDataList, data, dataLen))
1494             {
1495                 oc_mutex_unlock(g_LEServerListMutex);
1496                 OIC_LOG(ERROR, TAG, "Could not add data to pending list");
1497                 return CA_STATUS_FAILED;
1498             }
1499         }
1500
1501         if(serverInfo->status == LE_STATUS_UNICAST_PENDING)
1502         {
1503             oc_mutex_lock(g_scanMutex);
1504             if (!g_isMulticastInProgress && !g_isUnicastScanInProgress)
1505             {
1506                 CAResult_t result = CALEGattStartDeviceScanning();
1507                 if (CA_STATUS_OK != result)
1508                 {
1509                     oc_mutex_unlock(g_scanMutex);
1510                     OIC_LOG(ERROR, TAG, "CALEGattStartDeviceScanning failed");
1511                     return CA_STATUS_FAILED;
1512                 }
1513                 g_isUnicastScanInProgress = true;
1514                 // Start Timer
1515                 oc_cond_signal(g_startTimerCond);
1516             }
1517             else
1518             {
1519                 g_isUnicastScanInProgress = true;
1520                 // Reset Timer
1521                 oc_cond_signal(g_scanningTimeCond);
1522             }
1523             oc_mutex_unlock(g_scanMutex);
1524
1525         }
1526
1527         if (serverInfo->status == LE_STATUS_DISCOVERED)
1528         {
1529             if (CA_STATUS_OK != CAAddLEDataToList(&serverInfo->pendingDataList, data, dataLen))
1530             {
1531                 oc_mutex_unlock(g_LEServerListMutex);
1532                 OIC_LOG(ERROR, TAG, "Could not add data to pending list");
1533                 return CA_STATUS_FAILED;
1534             }
1535
1536             bt_gatt_client_h clientHandle = NULL;
1537             int32_t ret = bt_gatt_client_create(serverInfo->remoteAddress, &clientHandle);
1538             if (BT_ERROR_NONE != ret || NULL == clientHandle)
1539             {
1540                 OIC_LOG_V(ERROR, TAG,
1541                           "bt_gatt_client_create Failed with ret value [%s] ", CALEGetErrorMsg(ret));
1542                 CALEGattDisConnect(serverInfo->remoteAddress);
1543                 return CA_STATUS_FAILED;
1544             }
1545             serverInfo->clientHandle = clientHandle;
1546
1547             serverInfo->status = LE_STATUS_CONNECTION_INITIATED;
1548             if (CA_STATUS_OK != CALEGattInitiateConnection(serverInfo->remoteAddress))
1549             {
1550                 OIC_LOG_V(ERROR, TAG, "Could not initiate connection to [%s]", serverInfo->remoteAddress);
1551                 serverInfo->status = LE_STATUS_DISCOVERED;
1552                 CADestroyLEDataList(&serverInfo->pendingDataList);
1553                 oc_mutex_unlock(g_LEServerListMutex);
1554                 return CA_STATUS_FAILED;
1555             }
1556         }
1557         else if (serverInfo->status < LE_STATUS_SERVICES_DISCOVERED)
1558         {
1559             if (CA_STATUS_OK != CAAddLEDataToList(&serverInfo->pendingDataList, data, dataLen))
1560             {
1561                 oc_mutex_unlock(g_LEServerListMutex);
1562                 OIC_LOG(ERROR, TAG, "Could not add data to pending list");
1563                 return CA_STATUS_FAILED;
1564             }
1565         }
1566         else
1567         {
1568             if (CA_STATUS_OK != CAUpdateCharacteristicsToGattServerImpl(serverInfo, data, dataLen))
1569             {
1570                 OIC_LOG_V(ERROR, TAG, "Could not update characteristic to gatt server [%s]",
1571                           serverInfo->remoteAddress);
1572                 oc_mutex_unlock(g_LEServerListMutex);
1573                 return CA_STATUS_FAILED;
1574             }
1575         }
1576     }
1577     else if (LE_MULTICAST == type)
1578     {
1579         OIC_LOG(ERROR, TAG, "LE_MULTICAST type Not used");
1580     }
1581     oc_mutex_unlock(g_LEServerListMutex);
1582     OIC_LOG(DEBUG, TAG, "OUT");
1583     return CA_STATUS_OK;
1584 }
1585
1586 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
1587 {
1588     OIC_LOG(DEBUG,  TAG, "IN");
1589
1590     VERIFY_NON_NULL(data, TAG, "data is NULL");
1591
1592     if (0 >= dataLen)
1593     {
1594         OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input !");
1595         return CA_STATUS_INVALID_PARAM;
1596     }
1597
1598     oc_mutex_lock(g_LEServerListMutex);
1599     LEServerInfoList *curNode = g_LEServerList;
1600     while (curNode)
1601     {
1602         LEServerInfo *serverInfo = curNode->serverInfo;
1603         if (serverInfo->status == LE_STATUS_SERVICES_DISCOVERED)
1604         {
1605             if (CA_STATUS_OK != CAUpdateCharacteristicsToGattServerImpl(serverInfo, data, dataLen))
1606             {
1607                 OIC_LOG_V(ERROR, TAG, "Failed to update characteristics to gatt server [%s]",
1608                           serverInfo->remoteAddress);
1609             }
1610         }
1611         else if (serverInfo->status != LE_STATUS_INVALID)
1612         {
1613             if (CA_STATUS_OK != CAAddLEDataToList(&serverInfo->pendingDataList, data, dataLen))
1614             {
1615                 OIC_LOG(ERROR, TAG, "Failed to add to pending list");
1616             }
1617         }
1618         curNode = curNode->next;
1619     }
1620     oc_mutex_unlock(g_LEServerListMutex);
1621
1622     // Add the data to pending list.
1623     LEData *multicastData = (LEData *)OICCalloc(1, sizeof(LEData));
1624     if (NULL == multicastData)
1625     {
1626         OIC_LOG(ERROR, TAG, "Calloc failed");
1627         goto exit;
1628     }
1629     multicastData->data = OICCalloc(1, dataLen);
1630     if (NULL == multicastData->data)
1631     {
1632         OIC_LOG(ERROR, TAG, "Calloc failed");
1633         goto exit;
1634     }
1635     memcpy(multicastData->data, data, dataLen);
1636     multicastData->dataLength = dataLen;
1637
1638     oc_mutex_lock(g_multicastDataListMutex);
1639     if (NULL == g_multicastDataList)
1640     {
1641         g_multicastDataList = u_arraylist_create();
1642     }
1643     u_arraylist_add(g_multicastDataList, (void *)multicastData);
1644     oc_mutex_unlock(g_multicastDataListMutex);
1645
1646     // Start the scanning, if not started, else reset timer
1647     oc_mutex_lock(g_scanMutex);
1648     if (!g_isMulticastInProgress && !g_isUnicastScanInProgress)
1649     {
1650         CAResult_t result = CALEGattStartDeviceScanning();
1651         if (CA_STATUS_OK != result)
1652         {
1653             oc_mutex_unlock(g_scanMutex);
1654             OIC_LOG(ERROR, TAG, "CALEGattStartDeviceScanning Failed");
1655             goto exit;
1656         }
1657         g_isMulticastInProgress = true;
1658         // Start the timer by signalling it
1659         oc_cond_signal(g_startTimerCond);
1660     }
1661     else
1662     {
1663         g_isMulticastInProgress = true;
1664         // Reset timer
1665         oc_cond_signal(g_scanningTimeCond);
1666     }
1667     oc_mutex_unlock(g_scanMutex);
1668
1669 exit:
1670     OIC_LOG(DEBUG, TAG, "OUT ");
1671     return CA_STATUS_OK;
1672 }
1673
1674 uint16_t CALEClientGetMtuSize(const char* remote_address)
1675 {
1676     LEServerInfo *serverInfo = NULL;
1677     oc_mutex_lock(g_LEServerListMutex);
1678     if (CA_STATUS_OK == CAGetLEServerInfo(g_LEServerList, remote_address, &serverInfo))
1679     {
1680         if (serverInfo->status == LE_STATUS_SERVICES_DISCOVERED){
1681             OIC_LOG_V(DEBUG, TAG, "Mtu Size [%d]", serverInfo->mtu_size);
1682             oc_mutex_unlock(g_LEServerListMutex);
1683             OIC_LOG_V(INFO, TAG, "Returning Mtu Size [%d]", serverInfo->mtu_size - CA_BLE_MTU_HEADER_SIZE);
1684             return serverInfo->mtu_size - CA_BLE_MTU_HEADER_SIZE;
1685         }
1686     }
1687     oc_mutex_unlock(g_LEServerListMutex);
1688     return CA_DEFAULT_BLE_MTU_SIZE;
1689
1690 }
1691
1692 bool CALEClientIsConnected(const char* address)
1693 {
1694     (void)address;
1695     //@Todo
1696     return true;
1697 }
1698
1699 CAResult_t CALEClientSetMtuSize(const char* address, uint16_t mtuSize)
1700 {
1701     (void)mtuSize;
1702
1703     VERIFY_NON_NULL(address, TAG, "address is null");
1704     //@Todo
1705     //it should be implemented after update Tizen 3.0
1706     return CA_NOT_SUPPORTED;
1707 }
1708
1709 CAResult_t CALEClientSendNegotiationMessage(const char* address)
1710 {
1711     OIC_LOG_V(DEBUG, TAG, "CALEClientSendNegotiationMessage(%s)", address);
1712     //@Todo
1713     //it will be implemented when tizen public 3.0 is released.
1714     return CA_NOT_SUPPORTED;
1715 }