Add vd specific caleclient code
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / tizen / caleclient_vd.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         bt_gatt_client_h clientHandle = NULL;
474         int32_t ret = bt_gatt_client_create(remoteAddress, &clientHandle);
475         if (BT_ERROR_NONE != ret || NULL == clientHandle)
476         {
477             OIC_LOG_V(ERROR, TAG,
478                 "bt_gatt_client_create Failed with ret value [%s] ", CALEGetErrorMsg(ret));
479             CALEGattDisConnect(remoteAddress);
480             return CA_STATUS_FAILED;
481         }
482         serverInfo->clientHandle = clientHandle;
483
484         serverInfo->status = LE_STATUS_CONNECTION_INITIATED;
485         if (CA_STATUS_OK != CALEGattInitiateConnection(serverInfo->remoteAddress))
486         {
487             serverInfo->status = LE_STATUS_DISCOVERED;
488             OIC_LOG_V(ERROR, TAG, "Could not initiate connection to [%s]", serverInfo->remoteAddress);
489             oc_mutex_unlock(g_LEServerListMutex);
490             return;
491         }
492         oc_mutex_unlock(g_LEServerListMutex);
493         OIC_LOG(DEBUG, TAG, "OUT");
494         return;
495     }
496
497     if (isMulticastInProgress)
498     {
499         if (CA_STATUS_OK != ret)
500         {
501             OIC_LOG_V(DEBUG, TAG,
502                       "Newly discovered device with address [%s], adding to list", scanInfo->remote_address);
503
504             char *addr = OICStrdup(scanInfo->remote_address);
505             if (NULL == addr)
506             {
507                 oc_mutex_unlock(g_LEServerListMutex);
508                 OIC_LOG(ERROR, TAG, "Device address is NULL");
509                 return;
510             }
511             serverInfo = (LEServerInfo *)OICCalloc(1, sizeof(LEServerInfo));
512             if (NULL == serverInfo)
513             {
514                 oc_mutex_unlock(g_LEServerListMutex);
515                 OIC_LOG(ERROR, TAG, "Calloc failed");
516                 OICFree(addr);
517                 return;
518             }
519             serverInfo->remoteAddress = addr;
520             serverInfo->status = LE_STATUS_DISCOVERED;
521
522             if (CA_STATUS_OK != CAAddLEServerInfoToList(&g_LEServerList, serverInfo))
523             {
524                 oc_mutex_unlock(g_LEServerListMutex);
525                 OIC_LOG_V(ERROR, TAG, "Could not add [%s] to server list", scanInfo->remote_address);
526                 CAFreeLEServerInfo(serverInfo);
527                 return;
528             }
529
530             if (!CALEIsHaveService(scanInfo, CA_GATT_SERVICE_UUID))
531             {
532                 serverInfo->status = LE_STATUS_INVALID;
533                 OIC_LOG_V(DEBUG, TAG, "Device [%s] does not support OIC service", serverInfo->remoteAddress);
534                 oc_mutex_unlock(g_LEServerListMutex);
535                 return;
536             }
537
538             oc_mutex_lock(g_multicastDataListMutex);
539             uint32_t lengthData = u_arraylist_length(g_multicastDataList);
540             for (uint32_t len = 0; len < lengthData; ++len)
541             {
542                 LEData *multicastData = (LEData *)u_arraylist_get(g_multicastDataList, len);
543                 if (NULL == multicastData)
544                 {
545                     OIC_LOG(ERROR, TAG, "multicastData is NULL");
546                     continue;
547                 }
548                 if (CA_STATUS_OK != CAAddLEDataToList(&serverInfo->pendingDataList,
549                                                       multicastData->data, multicastData->dataLength))
550                 {
551                     OIC_LOG(ERROR, TAG, "Failed to add to pending list");
552                     continue;
553                 }
554             }
555             oc_mutex_unlock(g_multicastDataListMutex);
556         }
557
558         if (serverInfo->status == LE_STATUS_DISCOVERED)
559         {
560             // Initiate connection if not yet initiated
561             serverInfo->status = LE_STATUS_CONNECTION_INITIATED;
562             if (CA_STATUS_OK != CALEGattInitiateConnection(serverInfo->remoteAddress))
563             {
564                 OIC_LOG_V(ERROR, TAG, "Could not initiate connection to [%s]", serverInfo->remoteAddress);
565                 serverInfo->status = LE_STATUS_DISCOVERED;
566             }
567         }
568         else
569         {
570             OIC_LOG_V(DEBUG, TAG, "Device already discovered, status= [%d]", serverInfo->status);
571         }
572     }
573
574     oc_mutex_unlock(g_LEServerListMutex);
575     OIC_LOG(DEBUG, TAG, "OUT");
576 }
577
578 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
579 {
580     OIC_LOG(DEBUG, TAG, "IN");
581
582     oc_mutex_lock(g_LEClientThreadPoolMutex);
583     g_LEClientThreadPool = handle;
584     oc_mutex_unlock(g_LEClientThreadPoolMutex);
585
586     OIC_LOG(DEBUG, TAG, "OUT");
587 }
588
589 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
590 {
591     OIC_LOG(DEBUG, TAG, "IN");
592
593     oc_mutex_lock(g_LEReqRespClientCbMutex);
594
595     g_LEClientDataReceivedCallback = callback;
596
597     oc_mutex_unlock(g_LEReqRespClientCbMutex);
598
599     OIC_LOG(DEBUG, TAG, "OUT");
600 }
601
602 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
603 {
604     g_clientErrorCallback = callback;
605 }
606
607 CAResult_t CAStartLEGattClient()
608 {
609     OIC_LOG(DEBUG, TAG, "IN");
610
611     oc_mutex_lock(g_LEClientStateMutex);
612     if (true  == g_isLEGattClientStarted)
613     {
614         OIC_LOG(ERROR, TAG, "Gatt Client is already running!!");
615         oc_mutex_unlock(g_LEClientStateMutex);
616         return CA_STATUS_FAILED;
617     }
618
619     CAResult_t  result = CALEGattSetCallbacks();
620     if (CA_STATUS_OK != result)
621     {
622         OIC_LOG(ERROR, TAG, "CABleGattSetCallbacks Failed");
623         oc_mutex_unlock(g_LEClientStateMutex);
624         CATerminateLEGattClient();
625         return CA_STATUS_FAILED;
626     }
627
628     g_isLEGattClientStarted = true;
629     oc_mutex_unlock(g_LEClientStateMutex);
630
631     oc_mutex_lock(g_LEClientThreadPoolMutex);
632     if (NULL == g_LEClientThreadPool)
633     {
634         OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL");
635         CATerminateGattClientMutexVariables();
636         oc_mutex_unlock(g_LEClientThreadPoolMutex);
637         return CA_STATUS_FAILED;
638     }
639
640     result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartTimerThread,
641                                      NULL, NULL);
642     if (CA_STATUS_OK != result)
643     {
644         OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed");
645         CATerminateGattClientMutexVariables();
646         oc_mutex_unlock(g_LEClientThreadPoolMutex);
647         return CA_STATUS_FAILED;
648     }
649     oc_mutex_unlock(g_LEClientThreadPoolMutex);
650
651     OIC_LOG(DEBUG, TAG, "OUT");
652     return CA_STATUS_OK;
653 }
654
655 void CAStartTimerThread(void *data)
656 {
657     (void)data;
658
659     OIC_LOG(DEBUG, TAG, "IN");
660     while (g_isLEGattClientStarted)
661     {
662         oc_mutex_lock(g_scanMutex);
663         if (!g_isMulticastInProgress && !g_isUnicastScanInProgress)
664         {
665             OIC_LOG(DEBUG, TAG, "waiting....");
666             oc_cond_wait(g_startTimerCond, g_scanMutex);
667             OIC_LOG(DEBUG, TAG, "Wake up");
668         }
669
670         // Timed conditional wait for stopping the scan.
671         OCWaitResult_t ret = oc_cond_wait_for(g_scanningTimeCond, g_scanMutex,
672                                               TIMEOUT);
673         if (OC_WAIT_TIMEDOUT == ret)
674         {
675             OIC_LOG(DEBUG, TAG, "Scan is timed Out");
676             // Call stop scan.
677             CALEGattStopDeviceScanning();
678
679             if (g_isMulticastInProgress)
680             {
681                 oc_mutex_lock(g_multicastDataListMutex);
682                 // Clear the data list and device list.
683                 u_arraylist_destroy(g_multicastDataList);
684                 g_multicastDataList = NULL;
685                 oc_mutex_unlock(g_multicastDataListMutex);
686                 g_isMulticastInProgress = false;
687             }
688             g_isUnicastScanInProgress = false;
689         }
690         oc_mutex_unlock(g_scanMutex);
691     }
692
693     OIC_LOG(DEBUG, TAG, "OUT");
694 }
695
696 void CAStopLEGattClient()
697 {
698     OIC_LOG(DEBUG,  TAG, "IN");
699
700     oc_mutex_lock(g_LEClientStateMutex);
701
702     if (false == g_isLEGattClientStarted)
703     {
704         OIC_LOG(ERROR, TAG, "Gatt Client is not running to stop");
705         oc_mutex_unlock(g_LEClientStateMutex);
706         return;
707     }
708
709     CALEGattUnSetCallbacks();
710
711     CALEGattStopDeviceScanning();
712
713     g_isLEGattClientStarted = false;
714
715     // Signal the conditions waiting in Start timer.
716     oc_cond_signal(g_startTimerCond);
717     oc_cond_signal(g_scanningTimeCond);
718
719     // Destroy the multicast data list and device list if not empty.
720     if (NULL != g_multicastDataList)
721     {
722         oc_mutex_lock(g_multicastDataListMutex);
723         u_arraylist_destroy(g_multicastDataList);
724         g_multicastDataList = NULL;
725         oc_mutex_unlock(g_multicastDataListMutex);
726     }
727
728     oc_mutex_lock(g_LEServerListMutex);
729     CAFreeLEServerList(g_LEServerList);
730     g_LEServerList = NULL;
731     oc_mutex_unlock(g_LEServerListMutex);
732
733     oc_mutex_lock(g_threadWriteCharacteristicMutex);
734     oc_cond_signal(g_threadWriteCharacteristicCond);
735     oc_mutex_unlock(g_threadWriteCharacteristicMutex);
736
737     GMainContext  *context_event_loop = NULL;
738     // Required for waking up the thread which is running in gmain loop
739     if (NULL != g_eventLoop)
740     {
741         context_event_loop = g_main_loop_get_context(g_eventLoop);
742     }
743     if (context_event_loop)
744     {
745         OIC_LOG_V(DEBUG,  TAG, "g_eventLoop context %p", (void *)context_event_loop);
746         g_main_context_wakeup(context_event_loop);
747
748         // Kill g main loops and kill threads.
749         g_main_loop_quit(g_eventLoop);
750     }
751     else
752     {
753         OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL");
754     }
755
756     oc_mutex_unlock(g_LEClientStateMutex);
757
758     OIC_LOG(DEBUG,  TAG, "OUT");
759 }
760
761 CAResult_t CAInitializeLEGattClient()
762 {
763     OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
764     CAResult_t res = CAInitGattClientMutexVariables();
765     if (CA_STATUS_OK != res)
766     {
767         OIC_LOG(ERROR, TAG, "CAInitGattClientMutexVariables failed!");
768         CATerminateGattClientMutexVariables();
769         return CA_STATUS_FAILED;
770     }
771     return res;
772 }
773
774 void CATerminateLEGattClient()
775 {
776     OIC_LOG(DEBUG,  TAG, "IN");
777
778     CATerminateGattClientMutexVariables();
779
780     OIC_LOG(DEBUG,  TAG, "OUT");
781 }
782
783 CAResult_t CAInitGattClientMutexVariables()
784 {
785     OIC_LOG(DEBUG,  TAG, "IN");
786     if (NULL == g_LEClientStateMutex)
787     {
788         g_LEClientStateMutex = oc_mutex_new();
789         if (NULL == g_LEClientStateMutex)
790         {
791             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
792             return CA_STATUS_FAILED;
793         }
794     }
795
796     if (NULL == g_LEServerListMutex)
797     {
798         g_LEServerListMutex = oc_mutex_new();
799         if (NULL == g_LEServerListMutex)
800         {
801             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
802             return CA_STATUS_FAILED;
803         }
804     }
805
806     if (NULL == g_LEReqRespClientCbMutex)
807     {
808         g_LEReqRespClientCbMutex = oc_mutex_new();
809         if (NULL == g_LEReqRespClientCbMutex)
810         {
811             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
812             return CA_STATUS_FAILED;
813         }
814     }
815
816     if (NULL == g_LEClientThreadPoolMutex)
817     {
818         g_LEClientThreadPoolMutex = oc_mutex_new();
819         if (NULL == g_LEClientThreadPoolMutex)
820         {
821             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
822             return CA_STATUS_FAILED;
823         }
824     }
825
826     if (NULL == g_LEClientConnectMutex)
827     {
828         g_LEClientConnectMutex = oc_mutex_new();
829         if (NULL == g_LEClientConnectMutex)
830         {
831             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
832             return CA_STATUS_FAILED;
833         }
834     }
835
836     if (NULL == g_isScanningInProgressMutex)
837     {
838         g_isScanningInProgressMutex = oc_mutex_new();
839         if (NULL == g_isScanningInProgressMutex)
840         {
841             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
842             return CA_STATUS_FAILED;
843         }
844     }
845
846     if (NULL == g_isConnectionInProgressMutex)
847     {
848         g_isConnectionInProgressMutex = oc_mutex_new();
849         if (NULL == g_isConnectionInProgressMutex)
850         {
851             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
852             return CA_STATUS_FAILED;
853         }
854     }
855
856     if (NULL == g_multicastDataListMutex)
857     {
858         g_multicastDataListMutex = oc_mutex_new();
859         if (NULL == g_multicastDataListMutex)
860         {
861             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
862             return CA_STATUS_FAILED;
863         }
864     }
865
866     if (NULL == g_scanMutex)
867     {
868         g_scanMutex = oc_mutex_new();
869         if (NULL == g_scanMutex)
870         {
871             OIC_LOG(ERROR, TAG, "oc_mutex_new failed");
872             return CA_STATUS_FAILED;
873         }
874     }
875
876     if (NULL == g_threadWriteCharacteristicMutex)
877     {
878         g_threadWriteCharacteristicMutex = oc_mutex_new();
879         if (NULL == g_threadWriteCharacteristicMutex)
880         {
881             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
882             return CA_STATUS_FAILED;
883         }
884     }
885
886     if (NULL == g_startTimerCond)
887     {
888         g_startTimerCond = oc_cond_new();
889         if (NULL == g_startTimerCond)
890         {
891             OIC_LOG(ERROR, TAG, "oc_cond_new failed");
892             return CA_STATUS_FAILED;
893         }
894     }
895
896     if (NULL == g_scanningTimeCond)
897     {
898         g_scanningTimeCond = oc_cond_new();
899         if (NULL == g_scanningTimeCond)
900         {
901             OIC_LOG(ERROR, TAG, "oc_cond_new failed");
902             return CA_STATUS_FAILED;
903         }
904     }
905
906     if (NULL == g_threadWriteCharacteristicCond)
907     {
908         g_threadWriteCharacteristicCond = oc_cond_new();
909         if (NULL == g_threadWriteCharacteristicCond)
910         {
911             OIC_LOG(ERROR, TAG, "oc_cond_new failed");
912             return CA_STATUS_FAILED;
913         }
914     }
915
916     OIC_LOG(DEBUG,  TAG, "OUT");
917     return CA_STATUS_OK;
918 }
919
920 void CATerminateGattClientMutexVariables()
921 {
922     OIC_LOG(DEBUG,  TAG, "IN");
923
924     oc_mutex_free(g_LEClientStateMutex);
925     g_LEClientStateMutex = NULL;
926
927     oc_mutex_free(g_LEServerListMutex);
928     g_LEServerListMutex = NULL;
929
930     oc_mutex_free(g_LEReqRespClientCbMutex);
931     g_LEReqRespClientCbMutex = NULL;
932
933     oc_mutex_free(g_LEClientConnectMutex);
934     g_LEClientConnectMutex = NULL;
935
936     oc_mutex_free(g_LEClientThreadPoolMutex);
937     g_LEClientThreadPoolMutex = NULL;
938
939     oc_mutex_free(g_isScanningInProgressMutex);
940     g_isScanningInProgressMutex = NULL;
941
942     oc_mutex_free(g_isConnectionInProgressMutex);
943     g_isConnectionInProgressMutex = NULL;
944
945     oc_mutex_free(g_multicastDataListMutex);
946     g_multicastDataListMutex = NULL;
947
948     oc_mutex_free(g_scanMutex);
949     g_scanMutex = NULL;
950
951     oc_mutex_free(g_threadWriteCharacteristicMutex);
952     g_threadWriteCharacteristicMutex = NULL;
953
954     oc_cond_free(g_startTimerCond);
955     g_startTimerCond = NULL;
956
957     oc_cond_free(g_scanningTimeCond);
958     g_scanningTimeCond = NULL;
959
960     oc_cond_free(g_threadWriteCharacteristicCond);
961     g_threadWriteCharacteristicCond = NULL;
962     g_isSignalSetFlag = false;
963
964     OIC_LOG(DEBUG,  TAG, "OUT");
965 }
966
967 CAResult_t CALEGattSetCallbacks()
968 {
969     OIC_LOG(DEBUG, TAG, "IN");
970
971     OIC_LOG(DEBUG, TAG, "OUT");
972     return CA_STATUS_OK;
973 }
974
975 void CALEGattUnSetCallbacks()
976 {
977     OIC_LOG(DEBUG, TAG, "IN");
978
979     bt_gatt_unset_connection_state_changed_cb();
980
981     oc_mutex_lock(g_LEServerListMutex);
982     LEServerInfoList *curNode = g_LEServerList;
983     while (curNode)
984     {
985         LEServerInfo *serverInfo = curNode->serverInfo;
986         if (serverInfo->status >= LE_STATUS_SERVICES_DISCOVERED)
987         {
988             bt_gatt_client_unset_characteristic_value_changed_cb(serverInfo->readChar);
989         }
990         curNode = curNode->next;
991     }
992     oc_mutex_unlock(g_LEServerListMutex);
993
994     OIC_LOG(DEBUG, TAG, "OUT");
995 }
996
997 CAResult_t CALEGattStartDeviceScanning()
998 {
999     OIC_LOG(DEBUG, TAG, "IN");
1000
1001     oc_mutex_lock(g_isScanningInProgressMutex);
1002     if (!g_isScanningInProgress)
1003     {
1004         int ret = bt_adapter_le_start_scan(CALEAdapterScanResultCb, NULL);
1005         if (BT_ERROR_NONE != ret)
1006         {
1007             oc_mutex_unlock(g_isScanningInProgressMutex);
1008             OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_scan failed[%s]",
1009                       CALEGetErrorMsg(ret));
1010             return CA_STATUS_FAILED;
1011         }
1012         g_isScanningInProgress = true;
1013     }
1014     else
1015     {
1016         OIC_LOG(DEBUG, TAG, "Ignore, scanning already in progress");
1017     }
1018     oc_mutex_unlock(g_isScanningInProgressMutex);
1019
1020     OIC_LOG(DEBUG, TAG, "OUT");
1021     return CA_STATUS_OK;
1022 }
1023
1024 void CALEGattStopDeviceScanning()
1025 {
1026     OIC_LOG(DEBUG, TAG, "IN");
1027
1028     oc_mutex_lock(g_isScanningInProgressMutex);
1029     if (g_isScanningInProgress)
1030     {
1031         int ret = bt_adapter_le_stop_scan();
1032         if (BT_ERROR_NONE != ret)
1033         {
1034             oc_mutex_unlock(g_isScanningInProgressMutex);
1035             OIC_LOG_V(ERROR, TAG, "bt_adapter_le_stop_scan failed[%s]",
1036                       CALEGetErrorMsg(ret));
1037             return;
1038         }
1039         g_isScanningInProgress = false;
1040     }
1041     else
1042     {
1043         OIC_LOG(DEBUG, TAG, "Ignore, scanning not in progress");
1044     }
1045     oc_mutex_unlock(g_isScanningInProgressMutex);
1046
1047     OIC_LOG(DEBUG, TAG, "OUT");
1048 }
1049
1050 void CAGattConnectThread (void *remoteAddress)
1051 {
1052     OIC_LOG(DEBUG, TAG, "IN ");
1053
1054     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
1055
1056     char *address  = (char *)remoteAddress;
1057
1058     OIC_LOG_V(DEBUG, TAG, "remote address is [%s]", address);
1059
1060     CAResult_t result = CALEGattConnect(address);
1061
1062     if (CA_STATUS_OK != result)
1063     {
1064         OIC_LOG_V(ERROR, TAG, "bt_gatt_connect failed for [%s]", address);
1065     }
1066
1067     OICFree(address);
1068
1069     OIC_LOG(DEBUG, TAG, "OUT");
1070 }
1071
1072 CAResult_t CALEGattConnect(const char *remoteAddress)
1073 {
1074     OIC_LOG(DEBUG, TAG, "IN");
1075
1076     VERIFY_NON_NULL_RET(remoteAddress, TAG,
1077                         "remote address is NULL", CA_STATUS_FAILED);
1078
1079     oc_mutex_lock(g_LEClientConnectMutex);
1080     CAResult_t result = CA_STATUS_OK;
1081
1082     int ret = bt_gatt_connect(remoteAddress, false);
1083     if (BT_ERROR_NONE != ret)
1084     {
1085         OIC_LOG_V(ERROR, TAG, "bt_gatt_connect Failed with ret value [%s] ",
1086                   CALEGetErrorMsg(ret));
1087         oc_mutex_unlock(g_LEClientConnectMutex);
1088         return CA_STATUS_FAILED;
1089     }
1090
1091     oc_mutex_unlock(g_LEClientConnectMutex);
1092
1093     OIC_LOG(DEBUG, TAG, "OUT");
1094     return result;
1095 }
1096
1097 CAResult_t CALEGattDisConnect(const char *remoteAddress)
1098 {
1099     OIC_LOG(DEBUG, TAG, "IN");
1100
1101     VERIFY_NON_NULL_RET(remoteAddress, TAG,
1102                         "remote address is NULL", CA_STATUS_FAILED);
1103
1104     int ret = bt_gatt_disconnect(remoteAddress);
1105
1106     if (BT_ERROR_NONE != ret)
1107     {
1108         OIC_LOG_V(ERROR, TAG, "bt_gatt_disconnect Failed with ret value [%s] ",
1109                   CALEGetErrorMsg(ret));
1110         return CA_STATUS_FAILED;
1111     }
1112
1113     OIC_LOG(DEBUG, TAG, "OUT");
1114     return CA_STATUS_OK;
1115 }
1116
1117 CAResult_t CAUpdateCharacteristicsToGattServerImpl(LEServerInfo *serverInfo,
1118         const uint8_t *data, const uint32_t dataLen)
1119 {
1120     OIC_LOG(DEBUG, TAG, "IN");
1121
1122     VERIFY_NON_NULL(serverInfo, TAG, "Server Info is NULL");
1123
1124     CALEGattStopDeviceScanning();
1125
1126     OIC_LOG_V(DEBUG, TAG, "Updating the data of length [%d] to [%s] ", dataLen,
1127               serverInfo->remoteAddress);
1128
1129     int result = bt_gatt_set_value(serverInfo->writeChar, (char *)data, dataLen);
1130
1131     if (BT_ERROR_NONE != result)
1132     {
1133         OIC_LOG_V(ERROR, TAG,
1134                   "bt_gatt_set_value Failed with return val [%s]",
1135                   CALEGetErrorMsg(result));
1136         goto exit;
1137     }
1138
1139     result = bt_gatt_client_write_value(serverInfo->writeChar, CALEGattCharacteristicWriteCb,
1140                                         NULL);
1141     if (BT_ERROR_NONE != result)
1142     {
1143         OIC_LOG_V(ERROR, TAG,
1144                   "bt_gatt_client_write_value Failed with return val [%s]",
1145                   CALEGetErrorMsg(result));
1146         goto exit;
1147     }
1148
1149     // wait for callback for write Characteristic with success to sent data
1150     OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
1151     oc_mutex_lock(g_threadWriteCharacteristicMutex);
1152     if (!g_isSignalSetFlag)
1153     {
1154         OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success");
1155         if (OC_WAIT_SUCCESS != oc_cond_wait_for(g_threadWriteCharacteristicCond,
1156                                                 g_threadWriteCharacteristicMutex,
1157                                                 WAIT_TIME_WRITE_CHARACTERISTIC))
1158         {
1159             g_isSignalSetFlag = false;
1160             oc_mutex_unlock(g_threadWriteCharacteristicMutex);
1161             OIC_LOG(ERROR, TAG, "there is no response. write has failed");
1162             goto exit;
1163         }
1164     }
1165     // reset flag set by writeCharacteristic Callback
1166     g_isSignalSetFlag = false;
1167     oc_mutex_unlock(g_threadWriteCharacteristicMutex);
1168
1169     oc_mutex_lock(g_scanMutex);
1170     if (g_isMulticastInProgress || g_isUnicastScanInProgress)
1171     {
1172         if (CA_STATUS_OK != CALEGattStartDeviceScanning())
1173         {
1174             OIC_LOG(ERROR, TAG, "Could not start device scanning");
1175         }
1176     }
1177     oc_mutex_unlock(g_scanMutex);
1178     OIC_LOG(DEBUG, TAG, "OUT");
1179     return CA_STATUS_OK;
1180
1181 exit:
1182     oc_mutex_lock(g_scanMutex);
1183     if (g_isMulticastInProgress || g_isUnicastScanInProgress)
1184     {
1185         if (CA_STATUS_OK != CALEGattStartDeviceScanning())
1186         {
1187             OIC_LOG(ERROR, TAG, "Could not start device scanning");
1188         }
1189     }
1190     oc_mutex_unlock(g_scanMutex);
1191
1192     OIC_LOG(DEBUG, TAG, "OUT");
1193     return CA_STATUS_FAILED;
1194 }
1195
1196 void CADiscoverLEServicesThread(void *remoteAddress)
1197 {
1198     OIC_LOG(DEBUG, TAG, "IN");
1199
1200     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
1201
1202     char *address  = (char *)remoteAddress;
1203
1204     CAResult_t result = CALEGattDiscoverServices(address);
1205     if (CA_STATUS_OK != result)
1206     {
1207         OIC_LOG(ERROR, TAG, "CALEGattDiscoverServices failed");
1208     }
1209
1210     OICFree(address);
1211     OIC_LOG(DEBUG, TAG, "OUT");
1212 }
1213
1214 CAResult_t CALEGattDiscoverServices(const char *remoteAddress)
1215 {
1216     OIC_LOG(DEBUG, TAG, "IN");
1217
1218     VERIFY_NON_NULL_RET(remoteAddress, TAG,
1219                         "remote address is NULL", CA_STATUS_FAILED);
1220
1221     LEServerInfo *serverInfo = NULL;
1222     oc_mutex_lock(g_LEServerListMutex);
1223     if (CA_STATUS_OK != CAGetLEServerInfo(g_LEServerList, remoteAddress, &serverInfo))
1224     {
1225         oc_mutex_unlock(g_LEServerListMutex);
1226         OIC_LOG_V(ERROR, TAG, "Could not get server info for [%s]", remoteAddress);
1227         CALEGattDisConnect(remoteAddress);
1228         return CA_STATUS_FAILED;
1229     }
1230
1231     bt_gatt_h serviceHandle = NULL;
1232     ret = bt_gatt_client_get_service(serverInfo->clientHandle, CA_GATT_SERVICE_UUID, &serviceHandle);
1233     if (BT_ERROR_NONE != ret || NULL == serviceHandle)
1234     {
1235         OIC_LOG_V(ERROR, TAG,
1236                   "bt_gatt_client_get_service Failed with ret value [%s] ", CALEGetErrorMsg(ret));
1237         bt_gatt_client_destroy(serverInfo->clientHandle);
1238         CALEGattDisConnect(remoteAddress);
1239         return CA_STATUS_FAILED;
1240     }
1241
1242     // Server will read data on this characteristic.
1243     bt_gatt_h writeChrHandle = NULL;
1244     ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_REQUEST_CHRC_UUID,
1245             &writeChrHandle);
1246     if (BT_ERROR_NONE != ret || NULL == writeChrHandle)
1247     {
1248         OIC_LOG_V(ERROR, TAG,
1249                   "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
1250                   CALEGetErrorMsg(ret));
1251         bt_gatt_client_destroy(serverInfo->clientHandle);
1252         CALEGattDisConnect(remoteAddress);
1253         return CA_STATUS_FAILED;
1254     }
1255
1256     // Server will notify data on this characteristic.
1257     bt_gatt_h readChrHandle = NULL;
1258     ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_RESPONSE_CHRC_UUID,
1259             &readChrHandle);
1260     if (BT_ERROR_NONE != ret || NULL == readChrHandle)
1261     {
1262         OIC_LOG_V(ERROR, TAG,
1263                   "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
1264                   CALEGetErrorMsg(ret));
1265         bt_gatt_client_destroy(serverInfo->clientHandle);
1266         CALEGattDisConnect(remoteAddress);
1267         return CA_STATUS_FAILED;
1268     }
1269
1270
1271     //TODO: This data has to be freed while unsetting the callback.
1272     char *addr = OICStrdup(remoteAddress);
1273     if (NULL == addr)
1274     {
1275         OIC_LOG(ERROR, TAG, "addr is NULL");
1276         bt_gatt_client_destroy(serverInfo->clientHandle);
1277         CALEGattDisConnect(remoteAddress);
1278         return CA_STATUS_FAILED;
1279     }
1280
1281     ret = bt_gatt_client_set_characteristic_value_changed_cb(readChrHandle,
1282             CALEGattCharacteristicChangedCb,
1283             (void *)addr);
1284     if (BT_ERROR_NONE != ret)
1285     {
1286         OIC_LOG_V(ERROR, TAG,
1287                   "bt_gatt_client_set_characteristic_value_changed_cb Failed with ret value [%s]",
1288                   CALEGetErrorMsg(ret));
1289         bt_gatt_client_destroy(serverInfo->clientHandle);
1290         CALEGattDisConnect(remoteAddress);
1291         return CA_STATUS_FAILED;
1292     }
1293
1294     serverInfo->serviceHandle = serviceHandle;
1295     serverInfo->readChar = readChrHandle;
1296     serverInfo->writeChar = writeChrHandle;
1297     serverInfo->status = LE_STATUS_SERVICES_DISCOVERED;
1298
1299     while (serverInfo->pendingDataList)
1300     {
1301         LEData *leData = serverInfo->pendingDataList->data;
1302         if (CA_STATUS_OK != CAUpdateCharacteristicsToGattServerImpl(
1303                 serverInfo, leData->data, leData->dataLength))
1304         {
1305             OIC_LOG_V(ERROR, TAG, "Failed to send pending data to [%s]",
1306                       serverInfo->remoteAddress);
1307
1308             CADestroyLEDataList(&serverInfo->pendingDataList);
1309             break;
1310         }
1311         CARemoveLEDataFromList(&serverInfo->pendingDataList);
1312     }
1313     oc_mutex_unlock(g_LEServerListMutex);
1314
1315     OIC_LOG(DEBUG, TAG, "OUT");
1316     return CA_STATUS_OK;
1317 }
1318
1319 CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress,
1320         const uint8_t *data, const uint32_t dataLen,
1321         CALETransferType_t type, const int32_t position)
1322 {
1323     OIC_LOG(DEBUG, TAG, "IN");
1324
1325     VERIFY_NON_NULL(data, TAG, "data is NULL");
1326
1327     if (0 >= dataLen)
1328     {
1329         OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input!");
1330         return CA_STATUS_INVALID_PARAM;
1331     }
1332
1333     LEServerInfo *serverInfo = NULL;
1334     oc_mutex_lock(g_LEServerListMutex);
1335     if (LE_UNICAST == type)
1336     {
1337         if (CA_STATUS_OK != CAGetLEServerInfo(g_LEServerList, remoteAddress, &serverInfo))
1338         {
1339             OIC_LOG_V(DEBUG, TAG,
1340                       "Device with address [%s] not yet found, initiating scan",
1341                       remoteAddress);
1342
1343             char *addr = OICStrdup(remoteAddress);
1344             if (NULL == addr)
1345             {
1346                 oc_mutex_unlock(g_LEServerListMutex);
1347                 OIC_LOG(ERROR, TAG, "Device address is NULL");
1348                 return CA_STATUS_FAILED;
1349             }
1350
1351             serverInfo = (LEServerInfo *)OICCalloc(1, sizeof(LEServerInfo));
1352             if (NULL == serverInfo)
1353             {
1354                 oc_mutex_unlock(g_LEServerListMutex);
1355                 OIC_LOG(ERROR, TAG, "Calloc failed");
1356                 OICFree(addr);
1357                 return CA_STATUS_FAILED;
1358             }
1359
1360             serverInfo->remoteAddress = addr;
1361             serverInfo->status = LE_STATUS_UNICAST_PENDING;
1362
1363             if (CA_STATUS_OK != CAAddLEServerInfoToList(&g_LEServerList, serverInfo))
1364             {
1365                 oc_mutex_unlock(g_LEServerListMutex);
1366                 OIC_LOG_V(ERROR, TAG, "Could not add [%s] to server list", serverInfo->remoteAddress);
1367                 CAFreeLEServerInfo(serverInfo);
1368                 return CA_STATUS_FAILED;
1369             }
1370
1371             if (CA_STATUS_OK != CAAddLEDataToList(&serverInfo->pendingDataList, data, dataLen))
1372             {
1373                 oc_mutex_unlock(g_LEServerListMutex);
1374                 OIC_LOG(ERROR, TAG, "Could not add data to pending list");
1375                 return CA_STATUS_FAILED;
1376             }
1377
1378             oc_mutex_unlock(g_LEServerListMutex);
1379
1380             oc_mutex_lock(g_scanMutex);
1381             if (!g_isMulticastInProgress && !g_isUnicastScanInProgress)
1382             {
1383                 CAResult_t result = CALEGattStartDeviceScanning();
1384                 if (CA_STATUS_OK != result)
1385                 {
1386                     oc_mutex_unlock(g_scanMutex);
1387                     OIC_LOG(ERROR, TAG, "CALEGattStartDeviceScanning failed");
1388                     return CA_STATUS_FAILED;
1389                 }
1390                 g_isUnicastScanInProgress = true;
1391                 // Start Timer
1392                 oc_cond_signal(g_startTimerCond);
1393             }
1394             else
1395             {
1396                 g_isUnicastScanInProgress = true;
1397                 // Reset Timer
1398                 oc_cond_signal(g_scanningTimeCond);
1399             }
1400             oc_mutex_unlock(g_scanMutex);
1401
1402             OIC_LOG(DEBUG, TAG, "OUT");
1403             return CA_STATUS_OK;
1404         }
1405
1406         if (serverInfo->status == LE_STATUS_DISCOVERED)
1407         {
1408             if (CA_STATUS_OK != CAAddLEDataToList(&serverInfo->pendingDataList, data, dataLen))
1409             {
1410                 oc_mutex_unlock(g_LEServerListMutex);
1411                 OIC_LOG(ERROR, TAG, "Could not add data to pending list");
1412                 return CA_STATUS_FAILED;
1413             }
1414
1415             bt_gatt_client_h clientHandle = NULL;
1416             int32_t ret = bt_gatt_client_create(remoteAddress, &clientHandle);
1417             if (BT_ERROR_NONE != ret || NULL == clientHandle)
1418             {
1419                 OIC_LOG_V(ERROR, TAG,
1420                     "bt_gatt_client_create Failed with ret value [%s] ", CALEGetErrorMsg(ret));
1421                 CALEGattDisConnect(remoteAddress);
1422                 return CA_STATUS_FAILED;
1423             }
1424             serverInfo->clientHandle = clientHandle;
1425
1426             serverInfo->status = LE_STATUS_CONNECTION_INITIATED;
1427             if (CA_STATUS_OK != CALEGattInitiateConnection(serverInfo->remoteAddress))
1428             {
1429                 OIC_LOG_V(ERROR, TAG, "Could not initiate connection to [%s]", serverInfo->remoteAddress);
1430                 serverInfo->status = LE_STATUS_DISCOVERED;
1431                 CADestroyLEDataList(&serverInfo->pendingDataList);
1432                 oc_mutex_unlock(g_LEServerListMutex);
1433                 return CA_STATUS_FAILED;
1434             }
1435         }
1436         else if (serverInfo->status < LE_STATUS_SERVICES_DISCOVERED)
1437         {
1438             if (CA_STATUS_OK != CAAddLEDataToList(&serverInfo->pendingDataList, data, dataLen))
1439             {
1440                 oc_mutex_unlock(g_LEServerListMutex);
1441                 OIC_LOG(ERROR, TAG, "Could not add data to pending list");
1442                 return CA_STATUS_FAILED;
1443             }
1444         }
1445         else
1446         {
1447             if (CA_STATUS_OK != CAUpdateCharacteristicsToGattServerImpl(serverInfo, data, dataLen))
1448             {
1449                 OIC_LOG_V(ERROR, TAG, "Could not update characteristic to gatt server [%s]",
1450                           serverInfo->remoteAddress);
1451                 oc_mutex_unlock(g_LEServerListMutex);
1452                 return CA_STATUS_FAILED;
1453             }
1454         }
1455     }
1456     else if (LE_MULTICAST == type)
1457     {
1458         OIC_LOG(ERROR, TAG, "LE_MULTICAST type Not used");
1459     }
1460     oc_mutex_unlock(g_LEServerListMutex);
1461     OIC_LOG(DEBUG, TAG, "OUT");
1462     return CA_STATUS_OK;
1463 }
1464
1465 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
1466 {
1467     OIC_LOG(DEBUG,  TAG, "IN");
1468
1469     VERIFY_NON_NULL(data, TAG, "data is NULL");
1470
1471     if (0 >= dataLen)
1472     {
1473         OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input !");
1474         return CA_STATUS_INVALID_PARAM;
1475     }
1476
1477     oc_mutex_lock(g_LEServerListMutex);
1478     LEServerInfoList *curNode = g_LEServerList;
1479     while (curNode)
1480     {
1481         LEServerInfo *serverInfo = curNode->serverInfo;
1482         if (serverInfo->status == LE_STATUS_SERVICES_DISCOVERED)
1483         {
1484             if (CA_STATUS_OK != CAUpdateCharacteristicsToGattServerImpl(serverInfo, data, dataLen))
1485             {
1486                 OIC_LOG_V(ERROR, TAG, "Failed to update characteristics to gatt server [%s]",
1487                           serverInfo->remoteAddress);
1488             }
1489         }
1490         else if (serverInfo->status != LE_STATUS_INVALID)
1491         {
1492             if (CA_STATUS_OK != CAAddLEDataToList(&serverInfo->pendingDataList, data, dataLen))
1493             {
1494                 OIC_LOG(ERROR, TAG, "Failed to add to pending list");
1495             }
1496         }
1497         curNode = curNode->next;
1498     }
1499     oc_mutex_unlock(g_LEServerListMutex);
1500
1501     // Add the data to pending list.
1502     LEData *multicastData = (LEData *)OICCalloc(1, sizeof(LEData));
1503     if (NULL == multicastData)
1504     {
1505         OIC_LOG(ERROR, TAG, "Calloc failed");
1506         goto exit;
1507     }
1508     multicastData->data = OICCalloc(1, dataLen);
1509     if (NULL == multicastData->data)
1510     {
1511         OIC_LOG(ERROR, TAG, "Calloc failed");
1512         goto exit;
1513     }
1514     memcpy(multicastData->data, data, dataLen);
1515     multicastData->dataLength = dataLen;
1516
1517     oc_mutex_lock(g_multicastDataListMutex);
1518     if (NULL == g_multicastDataList)
1519     {
1520         g_multicastDataList = u_arraylist_create();
1521     }
1522     u_arraylist_add(g_multicastDataList, (void *)multicastData);
1523     oc_mutex_unlock(g_multicastDataListMutex);
1524
1525     // Start the scanning, if not started, else reset timer
1526     oc_mutex_lock(g_scanMutex);
1527     if (!g_isMulticastInProgress && !g_isUnicastScanInProgress)
1528     {
1529         CAResult_t result = CALEGattStartDeviceScanning();
1530         if (CA_STATUS_OK != result)
1531         {
1532             oc_mutex_unlock(g_scanMutex);
1533             OIC_LOG(ERROR, TAG, "CALEGattStartDeviceScanning Failed");
1534             goto exit;
1535         }
1536         g_isMulticastInProgress = true;
1537         // Start the timer by signalling it
1538         oc_cond_signal(g_startTimerCond);
1539     }
1540     else
1541     {
1542         g_isMulticastInProgress = true;
1543         // Reset timer
1544         oc_cond_signal(g_scanningTimeCond);
1545     }
1546     oc_mutex_unlock(g_scanMutex);
1547
1548 exit:
1549     OIC_LOG(DEBUG, TAG, "OUT ");
1550     return CA_STATUS_OK;
1551 }