1 /* ****************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
21 #include "caleclient.h"
26 #include <arpa/inet.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <netinet/in.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"
43 * Logging tag for module name.
45 #define TAG "OIC_CA_LE_CLIENT"
47 #define MICROSECS_PER_SEC 1000000
49 uint64_t const TIMEOUT = 30 * MICROSECS_PER_SEC;
52 * Flag to check if multicast is already in progress.
54 static bool g_isMulticastInProgress = false;
57 * Pending multicast data list to be sent.
59 static u_arraylist_t *g_multicastDataList = NULL;
62 * Mutex to synchronize the access to Pending multicast data list.
64 static ca_mutex g_multicastDataListMutex = NULL;
67 * List of devices discovered.
69 static u_arraylist_t *g_deviceDiscoveredList = NULL;
72 * Mutex to synchronize the access to discovered devices list.
74 static ca_mutex g_deviceDiscoveredListMutex = NULL;
77 * Condition to start the timer for scanning.
79 static ca_cond g_startTimerCond = NULL;
82 * Condition for scanning Time interval.
84 static ca_cond g_scanningTimeCond = NULL;
87 * This contains the list of OIC services a client connect tot.
89 static LEServerInfoList *g_LEServerList = NULL;
92 * Mutex to synchronize access to BleServiceList.
94 static ca_mutex g_LEServerListMutex = NULL;
97 * Boolean variable to keep the state of the GATT Client.
99 static bool g_isLEGattClientStarted = false;
102 * Mutex to synchronize access to the requestResponse callback to be called
103 * when the data needs to be sent from GATTClient.
105 static ca_mutex g_LEReqRespClientCbMutex = NULL;
108 * Mutex to synchronize access to the requestResponse callback to be called
109 * when the data needs to be sent from GATTClient.
111 static ca_mutex g_LEClientConnectMutex = NULL;
114 * Mutex to synchronize the calls to be done to the platform from GATTClient
115 * interfaces from different threads.
117 static ca_mutex g_LEClientStateMutex = NULL;
120 * Mutex to synchronize the task to be pushed to thread pool.
122 static ca_mutex g_LEClientThreadPoolMutex = NULL;
125 * Maintains the callback to be notified on receival of network packets from other
128 static CABLEDataReceivedCallback g_LEClientDataReceivedCallback = NULL;
131 * callback to update the error to le adapter
133 static CABLEErrorHandleCallback g_clientErrorCallback;
136 * gmainLoop to manage the threads to receive the callback from the platfrom.
138 static GMainLoop *g_eventLoop = NULL;
141 * Reference to threadpool
143 static ca_thread_pool_t g_LEClientThreadPool = NULL;
145 bt_scan_filter_h g_scanFilter = NULL;
147 bool CALEIsDeviceDiscovered(const char * address)
149 OIC_LOG(DEBUG, TAG, "IN");
150 if (g_deviceDiscoveredList)
152 ca_mutex_lock(g_deviceDiscoveredListMutex);
153 uint32_t arrayLength = u_arraylist_length(g_deviceDiscoveredList);
154 for (int i = 0; i < arrayLength; i++)
156 char *deviceAddr = u_arraylist_get(g_deviceDiscoveredList, i);
157 if (0 == strcasecmp(deviceAddr, address))
159 OIC_LOG(DEBUG, TAG, "Device Found");
160 ca_mutex_unlock(g_deviceDiscoveredListMutex);
165 ca_mutex_unlock(g_deviceDiscoveredListMutex);
167 OIC_LOG(DEBUG, TAG, "OUT");
171 void CALEGattCharacteristicChangedCb(bt_gatt_h characteristic,
173 int valueLen, void *userData)
175 OIC_LOG(DEBUG, TAG, "IN");
176 OIC_LOG_V(DEBUG, TAG, "Changed characteristic value length [%d]", valueLen);
178 ca_mutex_lock(g_LEReqRespClientCbMutex);
179 if (NULL == g_LEClientDataReceivedCallback)
181 OIC_LOG(ERROR, TAG, "Request response callback is not set");
182 ca_mutex_unlock(g_LEReqRespClientCbMutex);
186 uint32_t sentLength = 0;
187 g_LEClientDataReceivedCallback(userData, (uint8_t *)value, valueLen, &sentLength);
189 OIC_LOG_V(DEBUG, TAG, "Sent data Length is %d", sentLength);
191 ca_mutex_unlock(g_LEReqRespClientCbMutex);
193 OIC_LOG(DEBUG, TAG, "OUT");
196 void CALEGattCharacteristicWriteCb(int result, bt_gatt_h reqHandle, void *userData)
198 OIC_LOG(DEBUG, TAG, "IN ");
199 OIC_LOG(DEBUG, TAG, "OUT ");
202 void CALEGattConnectionStateChangedCb(int result, bool connected,
203 const char *remoteAddress, void *userData)
205 OIC_LOG(DEBUG, TAG, "IN ");
207 VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
209 // Start the scanning.
210 CAResult_t ret = CALEGattStartDeviceScanning();
211 if (CA_STATUS_OK != ret)
213 OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed");
215 // Signal the start timer.
216 ca_cond_signal(g_scanningTimeCond);
220 OIC_LOG_V(DEBUG, TAG, "DisConnected from [%s] ", remoteAddress);
224 OIC_LOG_V(DEBUG, TAG, "Connected to [%s] ", remoteAddress);
226 char *addr = OICStrdup(remoteAddress);
228 ca_mutex_lock(g_LEClientThreadPoolMutex);
229 if (NULL == g_LEClientThreadPool)
231 OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
233 ca_mutex_unlock(g_LEClientThreadPoolMutex);
237 ret = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread,
239 if (CA_STATUS_OK != ret)
241 OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", ret);
244 ca_mutex_unlock(g_LEClientThreadPoolMutex);
246 OIC_LOG(DEBUG, TAG, "OUT");
249 void CALEAdapterScanResultCb(int result, bt_adapter_le_device_scan_result_info_s *scanInfo,
252 OIC_LOG(DEBUG, TAG, "IN");
254 VERIFY_NON_NULL_VOID(scanInfo, TAG, "scanInfo");
255 VERIFY_NON_NULL_VOID(scanInfo->remote_address, TAG, "scanInfo->remote_address");
257 OIC_LOG_V(DEBUG, TAG, "Remote Address [%s]", scanInfo->remote_address);
258 OIC_LOG_V(DEBUG, TAG, "Scan Result [%d]", result);
259 OIC_LOG_V(DEBUG, TAG,
260 " Adv data len [%d] Scan data len[%d]RSSI [%d] Addr_type [%d] ",
261 scanInfo->adv_data_len, scanInfo->scan_data_len, scanInfo->rssi,
262 scanInfo->address_type);
264 // Check if device is already discovered.
265 if (CALEIsDeviceDiscovered(scanInfo->remote_address))
267 OIC_LOG_V(INFO, TAG, "Device[%s] is already discovered", scanInfo->remote_address);
271 // Stop the scan before invoking bt_gatt_connect().
272 CALEGattStopDeviceScanning();
274 ca_mutex_lock(g_deviceDiscoveredListMutex);
275 // Add the the device Discovered list.
276 if (NULL == g_deviceDiscoveredList)
278 g_deviceDiscoveredList = u_arraylist_create();
280 char *deviceAddr = OICStrdup(scanInfo->remote_address);
281 u_arraylist_add(g_deviceDiscoveredList, (void *) deviceAddr);
282 ca_mutex_unlock(g_deviceDiscoveredListMutex);
284 size_t len = strlen(scanInfo->remote_address);
286 char *addr = (char *)OICMalloc(sizeof(char) * (len + 1));
287 VERIFY_NON_NULL_VOID(addr, TAG, "Malloc failed");
289 strncpy(addr, scanInfo->remote_address, len + 1);
291 OIC_LOG_V(DEBUG, TAG,
292 "Trying to do Gatt connection to [%s]", addr);
294 ca_mutex_lock(g_LEClientThreadPoolMutex);
295 if (NULL == g_LEClientThreadPool)
297 OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
299 ca_mutex_unlock(g_LEClientThreadPoolMutex);
303 CAResult_t res = ca_thread_pool_add_task(g_LEClientThreadPool, CAGattConnectThread, addr);
304 if (CA_STATUS_OK != res)
306 OIC_LOG_V(ERROR, TAG,
307 "ca_thread_pool_add_task failed with ret [%d]", res);
310 ca_mutex_unlock(g_LEClientThreadPoolMutex);
311 OIC_LOG(DEBUG, TAG, "OUT");
314 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
316 OIC_LOG(DEBUG, TAG, "IN");
318 ca_mutex_lock(g_LEClientThreadPoolMutex);
319 g_LEClientThreadPool = handle;
320 ca_mutex_unlock(g_LEClientThreadPoolMutex);
322 OIC_LOG(DEBUG, TAG, "OUT");
325 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
327 OIC_LOG(DEBUG, TAG, "IN");
329 ca_mutex_lock(g_LEReqRespClientCbMutex);
331 g_LEClientDataReceivedCallback = callback;
333 ca_mutex_unlock(g_LEReqRespClientCbMutex);
335 OIC_LOG(DEBUG, TAG, "OUT");
338 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
340 g_clientErrorCallback = callback;
343 CAResult_t CAStartLEGattClient()
345 OIC_LOG(DEBUG, TAG, "IN");
347 ca_mutex_lock(g_LEClientThreadPoolMutex);
348 if (NULL == g_LEClientThreadPool)
350 OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL");
351 CATerminateGattClientMutexVariables();
352 ca_mutex_unlock(g_LEClientThreadPoolMutex);
353 return CA_STATUS_FAILED;
356 CAResult_t result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartLEGattClientThread,
358 if (CA_STATUS_OK != result)
360 OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed");
361 CATerminateGattClientMutexVariables();
362 ca_mutex_unlock(g_LEClientThreadPoolMutex);
363 return CA_STATUS_FAILED;
365 ca_mutex_unlock(g_LEClientThreadPoolMutex);
367 OIC_LOG(DEBUG, TAG, "OUT");
371 void CAStartLEGattClientThread(void *data)
373 OIC_LOG(DEBUG, TAG, "IN");
375 ca_mutex_lock(g_LEClientStateMutex);
376 if (true == g_isLEGattClientStarted)
378 OIC_LOG(ERROR, TAG, "Gatt Client is already running!!");
379 ca_mutex_unlock(g_LEClientStateMutex);
383 CAResult_t result = CALEGattSetCallbacks();
384 if (CA_STATUS_OK != result)
386 OIC_LOG(ERROR, TAG, "CABleGattSetCallbacks Failed");
387 ca_mutex_unlock(g_LEClientStateMutex);
388 CATerminateLEGattClient();
392 g_isLEGattClientStarted = true;
393 ca_mutex_unlock(g_LEClientStateMutex);
395 ca_mutex_lock(g_LEClientThreadPoolMutex);
396 if (NULL == g_LEClientThreadPool)
398 OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL");
399 CATerminateGattClientMutexVariables();
400 ca_mutex_unlock(g_LEClientThreadPoolMutex);
404 result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartTimerThread,
406 if (CA_STATUS_OK != result)
408 OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed");
409 ca_mutex_unlock(g_LEClientThreadPoolMutex);
412 ca_mutex_unlock(g_LEClientThreadPoolMutex);
414 OIC_LOG(DEBUG, TAG, "Giving the control to threadPool");
416 GMainContext *thread_context = g_main_context_new();
418 g_eventLoop = g_main_loop_new(thread_context, FALSE);
420 g_main_context_push_thread_default(thread_context);
422 g_main_loop_run(g_eventLoop);
424 OIC_LOG(DEBUG, TAG, "OUT");
427 void CAStartTimerThread(void *data)
429 OIC_LOG(DEBUG, TAG, "IN");
430 while (g_isLEGattClientStarted)
432 ca_mutex_lock(g_multicastDataListMutex);
433 if (!g_isMulticastInProgress)
435 OIC_LOG(DEBUG, TAG, "waiting....");
436 ca_cond_wait(g_startTimerCond, g_multicastDataListMutex);
437 OIC_LOG(DEBUG, TAG, "Wake up");
438 g_isMulticastInProgress = true;
441 // Timed conditional wait for stopping the scan.
442 CAWaitResult_t ret = ca_cond_wait_for(g_scanningTimeCond, g_multicastDataListMutex,
444 if (CA_WAIT_TIMEDOUT == ret)
446 OIC_LOG(DEBUG, TAG, "Scan is timed Out");
448 CALEGattStopDeviceScanning();
450 // Clear the data list and device list.
451 u_arraylist_destroy(g_multicastDataList);
452 g_multicastDataList = NULL;
454 ca_mutex_lock(g_deviceDiscoveredListMutex);
455 u_arraylist_destroy(g_deviceDiscoveredList);
456 g_deviceDiscoveredList = NULL;
457 ca_mutex_unlock(g_deviceDiscoveredListMutex);
459 g_isMulticastInProgress = false;
461 ca_mutex_unlock(g_multicastDataListMutex);
464 OIC_LOG(DEBUG, TAG, "OUT");
467 void CAStopLEGattClient()
469 OIC_LOG(DEBUG, TAG, "IN");
471 ca_mutex_lock(g_LEClientStateMutex);
473 if (false == g_isLEGattClientStarted)
475 OIC_LOG(ERROR, TAG, "Gatt Client is not running to stop");
476 ca_mutex_unlock(g_LEClientStateMutex);
480 CALEGattUnSetCallbacks();
482 CALEGattStopDeviceScanning();
484 g_isLEGattClientStarted = false;
486 // Signal the conditions waiting in Start timer.
487 ca_cond_signal(g_startTimerCond);
488 ca_cond_signal(g_scanningTimeCond);
490 // Destroy the multicast data list and device list if not empty.
491 if (NULL != g_multicastDataList)
493 ca_mutex_lock(g_multicastDataListMutex);
494 u_arraylist_destroy(g_multicastDataList);
495 g_multicastDataList = NULL;
496 ca_mutex_unlock(g_multicastDataListMutex);
499 if (NULL != g_deviceDiscoveredList)
501 ca_mutex_lock(g_deviceDiscoveredListMutex);
502 u_arraylist_destroy(g_deviceDiscoveredList);
503 g_deviceDiscoveredList = NULL;
504 ca_mutex_unlock(g_deviceDiscoveredListMutex);
507 ca_mutex_lock(g_LEServerListMutex);
508 CAFreeLEServerList(g_LEServerList);
509 g_LEServerList = NULL;
510 ca_mutex_unlock(g_LEServerListMutex);
512 CAResetRegisteredServiceCount();
514 GMainContext *context_event_loop = NULL;
515 // Required for waking up the thread which is running in gmain loop
516 if (NULL != g_eventLoop)
518 context_event_loop = g_main_loop_get_context(g_eventLoop);
520 if (context_event_loop)
522 OIC_LOG_V(DEBUG, TAG, "g_eventLoop context %x", context_event_loop);
523 g_main_context_wakeup(context_event_loop);
525 // Kill g main loops and kill threads.
526 g_main_loop_quit(g_eventLoop);
530 OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL");
533 ca_mutex_unlock(g_LEClientStateMutex);
535 OIC_LOG(DEBUG, TAG, "OUT");
538 CAResult_t CAInitializeLEGattClient()
540 OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
541 CAResult_t res = CAInitGattClientMutexVariables();
542 if (CA_STATUS_OK != res)
544 OIC_LOG(ERROR, TAG, "CAInitGattClientMutexVariables failed!");
545 CATerminateGattClientMutexVariables();
546 return CA_STATUS_FAILED;
551 void CATerminateLEGattClient()
553 OIC_LOG(DEBUG, TAG, "IN");
555 CATerminateGattClientMutexVariables();
557 OIC_LOG(DEBUG, TAG, "OUT");
560 CAResult_t CAInitGattClientMutexVariables()
562 OIC_LOG(DEBUG, TAG, "IN");
563 if (NULL == g_LEClientStateMutex)
565 g_LEClientStateMutex = ca_mutex_new();
566 if (NULL == g_LEClientStateMutex)
568 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
569 return CA_STATUS_FAILED;
573 if (NULL == g_LEServerListMutex)
575 g_LEServerListMutex = ca_mutex_new();
576 if (NULL == g_LEServerListMutex)
578 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
579 return CA_STATUS_FAILED;
583 if (NULL == g_LEReqRespClientCbMutex)
585 g_LEReqRespClientCbMutex = ca_mutex_new();
586 if (NULL == g_LEReqRespClientCbMutex)
588 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
589 return CA_STATUS_FAILED;
593 if (NULL == g_LEClientThreadPoolMutex)
595 g_LEClientThreadPoolMutex = ca_mutex_new();
596 if (NULL == g_LEClientThreadPoolMutex)
598 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
599 return CA_STATUS_FAILED;
603 if (NULL == g_LEClientConnectMutex)
605 g_LEClientConnectMutex = ca_mutex_new();
606 if (NULL == g_LEClientConnectMutex)
608 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
609 return CA_STATUS_FAILED;
613 if (NULL == g_multicastDataListMutex)
615 g_multicastDataListMutex = ca_mutex_new();
616 if (NULL == g_multicastDataListMutex)
618 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
619 return CA_STATUS_FAILED;
623 if (NULL == g_deviceDiscoveredListMutex)
625 g_deviceDiscoveredListMutex = ca_mutex_new();
626 if (NULL == g_deviceDiscoveredListMutex)
628 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
629 return CA_STATUS_FAILED;
633 if (NULL == g_startTimerCond)
635 g_startTimerCond = ca_cond_new();
636 if (NULL == g_startTimerCond)
638 OIC_LOG(ERROR, TAG, "ca_cond_new failed");
639 return CA_STATUS_FAILED;
643 if (NULL == g_scanningTimeCond)
645 g_scanningTimeCond = ca_cond_new();
646 if (NULL == g_scanningTimeCond)
648 OIC_LOG(ERROR, TAG, "ca_cond_new failed");
649 return CA_STATUS_FAILED;
653 OIC_LOG(DEBUG, TAG, "OUT");
657 void CATerminateGattClientMutexVariables()
659 OIC_LOG(DEBUG, TAG, "IN");
661 ca_mutex_free(g_LEClientStateMutex);
662 g_LEClientStateMutex = NULL;
664 ca_mutex_free(g_LEServerListMutex);
665 g_LEServerListMutex = NULL;
667 ca_mutex_free(g_LEReqRespClientCbMutex);
668 g_LEReqRespClientCbMutex = NULL;
670 ca_mutex_free(g_LEClientConnectMutex);
671 g_LEClientConnectMutex = NULL;
673 ca_mutex_free(g_LEClientThreadPoolMutex);
674 g_LEClientThreadPoolMutex = NULL;
676 ca_mutex_free(g_multicastDataListMutex);
677 g_multicastDataListMutex = NULL;
679 ca_mutex_free(g_deviceDiscoveredListMutex);
680 g_deviceDiscoveredListMutex = NULL;
682 ca_cond_free(g_startTimerCond);
683 g_startTimerCond = NULL;
685 ca_cond_free(g_scanningTimeCond);
686 g_scanningTimeCond = NULL;
688 OIC_LOG(DEBUG, TAG, "OUT");
691 CAResult_t CALEGattSetCallbacks()
693 OIC_LOG(DEBUG, TAG, "IN");
695 int ret = bt_gatt_set_connection_state_changed_cb(CALEGattConnectionStateChangedCb, NULL);
696 if (BT_ERROR_NONE != ret)
698 OIC_LOG_V(ERROR, TAG,
699 "bt_gatt_set_connection_state_changed_cb Failed with return as [%s ]",
700 CALEGetErrorMsg(ret));
701 return CA_STATUS_FAILED;
704 OIC_LOG(DEBUG, TAG, "OUT");
708 void CALEGattUnSetCallbacks()
710 OIC_LOG(DEBUG, TAG, "IN");
712 bt_gatt_unset_connection_state_changed_cb();
714 int numOfServersConnected = CAGetRegisteredServiceCount();
715 LEServerInfo *leServerInfo = NULL;
717 for (int32_t index = 0; index < numOfServersConnected; index++)
719 CAGetLEServerInfoByPosition(g_LEServerList, index, &leServerInfo);
720 bt_gatt_client_unset_characteristic_value_changed_cb(leServerInfo->readChar);
722 OIC_LOG(DEBUG, TAG, "OUT");
725 CAResult_t CALEGattStartDeviceScanning()
727 OIC_LOG(DEBUG, TAG, "IN");
729 int ret = bt_adapter_le_start_scan(CALEAdapterScanResultCb, NULL);
730 if(BT_ERROR_NONE != ret)
732 OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_scan failed[%s]",
733 CALEGetErrorMsg(ret));
734 return CA_STATUS_FAILED;
737 OIC_LOG(DEBUG, TAG, "OUT");
741 void CALEGattStopDeviceScanning()
743 OIC_LOG(DEBUG, TAG, "IN");
745 int ret = bt_adapter_le_stop_scan();
746 if (BT_ERROR_NONE != ret)
748 OIC_LOG_V(ERROR, TAG, "bt_adapter_le_stop_scan failed[%s]",
749 CALEGetErrorMsg(ret));
752 OIC_LOG(DEBUG, TAG, "OUT");
755 void CAGattConnectThread (void *remoteAddress)
757 OIC_LOG(DEBUG, TAG, "IN ");
759 VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
761 char *address = (char *)remoteAddress;
763 OIC_LOG_V(DEBUG, TAG, "remote address is [%s]", address);
765 CAResult_t result = CALEGattConnect(address);
767 if (CA_STATUS_OK != result)
769 OIC_LOG_V(ERROR, TAG, "bt_gatt_connect failed for [%s]", address);
774 OIC_LOG(DEBUG, TAG, "OUT");
777 CAResult_t CALEGattConnect(const char *remoteAddress)
779 OIC_LOG(DEBUG, TAG, "IN");
781 VERIFY_NON_NULL_RET(remoteAddress, TAG,
782 "remote address is NULL", CA_STATUS_FAILED);
784 ca_mutex_lock(g_LEClientConnectMutex);
786 int ret = bt_gatt_connect(remoteAddress, true);
788 if (BT_ERROR_NONE != ret)
790 OIC_LOG_V(ERROR, TAG, "bt_gatt_connect Failed with ret value [%s] ",
791 CALEGetErrorMsg(ret));
792 ca_mutex_unlock(g_LEClientConnectMutex);
793 return CA_STATUS_FAILED;
795 ca_mutex_unlock(g_LEClientConnectMutex);
797 OIC_LOG(DEBUG, TAG, "OUT");
801 CAResult_t CALEGattDisConnect(const char *remoteAddress)
803 OIC_LOG(DEBUG, TAG, "IN");
805 VERIFY_NON_NULL_RET(remoteAddress, TAG,
806 "remote address is NULL", CA_STATUS_FAILED);
808 int ret = bt_gatt_disconnect(remoteAddress);
810 if (BT_ERROR_NONE != ret)
812 OIC_LOG_V(ERROR, TAG, "bt_gatt_disconnect Failed with ret value [%d] ",
813 CALEGetErrorMsg(ret));
814 return CA_STATUS_FAILED;
817 OIC_LOG(DEBUG, TAG, "OUT");
821 void CADiscoverLEServicesThread (void *remoteAddress)
823 OIC_LOG(DEBUG, TAG, "IN");
825 VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
827 char *address = (char *)remoteAddress;
829 CAResult_t result = CALEGattDiscoverServices(address);
830 if (CA_STATUS_OK != result)
832 OIC_LOG(ERROR, TAG, "CALEGattDiscoverServices failed");
836 OIC_LOG(DEBUG, TAG, "OUT");
839 CAResult_t CALEGattDiscoverServices(const char *remoteAddress)
841 OIC_LOG(DEBUG, TAG, "IN");
843 VERIFY_NON_NULL_RET(remoteAddress, TAG,
844 "remote address is NULL", CA_STATUS_FAILED);
846 bt_gatt_client_h clientHandle = NULL;
847 int32_t ret = bt_gatt_client_create(remoteAddress, &clientHandle);
848 if (BT_ERROR_NONE != ret || NULL == clientHandle)
850 OIC_LOG_V(ERROR, TAG,
851 "bt_gatt_client_create Failed with ret value [%s] ", CALEGetErrorMsg(ret));
852 CALEGattDisConnect(remoteAddress);
853 return CA_STATUS_FAILED;
856 bt_gatt_h serviceHandle = NULL;
857 ret = bt_gatt_client_get_service(clientHandle, CA_GATT_SERVICE_UUID, &serviceHandle);
858 if (BT_ERROR_NONE != ret || NULL == serviceHandle)
860 OIC_LOG_V(ERROR, TAG,
861 "bt_gatt_client_get_service Failed with ret value [%s] ", CALEGetErrorMsg(ret));
862 bt_gatt_client_destroy(clientHandle);
863 CALEGattDisConnect(remoteAddress);
864 return CA_STATUS_FAILED;
867 // Server will read data on this characteristic.
868 bt_gatt_h writeChrHandle = NULL;
869 ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_REQUEST_CHRC_UUID,
871 if (BT_ERROR_NONE != ret || NULL == writeChrHandle)
873 OIC_LOG_V(ERROR, TAG,
874 "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
875 CALEGetErrorMsg(ret));
876 bt_gatt_client_destroy(clientHandle);
877 CALEGattDisConnect(remoteAddress);
878 return CA_STATUS_FAILED;
881 // Server will notify data on this characteristic.
882 bt_gatt_h readChrHandle = NULL;
883 ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_RESPONSE_CHRC_UUID,
885 if (BT_ERROR_NONE != ret || NULL == readChrHandle)
887 OIC_LOG_V(ERROR, TAG,
888 "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
889 CALEGetErrorMsg(ret));
890 bt_gatt_client_destroy(clientHandle);
891 CALEGattDisConnect(remoteAddress);
892 return CA_STATUS_FAILED;
896 //TODO: This data has to be freed while unsetting the callback.
897 char *addr = OICStrdup(remoteAddress);
898 ret = bt_gatt_client_set_characteristic_value_changed_cb(readChrHandle,
899 CALEGattCharacteristicChangedCb,
901 if (BT_ERROR_NONE != ret)
903 OIC_LOG_V(ERROR, TAG,
904 "bt_gatt_client_set_characteristic_value_changed_cb Failed with ret value [%s]",
905 CALEGetErrorMsg(ret));
906 bt_gatt_client_destroy(clientHandle);
907 CALEGattDisConnect(remoteAddress);
908 return CA_STATUS_FAILED;
911 LEServerInfo *serverInfo = (LEServerInfo *)OICCalloc(1, sizeof(LEServerInfo));
912 if (NULL == serverInfo)
914 OIC_LOG(ERROR, TAG, "Malloc failed");
915 CALEGattDisConnect(remoteAddress);
916 return CA_MEMORY_ALLOC_FAILED;
918 serverInfo->clientHandle = clientHandle;
919 serverInfo->serviceHandle = serviceHandle;
920 serverInfo->readChar = readChrHandle;
921 serverInfo->writeChar = writeChrHandle;
922 serverInfo->remoteAddress = OICStrdup(remoteAddress);
924 ca_mutex_lock(g_LEServerListMutex);
925 CAResult_t result = CAAddLEServerInfoToList(&g_LEServerList, serverInfo);
926 if (CA_STATUS_OK != result)
928 OIC_LOG(ERROR, TAG, "CAAddBLEClientInfoToList failed");
929 bt_gatt_client_destroy(clientHandle);
930 CALEGattDisConnect(remoteAddress);
931 return CA_STATUS_FAILED;
933 ca_mutex_unlock(g_LEServerListMutex);
935 // Send the data of pending multicast data list if any.
936 if (g_multicastDataList)
938 ca_mutex_lock(g_multicastDataListMutex);
939 uint32_t arrayLength = u_arraylist_length(g_multicastDataList);
940 for (int i = 0; i < arrayLength; i++)
942 CALEData_t *multicastData = u_arraylist_get(g_multicastDataList, i);
943 if (NULL == multicastData)
945 OIC_LOG(DEBUG, TAG, "multicastData is NULL");
948 CAUpdateCharacteristicsToGattServer(remoteAddress, multicastData->data,
949 multicastData->dataLen, LE_UNICAST, 0);
951 ca_mutex_unlock(g_multicastDataListMutex);
954 OIC_LOG(DEBUG, TAG, "OUT");
958 CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress,
959 const uint8_t *data, const uint32_t dataLen,
960 CALETransferType_t type, const int32_t position)
962 OIC_LOG(DEBUG, TAG, "IN");
964 VERIFY_NON_NULL(data, TAG, "data is NULL");
968 OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input!");
969 return CA_STATUS_INVALID_PARAM;
972 LEServerInfo *leServerInfo = NULL;
973 CAResult_t ret = CA_STATUS_FAILED;
975 ca_mutex_lock(g_LEServerListMutex);
976 if (LE_UNICAST == type)
978 ret = CAGetLEServerInfo(g_LEServerList, remoteAddress, &leServerInfo);
980 else if (LE_MULTICAST == type)
982 ret = CAGetLEServerInfoByPosition(g_LEServerList, position, &leServerInfo);
984 ca_mutex_unlock(g_LEServerListMutex);
986 if (CA_STATUS_OK != ret)
988 OIC_LOG(ERROR, TAG, "CAGetBLEServiceInfoByPosition is failed");
989 return CA_STATUS_FAILED;
992 VERIFY_NON_NULL(leServerInfo, TAG, "bleServiceInfo is NULL");
994 OIC_LOG_V(DEBUG, TAG, "Updating the data of length [%d] to [%s] ", dataLen,
995 leServerInfo->remoteAddress);
997 int result = bt_gatt_set_value(leServerInfo->writeChar, (char *)data, dataLen);
999 if (BT_ERROR_NONE != result)
1001 OIC_LOG_V(ERROR, TAG,
1002 "bt_gatt_set_value Failed with return val [%s]",
1003 CALEGetErrorMsg(result));
1004 return CA_STATUS_FAILED;
1007 result = bt_gatt_client_write_value(leServerInfo->writeChar, CALEGattCharacteristicWriteCb,
1009 if (BT_ERROR_NONE != result)
1011 OIC_LOG_V(ERROR, TAG,
1012 "bt_gatt_client_write_value Failed with return val [%s]",
1013 CALEGetErrorMsg(result));
1014 return CA_STATUS_FAILED;
1017 OIC_LOG(DEBUG, TAG, "OUT");
1018 return CA_STATUS_OK;
1021 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
1023 OIC_LOG(DEBUG, TAG, "IN");
1025 VERIFY_NON_NULL(data, TAG, "data is NULL");
1029 OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input !");
1030 return CA_STATUS_INVALID_PARAM;
1033 int numOfServersConnected = CAGetRegisteredServiceCount();
1035 // Send data to already connected devices.
1036 for (int32_t pos = 0; pos < numOfServersConnected; pos++)
1038 /*remoteAddress will be NULL.
1039 Since we have to send to all destinations. pos will be used for getting remote address.
1041 int32_t ret = CAUpdateCharacteristicsToGattServer(NULL, data, dataLen, LE_MULTICAST, pos);
1043 if (CA_STATUS_OK != ret)
1045 OIC_LOG_V(ERROR, TAG,
1046 "CAUpdateCharacteristicsToGattServer Failed with return val [%d] ", ret);
1047 g_clientErrorCallback(NULL, data, dataLen, ret);
1051 // Add the data to pending list.
1052 CALEData_t *multicastData = (CALEData_t *)OICCalloc(1, sizeof(CALEData_t));
1053 if (NULL == multicastData)
1055 OIC_LOG(ERROR, TAG, "Calloc failed");
1058 multicastData->data = OICCalloc(1, dataLen);
1059 if (NULL == multicastData->data)
1061 OIC_LOG(ERROR, TAG, "Calloc failed");
1064 memcpy(multicastData->data, data, dataLen);
1065 multicastData->dataLen = dataLen;
1067 ca_mutex_lock(g_multicastDataListMutex);
1068 if (NULL == g_multicastDataList)
1070 g_multicastDataList = u_arraylist_create();
1072 u_arraylist_add(g_multicastDataList, (void *)multicastData);
1073 ca_mutex_unlock(g_multicastDataListMutex);
1075 // Start the scanning.
1076 CAResult_t result = CALEGattStartDeviceScanning();
1077 if (CA_STATUS_OK != result)
1079 OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed");
1083 // Start the timer by signalling it.
1084 ca_cond_signal(g_startTimerCond);
1087 OIC_LOG(DEBUG, TAG, "OUT ");
1088 return CA_STATUS_OK;