[TIZEN]Moved GMainloop to CSDK sample from network monitor[LE/EDR].
[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     }
251     else
252     {
253         OIC_LOG_V(DEBUG, TAG, "Connected to [%s] ", remoteAddress);
254
255         char *addr = OICStrdup(remoteAddress);
256
257         ca_mutex_lock(g_LEClientThreadPoolMutex);
258         if (NULL == g_LEClientThreadPool)
259         {
260             OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
261             OICFree(addr);
262             ca_mutex_unlock(g_LEClientThreadPoolMutex);
263             return;
264         }
265
266         ret = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread,
267                                       addr);
268         if (CA_STATUS_OK != ret)
269         {
270             OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", ret);
271             OICFree(addr);
272         }
273         ca_mutex_unlock(g_LEClientThreadPoolMutex);
274     }
275     OIC_LOG(DEBUG, TAG, "OUT");
276 }
277
278 void CALEAdapterScanResultCb(int result, bt_adapter_le_device_scan_result_info_s *scanInfo,
279                              void *userData)
280 {
281     OIC_LOG(DEBUG, TAG, "IN");
282
283     VERIFY_NON_NULL_VOID(scanInfo, TAG, "scanInfo");
284     VERIFY_NON_NULL_VOID(scanInfo->remote_address, TAG, "scanInfo->remote_address");
285
286     OIC_LOG_V(DEBUG, TAG, "Remote Address [%s]", scanInfo->remote_address);
287     OIC_LOG_V(DEBUG, TAG, "Scan Result [%d]", result);
288     OIC_LOG_V(DEBUG, TAG,
289               " Adv data len [%d] Scan data len[%d]RSSI [%d] Addr_type [%d] ",
290               scanInfo->adv_data_len, scanInfo->scan_data_len, scanInfo->rssi,
291               scanInfo->address_type);
292
293     // Check if device is already discovered.
294     if (CALEIsDeviceDiscovered(scanInfo->remote_address))
295     {
296         OIC_LOG_V(INFO, TAG, "Device[%s] is already discovered", scanInfo->remote_address);
297         return;
298     }
299
300     // Stop the scan before invoking bt_gatt_connect().
301     CALEGattStopDeviceScanning();
302
303     ca_mutex_lock(g_deviceDiscoveredListMutex);
304     // Add the the device Discovered list.
305     if (NULL == g_deviceDiscoveredList)
306     {
307         g_deviceDiscoveredList = u_arraylist_create();
308     }
309     char *deviceAddr = OICStrdup(scanInfo->remote_address);
310     u_arraylist_add(g_deviceDiscoveredList, (void *) deviceAddr);
311     ca_mutex_unlock(g_deviceDiscoveredListMutex);
312
313     size_t len = strlen(scanInfo->remote_address);
314
315     char *addr = (char *)OICMalloc(sizeof(char) * (len + 1));
316     VERIFY_NON_NULL_VOID(addr, TAG, "Malloc failed");
317
318     strncpy(addr, scanInfo->remote_address, len + 1);
319
320     OIC_LOG_V(DEBUG, TAG,
321               "Trying to do Gatt connection to [%s]", addr);
322
323     ca_mutex_lock(g_LEClientThreadPoolMutex);
324     if (NULL == g_LEClientThreadPool)
325     {
326         OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
327         OICFree(addr);
328         ca_mutex_unlock(g_LEClientThreadPoolMutex);
329         return;
330     }
331
332     CAResult_t res = ca_thread_pool_add_task(g_LEClientThreadPool, CAGattConnectThread, addr);
333     if (CA_STATUS_OK != res)
334     {
335         OIC_LOG_V(ERROR, TAG,
336                   "ca_thread_pool_add_task failed with ret [%d]", res);
337         OICFree(addr);
338     }
339     ca_mutex_unlock(g_LEClientThreadPoolMutex);
340     OIC_LOG(DEBUG, TAG, "OUT");
341 }
342
343 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
344 {
345     OIC_LOG(DEBUG, TAG, "IN");
346
347     ca_mutex_lock(g_LEClientThreadPoolMutex);
348     g_LEClientThreadPool = handle;
349     ca_mutex_unlock(g_LEClientThreadPoolMutex);
350
351     OIC_LOG(DEBUG, TAG, "OUT");
352 }
353
354 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
355 {
356     OIC_LOG(DEBUG, TAG, "IN");
357
358     ca_mutex_lock(g_LEReqRespClientCbMutex);
359
360     g_LEClientDataReceivedCallback = callback;
361
362     ca_mutex_unlock(g_LEReqRespClientCbMutex);
363
364     OIC_LOG(DEBUG, TAG, "OUT");
365 }
366
367 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
368 {
369     g_clientErrorCallback = callback;
370 }
371
372 CAResult_t CAStartLEGattClient()
373 {
374     OIC_LOG(DEBUG, TAG, "IN");
375
376     ca_mutex_lock(g_LEClientStateMutex);
377     if (true  == g_isLEGattClientStarted)
378     {
379         OIC_LOG(ERROR, TAG, "Gatt Client is already running!!");
380         ca_mutex_unlock(g_LEClientStateMutex);
381         return CA_STATUS_FAILED;
382     }
383
384     CAResult_t  result = CALEGattSetCallbacks();
385     if (CA_STATUS_OK != result)
386     {
387         OIC_LOG(ERROR, TAG, "CABleGattSetCallbacks Failed");
388         ca_mutex_unlock(g_LEClientStateMutex);
389         CATerminateLEGattClient();
390         return CA_STATUS_FAILED;
391     }
392
393     g_isLEGattClientStarted = true;
394     ca_mutex_unlock(g_LEClientStateMutex);
395
396     ca_mutex_lock(g_LEClientThreadPoolMutex);
397     if (NULL == g_LEClientThreadPool)
398     {
399         OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL");
400         CATerminateGattClientMutexVariables();
401         ca_mutex_unlock(g_LEClientThreadPoolMutex);
402         return CA_STATUS_FAILED;
403     }
404
405     result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartTimerThread,
406                                      NULL);
407     if (CA_STATUS_OK != result)
408     {
409         OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed");
410         CATerminateGattClientMutexVariables();
411         ca_mutex_unlock(g_LEClientThreadPoolMutex);
412         return CA_STATUS_FAILED;
413     }
414     ca_mutex_unlock(g_LEClientThreadPoolMutex);
415
416     OIC_LOG(DEBUG, TAG, "OUT");
417     return CA_STATUS_OK;
418 }
419
420 void CAStartTimerThread(void *data)
421 {
422     OIC_LOG(DEBUG, TAG, "IN");
423     while (g_isLEGattClientStarted)
424     {
425         ca_mutex_lock(g_multicastDataListMutex);
426         if (!g_isMulticastInProgress)
427         {
428             OIC_LOG(DEBUG, TAG, "waiting....");
429             ca_cond_wait(g_startTimerCond, g_multicastDataListMutex);
430             OIC_LOG(DEBUG, TAG, "Wake up");
431             g_isMulticastInProgress = true;
432         }
433
434         // Timed conditional wait for stopping the scan.
435         CAWaitResult_t ret = ca_cond_wait_for(g_scanningTimeCond, g_multicastDataListMutex,
436                                               TIMEOUT);
437         if (CA_WAIT_TIMEDOUT == ret)
438         {
439             OIC_LOG(DEBUG, TAG, "Scan is timed Out");
440             // Call stop scan.
441             CALEGattStopDeviceScanning();
442
443             // Clear the data list and device list.
444             u_arraylist_destroy(g_multicastDataList);
445             g_multicastDataList = NULL;
446
447             ca_mutex_lock(g_deviceDiscoveredListMutex);
448             u_arraylist_destroy(g_deviceDiscoveredList);
449             g_deviceDiscoveredList = NULL;
450             ca_mutex_unlock(g_deviceDiscoveredListMutex);
451
452             g_isMulticastInProgress = false;
453         }
454         ca_mutex_unlock(g_multicastDataListMutex);
455     }
456
457     OIC_LOG(DEBUG, TAG, "OUT");
458 }
459
460 void CAStopLEGattClient()
461 {
462     OIC_LOG(DEBUG,  TAG, "IN");
463
464     ca_mutex_lock(g_LEClientStateMutex);
465
466     if (false == g_isLEGattClientStarted)
467     {
468         OIC_LOG(ERROR, TAG, "Gatt Client is not running to stop");
469         ca_mutex_unlock(g_LEClientStateMutex);
470         return;
471     }
472
473     CALEGattUnSetCallbacks();
474
475     CALEGattStopDeviceScanning();
476
477     g_isLEGattClientStarted = false;
478
479     // Signal the conditions waiting in Start timer.
480     ca_cond_signal(g_startTimerCond);
481     ca_cond_signal(g_scanningTimeCond);
482
483     // Destroy the multicast data list and device list if not empty.
484     if (NULL != g_multicastDataList)
485     {
486         ca_mutex_lock(g_multicastDataListMutex);
487         u_arraylist_destroy(g_multicastDataList);
488         g_multicastDataList = NULL;
489         ca_mutex_unlock(g_multicastDataListMutex);
490     }
491
492     if (NULL != g_deviceDiscoveredList)
493     {
494         ca_mutex_lock(g_deviceDiscoveredListMutex);
495         u_arraylist_destroy(g_deviceDiscoveredList);
496         g_deviceDiscoveredList = NULL;
497         ca_mutex_unlock(g_deviceDiscoveredListMutex);
498     }
499
500     ca_mutex_lock(g_LEServerListMutex);
501     CAFreeLEServerList(g_LEServerList);
502     g_LEServerList = NULL;
503     ca_mutex_unlock(g_LEServerListMutex);
504
505     ca_mutex_lock(g_threadWriteCharacteristicMutex);
506     ca_cond_signal(g_threadWriteCharacteristicCond);
507     ca_mutex_unlock(g_threadWriteCharacteristicMutex);
508
509     CAResetRegisteredServiceCount();
510
511     GMainContext  *context_event_loop = NULL;
512     // Required for waking up the thread which is running in gmain loop
513     if (NULL != g_eventLoop)
514     {
515         context_event_loop = g_main_loop_get_context(g_eventLoop);
516     }
517     if (context_event_loop)
518     {
519         OIC_LOG_V(DEBUG,  TAG, "g_eventLoop context %x", context_event_loop);
520         g_main_context_wakeup(context_event_loop);
521
522         // Kill g main loops and kill threads.
523         g_main_loop_quit(g_eventLoop);
524     }
525     else
526     {
527         OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL");
528     }
529
530     ca_mutex_unlock(g_LEClientStateMutex);
531
532     OIC_LOG(DEBUG,  TAG, "OUT");
533 }
534
535 CAResult_t CAInitializeLEGattClient()
536 {
537     OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
538     CAResult_t res = CAInitGattClientMutexVariables();
539     if (CA_STATUS_OK != res)
540     {
541         OIC_LOG(ERROR, TAG, "CAInitGattClientMutexVariables failed!");
542         CATerminateGattClientMutexVariables();
543         return CA_STATUS_FAILED;
544     }
545     return res;
546 }
547
548 void CATerminateLEGattClient()
549 {
550     OIC_LOG(DEBUG,  TAG, "IN");
551
552     CATerminateGattClientMutexVariables();
553
554     OIC_LOG(DEBUG,  TAG, "OUT");
555 }
556
557 CAResult_t CAInitGattClientMutexVariables()
558 {
559     OIC_LOG(DEBUG,  TAG, "IN");
560     if (NULL == g_LEClientStateMutex)
561     {
562         g_LEClientStateMutex = ca_mutex_new();
563         if (NULL == g_LEClientStateMutex)
564         {
565             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
566             return CA_STATUS_FAILED;
567         }
568     }
569
570     if (NULL == g_LEServerListMutex)
571     {
572         g_LEServerListMutex = ca_mutex_new();
573         if (NULL == g_LEServerListMutex)
574         {
575             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
576             return CA_STATUS_FAILED;
577         }
578     }
579
580     if (NULL == g_LEReqRespClientCbMutex)
581     {
582         g_LEReqRespClientCbMutex = ca_mutex_new();
583         if (NULL == g_LEReqRespClientCbMutex)
584         {
585             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
586             return CA_STATUS_FAILED;
587         }
588     }
589
590     if (NULL == g_LEClientThreadPoolMutex)
591     {
592         g_LEClientThreadPoolMutex = ca_mutex_new();
593         if (NULL == g_LEClientThreadPoolMutex)
594         {
595             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
596             return CA_STATUS_FAILED;
597         }
598     }
599
600     if (NULL == g_LEClientConnectMutex)
601     {
602         g_LEClientConnectMutex = ca_mutex_new();
603         if (NULL == g_LEClientConnectMutex)
604         {
605             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
606             return CA_STATUS_FAILED;
607         }
608     }
609
610     if (NULL == g_multicastDataListMutex)
611     {
612         g_multicastDataListMutex = ca_mutex_new();
613         if (NULL == g_multicastDataListMutex)
614         {
615             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
616             return CA_STATUS_FAILED;
617         }
618     }
619
620     if (NULL == g_deviceDiscoveredListMutex)
621     {
622         g_deviceDiscoveredListMutex = ca_mutex_new();
623         if (NULL == g_deviceDiscoveredListMutex)
624         {
625             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
626             return CA_STATUS_FAILED;
627         }
628     }
629
630     if (NULL == g_threadWriteCharacteristicMutex)
631     {
632         g_threadWriteCharacteristicMutex = ca_mutex_new();
633         if (NULL == g_threadWriteCharacteristicMutex)
634         {
635             OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
636             return CA_STATUS_FAILED;
637         }
638     }
639
640     if (NULL == g_startTimerCond)
641     {
642         g_startTimerCond = ca_cond_new();
643         if (NULL == g_startTimerCond)
644         {
645             OIC_LOG(ERROR, TAG, "ca_cond_new failed");
646             return CA_STATUS_FAILED;
647         }
648     }
649
650     if (NULL == g_scanningTimeCond)
651     {
652         g_scanningTimeCond = ca_cond_new();
653         if (NULL == g_scanningTimeCond)
654         {
655             OIC_LOG(ERROR, TAG, "ca_cond_new failed");
656             return CA_STATUS_FAILED;
657         }
658     }
659
660     if (NULL == g_threadWriteCharacteristicCond)
661     {
662         g_threadWriteCharacteristicCond = ca_cond_new();
663         if (NULL == g_threadWriteCharacteristicCond)
664         {
665             OIC_LOG(ERROR, TAG, "ca_cond_new failed");
666             return CA_STATUS_FAILED;
667         }
668     }
669
670     OIC_LOG(DEBUG,  TAG, "OUT");
671     return CA_STATUS_OK;
672 }
673
674 void CATerminateGattClientMutexVariables()
675 {
676     OIC_LOG(DEBUG,  TAG, "IN");
677
678     ca_mutex_free(g_LEClientStateMutex);
679     g_LEClientStateMutex = NULL;
680
681     ca_mutex_free(g_LEServerListMutex);
682     g_LEServerListMutex = NULL;
683
684     ca_mutex_free(g_LEReqRespClientCbMutex);
685     g_LEReqRespClientCbMutex = NULL;
686
687     ca_mutex_free(g_LEClientConnectMutex);
688     g_LEClientConnectMutex = NULL;
689
690     ca_mutex_free(g_LEClientThreadPoolMutex);
691     g_LEClientThreadPoolMutex = NULL;
692
693     ca_mutex_free(g_multicastDataListMutex);
694     g_multicastDataListMutex = NULL;
695
696     ca_mutex_free(g_deviceDiscoveredListMutex);
697     g_deviceDiscoveredListMutex = NULL;
698
699     ca_mutex_free(g_threadWriteCharacteristicMutex);
700     g_threadWriteCharacteristicMutex = NULL;
701
702     ca_cond_free(g_startTimerCond);
703     g_startTimerCond = NULL;
704
705     ca_cond_free(g_scanningTimeCond);
706     g_scanningTimeCond = NULL;
707
708     ca_cond_free(g_threadWriteCharacteristicCond);
709     g_threadWriteCharacteristicCond = NULL;
710     g_isSignalSetFlag = false;
711
712     OIC_LOG(DEBUG,  TAG, "OUT");
713 }
714
715 CAResult_t CALEGattSetCallbacks()
716 {
717     OIC_LOG(DEBUG, TAG, "IN");
718
719     OIC_LOG(DEBUG, TAG, "OUT");
720     return CA_STATUS_OK;
721 }
722
723 void CALEGattUnSetCallbacks()
724 {
725     OIC_LOG(DEBUG, TAG, "IN");
726
727     bt_gatt_unset_connection_state_changed_cb();
728
729     int numOfServersConnected = CAGetRegisteredServiceCount();
730     LEServerInfo *leServerInfo = NULL;
731
732     for (int32_t index = 0; index < numOfServersConnected; index++)
733     {
734         CAGetLEServerInfoByPosition(g_LEServerList, index, &leServerInfo);
735         bt_gatt_client_unset_characteristic_value_changed_cb(leServerInfo->readChar);
736     }
737     OIC_LOG(DEBUG, TAG, "OUT");
738 }
739
740 CAResult_t CALEGattStartDeviceScanning()
741 {
742     OIC_LOG(DEBUG, TAG, "IN");
743
744     int ret = bt_adapter_le_start_scan(CALEAdapterScanResultCb, NULL);
745     if(BT_ERROR_NONE != ret)
746     {
747         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_scan failed[%s]",
748                   CALEGetErrorMsg(ret));
749         return CA_STATUS_FAILED;
750     }
751
752     OIC_LOG(DEBUG, TAG, "OUT");
753     return CA_STATUS_OK;
754 }
755
756 void CALEGattStopDeviceScanning()
757 {
758     OIC_LOG(DEBUG, TAG, "IN");
759
760     int ret = bt_adapter_le_stop_scan();
761     if (BT_ERROR_NONE != ret)
762     {
763         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_stop_scan failed[%s]",
764                   CALEGetErrorMsg(ret));
765     }
766
767     OIC_LOG(DEBUG, TAG, "OUT");
768 }
769
770 void CAGattConnectThread (void *remoteAddress)
771 {
772     OIC_LOG(DEBUG, TAG, "IN ");
773
774     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
775
776     char *address  = (char *)remoteAddress;
777
778     OIC_LOG_V(DEBUG, TAG, "remote address is [%s]", address);
779
780     CAResult_t result = CALEGattConnect(address);
781
782     if (CA_STATUS_OK != result)
783     {
784         OIC_LOG_V(ERROR, TAG, "bt_gatt_connect failed for [%s]", address);
785     }
786
787     OICFree(address);
788
789     OIC_LOG(DEBUG, TAG, "OUT");
790 }
791
792 CAResult_t CALEGattConnect(const char *remoteAddress)
793 {
794     OIC_LOG(DEBUG, TAG, "IN");
795
796     VERIFY_NON_NULL_RET(remoteAddress, TAG,
797                         "remote address is NULL", CA_STATUS_FAILED);
798
799     ca_mutex_lock(g_LEClientConnectMutex);
800     bool isConnected = false;
801     int ret = bt_device_is_profile_connected(remoteAddress, BT_PROFILE_GATT, &isConnected);
802     if (BT_ERROR_NONE != ret)
803     {
804         OIC_LOG_V(ERROR, TAG, "bt_device_is_profile_connected Failed with ret value [%s] ",
805                   CALEGetErrorMsg(ret));
806         ca_mutex_unlock(g_LEClientConnectMutex);
807         return CA_STATUS_FAILED;
808     }
809
810     CAResult_t result = CA_STATUS_OK;
811     if (!isConnected)
812     {
813         ret = bt_gatt_connect(remoteAddress, true);
814
815         if (BT_ERROR_NONE != ret)
816         {
817             OIC_LOG_V(ERROR, TAG, "bt_gatt_connect Failed with ret value [%s] ",
818                       CALEGetErrorMsg(ret));
819             ca_mutex_unlock(g_LEClientConnectMutex);
820             return CA_STATUS_FAILED;
821         }
822     }
823     else
824     {
825         OIC_LOG_V(INFO, TAG, "Remote address[%s] is already connected",
826                   remoteAddress);
827         char *addr = OICStrdup(remoteAddress);
828         if (NULL == addr)
829         {
830             OIC_LOG(ERROR, TAG, "addr is NULL");
831             ca_mutex_unlock(g_LEClientConnectMutex);
832             return CA_STATUS_FAILED;
833         }
834
835         ca_mutex_lock(g_LEClientThreadPoolMutex);
836         if (NULL == g_LEClientThreadPool)
837         {
838             OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
839             OICFree(addr);
840             ca_mutex_unlock(g_LEClientThreadPoolMutex);
841             ca_mutex_unlock(g_LEClientConnectMutex);
842             return CA_STATUS_FAILED;
843         }
844
845         result = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread,
846                                       addr);
847         if (CA_STATUS_OK != result)
848         {
849             OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", result);
850             OICFree(addr);
851         }
852         ca_mutex_unlock(g_LEClientThreadPoolMutex);
853     }
854     ca_mutex_unlock(g_LEClientConnectMutex);
855
856     OIC_LOG(DEBUG, TAG, "OUT");
857     return result;
858 }
859
860 CAResult_t CALEGattDisConnect(const char *remoteAddress)
861 {
862     OIC_LOG(DEBUG, TAG, "IN");
863
864     VERIFY_NON_NULL_RET(remoteAddress, TAG,
865                         "remote address is NULL", CA_STATUS_FAILED);
866
867     int ret = bt_gatt_disconnect(remoteAddress);
868
869     if (BT_ERROR_NONE != ret)
870     {
871         OIC_LOG_V(ERROR, TAG, "bt_gatt_disconnect Failed with ret value [%d] ",
872                   CALEGetErrorMsg(ret));
873         return CA_STATUS_FAILED;
874     }
875
876     OIC_LOG(DEBUG, TAG, "OUT");
877     return CA_STATUS_OK;
878 }
879
880 void CADiscoverLEServicesThread (void *remoteAddress)
881 {
882     OIC_LOG(DEBUG, TAG, "IN");
883
884     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
885
886     char *address  = (char *)remoteAddress;
887
888     CAResult_t result = CALEGattDiscoverServices(address);
889     if (CA_STATUS_OK != result)
890     {
891         OIC_LOG(ERROR, TAG, "CALEGattDiscoverServices failed");
892     }
893
894     OICFree(address);
895     OIC_LOG(DEBUG, TAG, "OUT");
896 }
897
898 CAResult_t CALEGattDiscoverServices(const char *remoteAddress)
899 {
900     OIC_LOG(DEBUG, TAG, "IN");
901
902     VERIFY_NON_NULL_RET(remoteAddress, TAG,
903                         "remote address is NULL", CA_STATUS_FAILED);
904
905     bt_gatt_client_h clientHandle = NULL;
906     int32_t ret = bt_gatt_client_create(remoteAddress, &clientHandle);
907     if (BT_ERROR_NONE != ret || NULL == clientHandle)
908     {
909         OIC_LOG_V(ERROR, TAG,
910                   "bt_gatt_client_create Failed with ret value [%s] ", CALEGetErrorMsg(ret));
911         CALEGattDisConnect(remoteAddress);
912         return CA_STATUS_FAILED;
913     }
914
915     bt_gatt_h serviceHandle = NULL;
916     ret = bt_gatt_client_get_service(clientHandle, CA_GATT_SERVICE_UUID, &serviceHandle);
917     if (BT_ERROR_NONE != ret || NULL == serviceHandle)
918     {
919         OIC_LOG_V(ERROR, TAG,
920                   "bt_gatt_client_get_service Failed with ret value [%s] ", CALEGetErrorMsg(ret));
921         bt_gatt_client_destroy(clientHandle);
922         CALEGattDisConnect(remoteAddress);
923         return CA_STATUS_FAILED;
924     }
925
926     // Server will read data on this characteristic.
927     bt_gatt_h writeChrHandle = NULL;
928     ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_REQUEST_CHRC_UUID,
929                                              &writeChrHandle);
930     if (BT_ERROR_NONE != ret || NULL == writeChrHandle)
931     {
932         OIC_LOG_V(ERROR, TAG,
933                   "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
934                   CALEGetErrorMsg(ret));
935         bt_gatt_client_destroy(clientHandle);
936         CALEGattDisConnect(remoteAddress);
937         return CA_STATUS_FAILED;
938     }
939
940     // Server will notify data on this characteristic.
941     bt_gatt_h readChrHandle = NULL;
942     ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_RESPONSE_CHRC_UUID,
943                                              &readChrHandle);
944     if (BT_ERROR_NONE != ret || NULL == readChrHandle)
945     {
946         OIC_LOG_V(ERROR, TAG,
947                   "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
948                   CALEGetErrorMsg(ret));
949         bt_gatt_client_destroy(clientHandle);
950         CALEGattDisConnect(remoteAddress);
951         return CA_STATUS_FAILED;
952     }
953
954
955     //TODO: This data has to be freed while unsetting the callback.
956     char *addr = OICStrdup(remoteAddress);
957     ret = bt_gatt_client_set_characteristic_value_changed_cb(readChrHandle,
958                                                              CALEGattCharacteristicChangedCb,
959                                                              (void *)addr);
960     if (BT_ERROR_NONE != ret)
961     {
962         OIC_LOG_V(ERROR, TAG,
963                   "bt_gatt_client_set_characteristic_value_changed_cb Failed with ret value [%s]",
964                   CALEGetErrorMsg(ret));
965         bt_gatt_client_destroy(clientHandle);
966         CALEGattDisConnect(remoteAddress);
967         return CA_STATUS_FAILED;
968     }
969
970     LEServerInfo *serverInfo = (LEServerInfo *)OICCalloc(1, sizeof(LEServerInfo));
971     if (NULL == serverInfo)
972     {
973         OIC_LOG(ERROR, TAG, "Malloc failed");
974         CALEGattDisConnect(remoteAddress);
975         return CA_MEMORY_ALLOC_FAILED;
976     }
977     serverInfo->clientHandle = clientHandle;
978     serverInfo->serviceHandle = serviceHandle;
979     serverInfo->readChar = readChrHandle;
980     serverInfo->writeChar = writeChrHandle;
981     serverInfo->remoteAddress = OICStrdup(remoteAddress);
982
983     ca_mutex_lock(g_LEServerListMutex);
984     CAResult_t result = CAAddLEServerInfoToList(&g_LEServerList, serverInfo);
985     if (CA_STATUS_OK != result)
986     {
987         OIC_LOG(ERROR, TAG, "CAAddBLEClientInfoToList failed");
988         bt_gatt_client_destroy(clientHandle);
989         CALEGattDisConnect(remoteAddress);
990         return CA_STATUS_FAILED;
991     }
992     ca_mutex_unlock(g_LEServerListMutex);
993
994     // Send the data of pending multicast data list if any.
995     if (g_multicastDataList)
996     {
997         ca_mutex_lock(g_multicastDataListMutex);
998         uint32_t arrayLength = u_arraylist_length(g_multicastDataList);
999         for (int i = 0; i < arrayLength; i++)
1000         {
1001             CALEData_t *multicastData = u_arraylist_get(g_multicastDataList, i);
1002             if (NULL == multicastData)
1003             {
1004                 OIC_LOG(DEBUG, TAG, "multicastData is NULL");
1005                 continue;
1006             }
1007             CAUpdateCharacteristicsToGattServer(remoteAddress, multicastData->data,
1008                                                 multicastData->dataLen, LE_UNICAST, 0);
1009         }
1010         ca_mutex_unlock(g_multicastDataListMutex);
1011     }
1012
1013     OIC_LOG(DEBUG, TAG, "OUT");
1014     return CA_STATUS_OK;
1015 }
1016
1017 CAResult_t  CAUpdateCharacteristicsToGattServer(const char *remoteAddress,
1018                                                 const uint8_t *data, const uint32_t dataLen,
1019                                                 CALETransferType_t type, const int32_t position)
1020 {
1021     OIC_LOG(DEBUG, TAG, "IN");
1022
1023     VERIFY_NON_NULL(data, TAG, "data is NULL");
1024
1025     if (0 >= dataLen)
1026     {
1027         OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input!");
1028         return CA_STATUS_INVALID_PARAM;
1029     }
1030
1031     LEServerInfo *leServerInfo = NULL;
1032     CAResult_t ret =  CA_STATUS_FAILED;
1033
1034     ca_mutex_lock(g_LEServerListMutex);
1035     if (LE_UNICAST == type)
1036     {
1037         ret = CAGetLEServerInfo(g_LEServerList, remoteAddress, &leServerInfo);
1038     }
1039     else if (LE_MULTICAST == type)
1040     {
1041         ret = CAGetLEServerInfoByPosition(g_LEServerList, position, &leServerInfo);
1042     }
1043     ca_mutex_unlock(g_LEServerListMutex);
1044
1045     if (CA_STATUS_OK != ret)
1046     {
1047         OIC_LOG(ERROR, TAG, "CAGetBLEServiceInfoByPosition is failed");
1048         return CA_STATUS_FAILED;
1049     }
1050
1051     VERIFY_NON_NULL(leServerInfo, TAG, "bleServiceInfo is NULL");
1052
1053     OIC_LOG_V(DEBUG, TAG, "Updating the data of length [%d] to [%s] ", dataLen,
1054               leServerInfo->remoteAddress);
1055
1056     int result = bt_gatt_set_value(leServerInfo->writeChar, (char *)data, dataLen);
1057
1058     if (BT_ERROR_NONE != result)
1059     {
1060         OIC_LOG_V(ERROR, TAG,
1061                   "bt_gatt_set_value Failed with return val [%s]",
1062                   CALEGetErrorMsg(result));
1063         return CA_STATUS_FAILED;
1064     }
1065
1066     result = bt_gatt_client_write_value(leServerInfo->writeChar, CALEGattCharacteristicWriteCb,
1067                                         NULL);
1068     if (BT_ERROR_NONE != result)
1069     {
1070         OIC_LOG_V(ERROR, TAG,
1071                   "bt_gatt_client_write_value Failed with return val [%s]",
1072                   CALEGetErrorMsg(result));
1073         return CA_STATUS_FAILED;
1074     }
1075
1076     // wait for callback for write Characteristic with success to sent data
1077     OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
1078     ca_mutex_lock(g_threadWriteCharacteristicMutex);
1079     if (!g_isSignalSetFlag)
1080     {
1081         OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success");
1082         if (CA_WAIT_SUCCESS != ca_cond_wait_for(g_threadWriteCharacteristicCond,
1083                                   g_threadWriteCharacteristicMutex,
1084                                   WAIT_TIME_WRITE_CHARACTERISTIC))
1085         {
1086             OIC_LOG(ERROR, TAG, "there is no response. write has failed");
1087             g_isSignalSetFlag = false;
1088             ca_mutex_unlock(g_threadWriteCharacteristicMutex);
1089             return CA_SEND_FAILED;
1090         }
1091     }
1092     // reset flag set by writeCharacteristic Callback
1093     g_isSignalSetFlag = false;
1094     ca_mutex_unlock(g_threadWriteCharacteristicMutex);
1095
1096     OIC_LOG(DEBUG, TAG, "OUT");
1097     return CA_STATUS_OK;
1098 }
1099
1100 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
1101 {
1102     OIC_LOG(DEBUG,  TAG, "IN");
1103
1104     VERIFY_NON_NULL(data, TAG, "data is NULL");
1105
1106     if (0 >= dataLen)
1107     {
1108         OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input !");
1109         return CA_STATUS_INVALID_PARAM;
1110     }
1111
1112     int numOfServersConnected = CAGetRegisteredServiceCount();
1113
1114     // Send data to already connected devices.
1115     for (int32_t pos = 0; pos < numOfServersConnected; pos++)
1116     {
1117         /*remoteAddress will be NULL.
1118           Since we have to send to all destinations. pos will be used for getting remote address.
1119          */
1120         int32_t ret = CAUpdateCharacteristicsToGattServer(NULL, data, dataLen, LE_MULTICAST, pos);
1121
1122         if (CA_STATUS_OK != ret)
1123         {
1124             OIC_LOG_V(ERROR, TAG,
1125                       "CAUpdateCharacteristicsToGattServer Failed with return val [%d] ", ret);
1126             g_clientErrorCallback(NULL, data, dataLen, ret);
1127         }
1128     }
1129
1130     // Add the data to pending list.
1131     CALEData_t *multicastData = (CALEData_t *)OICCalloc(1, sizeof(CALEData_t));
1132     if (NULL == multicastData)
1133     {
1134         OIC_LOG(ERROR, TAG, "Calloc failed");
1135         goto exit;
1136     }
1137     multicastData->data = OICCalloc(1, dataLen);
1138     if (NULL == multicastData->data)
1139     {
1140         OIC_LOG(ERROR, TAG, "Calloc failed");
1141         goto exit;
1142     }
1143     memcpy(multicastData->data, data, dataLen);
1144     multicastData->dataLen = dataLen;
1145
1146     ca_mutex_lock(g_multicastDataListMutex);
1147     if (NULL == g_multicastDataList)
1148     {
1149         g_multicastDataList = u_arraylist_create();
1150     }
1151     u_arraylist_add(g_multicastDataList, (void *)multicastData);
1152     ca_mutex_unlock(g_multicastDataListMutex);
1153
1154     // Start the scanning.
1155     CAResult_t result = CALEGattStartDeviceScanning();
1156     if (CA_STATUS_OK != result)
1157     {
1158         OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed");
1159         goto exit;
1160     }
1161
1162     // Start the timer by signalling it.
1163     ca_cond_signal(g_startTimerCond);
1164
1165 exit:
1166     OIC_LOG(DEBUG, TAG, "OUT ");
1167     return CA_STATUS_OK;
1168 }
1169
1170