Merge branch 'easysetup'
[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 "camutex.h"
34 #include "uarraylist.h"
35 #include "caqueueingthread.h"
36 #include "caadapterutils.h"
37 #include "cafragmentation.h"
38 #include "cagattservice.h"
39 #include "oic_string.h"
40 #include "oic_malloc.h"
41
42 /**
43  * Logging tag for module name.
44  */
45 #define TAG "OIC_CA_LE_CLIENT"
46
47 #define MICROSECS_PER_SEC 1000000
48 #define WAIT_TIME_WRITE_CHARACTERISTIC 10 * MICROSECS_PER_SEC
49
50 uint64_t const TIMEOUT = 30 * MICROSECS_PER_SEC;
51
52 /**
53  * Flag to check if multicast is already in progress.
54  */
55 static bool g_isMulticastInProgress = false;
56
57 /**
58  * Pending multicast data list to be sent.
59  */
60 static u_arraylist_t *g_multicastDataList = NULL;
61
62 /**
63  * Mutex to synchronize the access to Pending multicast data list.
64  */
65 static ca_mutex g_multicastDataListMutex = NULL;
66
67 /**
68  * List of devices discovered.
69  */
70 static u_arraylist_t *g_deviceDiscoveredList = NULL;
71
72 /**
73  * Mutex to synchronize the access to discovered devices list.
74  */
75 static ca_mutex g_deviceDiscoveredListMutex = NULL;
76
77 /**
78  * Condition to start the timer for scanning.
79  */
80 static ca_cond g_startTimerCond = NULL;
81
82 /**
83  * Condition for scanning Time interval.
84  */
85 static ca_cond g_scanningTimeCond = NULL;
86
87 /**
88  * This contains the list of OIC services a client connect tot.
89  */
90 static LEServerInfoList *g_LEServerList = NULL;
91
92 /**
93  * Mutex to synchronize access to BleServiceList.
94  */
95 static ca_mutex g_LEServerListMutex = NULL;
96
97 /**
98  * Boolean variable to keep the state of the GATT Client.
99  */
100 static bool g_isLEGattClientStarted = false;
101
102 /**
103  * Mutex to synchronize access to the requestResponse callback to be called
104  * when the data needs to be sent from GATTClient.
105  */
106 static ca_mutex g_LEReqRespClientCbMutex = NULL;
107
108 /**
109  * Mutex to synchronize access to the requestResponse callback to be called
110  * when the data needs to be sent from GATTClient.
111  */
112 static ca_mutex g_LEClientConnectMutex = NULL;
113
114 /**
115  * Mutex to synchronize the calls to be done to the platform from GATTClient
116  * interfaces from different threads.
117  */
118 static ca_mutex g_LEClientStateMutex = NULL;
119
120 /**
121  * Mutex to synchronize the task to be pushed to thread pool.
122  */
123 static ca_mutex g_LEClientThreadPoolMutex = NULL;
124
125 /**
126  * Mutex to synchronize the task to write characteristic one packet after another.
127  */
128 static ca_mutex g_threadWriteCharacteristicMutex = NULL;
129
130 /**
131  * Condition for Writing characteristic.
132  */
133 static ca_cond g_threadWriteCharacteristicCond = NULL;
134
135 /**
136  * Flag to check status of write characteristic.
137  */
138 static bool g_isSignalSetFlag = false;
139
140 /**
141  * Maintains the callback to be notified on receival of network packets from other
142  *           BLE devices
143  */
144 static CABLEDataReceivedCallback g_LEClientDataReceivedCallback = NULL;
145
146 /**
147  * callback to update the error to le adapter
148  */
149 static CABLEErrorHandleCallback g_clientErrorCallback;
150
151 /**
152  * gmainLoop to manage the threads to receive the callback from the platfrom.
153  */
154 static GMainLoop *g_eventLoop = NULL;
155
156 /**
157  * Reference to threadpool
158  */
159 static ca_thread_pool_t g_LEClientThreadPool = NULL;
160
161 bt_scan_filter_h g_scanFilter = NULL;
162
163 bool CALEIsDeviceDiscovered(const char * address)
164 {
165     OIC_LOG(DEBUG, TAG, "IN");
166     if (g_deviceDiscoveredList)
167     {
168         ca_mutex_lock(g_deviceDiscoveredListMutex);
169         uint32_t arrayLength = u_arraylist_length(g_deviceDiscoveredList);
170         for (int i = 0; i < arrayLength; i++)
171         {
172             char *deviceAddr = u_arraylist_get(g_deviceDiscoveredList, i);
173             if (0 == strcasecmp(deviceAddr, address))
174             {
175                 OIC_LOG(DEBUG, TAG, "Device Found");
176                 ca_mutex_unlock(g_deviceDiscoveredListMutex);
177                 return true;
178             }
179
180         }
181         ca_mutex_unlock(g_deviceDiscoveredListMutex);
182     }
183     OIC_LOG(DEBUG, TAG, "OUT");
184     return false;
185 }
186
187 void CALEGattCharacteristicChangedCb(bt_gatt_h characteristic,
188                                      char *value,
189                                      int valueLen, void *userData)
190 {
191     OIC_LOG(DEBUG, TAG, "IN");
192     OIC_LOG_V(DEBUG, TAG, "Changed characteristic value length [%d]", valueLen);
193
194     ca_mutex_lock(g_LEReqRespClientCbMutex);
195     if (NULL == g_LEClientDataReceivedCallback)
196     {
197         OIC_LOG(ERROR, TAG, "Request response callback is not set");
198         ca_mutex_unlock(g_LEReqRespClientCbMutex);
199         return;
200     }
201
202     uint32_t sentLength = 0;
203     g_LEClientDataReceivedCallback(userData, (uint8_t *)value, valueLen, &sentLength);
204
205     OIC_LOG_V(DEBUG, TAG, "Sent data Length is %d", sentLength);
206
207     ca_mutex_unlock(g_LEReqRespClientCbMutex);
208
209     OIC_LOG(DEBUG, TAG, "OUT");
210 }
211
212 void CALEGattCharacteristicWriteCb(int result, bt_gatt_h reqHandle, void *userData)
213 {
214     OIC_LOG(DEBUG, TAG, "IN ");
215
216     if (BT_ERROR_NONE != result)
217     {
218         OIC_LOG(ERROR, TAG, "Write failed Need Retry ");
219         //Need to Implement retry mechanism
220     }
221     else
222     {
223         ca_mutex_lock(g_threadWriteCharacteristicMutex);
224         OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
225         g_isSignalSetFlag = true;
226         ca_cond_signal(g_threadWriteCharacteristicCond);
227         ca_mutex_unlock(g_threadWriteCharacteristicMutex);
228     }
229
230     OIC_LOG(DEBUG, TAG, "OUT ");
231 }
232
233 void CALEGattConnectionStateChanged(bool connected, const char *remoteAddress)
234 {
235     OIC_LOG(DEBUG, TAG, "IN ");
236
237     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
238
239     // Start the scanning.
240     CAResult_t ret = CALEGattStartDeviceScanning();
241     if (CA_STATUS_OK != ret)
242     {
243         OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed");
244     }
245     // Signal the start timer.
246     ca_cond_signal(g_scanningTimeCond);
247
248     if (!connected)
249     {
250         OIC_LOG_V(DEBUG, TAG, "DisConnected from [%s] ", remoteAddress);
251     }
252     else
253     {
254         OIC_LOG_V(DEBUG, TAG, "Connected to [%s] ", remoteAddress);
255
256         char *addr = OICStrdup(remoteAddress);
257
258         ca_mutex_lock(g_LEClientThreadPoolMutex);
259         if (NULL == g_LEClientThreadPool)
260         {
261             OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
262             OICFree(addr);
263             ca_mutex_unlock(g_LEClientThreadPoolMutex);
264             return;
265         }
266
267         ret = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread,
268                                       addr);
269         if (CA_STATUS_OK != ret)
270         {
271             OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", ret);
272             OICFree(addr);
273         }
274         ca_mutex_unlock(g_LEClientThreadPoolMutex);
275     }
276     OIC_LOG(DEBUG, TAG, "OUT");
277 }
278
279 void CALEAdapterScanResultCb(int result, bt_adapter_le_device_scan_result_info_s *scanInfo,
280                              void *userData)
281 {
282     OIC_LOG(DEBUG, TAG, "IN");
283
284     VERIFY_NON_NULL_VOID(scanInfo, TAG, "scanInfo");
285     VERIFY_NON_NULL_VOID(scanInfo->remote_address, TAG, "scanInfo->remote_address");
286
287     OIC_LOG_V(DEBUG, TAG, "Remote Address [%s]", scanInfo->remote_address);
288     OIC_LOG_V(DEBUG, TAG, "Scan Result [%d]", result);
289     OIC_LOG_V(DEBUG, TAG,
290               " Adv data len [%d] Scan data len[%d]RSSI [%d] Addr_type [%d] ",
291               scanInfo->adv_data_len, scanInfo->scan_data_len, scanInfo->rssi,
292               scanInfo->address_type);
293
294     // Check if device is already discovered.
295     if (CALEIsDeviceDiscovered(scanInfo->remote_address))
296     {
297         OIC_LOG_V(INFO, TAG, "Device[%s] is already discovered", scanInfo->remote_address);
298         return;
299     }
300
301     // Stop the scan before invoking bt_gatt_connect().
302     CALEGattStopDeviceScanning();
303
304     ca_mutex_lock(g_deviceDiscoveredListMutex);
305     // Add the the device Discovered list.
306     if (NULL == g_deviceDiscoveredList)
307     {
308         g_deviceDiscoveredList = u_arraylist_create();
309     }
310     char *deviceAddr = OICStrdup(scanInfo->remote_address);
311     u_arraylist_add(g_deviceDiscoveredList, (void *) deviceAddr);
312     ca_mutex_unlock(g_deviceDiscoveredListMutex);
313
314     size_t len = strlen(scanInfo->remote_address);
315
316     char *addr = (char *)OICMalloc(sizeof(char) * (len + 1));
317     VERIFY_NON_NULL_VOID(addr, TAG, "Malloc failed");
318
319     strncpy(addr, scanInfo->remote_address, len + 1);
320
321     OIC_LOG_V(DEBUG, TAG,
322               "Trying to do Gatt connection to [%s]", addr);
323
324     ca_mutex_lock(g_LEClientThreadPoolMutex);
325     if (NULL == g_LEClientThreadPool)
326     {
327         OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
328         OICFree(addr);
329         ca_mutex_unlock(g_LEClientThreadPoolMutex);
330         return;
331     }
332
333     CAResult_t res = ca_thread_pool_add_task(g_LEClientThreadPool, CAGattConnectThread, addr);
334     if (CA_STATUS_OK != res)
335     {
336         OIC_LOG_V(ERROR, TAG,
337                   "ca_thread_pool_add_task failed with ret [%d]", res);
338         OICFree(addr);
339     }
340     ca_mutex_unlock(g_LEClientThreadPoolMutex);
341     OIC_LOG(DEBUG, TAG, "OUT");
342 }
343
344 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
345 {
346     OIC_LOG(DEBUG, TAG, "IN");
347
348     ca_mutex_lock(g_LEClientThreadPoolMutex);
349     g_LEClientThreadPool = handle;
350     ca_mutex_unlock(g_LEClientThreadPoolMutex);
351
352     OIC_LOG(DEBUG, TAG, "OUT");
353 }
354
355 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
356 {
357     OIC_LOG(DEBUG, TAG, "IN");
358
359     ca_mutex_lock(g_LEReqRespClientCbMutex);
360
361     g_LEClientDataReceivedCallback = callback;
362
363     ca_mutex_unlock(g_LEReqRespClientCbMutex);
364
365     OIC_LOG(DEBUG, TAG, "OUT");
366 }
367
368 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
369 {
370     g_clientErrorCallback = callback;
371 }
372
373 CAResult_t CAStartLEGattClient()
374 {
375     OIC_LOG(DEBUG, TAG, "IN");
376
377     ca_mutex_lock(g_LEClientThreadPoolMutex);
378     if (NULL == g_LEClientThreadPool)
379     {
380         OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL");
381         CATerminateGattClientMutexVariables();
382         ca_mutex_unlock(g_LEClientThreadPoolMutex);
383         return CA_STATUS_FAILED;
384     }
385
386     CAResult_t result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartLEGattClientThread,
387                                      NULL);
388     if (CA_STATUS_OK != result)
389     {
390         OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed");
391         CATerminateGattClientMutexVariables();
392         ca_mutex_unlock(g_LEClientThreadPoolMutex);
393         return CA_STATUS_FAILED;
394     }
395     ca_mutex_unlock(g_LEClientThreadPoolMutex);
396
397     OIC_LOG(DEBUG, TAG, "OUT");
398     return CA_STATUS_OK;
399 }
400
401 void CAStartLEGattClientThread(void *data)
402 {
403     OIC_LOG(DEBUG, TAG, "IN");
404
405     ca_mutex_lock(g_LEClientStateMutex);
406     if (true  == g_isLEGattClientStarted)
407     {
408         OIC_LOG(ERROR, TAG, "Gatt Client is already running!!");
409         ca_mutex_unlock(g_LEClientStateMutex);
410         return;
411     }
412
413     CAResult_t  result = CALEGattSetCallbacks();
414     if (CA_STATUS_OK != result)
415     {
416         OIC_LOG(ERROR, TAG, "CABleGattSetCallbacks Failed");
417         ca_mutex_unlock(g_LEClientStateMutex);
418         CATerminateLEGattClient();
419         return;
420     }
421
422     g_isLEGattClientStarted = true;
423     ca_mutex_unlock(g_LEClientStateMutex);
424
425     ca_mutex_lock(g_LEClientThreadPoolMutex);
426     if (NULL == g_LEClientThreadPool)
427     {
428         OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL");
429         CATerminateGattClientMutexVariables();
430         ca_mutex_unlock(g_LEClientThreadPoolMutex);
431         return;
432     }
433
434     result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartTimerThread,
435                                      NULL);
436     if (CA_STATUS_OK != result)
437     {
438         OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed");
439         ca_mutex_unlock(g_LEClientThreadPoolMutex);
440         return;
441     }
442     ca_mutex_unlock(g_LEClientThreadPoolMutex);
443
444     OIC_LOG(DEBUG, TAG, "Giving the control to threadPool");
445
446     GMainContext *thread_context = g_main_context_new();
447
448     g_eventLoop = g_main_loop_new(thread_context, FALSE);
449
450     g_main_context_push_thread_default(thread_context);
451
452     g_main_loop_run(g_eventLoop);
453
454     OIC_LOG(DEBUG, TAG, "OUT");
455 }
456
457 void CAStartTimerThread(void *data)
458 {
459     OIC_LOG(DEBUG, TAG, "IN");
460     while (g_isLEGattClientStarted)
461     {
462         ca_mutex_lock(g_multicastDataListMutex);
463         if (!g_isMulticastInProgress)
464         {
465             OIC_LOG(DEBUG, TAG, "waiting....");
466             ca_cond_wait(g_startTimerCond, g_multicastDataListMutex);
467             OIC_LOG(DEBUG, TAG, "Wake up");
468             g_isMulticastInProgress = true;
469         }
470
471         // Timed conditional wait for stopping the scan.
472         CAWaitResult_t ret = ca_cond_wait_for(g_scanningTimeCond, g_multicastDataListMutex,
473                                               TIMEOUT);
474         if (CA_WAIT_TIMEDOUT == ret)
475         {
476             OIC_LOG(DEBUG, TAG, "Scan is timed Out");
477             // Call stop scan.
478             CALEGattStopDeviceScanning();
479
480             // Clear the data list and device list.
481             u_arraylist_destroy(g_multicastDataList);
482             g_multicastDataList = NULL;
483
484             ca_mutex_lock(g_deviceDiscoveredListMutex);
485             u_arraylist_destroy(g_deviceDiscoveredList);
486             g_deviceDiscoveredList = NULL;
487             ca_mutex_unlock(g_deviceDiscoveredListMutex);
488
489             g_isMulticastInProgress = false;
490         }
491         ca_mutex_unlock(g_multicastDataListMutex);
492     }
493
494     OIC_LOG(DEBUG, TAG, "OUT");
495 }
496
497 void CAStopLEGattClient()
498 {
499     OIC_LOG(DEBUG,  TAG, "IN");
500
501     ca_mutex_lock(g_LEClientStateMutex);
502
503     if (false == g_isLEGattClientStarted)
504     {
505         OIC_LOG(ERROR, TAG, "Gatt Client is not running to stop");
506         ca_mutex_unlock(g_LEClientStateMutex);
507         return;
508     }
509
510     CALEGattUnSetCallbacks();
511
512     CALEGattStopDeviceScanning();
513
514     g_isLEGattClientStarted = false;
515
516     // Signal the conditions waiting in Start timer.
517     ca_cond_signal(g_startTimerCond);
518     ca_cond_signal(g_scanningTimeCond);
519
520     // Destroy the multicast data list and device list if not empty.
521     if (NULL != g_multicastDataList)
522     {
523         ca_mutex_lock(g_multicastDataListMutex);
524         u_arraylist_destroy(g_multicastDataList);
525         g_multicastDataList = NULL;
526         ca_mutex_unlock(g_multicastDataListMutex);
527     }
528
529     if (NULL != g_deviceDiscoveredList)
530     {
531         ca_mutex_lock(g_deviceDiscoveredListMutex);
532         u_arraylist_destroy(g_deviceDiscoveredList);
533         g_deviceDiscoveredList = NULL;
534         ca_mutex_unlock(g_deviceDiscoveredListMutex);
535     }
536
537     ca_mutex_lock(g_LEServerListMutex);
538     CAFreeLEServerList(g_LEServerList);
539     g_LEServerList = NULL;
540     ca_mutex_unlock(g_LEServerListMutex);
541
542     ca_mutex_lock(g_threadWriteCharacteristicMutex);
543     ca_cond_signal(g_threadWriteCharacteristicCond);
544     ca_mutex_unlock(g_threadWriteCharacteristicMutex);
545
546     CAResetRegisteredServiceCount();
547
548     GMainContext  *context_event_loop = NULL;
549     // Required for waking up the thread which is running in gmain loop
550     if (NULL != g_eventLoop)
551     {
552         context_event_loop = g_main_loop_get_context(g_eventLoop);
553     }
554     if (context_event_loop)
555     {
556         OIC_LOG_V(DEBUG,  TAG, "g_eventLoop context %x", context_event_loop);
557         g_main_context_wakeup(context_event_loop);
558
559         // Kill g main loops and kill threads.
560         g_main_loop_quit(g_eventLoop);
561     }
562     else
563     {
564         OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL");
565     }
566
567     ca_mutex_unlock(g_LEClientStateMutex);
568
569     OIC_LOG(DEBUG,  TAG, "OUT");
570 }
571
572 CAResult_t CAInitializeLEGattClient()
573 {
574     OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
575     CAResult_t res = CAInitGattClientMutexVariables();
576     if (CA_STATUS_OK != res)
577     {
578         OIC_LOG(ERROR, TAG, "CAInitGattClientMutexVariables failed!");
579         CATerminateGattClientMutexVariables();
580         return CA_STATUS_FAILED;
581     }
582     return res;
583 }
584
585 void CATerminateLEGattClient()
586 {
587     OIC_LOG(DEBUG,  TAG, "IN");
588
589     CATerminateGattClientMutexVariables();
590
591     OIC_LOG(DEBUG,  TAG, "OUT");
592 }
593
594 CAResult_t CAInitGattClientMutexVariables()
595 {
596     OIC_LOG(DEBUG,  TAG, "IN");
597     if (NULL == g_LEClientStateMutex)
598     {
599         g_LEClientStateMutex = ca_mutex_new();
600         if (NULL == g_LEClientStateMutex)
601         {
602             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
603             return CA_STATUS_FAILED;
604         }
605     }
606
607     if (NULL == g_LEServerListMutex)
608     {
609         g_LEServerListMutex = ca_mutex_new();
610         if (NULL == g_LEServerListMutex)
611         {
612             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
613             return CA_STATUS_FAILED;
614         }
615     }
616
617     if (NULL == g_LEReqRespClientCbMutex)
618     {
619         g_LEReqRespClientCbMutex = ca_mutex_new();
620         if (NULL == g_LEReqRespClientCbMutex)
621         {
622             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
623             return CA_STATUS_FAILED;
624         }
625     }
626
627     if (NULL == g_LEClientThreadPoolMutex)
628     {
629         g_LEClientThreadPoolMutex = ca_mutex_new();
630         if (NULL == g_LEClientThreadPoolMutex)
631         {
632             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
633             return CA_STATUS_FAILED;
634         }
635     }
636
637     if (NULL == g_LEClientConnectMutex)
638     {
639         g_LEClientConnectMutex = ca_mutex_new();
640         if (NULL == g_LEClientConnectMutex)
641         {
642             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
643             return CA_STATUS_FAILED;
644         }
645     }
646
647     if (NULL == g_multicastDataListMutex)
648     {
649         g_multicastDataListMutex = ca_mutex_new();
650         if (NULL == g_multicastDataListMutex)
651         {
652             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
653             return CA_STATUS_FAILED;
654         }
655     }
656
657     if (NULL == g_deviceDiscoveredListMutex)
658     {
659         g_deviceDiscoveredListMutex = ca_mutex_new();
660         if (NULL == g_deviceDiscoveredListMutex)
661         {
662             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
663             return CA_STATUS_FAILED;
664         }
665     }
666
667     if (NULL == g_threadWriteCharacteristicMutex)
668     {
669         g_threadWriteCharacteristicMutex = ca_mutex_new();
670         if (NULL == g_threadWriteCharacteristicMutex)
671         {
672             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
673             return CA_STATUS_FAILED;
674         }
675     }
676
677     if (NULL == g_startTimerCond)
678     {
679         g_startTimerCond = ca_cond_new();
680         if (NULL == g_startTimerCond)
681         {
682             OIC_LOG(ERROR, TAG, "ca_cond_new failed");
683             return CA_STATUS_FAILED;
684         }
685     }
686
687     if (NULL == g_scanningTimeCond)
688     {
689         g_scanningTimeCond = ca_cond_new();
690         if (NULL == g_scanningTimeCond)
691         {
692             OIC_LOG(ERROR, TAG, "ca_cond_new failed");
693             return CA_STATUS_FAILED;
694         }
695     }
696
697     if (NULL == g_threadWriteCharacteristicCond)
698     {
699         g_threadWriteCharacteristicCond = ca_cond_new();
700         if (NULL == g_threadWriteCharacteristicCond)
701         {
702             OIC_LOG(ERROR, TAG, "ca_cond_new failed");
703             return CA_STATUS_FAILED;
704         }
705     }
706
707     OIC_LOG(DEBUG,  TAG, "OUT");
708     return CA_STATUS_OK;
709 }
710
711 void CATerminateGattClientMutexVariables()
712 {
713     OIC_LOG(DEBUG,  TAG, "IN");
714
715     ca_mutex_free(g_LEClientStateMutex);
716     g_LEClientStateMutex = NULL;
717
718     ca_mutex_free(g_LEServerListMutex);
719     g_LEServerListMutex = NULL;
720
721     ca_mutex_free(g_LEReqRespClientCbMutex);
722     g_LEReqRespClientCbMutex = NULL;
723
724     ca_mutex_free(g_LEClientConnectMutex);
725     g_LEClientConnectMutex = NULL;
726
727     ca_mutex_free(g_LEClientThreadPoolMutex);
728     g_LEClientThreadPoolMutex = NULL;
729
730     ca_mutex_free(g_multicastDataListMutex);
731     g_multicastDataListMutex = NULL;
732
733     ca_mutex_free(g_deviceDiscoveredListMutex);
734     g_deviceDiscoveredListMutex = NULL;
735
736     ca_mutex_free(g_threadWriteCharacteristicMutex);
737     g_threadWriteCharacteristicMutex = NULL;
738
739     ca_cond_free(g_startTimerCond);
740     g_startTimerCond = NULL;
741
742     ca_cond_free(g_scanningTimeCond);
743     g_scanningTimeCond = NULL;
744
745     ca_cond_free(g_threadWriteCharacteristicCond);
746     g_threadWriteCharacteristicCond = NULL;
747     g_isSignalSetFlag = false;
748
749     OIC_LOG(DEBUG,  TAG, "OUT");
750 }
751
752 CAResult_t CALEGattSetCallbacks()
753 {
754     OIC_LOG(DEBUG, TAG, "IN");
755
756     OIC_LOG(DEBUG, TAG, "OUT");
757     return CA_STATUS_OK;
758 }
759
760 void CALEGattUnSetCallbacks()
761 {
762     OIC_LOG(DEBUG, TAG, "IN");
763
764     bt_gatt_unset_connection_state_changed_cb();
765
766     int numOfServersConnected = CAGetRegisteredServiceCount();
767     LEServerInfo *leServerInfo = NULL;
768
769     for (int32_t index = 0; index < numOfServersConnected; index++)
770     {
771         CAGetLEServerInfoByPosition(g_LEServerList, index, &leServerInfo);
772         bt_gatt_client_unset_characteristic_value_changed_cb(leServerInfo->readChar);
773     }
774     OIC_LOG(DEBUG, TAG, "OUT");
775 }
776
777 CAResult_t CALEGattStartDeviceScanning()
778 {
779     OIC_LOG(DEBUG, TAG, "IN");
780
781     int ret = bt_adapter_le_start_scan(CALEAdapterScanResultCb, NULL);
782     if(BT_ERROR_NONE != ret)
783     {
784         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_scan failed[%s]",
785                   CALEGetErrorMsg(ret));
786         return CA_STATUS_FAILED;
787     }
788
789     OIC_LOG(DEBUG, TAG, "OUT");
790     return CA_STATUS_OK;
791 }
792
793 void CALEGattStopDeviceScanning()
794 {
795     OIC_LOG(DEBUG, TAG, "IN");
796
797     int ret = bt_adapter_le_stop_scan();
798     if (BT_ERROR_NONE != ret)
799     {
800         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_stop_scan failed[%s]",
801                   CALEGetErrorMsg(ret));
802     }
803
804     OIC_LOG(DEBUG, TAG, "OUT");
805 }
806
807 void CAGattConnectThread (void *remoteAddress)
808 {
809     OIC_LOG(DEBUG, TAG, "IN ");
810
811     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
812
813     char *address  = (char *)remoteAddress;
814
815     OIC_LOG_V(DEBUG, TAG, "remote address is [%s]", address);
816
817     CAResult_t result = CALEGattConnect(address);
818
819     if (CA_STATUS_OK != result)
820     {
821         OIC_LOG_V(ERROR, TAG, "bt_gatt_connect failed for [%s]", address);
822     }
823
824     OICFree(address);
825
826     OIC_LOG(DEBUG, TAG, "OUT");
827 }
828
829 CAResult_t CALEGattConnect(const char *remoteAddress)
830 {
831     OIC_LOG(DEBUG, TAG, "IN");
832
833     VERIFY_NON_NULL_RET(remoteAddress, TAG,
834                         "remote address is NULL", CA_STATUS_FAILED);
835
836     ca_mutex_lock(g_LEClientConnectMutex);
837     bool isConnected = false;
838     int ret = bt_device_is_profile_connected(remoteAddress, BT_PROFILE_GATT, &isConnected);
839     if (BT_ERROR_NONE != ret)
840     {
841         OIC_LOG_V(ERROR, TAG, "bt_device_is_profile_connected Failed with ret value [%s] ",
842                   CALEGetErrorMsg(ret));
843         ca_mutex_unlock(g_LEClientConnectMutex);
844         return CA_STATUS_FAILED;
845     }
846
847     CAResult_t result = CA_STATUS_OK;
848     if (!isConnected)
849     {
850         ret = bt_gatt_connect(remoteAddress, true);
851
852         if (BT_ERROR_NONE != ret)
853         {
854             OIC_LOG_V(ERROR, TAG, "bt_gatt_connect Failed with ret value [%s] ",
855                       CALEGetErrorMsg(ret));
856             ca_mutex_unlock(g_LEClientConnectMutex);
857             return CA_STATUS_FAILED;
858         }
859     }
860     else
861     {
862         OIC_LOG_V(INFO, TAG, "Remote address[%s] is already connected",
863                   remoteAddress);
864         char *addr = OICStrdup(remoteAddress);
865         if (NULL == addr)
866         {
867             OIC_LOG(ERROR, TAG, "addr is NULL");
868             ca_mutex_unlock(g_LEClientConnectMutex);
869             return CA_STATUS_FAILED;
870         }
871
872         ca_mutex_lock(g_LEClientThreadPoolMutex);
873         if (NULL == g_LEClientThreadPool)
874         {
875             OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
876             OICFree(addr);
877             ca_mutex_unlock(g_LEClientThreadPoolMutex);
878             ca_mutex_unlock(g_LEClientConnectMutex);
879             return CA_STATUS_FAILED;
880         }
881
882         result = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread,
883                                       addr);
884         if (CA_STATUS_OK != result)
885         {
886             OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", result);
887             OICFree(addr);
888         }
889         ca_mutex_unlock(g_LEClientThreadPoolMutex);
890     }
891     ca_mutex_unlock(g_LEClientConnectMutex);
892
893     OIC_LOG(DEBUG, TAG, "OUT");
894     return result;
895 }
896
897 CAResult_t CALEGattDisConnect(const char *remoteAddress)
898 {
899     OIC_LOG(DEBUG, TAG, "IN");
900
901     VERIFY_NON_NULL_RET(remoteAddress, TAG,
902                         "remote address is NULL", CA_STATUS_FAILED);
903
904     int ret = bt_gatt_disconnect(remoteAddress);
905
906     if (BT_ERROR_NONE != ret)
907     {
908         OIC_LOG_V(ERROR, TAG, "bt_gatt_disconnect Failed with ret value [%d] ",
909                   CALEGetErrorMsg(ret));
910         return CA_STATUS_FAILED;
911     }
912
913     OIC_LOG(DEBUG, TAG, "OUT");
914     return CA_STATUS_OK;
915 }
916
917 void CADiscoverLEServicesThread (void *remoteAddress)
918 {
919     OIC_LOG(DEBUG, TAG, "IN");
920
921     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
922
923     char *address  = (char *)remoteAddress;
924
925     CAResult_t result = CALEGattDiscoverServices(address);
926     if (CA_STATUS_OK != result)
927     {
928         OIC_LOG(ERROR, TAG, "CALEGattDiscoverServices failed");
929     }
930
931     OICFree(address);
932     OIC_LOG(DEBUG, TAG, "OUT");
933 }
934
935 CAResult_t CALEGattDiscoverServices(const char *remoteAddress)
936 {
937     OIC_LOG(DEBUG, TAG, "IN");
938
939     VERIFY_NON_NULL_RET(remoteAddress, TAG,
940                         "remote address is NULL", CA_STATUS_FAILED);
941
942     bt_gatt_client_h clientHandle = NULL;
943     int32_t ret = bt_gatt_client_create(remoteAddress, &clientHandle);
944     if (BT_ERROR_NONE != ret || NULL == clientHandle)
945     {
946         OIC_LOG_V(ERROR, TAG,
947                   "bt_gatt_client_create Failed with ret value [%s] ", CALEGetErrorMsg(ret));
948         CALEGattDisConnect(remoteAddress);
949         return CA_STATUS_FAILED;
950     }
951
952     bt_gatt_h serviceHandle = NULL;
953     ret = bt_gatt_client_get_service(clientHandle, CA_GATT_SERVICE_UUID, &serviceHandle);
954     if (BT_ERROR_NONE != ret || NULL == serviceHandle)
955     {
956         OIC_LOG_V(ERROR, TAG,
957                   "bt_gatt_client_get_service Failed with ret value [%s] ", CALEGetErrorMsg(ret));
958         bt_gatt_client_destroy(clientHandle);
959         CALEGattDisConnect(remoteAddress);
960         return CA_STATUS_FAILED;
961     }
962
963     // Server will read data on this characteristic.
964     bt_gatt_h writeChrHandle = NULL;
965     ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_REQUEST_CHRC_UUID,
966                                              &writeChrHandle);
967     if (BT_ERROR_NONE != ret || NULL == writeChrHandle)
968     {
969         OIC_LOG_V(ERROR, TAG,
970                   "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
971                   CALEGetErrorMsg(ret));
972         bt_gatt_client_destroy(clientHandle);
973         CALEGattDisConnect(remoteAddress);
974         return CA_STATUS_FAILED;
975     }
976
977     // Server will notify data on this characteristic.
978     bt_gatt_h readChrHandle = NULL;
979     ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_RESPONSE_CHRC_UUID,
980                                              &readChrHandle);
981     if (BT_ERROR_NONE != ret || NULL == readChrHandle)
982     {
983         OIC_LOG_V(ERROR, TAG,
984                   "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
985                   CALEGetErrorMsg(ret));
986         bt_gatt_client_destroy(clientHandle);
987         CALEGattDisConnect(remoteAddress);
988         return CA_STATUS_FAILED;
989     }
990
991
992     //TODO: This data has to be freed while unsetting the callback.
993     char *addr = OICStrdup(remoteAddress);
994     ret = bt_gatt_client_set_characteristic_value_changed_cb(readChrHandle,
995                                                              CALEGattCharacteristicChangedCb,
996                                                              (void *)addr);
997     if (BT_ERROR_NONE != ret)
998     {
999         OIC_LOG_V(ERROR, TAG,
1000                   "bt_gatt_client_set_characteristic_value_changed_cb Failed with ret value [%s]",
1001                   CALEGetErrorMsg(ret));
1002         bt_gatt_client_destroy(clientHandle);
1003         CALEGattDisConnect(remoteAddress);
1004         return CA_STATUS_FAILED;
1005     }
1006
1007     LEServerInfo *serverInfo = (LEServerInfo *)OICCalloc(1, sizeof(LEServerInfo));
1008     if (NULL == serverInfo)
1009     {
1010         OIC_LOG(ERROR, TAG, "Malloc failed");
1011         CALEGattDisConnect(remoteAddress);
1012         return CA_MEMORY_ALLOC_FAILED;
1013     }
1014     serverInfo->clientHandle = clientHandle;
1015     serverInfo->serviceHandle = serviceHandle;
1016     serverInfo->readChar = readChrHandle;
1017     serverInfo->writeChar = writeChrHandle;
1018     serverInfo->remoteAddress = OICStrdup(remoteAddress);
1019
1020     ca_mutex_lock(g_LEServerListMutex);
1021     CAResult_t result = CAAddLEServerInfoToList(&g_LEServerList, serverInfo);
1022     if (CA_STATUS_OK != result)
1023     {
1024         OIC_LOG(ERROR, TAG, "CAAddBLEClientInfoToList failed");
1025         bt_gatt_client_destroy(clientHandle);
1026         CALEGattDisConnect(remoteAddress);
1027         return CA_STATUS_FAILED;
1028     }
1029     ca_mutex_unlock(g_LEServerListMutex);
1030
1031     // Send the data of pending multicast data list if any.
1032     if (g_multicastDataList)
1033     {
1034         ca_mutex_lock(g_multicastDataListMutex);
1035         uint32_t arrayLength = u_arraylist_length(g_multicastDataList);
1036         for (int i = 0; i < arrayLength; i++)
1037         {
1038             CALEData_t *multicastData = u_arraylist_get(g_multicastDataList, i);
1039             if (NULL == multicastData)
1040             {
1041                 OIC_LOG(DEBUG, TAG, "multicastData is NULL");
1042                 continue;
1043             }
1044             CAUpdateCharacteristicsToGattServer(remoteAddress, multicastData->data,
1045                                                 multicastData->dataLen, LE_UNICAST, 0);
1046         }
1047         ca_mutex_unlock(g_multicastDataListMutex);
1048     }
1049
1050     OIC_LOG(DEBUG, TAG, "OUT");
1051     return CA_STATUS_OK;
1052 }
1053
1054 CAResult_t  CAUpdateCharacteristicsToGattServer(const char *remoteAddress,
1055                                                 const uint8_t *data, const uint32_t dataLen,
1056                                                 CALETransferType_t type, const int32_t position)
1057 {
1058     OIC_LOG(DEBUG, TAG, "IN");
1059
1060     VERIFY_NON_NULL(data, TAG, "data is NULL");
1061
1062     if (0 >= dataLen)
1063     {
1064         OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input!");
1065         return CA_STATUS_INVALID_PARAM;
1066     }
1067
1068     LEServerInfo *leServerInfo = NULL;
1069     CAResult_t ret =  CA_STATUS_FAILED;
1070
1071     ca_mutex_lock(g_LEServerListMutex);
1072     if (LE_UNICAST == type)
1073     {
1074         ret = CAGetLEServerInfo(g_LEServerList, remoteAddress, &leServerInfo);
1075     }
1076     else if (LE_MULTICAST == type)
1077     {
1078         ret = CAGetLEServerInfoByPosition(g_LEServerList, position, &leServerInfo);
1079     }
1080     ca_mutex_unlock(g_LEServerListMutex);
1081
1082     if (CA_STATUS_OK != ret)
1083     {
1084         OIC_LOG(ERROR, TAG, "CAGetBLEServiceInfoByPosition is failed");
1085         return CA_STATUS_FAILED;
1086     }
1087
1088     VERIFY_NON_NULL(leServerInfo, TAG, "bleServiceInfo is NULL");
1089
1090     OIC_LOG_V(DEBUG, TAG, "Updating the data of length [%d] to [%s] ", dataLen,
1091               leServerInfo->remoteAddress);
1092
1093     int result = bt_gatt_set_value(leServerInfo->writeChar, (char *)data, dataLen);
1094
1095     if (BT_ERROR_NONE != result)
1096     {
1097         OIC_LOG_V(ERROR, TAG,
1098                   "bt_gatt_set_value Failed with return val [%s]",
1099                   CALEGetErrorMsg(result));
1100         return CA_STATUS_FAILED;
1101     }
1102
1103     result = bt_gatt_client_write_value(leServerInfo->writeChar, CALEGattCharacteristicWriteCb,
1104                                         NULL);
1105     if (BT_ERROR_NONE != result)
1106     {
1107         OIC_LOG_V(ERROR, TAG,
1108                   "bt_gatt_client_write_value Failed with return val [%s]",
1109                   CALEGetErrorMsg(result));
1110         return CA_STATUS_FAILED;
1111     }
1112
1113     // wait for callback for write Characteristic with success to sent data
1114     OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
1115     ca_mutex_lock(g_threadWriteCharacteristicMutex);
1116     if (!g_isSignalSetFlag)
1117     {
1118         OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success");
1119         if (CA_WAIT_SUCCESS != ca_cond_wait_for(g_threadWriteCharacteristicCond,
1120                                   g_threadWriteCharacteristicMutex,
1121                                   WAIT_TIME_WRITE_CHARACTERISTIC))
1122         {
1123             OIC_LOG(ERROR, TAG, "there is no response. write has failed");
1124             g_isSignalSetFlag = false;
1125             ca_mutex_unlock(g_threadWriteCharacteristicMutex);
1126             return CA_SEND_FAILED;
1127         }
1128     }
1129     // reset flag set by writeCharacteristic Callback
1130     g_isSignalSetFlag = false;
1131     ca_mutex_unlock(g_threadWriteCharacteristicMutex);
1132
1133     OIC_LOG(DEBUG, TAG, "OUT");
1134     return CA_STATUS_OK;
1135 }
1136
1137 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
1138 {
1139     OIC_LOG(DEBUG,  TAG, "IN");
1140
1141     VERIFY_NON_NULL(data, TAG, "data is NULL");
1142
1143     if (0 >= dataLen)
1144     {
1145         OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input !");
1146         return CA_STATUS_INVALID_PARAM;
1147     }
1148
1149     int numOfServersConnected = CAGetRegisteredServiceCount();
1150
1151     // Send data to already connected devices.
1152     for (int32_t pos = 0; pos < numOfServersConnected; pos++)
1153     {
1154         /*remoteAddress will be NULL.
1155           Since we have to send to all destinations. pos will be used for getting remote address.
1156          */
1157         int32_t ret = CAUpdateCharacteristicsToGattServer(NULL, data, dataLen, LE_MULTICAST, pos);
1158
1159         if (CA_STATUS_OK != ret)
1160         {
1161             OIC_LOG_V(ERROR, TAG,
1162                       "CAUpdateCharacteristicsToGattServer Failed with return val [%d] ", ret);
1163             g_clientErrorCallback(NULL, data, dataLen, ret);
1164         }
1165     }
1166
1167     // Add the data to pending list.
1168     CALEData_t *multicastData = (CALEData_t *)OICCalloc(1, sizeof(CALEData_t));
1169     if (NULL == multicastData)
1170     {
1171         OIC_LOG(ERROR, TAG, "Calloc failed");
1172         goto exit;
1173     }
1174     multicastData->data = OICCalloc(1, dataLen);
1175     if (NULL == multicastData->data)
1176     {
1177         OIC_LOG(ERROR, TAG, "Calloc failed");
1178         goto exit;
1179     }
1180     memcpy(multicastData->data, data, dataLen);
1181     multicastData->dataLen = dataLen;
1182
1183     ca_mutex_lock(g_multicastDataListMutex);
1184     if (NULL == g_multicastDataList)
1185     {
1186         g_multicastDataList = u_arraylist_create();
1187     }
1188     u_arraylist_add(g_multicastDataList, (void *)multicastData);
1189     ca_mutex_unlock(g_multicastDataListMutex);
1190
1191     // Start the scanning.
1192     CAResult_t result = CALEGattStartDeviceScanning();
1193     if (CA_STATUS_OK != result)
1194     {
1195         OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed");
1196         goto exit;
1197     }
1198
1199     // Start the timer by signalling it.
1200     ca_cond_signal(g_startTimerCond);
1201
1202 exit:
1203     OIC_LOG(DEBUG, TAG, "OUT ");
1204     return CA_STATUS_OK;
1205 }
1206
1207