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