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