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