Imported Upstream version 0.9.1
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / tizen / cableclient.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 "cableclient.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 "camsgparser.h"
38 #include "oic_string.h"
39 #include "oic_malloc.h"
40
41 /**
42  * @def TZ_BLE_CLIENT_TAG
43  * @brief Logging tag for module name
44  */
45 #define TZ_BLE_CLIENT_TAG "TZ_BLE_GATT_CLIENT"
46
47 /**
48  * @var BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG
49  * @brief Its the constant value for characteristic descriptor from spec.
50  */
51 #define BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG "2902"
52
53 /**
54  * @var g_bLEServiceList
55  * @brief This contains the list of OIC services a client connect tot.
56  */
57 static BLEServiceList *g_bLEServiceList = NULL;
58
59 /**
60  * @var g_isBleGattClientStarted
61  * @brief Boolean variable to keep the state of the GATT Client.
62  */
63 static bool g_isBleGattClientStarted = false;
64
65 /**
66  * @var g_bleServiceListMutex
67  * @brief Mutex to synchronize access to BleServiceList.
68  */
69 static ca_mutex g_bleServiceListMutex = NULL;
70
71 /**
72  * @var g_bleReqRespClientCbMutex
73  * @brief Mutex to synchronize access to the requestResponse callback to be called
74  *           when the data needs to be sent from GATTClient.
75  */
76 static ca_mutex g_bleReqRespClientCbMutex = NULL;
77
78 /**
79  * @var g_bleReqRespClientCbMutex
80  * @brief Mutex to synchronize access to the requestResponse callback to be called
81  *           when the data needs to be sent from GATTClient.
82  */
83 static ca_mutex g_bleClientConnectMutex = NULL;
84
85
86 /**
87  * @var g_bleClientStateMutex
88  * @brief Mutex to synchronize the calls to be done to the platform from GATTClient
89  *           interfaces from different threads.
90  */
91 static ca_mutex g_bleClientStateMutex = NULL;
92
93 /**
94  * @var g_bleServerBDAddressMutex
95  * @brief Mutex to synchronize the Server BD Address update on client side.
96  */
97 static ca_mutex g_bleServerBDAddressMutex = NULL;
98
99 /**
100  * @var g_bleClientSendCondWait
101  * @brief Condition used for notifying handler the presence of data in send queue.
102  */
103 static ca_cond g_bleClientSendCondWait = NULL;
104
105 /**
106  * @var g_bleClientThreadPoolMutex
107  * @brief Mutex to synchronize the task to be pushed to thread pool.
108  */
109 static ca_mutex g_bleClientThreadPoolMutex = NULL;
110
111 /**
112  * @var gNetworkPacketReceivedClientCallback
113  * @brief Maintains the callback to be notified on receival of network packets from other
114  *           BLE devices
115  */
116 static CABLEClientDataReceivedCallback g_bleClientDataReceivedCallback = NULL;
117
118 /**
119  * @var g_eventLoop
120  * @brief gmainLoop to manage the threads to receive the callback from the platfrom.
121  */
122 static GMainLoop *g_eventLoop = NULL;
123
124 /**
125  * @var g_bleClientThreadPool
126  * @brief reference to threadpool
127  */
128 static ca_thread_pool_t g_bleClientThreadPool = NULL;
129
130 /**
131  * @struct stGattServiceInfo_t
132  * @brief structure to map the service attribute to BD Address.
133  */
134 typedef struct gattService
135 {
136     bt_gatt_attribute_h serviceInfo;         /**< bluetoth attribute for oic service*/
137     char *address;                           /**< BD Address of */
138 } stGattServiceInfo_t;
139
140 /**
141  * @var g_remoteAddress
142  * @brief Remote address of Gatt Server
143  */
144 static char *g_remoteAddress = NULL;
145
146 void CABleGattCharacteristicChangedCb(bt_gatt_attribute_h characteristic,
147                                       unsigned char *value,
148                                       int valueLen, void *userData)
149 {
150     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
151
152     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Changed characteristic is  [%s]", (char *)characteristic);
153     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Changed characteristic value length [%d]", valueLen);
154
155     ca_mutex_lock(g_bleReqRespClientCbMutex);
156     if (NULL == g_bleClientDataReceivedCallback)
157     {
158         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "gReqRespCallback is NULL!");
159         ca_mutex_unlock(g_bleReqRespClientCbMutex);
160         return;
161     }
162     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Sending data up !");
163
164     ca_mutex_lock(g_bleServerBDAddressMutex);
165     uint32_t sentLength = 0;
166     g_bleClientDataReceivedCallback(g_remoteAddress, OIC_BLE_SERVICE_ID,
167                                      value, valueLen, &sentLength);
168
169     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Sent data Length is %d", sentLength);
170     ca_mutex_unlock(g_bleServerBDAddressMutex);
171
172     ca_mutex_unlock(g_bleReqRespClientCbMutex);
173
174     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
175 }
176
177 void CABleGattCharacteristicWriteCb(int result, void *userData)
178 {
179     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN ");
180
181
182     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT ");
183 }
184
185 void CABleGattDescriptorDiscoveredCb(int result, unsigned char format, int total,
186                                      bt_gatt_attribute_h descriptor,
187                                      bt_gatt_attribute_h characteristic, void *userData)
188 {
189     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
190
191     stGattCharDescriptor_t *stTemp = (stGattCharDescriptor_t *)OICCalloc(1, sizeof(
192                                                                          stGattCharDescriptor_t));
193
194     VERIFY_NON_NULL_VOID(stTemp, TZ_BLE_CLIENT_TAG, "malloc failed!");
195
196     stTemp->desc = (uint8_t *)OICMalloc(total);
197     if (NULL == stTemp->desc)
198     {
199         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "malloc failed");
200         OICFree(stTemp);
201         return;
202     }
203     memcpy(stTemp->desc, descriptor, total);
204
205     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "result[%d] format[%d] total[%d]", result, format, total);
206     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "characteristic [%s]", (const char *) characteristic);
207
208
209     bt_gatt_clone_attribute_handle(&(stTemp->characteristic), characteristic);
210     stTemp->total = total;
211
212     ca_mutex_lock(g_bleClientThreadPoolMutex);
213     if (NULL == g_bleClientThreadPool)
214     {
215         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "g_bleClientThreadPool is NULL");
216         bt_gatt_destroy_attribute_handle(stTemp->characteristic);
217         OICFree(stTemp->desc);
218         OICFree(stTemp);
219         ca_mutex_unlock(g_bleClientThreadPoolMutex);
220         return;
221     }
222
223     CAResult_t ret = ca_thread_pool_add_task(g_bleClientThreadPool,
224                                             CASetCharacteristicDescriptorValueThread,
225                                             stTemp);
226     if (CA_STATUS_OK != ret)
227     {
228         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "ca_thread_pool_add_task failed");
229         bt_gatt_destroy_attribute_handle(stTemp->characteristic);
230         OICFree(stTemp->desc);
231         OICFree(stTemp);
232         ca_mutex_unlock(g_bleClientThreadPoolMutex);
233         return;
234     }
235
236     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG,
237             "LE Client initialization flow complete");
238
239     ca_mutex_unlock(g_bleClientThreadPoolMutex);
240
241     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
242 }
243
244 bool CABleGattCharacteristicsDiscoveredCb(int result,
245         int inputIndex, int total,
246         bt_gatt_attribute_h characteristic, void *userData)
247 {
248
249     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
250
251     VERIFY_NON_NULL_RET(characteristic, TZ_BLE_CLIENT_TAG, "Param characteristic is NULL", false);
252
253     VERIFY_NON_NULL_RET(userData, TZ_BLE_CLIENT_TAG, "Param userData is NULL", false);
254
255     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
256               "result [%d] input_index [%d] total [%d]",
257               result, inputIndex, total);
258
259     BLEServiceInfo *bleServiceInfo = NULL;
260
261     ca_mutex_lock(g_bleServiceListMutex);
262
263     char *bdAddress = (char *) userData;
264     CAGetBLEServiceInfo(g_bLEServiceList, bdAddress, &bleServiceInfo);
265
266     ca_mutex_unlock(g_bleServiceListMutex);
267
268     char *uuid = NULL;
269     bt_gatt_get_service_uuid(characteristic, &uuid);
270
271     VERIFY_NON_NULL_RET(uuid, TZ_BLE_CLIENT_TAG, "uuid is NULL", false);
272
273     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "New Characteristics[%s] of uuid[%s] is obtained",
274               (char *)characteristic, uuid);
275
276     if(0 == strcasecmp(uuid, CA_BLE_READ_CHAR_UUID)) // Server will read on this characterisctics
277     {
278         OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG , "Read characteristics is obtained");
279         OICFree(uuid);
280         CAResult_t retVal = CAAppendBLECharInfo(characteristic, BLE_GATT_READ_CHAR, bleServiceInfo);
281         if (CA_STATUS_OK != retVal)
282         {
283             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "CAAppendBLECharInfo failed! ");
284             return false;
285         }
286
287         stGattServiceInfo_t *stTemp = (stGattServiceInfo_t *)OICCalloc(1,
288                                                                       sizeof(stGattServiceInfo_t));
289
290         VERIFY_NON_NULL_RET(stTemp, TZ_BLE_CLIENT_TAG, "calloc failed!", false);
291
292         size_t len = strlen(bdAddress);
293         stTemp->address = (char *)OICMalloc(sizeof(char) * (len + 1));
294         if (NULL == stTemp->address)
295         {
296             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "Malloc failed!");
297             OICFree(stTemp);
298             return false;
299         }
300
301         strncpy(stTemp->address, bdAddress, len + 1);
302         bt_gatt_clone_attribute_handle(&(stTemp->serviceInfo), characteristic);
303
304         ca_mutex_lock(g_bleClientThreadPoolMutex);
305         if (NULL == g_bleClientThreadPool)
306         {
307             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "g_bleClientThreadPool is NULL");
308             bt_gatt_destroy_attribute_handle(stTemp->serviceInfo);
309             OICFree(stTemp->address);
310             OICFree(stTemp);
311             ca_mutex_unlock(g_bleClientThreadPoolMutex);
312             return false;
313         }
314
315         retVal = ca_thread_pool_add_task(g_bleClientThreadPool,
316                                         CADiscoverDescriptorThread,
317                                         stTemp);
318         if (CA_STATUS_OK != retVal)
319         {
320             OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
321                       "ca_thread_pool_add_task failed with ret [%d]", retVal);
322             bt_gatt_destroy_attribute_handle(stTemp->serviceInfo);
323             OICFree(stTemp->address);
324             OICFree(stTemp);
325             ca_mutex_unlock(g_bleClientThreadPoolMutex);
326             return false;
327         }
328         ca_mutex_unlock(g_bleClientThreadPoolMutex);
329     }
330     else if (0 == strcasecmp(uuid, CA_BLE_WRITE_CHAR_UUID)) // Server will write on this characteristics.
331     {
332         OICFree(uuid);
333         OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG , "Write characteristics is obtained");
334         CAResult_t retVal = CAAppendBLECharInfo(characteristic, BLE_GATT_WRITE_CHAR, bleServiceInfo);
335         if (CA_STATUS_OK != retVal)
336         {
337             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "CAAppendBLECharInfo failed ");
338             return false;
339         }
340     }
341
342     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
343     return true;
344 }
345
346 bool CABleGattPrimaryServiceCb(bt_gatt_attribute_h service, int index, int count,
347                                void *userData)
348 {
349     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
350
351     VERIFY_NON_NULL_RET(service, TZ_BLE_CLIENT_TAG, "Param service is NULL", false);
352
353     VERIFY_NON_NULL_RET(userData, TZ_BLE_CLIENT_TAG, "Param userData is NULL", false);
354
355     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Service info [%s] index [%d] count [%d]", (char *)service,
356               index, count);
357
358     CAResult_t result = CAVerifyOICServiceByServiceHandle(service);
359
360     if (CA_STATUS_OK == result)
361     {
362         OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Its OIC service");
363
364         OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG , "Registering to watch characteristics changes");
365
366         result = CABleGattWatchCharacteristicChanges(service);
367         if (CA_STATUS_OK != result)
368         {
369             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG,
370                       "CABleGattWatchCharacteristicChanges failed!");
371             return false;
372         }
373
374         stGattServiceInfo_t *stTemp = (stGattServiceInfo_t *)OICCalloc(1,
375                                                                       sizeof(stGattServiceInfo_t));
376         VERIFY_NON_NULL_RET(stTemp, TZ_BLE_CLIENT_TAG, "Calloc Failed", false);
377
378         char *bdAddress = (char *)userData;
379         size_t len = strlen(bdAddress);
380
381         stTemp->address = (char *)OICMalloc(sizeof(char) * (len + 1));
382         if (NULL == stTemp->address)
383         {
384             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "Malloc failed!");
385             OICFree(stTemp);
386             return false;
387         }
388
389         strncpy(stTemp->address, bdAddress, len + 1);
390
391         BLEServiceInfo *bleServiceInfo = NULL;
392
393         result = CACreateBLEServiceInfo(bdAddress, service, &bleServiceInfo);
394         if (CA_STATUS_OK != result)
395         {
396             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "CACreateBLEServiceInfo failed! ");
397             OICFree(stTemp->address);
398             OICFree(stTemp);
399             OICFree(bleServiceInfo);
400             return false;
401         }
402         if (NULL == bleServiceInfo )
403         {
404             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , " bleServiceInfo is NULL");
405             OICFree(stTemp->address);
406             OICFree(stTemp);
407             OICFree(bleServiceInfo);
408             return false;
409         }
410
411         OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG ,
412                   " serviceInfo remote address [%s]", bleServiceInfo->bdAddress);
413
414         ca_mutex_lock(g_bleServiceListMutex);
415         result = CAAddBLEServiceInfoToList(&g_bLEServiceList, bleServiceInfo);
416         ca_mutex_unlock(g_bleServiceListMutex);
417         if (CA_STATUS_OK != result)
418         {
419             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "CAAddBLEServiceInfoToList failed!");
420             OICFree(stTemp->address);
421             OICFree(stTemp);
422             CAFreeBLEServiceInfo(bleServiceInfo);
423             return false;
424         }
425
426
427         ca_mutex_lock(g_bleClientThreadPoolMutex);
428         if (NULL == g_bleClientThreadPool)
429         {
430             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "g_bleClientThreadPool is NULL");
431             OICFree(stTemp->address);
432             OICFree(stTemp);
433             ca_mutex_lock(g_bleServiceListMutex);
434             CARemoveBLEServiceInfoToList(&g_bLEServiceList, bleServiceInfo,
435                                          bleServiceInfo->bdAddress);
436             ca_mutex_unlock(g_bleServiceListMutex);
437             ca_mutex_unlock(g_bleClientThreadPoolMutex);
438             return false;
439         }
440         bt_gatt_clone_attribute_handle(&(stTemp->serviceInfo), service);
441
442         result = ca_thread_pool_add_task(g_bleClientThreadPool,
443                                         CADiscoverCharThread,
444                                         stTemp);
445         if (CA_STATUS_OK != result)
446         {
447             OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
448                       "ca_thread_pool_add_task failed with ret [%d]", result);
449             OICFree(stTemp->address);
450             OICFree(stTemp);
451             ca_mutex_lock(g_bleServiceListMutex);
452             CARemoveBLEServiceInfoToList(&g_bLEServiceList, bleServiceInfo,
453                                          bleServiceInfo->bdAddress);
454             ca_mutex_unlock(g_bleServiceListMutex);
455             ca_mutex_unlock(g_bleClientThreadPoolMutex);
456             return false;
457         }
458         ca_mutex_unlock(g_bleClientThreadPoolMutex);
459     }
460
461     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT ");
462     return true;;
463 }
464
465 void CABleGattConnectionStateChangedCb(int result, bool connected,
466                                        const char *remoteAddress, void *userData)
467 {
468     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN ");
469
470     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "CABleGattConnectionStateChangedCb result[%d] ", result);
471
472     VERIFY_NON_NULL_VOID(remoteAddress, TZ_BLE_CLIENT_TAG, "remote address is NULL");
473
474     CAResult_t ret = CA_STATUS_FAILED;
475     if (!connected)
476     {
477         OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "DisConnected from [%s] ", remoteAddress);
478
479         ret = CABleGattStartDeviceDiscovery();
480         if (CA_STATUS_OK != ret)
481         {
482             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "CABleGattStartDeviceDiscovery failed");
483             return;
484         }
485     }
486     else
487     {
488         OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Connected to [%s] ", remoteAddress);
489
490         ca_mutex_lock(g_bleServerBDAddressMutex);
491
492         g_remoteAddress = OICStrdup(remoteAddress);
493
494         ca_mutex_unlock(g_bleServerBDAddressMutex);
495
496         VERIFY_NON_NULL_VOID(g_remoteAddress, TZ_BLE_CLIENT_TAG, "Malloc failed");
497
498         char *addr = OICStrdup(remoteAddress);
499
500         ca_mutex_lock(g_bleClientThreadPoolMutex);
501         if (NULL == g_bleClientThreadPool)
502         {
503             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "g_bleClientThreadPool is NULL");
504             OICFree(addr);
505
506             ca_mutex_lock(g_bleServerBDAddressMutex);
507             OICFree(g_remoteAddress);
508             ca_mutex_unlock(g_bleServerBDAddressMutex);
509
510             ca_mutex_unlock(g_bleClientThreadPoolMutex);
511             return;
512         }
513
514         ret = ca_thread_pool_add_task(g_bleClientThreadPool, CADiscoverBLEServicesThread,
515                                      addr);
516         if (CA_STATUS_OK != ret)
517         {
518             OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "ca_thread_pool_add_task failed with ret [%d]", ret);
519             OICFree(addr);
520
521             ca_mutex_lock(g_bleServerBDAddressMutex);
522             OICFree(g_remoteAddress);
523             ca_mutex_unlock(g_bleServerBDAddressMutex);
524
525             ca_mutex_unlock(g_bleClientThreadPoolMutex);
526             return;
527         }
528         ca_mutex_unlock(g_bleClientThreadPoolMutex);
529     }
530
531     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
532 }
533
534 void CABtAdapterLeDeviceDiscoveryStateChangedCb(int result,
535         bt_adapter_le_device_discovery_state_e discoveryState,
536         bt_adapter_le_device_discovery_info_s *discoveryInfo,
537         void *userData)
538 {
539     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
540
541     if (NULL  == discoveryInfo && BT_ADAPTER_LE_DEVICE_DISCOVERY_FOUND == discoveryState)
542     {
543         OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "discoveryInfo is NULL");
544         return;
545     }
546
547     if (BT_ADAPTER_LE_DEVICE_DISCOVERY_FOUND != discoveryState)
548     {
549         OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
550                   " LE Discovery state is [%s]",
551           discoveryState == BT_ADAPTER_LE_DEVICE_DISCOVERY_STARTED ? "Started" : "Finished");
552     }
553     else
554     {
555         CAPrintDiscoveryInformation(discoveryInfo);
556
557         if (discoveryInfo->service_uuid == NULL)
558         {
559             OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "NO UUIDS from device");
560         }
561         else
562         {
563             for (int32_t i = discoveryInfo->service_count - 1; i >= 0; i--)
564             {
565                 OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "uuid[%d]: [%s]",
566                           i, discoveryInfo->service_uuid[i]);
567                 CAResult_t res = CAVerifyOICServiceByUUID(discoveryInfo->service_uuid[i]);
568                 if (CA_STATUS_OK == res)
569                 {
570
571                     size_t len = strlen(discoveryInfo->remote_address);
572
573                     char *addr = (char *)OICMalloc(sizeof(char) * (len + 1));
574                     VERIFY_NON_NULL_VOID(addr, TZ_BLE_CLIENT_TAG, "Malloc failed");
575                     strncpy(addr, discoveryInfo->remote_address, len + 1);
576
577                     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
578                               "Trying to do Gatt connection to [%s]", addr);
579
580                     ca_mutex_lock(g_bleClientThreadPoolMutex);
581                     if (NULL == g_bleClientThreadPool)
582                     {
583                         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "g_bleClientThreadPool is NULL");
584                         OICFree(addr);
585                         ca_mutex_unlock(g_bleClientThreadPoolMutex);
586                         return;
587                     }
588
589                     CAResult_t ret = ca_thread_pool_add_task(g_bleClientThreadPool,
590                                                   CAGattConnectThread, addr);
591                     if (CA_STATUS_OK != ret)
592                     {
593                         OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
594                                   "ca_thread_pool_add_task failed with ret [%d]", ret);
595                         OICFree(addr);
596                         ca_mutex_unlock(g_bleClientThreadPoolMutex);
597                         return;
598                     }
599                     ca_mutex_unlock(g_bleClientThreadPoolMutex);
600                     if (discoveryInfo->adv_data_len > 31 || discoveryInfo->scan_data_len > 31)
601                     {
602                         bt_adapter_le_stop_device_discovery();
603                         return;
604                     }
605                     break;  // Found the OIC Service. No need to verify remaining services.
606                 }
607             }
608         }
609     }
610     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
611 }
612
613
614 void CAPrintDiscoveryInformation(const bt_adapter_le_device_discovery_info_s *discoveryInfo)
615 {
616     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
617
618     if (NULL == discoveryInfo)
619     {
620         OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "discoveryInfo is NULL ");
621         return;
622     }
623
624     if (discoveryInfo->remote_address)
625     {
626         OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Remote Address [%s]", discoveryInfo->remote_address);
627     }
628
629     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
630               " Adv data len [%d] Scan data len[%d]RSSI [%d] Addr_type [%d] ",
631               discoveryInfo->adv_data_len, discoveryInfo->scan_data_len, discoveryInfo->rssi,
632               discoveryInfo->address_type);
633     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
634               " Number of services present in device [%s] is [%d]",
635               discoveryInfo->remote_address, discoveryInfo->service_count);
636
637     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
638 }
639
640 void CASetBleClientThreadPoolHandle(ca_thread_pool_t handle)
641 {
642     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
643
644     ca_mutex_lock(g_bleClientThreadPoolMutex);
645     g_bleClientThreadPool = handle;
646     ca_mutex_unlock(g_bleClientThreadPoolMutex);
647
648     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
649 }
650
651 void CASetBLEReqRespClientCallback(CABLEClientDataReceivedCallback callback)
652 {
653     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
654
655     ca_mutex_lock(g_bleReqRespClientCbMutex);
656
657     g_bleClientDataReceivedCallback = callback;
658
659     ca_mutex_unlock(g_bleReqRespClientCbMutex);
660
661     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
662 }
663
664 CAResult_t CAStartBLEGattClient()
665 {
666     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
667
668     CAResult_t retVal = CAInitGattClientMutexVariables();
669
670     if (CA_STATUS_OK != retVal)
671     {
672         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "CAInitGattClientMutexVariables failed!");
673         CATerminateGattClientMutexVariables();
674         return CA_STATUS_FAILED;
675     }
676
677     ca_mutex_lock(g_bleClientThreadPoolMutex);
678     if (NULL == g_bleClientThreadPool)
679     {
680         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "gBleServerThreadPool is NULL");
681         CATerminateGattClientMutexVariables();
682         ca_mutex_unlock(g_bleClientThreadPoolMutex);
683         return CA_STATUS_FAILED;
684     }
685
686     retVal = ca_thread_pool_add_task(g_bleClientThreadPool, CAStartBleGattClientThread,
687                                      NULL);
688     if (CA_STATUS_OK != retVal)
689     {
690         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "ca_thread_pool_add_task failed");
691         CATerminateGattClientMutexVariables();
692         ca_mutex_unlock(g_bleClientThreadPoolMutex);
693         return CA_STATUS_FAILED;
694     }
695     ca_mutex_unlock(g_bleClientThreadPoolMutex);
696
697     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
698     return CA_STATUS_OK;
699 }
700
701 void CAStartBleGattClientThread(void *data)
702 {
703     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
704
705     ca_mutex_lock(g_bleClientStateMutex);
706
707     if (true  == g_isBleGattClientStarted)
708     {
709         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "Gatt Client is already running!!");
710         ca_mutex_unlock(g_bleClientStateMutex);
711         return;
712     }
713
714     CAResult_t  ret = CABleGattSetScanParameter();
715     if (CA_STATUS_OK != ret)
716     {
717         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "CABleSetScanParameter Failed");
718         ca_mutex_unlock(g_bleClientStateMutex);
719         CATerminateBLEGattClient();
720         return;
721     }
722
723     ret = CABleGattSetCallbacks();
724     if (CA_STATUS_OK != ret)
725     {
726         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "CABleGattSetCallbacks Failed");
727         ca_mutex_unlock(g_bleClientStateMutex);
728         CATerminateBLEGattClient();
729         return;
730     }
731
732     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Starting LE device discovery");
733
734     ret = CABleGattStartDeviceDiscovery();
735     if (CA_STATUS_OK != ret)
736     {
737         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "bt_adapter_le_start_device_discovery Failed");
738         ca_mutex_unlock(g_bleClientStateMutex);
739         CATerminateBLEGattClient();
740         return;
741     }
742
743     g_isBleGattClientStarted = true;
744
745     ca_mutex_unlock(g_bleClientStateMutex);
746
747     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "Giveing the control to threadPool");
748
749     GMainContext *thread_context = g_main_context_new();
750
751     g_eventLoop = g_main_loop_new(thread_context, FALSE);
752
753     g_main_context_push_thread_default(thread_context);
754
755     g_main_loop_run(g_eventLoop);
756
757     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
758 }
759
760 void CAStopBLEGattClient()
761 {
762     OIC_LOG(DEBUG,  TZ_BLE_CLIENT_TAG, "IN");
763
764     ca_mutex_lock(g_bleClientStateMutex);
765
766     if (false == g_isBleGattClientStarted)
767     {
768         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "Gatt Client is not running to stop");
769         ca_mutex_unlock(g_bleClientStateMutex);
770         return;
771     }
772
773     CABleGattUnSetCallbacks();
774
775     CABleGattUnWatchCharacteristicChanges();
776
777     CABleGattStopDeviceDiscovery();
778
779     g_isBleGattClientStarted = false;
780
781     GMainContext  *context_event_loop = NULL;
782     // Required for waking up the thread which is running in gmain loop
783     if (NULL != g_eventLoop)
784     {
785         context_event_loop = g_main_loop_get_context(g_eventLoop);
786     }
787     if (context_event_loop)
788     {
789         OIC_LOG_V(DEBUG,  TZ_BLE_CLIENT_TAG, "g_eventLoop context %x", context_event_loop);
790         g_main_context_wakeup(context_event_loop);
791
792         // Kill g main loops and kill threads.
793         g_main_loop_quit(g_eventLoop);
794     }
795     else
796     {
797         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "g_eventLoop context is NULL");
798     }
799
800     ca_mutex_unlock(g_bleClientStateMutex);
801
802     OIC_LOG(DEBUG,  TZ_BLE_CLIENT_TAG, "OUT");
803 }
804
805 void CATerminateBLEGattClient()
806 {
807     OIC_LOG(DEBUG,  TZ_BLE_CLIENT_TAG, "IN");
808     ca_mutex_lock(g_bleClientStateMutex);
809
810     ca_mutex_lock(g_bleServerBDAddressMutex);
811
812     OICFree(g_remoteAddress);
813
814     ca_mutex_unlock(g_bleServerBDAddressMutex);
815
816     ca_mutex_lock(g_bleServiceListMutex);
817     CAFreeBLEServiceList(g_bLEServiceList);
818     g_bLEServiceList = NULL;
819     ca_mutex_unlock(g_bleServiceListMutex);
820
821     CAResetRegisteredServiceCount();
822
823     ca_mutex_unlock(g_bleClientStateMutex);
824
825     CATerminateGattClientMutexVariables();
826
827     OIC_LOG(DEBUG,  TZ_BLE_CLIENT_TAG, "OUT");
828 }
829
830 CAResult_t CAInitGattClientMutexVariables()
831 {
832     OIC_LOG(DEBUG,  TZ_BLE_CLIENT_TAG, "IN");
833     if (NULL == g_bleClientStateMutex)
834     {
835         g_bleClientStateMutex = ca_mutex_new();
836         if (NULL == g_bleClientStateMutex)
837         {
838             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "ca_mutex_new failed");
839             return CA_STATUS_FAILED;
840         }
841     }
842
843     if (NULL == g_bleServiceListMutex)
844     {
845         g_bleServiceListMutex = ca_mutex_new();
846         if (NULL == g_bleServiceListMutex)
847         {
848             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "ca_mutex_new failed");
849             return CA_STATUS_FAILED;
850         }
851     }
852
853     if (NULL == g_bleReqRespClientCbMutex)
854     {
855         g_bleReqRespClientCbMutex = ca_mutex_new();
856         if (NULL == g_bleReqRespClientCbMutex)
857         {
858             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "ca_mutex_new failed");
859             return CA_STATUS_FAILED;
860         }
861     }
862
863     if (NULL == g_bleClientThreadPoolMutex)
864     {
865         g_bleClientThreadPoolMutex = ca_mutex_new();
866         if (NULL == g_bleClientThreadPoolMutex)
867         {
868             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "ca_mutex_new failed");
869             return CA_STATUS_FAILED;
870         }
871     }
872
873     if (NULL == g_bleClientConnectMutex)
874     {
875         g_bleClientConnectMutex = ca_mutex_new();
876         if (NULL == g_bleClientConnectMutex)
877         {
878             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "ca_mutex_new failed");
879             return CA_STATUS_FAILED;
880         }
881     }
882
883     if (NULL == g_bleClientSendCondWait)
884     {
885         g_bleClientSendCondWait = ca_cond_new();
886         if (NULL == g_bleClientSendCondWait)
887         {
888             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "ca_cond_new failed");
889             return CA_STATUS_FAILED;
890         }
891     }
892
893     if (NULL == g_bleServerBDAddressMutex)
894     {
895         g_bleServerBDAddressMutex = ca_mutex_new();
896         if (NULL == g_bleServerBDAddressMutex)
897         {
898             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "ca_mutex_new failed");
899             return CA_STATUS_FAILED;
900         }
901     }
902
903     OIC_LOG(DEBUG,  TZ_BLE_CLIENT_TAG, "OUT");
904     return CA_STATUS_OK;
905 }
906
907 void CATerminateGattClientMutexVariables()
908 {
909     OIC_LOG(DEBUG,  TZ_BLE_CLIENT_TAG, "IN");
910
911     ca_mutex_free(g_bleClientStateMutex);
912     g_bleClientStateMutex = NULL;
913
914     ca_mutex_free(g_bleServiceListMutex);
915     g_bleServiceListMutex = NULL;
916
917     ca_mutex_free(g_bleReqRespClientCbMutex);
918     g_bleReqRespClientCbMutex = NULL;
919
920     ca_mutex_free(g_bleClientConnectMutex);
921     g_bleClientConnectMutex = NULL;
922
923     ca_mutex_free(g_bleClientThreadPoolMutex);
924     g_bleClientThreadPoolMutex = NULL;
925
926     ca_mutex_free(g_bleServerBDAddressMutex);
927     g_bleServerBDAddressMutex = NULL;
928
929     ca_cond_free(g_bleClientSendCondWait);
930     g_bleClientSendCondWait = NULL;
931
932
933     OIC_LOG(DEBUG,  TZ_BLE_CLIENT_TAG, "OUT");
934 }
935
936 CAResult_t CABleGattSetScanParameter()
937 {
938     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
939
940     bt_adapter_le_scan_params_s scan_param = { 0, };
941     scan_param.type = BT_ADAPTER_LE_PASSIVE_SCAN;
942     scan_param.interval = 1560;
943     scan_param.window = 160;
944
945     int ret = bt_adapter_le_set_scan_parameter(&scan_param);
946     if (BT_ERROR_NONE != ret)
947     {
948         OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "bt_adapter_le_set_scan_parameter Failed with ret [%d]", ret);
949         return CA_STATUS_FAILED;
950     }
951
952     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
953     return CA_STATUS_OK;
954 }
955
956 CAResult_t CABleGattSetCallbacks()
957 {
958     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
959
960     int ret = bt_gatt_set_connection_state_changed_cb(CABleGattConnectionStateChangedCb, NULL);
961     if (BT_ERROR_NONE != ret)
962     {
963         OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
964                   "bt_gatt_set_connection_state_changed_cb Failed with return as [%s ]",
965                   CABTGetErrorMsg(ret));
966         return CA_STATUS_FAILED;
967     }
968
969     ret = bt_adapter_le_set_device_discovery_state_changed_cb(
970               CABtAdapterLeDeviceDiscoveryStateChangedCb, NULL);
971     if (BT_ERROR_NONE != ret)
972     {
973         OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
974                   "bt_adapter_le_set_device_discovery_state_changed_cb Failed with return as [%s ]",
975                   CABTGetErrorMsg(ret));;
976         return CA_STATUS_FAILED;
977     }
978
979     ret = bt_gatt_set_characteristic_changed_cb(CABleGattCharacteristicChangedCb, NULL);
980     if (BT_ERROR_NONE != ret)
981     {
982         OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "bt_gatt_set_characteristic_changed_cb Failed as [%s ]",
983                   CABTGetErrorMsg(ret));
984         return CA_STATUS_FAILED;
985     }
986
987     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
988     return CA_STATUS_OK;
989 }
990
991 void CABleGattUnSetCallbacks()
992 {
993     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
994
995     bt_gatt_unset_characteristic_changed_cb();
996
997     bt_gatt_unset_connection_state_changed_cb();
998
999     bt_adapter_le_unset_device_discovery_state_changed_cb();
1000
1001     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1002 }
1003
1004 CAResult_t CABleGattWatchCharacteristicChanges(bt_gatt_attribute_h service)
1005 {
1006     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1007
1008     int ret = bt_gatt_watch_characteristic_changes(service);
1009     if (BT_ERROR_NONE != ret)
1010     {
1011         OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
1012                   "bt_gatt_watch_characteristic_changes failed  with [%s]",
1013                   CABTGetErrorMsg(ret));
1014
1015         return CA_STATUS_FAILED;
1016     }
1017
1018     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1019     return CA_STATUS_OK;
1020 }
1021
1022 void CABleGattUnWatchCharacteristicChanges()
1023 {
1024     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1025
1026     int32_t count = CAGetRegisteredServiceCount();
1027
1028     for (int32_t index = 0; index < count; index++)
1029     {
1030         BLEServiceInfo *bleServiceInfo = NULL;
1031
1032         ca_mutex_lock(g_bleServiceListMutex);
1033
1034         CAResult_t  result = CAGetBLEServiceInfoByPosition(g_bLEServiceList, index, &bleServiceInfo);
1035         if (CA_STATUS_OK == result && NULL != bleServiceInfo
1036             && NULL != bleServiceInfo->service_clone)
1037         {
1038             bt_gatt_unwatch_characteristic_changes(bleServiceInfo->service_clone);
1039             OIC_LOG(INFO, TZ_BLE_CLIENT_TAG, "bt_gatt_unwatch_characteristic_changes done");
1040         }
1041
1042         ca_mutex_unlock(g_bleServiceListMutex);
1043     }
1044
1045     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1046 }
1047
1048 CAResult_t CABleGattStartDeviceDiscovery()
1049 {
1050     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1051     bool isDiscovering = false;
1052
1053     int ret = bt_adapter_le_is_discovering(&isDiscovering);
1054     if (BT_ERROR_NONE != ret)
1055     {
1056         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "bt_adapter_le_is_discovering Failed");
1057         return CA_STATUS_FAILED;
1058     }
1059
1060     if(!isDiscovering)
1061     {
1062         ret = bt_adapter_le_start_device_discovery();
1063         if (BT_ERROR_NONE != ret)
1064         {
1065             OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "bt_adapter_le_start_device_discovery Failed Ret: %d, %x", ret, ret);
1066             return CA_STATUS_FAILED;
1067         }
1068     }
1069
1070     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1071     return CA_STATUS_OK;
1072 }
1073
1074 void CABleGattStopDeviceDiscovery()
1075 {
1076     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1077
1078     bool isDiscovering = false;
1079
1080     int ret = bt_adapter_le_is_discovering(&isDiscovering);
1081     if (BT_ERROR_NONE != ret)
1082     {
1083         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "bt_adapter_le_is_discovering Failed");
1084         return;
1085     }
1086
1087     if(isDiscovering)
1088     {
1089         ret = bt_adapter_le_stop_device_discovery();
1090         if (BT_ERROR_NONE != ret)
1091         {
1092             OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "bt_adapter_le_stop_device_discovery Failed");
1093             return;
1094         }
1095     }
1096
1097     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1098 }
1099
1100 void CAGattConnectThread (void *remoteAddress)
1101 {
1102     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN ");
1103
1104     VERIFY_NON_NULL_VOID(remoteAddress, TZ_BLE_CLIENT_TAG, "remote address is NULL");
1105
1106     char *address  = (char *)remoteAddress;
1107
1108     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "remote address is [%s]", address);
1109
1110     CAResult_t result = CABleGattConnect(address);
1111
1112     if (CA_STATUS_OK != result)
1113     {
1114         OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "bt_gatt_connect failed for [%s]", address);
1115     }
1116
1117     OICFree(address);
1118
1119     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1120 }
1121
1122 CAResult_t CABleGattConnect(const char *remoteAddress)
1123 {
1124     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1125
1126     VERIFY_NON_NULL_RET(remoteAddress, TZ_BLE_CLIENT_TAG,
1127                         "remote address is NULL", CA_STATUS_FAILED);
1128
1129     //Because of the platform issue, we added. Once platform is stablized, then it will be removed
1130     sleep(1);
1131
1132     ca_mutex_lock(g_bleClientConnectMutex);
1133
1134     int ret = bt_gatt_connect(remoteAddress, true);
1135
1136     if (BT_ERROR_NONE != ret)
1137     {
1138         OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "bt_gatt_connect Failed with ret value [%s] ",
1139                   CABTGetErrorMsg(ret));
1140         ca_mutex_unlock(g_bleClientConnectMutex);
1141         return CA_STATUS_FAILED;
1142     }
1143     ca_mutex_unlock(g_bleClientConnectMutex);
1144
1145     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1146     return CA_STATUS_OK;
1147 }
1148
1149 CAResult_t CABleGattDisConnect(const char *remoteAddress)
1150 {
1151     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1152
1153     VERIFY_NON_NULL_RET(remoteAddress, TZ_BLE_CLIENT_TAG,
1154                         "remote address is NULL", CA_STATUS_FAILED);
1155
1156     int32_t ret = bt_gatt_disconnect(remoteAddress);
1157
1158     if (BT_ERROR_NONE != ret)
1159     {
1160         OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG, "bt_gatt_disconnect Failed with ret value [%d] ",
1161                   ret);
1162         return CA_STATUS_FAILED;
1163     }
1164
1165     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1166     return CA_STATUS_OK;
1167 }
1168
1169 void CADiscoverBLEServicesThread (void *remoteAddress)
1170 {
1171     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1172
1173     VERIFY_NON_NULL_VOID(remoteAddress, TZ_BLE_CLIENT_TAG, "remote address is NULL");
1174
1175     char *address  = (char *)remoteAddress;
1176
1177     CAResult_t result = CABleGattDiscoverServices(address);
1178     if (CA_STATUS_OK != result)
1179     {
1180         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "CABleGattDiscoverServices failed");
1181     }
1182
1183     OICFree(address);
1184
1185     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT ");
1186 }
1187
1188 CAResult_t CABleGattDiscoverServices(const char *remoteAddress)
1189 {
1190     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1191
1192     VERIFY_NON_NULL_RET(remoteAddress, TZ_BLE_CLIENT_TAG,
1193                         "remote address is NULL", CA_STATUS_FAILED);
1194
1195     size_t len = strlen(remoteAddress);
1196     char *addr = (char *)OICMalloc(sizeof(char) * (len + 1));
1197     VERIFY_NON_NULL_RET(addr, TZ_BLE_CLIENT_TAG, "Malloc failed", CA_STATUS_FAILED);
1198
1199     strncpy(addr, remoteAddress, len + 1);
1200
1201     int32_t ret = bt_gatt_foreach_primary_services(remoteAddress, CABleGattPrimaryServiceCb,
1202                   (void *)addr); // addr memory will be free in callback.
1203     if (BT_ERROR_NONE != ret)
1204     {
1205         OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
1206                   "bt_gatt_foreach_primary_services Failed with ret value [%d] ", ret);
1207         OICFree(addr);
1208         return CA_STATUS_FAILED;
1209     }
1210     else
1211     {
1212         OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
1213                   "bt_gatt_foreach_primary_services success for address [%s]", remoteAddress);
1214     }
1215
1216     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1217     return CA_STATUS_OK;
1218 }
1219
1220 void CADiscoverCharThread(void *stServiceInfo)
1221 {
1222     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1223
1224     VERIFY_NON_NULL_VOID(stServiceInfo, TZ_BLE_CLIENT_TAG, "stServiceInfo is NULL");
1225
1226     stGattServiceInfo_t *stTemp  = (stGattServiceInfo_t *)stServiceInfo;
1227
1228     VERIFY_NON_NULL_VOID(stTemp->address, TZ_BLE_CLIENT_TAG, "stTemp->address is NULL");
1229
1230     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "remote address [%s]", stTemp->address);
1231
1232     CAResult_t  result = CABleGattDiscoverCharacteristics(stTemp->serviceInfo, stTemp->address);
1233     if (CA_STATUS_OK != result)
1234     {
1235         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "CABleGattDiscoverCharacteristics failed!");
1236         bt_gatt_destroy_attribute_handle(stTemp->serviceInfo);
1237         OICFree(stTemp->address);
1238         OICFree(stTemp);
1239         return;
1240     }
1241     bt_gatt_destroy_attribute_handle(stTemp->serviceInfo);
1242     OICFree(stTemp->address);
1243     OICFree(stTemp);
1244
1245     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1246 }
1247
1248 CAResult_t CABleGattDiscoverCharacteristics(bt_gatt_attribute_h service,
1249         const char *remoteAddress)
1250 {
1251     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1252
1253     VERIFY_NON_NULL_RET(service, NULL, "service is NULL", CA_STATUS_FAILED);
1254
1255     VERIFY_NON_NULL_RET(remoteAddress, NULL, "remoteAddress is NULL", CA_STATUS_FAILED);
1256
1257     size_t len = strlen(remoteAddress);
1258
1259     char *addr = (char *)OICMalloc(sizeof(char) * (len + 1));
1260     VERIFY_NON_NULL_RET(addr, TZ_BLE_CLIENT_TAG, "Malloc failed", CA_STATUS_FAILED);
1261     strncpy(addr, remoteAddress, len + 1);
1262
1263     int32_t ret = bt_gatt_discover_characteristics(service, CABleGattCharacteristicsDiscoveredCb,
1264                   (void *)addr); // addr will be freed in callback.
1265     if (BT_ERROR_NONE != ret)
1266     {
1267         OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
1268                   "bt_gatt_discover_characteristics failed with error [%d]", ret);
1269         OICFree(addr);
1270         return CA_STATUS_FAILED;
1271     }
1272
1273     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1274     return CA_STATUS_OK;
1275 }
1276
1277 void CADiscoverDescriptorThread(void *stServiceInfo)
1278 {
1279     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, " IN");
1280
1281     VERIFY_NON_NULL_VOID(stServiceInfo, TZ_BLE_CLIENT_TAG, "stServiceInfo is NULL");
1282
1283     stGattServiceInfo_t *stTemp  = (stGattServiceInfo_t *)stServiceInfo;
1284
1285     CAResult_t result = CABleGattDiscoverDescriptor(stTemp->serviceInfo, NULL);
1286     if (CA_STATUS_OK != result)
1287     {
1288         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG,
1289                   "bt_gatt_discover_characteristic_descriptor failed");
1290         bt_gatt_destroy_attribute_handle(stTemp->serviceInfo);
1291         OICFree(stTemp->address);
1292         OICFree(stTemp);
1293         return;
1294     }
1295
1296     bt_gatt_destroy_attribute_handle(stTemp->serviceInfo);
1297     OICFree(stTemp->address);
1298     OICFree(stTemp);
1299
1300     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1301 }
1302
1303 CAResult_t CABleGattDiscoverDescriptor(bt_gatt_attribute_h service, const char *remoteAddress)
1304 {
1305     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1306
1307     VERIFY_NON_NULL_RET(service, NULL, "service is NULL", CA_STATUS_FAILED);
1308
1309     int ret = bt_gatt_discover_characteristic_descriptor(service,
1310                   CABleGattDescriptorDiscoveredCb, NULL);
1311     if (BT_ERROR_NONE != ret)
1312     {
1313         OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
1314                   "bt_gatt_discover_characteristic_descriptor failed with returns[%s]",
1315                   CABTGetErrorMsg(ret));
1316         return CA_STATUS_FAILED;
1317     }
1318
1319     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1320     return CA_STATUS_OK;
1321 }
1322
1323 void CASetCharacteristicDescriptorValueThread(void *stServiceInfo)
1324 {
1325     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1326
1327     VERIFY_NON_NULL_VOID(stServiceInfo, TZ_BLE_CLIENT_TAG, "stServiceInfo is NULL");
1328
1329     stGattCharDescriptor_t *stTemp  = (stGattCharDescriptor_t *)stServiceInfo;
1330
1331     CAResult_t  result = CASetCharacteristicDescriptorValue(stTemp);
1332     if (CA_STATUS_OK != result)
1333     {
1334         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG , "CASetCharacteristicDescriptorValue failed!");
1335         bt_gatt_destroy_attribute_handle(stTemp->characteristic);
1336         OICFree(stTemp->desc);
1337         OICFree(stTemp);
1338         return;
1339     }
1340     bt_gatt_destroy_attribute_handle(stTemp->characteristic);
1341     OICFree(stTemp->desc);
1342     OICFree(stTemp);
1343
1344     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1345 }
1346
1347 CAResult_t CASetCharacteristicDescriptorValue(stGattCharDescriptor_t *stGattCharDescInfo)
1348 {
1349     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1350
1351     unsigned char noti[4] = {0,};
1352
1353     char *strUUID = (char *)OICCalloc(5, sizeof(char));
1354
1355     VERIFY_NON_NULL_RET(strUUID, TZ_BLE_CLIENT_TAG, "calloc failed", CA_STATUS_FAILED);
1356
1357     snprintf(strUUID, 4, "%x%x", stGattCharDescInfo->desc[3], stGattCharDescInfo->desc[2]);
1358     noti[0] = stGattCharDescInfo->desc[0];
1359     noti[1] = stGattCharDescInfo->desc[1];
1360     noti[2] = 0x01;
1361     noti[3] = 0x00;
1362
1363     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "desc x0 [%x]", stGattCharDescInfo->desc[0]);
1364     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "desc x1 [%x]", stGattCharDescInfo->desc[1]);
1365     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "desc x2 [%x]", stGattCharDescInfo->desc[2]);
1366     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "desc x3 [%x]", stGattCharDescInfo->desc[3]);
1367
1368
1369     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG strUUID is [%s]",
1370               strUUID);
1371     //if (!strncmp(strUUID, BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG, 2))
1372     {
1373         OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "setting notification/indication for descriptor");
1374
1375         int ret =  bt_gatt_set_characteristic_desc_value_request(
1376                            stGattCharDescInfo->characteristic,
1377                            noti,  4, CABleGattCharacteristicWriteCb);
1378         if (BT_ERROR_NONE != ret)
1379         {
1380             OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
1381                       "bt_gatt_set_characteristic_desc_value_request failed with return[%s]",
1382                       CABTGetErrorMsg(ret));
1383             OICFree(strUUID);
1384             return CA_STATUS_FAILED;
1385         }
1386     }
1387     OICFree(strUUID);
1388
1389     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1390     return CA_STATUS_OK;
1391 }
1392
1393 CAResult_t  CAUpdateCharacteristicsToGattServer(const char *remoteAddress,
1394         const char  *data, const uint32_t dataLen,
1395         CALETransferType_t type, const int32_t position)
1396 {
1397     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
1398
1399     VERIFY_NON_NULL(data, NULL, "data is NULL");
1400
1401     if (0 >= dataLen)
1402     {
1403         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "dataLen is less than or equal zero. Invalid input!");
1404         return CA_STATUS_INVALID_PARAM;
1405     }
1406
1407     BLEServiceInfo *bleServiceInfo = NULL;
1408
1409     CAResult_t ret =  CA_STATUS_FAILED;
1410
1411     ca_mutex_lock(g_bleServiceListMutex);
1412     if ( LE_UNICAST == type)
1413     {
1414         VERIFY_NON_NULL(remoteAddress, NULL, "remoteAddress is NULL");
1415
1416         ret = CAGetBLEServiceInfo(g_bLEServiceList, remoteAddress, &bleServiceInfo);
1417     }
1418     else if ( LE_MULTICAST == type)
1419     {
1420         ret = CAGetBLEServiceInfoByPosition(g_bLEServiceList, position, &bleServiceInfo);
1421     }
1422     ca_mutex_unlock(g_bleServiceListMutex);
1423
1424     if (CA_STATUS_OK != ret)
1425     {
1426         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "CAGetBLEServiceInfoByPosition is failed");
1427         return CA_STATUS_FAILED;
1428     }
1429
1430     VERIFY_NON_NULL(bleServiceInfo, NULL, "bleServiceInfo is NULL");
1431
1432     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Updating the data of length [%d] to [%s] ", dataLen,
1433               bleServiceInfo->bdAddress);
1434
1435     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Updating to write char [%s]",
1436               bleServiceInfo->read_char);
1437
1438     OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
1439               "Updating the data of length [%d] to [%s]", dataLen,
1440               bleServiceInfo->bdAddress);
1441
1442     int result = bt_gatt_set_characteristic_value(bleServiceInfo->write_char, (unsigned char *)data,
1443                      dataLen);
1444     if (BT_ERROR_NONE != result)
1445     {
1446         OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
1447                   "bt_gatt_set_characteristic_value Failed with return val [%d]",
1448                   result);
1449         return CA_STATUS_FAILED;
1450     }
1451
1452     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT");
1453     return CA_STATUS_OK;
1454 }
1455
1456 CAResult_t  CAUpdateCharacteristicsToAllGattServers(const char  *data,
1457             uint32_t dataLen)
1458 {
1459     OIC_LOG(DEBUG,  TZ_BLE_CLIENT_TAG, "IN");
1460
1461     VERIFY_NON_NULL(data, NULL, "data is NULL");
1462
1463     if (0 >= dataLen)
1464     {
1465         OIC_LOG(ERROR, TZ_BLE_CLIENT_TAG, "dataLen is less than or equal zero. Invalid input !");
1466         return CA_STATUS_INVALID_PARAM;
1467     }
1468
1469     int numOfServersConnected = CAGetRegisteredServiceCount();
1470
1471     for (int32_t pos = 0; pos < numOfServersConnected; pos++)
1472     {
1473         /*remoteAddress will be NULL.
1474           Since we have to send to all destinations. pos will be used for getting remote address.
1475          */
1476         int32_t ret = CAUpdateCharacteristicsToGattServer(NULL, data, dataLen, LE_MULTICAST, pos);
1477
1478         if (CA_STATUS_OK != ret)
1479         {
1480             OIC_LOG_V(ERROR, TZ_BLE_CLIENT_TAG,
1481                       "CAUpdateCharacteristicsToGattServer Failed with return val [%d] ", ret);
1482         }
1483     }
1484
1485     OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "OUT ");
1486     return CA_STATUS_OK;
1487 }
1488
1489