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