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