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