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