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
48 #define WAIT_TIME_WRITE_CHARACTERISTIC 10 * MICROSECS_PER_SEC
50 uint64_t const TIMEOUT = 30 * MICROSECS_PER_SEC;
53 * Flag to check if multicast is already in progress.
55 static bool g_isMulticastInProgress = false;
58 * Pending multicast data list to be sent.
60 static u_arraylist_t *g_multicastDataList = NULL;
63 * Mutex to synchronize the access to Pending multicast data list.
65 static ca_mutex g_multicastDataListMutex = NULL;
68 * List of devices discovered.
70 static u_arraylist_t *g_deviceDiscoveredList = NULL;
73 * Mutex to synchronize the access to discovered devices list.
75 static ca_mutex g_deviceDiscoveredListMutex = NULL;
78 * Condition to start the timer for scanning.
80 static ca_cond g_startTimerCond = NULL;
83 * Condition for scanning Time interval.
85 static ca_cond g_scanningTimeCond = NULL;
88 * This contains the list of OIC services a client connect tot.
90 static LEServerInfoList *g_LEServerList = NULL;
93 * Mutex to synchronize access to BleServiceList.
95 static ca_mutex g_LEServerListMutex = NULL;
98 * Boolean variable to keep the state of the GATT Client.
100 static bool g_isLEGattClientStarted = false;
103 * Mutex to synchronize access to the requestResponse callback to be called
104 * when the data needs to be sent from GATTClient.
106 static ca_mutex g_LEReqRespClientCbMutex = NULL;
109 * Mutex to synchronize access to the requestResponse callback to be called
110 * when the data needs to be sent from GATTClient.
112 static ca_mutex g_LEClientConnectMutex = NULL;
115 * Mutex to synchronize the calls to be done to the platform from GATTClient
116 * interfaces from different threads.
118 static ca_mutex g_LEClientStateMutex = NULL;
121 * Mutex to synchronize the task to be pushed to thread pool.
123 static ca_mutex g_LEClientThreadPoolMutex = NULL;
126 * Mutex to synchronize the task to write characteristic one packet after another.
128 static ca_mutex g_threadWriteCharacteristicMutex = NULL;
131 * Condition for Writing characteristic.
133 static ca_cond g_threadWriteCharacteristicCond = NULL;
136 * Flag to check status of write characteristic.
138 static bool g_isSignalSetFlag = false;
141 * Maintains the callback to be notified on receival of network packets from other
144 static CABLEDataReceivedCallback g_LEClientDataReceivedCallback = NULL;
147 * callback to update the error to le adapter
149 static CABLEErrorHandleCallback g_clientErrorCallback;
152 * gmainLoop to manage the threads to receive the callback from the platfrom.
154 static GMainLoop *g_eventLoop = NULL;
157 * Reference to threadpool
159 static ca_thread_pool_t g_LEClientThreadPool = NULL;
161 bt_scan_filter_h g_scanFilter = NULL;
163 bool CALEIsDeviceDiscovered(const char * address)
165 OIC_LOG(DEBUG, TAG, "IN");
166 if (g_deviceDiscoveredList)
168 ca_mutex_lock(g_deviceDiscoveredListMutex);
169 uint32_t arrayLength = u_arraylist_length(g_deviceDiscoveredList);
170 for (int i = 0; i < arrayLength; i++)
172 char *deviceAddr = u_arraylist_get(g_deviceDiscoveredList, i);
173 if (0 == strcasecmp(deviceAddr, address))
175 OIC_LOG(DEBUG, TAG, "Device Found");
176 ca_mutex_unlock(g_deviceDiscoveredListMutex);
181 ca_mutex_unlock(g_deviceDiscoveredListMutex);
183 OIC_LOG(DEBUG, TAG, "OUT");
187 void CALEGattCharacteristicChangedCb(bt_gatt_h characteristic,
189 int valueLen, void *userData)
191 OIC_LOG(DEBUG, TAG, "IN");
192 OIC_LOG_V(DEBUG, TAG, "Changed characteristic value length [%d]", valueLen);
194 ca_mutex_lock(g_LEReqRespClientCbMutex);
195 if (NULL == g_LEClientDataReceivedCallback)
197 OIC_LOG(ERROR, TAG, "Request response callback is not set");
198 ca_mutex_unlock(g_LEReqRespClientCbMutex);
202 uint32_t sentLength = 0;
203 g_LEClientDataReceivedCallback(userData, (uint8_t *)value, valueLen, &sentLength);
205 OIC_LOG_V(DEBUG, TAG, "Sent data Length is %d", sentLength);
207 ca_mutex_unlock(g_LEReqRespClientCbMutex);
209 OIC_LOG(DEBUG, TAG, "OUT");
212 void CALEGattCharacteristicWriteCb(int result, bt_gatt_h reqHandle, void *userData)
214 OIC_LOG(DEBUG, TAG, "IN ");
216 if (BT_ERROR_NONE != result)
218 OIC_LOG(ERROR, TAG, "Write failed Need Retry ");
219 //Need to Implement retry mechanism
223 ca_mutex_lock(g_threadWriteCharacteristicMutex);
224 OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
225 g_isSignalSetFlag = true;
226 ca_cond_signal(g_threadWriteCharacteristicCond);
227 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
230 OIC_LOG(DEBUG, TAG, "OUT ");
233 void CALEGattConnectionStateChangedCb(int result, bool connected,
234 const char *remoteAddress, void *userData)
236 OIC_LOG(DEBUG, TAG, "IN ");
238 VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
240 // Start the scanning.
241 CAResult_t ret = CALEGattStartDeviceScanning();
242 if (CA_STATUS_OK != ret)
244 OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed");
246 // Signal the start timer.
247 ca_cond_signal(g_scanningTimeCond);
251 OIC_LOG_V(DEBUG, TAG, "DisConnected from [%s] ", remoteAddress);
255 OIC_LOG_V(DEBUG, TAG, "Connected to [%s] ", remoteAddress);
257 char *addr = OICStrdup(remoteAddress);
259 ca_mutex_lock(g_LEClientThreadPoolMutex);
260 if (NULL == g_LEClientThreadPool)
262 OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
264 ca_mutex_unlock(g_LEClientThreadPoolMutex);
268 ret = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread,
270 if (CA_STATUS_OK != ret)
272 OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", ret);
275 ca_mutex_unlock(g_LEClientThreadPoolMutex);
277 OIC_LOG(DEBUG, TAG, "OUT");
280 void CALEAdapterScanResultCb(int result, bt_adapter_le_device_scan_result_info_s *scanInfo,
283 OIC_LOG(DEBUG, TAG, "IN");
285 VERIFY_NON_NULL_VOID(scanInfo, TAG, "scanInfo");
286 VERIFY_NON_NULL_VOID(scanInfo->remote_address, TAG, "scanInfo->remote_address");
288 OIC_LOG_V(DEBUG, TAG, "Remote Address [%s]", scanInfo->remote_address);
289 OIC_LOG_V(DEBUG, TAG, "Scan Result [%d]", result);
290 OIC_LOG_V(DEBUG, TAG,
291 " Adv data len [%d] Scan data len[%d]RSSI [%d] Addr_type [%d] ",
292 scanInfo->adv_data_len, scanInfo->scan_data_len, scanInfo->rssi,
293 scanInfo->address_type);
295 // Check if device is already discovered.
296 if (CALEIsDeviceDiscovered(scanInfo->remote_address))
298 OIC_LOG_V(INFO, TAG, "Device[%s] is already discovered", scanInfo->remote_address);
302 // Stop the scan before invoking bt_gatt_connect().
303 CALEGattStopDeviceScanning();
305 ca_mutex_lock(g_deviceDiscoveredListMutex);
306 // Add the the device Discovered list.
307 if (NULL == g_deviceDiscoveredList)
309 g_deviceDiscoveredList = u_arraylist_create();
311 char *deviceAddr = OICStrdup(scanInfo->remote_address);
312 u_arraylist_add(g_deviceDiscoveredList, (void *) deviceAddr);
313 ca_mutex_unlock(g_deviceDiscoveredListMutex);
315 size_t len = strlen(scanInfo->remote_address);
317 char *addr = (char *)OICMalloc(sizeof(char) * (len + 1));
318 VERIFY_NON_NULL_VOID(addr, TAG, "Malloc failed");
320 strncpy(addr, scanInfo->remote_address, len + 1);
322 OIC_LOG_V(DEBUG, TAG,
323 "Trying to do Gatt connection to [%s]", addr);
325 ca_mutex_lock(g_LEClientThreadPoolMutex);
326 if (NULL == g_LEClientThreadPool)
328 OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
330 ca_mutex_unlock(g_LEClientThreadPoolMutex);
334 CAResult_t res = ca_thread_pool_add_task(g_LEClientThreadPool, CAGattConnectThread, addr);
335 if (CA_STATUS_OK != res)
337 OIC_LOG_V(ERROR, TAG,
338 "ca_thread_pool_add_task failed with ret [%d]", res);
341 ca_mutex_unlock(g_LEClientThreadPoolMutex);
342 OIC_LOG(DEBUG, TAG, "OUT");
345 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
347 OIC_LOG(DEBUG, TAG, "IN");
349 ca_mutex_lock(g_LEClientThreadPoolMutex);
350 g_LEClientThreadPool = handle;
351 ca_mutex_unlock(g_LEClientThreadPoolMutex);
353 OIC_LOG(DEBUG, TAG, "OUT");
356 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
358 OIC_LOG(DEBUG, TAG, "IN");
360 ca_mutex_lock(g_LEReqRespClientCbMutex);
362 g_LEClientDataReceivedCallback = callback;
364 ca_mutex_unlock(g_LEReqRespClientCbMutex);
366 OIC_LOG(DEBUG, TAG, "OUT");
369 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
371 g_clientErrorCallback = callback;
374 CAResult_t CAStartLEGattClient()
376 OIC_LOG(DEBUG, TAG, "IN");
378 ca_mutex_lock(g_LEClientThreadPoolMutex);
379 if (NULL == g_LEClientThreadPool)
381 OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL");
382 CATerminateGattClientMutexVariables();
383 ca_mutex_unlock(g_LEClientThreadPoolMutex);
384 return CA_STATUS_FAILED;
387 CAResult_t result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartLEGattClientThread,
389 if (CA_STATUS_OK != result)
391 OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed");
392 CATerminateGattClientMutexVariables();
393 ca_mutex_unlock(g_LEClientThreadPoolMutex);
394 return CA_STATUS_FAILED;
396 ca_mutex_unlock(g_LEClientThreadPoolMutex);
398 OIC_LOG(DEBUG, TAG, "OUT");
402 void CAStartLEGattClientThread(void *data)
404 OIC_LOG(DEBUG, TAG, "IN");
406 ca_mutex_lock(g_LEClientStateMutex);
407 if (true == g_isLEGattClientStarted)
409 OIC_LOG(ERROR, TAG, "Gatt Client is already running!!");
410 ca_mutex_unlock(g_LEClientStateMutex);
414 CAResult_t result = CALEGattSetCallbacks();
415 if (CA_STATUS_OK != result)
417 OIC_LOG(ERROR, TAG, "CABleGattSetCallbacks Failed");
418 ca_mutex_unlock(g_LEClientStateMutex);
419 CATerminateLEGattClient();
423 g_isLEGattClientStarted = true;
424 ca_mutex_unlock(g_LEClientStateMutex);
426 ca_mutex_lock(g_LEClientThreadPoolMutex);
427 if (NULL == g_LEClientThreadPool)
429 OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL");
430 CATerminateGattClientMutexVariables();
431 ca_mutex_unlock(g_LEClientThreadPoolMutex);
435 result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartTimerThread,
437 if (CA_STATUS_OK != result)
439 OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed");
440 ca_mutex_unlock(g_LEClientThreadPoolMutex);
443 ca_mutex_unlock(g_LEClientThreadPoolMutex);
445 OIC_LOG(DEBUG, TAG, "Giving the control to threadPool");
447 GMainContext *thread_context = g_main_context_new();
449 g_eventLoop = g_main_loop_new(thread_context, FALSE);
451 g_main_context_push_thread_default(thread_context);
453 g_main_loop_run(g_eventLoop);
455 OIC_LOG(DEBUG, TAG, "OUT");
458 void CAStartTimerThread(void *data)
460 OIC_LOG(DEBUG, TAG, "IN");
461 while (g_isLEGattClientStarted)
463 ca_mutex_lock(g_multicastDataListMutex);
464 if (!g_isMulticastInProgress)
466 OIC_LOG(DEBUG, TAG, "waiting....");
467 ca_cond_wait(g_startTimerCond, g_multicastDataListMutex);
468 OIC_LOG(DEBUG, TAG, "Wake up");
469 g_isMulticastInProgress = true;
472 // Timed conditional wait for stopping the scan.
473 CAWaitResult_t ret = ca_cond_wait_for(g_scanningTimeCond, g_multicastDataListMutex,
475 if (CA_WAIT_TIMEDOUT == ret)
477 OIC_LOG(DEBUG, TAG, "Scan is timed Out");
479 CALEGattStopDeviceScanning();
481 // Clear the data list and device list.
482 u_arraylist_destroy(g_multicastDataList);
483 g_multicastDataList = NULL;
485 ca_mutex_lock(g_deviceDiscoveredListMutex);
486 u_arraylist_destroy(g_deviceDiscoveredList);
487 g_deviceDiscoveredList = NULL;
488 ca_mutex_unlock(g_deviceDiscoveredListMutex);
490 g_isMulticastInProgress = false;
492 ca_mutex_unlock(g_multicastDataListMutex);
495 OIC_LOG(DEBUG, TAG, "OUT");
498 void CAStopLEGattClient()
500 OIC_LOG(DEBUG, TAG, "IN");
502 ca_mutex_lock(g_LEClientStateMutex);
504 if (false == g_isLEGattClientStarted)
506 OIC_LOG(ERROR, TAG, "Gatt Client is not running to stop");
507 ca_mutex_unlock(g_LEClientStateMutex);
511 CALEGattUnSetCallbacks();
513 CALEGattStopDeviceScanning();
515 g_isLEGattClientStarted = false;
517 // Signal the conditions waiting in Start timer.
518 ca_cond_signal(g_startTimerCond);
519 ca_cond_signal(g_scanningTimeCond);
521 // Destroy the multicast data list and device list if not empty.
522 if (NULL != g_multicastDataList)
524 ca_mutex_lock(g_multicastDataListMutex);
525 u_arraylist_destroy(g_multicastDataList);
526 g_multicastDataList = NULL;
527 ca_mutex_unlock(g_multicastDataListMutex);
530 if (NULL != g_deviceDiscoveredList)
532 ca_mutex_lock(g_deviceDiscoveredListMutex);
533 u_arraylist_destroy(g_deviceDiscoveredList);
534 g_deviceDiscoveredList = NULL;
535 ca_mutex_unlock(g_deviceDiscoveredListMutex);
538 ca_mutex_lock(g_LEServerListMutex);
539 CAFreeLEServerList(g_LEServerList);
540 g_LEServerList = NULL;
541 ca_mutex_unlock(g_LEServerListMutex);
543 ca_mutex_lock(g_threadWriteCharacteristicMutex);
544 ca_cond_signal(g_threadWriteCharacteristicCond);
545 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
547 CAResetRegisteredServiceCount();
549 GMainContext *context_event_loop = NULL;
550 // Required for waking up the thread which is running in gmain loop
551 if (NULL != g_eventLoop)
553 context_event_loop = g_main_loop_get_context(g_eventLoop);
555 if (context_event_loop)
557 OIC_LOG_V(DEBUG, TAG, "g_eventLoop context %x", context_event_loop);
558 g_main_context_wakeup(context_event_loop);
560 // Kill g main loops and kill threads.
561 g_main_loop_quit(g_eventLoop);
565 OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL");
568 ca_mutex_unlock(g_LEClientStateMutex);
570 OIC_LOG(DEBUG, TAG, "OUT");
573 CAResult_t CAInitializeLEGattClient()
575 OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
576 CAResult_t res = CAInitGattClientMutexVariables();
577 if (CA_STATUS_OK != res)
579 OIC_LOG(ERROR, TAG, "CAInitGattClientMutexVariables failed!");
580 CATerminateGattClientMutexVariables();
581 return CA_STATUS_FAILED;
586 void CATerminateLEGattClient()
588 OIC_LOG(DEBUG, TAG, "IN");
590 CATerminateGattClientMutexVariables();
592 OIC_LOG(DEBUG, TAG, "OUT");
595 CAResult_t CAInitGattClientMutexVariables()
597 OIC_LOG(DEBUG, TAG, "IN");
598 if (NULL == g_LEClientStateMutex)
600 g_LEClientStateMutex = ca_mutex_new();
601 if (NULL == g_LEClientStateMutex)
603 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
604 return CA_STATUS_FAILED;
608 if (NULL == g_LEServerListMutex)
610 g_LEServerListMutex = ca_mutex_new();
611 if (NULL == g_LEServerListMutex)
613 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
614 return CA_STATUS_FAILED;
618 if (NULL == g_LEReqRespClientCbMutex)
620 g_LEReqRespClientCbMutex = ca_mutex_new();
621 if (NULL == g_LEReqRespClientCbMutex)
623 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
624 return CA_STATUS_FAILED;
628 if (NULL == g_LEClientThreadPoolMutex)
630 g_LEClientThreadPoolMutex = ca_mutex_new();
631 if (NULL == g_LEClientThreadPoolMutex)
633 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
634 return CA_STATUS_FAILED;
638 if (NULL == g_LEClientConnectMutex)
640 g_LEClientConnectMutex = ca_mutex_new();
641 if (NULL == g_LEClientConnectMutex)
643 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
644 return CA_STATUS_FAILED;
648 if (NULL == g_multicastDataListMutex)
650 g_multicastDataListMutex = ca_mutex_new();
651 if (NULL == g_multicastDataListMutex)
653 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
654 return CA_STATUS_FAILED;
658 if (NULL == g_deviceDiscoveredListMutex)
660 g_deviceDiscoveredListMutex = ca_mutex_new();
661 if (NULL == g_deviceDiscoveredListMutex)
663 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
664 return CA_STATUS_FAILED;
668 if (NULL == g_threadWriteCharacteristicMutex)
670 g_threadWriteCharacteristicMutex = ca_mutex_new();
671 if (NULL == g_threadWriteCharacteristicMutex)
673 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
674 return CA_STATUS_FAILED;
678 if (NULL == g_startTimerCond)
680 g_startTimerCond = ca_cond_new();
681 if (NULL == g_startTimerCond)
683 OIC_LOG(ERROR, TAG, "ca_cond_new failed");
684 return CA_STATUS_FAILED;
688 if (NULL == g_scanningTimeCond)
690 g_scanningTimeCond = ca_cond_new();
691 if (NULL == g_scanningTimeCond)
693 OIC_LOG(ERROR, TAG, "ca_cond_new failed");
694 return CA_STATUS_FAILED;
698 if (NULL == g_threadWriteCharacteristicCond)
700 g_threadWriteCharacteristicCond = ca_cond_new();
701 if (NULL == g_threadWriteCharacteristicCond)
703 OIC_LOG(ERROR, TAG, "ca_cond_new failed");
704 return CA_STATUS_FAILED;
708 OIC_LOG(DEBUG, TAG, "OUT");
712 void CATerminateGattClientMutexVariables()
714 OIC_LOG(DEBUG, TAG, "IN");
716 ca_mutex_free(g_LEClientStateMutex);
717 g_LEClientStateMutex = NULL;
719 ca_mutex_free(g_LEServerListMutex);
720 g_LEServerListMutex = NULL;
722 ca_mutex_free(g_LEReqRespClientCbMutex);
723 g_LEReqRespClientCbMutex = NULL;
725 ca_mutex_free(g_LEClientConnectMutex);
726 g_LEClientConnectMutex = NULL;
728 ca_mutex_free(g_LEClientThreadPoolMutex);
729 g_LEClientThreadPoolMutex = NULL;
731 ca_mutex_free(g_multicastDataListMutex);
732 g_multicastDataListMutex = NULL;
734 ca_mutex_free(g_deviceDiscoveredListMutex);
735 g_deviceDiscoveredListMutex = NULL;
737 ca_mutex_free(g_threadWriteCharacteristicMutex);
738 g_threadWriteCharacteristicMutex = NULL;
740 ca_cond_free(g_startTimerCond);
741 g_startTimerCond = NULL;
743 ca_cond_free(g_scanningTimeCond);
744 g_scanningTimeCond = NULL;
746 ca_cond_free(g_threadWriteCharacteristicCond);
747 g_threadWriteCharacteristicCond = NULL;
748 g_isSignalSetFlag = false;
750 OIC_LOG(DEBUG, TAG, "OUT");
753 CAResult_t CALEGattSetCallbacks()
755 OIC_LOG(DEBUG, TAG, "IN");
757 int ret = bt_gatt_set_connection_state_changed_cb(CALEGattConnectionStateChangedCb, NULL);
758 if (BT_ERROR_NONE != ret)
760 OIC_LOG_V(ERROR, TAG,
761 "bt_gatt_set_connection_state_changed_cb Failed with return as [%s ]",
762 CALEGetErrorMsg(ret));
763 return CA_STATUS_FAILED;
766 OIC_LOG(DEBUG, TAG, "OUT");
770 void CALEGattUnSetCallbacks()
772 OIC_LOG(DEBUG, TAG, "IN");
774 bt_gatt_unset_connection_state_changed_cb();
776 int numOfServersConnected = CAGetRegisteredServiceCount();
777 LEServerInfo *leServerInfo = NULL;
779 for (int32_t index = 0; index < numOfServersConnected; index++)
781 CAGetLEServerInfoByPosition(g_LEServerList, index, &leServerInfo);
782 bt_gatt_client_unset_characteristic_value_changed_cb(leServerInfo->readChar);
784 OIC_LOG(DEBUG, TAG, "OUT");
787 CAResult_t CALEGattStartDeviceScanning()
789 OIC_LOG(DEBUG, TAG, "IN");
791 int ret = bt_adapter_le_start_scan(CALEAdapterScanResultCb, NULL);
792 if(BT_ERROR_NONE != ret)
794 OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_scan failed[%s]",
795 CALEGetErrorMsg(ret));
796 return CA_STATUS_FAILED;
799 OIC_LOG(DEBUG, TAG, "OUT");
803 void CALEGattStopDeviceScanning()
805 OIC_LOG(DEBUG, TAG, "IN");
807 int ret = bt_adapter_le_stop_scan();
808 if (BT_ERROR_NONE != ret)
810 OIC_LOG_V(ERROR, TAG, "bt_adapter_le_stop_scan failed[%s]",
811 CALEGetErrorMsg(ret));
814 OIC_LOG(DEBUG, TAG, "OUT");
817 void CAGattConnectThread (void *remoteAddress)
819 OIC_LOG(DEBUG, TAG, "IN ");
821 VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
823 char *address = (char *)remoteAddress;
825 OIC_LOG_V(DEBUG, TAG, "remote address is [%s]", address);
827 CAResult_t result = CALEGattConnect(address);
829 if (CA_STATUS_OK != result)
831 OIC_LOG_V(ERROR, TAG, "bt_gatt_connect failed for [%s]", address);
836 OIC_LOG(DEBUG, TAG, "OUT");
839 CAResult_t CALEGattConnect(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 ca_mutex_lock(g_LEClientConnectMutex);
848 int ret = bt_gatt_connect(remoteAddress, true);
850 if (BT_ERROR_NONE != ret)
852 OIC_LOG_V(ERROR, TAG, "bt_gatt_connect Failed with ret value [%s] ",
853 CALEGetErrorMsg(ret));
854 ca_mutex_unlock(g_LEClientConnectMutex);
855 return CA_STATUS_FAILED;
857 ca_mutex_unlock(g_LEClientConnectMutex);
859 OIC_LOG(DEBUG, TAG, "OUT");
863 CAResult_t CALEGattDisConnect(const char *remoteAddress)
865 OIC_LOG(DEBUG, TAG, "IN");
867 VERIFY_NON_NULL_RET(remoteAddress, TAG,
868 "remote address is NULL", CA_STATUS_FAILED);
870 int ret = bt_gatt_disconnect(remoteAddress);
872 if (BT_ERROR_NONE != ret)
874 OIC_LOG_V(ERROR, TAG, "bt_gatt_disconnect Failed with ret value [%d] ",
875 CALEGetErrorMsg(ret));
876 return CA_STATUS_FAILED;
879 OIC_LOG(DEBUG, TAG, "OUT");
883 void CADiscoverLEServicesThread (void *remoteAddress)
885 OIC_LOG(DEBUG, TAG, "IN");
887 VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
889 char *address = (char *)remoteAddress;
891 CAResult_t result = CALEGattDiscoverServices(address);
892 if (CA_STATUS_OK != result)
894 OIC_LOG(ERROR, TAG, "CALEGattDiscoverServices failed");
898 OIC_LOG(DEBUG, TAG, "OUT");
901 CAResult_t CALEGattDiscoverServices(const char *remoteAddress)
903 OIC_LOG(DEBUG, TAG, "IN");
905 VERIFY_NON_NULL_RET(remoteAddress, TAG,
906 "remote address is NULL", CA_STATUS_FAILED);
908 bt_gatt_client_h clientHandle = NULL;
909 int32_t ret = bt_gatt_client_create(remoteAddress, &clientHandle);
910 if (BT_ERROR_NONE != ret || NULL == clientHandle)
912 OIC_LOG_V(ERROR, TAG,
913 "bt_gatt_client_create Failed with ret value [%s] ", CALEGetErrorMsg(ret));
914 CALEGattDisConnect(remoteAddress);
915 return CA_STATUS_FAILED;
918 bt_gatt_h serviceHandle = NULL;
919 ret = bt_gatt_client_get_service(clientHandle, CA_GATT_SERVICE_UUID, &serviceHandle);
920 if (BT_ERROR_NONE != ret || NULL == serviceHandle)
922 OIC_LOG_V(ERROR, TAG,
923 "bt_gatt_client_get_service Failed with ret value [%s] ", CALEGetErrorMsg(ret));
924 bt_gatt_client_destroy(clientHandle);
925 CALEGattDisConnect(remoteAddress);
926 return CA_STATUS_FAILED;
929 // Server will read data on this characteristic.
930 bt_gatt_h writeChrHandle = NULL;
931 ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_REQUEST_CHRC_UUID,
933 if (BT_ERROR_NONE != ret || NULL == writeChrHandle)
935 OIC_LOG_V(ERROR, TAG,
936 "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
937 CALEGetErrorMsg(ret));
938 bt_gatt_client_destroy(clientHandle);
939 CALEGattDisConnect(remoteAddress);
940 return CA_STATUS_FAILED;
943 // Server will notify data on this characteristic.
944 bt_gatt_h readChrHandle = NULL;
945 ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_RESPONSE_CHRC_UUID,
947 if (BT_ERROR_NONE != ret || NULL == readChrHandle)
949 OIC_LOG_V(ERROR, TAG,
950 "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
951 CALEGetErrorMsg(ret));
952 bt_gatt_client_destroy(clientHandle);
953 CALEGattDisConnect(remoteAddress);
954 return CA_STATUS_FAILED;
958 //TODO: This data has to be freed while unsetting the callback.
959 char *addr = OICStrdup(remoteAddress);
960 ret = bt_gatt_client_set_characteristic_value_changed_cb(readChrHandle,
961 CALEGattCharacteristicChangedCb,
963 if (BT_ERROR_NONE != ret)
965 OIC_LOG_V(ERROR, TAG,
966 "bt_gatt_client_set_characteristic_value_changed_cb Failed with ret value [%s]",
967 CALEGetErrorMsg(ret));
968 bt_gatt_client_destroy(clientHandle);
969 CALEGattDisConnect(remoteAddress);
970 return CA_STATUS_FAILED;
973 LEServerInfo *serverInfo = (LEServerInfo *)OICCalloc(1, sizeof(LEServerInfo));
974 if (NULL == serverInfo)
976 OIC_LOG(ERROR, TAG, "Malloc failed");
977 CALEGattDisConnect(remoteAddress);
978 return CA_MEMORY_ALLOC_FAILED;
980 serverInfo->clientHandle = clientHandle;
981 serverInfo->serviceHandle = serviceHandle;
982 serverInfo->readChar = readChrHandle;
983 serverInfo->writeChar = writeChrHandle;
984 serverInfo->remoteAddress = OICStrdup(remoteAddress);
986 ca_mutex_lock(g_LEServerListMutex);
987 CAResult_t result = CAAddLEServerInfoToList(&g_LEServerList, serverInfo);
988 if (CA_STATUS_OK != result)
990 OIC_LOG(ERROR, TAG, "CAAddBLEClientInfoToList failed");
991 bt_gatt_client_destroy(clientHandle);
992 CALEGattDisConnect(remoteAddress);
993 return CA_STATUS_FAILED;
995 ca_mutex_unlock(g_LEServerListMutex);
997 // Send the data of pending multicast data list if any.
998 if (g_multicastDataList)
1000 ca_mutex_lock(g_multicastDataListMutex);
1001 uint32_t arrayLength = u_arraylist_length(g_multicastDataList);
1002 for (int i = 0; i < arrayLength; i++)
1004 CALEData_t *multicastData = u_arraylist_get(g_multicastDataList, i);
1005 if (NULL == multicastData)
1007 OIC_LOG(DEBUG, TAG, "multicastData is NULL");
1010 CAUpdateCharacteristicsToGattServer(remoteAddress, multicastData->data,
1011 multicastData->dataLen, LE_UNICAST, 0);
1013 ca_mutex_unlock(g_multicastDataListMutex);
1016 OIC_LOG(DEBUG, TAG, "OUT");
1017 return CA_STATUS_OK;
1020 CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress,
1021 const uint8_t *data, const uint32_t dataLen,
1022 CALETransferType_t type, const int32_t position)
1024 OIC_LOG(DEBUG, TAG, "IN");
1026 VERIFY_NON_NULL(data, TAG, "data is NULL");
1030 OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input!");
1031 return CA_STATUS_INVALID_PARAM;
1034 LEServerInfo *leServerInfo = NULL;
1035 CAResult_t ret = CA_STATUS_FAILED;
1037 ca_mutex_lock(g_LEServerListMutex);
1038 if (LE_UNICAST == type)
1040 ret = CAGetLEServerInfo(g_LEServerList, remoteAddress, &leServerInfo);
1042 else if (LE_MULTICAST == type)
1044 ret = CAGetLEServerInfoByPosition(g_LEServerList, position, &leServerInfo);
1046 ca_mutex_unlock(g_LEServerListMutex);
1048 if (CA_STATUS_OK != ret)
1050 OIC_LOG(ERROR, TAG, "CAGetBLEServiceInfoByPosition is failed");
1051 return CA_STATUS_FAILED;
1054 VERIFY_NON_NULL(leServerInfo, TAG, "bleServiceInfo is NULL");
1056 OIC_LOG_V(DEBUG, TAG, "Updating the data of length [%d] to [%s] ", dataLen,
1057 leServerInfo->remoteAddress);
1059 int result = bt_gatt_set_value(leServerInfo->writeChar, (char *)data, dataLen);
1061 if (BT_ERROR_NONE != result)
1063 OIC_LOG_V(ERROR, TAG,
1064 "bt_gatt_set_value Failed with return val [%s]",
1065 CALEGetErrorMsg(result));
1066 return CA_STATUS_FAILED;
1069 result = bt_gatt_client_write_value(leServerInfo->writeChar, CALEGattCharacteristicWriteCb,
1071 if (BT_ERROR_NONE != result)
1073 OIC_LOG_V(ERROR, TAG,
1074 "bt_gatt_client_write_value Failed with return val [%s]",
1075 CALEGetErrorMsg(result));
1076 return CA_STATUS_FAILED;
1079 // wait for callback for write Characteristic with success to sent data
1080 OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
1081 ca_mutex_lock(g_threadWriteCharacteristicMutex);
1082 if (!g_isSignalSetFlag)
1084 OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success");
1085 if (CA_WAIT_SUCCESS != ca_cond_wait_for(g_threadWriteCharacteristicCond,
1086 g_threadWriteCharacteristicMutex,
1087 WAIT_TIME_WRITE_CHARACTERISTIC))
1089 OIC_LOG(ERROR, TAG, "there is no response. write has failed");
1090 g_isSignalSetFlag = false;
1091 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
1092 return CA_SEND_FAILED;
1095 // reset flag set by writeCharacteristic Callback
1096 g_isSignalSetFlag = false;
1097 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
1099 OIC_LOG(DEBUG, TAG, "OUT");
1100 return CA_STATUS_OK;
1103 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
1105 OIC_LOG(DEBUG, TAG, "IN");
1107 VERIFY_NON_NULL(data, TAG, "data is NULL");
1111 OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input !");
1112 return CA_STATUS_INVALID_PARAM;
1115 int numOfServersConnected = CAGetRegisteredServiceCount();
1117 // Send data to already connected devices.
1118 for (int32_t pos = 0; pos < numOfServersConnected; pos++)
1120 /*remoteAddress will be NULL.
1121 Since we have to send to all destinations. pos will be used for getting remote address.
1123 int32_t ret = CAUpdateCharacteristicsToGattServer(NULL, data, dataLen, LE_MULTICAST, pos);
1125 if (CA_STATUS_OK != ret)
1127 OIC_LOG_V(ERROR, TAG,
1128 "CAUpdateCharacteristicsToGattServer Failed with return val [%d] ", ret);
1129 g_clientErrorCallback(NULL, data, dataLen, ret);
1133 // Add the data to pending list.
1134 CALEData_t *multicastData = (CALEData_t *)OICCalloc(1, sizeof(CALEData_t));
1135 if (NULL == multicastData)
1137 OIC_LOG(ERROR, TAG, "Calloc failed");
1140 multicastData->data = OICCalloc(1, dataLen);
1141 if (NULL == multicastData->data)
1143 OIC_LOG(ERROR, TAG, "Calloc failed");
1146 memcpy(multicastData->data, data, dataLen);
1147 multicastData->dataLen = dataLen;
1149 ca_mutex_lock(g_multicastDataListMutex);
1150 if (NULL == g_multicastDataList)
1152 g_multicastDataList = u_arraylist_create();
1154 u_arraylist_add(g_multicastDataList, (void *)multicastData);
1155 ca_mutex_unlock(g_multicastDataListMutex);
1157 // Start the scanning.
1158 CAResult_t result = CALEGattStartDeviceScanning();
1159 if (CA_STATUS_OK != result)
1161 OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed");
1165 // Start the timer by signalling it.
1166 ca_cond_signal(g_startTimerCond);
1169 OIC_LOG(DEBUG, TAG, "OUT ");
1170 return CA_STATUS_OK;