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