Merge "Merge branch 'master' into group-manager" into group-manager
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / tizen / caleclient.c
1 /* ****************************************************************
2 *
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
4 *
5 *
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************/
20
21 #include "caleclient.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <arpa/inet.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <pthread.h>
31 #include <gio/gio.h>
32
33 #include "camutex.h"
34 #include "uarraylist.h"
35 #include "caqueueingthread.h"
36 #include "caadapterutils.h"
37 #include "cafragmentation.h"
38 #include "cagattservice.h"
39 #include "oic_string.h"
40 #include "oic_malloc.h"
41
42 /**
43  * Logging tag for module name.
44  */
45 #define TAG "OIC_CA_LE_CLIENT"
46
47 #define MICROSECS_PER_SEC 1000000
48
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  * Maintains the callback to be notified on receival of network packets from other
126  *           BLE devices
127  */
128 static CABLEDataReceivedCallback g_LEClientDataReceivedCallback = NULL;
129
130 /**
131  * callback to update the error to le adapter
132  */
133 static CABLEErrorHandleCallback g_clientErrorCallback;
134
135 /**
136  * gmainLoop to manage the threads to receive the callback from the platfrom.
137  */
138 static GMainLoop *g_eventLoop = NULL;
139
140 /**
141  * Reference to threadpool
142  */
143 static ca_thread_pool_t g_LEClientThreadPool = NULL;
144
145 bt_scan_filter_h g_scanFilter = NULL;
146
147 bool CALEIsDeviceDiscovered(const char * address)
148 {
149     OIC_LOG(DEBUG, TAG, "IN");
150     if (g_deviceDiscoveredList)
151     {
152         ca_mutex_lock(g_deviceDiscoveredListMutex);
153         uint32_t arrayLength = u_arraylist_length(g_deviceDiscoveredList);
154         for (int i = 0; i < arrayLength; i++)
155         {
156             char *deviceAddr = u_arraylist_get(g_deviceDiscoveredList, i);
157             if (0 == strcasecmp(deviceAddr, address))
158             {
159                 OIC_LOG(DEBUG, TAG, "Device Found");
160                 ca_mutex_unlock(g_deviceDiscoveredListMutex);
161                 return true;
162             }
163
164         }
165         ca_mutex_unlock(g_deviceDiscoveredListMutex);
166     }
167     OIC_LOG(DEBUG, TAG, "OUT");
168     return false;
169 }
170
171 void CALEGattCharacteristicChangedCb(bt_gatt_h characteristic,
172                                      char *value,
173                                      int valueLen, void *userData)
174 {
175     OIC_LOG(DEBUG, TAG, "IN");
176     OIC_LOG_V(DEBUG, TAG, "Changed characteristic value length [%d]", valueLen);
177
178     ca_mutex_lock(g_LEReqRespClientCbMutex);
179     if (NULL == g_LEClientDataReceivedCallback)
180     {
181         OIC_LOG(ERROR, TAG, "Request response callback is not set");
182         ca_mutex_unlock(g_LEReqRespClientCbMutex);
183         return;
184     }
185
186     uint32_t sentLength = 0;
187     g_LEClientDataReceivedCallback(userData, (uint8_t *)value, valueLen, &sentLength);
188
189     OIC_LOG_V(DEBUG, TAG, "Sent data Length is %d", sentLength);
190
191     ca_mutex_unlock(g_LEReqRespClientCbMutex);
192
193     OIC_LOG(DEBUG, TAG, "OUT");
194 }
195
196 void CALEGattCharacteristicWriteCb(int result, bt_gatt_h reqHandle, void *userData)
197 {
198     OIC_LOG(DEBUG, TAG, "IN ");
199     OIC_LOG(DEBUG, TAG, "OUT ");
200 }
201
202 void CALEGattConnectionStateChangedCb(int result, bool connected,
203                                       const char *remoteAddress, void *userData)
204 {
205     OIC_LOG(DEBUG, TAG, "IN ");
206
207     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
208
209     // Start the scanning.
210     CAResult_t ret = CALEGattStartDeviceScanning();
211     if (CA_STATUS_OK != ret)
212     {
213         OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed");
214     }
215     // Signal the start timer.
216     ca_cond_signal(g_scanningTimeCond);
217
218     if (!connected)
219     {
220         OIC_LOG_V(DEBUG, TAG, "DisConnected from [%s] ", remoteAddress);
221     }
222     else
223     {
224         OIC_LOG_V(DEBUG, TAG, "Connected to [%s] ", remoteAddress);
225
226         char *addr = OICStrdup(remoteAddress);
227
228         ca_mutex_lock(g_LEClientThreadPoolMutex);
229         if (NULL == g_LEClientThreadPool)
230         {
231             OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
232             OICFree(addr);
233             ca_mutex_unlock(g_LEClientThreadPoolMutex);
234             return;
235         }
236
237         ret = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread,
238                                       addr);
239         if (CA_STATUS_OK != ret)
240         {
241             OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", ret);
242             OICFree(addr);
243         }
244         ca_mutex_unlock(g_LEClientThreadPoolMutex);
245     }
246     OIC_LOG(DEBUG, TAG, "OUT");
247 }
248
249 void CALEAdapterScanResultCb(int result, bt_adapter_le_device_scan_result_info_s *scanInfo,
250                              void *userData)
251 {
252     OIC_LOG(DEBUG, TAG, "IN");
253
254     VERIFY_NON_NULL_VOID(scanInfo, TAG, "scanInfo");
255     VERIFY_NON_NULL_VOID(scanInfo->remote_address, TAG, "scanInfo->remote_address");
256
257     OIC_LOG_V(DEBUG, TAG, "Remote Address [%s]", scanInfo->remote_address);
258     OIC_LOG_V(DEBUG, TAG, "Scan Result [%d]", result);
259     OIC_LOG_V(DEBUG, TAG,
260               " Adv data len [%d] Scan data len[%d]RSSI [%d] Addr_type [%d] ",
261               scanInfo->adv_data_len, scanInfo->scan_data_len, scanInfo->rssi,
262               scanInfo->address_type);
263
264     // Check if device is already discovered.
265     if (CALEIsDeviceDiscovered(scanInfo->remote_address))
266     {
267         OIC_LOG_V(INFO, TAG, "Device[%s] is already discovered", scanInfo->remote_address);
268         return;
269     }
270
271     // Stop the scan before invoking bt_gatt_connect().
272     CALEGattStopDeviceScanning();
273
274     ca_mutex_lock(g_deviceDiscoveredListMutex);
275     // Add the the device Discovered list.
276     if (NULL == g_deviceDiscoveredList)
277     {
278         g_deviceDiscoveredList = u_arraylist_create();
279     }
280     char *deviceAddr = OICStrdup(scanInfo->remote_address);
281     u_arraylist_add(g_deviceDiscoveredList, (void *) deviceAddr);
282     ca_mutex_unlock(g_deviceDiscoveredListMutex);
283
284     size_t len = strlen(scanInfo->remote_address);
285
286     char *addr = (char *)OICMalloc(sizeof(char) * (len + 1));
287     VERIFY_NON_NULL_VOID(addr, TAG, "Malloc failed");
288
289     strncpy(addr, scanInfo->remote_address, len + 1);
290
291     OIC_LOG_V(DEBUG, TAG,
292               "Trying to do Gatt connection to [%s]", addr);
293
294     ca_mutex_lock(g_LEClientThreadPoolMutex);
295     if (NULL == g_LEClientThreadPool)
296     {
297         OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
298         OICFree(addr);
299         ca_mutex_unlock(g_LEClientThreadPoolMutex);
300         return;
301     }
302
303     CAResult_t res = ca_thread_pool_add_task(g_LEClientThreadPool, CAGattConnectThread, addr);
304     if (CA_STATUS_OK != res)
305     {
306         OIC_LOG_V(ERROR, TAG,
307                   "ca_thread_pool_add_task failed with ret [%d]", res);
308         OICFree(addr);
309     }
310     ca_mutex_unlock(g_LEClientThreadPoolMutex);
311     OIC_LOG(DEBUG, TAG, "OUT");
312 }
313
314 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
315 {
316     OIC_LOG(DEBUG, TAG, "IN");
317
318     ca_mutex_lock(g_LEClientThreadPoolMutex);
319     g_LEClientThreadPool = handle;
320     ca_mutex_unlock(g_LEClientThreadPoolMutex);
321
322     OIC_LOG(DEBUG, TAG, "OUT");
323 }
324
325 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
326 {
327     OIC_LOG(DEBUG, TAG, "IN");
328
329     ca_mutex_lock(g_LEReqRespClientCbMutex);
330
331     g_LEClientDataReceivedCallback = callback;
332
333     ca_mutex_unlock(g_LEReqRespClientCbMutex);
334
335     OIC_LOG(DEBUG, TAG, "OUT");
336 }
337
338 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
339 {
340     g_clientErrorCallback = callback;
341 }
342
343 CAResult_t CAStartLEGattClient()
344 {
345     OIC_LOG(DEBUG, TAG, "IN");
346
347     ca_mutex_lock(g_LEClientThreadPoolMutex);
348     if (NULL == g_LEClientThreadPool)
349     {
350         OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL");
351         CATerminateGattClientMutexVariables();
352         ca_mutex_unlock(g_LEClientThreadPoolMutex);
353         return CA_STATUS_FAILED;
354     }
355
356     CAResult_t result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartLEGattClientThread,
357                                      NULL);
358     if (CA_STATUS_OK != result)
359     {
360         OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed");
361         CATerminateGattClientMutexVariables();
362         ca_mutex_unlock(g_LEClientThreadPoolMutex);
363         return CA_STATUS_FAILED;
364     }
365     ca_mutex_unlock(g_LEClientThreadPoolMutex);
366
367     OIC_LOG(DEBUG, TAG, "OUT");
368     return CA_STATUS_OK;
369 }
370
371 void CAStartLEGattClientThread(void *data)
372 {
373     OIC_LOG(DEBUG, TAG, "IN");
374
375     ca_mutex_lock(g_LEClientStateMutex);
376     if (true  == g_isLEGattClientStarted)
377     {
378         OIC_LOG(ERROR, TAG, "Gatt Client is already running!!");
379         ca_mutex_unlock(g_LEClientStateMutex);
380         return;
381     }
382
383     CAResult_t  result = CALEGattSetCallbacks();
384     if (CA_STATUS_OK != result)
385     {
386         OIC_LOG(ERROR, TAG, "CABleGattSetCallbacks Failed");
387         ca_mutex_unlock(g_LEClientStateMutex);
388         CATerminateLEGattClient();
389         return;
390     }
391
392     g_isLEGattClientStarted = true;
393     ca_mutex_unlock(g_LEClientStateMutex);
394
395     ca_mutex_lock(g_LEClientThreadPoolMutex);
396     if (NULL == g_LEClientThreadPool)
397     {
398         OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL");
399         CATerminateGattClientMutexVariables();
400         ca_mutex_unlock(g_LEClientThreadPoolMutex);
401         return;
402     }
403
404     result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartTimerThread,
405                                      NULL);
406     if (CA_STATUS_OK != result)
407     {
408         OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed");
409         ca_mutex_unlock(g_LEClientThreadPoolMutex);
410         return;
411     }
412     ca_mutex_unlock(g_LEClientThreadPoolMutex);
413
414     OIC_LOG(DEBUG, TAG, "Giving the control to threadPool");
415
416     GMainContext *thread_context = g_main_context_new();
417
418     g_eventLoop = g_main_loop_new(thread_context, FALSE);
419
420     g_main_context_push_thread_default(thread_context);
421
422     g_main_loop_run(g_eventLoop);
423
424     OIC_LOG(DEBUG, TAG, "OUT");
425 }
426
427 void CAStartTimerThread(void *data)
428 {
429     OIC_LOG(DEBUG, TAG, "IN");
430     while (g_isLEGattClientStarted)
431     {
432         ca_mutex_lock(g_multicastDataListMutex);
433         if (!g_isMulticastInProgress)
434         {
435             OIC_LOG(DEBUG, TAG, "waiting....");
436             ca_cond_wait(g_startTimerCond, g_multicastDataListMutex);
437             OIC_LOG(DEBUG, TAG, "Wake up");
438             g_isMulticastInProgress = true;
439         }
440
441         // Timed conditional wait for stopping the scan.
442         CAWaitResult_t ret = ca_cond_wait_for(g_scanningTimeCond, g_multicastDataListMutex,
443                                               TIMEOUT);
444         if (CA_WAIT_TIMEDOUT == ret)
445         {
446             OIC_LOG(DEBUG, TAG, "Scan is timed Out");
447             // Call stop scan.
448             CALEGattStopDeviceScanning();
449
450             // Clear the data list and device list.
451             u_arraylist_destroy(g_multicastDataList);
452             g_multicastDataList = NULL;
453
454             ca_mutex_lock(g_deviceDiscoveredListMutex);
455             u_arraylist_destroy(g_deviceDiscoveredList);
456             g_deviceDiscoveredList = NULL;
457             ca_mutex_unlock(g_deviceDiscoveredListMutex);
458
459             g_isMulticastInProgress = false;
460         }
461         ca_mutex_unlock(g_multicastDataListMutex);
462     }
463
464     OIC_LOG(DEBUG, TAG, "OUT");
465 }
466
467 void CAStopLEGattClient()
468 {
469     OIC_LOG(DEBUG,  TAG, "IN");
470
471     ca_mutex_lock(g_LEClientStateMutex);
472
473     if (false == g_isLEGattClientStarted)
474     {
475         OIC_LOG(ERROR, TAG, "Gatt Client is not running to stop");
476         ca_mutex_unlock(g_LEClientStateMutex);
477         return;
478     }
479
480     CALEGattUnSetCallbacks();
481
482     CALEGattStopDeviceScanning();
483
484     g_isLEGattClientStarted = false;
485
486     // Signal the conditions waiting in Start timer.
487     ca_cond_signal(g_startTimerCond);
488     ca_cond_signal(g_scanningTimeCond);
489
490     // Destroy the multicast data list and device list if not empty.
491     if (NULL != g_multicastDataList)
492     {
493         ca_mutex_lock(g_multicastDataListMutex);
494         u_arraylist_destroy(g_multicastDataList);
495         g_multicastDataList = NULL;
496         ca_mutex_unlock(g_multicastDataListMutex);
497     }
498
499     if (NULL != g_deviceDiscoveredList)
500     {
501         ca_mutex_lock(g_deviceDiscoveredListMutex);
502         u_arraylist_destroy(g_deviceDiscoveredList);
503         g_deviceDiscoveredList = NULL;
504         ca_mutex_unlock(g_deviceDiscoveredListMutex);
505     }
506
507     ca_mutex_lock(g_LEServerListMutex);
508     CAFreeLEServerList(g_LEServerList);
509     g_LEServerList = NULL;
510     ca_mutex_unlock(g_LEServerListMutex);
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_startTimerCond)
634     {
635         g_startTimerCond = ca_cond_new();
636         if (NULL == g_startTimerCond)
637         {
638             OIC_LOG(ERROR, TAG, "ca_cond_new failed");
639             return CA_STATUS_FAILED;
640         }
641     }
642
643     if (NULL == g_scanningTimeCond)
644     {
645         g_scanningTimeCond = ca_cond_new();
646         if (NULL == g_scanningTimeCond)
647         {
648             OIC_LOG(ERROR, TAG, "ca_cond_new failed");
649             return CA_STATUS_FAILED;
650         }
651     }
652
653     OIC_LOG(DEBUG,  TAG, "OUT");
654     return CA_STATUS_OK;
655 }
656
657 void CATerminateGattClientMutexVariables()
658 {
659     OIC_LOG(DEBUG,  TAG, "IN");
660
661     ca_mutex_free(g_LEClientStateMutex);
662     g_LEClientStateMutex = NULL;
663
664     ca_mutex_free(g_LEServerListMutex);
665     g_LEServerListMutex = NULL;
666
667     ca_mutex_free(g_LEReqRespClientCbMutex);
668     g_LEReqRespClientCbMutex = NULL;
669
670     ca_mutex_free(g_LEClientConnectMutex);
671     g_LEClientConnectMutex = NULL;
672
673     ca_mutex_free(g_LEClientThreadPoolMutex);
674     g_LEClientThreadPoolMutex = NULL;
675
676     ca_mutex_free(g_multicastDataListMutex);
677     g_multicastDataListMutex = NULL;
678
679     ca_mutex_free(g_deviceDiscoveredListMutex);
680     g_deviceDiscoveredListMutex = NULL;
681
682     ca_cond_free(g_startTimerCond);
683     g_startTimerCond = NULL;
684
685     ca_cond_free(g_scanningTimeCond);
686     g_scanningTimeCond = NULL;
687
688     OIC_LOG(DEBUG,  TAG, "OUT");
689 }
690
691 CAResult_t CALEGattSetCallbacks()
692 {
693     OIC_LOG(DEBUG, TAG, "IN");
694
695     int ret = bt_gatt_set_connection_state_changed_cb(CALEGattConnectionStateChangedCb, NULL);
696     if (BT_ERROR_NONE != ret)
697     {
698         OIC_LOG_V(ERROR, TAG,
699                   "bt_gatt_set_connection_state_changed_cb Failed with return as [%s ]",
700                   CALEGetErrorMsg(ret));
701         return CA_STATUS_FAILED;
702     }
703
704     OIC_LOG(DEBUG, TAG, "OUT");
705     return CA_STATUS_OK;
706 }
707
708 void CALEGattUnSetCallbacks()
709 {
710     OIC_LOG(DEBUG, TAG, "IN");
711
712     bt_gatt_unset_connection_state_changed_cb();
713
714     int numOfServersConnected = CAGetRegisteredServiceCount();
715     LEServerInfo *leServerInfo = NULL;
716
717     for (int32_t index = 0; index < numOfServersConnected; index++)
718     {
719         CAGetLEServerInfoByPosition(g_LEServerList, index, &leServerInfo);
720         bt_gatt_client_unset_characteristic_value_changed_cb(leServerInfo->readChar);
721     }
722     OIC_LOG(DEBUG, TAG, "OUT");
723 }
724
725 CAResult_t CALEGattStartDeviceScanning()
726 {
727     OIC_LOG(DEBUG, TAG, "IN");
728
729     int ret = bt_adapter_le_start_scan(CALEAdapterScanResultCb, NULL);
730     if(BT_ERROR_NONE != ret)
731     {
732         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_scan failed[%s]",
733                   CALEGetErrorMsg(ret));
734         return CA_STATUS_FAILED;
735     }
736
737     OIC_LOG(DEBUG, TAG, "OUT");
738     return CA_STATUS_OK;
739 }
740
741 void CALEGattStopDeviceScanning()
742 {
743     OIC_LOG(DEBUG, TAG, "IN");
744
745     int ret = bt_adapter_le_stop_scan();
746     if (BT_ERROR_NONE != ret)
747     {
748         OIC_LOG_V(ERROR, TAG, "bt_adapter_le_stop_scan failed[%s]",
749                   CALEGetErrorMsg(ret));
750     }
751
752     OIC_LOG(DEBUG, TAG, "OUT");
753 }
754
755 void CAGattConnectThread (void *remoteAddress)
756 {
757     OIC_LOG(DEBUG, TAG, "IN ");
758
759     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
760
761     char *address  = (char *)remoteAddress;
762
763     OIC_LOG_V(DEBUG, TAG, "remote address is [%s]", address);
764
765     CAResult_t result = CALEGattConnect(address);
766
767     if (CA_STATUS_OK != result)
768     {
769         OIC_LOG_V(ERROR, TAG, "bt_gatt_connect failed for [%s]", address);
770     }
771
772     OICFree(address);
773
774     OIC_LOG(DEBUG, TAG, "OUT");
775 }
776
777 CAResult_t CALEGattConnect(const char *remoteAddress)
778 {
779     OIC_LOG(DEBUG, TAG, "IN");
780
781     VERIFY_NON_NULL_RET(remoteAddress, TAG,
782                         "remote address is NULL", CA_STATUS_FAILED);
783
784     ca_mutex_lock(g_LEClientConnectMutex);
785
786     int ret = bt_gatt_connect(remoteAddress, true);
787
788     if (BT_ERROR_NONE != ret)
789     {
790         OIC_LOG_V(ERROR, TAG, "bt_gatt_connect Failed with ret value [%s] ",
791                   CALEGetErrorMsg(ret));
792         ca_mutex_unlock(g_LEClientConnectMutex);
793         return CA_STATUS_FAILED;
794     }
795     ca_mutex_unlock(g_LEClientConnectMutex);
796
797     OIC_LOG(DEBUG, TAG, "OUT");
798     return CA_STATUS_OK;
799 }
800
801 CAResult_t CALEGattDisConnect(const char *remoteAddress)
802 {
803     OIC_LOG(DEBUG, TAG, "IN");
804
805     VERIFY_NON_NULL_RET(remoteAddress, TAG,
806                         "remote address is NULL", CA_STATUS_FAILED);
807
808     int ret = bt_gatt_disconnect(remoteAddress);
809
810     if (BT_ERROR_NONE != ret)
811     {
812         OIC_LOG_V(ERROR, TAG, "bt_gatt_disconnect Failed with ret value [%d] ",
813                   CALEGetErrorMsg(ret));
814         return CA_STATUS_FAILED;
815     }
816
817     OIC_LOG(DEBUG, TAG, "OUT");
818     return CA_STATUS_OK;
819 }
820
821 void CADiscoverLEServicesThread (void *remoteAddress)
822 {
823     OIC_LOG(DEBUG, TAG, "IN");
824
825     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
826
827     char *address  = (char *)remoteAddress;
828
829     CAResult_t result = CALEGattDiscoverServices(address);
830     if (CA_STATUS_OK != result)
831     {
832         OIC_LOG(ERROR, TAG, "CALEGattDiscoverServices failed");
833     }
834
835     OICFree(address);
836     OIC_LOG(DEBUG, TAG, "OUT");
837 }
838
839 CAResult_t CALEGattDiscoverServices(const char *remoteAddress)
840 {
841     OIC_LOG(DEBUG, TAG, "IN");
842
843     VERIFY_NON_NULL_RET(remoteAddress, TAG,
844                         "remote address is NULL", CA_STATUS_FAILED);
845
846     bt_gatt_client_h clientHandle = NULL;
847     int32_t ret = bt_gatt_client_create(remoteAddress, &clientHandle);
848     if (BT_ERROR_NONE != ret || NULL == clientHandle)
849     {
850         OIC_LOG_V(ERROR, TAG,
851                   "bt_gatt_client_create Failed with ret value [%s] ", CALEGetErrorMsg(ret));
852         CALEGattDisConnect(remoteAddress);
853         return CA_STATUS_FAILED;
854     }
855
856     bt_gatt_h serviceHandle = NULL;
857     ret = bt_gatt_client_get_service(clientHandle, CA_GATT_SERVICE_UUID, &serviceHandle);
858     if (BT_ERROR_NONE != ret || NULL == serviceHandle)
859     {
860         OIC_LOG_V(ERROR, TAG,
861                   "bt_gatt_client_get_service Failed with ret value [%s] ", CALEGetErrorMsg(ret));
862         bt_gatt_client_destroy(clientHandle);
863         CALEGattDisConnect(remoteAddress);
864         return CA_STATUS_FAILED;
865     }
866
867     // Server will read data on this characteristic.
868     bt_gatt_h writeChrHandle = NULL;
869     ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_REQUEST_CHRC_UUID,
870                                              &writeChrHandle);
871     if (BT_ERROR_NONE != ret || NULL == writeChrHandle)
872     {
873         OIC_LOG_V(ERROR, TAG,
874                   "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
875                   CALEGetErrorMsg(ret));
876         bt_gatt_client_destroy(clientHandle);
877         CALEGattDisConnect(remoteAddress);
878         return CA_STATUS_FAILED;
879     }
880
881     // Server will notify data on this characteristic.
882     bt_gatt_h readChrHandle = NULL;
883     ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_RESPONSE_CHRC_UUID,
884                                              &readChrHandle);
885     if (BT_ERROR_NONE != ret || NULL == readChrHandle)
886     {
887         OIC_LOG_V(ERROR, TAG,
888                   "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
889                   CALEGetErrorMsg(ret));
890         bt_gatt_client_destroy(clientHandle);
891         CALEGattDisConnect(remoteAddress);
892         return CA_STATUS_FAILED;
893     }
894
895
896     //TODO: This data has to be freed while unsetting the callback.
897     char *addr = OICStrdup(remoteAddress);
898     ret = bt_gatt_client_set_characteristic_value_changed_cb(readChrHandle,
899                                                              CALEGattCharacteristicChangedCb,
900                                                              (void *)addr);
901     if (BT_ERROR_NONE != ret)
902     {
903         OIC_LOG_V(ERROR, TAG,
904                   "bt_gatt_client_set_characteristic_value_changed_cb Failed with ret value [%s]",
905                   CALEGetErrorMsg(ret));
906         bt_gatt_client_destroy(clientHandle);
907         CALEGattDisConnect(remoteAddress);
908         return CA_STATUS_FAILED;
909     }
910
911     LEServerInfo *serverInfo = (LEServerInfo *)OICCalloc(1, sizeof(LEServerInfo));
912     if (NULL == serverInfo)
913     {
914         OIC_LOG(ERROR, TAG, "Malloc failed");
915         CALEGattDisConnect(remoteAddress);
916         return CA_MEMORY_ALLOC_FAILED;
917     }
918     serverInfo->clientHandle = clientHandle;
919     serverInfo->serviceHandle = serviceHandle;
920     serverInfo->readChar = readChrHandle;
921     serverInfo->writeChar = writeChrHandle;
922     serverInfo->remoteAddress = OICStrdup(remoteAddress);
923
924     ca_mutex_lock(g_LEServerListMutex);
925     CAResult_t result = CAAddLEServerInfoToList(&g_LEServerList, serverInfo);
926     if (CA_STATUS_OK != result)
927     {
928         OIC_LOG(ERROR, TAG, "CAAddBLEClientInfoToList failed");
929         bt_gatt_client_destroy(clientHandle);
930         CALEGattDisConnect(remoteAddress);
931         return CA_STATUS_FAILED;
932     }
933     ca_mutex_unlock(g_LEServerListMutex);
934
935     // Send the data of pending multicast data list if any.
936     if (g_multicastDataList)
937     {
938         ca_mutex_lock(g_multicastDataListMutex);
939         uint32_t arrayLength = u_arraylist_length(g_multicastDataList);
940         for (int i = 0; i < arrayLength; i++)
941         {
942             CALEData_t *multicastData = u_arraylist_get(g_multicastDataList, i);
943             if (NULL == multicastData)
944             {
945                 OIC_LOG(DEBUG, TAG, "multicastData is NULL");
946                 continue;
947             }
948             CAUpdateCharacteristicsToGattServer(remoteAddress, multicastData->data,
949                                                 multicastData->dataLen, LE_UNICAST, 0);
950         }
951         ca_mutex_unlock(g_multicastDataListMutex);
952     }
953
954     OIC_LOG(DEBUG, TAG, "OUT");
955     return CA_STATUS_OK;
956 }
957
958 CAResult_t  CAUpdateCharacteristicsToGattServer(const char *remoteAddress,
959                                                 const uint8_t *data, const uint32_t dataLen,
960                                                 CALETransferType_t type, const int32_t position)
961 {
962     OIC_LOG(DEBUG, TAG, "IN");
963
964     VERIFY_NON_NULL(data, TAG, "data is NULL");
965
966     if (0 >= dataLen)
967     {
968         OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input!");
969         return CA_STATUS_INVALID_PARAM;
970     }
971
972     LEServerInfo *leServerInfo = NULL;
973     CAResult_t ret =  CA_STATUS_FAILED;
974
975     ca_mutex_lock(g_LEServerListMutex);
976     if (LE_UNICAST == type)
977     {
978         ret = CAGetLEServerInfo(g_LEServerList, remoteAddress, &leServerInfo);
979     }
980     else if (LE_MULTICAST == type)
981     {
982         ret = CAGetLEServerInfoByPosition(g_LEServerList, position, &leServerInfo);
983     }
984     ca_mutex_unlock(g_LEServerListMutex);
985
986     if (CA_STATUS_OK != ret)
987     {
988         OIC_LOG(ERROR, TAG, "CAGetBLEServiceInfoByPosition is failed");
989         return CA_STATUS_FAILED;
990     }
991
992     VERIFY_NON_NULL(leServerInfo, TAG, "bleServiceInfo is NULL");
993
994     OIC_LOG_V(DEBUG, TAG, "Updating the data of length [%d] to [%s] ", dataLen,
995               leServerInfo->remoteAddress);
996
997     int result = bt_gatt_set_value(leServerInfo->writeChar, (char *)data, dataLen);
998
999     if (BT_ERROR_NONE != result)
1000     {
1001         OIC_LOG_V(ERROR, TAG,
1002                   "bt_gatt_set_value Failed with return val [%s]",
1003                   CALEGetErrorMsg(result));
1004         return CA_STATUS_FAILED;
1005     }
1006
1007     result = bt_gatt_client_write_value(leServerInfo->writeChar, CALEGattCharacteristicWriteCb,
1008                                         NULL);
1009     if (BT_ERROR_NONE != result)
1010     {
1011         OIC_LOG_V(ERROR, TAG,
1012                   "bt_gatt_client_write_value Failed with return val [%s]",
1013                   CALEGetErrorMsg(result));
1014         return CA_STATUS_FAILED;
1015     }
1016
1017     OIC_LOG(DEBUG, TAG, "OUT");
1018     return CA_STATUS_OK;
1019 }
1020
1021 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
1022 {
1023     OIC_LOG(DEBUG,  TAG, "IN");
1024
1025     VERIFY_NON_NULL(data, TAG, "data is NULL");
1026
1027     if (0 >= dataLen)
1028     {
1029         OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input !");
1030         return CA_STATUS_INVALID_PARAM;
1031     }
1032
1033     int numOfServersConnected = CAGetRegisteredServiceCount();
1034
1035     // Send data to already connected devices.
1036     for (int32_t pos = 0; pos < numOfServersConnected; pos++)
1037     {
1038         /*remoteAddress will be NULL.
1039           Since we have to send to all destinations. pos will be used for getting remote address.
1040          */
1041         int32_t ret = CAUpdateCharacteristicsToGattServer(NULL, data, dataLen, LE_MULTICAST, pos);
1042
1043         if (CA_STATUS_OK != ret)
1044         {
1045             OIC_LOG_V(ERROR, TAG,
1046                       "CAUpdateCharacteristicsToGattServer Failed with return val [%d] ", ret);
1047             g_clientErrorCallback(NULL, data, dataLen, ret);
1048         }
1049     }
1050
1051     // Add the data to pending list.
1052     CALEData_t *multicastData = (CALEData_t *)OICCalloc(1, sizeof(CALEData_t));
1053     if (NULL == multicastData)
1054     {
1055         OIC_LOG(ERROR, TAG, "Calloc failed");
1056         goto exit;
1057     }
1058     multicastData->data = OICCalloc(1, dataLen);
1059     if (NULL == multicastData->data)
1060     {
1061         OIC_LOG(ERROR, TAG, "Calloc failed");
1062         goto exit;
1063     }
1064     memcpy(multicastData->data, data, dataLen);
1065     multicastData->dataLen = dataLen;
1066
1067     ca_mutex_lock(g_multicastDataListMutex);
1068     if (NULL == g_multicastDataList)
1069     {
1070         g_multicastDataList = u_arraylist_create();
1071     }
1072     u_arraylist_add(g_multicastDataList, (void *)multicastData);
1073     ca_mutex_unlock(g_multicastDataListMutex);
1074
1075     // Start the scanning.
1076     CAResult_t result = CALEGattStartDeviceScanning();
1077     if (CA_STATUS_OK != result)
1078     {
1079         OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed");
1080         goto exit;
1081     }
1082
1083     // Start the timer by signalling it.
1084     ca_cond_signal(g_startTimerCond);
1085
1086 exit:
1087     OIC_LOG(DEBUG, TAG, "OUT ");
1088     return CA_STATUS_OK;
1089 }
1090
1091