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