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 CALEGattConnectionStateChanged(bool connected, const char *remoteAddress)
235 OIC_LOG(DEBUG, TAG, "IN ");
237 VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
239 // Start the scanning.
240 CAResult_t ret = CALEGattStartDeviceScanning();
241 if (CA_STATUS_OK != ret)
243 OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed");
245 // Signal the start timer.
246 ca_cond_signal(g_scanningTimeCond);
250 OIC_LOG_V(DEBUG, TAG, "DisConnected from [%s] ", remoteAddress);
254 OIC_LOG_V(DEBUG, TAG, "Connected to [%s] ", remoteAddress);
256 char *addr = OICStrdup(remoteAddress);
258 ca_mutex_lock(g_LEClientThreadPoolMutex);
259 if (NULL == g_LEClientThreadPool)
261 OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
263 ca_mutex_unlock(g_LEClientThreadPoolMutex);
267 ret = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread,
269 if (CA_STATUS_OK != ret)
271 OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", ret);
274 ca_mutex_unlock(g_LEClientThreadPoolMutex);
276 OIC_LOG(DEBUG, TAG, "OUT");
279 void CALEAdapterScanResultCb(int result, bt_adapter_le_device_scan_result_info_s *scanInfo,
282 OIC_LOG(DEBUG, TAG, "IN");
284 VERIFY_NON_NULL_VOID(scanInfo, TAG, "scanInfo");
285 VERIFY_NON_NULL_VOID(scanInfo->remote_address, TAG, "scanInfo->remote_address");
287 OIC_LOG_V(DEBUG, TAG, "Remote Address [%s]", scanInfo->remote_address);
288 OIC_LOG_V(DEBUG, TAG, "Scan Result [%d]", result);
289 OIC_LOG_V(DEBUG, TAG,
290 " Adv data len [%d] Scan data len[%d]RSSI [%d] Addr_type [%d] ",
291 scanInfo->adv_data_len, scanInfo->scan_data_len, scanInfo->rssi,
292 scanInfo->address_type);
294 // Check if device is already discovered.
295 if (CALEIsDeviceDiscovered(scanInfo->remote_address))
297 OIC_LOG_V(INFO, TAG, "Device[%s] is already discovered", scanInfo->remote_address);
301 // Stop the scan before invoking bt_gatt_connect().
302 CALEGattStopDeviceScanning();
304 ca_mutex_lock(g_deviceDiscoveredListMutex);
305 // Add the the device Discovered list.
306 if (NULL == g_deviceDiscoveredList)
308 g_deviceDiscoveredList = u_arraylist_create();
310 char *deviceAddr = OICStrdup(scanInfo->remote_address);
311 u_arraylist_add(g_deviceDiscoveredList, (void *) deviceAddr);
312 ca_mutex_unlock(g_deviceDiscoveredListMutex);
314 size_t len = strlen(scanInfo->remote_address);
316 char *addr = (char *)OICMalloc(sizeof(char) * (len + 1));
317 VERIFY_NON_NULL_VOID(addr, TAG, "Malloc failed");
319 strncpy(addr, scanInfo->remote_address, len + 1);
321 OIC_LOG_V(DEBUG, TAG,
322 "Trying to do Gatt connection to [%s]", addr);
324 ca_mutex_lock(g_LEClientThreadPoolMutex);
325 if (NULL == g_LEClientThreadPool)
327 OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL");
329 ca_mutex_unlock(g_LEClientThreadPoolMutex);
333 CAResult_t res = ca_thread_pool_add_task(g_LEClientThreadPool, CAGattConnectThread, addr);
334 if (CA_STATUS_OK != res)
336 OIC_LOG_V(ERROR, TAG,
337 "ca_thread_pool_add_task failed with ret [%d]", res);
340 ca_mutex_unlock(g_LEClientThreadPoolMutex);
341 OIC_LOG(DEBUG, TAG, "OUT");
344 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
346 OIC_LOG(DEBUG, TAG, "IN");
348 ca_mutex_lock(g_LEClientThreadPoolMutex);
349 g_LEClientThreadPool = handle;
350 ca_mutex_unlock(g_LEClientThreadPoolMutex);
352 OIC_LOG(DEBUG, TAG, "OUT");
355 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
357 OIC_LOG(DEBUG, TAG, "IN");
359 ca_mutex_lock(g_LEReqRespClientCbMutex);
361 g_LEClientDataReceivedCallback = callback;
363 ca_mutex_unlock(g_LEReqRespClientCbMutex);
365 OIC_LOG(DEBUG, TAG, "OUT");
368 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
370 g_clientErrorCallback = callback;
373 CAResult_t CAStartLEGattClient()
375 OIC_LOG(DEBUG, TAG, "IN");
377 ca_mutex_lock(g_LEClientThreadPoolMutex);
378 if (NULL == g_LEClientThreadPool)
380 OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL");
381 CATerminateGattClientMutexVariables();
382 ca_mutex_unlock(g_LEClientThreadPoolMutex);
383 return CA_STATUS_FAILED;
386 CAResult_t result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartLEGattClientThread,
388 if (CA_STATUS_OK != result)
390 OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed");
391 CATerminateGattClientMutexVariables();
392 ca_mutex_unlock(g_LEClientThreadPoolMutex);
393 return CA_STATUS_FAILED;
395 ca_mutex_unlock(g_LEClientThreadPoolMutex);
397 OIC_LOG(DEBUG, TAG, "OUT");
401 void CAStartLEGattClientThread(void *data)
403 OIC_LOG(DEBUG, TAG, "IN");
405 ca_mutex_lock(g_LEClientStateMutex);
406 if (true == g_isLEGattClientStarted)
408 OIC_LOG(ERROR, TAG, "Gatt Client is already running!!");
409 ca_mutex_unlock(g_LEClientStateMutex);
413 CAResult_t result = CALEGattSetCallbacks();
414 if (CA_STATUS_OK != result)
416 OIC_LOG(ERROR, TAG, "CABleGattSetCallbacks Failed");
417 ca_mutex_unlock(g_LEClientStateMutex);
418 CATerminateLEGattClient();
422 g_isLEGattClientStarted = true;
423 ca_mutex_unlock(g_LEClientStateMutex);
425 ca_mutex_lock(g_LEClientThreadPoolMutex);
426 if (NULL == g_LEClientThreadPool)
428 OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL");
429 CATerminateGattClientMutexVariables();
430 ca_mutex_unlock(g_LEClientThreadPoolMutex);
434 result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartTimerThread,
436 if (CA_STATUS_OK != result)
438 OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed");
439 ca_mutex_unlock(g_LEClientThreadPoolMutex);
442 ca_mutex_unlock(g_LEClientThreadPoolMutex);
444 OIC_LOG(DEBUG, TAG, "Giving the control to threadPool");
446 GMainContext *thread_context = g_main_context_new();
448 g_eventLoop = g_main_loop_new(thread_context, FALSE);
450 g_main_context_push_thread_default(thread_context);
452 g_main_loop_run(g_eventLoop);
454 OIC_LOG(DEBUG, TAG, "OUT");
457 void CAStartTimerThread(void *data)
459 OIC_LOG(DEBUG, TAG, "IN");
460 while (g_isLEGattClientStarted)
462 ca_mutex_lock(g_multicastDataListMutex);
463 if (!g_isMulticastInProgress)
465 OIC_LOG(DEBUG, TAG, "waiting....");
466 ca_cond_wait(g_startTimerCond, g_multicastDataListMutex);
467 OIC_LOG(DEBUG, TAG, "Wake up");
468 g_isMulticastInProgress = true;
471 // Timed conditional wait for stopping the scan.
472 CAWaitResult_t ret = ca_cond_wait_for(g_scanningTimeCond, g_multicastDataListMutex,
474 if (CA_WAIT_TIMEDOUT == ret)
476 OIC_LOG(DEBUG, TAG, "Scan is timed Out");
478 CALEGattStopDeviceScanning();
480 // Clear the data list and device list.
481 u_arraylist_destroy(g_multicastDataList);
482 g_multicastDataList = NULL;
484 ca_mutex_lock(g_deviceDiscoveredListMutex);
485 u_arraylist_destroy(g_deviceDiscoveredList);
486 g_deviceDiscoveredList = NULL;
487 ca_mutex_unlock(g_deviceDiscoveredListMutex);
489 g_isMulticastInProgress = false;
491 ca_mutex_unlock(g_multicastDataListMutex);
494 OIC_LOG(DEBUG, TAG, "OUT");
497 void CAStopLEGattClient()
499 OIC_LOG(DEBUG, TAG, "IN");
501 ca_mutex_lock(g_LEClientStateMutex);
503 if (false == g_isLEGattClientStarted)
505 OIC_LOG(ERROR, TAG, "Gatt Client is not running to stop");
506 ca_mutex_unlock(g_LEClientStateMutex);
510 CALEGattUnSetCallbacks();
512 CALEGattStopDeviceScanning();
514 g_isLEGattClientStarted = false;
516 // Signal the conditions waiting in Start timer.
517 ca_cond_signal(g_startTimerCond);
518 ca_cond_signal(g_scanningTimeCond);
520 // Destroy the multicast data list and device list if not empty.
521 if (NULL != g_multicastDataList)
523 ca_mutex_lock(g_multicastDataListMutex);
524 u_arraylist_destroy(g_multicastDataList);
525 g_multicastDataList = NULL;
526 ca_mutex_unlock(g_multicastDataListMutex);
529 if (NULL != g_deviceDiscoveredList)
531 ca_mutex_lock(g_deviceDiscoveredListMutex);
532 u_arraylist_destroy(g_deviceDiscoveredList);
533 g_deviceDiscoveredList = NULL;
534 ca_mutex_unlock(g_deviceDiscoveredListMutex);
537 ca_mutex_lock(g_LEServerListMutex);
538 CAFreeLEServerList(g_LEServerList);
539 g_LEServerList = NULL;
540 ca_mutex_unlock(g_LEServerListMutex);
542 ca_mutex_lock(g_threadWriteCharacteristicMutex);
543 ca_cond_signal(g_threadWriteCharacteristicCond);
544 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
546 CAResetRegisteredServiceCount();
548 GMainContext *context_event_loop = NULL;
549 // Required for waking up the thread which is running in gmain loop
550 if (NULL != g_eventLoop)
552 context_event_loop = g_main_loop_get_context(g_eventLoop);
554 if (context_event_loop)
556 OIC_LOG_V(DEBUG, TAG, "g_eventLoop context %x", context_event_loop);
557 g_main_context_wakeup(context_event_loop);
559 // Kill g main loops and kill threads.
560 g_main_loop_quit(g_eventLoop);
564 OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL");
567 ca_mutex_unlock(g_LEClientStateMutex);
569 OIC_LOG(DEBUG, TAG, "OUT");
572 CAResult_t CAInitializeLEGattClient()
574 OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
575 CAResult_t res = CAInitGattClientMutexVariables();
576 if (CA_STATUS_OK != res)
578 OIC_LOG(ERROR, TAG, "CAInitGattClientMutexVariables failed!");
579 CATerminateGattClientMutexVariables();
580 return CA_STATUS_FAILED;
585 void CATerminateLEGattClient()
587 OIC_LOG(DEBUG, TAG, "IN");
589 CATerminateGattClientMutexVariables();
591 OIC_LOG(DEBUG, TAG, "OUT");
594 CAResult_t CAInitGattClientMutexVariables()
596 OIC_LOG(DEBUG, TAG, "IN");
597 if (NULL == g_LEClientStateMutex)
599 g_LEClientStateMutex = ca_mutex_new();
600 if (NULL == g_LEClientStateMutex)
602 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
603 return CA_STATUS_FAILED;
607 if (NULL == g_LEServerListMutex)
609 g_LEServerListMutex = ca_mutex_new();
610 if (NULL == g_LEServerListMutex)
612 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
613 return CA_STATUS_FAILED;
617 if (NULL == g_LEReqRespClientCbMutex)
619 g_LEReqRespClientCbMutex = ca_mutex_new();
620 if (NULL == g_LEReqRespClientCbMutex)
622 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
623 return CA_STATUS_FAILED;
627 if (NULL == g_LEClientThreadPoolMutex)
629 g_LEClientThreadPoolMutex = ca_mutex_new();
630 if (NULL == g_LEClientThreadPoolMutex)
632 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
633 return CA_STATUS_FAILED;
637 if (NULL == g_LEClientConnectMutex)
639 g_LEClientConnectMutex = ca_mutex_new();
640 if (NULL == g_LEClientConnectMutex)
642 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
643 return CA_STATUS_FAILED;
647 if (NULL == g_multicastDataListMutex)
649 g_multicastDataListMutex = ca_mutex_new();
650 if (NULL == g_multicastDataListMutex)
652 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
653 return CA_STATUS_FAILED;
657 if (NULL == g_deviceDiscoveredListMutex)
659 g_deviceDiscoveredListMutex = ca_mutex_new();
660 if (NULL == g_deviceDiscoveredListMutex)
662 OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
663 return CA_STATUS_FAILED;
667 if (NULL == g_threadWriteCharacteristicMutex)
669 g_threadWriteCharacteristicMutex = ca_mutex_new();
670 if (NULL == g_threadWriteCharacteristicMutex)
672 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
673 return CA_STATUS_FAILED;
677 if (NULL == g_startTimerCond)
679 g_startTimerCond = ca_cond_new();
680 if (NULL == g_startTimerCond)
682 OIC_LOG(ERROR, TAG, "ca_cond_new failed");
683 return CA_STATUS_FAILED;
687 if (NULL == g_scanningTimeCond)
689 g_scanningTimeCond = ca_cond_new();
690 if (NULL == g_scanningTimeCond)
692 OIC_LOG(ERROR, TAG, "ca_cond_new failed");
693 return CA_STATUS_FAILED;
697 if (NULL == g_threadWriteCharacteristicCond)
699 g_threadWriteCharacteristicCond = ca_cond_new();
700 if (NULL == g_threadWriteCharacteristicCond)
702 OIC_LOG(ERROR, TAG, "ca_cond_new failed");
703 return CA_STATUS_FAILED;
707 OIC_LOG(DEBUG, TAG, "OUT");
711 void CATerminateGattClientMutexVariables()
713 OIC_LOG(DEBUG, TAG, "IN");
715 ca_mutex_free(g_LEClientStateMutex);
716 g_LEClientStateMutex = NULL;
718 ca_mutex_free(g_LEServerListMutex);
719 g_LEServerListMutex = NULL;
721 ca_mutex_free(g_LEReqRespClientCbMutex);
722 g_LEReqRespClientCbMutex = NULL;
724 ca_mutex_free(g_LEClientConnectMutex);
725 g_LEClientConnectMutex = NULL;
727 ca_mutex_free(g_LEClientThreadPoolMutex);
728 g_LEClientThreadPoolMutex = NULL;
730 ca_mutex_free(g_multicastDataListMutex);
731 g_multicastDataListMutex = NULL;
733 ca_mutex_free(g_deviceDiscoveredListMutex);
734 g_deviceDiscoveredListMutex = NULL;
736 ca_mutex_free(g_threadWriteCharacteristicMutex);
737 g_threadWriteCharacteristicMutex = NULL;
739 ca_cond_free(g_startTimerCond);
740 g_startTimerCond = NULL;
742 ca_cond_free(g_scanningTimeCond);
743 g_scanningTimeCond = NULL;
745 ca_cond_free(g_threadWriteCharacteristicCond);
746 g_threadWriteCharacteristicCond = NULL;
747 g_isSignalSetFlag = false;
749 OIC_LOG(DEBUG, TAG, "OUT");
752 CAResult_t CALEGattSetCallbacks()
754 OIC_LOG(DEBUG, TAG, "IN");
756 OIC_LOG(DEBUG, TAG, "OUT");
760 void CALEGattUnSetCallbacks()
762 OIC_LOG(DEBUG, TAG, "IN");
764 bt_gatt_unset_connection_state_changed_cb();
766 int numOfServersConnected = CAGetRegisteredServiceCount();
767 LEServerInfo *leServerInfo = NULL;
769 for (int32_t index = 0; index < numOfServersConnected; index++)
771 CAGetLEServerInfoByPosition(g_LEServerList, index, &leServerInfo);
772 bt_gatt_client_unset_characteristic_value_changed_cb(leServerInfo->readChar);
774 OIC_LOG(DEBUG, TAG, "OUT");
777 CAResult_t CALEGattStartDeviceScanning()
779 OIC_LOG(DEBUG, TAG, "IN");
781 int ret = bt_adapter_le_start_scan(CALEAdapterScanResultCb, NULL);
782 if(BT_ERROR_NONE != ret)
784 OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_scan failed[%s]",
785 CALEGetErrorMsg(ret));
786 return CA_STATUS_FAILED;
789 OIC_LOG(DEBUG, TAG, "OUT");
793 void CALEGattStopDeviceScanning()
795 OIC_LOG(DEBUG, TAG, "IN");
797 int ret = bt_adapter_le_stop_scan();
798 if (BT_ERROR_NONE != ret)
800 OIC_LOG_V(ERROR, TAG, "bt_adapter_le_stop_scan failed[%s]",
801 CALEGetErrorMsg(ret));
804 OIC_LOG(DEBUG, TAG, "OUT");
807 void CAGattConnectThread (void *remoteAddress)
809 OIC_LOG(DEBUG, TAG, "IN ");
811 VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
813 char *address = (char *)remoteAddress;
815 OIC_LOG_V(DEBUG, TAG, "remote address is [%s]", address);
817 CAResult_t result = CALEGattConnect(address);
819 if (CA_STATUS_OK != result)
821 OIC_LOG_V(ERROR, TAG, "bt_gatt_connect failed for [%s]", address);
826 OIC_LOG(DEBUG, TAG, "OUT");
829 CAResult_t CALEGattConnect(const char *remoteAddress)
831 OIC_LOG(DEBUG, TAG, "IN");
833 VERIFY_NON_NULL_RET(remoteAddress, TAG,
834 "remote address is NULL", CA_STATUS_FAILED);
836 ca_mutex_lock(g_LEClientConnectMutex);
838 int ret = bt_gatt_connect(remoteAddress, true);
840 if (BT_ERROR_NONE != ret)
842 OIC_LOG_V(ERROR, TAG, "bt_gatt_connect Failed with ret value [%s] ",
843 CALEGetErrorMsg(ret));
844 ca_mutex_unlock(g_LEClientConnectMutex);
845 return CA_STATUS_FAILED;
847 ca_mutex_unlock(g_LEClientConnectMutex);
849 OIC_LOG(DEBUG, TAG, "OUT");
853 CAResult_t CALEGattDisConnect(const char *remoteAddress)
855 OIC_LOG(DEBUG, TAG, "IN");
857 VERIFY_NON_NULL_RET(remoteAddress, TAG,
858 "remote address is NULL", CA_STATUS_FAILED);
860 int ret = bt_gatt_disconnect(remoteAddress);
862 if (BT_ERROR_NONE != ret)
864 OIC_LOG_V(ERROR, TAG, "bt_gatt_disconnect Failed with ret value [%d] ",
865 CALEGetErrorMsg(ret));
866 return CA_STATUS_FAILED;
869 OIC_LOG(DEBUG, TAG, "OUT");
873 void CADiscoverLEServicesThread (void *remoteAddress)
875 OIC_LOG(DEBUG, TAG, "IN");
877 VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
879 char *address = (char *)remoteAddress;
881 CAResult_t result = CALEGattDiscoverServices(address);
882 if (CA_STATUS_OK != result)
884 OIC_LOG(ERROR, TAG, "CALEGattDiscoverServices failed");
888 OIC_LOG(DEBUG, TAG, "OUT");
891 CAResult_t CALEGattDiscoverServices(const char *remoteAddress)
893 OIC_LOG(DEBUG, TAG, "IN");
895 VERIFY_NON_NULL_RET(remoteAddress, TAG,
896 "remote address is NULL", CA_STATUS_FAILED);
898 bt_gatt_client_h clientHandle = NULL;
899 int32_t ret = bt_gatt_client_create(remoteAddress, &clientHandle);
900 if (BT_ERROR_NONE != ret || NULL == clientHandle)
902 OIC_LOG_V(ERROR, TAG,
903 "bt_gatt_client_create Failed with ret value [%s] ", CALEGetErrorMsg(ret));
904 CALEGattDisConnect(remoteAddress);
905 return CA_STATUS_FAILED;
908 bt_gatt_h serviceHandle = NULL;
909 ret = bt_gatt_client_get_service(clientHandle, CA_GATT_SERVICE_UUID, &serviceHandle);
910 if (BT_ERROR_NONE != ret || NULL == serviceHandle)
912 OIC_LOG_V(ERROR, TAG,
913 "bt_gatt_client_get_service Failed with ret value [%s] ", CALEGetErrorMsg(ret));
914 bt_gatt_client_destroy(clientHandle);
915 CALEGattDisConnect(remoteAddress);
916 return CA_STATUS_FAILED;
919 // Server will read data on this characteristic.
920 bt_gatt_h writeChrHandle = NULL;
921 ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_REQUEST_CHRC_UUID,
923 if (BT_ERROR_NONE != ret || NULL == writeChrHandle)
925 OIC_LOG_V(ERROR, TAG,
926 "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
927 CALEGetErrorMsg(ret));
928 bt_gatt_client_destroy(clientHandle);
929 CALEGattDisConnect(remoteAddress);
930 return CA_STATUS_FAILED;
933 // Server will notify data on this characteristic.
934 bt_gatt_h readChrHandle = NULL;
935 ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_RESPONSE_CHRC_UUID,
937 if (BT_ERROR_NONE != ret || NULL == readChrHandle)
939 OIC_LOG_V(ERROR, TAG,
940 "bt_gatt_service_get_characteristic Failed with ret value [%s] ",
941 CALEGetErrorMsg(ret));
942 bt_gatt_client_destroy(clientHandle);
943 CALEGattDisConnect(remoteAddress);
944 return CA_STATUS_FAILED;
948 //TODO: This data has to be freed while unsetting the callback.
949 char *addr = OICStrdup(remoteAddress);
950 ret = bt_gatt_client_set_characteristic_value_changed_cb(readChrHandle,
951 CALEGattCharacteristicChangedCb,
953 if (BT_ERROR_NONE != ret)
955 OIC_LOG_V(ERROR, TAG,
956 "bt_gatt_client_set_characteristic_value_changed_cb Failed with ret value [%s]",
957 CALEGetErrorMsg(ret));
958 bt_gatt_client_destroy(clientHandle);
959 CALEGattDisConnect(remoteAddress);
960 return CA_STATUS_FAILED;
963 LEServerInfo *serverInfo = (LEServerInfo *)OICCalloc(1, sizeof(LEServerInfo));
964 if (NULL == serverInfo)
966 OIC_LOG(ERROR, TAG, "Malloc failed");
967 CALEGattDisConnect(remoteAddress);
968 return CA_MEMORY_ALLOC_FAILED;
970 serverInfo->clientHandle = clientHandle;
971 serverInfo->serviceHandle = serviceHandle;
972 serverInfo->readChar = readChrHandle;
973 serverInfo->writeChar = writeChrHandle;
974 serverInfo->remoteAddress = OICStrdup(remoteAddress);
976 ca_mutex_lock(g_LEServerListMutex);
977 CAResult_t result = CAAddLEServerInfoToList(&g_LEServerList, serverInfo);
978 if (CA_STATUS_OK != result)
980 OIC_LOG(ERROR, TAG, "CAAddBLEClientInfoToList failed");
981 bt_gatt_client_destroy(clientHandle);
982 CALEGattDisConnect(remoteAddress);
983 return CA_STATUS_FAILED;
985 ca_mutex_unlock(g_LEServerListMutex);
987 // Send the data of pending multicast data list if any.
988 if (g_multicastDataList)
990 ca_mutex_lock(g_multicastDataListMutex);
991 uint32_t arrayLength = u_arraylist_length(g_multicastDataList);
992 for (int i = 0; i < arrayLength; i++)
994 CALEData_t *multicastData = u_arraylist_get(g_multicastDataList, i);
995 if (NULL == multicastData)
997 OIC_LOG(DEBUG, TAG, "multicastData is NULL");
1000 CAUpdateCharacteristicsToGattServer(remoteAddress, multicastData->data,
1001 multicastData->dataLen, LE_UNICAST, 0);
1003 ca_mutex_unlock(g_multicastDataListMutex);
1006 OIC_LOG(DEBUG, TAG, "OUT");
1007 return CA_STATUS_OK;
1010 CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress,
1011 const uint8_t *data, const uint32_t dataLen,
1012 CALETransferType_t type, const int32_t position)
1014 OIC_LOG(DEBUG, TAG, "IN");
1016 VERIFY_NON_NULL(data, TAG, "data is NULL");
1020 OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input!");
1021 return CA_STATUS_INVALID_PARAM;
1024 LEServerInfo *leServerInfo = NULL;
1025 CAResult_t ret = CA_STATUS_FAILED;
1027 ca_mutex_lock(g_LEServerListMutex);
1028 if (LE_UNICAST == type)
1030 ret = CAGetLEServerInfo(g_LEServerList, remoteAddress, &leServerInfo);
1032 else if (LE_MULTICAST == type)
1034 ret = CAGetLEServerInfoByPosition(g_LEServerList, position, &leServerInfo);
1036 ca_mutex_unlock(g_LEServerListMutex);
1038 if (CA_STATUS_OK != ret)
1040 OIC_LOG(ERROR, TAG, "CAGetBLEServiceInfoByPosition is failed");
1041 return CA_STATUS_FAILED;
1044 VERIFY_NON_NULL(leServerInfo, TAG, "bleServiceInfo is NULL");
1046 OIC_LOG_V(DEBUG, TAG, "Updating the data of length [%d] to [%s] ", dataLen,
1047 leServerInfo->remoteAddress);
1049 int result = bt_gatt_set_value(leServerInfo->writeChar, (char *)data, dataLen);
1051 if (BT_ERROR_NONE != result)
1053 OIC_LOG_V(ERROR, TAG,
1054 "bt_gatt_set_value Failed with return val [%s]",
1055 CALEGetErrorMsg(result));
1056 return CA_STATUS_FAILED;
1059 result = bt_gatt_client_write_value(leServerInfo->writeChar, CALEGattCharacteristicWriteCb,
1061 if (BT_ERROR_NONE != result)
1063 OIC_LOG_V(ERROR, TAG,
1064 "bt_gatt_client_write_value Failed with return val [%s]",
1065 CALEGetErrorMsg(result));
1066 return CA_STATUS_FAILED;
1069 // wait for callback for write Characteristic with success to sent data
1070 OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
1071 ca_mutex_lock(g_threadWriteCharacteristicMutex);
1072 if (!g_isSignalSetFlag)
1074 OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success");
1075 if (CA_WAIT_SUCCESS != ca_cond_wait_for(g_threadWriteCharacteristicCond,
1076 g_threadWriteCharacteristicMutex,
1077 WAIT_TIME_WRITE_CHARACTERISTIC))
1079 OIC_LOG(ERROR, TAG, "there is no response. write has failed");
1080 g_isSignalSetFlag = false;
1081 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
1082 return CA_SEND_FAILED;
1085 // reset flag set by writeCharacteristic Callback
1086 g_isSignalSetFlag = false;
1087 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
1089 OIC_LOG(DEBUG, TAG, "OUT");
1090 return CA_STATUS_OK;
1093 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
1095 OIC_LOG(DEBUG, TAG, "IN");
1097 VERIFY_NON_NULL(data, TAG, "data is NULL");
1101 OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input !");
1102 return CA_STATUS_INVALID_PARAM;
1105 int numOfServersConnected = CAGetRegisteredServiceCount();
1107 // Send data to already connected devices.
1108 for (int32_t pos = 0; pos < numOfServersConnected; pos++)
1110 /*remoteAddress will be NULL.
1111 Since we have to send to all destinations. pos will be used for getting remote address.
1113 int32_t ret = CAUpdateCharacteristicsToGattServer(NULL, data, dataLen, LE_MULTICAST, pos);
1115 if (CA_STATUS_OK != ret)
1117 OIC_LOG_V(ERROR, TAG,
1118 "CAUpdateCharacteristicsToGattServer Failed with return val [%d] ", ret);
1119 g_clientErrorCallback(NULL, data, dataLen, ret);
1123 // Add the data to pending list.
1124 CALEData_t *multicastData = (CALEData_t *)OICCalloc(1, sizeof(CALEData_t));
1125 if (NULL == multicastData)
1127 OIC_LOG(ERROR, TAG, "Calloc failed");
1130 multicastData->data = OICCalloc(1, dataLen);
1131 if (NULL == multicastData->data)
1133 OIC_LOG(ERROR, TAG, "Calloc failed");
1136 memcpy(multicastData->data, data, dataLen);
1137 multicastData->dataLen = dataLen;
1139 ca_mutex_lock(g_multicastDataListMutex);
1140 if (NULL == g_multicastDataList)
1142 g_multicastDataList = u_arraylist_create();
1144 u_arraylist_add(g_multicastDataList, (void *)multicastData);
1145 ca_mutex_unlock(g_multicastDataListMutex);
1147 // Start the scanning.
1148 CAResult_t result = CALEGattStartDeviceScanning();
1149 if (CA_STATUS_OK != result)
1151 OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed");
1155 // Start the timer by signalling it.
1156 ca_cond_signal(g_startTimerCond);
1159 OIC_LOG(DEBUG, TAG, "OUT ");
1160 return CA_STATUS_OK;