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